/**
* 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 info@exolab.org.
*
* 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-2003 (C) Intalio, Inc. All Rights Reserved.
*
* $Id$
*/
package org.exolab.castor.builder.descriptors;
import org.exolab.castor.builder.BuilderConfiguration;
import org.exolab.castor.builder.SGTypes;
import org.exolab.castor.xml.XMLConstants;
import org.exolab.javasource.JAnnotation;
import org.exolab.javasource.JAnnotationType;
import org.exolab.javasource.JClass;
import org.exolab.javasource.JConstructor;
import org.exolab.javasource.JField;
import org.exolab.javasource.JMethod;
import org.exolab.javasource.JPrimitiveType;
import org.exolab.javasource.JSourceCode;
import org.exolab.javasource.JType;
/**
* A class which defines the necessary methods for generating ClassDescriptor
* source files.
*
* @author <a href="mailto:kvisco@intalio.com">Keith Visco</a>
* @version $Revision$ $Date: 2006-03-10 15:42:54 -0700 (Fri, 10 Mar 2006) $
*/
public final class DescriptorJClass extends JClass {
/** Class Descriptors extend this base class. */
private static final String XMLCLASS_DESCRIPTOR_IMPL =
"org.exolab.castor.xml.util.XMLClassDescriptorImpl";
private static final String MAPPING_ACCESS_MODE = "org.exolab.castor.mapping.AccessMode";
/** Field descriptors implement this interface from org.exolab.castor.mapping. */
private static final JClass FIELD_DESCRIPTOR_CLASS;
/** Field descriptors implement this interface from org.exolab.castor.xml. */
private static final JClass XML_FIELD_DESCRIPTOR_CLASS;
/** Type validators implement this interface from org.exolab.castor.xml. */
private static final JType TYPE_VALIDATOR_CLASS;
static {
FIELD_DESCRIPTOR_CLASS = new JClass("org.exolab.castor.mapping.FieldDescriptor");
XML_FIELD_DESCRIPTOR_CLASS = new JClass("org.exolab.castor.xml.XMLFieldDescriptor");
TYPE_VALIDATOR_CLASS = new JClass("org.exolab.castor.xml.TypeValidator");
}
/** The type being described by the Descriptor class we'll generate. */
private final JClass _type;
/** Source Builder configuration. */
private final BuilderConfiguration _config;
/**
* Constructs a DescriptorJClass.
* @param config Builder Configuration
* @param className name of this descriptor class
* @param type the type that is described by this descriptor
*/
public DescriptorJClass(final BuilderConfiguration config, final String className,
final JClass type) {
super(className);
this._config = config;
this._type = type;
init();
} //-- DescriptorJClass
//-------------------/
//- Private Methods -/
//-------------------/
/**
* Initializes this DescriptorJClass with the required methods.
*/
private void init() {
// Make sure that the Descriptor is extended XMLClassDescriptor even when
// the user has specified a super class for all the generated classes
String superClass = null;
if (_config != null) {
superClass = _config.getProperty(BuilderConfiguration.Property.SUPER_CLASS, null);
}
boolean extended = false;
if (_type.getSuperClassQualifiedName() == null
|| _type.getSuperClassQualifiedName().equals(superClass)) {
setSuperClass(XMLCLASS_DESCRIPTOR_IMPL);
} else {
if (_type.getSuperClass() == null) {
setSuperClass(null);
} else {
extended = true;
setSuperClass(getSuperClassName());
}
}
superClass = null;
if (_type.getPackageName() != null && _type.getPackageName().length() > 0) {
addImport(_type.getName());
}
addField(new JField(JType.BOOLEAN, "_elementDefinition"));
addField(new JField(SGTypes.STRING, "_nsPrefix"));
addField(new JField(SGTypes.STRING, "_nsURI"));
addField(new JField(SGTypes.STRING, "_xmlName"));
//-- if there is a super class, the identity field must remain
//-- the same than the one in the super class
addField(new JField(XML_FIELD_DESCRIPTOR_CLASS, "_identity"));
//-- create default constructor
addDefaultConstructor(extended);
//jsc.add("Class[] emptyClassArgs = new Class[0];");
//jsc.add("Class[] classArgs = new Class[1];");
//---------------------------------------------/
//- Methods Defined by XMLClassDescriptorImpl -/
//---------------------------------------------/
addXMLClassDescriptorImplOverrides();
//-----------------------------------------/
//- Methods Defined by XMLClassDescriptor -/
//-----------------------------------------/
addXMLClassDescriptorOverrides();
//--------------------------------------/
//- Methods defined by ClassDescriptor -/
//--------------------------------------/
addClassDescriptorOverrides(extended);
} //-- createSource
/**
* Returns the qualified class name of the super class, adjusted to add the
* 'descriptors' sub-package.
* @return Returns the qualified class name of the super class
*/
private String getSuperClassName() {
final String superClassName;
if (_type.getSuperClass().getPackageName() == null
|| _type.getSuperClass().getPackageName().equals("")) {
if (getPackageName() == null) {
// no target package specified --> do not append package (=null)
superClassName = _type.getSuperClass().getLocalName()
+ XMLConstants.DESCRIPTOR_SUFFIX;
} else {
// target package specified --> simply use it
superClassName = getPackageName() + "." + _type.getSuperClass().getLocalName()
+ XMLConstants.DESCRIPTOR_SUFFIX;
}
} else {
superClassName = _type.getSuperClass().getPackageName()
+ "." + XMLConstants.DESCRIPTOR_PACKAGE + "."
+ _type.getSuperClass().getLocalName() + XMLConstants.DESCRIPTOR_SUFFIX;
}
return superClassName;
}
/**
* Adds our default constructor.
* @param extended true if we extend another class and thus need to call super()
*/
private void addDefaultConstructor(final boolean extended) {
addConstructor(createConstructor());
JConstructor cons = getConstructor(0);
JSourceCode jsc = cons.getSourceCode();
jsc.add("super();");
if (extended) {
//-- add base class (for validation)
jsc.add("setExtendsWithoutFlatten(");
jsc.append("new ");
jsc.append(getSuperClassQualifiedName());
jsc.append("());");
}
}
/**
* Adds the methods we override from.
* {@link org.exolab.castor.xml.util.XMLClassDescriptorImpl}
*/
private void addXMLClassDescriptorImplOverrides() {
//-- create isElementDefinition method
JMethod getElementDefinition = new JMethod("isElementDefinition", JType.BOOLEAN,
"true if XML schema definition of this Class is that of a global\n"
+ "element or element with anonymous type definition.");
JSourceCode jsc = getElementDefinition.getSourceCode();
jsc.add("return _elementDefinition;");
addMethod(getElementDefinition);
}
/**
* Adds the methods we override from.
* {@link org.exolab.castor.xml.XMLClassDescriptor}
*/
private void addXMLClassDescriptorOverrides() {
JMethod method;
JSourceCode jsc;
//-- create getNameSpacePrefix method
method = new JMethod("getNameSpacePrefix", SGTypes.STRING,
"the namespace prefix to use when marshaling as XML.");
if (_config.useJava50()) {
method.addAnnotation(new JAnnotation(new JAnnotationType("Override")));
}
jsc = method.getSourceCode();
jsc.add("return _nsPrefix;");
addMethod(method);
//-- create getNameSpaceURI method
method = new JMethod("getNameSpaceURI", SGTypes.STRING,
"the namespace URI used when marshaling and unmarshaling as XML.");
if (_config.useJava50()) {
method.addAnnotation(new JAnnotation(new JAnnotationType("Override")));
}
jsc = method.getSourceCode();
jsc.add("return _nsURI;");
addMethod(method);
//-- create getValidator method
method = new JMethod("getValidator", TYPE_VALIDATOR_CLASS,
"a specific validator for the class described"
+ " by this ClassDescriptor.");
if (_config.useJava50()) {
method.addAnnotation(new JAnnotation(new JAnnotationType("Override")));
}
jsc = method.getSourceCode();
jsc.add("return this;");
addMethod(method);
//-- create getXMLName method
method = new JMethod("getXMLName", SGTypes.STRING,
"the XML Name for the Class being described.");
if (_config.useJava50()) {
method.addAnnotation(new JAnnotation(new JAnnotationType("Override")));
}
jsc = method.getSourceCode();
jsc.add("return _xmlName;");
addMethod(method);
}
/**
* Adds the methods we override from.
* {@link org.exolab.castor.mapping.ClassDescriptor}
* @param extended true if we extend another class and thus need to call super()
*/
private void addClassDescriptorOverrides(final boolean extended) {
JSourceCode jsc;
//-- create getAccessMode method
JClass amClass = new JClass(MAPPING_ACCESS_MODE);
JMethod getAccessMode = new JMethod("getAccessMode", amClass,
"the access mode specified for this class.");
if (_config.useJava50()) {
getAccessMode.addAnnotation(new JAnnotation(new JAnnotationType("Override")));
}
jsc = getAccessMode.getSourceCode();
jsc.add("return null;");
addMethod(getAccessMode);
//-- create getIdentity method
JMethod getIdentity = new JMethod("getIdentity", FIELD_DESCRIPTOR_CLASS,
"the identity field, null if this class has no identity.");
if (_config.useJava50()) {
getIdentity.addAnnotation(new JAnnotation(new JAnnotationType("Override")));
}
jsc = getIdentity.getSourceCode();
if (extended) {
jsc.add("if (_identity == null) {");
jsc.indent();
jsc.add("return super.getIdentity();");
jsc.unindent();
jsc.add("}");
}
jsc.add("return _identity;");
//--don't add the type to the import list
addMethod(getIdentity, false);
//-- create getJavaClass method
JMethod getJavaClass = new JMethod("getJavaClass", SGTypes.CLASS,
"the Java class represented by this descriptor.");
if (_config.useJava50()) {
getJavaClass.addAnnotation(new JAnnotation(new JAnnotationType("Override")));
}
jsc = getJavaClass.getSourceCode();
jsc.add("return ");
jsc.append(classType(_type));
jsc.append(";");
//--don't add the type to the import list
addMethod(getJavaClass, false);
}
/**
* Returns the Class type (as a String) for the given XSType.
*
* @param jType
* the JType we are to return the class name of
* @return the Class name (as a String) for the given XSType
*/
private static String classType(final JType jType) {
if (jType.isPrimitive()) {
JPrimitiveType primitive = (JPrimitiveType) jType;
return primitive.getWrapperName() + ".TYPE";
}
return jType.toString() + ".class";
} //-- classType
} //-- DescriptorJClass