> Remi,
> The simplest solution is to add get/setBVector methods to A, then reference
> these as the get-method and set-method in the mapping file. If you are going
> to be generating a lot of code, you can extend CollectionInfo to
> automatically do this.
>
> Hope this helps...
> Margaret
Thx Margaret, I've just done it and it works just fine :) I've attached
both my CollectionInfo implementation as well as the factory for it. To
use it, just edit the org/exolab/castor/castor.properties and add the
following:
org.exolab.castor.builder.type.j3=com.webmotion.assistants.test.castor.FieldInfoFactoryJ3
To use it when generating code, just use the -types option with a j3
value, like this:
.... -types j3 ....
Anyway, I think i've also found a bug in FieldModler class (line 778,
wrong test) that might be related to my previous post (Data[] object is
a Object[] object, still castor say it is not the case), so in case this
was really a bug (I might be mistaken) and will be fixed, then this j3
solution is no longer required.
Also, I've slightly changed the naming scheme of all methods related to
get/set/add/remove by index, where I add and "At" at the end of the
method name. That way, if int are store, the removeData( int ) means
remove the int of value v, whereas removeDataAt( int ) means remove the
value at the given index. I've tested it with both JDO and Marshaller
classes, it works just fine. The only thing I've not tested is the JDK
1.1 compatibility (however, since it uses Vector, it should be
compatible).
/**
* Redistribution and use of this software and associated documentation
* ("Software"), with or without modification, are permitted provided
* that the following conditions are met:
*
* 1. Redistributions of source code must retain copyright
* statements and notices. Redistributions must also contain a
* copy of this document.
*
* 2. Redistributions in binary form must reproduce the
* above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. The name "Exolab" must not be used to endorse or promote
* products derived from this Software without prior written
* permission of Intalio, Inc. For written permission,
* please contact [EMAIL PROTECTED]
*
* 4. Products derived from this Software may not be called "Exolab"
* nor may "Exolab" appear in their names without prior written
* permission of Intalio, Inc. Exolab is a registered
* trademark of Intalio, Inc.
*
* 5. Due credit should be given to the Exolab Project
* (http://www.exolab.org/).
*
* THIS SOFTWARE IS PROVIDED BY INTALIO, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* INTALIO, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Copyright 1999,2000 (C) Intalio, Inc. All Rights Reserved.
*
* Contribution(s):
*
* - Frank Thelen, [EMAIL PROTECTED]
* - Moved creation of access methods into an appropriate
* set of separate methods, for extensibility
*
* $Id: CollectionInfo.java,v 1.15 2001/08/03 14:15:24 afawcett Exp $
*/
package com.webmotion.assistants.test.castor;
import org.exolab.castor.builder.*;
import org.exolab.castor.builder.types.*;
import org.exolab.castor.xml.JavaNaming;
import org.exolab.javasource.*;
import java.util.Vector;
/**
* A helper used for generating source that deals with Collections
* @author <a href="mailto:[EMAIL PROTECTED]">Keith Visco</a>
* @version $Revision: 1.15 $ $Date: 2001/08/03 14:15:24 $
**/
public class CollectionInfoJ3 extends CollectionInfo {
/**
* Creates a new CollectionInfo
*
* @param contextType the content type of the collection, ie. the type
* of objects that the collection will contain
* @param name the name of the Collection
* @param elementName the element name for each element in collection
*/
public CollectionInfoJ3(XSType contentType, String name, String elementName)
{
super( contentType, name, elementName );
} //-- CollectionInfo
/**
* Creates code for initialization of this Member
* @param jsc the JSourceCode in which to add the source to
**/
public void generateInitializerCode(JSourceCode jsc) {
jsc.add(getName()+" = new Vector();");
} //-- generateConstructorCode
public String getReadMethodName() {
return "get" + JavaNaming.toJavaClassName(getElementName());
} //-- getReadMethodName
public String getWriteMethodName() {
return "add" + JavaNaming.toJavaClassName(getElementName());
} //-- getWriteMethodName
//------------------/
//- Public Methods -/
//------------------/
/**
* Creates the Access methods for the collection described
* by this CollectionInfo
*
* @param jClass the JClass to add the methods to.
**/
public void createAccessMethods(JClass jClass) {
JMethod method = null;
JParameter contentParam = new JParameter(
getContentType().getJType(),
getContentName()
);
JSourceCode jsc = null;
//------------------------/
//- Create addXxx method -/
//------------------------/
String cName = JavaNaming.toJavaClassName(getElementName());
method = new JMethod(null, "add"+cName);
jClass.addMethod(method);
method.addException(SGTypes.IndexOutOfBoundsException);
method.addParameter(contentParam);
createAddMethod(method);
//--------------------------/
//- Create addXxxAt method -/
//--------------------------/
method = new JMethod(null, "add"+cName+"At");
jClass.addMethod(method);
method.addException(SGTypes.IndexOutOfBoundsException);
method.addParameter(new JParameter(JType.Int, "index"));
method.addParameter(contentParam);
createAddInsertMethod(method);
//--------------------------/
//- Create getXxxAt method -/
//--------------------------/
JType jType = getContentType().getJType();
method = new JMethod(jType, "get"+cName+"At");
jClass.addMethod(method);
method.addException(SGTypes.IndexOutOfBoundsException);
method.addParameter(new JParameter(JType.Int, "index"));
createGetByIndexMethod(method);
//-------------------------/
//- Create getXxxx method -/
//-------------------------/
// MODIFIED: generates methods for Vectors
method = new JMethod(
getXSList().getJType(),
"get"+cName
);
jClass.addMethod(method);
createGetMethod(method);
//----------------------------/
//- Create setXxxxAt methods -/
//----------------------------/
method = new JMethod(null, "set"+cName+"At");
jClass.addMethod(method);
method.addException(SGTypes.IndexOutOfBoundsException);
method.addParameter(new JParameter(JType.Int, "index"));
method.addParameter(contentParam);
createSetByIndexMethod(method);
//-------------------------/
//- Create setXxxx method -/
//-------------------------/
// setXxxxList name might be better, but descriptor classes expect
// getXxxx method names.
method = new JMethod(null, "set"+cName );
JParameter param = new JParameter(
getXSList().getJType(),
cName+"List"
);
jClass.addMethod(method);
method.addParameter( param );
createSetArrayMethod(method);
//------------------------------/
//- Create getXxxxCount method -/
//------------------------------/
method = new JMethod(JType.Int, "get"+cName+"Count");
jClass.addMethod(method);
createGetCountMethod(method);
//-------------------------------/
//- Create enumerateXxxx Method -/
//-------------------------------/
method = new JMethod(SGTypes.Enumeration, "enumerate"+cName);
jClass.addMethod(method);
createEnumerateMethod(method);
//------------------------------------/
//- Create removeXxxx(Object) Method -/
//------------------------------------/
//-- commented out until I fix primitives
method = new JMethod(JType.Boolean, "remove"+cName);
jClass.addMethod( method );
method.addParameter(contentParam);
createRemoveByObjectMethod(method);
//-------------------------------------/
//- Create removeXxxxAt(int i) Method -/
//-------------------------------------/
jType = getContentType().getJType();
method = new JMethod(jType, "remove"+cName+"At");
jClass.addMethod(method);
method.addParameter(new JParameter(JType.Int, "index"));
createRemoveByIndexMethod(method);
//-----------------------------/
//- Create removeAll() Method -/
//-----------------------------/
method = new JMethod(null, "removeAll"+cName);
jClass.addMethod(method);
createRemoveAllMethod(method);
} //-- createAccessMethods
/**
* Creates implementation of add method.
*
* @param method the JMethod in which to create the source
* code.
**/
public void createAddMethod(JMethod method) {
JSourceCode jsc = method.getSourceCode();
int maxSize = getXSList().getMaximumSize();
if (maxSize > 0) {
jsc.add("if (!(");
jsc.append(getName());
jsc.append(".size() < ");
jsc.append(Integer.toString(maxSize));
jsc.append(")) {");
jsc.indent();
jsc.add("throw new IndexOutOfBoundsException();");
jsc.unindent();
jsc.add("}");
}
jsc.add(getName());
jsc.append(".add(");
jsc.append(getContentType().createToJavaObjectCode(getContentName()));
jsc.append(");");
//-- bound properties
if (isBound())
createBoundPropertyCode(jsc);
} //-- createAddMethod
/**
* Creates implementation of add method with an index.
*
* @param method the JMethod in which to create the source
* code.
**/
public void createAddInsertMethod(JMethod method) {
JSourceCode jsc = method.getSourceCode();
int maxSize = getXSList().getMaximumSize();
if (maxSize > 0) {
jsc.add("if (!(");
jsc.append(getName());
jsc.append(".size() < ");
jsc.append(Integer.toString(maxSize));
jsc.append(")) {");
jsc.indent();
jsc.add("throw new IndexOutOfBoundsException();");
jsc.unindent();
jsc.add("}");
}
jsc.add(getName());
jsc.append(".add( index, ");
jsc.append(getContentType().createToJavaObjectCode(getContentName()));
jsc.append(" );");
//-- bound properties
if (isBound())
createBoundPropertyCode(jsc);
} //-- createAddMethod
/**
* Creates implementation of <code>Vector getXxxxList()</code> method.
*
* @param method the JMethod in which to create the source
* code.
**/
public void createGetMethod(JMethod method) {
JSourceCode jsc = method.getSourceCode();
String listType = getXSList().getJType().getName();
// MODIFIED : clone-like operation that works with any arbitrary
// string. Only works if the class used for the list
// has a default constructor
jsc.add( listType+" "+getName()+"Clone = new "+listType+"();" );
jsc.add( getName()+"Clone.addAll( "+getName()+" );" );
jsc.add( "return "+getName()+"Clone;" );
} //-- createGetMethod
/**
* Creates implementation of the get(index) method.
**/
public void createGetByIndexMethod(JMethod method) {
JSourceCode jsc = method.getSourceCode();
JType jType = method.getReturnType();
jsc.add("//-- check bounds for index");
jsc.add("if ((index < 0) || (index > ");
jsc.append(getName());
jsc.append(".size())) {");
jsc.indent();
jsc.add("throw new IndexOutOfBoundsException();");
jsc.unindent();
jsc.add("}");
jsc.add("");
jsc.add("return ");
String variableName = getName()+".elementAt(index)";
if (getContentType().getType() == XSType.CLASS) {
jsc.append("(");
jsc.append(jType.toString());
jsc.append(") ");
jsc.append(variableName);
}
else {
jsc.append(getContentType().createFromJavaObjectCode(variableName));
}
jsc.append(";");
} //-- createGetByIndex
/**
* Creates implementation of array set method
*
* @param method the JMethod in which to create the source
* code.
**/
public void createSetArrayMethod(JMethod method) {
JSourceCode jsc = method.getSourceCode();
String paramName = method.getParameter(0).getName();
// MODIFIED : generate code to deal with arbitrary
// java.util.List implementation
jsc.add( getName()+".clear();" );
jsc.add( getName()+".addAll( "+paramName+" );" );
if (isBound())
createBoundPropertyCode(jsc);
} //-- createSetArrayMethod
/**
* Creates implementation of set method.
*
* @param method the JMethod in which to create the source
* code.
**/
public void createSetByIndexMethod(JMethod method) {
JSourceCode jsc = method.getSourceCode();
jsc.add("//-- check bounds for index");
jsc.add("if ((index < 0) || (index > ");
jsc.append(getName());
jsc.append(".size())) {");
jsc.indent();
jsc.add("throw new IndexOutOfBoundsException();");
jsc.unindent();
jsc.add("}");
int maxSize = getXSList().getMaximumSize();
if (maxSize > 0) {
jsc.add("if (!(");
jsc.append("index < ");
jsc.append(Integer.toString(maxSize));
jsc.append(")) {");
jsc.indent();
jsc.add("throw new IndexOutOfBoundsException();");
jsc.unindent();
jsc.add("}");
}
jsc.add(getName());
jsc.append(".set( index, " );
jsc.append(getContentType().createToJavaObjectCode(getContentName()));
jsc.append(" );");
//-- bound properties
if (isBound())
createBoundPropertyCode(jsc);
} //-- createSetMethod
/**
* Creates the necessary source code for notifying
* PropertyChangeListeners when the collection has
* been updated.
*
* @param jsc the JSourceCode to add the new source code to.
**/
protected void createBoundPropertyCode(JSourceCode jsc) {
//notify listeners
jsc.add("notifyPropertyChangeListeners(\"");
jsc.append(getName());
jsc.append("\", null, ");
jsc.append(getName());
jsc.append(");");
} //-- createBoundPropertyCode
/**
* Creates implementation of getCount method.
*
* @param method the JMethod in which to create the source
* code.
**/
public void createGetCountMethod(JMethod method) {
JSourceCode jsc = method.getSourceCode();
jsc.add("return ");
jsc.append(getName());
jsc.append(".size();");
} //-- createGetCoundMethod
/**
* Creates implementation of Enumerate method.
*
* @param method the JMethod in which to create the source
* code.
**/
public void createEnumerateMethod(JMethod method) {
JSourceCode jsc = method.getSourceCode();
jsc.add("return ");
jsc.append(getName());
jsc.append(".elements();");
} //-- createEnumerateMethod
/**
* Transform primitve types into their wrapping class (boolean -> Boolean,
* etc).
*/
public static String getWrappingType( JType type ) {
if ( ! type.isPrimitive() )
throw new IllegalArgumentException(
"Only primitive types may be wrapped, "+
"invoked with non-primitive type <"+type.getName()+">"
);
if ( type == JType.Boolean )
return "java.lang.Boolean";
else if ( type == JType.Byte )
return "java.lang.Byte";
else if ( type == JType.Short )
return "java.lang.Short";
else if ( type == JType.Int )
return "java.lang.Integer";
else if ( type == JType.Long )
return "java.lang.Long";
else if ( type == JType.Float )
return "java.lang.Float";
else if ( type == JType.Double )
return "java.lang.Double";
else if ( type == JType.Char )
return "java.lang.Character";
else
throw new IllegalArgumentException(
"Unknown primitive type <"+type.getName()+">"
);
}
/**
* Creates implementation of remove(Object) method.
*
* @param method the JMethod in which to create the source
* code.
**/
public void createRemoveByObjectMethod(JMethod method) {
JSourceCode jsc = method.getSourceCode();
JParameter param = method.getParameter(0);
String paramName = param.getName();
if ( param.getType().isPrimitive() ) {
String wrappingType = getWrappingType( param.getType() );
jsc.add( wrappingType+" wrapping_"+paramName+" = new "+wrappingType+"( "+paramName+");" );
paramName = "wrapping_"+paramName;
}
jsc.add( "boolean removed = " );
jsc.append( getName() );
jsc.append( ".remove( " );
jsc.append( paramName );
jsc.append( " );" );
//-- bound properties
if (isBound())
createBoundPropertyCode(jsc);
//-- return value
jsc.add("return removed;");
} //-- createRemoveByObjectMethod
/**
* Creates implementation of remove(int i) method.
*
* @param method the JMethod in which to create the source
* code.
**/
public void createRemoveByIndexMethod(JMethod method) {
JSourceCode jsc = method.getSourceCode();
JType jType = method.getReturnType();
jsc.add("Object obj = "+getName()+".remove( index );");
//-- bound properties
if (isBound())
createBoundPropertyCode(jsc);
//-- return value
jsc.add("return ");
if (getContentType().getType() == XSType.CLASS) {
jsc.append("(");
jsc.append(jType.getName());
jsc.append(") obj;");
}
else {
jsc.append(getContentType().createFromJavaObjectCode("obj"));
jsc.append(";");
}
} //-- createRemoveByIndexMethod
/**
* Creates implementation of removeAll() method.
*
* @param method the JMethod in which to create the source
* code.
**/
public void createRemoveAllMethod(JMethod method) {
JSourceCode jsc = method.getSourceCode();
jsc.add( getName() );
jsc.append( ".clear();" );
//-- bound properties
if (isBound())
createBoundPropertyCode(jsc);
} //-- createRemoveAllMethod
} //-- CollectionInfo
/**
* Redistribution and use of this software and associated documentation
* ("Software"), with or without modification, are permitted provided
* that the following conditions are met:
*
* 1. Redistributions of source code must retain copyright
* statements and notices. Redistributions must also contain a
* copy of this document.
*
* 2. Redistributions in binary form must reproduce the
* above copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* 3. The name "Exolab" must not be used to endorse or promote
* products derived from this Software without prior written
* permission of Intalio, Inc. For written permission,
* please contact [EMAIL PROTECTED]
*
* 4. Products derived from this Software may not be called "Exolab"
* nor may "Exolab" appear in their names without prior written
* permission of Intalio, Inc. Exolab is a registered
* trademark of Intalio, Inc.
*
* 5. Due credit should be given to the Exolab Project
* (http://www.exolab.org/).
*
* THIS SOFTWARE IS PROVIDED BY INTALIO, INC. AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* INTALIO, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Copyright 1999 (C) Intalio, Inc. All Rights Reserved.
*
* $Id: FieldInfoFactory.java,v 1.2 2000/11/04 01:31:00 yip Exp $
*/
package com.webmotion.assistants.test.castor;
import org.exolab.castor.builder.CollectionInfo;
import org.exolab.castor.builder.FieldInfoFactory;
import org.exolab.castor.builder.types.XSType;
/**
* This class is used as a factory to create all the FieldInfo
* objects used by the source generator. You may override the
* FieldInfo classes and this factory for specific adaptions.
*
* @author <a href="mailto:[EMAIL PROTECTED]">Frank Thelen</a>
* @version $Revision: 1.2 $ $Date: 2000/11/04 01:31:00 $
*/
public class FieldInfoFactoryJ3 extends FieldInfoFactory {
/**
* Creates and returns a <code>CollectionInfoJ3</code> object.
*/
public CollectionInfo createCollection(
XSType contentType,
String name,
String elementName
) {
return new CollectionInfoJ3(contentType,name,elementName);
}
} //-- FieldInfoFactory