/** * 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