0001: /*
0002: * Licensed to the Apache Software Foundation (ASF) under one
0003: * or more contributor license agreements. See the NOTICE file
0004: * distributed with this work for additional information
0005: * regarding copyright ownership. The ASF licenses this file
0006: * to you under the Apache License, Version 2.0 (the
0007: * "License"); you may not use this file except in compliance
0008: * with the License. You may obtain a copy of the License at
0009: *
0010: * http://www.apache.org/licenses/LICENSE-2.0
0011: *
0012: * Unless required by applicable law or agreed to in writing,
0013: * software distributed under the License is distributed on an
0014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
0015: * KIND, either express or implied. See the License for the
0016: * specific language governing permissions and limitations
0017: * under the License.
0018: */
0019: package org.apache.axis2.schema;
0020:
0021: import org.apache.axis2.namespace.Constants;
0022: import org.apache.axis2.schema.i18n.SchemaCompilerMessages;
0023: import org.apache.axis2.schema.util.SchemaPropertyLoader;
0024: import org.apache.axis2.schema.writer.BeanWriter;
0025: import org.apache.axis2.util.URLProcessor;
0026: import org.apache.axis2.util.SchemaUtil;
0027: import org.apache.commons.logging.Log;
0028: import org.apache.commons.logging.LogFactory;
0029: import org.apache.ws.commons.schema.*;
0030:
0031: import javax.xml.namespace.QName;
0032: import java.util.*;
0033:
0034: /**
0035: * Schema compiler for ADB. Based on WS-Commons schema object model.
0036: */
0037: public class SchemaCompiler {
0038:
0039: private static final Log log = LogFactory
0040: .getLog(SchemaCompiler.class);
0041:
0042: private CompilerOptions options;
0043: private HashMap processedTypemap;
0044:
0045: //the list of processedElements for the outer elements
0046: private HashMap processedElementMap;
0047:
0048: private HashMap processedAnonymousComplexTypesMap;
0049:
0050: //we need this map to keep the referenced elements. these elements need to be kept seperate
0051: //to avoid conflicts
0052: private HashMap processedElementRefMap;
0053: private HashMap simpleTypesMap;
0054: private HashMap changedTypeMap;
0055:
0056: private HashSet changedSimpleTypeSet;
0057: private HashSet changedComplexTypeSet;
0058: private HashSet changedElementSet;
0059:
0060: // this map is necessary to retain the metainformation of types. The reason why these
0061: // meta info 'bags' would be useful later is to cater for the extensions and restrictions
0062: // of types
0063: private HashMap processedTypeMetaInfoMap;
0064:
0065: //
0066: private ArrayList processedElementList;
0067:
0068: //a list of nillable elements - used to generate code
0069: //for nillable elements
0070: private List nillableElementList;
0071: // writee reference
0072: private BeanWriter writer = null;
0073: private Map baseSchemaTypeMap = null;
0074:
0075: //a map for keeping the already loaded schemas
0076: //the key is the targetnamespace and the value is the schema object
0077: private Map loadedSchemaMap = new HashMap();
0078:
0079: // A map keeping the available schemas
0080: //the key is the targetnamespace and the value is the schema object
0081: //this map will be populated when multiple schemas
0082: //are fed to the schema compiler!
0083: private Map availableSchemaMap = new HashMap();
0084:
0085: private Map loadedSourceURI = new HashMap();
0086:
0087: // a list of externally identified QNames to be processed. This becomes
0088: // useful when only a list of external elements need to be processed
0089:
0090: public static final String ANY_ELEMENT_FIELD_NAME = "extraElement";
0091: public static final String EXTRA_ATTRIBUTE_FIELD_NAME = "extraAttributes";
0092:
0093: public static final String USE_OPTIONAL = "optional";
0094: public static final String USE_REQUIRED = "required";
0095: public static final String USE_NONE = "none";
0096:
0097: /**
0098: * @return the processes element map
0099: * includes the Qname of the element as the key and a
0100: * String representing the fully qualified class name
0101: */
0102: public HashMap getProcessedElementMap() {
0103: return processedElementMap;
0104: }
0105:
0106: /**
0107: * @return a map of Qname vs models. A model can be anything,
0108: * ranging from a DOM document to a stream. This is taken from the
0109: * writer and the schema compiler has no control over it
0110: */
0111: public Map getProcessedModelMap() {
0112: return writer.getModelMap();
0113: }
0114:
0115: /**
0116: * Constructor - Accepts a options bean
0117: *
0118: * @param options
0119: */
0120: public SchemaCompiler(CompilerOptions options)
0121: throws SchemaCompilationException {
0122:
0123: if (options == null) {
0124: //create an empty options object
0125: this .options = new CompilerOptions();
0126: } else {
0127: this .options = options;
0128: }
0129:
0130: //instantiate the maps
0131: processedTypemap = new HashMap();
0132: processedElementMap = new HashMap();
0133: simpleTypesMap = new HashMap();
0134: processedElementList = new ArrayList();
0135: processedAnonymousComplexTypesMap = new HashMap();
0136: changedTypeMap = new HashMap();
0137: processedTypeMetaInfoMap = new HashMap();
0138: processedElementRefMap = new HashMap();
0139: nillableElementList = new ArrayList();
0140:
0141: changedComplexTypeSet = new HashSet();
0142: changedSimpleTypeSet = new HashSet();
0143: changedElementSet = new HashSet();
0144:
0145: //load the writer and initiliaze the base types
0146: writer = SchemaPropertyLoader.getBeanWriterInstance();
0147: writer.init(this .options);
0148:
0149: //load the base types
0150: baseSchemaTypeMap = SchemaPropertyLoader
0151: .getTypeMapperInstance().getTypeMap();
0152:
0153: }
0154:
0155: /**
0156: * Compile a list of schemas
0157: * This actually calls the compile (XmlSchema s) method repeatedly
0158: *
0159: * @param schemalist
0160: * @throws SchemaCompilationException
0161: * @see #compile(org.apache.ws.commons.schema.XmlSchema)
0162: */
0163: public void compile(List schemalist)
0164: throws SchemaCompilationException {
0165: try {
0166:
0167: if (schemalist.isEmpty()) {
0168: return;
0169: }
0170:
0171: //clear the loaded and available maps
0172: loadedSchemaMap.clear();
0173: availableSchemaMap.clear();
0174:
0175: XmlSchema schema;
0176: // first round - populate the avaialble map
0177: for (int i = 0; i < schemalist.size(); i++) {
0178: schema = (XmlSchema) schemalist.get(i);
0179: availableSchemaMap.put(schema.getTargetNamespace(),
0180: schema);
0181: }
0182:
0183: //set a mapper package if not avaialable
0184: if (writer.getExtensionMapperPackageName() == null) {
0185: String nsp = null;
0186: //get the first schema from the list and take that namespace as the
0187: //mapper namespace
0188: for (int i = 0; nsp == null && i < schemalist.size(); i++) {
0189: nsp = ((XmlSchema) schemalist.get(i))
0190: .getTargetNamespace();
0191: if (nsp != null)
0192: break;
0193: XmlSchema[] schemas = SchemaUtil
0194: .getAllSchemas((XmlSchema) schemalist
0195: .get(i));
0196: for (int j = 0; schemas != null
0197: && j < schemas.length; j++) {
0198: nsp = schemas[j].getTargetNamespace();
0199: if (nsp != null)
0200: break;
0201: }
0202: }
0203: if (nsp == null) {
0204: nsp = URLProcessor.DEFAULT_PACKAGE;
0205: }
0206:
0207: // if this name space exists in the ns2p list then we use it.
0208: if ((options.getNs2PackageMap() != null)
0209: && (options.getNs2PackageMap().containsKey(nsp))) {
0210: writer
0211: .registerExtensionMapperPackageName((String) options
0212: .getNs2PackageMap().get(nsp));
0213: } else {
0214: writer
0215: .registerExtensionMapperPackageName(URLProcessor
0216: .makePackageName(nsp));
0217: }
0218: }
0219: // second round - call the schema compiler one by one
0220: for (int i = 0; i < schemalist.size(); i++) {
0221: compile((XmlSchema) schemalist.get(i), true);
0222: }
0223:
0224: //finish up
0225: finalizeSchemaCompilation();
0226:
0227: } catch (SchemaCompilationException e) {
0228: throw e;
0229: } catch (Exception e) {
0230: throw new SchemaCompilationException(e);
0231: }
0232: }
0233:
0234: /**
0235: * Compile (rather codegen) a single schema element
0236: *
0237: * @param schema
0238: * @throws SchemaCompilationException
0239: */
0240: public void compile(XmlSchema schema)
0241: throws SchemaCompilationException {
0242: compile(schema, false);
0243: }
0244:
0245: /**
0246: * Compile (rather codegen) a single schema element
0247: *
0248: * @param schema
0249: * @param isPartofGroup
0250: * @throws SchemaCompilationException
0251: */
0252: private void compile(XmlSchema schema, boolean isPartofGroup)
0253: throws SchemaCompilationException {
0254:
0255: // some documents explicitly imports the schema of built in types. We don't actually need to compile
0256: // the built-in types. So check the target namespace here and ignore it.
0257: if (Constants.URI_2001_SCHEMA_XSD.equals(schema
0258: .getTargetNamespace())) {
0259: return;
0260: }
0261:
0262: //register the package from this namespace as the mapper classes package
0263: if (!isPartofGroup) {
0264: //set a mapper package if not avaialable
0265: if (writer.getExtensionMapperPackageName() == null) {
0266: writer.registerExtensionMapperPackageName(URLProcessor
0267: .makePackageName(schema.getTargetNamespace()));
0268: }
0269: }
0270:
0271: //First look for the schemas that are imported and process them
0272: //Note that these are processed recursively!
0273:
0274: //add the schema to the loaded schema list
0275: if (!loadedSchemaMap.containsKey(schema.getTargetNamespace())) {
0276: loadedSchemaMap.put(schema.getTargetNamespace(), schema);
0277: }
0278:
0279: // If we have/are loading a schema with a specific targetnamespace from a certain URI,
0280: // then just return back to the caller to avoid recursion.
0281: if (schema.getSourceURI() != null) {
0282: String key = schema.getTargetNamespace() + ":"
0283: + schema.getSourceURI();
0284: if (loadedSourceURI.containsKey(key)) {
0285: return;
0286: }
0287: loadedSourceURI.put(key, key);
0288: }
0289:
0290: XmlSchemaObjectCollection includes = schema.getIncludes();
0291: if (includes != null) {
0292: Iterator tempIterator = includes.getIterator();
0293: while (tempIterator.hasNext()) {
0294: Object o = tempIterator.next();
0295: if (o instanceof XmlSchemaImport) {
0296: XmlSchema schema1 = ((XmlSchemaImport) o)
0297: .getSchema();
0298: if (schema1 != null)
0299: compile(schema1, isPartofGroup);
0300: }
0301: if (o instanceof XmlSchemaInclude) {
0302: XmlSchema schema1 = ((XmlSchemaInclude) o)
0303: .getSchema();
0304: if (schema1 != null)
0305: compile(schema1, isPartofGroup);
0306: }
0307: }
0308: }
0309:
0310: //select all the elements. We generate the code for types
0311: //only if the elements refer them!!! regardless of the fact that
0312: //we have a list of elementnames, we'll need to process all the elements
0313: XmlSchemaObjectTable elements = schema.getElements();
0314: Iterator xmlSchemaElement1Iterator = elements.getValues();
0315: while (xmlSchemaElement1Iterator.hasNext()) {
0316: //this is the set of outer elements so we need to generate classes
0317: //The outermost elements do not contain occurence counts (!) so we do not need
0318: //to check for arraytypes
0319: processElement((XmlSchemaElement) xmlSchemaElement1Iterator
0320: .next(), schema);
0321: }
0322:
0323: Iterator xmlSchemaElement2Iterator = elements.getValues();
0324:
0325: // re-iterate through the elements and write them one by one
0326: // if the mode is unpack this process will not really write the
0327: // classes but will accumilate the models for a final single shot
0328: // write
0329: while (xmlSchemaElement2Iterator.hasNext()) {
0330: //this is the set of outer elements so we need to generate classes
0331: writeElement((XmlSchemaElement) xmlSchemaElement2Iterator
0332: .next());
0333: }
0334:
0335: if (options.isGenerateAll()) {
0336: Iterator xmlSchemaTypes2Iterator = schema.getSchemaTypes()
0337: .getValues();
0338: while (xmlSchemaTypes2Iterator.hasNext()) {
0339: XmlSchemaType schemaType = (XmlSchemaType) xmlSchemaTypes2Iterator
0340: .next();
0341: if (this .isAlreadyProcessed(schemaType.getQName())) {
0342: continue;
0343: }
0344: if (schemaType instanceof XmlSchemaComplexType) {
0345: //write classes for complex types
0346: XmlSchemaComplexType complexType = (XmlSchemaComplexType) schemaType;
0347: if (complexType.getName() != null) {
0348: processNamedComplexSchemaType(complexType,
0349: schema);
0350: }
0351: } else if (schemaType instanceof XmlSchemaSimpleType) {
0352: //process simple type
0353: processSimpleSchemaType(
0354: (XmlSchemaSimpleType) schemaType, null,
0355: schema, null);
0356: }
0357: }
0358: }
0359:
0360: if (!isPartofGroup) {
0361: //complete the compilation
0362: finalizeSchemaCompilation();
0363: }
0364: }
0365:
0366: /**
0367: * Completes the schema compilation process by writing the
0368: * mappers and the classes in a batch if needed
0369: *
0370: * @throws SchemaCompilationException
0371: */
0372: private void finalizeSchemaCompilation()
0373: throws SchemaCompilationException {
0374: //write the extension mapping class
0375: writer
0376: .writeExtensionMapper((BeanWriterMetaInfoHolder[]) processedTypeMetaInfoMap
0377: .values()
0378: .toArray(
0379: new BeanWriterMetaInfoHolder[processedTypeMetaInfoMap
0380: .size()]));
0381:
0382: if (options.isWrapClasses()) {
0383: writer.writeBatch();
0384: }
0385:
0386: // resets the changed types
0387: XmlSchemaComplexType xmlSchemaComplexType = null;
0388: for (Iterator iter = changedComplexTypeSet.iterator(); iter
0389: .hasNext();) {
0390: xmlSchemaComplexType = (XmlSchemaComplexType) iter.next();
0391: xmlSchemaComplexType.setName(null);
0392: }
0393:
0394: XmlSchemaSimpleType xmlSchemaSimpleType = null;
0395: for (Iterator iter = changedSimpleTypeSet.iterator(); iter
0396: .hasNext();) {
0397: xmlSchemaSimpleType = (XmlSchemaSimpleType) iter.next();
0398: xmlSchemaSimpleType.setName(null);
0399: }
0400:
0401: XmlSchemaElement xmlSchemaElement = null;
0402: for (Iterator iter = changedElementSet.iterator(); iter
0403: .hasNext();) {
0404: xmlSchemaElement = (XmlSchemaElement) iter.next();
0405: xmlSchemaElement.setSchemaTypeName(null);
0406: }
0407:
0408: }
0409:
0410: /**
0411: * @return the property map of the schemacompiler.
0412: * In this case it would be the property map loaded from
0413: * the configuration file
0414: */
0415: public Properties getCompilerProperties() {
0416: return SchemaPropertyLoader.getPropertyMap();
0417: }
0418:
0419: /**
0420: * Writes the element
0421: *
0422: * @param xsElt
0423: * @throws SchemaCompilationException
0424: */
0425: private void writeElement(XmlSchemaElement xsElt)
0426: throws SchemaCompilationException {
0427:
0428: if (this .processedElementMap.containsKey(xsElt.getQName())) {
0429: return;
0430: }
0431:
0432: XmlSchemaType schemaType = xsElt.getSchemaType();
0433:
0434: BeanWriterMetaInfoHolder metainf = new BeanWriterMetaInfoHolder();
0435: if (schemaType != null && schemaType.getName() != null) {
0436: //this is a named type
0437: QName qName = schemaType.getQName();
0438: //find the class name
0439: String className = findClassName(qName, isArray(xsElt));
0440:
0441: //this means the schema type actually returns a different QName
0442: if (changedTypeMap.containsKey(qName)) {
0443: metainf.registerMapping(xsElt.getQName(),
0444: (QName) changedTypeMap.get(qName), className);
0445: } else {
0446: metainf.registerMapping(xsElt.getQName(), qName,
0447: className);
0448: }
0449: if (isBinary(xsElt)) {
0450: metainf.addtStatus(xsElt.getQName(),
0451: SchemaConstants.BINARY_TYPE);
0452: }
0453:
0454: } else if (xsElt.getRefName() != null) {
0455: // Since top level elements would not have references
0456: // and we only write toplevel elements, this should
0457: // not be a problem , atleast should not occur in a legal schema
0458: } else if (xsElt.getSchemaTypeName() != null) {
0459: QName qName = xsElt.getSchemaTypeName();
0460: String className = findClassName(qName, isArray(xsElt));
0461: metainf.registerMapping(xsElt.getQName(), qName, className);
0462:
0463: } else if (schemaType != null) { //the named type should have been handled already
0464:
0465: //we are going to special case the anonymous complex type. Our algorithm for dealing
0466: //with it is to generate a single object that has the complex content inside. Really the
0467: //intent of the user when he declares the complexType anonymously is to use it privately
0468: //First copy the schema types content into the metainf holder
0469: metainf = (BeanWriterMetaInfoHolder) this .processedAnonymousComplexTypesMap
0470: .get(xsElt);
0471: metainf.setAnonymous(true);
0472: } else {
0473: //this means we did not find any schema type associated with the particular element.
0474: log.warn(SchemaCompilerMessages.getMessage(
0475: "schema.elementWithNoType", xsElt.getQName()
0476: .toString()));
0477: metainf.registerMapping(xsElt.getQName(), null, writer
0478: .getDefaultClassName(), SchemaConstants.ANY_TYPE);
0479: }
0480:
0481: if (nillableElementList.contains(xsElt.getQName())) {
0482: metainf.registerNillableQName(xsElt.getQName());
0483: }
0484:
0485: String writtenClassName = writer.write(xsElt, processedTypemap,
0486: metainf);
0487: //register the class name
0488: xsElt.addMetaInfo(
0489: SchemaConstants.SchemaCompilerInfoHolder.CLASSNAME_KEY,
0490: writtenClassName);
0491: processedElementMap.put(xsElt.getQName(), writtenClassName);
0492: }
0493:
0494: /**
0495: * For inner elements
0496: *
0497: * @param xsElt
0498: * @param innerElementMap
0499: * @param parentSchema
0500: * @throws SchemaCompilationException
0501: */
0502: private void processElement(XmlSchemaElement xsElt,
0503: Map innerElementMap, List localNillableList,
0504: XmlSchema parentSchema) throws SchemaCompilationException {
0505: processElement(xsElt, false, innerElementMap,
0506: localNillableList, parentSchema);
0507: }
0508:
0509: /**
0510: * For outer elements
0511: *
0512: * @param xsElt
0513: * @param parentSchema
0514: * @throws SchemaCompilationException
0515: */
0516: private void processElement(XmlSchemaElement xsElt,
0517: XmlSchema parentSchema) throws SchemaCompilationException {
0518: processElement(xsElt, true, null, null, parentSchema);
0519: }
0520:
0521: /**
0522: * Process and Element
0523: *
0524: * @param xsElt
0525: * @param isOuter We need to know this since the treatment of outer elements is different that
0526: * inner elements
0527: * @throws SchemaCompilationException
0528: */
0529: private void processElement(XmlSchemaElement xsElt,
0530: boolean isOuter, Map innerElementMap,
0531: List localNillableList, XmlSchema parentSchema)
0532: throws SchemaCompilationException {
0533:
0534: //if the element is null, which usually happens when the qname is not
0535: //proper, throw an exceptions
0536: if (xsElt == null) {
0537: throw new SchemaCompilationException(SchemaCompilerMessages
0538: .getMessage("schema.elementNull"));
0539: }
0540:
0541: //The processing element logic seems to be quite simple. Look at the relevant schema type
0542: //for each and every element and process that accordingly.
0543: //this means that any unused type definitions would not be generated!
0544: if (isOuter && processedElementList.contains(xsElt.getQName())) {
0545: return;
0546: }
0547:
0548: XmlSchemaType schemaType = xsElt.getSchemaType();
0549: if (schemaType != null) {
0550: processSchema(xsElt, schemaType, parentSchema);
0551: //at this time it is not wise to directly write the class for the element
0552: //so we push the complete element to an arraylist and let the process
0553: //pass through. We'll be iterating through the elements writing them
0554: //later
0555:
0556: if (!isOuter) {
0557: if (schemaType.getName() != null) {
0558: // this element already has a name. Which means we can directly
0559: // register it
0560: String className = findClassName(schemaType
0561: .getQName(), isArray(xsElt));
0562:
0563: innerElementMap.put(xsElt.getQName(), className);
0564:
0565: // always store the class name in the element meta Info itself
0566: // this details only needed by the unwrappig to set the complex type
0567: schemaType
0568: .addMetaInfo(
0569: SchemaConstants.SchemaCompilerInfoHolder.CLASSNAME_KEY,
0570: className);
0571: xsElt
0572: .addMetaInfo(
0573: SchemaConstants.SchemaCompilerInfoHolder.CLASSNAME_KEY,
0574: className);
0575:
0576: if (baseSchemaTypeMap.containsValue(className)) {
0577: schemaType
0578: .addMetaInfo(
0579: SchemaConstants.SchemaCompilerInfoHolder.CLASSNAME_PRIMITVE_KEY,
0580: Boolean.TRUE);
0581: }
0582: //since this is a inner element we should add it to the inner element map
0583: } else {
0584: //this is an anon type. This should have been already processed and registered at
0585: //the anon map. we've to write it just like we treat a referenced type(giving due
0586: //care that this is meant to be an attribute in some class)
0587:
0588: QName generatedTypeName = generateTypeQName(xsElt
0589: .getQName(), parentSchema);
0590:
0591: if (schemaType instanceof XmlSchemaComplexType) {
0592: //set a name
0593: schemaType.setName(generatedTypeName
0594: .getLocalPart());
0595: changedComplexTypeSet.add(schemaType);
0596: // Must do this up front to support recursive types
0597: String fullyQualifiedClassName = writer
0598: .makeFullyQualifiedClassName(schemaType
0599: .getQName());
0600: processedTypemap.put(schemaType.getQName(),
0601: fullyQualifiedClassName);
0602:
0603: BeanWriterMetaInfoHolder metaInfHolder = (BeanWriterMetaInfoHolder) processedAnonymousComplexTypesMap
0604: .get(xsElt);
0605: metaInfHolder
0606: .setOwnQname(schemaType.getQName());
0607: metaInfHolder
0608: .setOwnClassName(fullyQualifiedClassName);
0609:
0610: writeComplexType(
0611: (XmlSchemaComplexType) schemaType,
0612: metaInfHolder);
0613: //remove the reference from the anon list since we named the type
0614: processedAnonymousComplexTypesMap.remove(xsElt);
0615: String className = findClassName(schemaType
0616: .getQName(), isArray(xsElt));
0617: innerElementMap
0618: .put(xsElt.getQName(), className);
0619:
0620: //store in the schema map to retrive in the unwrapping
0621: xsElt
0622: .addMetaInfo(
0623: SchemaConstants.SchemaCompilerInfoHolder.CLASSNAME_KEY,
0624: className);
0625: } else if (schemaType instanceof XmlSchemaSimpleType) {
0626: //set a name
0627: schemaType.setName(generatedTypeName
0628: .getLocalPart());
0629: changedSimpleTypeSet.add(schemaType);
0630: // Must do this up front to support recursive types
0631: String fullyQualifiedClassName = writer
0632: .makeFullyQualifiedClassName(schemaType
0633: .getQName());
0634: processedTypemap.put(schemaType.getQName(),
0635: fullyQualifiedClassName);
0636:
0637: BeanWriterMetaInfoHolder metaInfHolder = (BeanWriterMetaInfoHolder) processedAnonymousComplexTypesMap
0638: .get(xsElt);
0639: metaInfHolder
0640: .setOwnQname(schemaType.getQName());
0641: metaInfHolder
0642: .setOwnClassName(fullyQualifiedClassName);
0643:
0644: writeSimpleType(
0645: (XmlSchemaSimpleType) schemaType,
0646: metaInfHolder);
0647: //remove the reference from the anon list since we named the type
0648: processedAnonymousComplexTypesMap.remove(xsElt);
0649: String className = findClassName(schemaType
0650: .getQName(), isArray(xsElt));
0651: innerElementMap
0652: .put(xsElt.getQName(), className);
0653:
0654: //store in the schema map
0655: xsElt
0656: .addMetaInfo(
0657: SchemaConstants.SchemaCompilerInfoHolder.CLASSNAME_KEY,
0658: className);
0659: }
0660: }
0661: } else {
0662: // set the binary status of this element
0663: this .processedElementList.add(xsElt.getQName());
0664: }
0665: //referenced name
0666: } else if (xsElt.getRefName() != null) {
0667:
0668: if (xsElt.getRefName().equals(SchemaConstants.XSD_SCHEMA)) {
0669: innerElementMap.put(xsElt.getQName(), writer
0670: .getDefaultClassName());
0671: return;
0672: }
0673: //process the referenced type. It could be thought that the referenced element replaces this
0674: //element
0675: XmlSchemaElement referencedElement = getReferencedElement(
0676: parentSchema, xsElt.getRefName());
0677: if (referencedElement == null) {
0678: throw new SchemaCompilationException(
0679: SchemaCompilerMessages.getMessage(
0680: "schema.referencedElementNotFound",
0681: xsElt.getRefName().toString()));
0682: }
0683:
0684: //if the element is referenced, then it should be one of the outer (global) ones
0685: processElement(referencedElement, parentSchema);
0686:
0687: //no outer check required here. If the element is having a ref, then it is definitely
0688: //not an outer element since the top level elements are not supposed to have refs
0689: //Also we are sure that it should have a type reference
0690: QName referenceEltQName = referencedElement.getQName();
0691: if (referencedElement.getSchemaTypeName() != null) {
0692: // we have to only find the class name without arrary part
0693: String javaClassName = findClassName(referencedElement
0694: .getSchemaTypeName(), false);
0695: //if this element is referenced, there's no QName for this element
0696: this .processedElementRefMap.put(referenceEltQName,
0697: javaClassName);
0698: referencedElement
0699: .addMetaInfo(
0700: SchemaConstants.SchemaCompilerInfoHolder.CLASSNAME_KEY,
0701: javaClassName);
0702: // set the element class name to be used in unwrapping
0703: xsElt
0704: .addMetaInfo(
0705: SchemaConstants.SchemaCompilerInfoHolder.CLASSNAME_KEY,
0706: javaClassName);
0707: } else {
0708: //this referenced element has an anon type and that anon type has been already
0709: //processed. But in this case we need it to be a seperate class since this
0710: //complextype has to be added as an attribute in a class.
0711: //generate a name for this type
0712: QName generatedTypeName = generateTypeQName(
0713: referenceEltQName, parentSchema);
0714: XmlSchemaType referenceSchemaType = referencedElement
0715: .getSchemaType();
0716:
0717: if (referenceSchemaType instanceof XmlSchemaComplexType) {
0718:
0719: if (referencedElement.getSchemaTypeName() == null) {
0720: referencedElement
0721: .setSchemaTypeName(generatedTypeName);
0722: }
0723:
0724: //set a name
0725: referenceSchemaType.setName(generatedTypeName
0726: .getLocalPart());
0727:
0728: String javaclassName = writeComplexType(
0729: (XmlSchemaComplexType) referenceSchemaType,
0730: (BeanWriterMetaInfoHolder) processedAnonymousComplexTypesMap
0731: .get(referencedElement));
0732: //remove the reference from the anon list since we named the type
0733: // DEEPAL :- We can not remove the entry from the hashtable ,
0734: // this will fail if there are two reference for the same type
0735:
0736: //processedAnonymousComplexTypesMap.remove(referencedElement);
0737:
0738: processedTypemap.put(generatedTypeName,
0739: javaclassName);
0740: this .processedElementRefMap.put(referenceEltQName,
0741: javaclassName);
0742: // set the class name to be used in unwrapping
0743: xsElt
0744: .addMetaInfo(
0745: SchemaConstants.SchemaCompilerInfoHolder.CLASSNAME_KEY,
0746: javaclassName);
0747:
0748: }
0749: }
0750: // schema type name is present but not the schema type object
0751: } else if (xsElt.getSchemaTypeName() != null) {
0752: //There can be instances where the SchemaType is null but the schemaTypeName is not!
0753: //this specifically happens with xsd:anyType.
0754: QName schemaTypeName = xsElt.getSchemaTypeName();
0755:
0756: XmlSchema currentParentSchema = resolveParentSchema(
0757: schemaTypeName, parentSchema);
0758: XmlSchemaType typeByName = getType(currentParentSchema,
0759: schemaTypeName);
0760:
0761: if (typeByName != null) {
0762: //this type is found in the schema so we can process it
0763: processSchema(xsElt, typeByName, currentParentSchema);
0764: if (!isOuter) {
0765: String className = findClassName(schemaTypeName,
0766: isArray(xsElt));
0767: //since this is a inner element we should add it to the inner element map
0768: innerElementMap.put(xsElt.getQName(), className);
0769: // set the class name to be used in unwrapping
0770: xsElt
0771: .addMetaInfo(
0772: SchemaConstants.SchemaCompilerInfoHolder.CLASSNAME_KEY,
0773: className);
0774: } else {
0775: this .processedElementList.add(xsElt.getQName());
0776: }
0777: } else {
0778: //this type is not found at all. we'll just register it with whatever the class name we can comeup with
0779: if (!isOuter) {
0780: String className = findClassName(schemaTypeName,
0781: isArray(xsElt));
0782: innerElementMap.put(xsElt.getQName(), className);
0783: // set the class name to be used in unwrapping
0784: xsElt
0785: .addMetaInfo(
0786: SchemaConstants.SchemaCompilerInfoHolder.CLASSNAME_KEY,
0787: className);
0788: } else {
0789: this .processedElementList.add(xsElt.getQName());
0790: }
0791: }
0792: }
0793:
0794: //add this elements QName to the nillable group if it has the nillable attribute
0795: if (xsElt.isNillable()) {
0796: if (isOuter) {
0797: this .nillableElementList.add(xsElt.getQName());
0798: } else {
0799: localNillableList.add(xsElt.getQName());
0800: }
0801: }
0802:
0803: }
0804:
0805: /**
0806: * resolve the parent schema for the given schema type name
0807: *
0808: * @param schemaTypeName
0809: * @param currentSchema
0810: */
0811: private XmlSchema resolveParentSchema(QName schemaTypeName,
0812: XmlSchema currentSchema) throws SchemaCompilationException {
0813: String targetNamespace = schemaTypeName.getNamespaceURI();
0814:
0815: // if the current schema has the same namespace we use it
0816: if ((currentSchema.getTargetNamespace() != null)
0817: && currentSchema.getTargetNamespace().equals(
0818: targetNamespace)) {
0819: return currentSchema;
0820: }
0821: Object loadedSchema = loadedSchemaMap.get(targetNamespace);
0822: if (loadedSchema != null) {
0823: return (XmlSchema) loadedSchema;
0824: } else if (availableSchemaMap.containsKey(targetNamespace)) {
0825: //compile the referenced Schema first and then pass it
0826: XmlSchema schema = (XmlSchema) availableSchemaMap
0827: .get(targetNamespace);
0828: compile(schema);
0829: return schema;
0830: } else {
0831: return currentSchema;
0832: }
0833: }
0834:
0835: /**
0836: * Generate a unique type Qname using an element name
0837: *
0838: * @param referenceEltQName
0839: * @param parentSchema
0840: */
0841: private QName generateTypeQName(QName referenceEltQName,
0842: XmlSchema parentSchema) {
0843: QName generatedTypeName = new QName(referenceEltQName
0844: .getNamespaceURI(), referenceEltQName.getLocalPart()
0845: + getNextTypeSuffix(referenceEltQName.getLocalPart()));
0846: while (parentSchema.getTypeByName(generatedTypeName) != null) {
0847: generatedTypeName = new QName(referenceEltQName
0848: .getNamespaceURI(), referenceEltQName
0849: .getLocalPart()
0850: + getNextTypeSuffix(referenceEltQName
0851: .getLocalPart()));
0852: }
0853: return generatedTypeName;
0854: }
0855:
0856: /**
0857: * Finds whether a given class is already made
0858: *
0859: * @param qName
0860: */
0861: private boolean isAlreadyProcessed(QName qName) {
0862: return processedTypemap.containsKey(qName)
0863: || simpleTypesMap.containsKey(qName)
0864: || baseSchemaTypeMap.containsKey(qName);
0865: }
0866:
0867: /**
0868: * A method to pick the ref class name
0869: *
0870: * @param name
0871: * @param isArray
0872: */
0873: private String findRefClassName(QName name, boolean isArray) {
0874: String className = null;
0875: if (processedElementRefMap.get(name) != null) {
0876: className = (String) processedElementRefMap.get(name);
0877:
0878: if (isArray) {
0879: //append the square braces that say this is an array
0880: //hope this works for all cases!!!!!!!
0881: //todo this however is a thing that needs to be
0882: //todo fixed to get complete language support
0883: className = className + "[]";
0884: }
0885: }
0886: return className;
0887:
0888: }
0889:
0890: /**
0891: * Finds a class name from the given Qname
0892: *
0893: * @param qName
0894: * @param isArray
0895: * @return FQCN
0896: */
0897: private String findClassName(QName qName, boolean isArray)
0898: throws SchemaCompilationException {
0899:
0900: //find the class name
0901: String className;
0902: if (processedTypemap.containsKey(qName)) {
0903: className = (String) processedTypemap.get(qName);
0904: } else if (simpleTypesMap.containsKey(qName)) {
0905: className = (String) simpleTypesMap.get(qName);
0906: } else if (baseSchemaTypeMap.containsKey(qName)) {
0907: className = (String) baseSchemaTypeMap.get(qName);
0908: } else {
0909: if (isSOAP_ENC(qName.getNamespaceURI())) {
0910: throw new SchemaCompilationException(
0911: SchemaCompilerMessages.getMessage(
0912: "schema.soapencoding.error", qName
0913: .toString()));
0914:
0915: }
0916: // We seem to have failed in finding a class name for the
0917: //contained schema type. We better set the default then
0918: //however it's better if the default can be set through the
0919: //property file
0920: className = writer.getDefaultClassName();
0921: log.warn(SchemaCompilerMessages.getMessage(
0922: "schema.typeMissing", qName.toString()));
0923: }
0924:
0925: if (isArray) {
0926: //append the square braces that say this is an array
0927: //hope this works for all cases!!!!!!!
0928: //todo this however is a thing that needs to be
0929: //todo fixed to get complete language support
0930: className = className + "[]";
0931: }
0932: return className;
0933: }
0934:
0935: /**
0936: * Returns true if SOAP_ENC Namespace.
0937: *
0938: * @param s a string representing the URI to check
0939: * @return true if <code>s</code> matches a SOAP ENCODING namespace URI,
0940: * false otherwise
0941: */
0942: public static boolean isSOAP_ENC(String s) {
0943: if (s.equals(Constants.URI_SOAP11_ENC))
0944: return true;
0945: return s.equals(Constants.URI_SOAP12_ENC);
0946: }
0947:
0948: /**
0949: * Process a schema element which has been refered to by an element
0950: *
0951: * @param schemaType
0952: * @throws SchemaCompilationException
0953: */
0954: private void processSchema(XmlSchemaElement xsElt,
0955: XmlSchemaType schemaType, XmlSchema parentSchema)
0956: throws SchemaCompilationException {
0957: if (schemaType instanceof XmlSchemaComplexType) {
0958: //write classes for complex types
0959: XmlSchemaComplexType complexType = (XmlSchemaComplexType) schemaType;
0960: if (complexType.getName() != null) {
0961: processNamedComplexSchemaType(complexType, parentSchema);
0962: } else {
0963: processAnonymousComplexSchemaType(xsElt, complexType,
0964: parentSchema);
0965: }
0966: } else if (schemaType instanceof XmlSchemaSimpleType) {
0967: //process simple type
0968: processSimpleSchemaType((XmlSchemaSimpleType) schemaType,
0969: xsElt, parentSchema, null);
0970: }
0971: }
0972:
0973: /**
0974: * @param complexType
0975: * @throws SchemaCompilationException
0976: */
0977: private void processAnonymousComplexSchemaType(
0978: XmlSchemaElement elt, XmlSchemaComplexType complexType,
0979: XmlSchema parentSchema) throws SchemaCompilationException {
0980: BeanWriterMetaInfoHolder metaInfHolder = processComplexType(elt
0981: .getQName(), complexType, parentSchema);
0982:
0983: //since this is a special case (an unnamed complex type) we'll put the already processed
0984: //metainf holder in a special map to be used later
0985: this .processedAnonymousComplexTypesMap.put(elt, metaInfHolder);
0986: }
0987:
0988: /**
0989: * handle the complex types which are named
0990: *
0991: * @param complexType
0992: */
0993: private void processNamedComplexSchemaType(
0994: XmlSchemaComplexType complexType, XmlSchema parentSchema)
0995: throws SchemaCompilationException {
0996:
0997: if (processedTypemap.containsKey(complexType.getQName())
0998: || baseSchemaTypeMap
0999: .containsKey(complexType.getQName())) {
1000: return;
1001: }
1002:
1003: // Must do this up front to support recursive types
1004: String fullyQualifiedClassName = writer
1005: .makeFullyQualifiedClassName(complexType.getQName());
1006: processedTypemap.put(complexType.getQName(),
1007: fullyQualifiedClassName);
1008:
1009: //register that in the schema metainfo bag
1010: complexType.addMetaInfo(
1011: SchemaConstants.SchemaCompilerInfoHolder.CLASSNAME_KEY,
1012: fullyQualifiedClassName);
1013:
1014: BeanWriterMetaInfoHolder metaInfHolder = processComplexType(
1015: complexType.getQName(), complexType, parentSchema);
1016: //add this information to the metainfo holder
1017: metaInfHolder.setOwnQname(complexType.getQName());
1018: metaInfHolder.setOwnClassName(fullyQualifiedClassName);
1019: //write the class. This type mapping would have been populated right now
1020: //Note - We always write classes for named complex types
1021: writeComplexType(complexType, metaInfHolder);
1022:
1023: }
1024:
1025: /**
1026: * Writes a complex type
1027: *
1028: * @param complexType
1029: * @param metaInfHolder
1030: * @throws SchemaCompilationException
1031: */
1032: private String writeComplexType(XmlSchemaComplexType complexType,
1033: BeanWriterMetaInfoHolder metaInfHolder)
1034: throws SchemaCompilationException {
1035: String javaClassName = writer.write(complexType.getQName(),
1036: processedTypemap, metaInfHolder, complexType
1037: .isAbstract());
1038: processedTypeMetaInfoMap.put(complexType.getQName(),
1039: metaInfHolder);
1040: return javaClassName;
1041: }
1042:
1043: /**
1044: * Writes complex Sequence,Choice, all elements
1045: * @param qname complex type qname
1046: * @param metaInfHolder
1047: * @return written java class name
1048: * @throws SchemaCompilationException
1049: */
1050:
1051: private String writeComplexParticle(QName qname,
1052: BeanWriterMetaInfoHolder metaInfHolder)
1053: throws SchemaCompilationException {
1054: String javaClassName = writer.write(qname, processedTypemap,
1055: metaInfHolder, false);
1056: processedTypeMetaInfoMap.put(qname, metaInfHolder);
1057: return javaClassName;
1058: }
1059:
1060: /**
1061: * Writes a complex type
1062: *
1063: * @param simpleType
1064: * @param metaInfHolder
1065: * @throws SchemaCompilationException
1066: */
1067: private void writeSimpleType(XmlSchemaSimpleType simpleType,
1068: BeanWriterMetaInfoHolder metaInfHolder)
1069: throws SchemaCompilationException {
1070: writer.write(simpleType, processedTypemap, metaInfHolder);
1071: processedTypeMetaInfoMap.put(simpleType.getQName(),
1072: metaInfHolder);
1073: }
1074:
1075: private BeanWriterMetaInfoHolder processComplexType(
1076: QName parentElementQName, XmlSchemaComplexType complexType,
1077: XmlSchema parentSchema) throws SchemaCompilationException {
1078: XmlSchemaParticle particle = complexType.getParticle();
1079: BeanWriterMetaInfoHolder metaInfHolder = new BeanWriterMetaInfoHolder();
1080: if (particle != null) {
1081: //Process the particle
1082: processParticle(parentElementQName, particle,
1083: metaInfHolder, parentSchema);
1084: }
1085:
1086: //process attributes - first look for the explicit attributes
1087: processAttributes(complexType.getAttributes(), metaInfHolder,
1088: parentSchema);
1089:
1090: //process any attribute
1091: //somehow the xml schema parser does not seem to pickup the any attribute!!
1092: XmlSchemaAnyAttribute anyAtt = complexType.getAnyAttribute();
1093: if (anyAtt != null) {
1094: processAnyAttribute(metaInfHolder, anyAtt);
1095: }
1096:
1097: //process content ,either complex or simple
1098: if (complexType.getContentModel() != null) {
1099: processContentModel(complexType.getContentModel(),
1100: metaInfHolder, parentSchema);
1101: }
1102: return metaInfHolder;
1103: }
1104:
1105: private void processAttributes(
1106: XmlSchemaObjectCollection attributes,
1107: BeanWriterMetaInfoHolder metaInfHolder,
1108: XmlSchema parentSchema) throws SchemaCompilationException {
1109: Iterator attribIterator = attributes.getIterator();
1110: while (attribIterator.hasNext()) {
1111: Object o = attribIterator.next();
1112: if (o instanceof XmlSchemaAttribute) {
1113: processAttribute((XmlSchemaAttribute) o, metaInfHolder,
1114: parentSchema);
1115: } else if (o instanceof XmlSchemaAttributeGroupRef) {
1116: processAttributeGroupReference(
1117: (XmlSchemaAttributeGroupRef) o, metaInfHolder,
1118: parentSchema);
1119: }
1120: }
1121: }
1122:
1123: private void processAttributeGroupReference(
1124: XmlSchemaAttributeGroupRef attributeGroupRef,
1125: BeanWriterMetaInfoHolder metaInfHolder,
1126: XmlSchema parentSchema) throws SchemaCompilationException {
1127:
1128: QName attributeGroupRefName = attributeGroupRef.getRefName();
1129: if (attributeGroupRefName != null) {
1130: parentSchema = resolveParentSchema(attributeGroupRefName,
1131: parentSchema);
1132: XmlSchemaAttributeGroup xmlSchemaAttributeGroup = getXmlSchemaAttributeGroup(
1133: attributeGroupRefName, parentSchema);
1134: if (xmlSchemaAttributeGroup != null) {
1135: processAttributes(xmlSchemaAttributeGroup
1136: .getAttributes(), metaInfHolder, parentSchema);
1137: } else {
1138: throw new SchemaCompilationException(
1139: "Can not find an attribute group for group reference "
1140: + attributeGroupRefName.getLocalPart());
1141: }
1142: } else {
1143: throw new SchemaCompilationException(
1144: "No group refernce has given");
1145: }
1146:
1147: }
1148:
1149: private XmlSchemaAttributeGroup getXmlSchemaAttributeGroup(
1150: QName attributeGroupQName, XmlSchema parentSchema) {
1151: XmlSchemaAttributeGroup xmlSchemaAttributeGroup = (XmlSchemaAttributeGroup) parentSchema
1152: .getAttributeGroups().getItem(attributeGroupQName);
1153: if (xmlSchemaAttributeGroup == null) {
1154: // i.e this attribute can be in a included or imported schema
1155: xmlSchemaAttributeGroup = (XmlSchemaAttributeGroup) parentSchema
1156: .getAttributeGroups().getItem(attributeGroupQName);
1157: if (xmlSchemaAttributeGroup == null) {
1158: // try to find in an import or an include
1159: XmlSchemaObjectCollection includes = parentSchema
1160: .getIncludes();
1161: if (includes != null) {
1162: Iterator includesIter = includes.getIterator();
1163: Object object = null;
1164: while (includesIter.hasNext()) {
1165: object = includesIter.next();
1166: if (object instanceof XmlSchemaImport) {
1167: XmlSchema schema1 = ((XmlSchemaImport) object)
1168: .getSchema();
1169: xmlSchemaAttributeGroup = (XmlSchemaAttributeGroup) schema1
1170: .getAttributeGroups().getItem(
1171: attributeGroupQName);
1172: }
1173: if (object instanceof XmlSchemaInclude) {
1174: XmlSchema schema1 = ((XmlSchemaInclude) object)
1175: .getSchema();
1176: xmlSchemaAttributeGroup = (XmlSchemaAttributeGroup) schema1
1177: .getAttributeGroups().getItem(
1178: attributeGroupQName);
1179: }
1180: if (xmlSchemaAttributeGroup != null) {
1181: break;
1182: }
1183: }
1184: }
1185: }
1186: }
1187: return xmlSchemaAttributeGroup;
1188: }
1189:
1190: /**
1191: * Process the content models. A content model is either simple type or a complex type
1192: * and included inside a complex content
1193: */
1194: private void processContentModel(XmlSchemaContentModel content,
1195: BeanWriterMetaInfoHolder metaInfHolder,
1196: XmlSchema parentSchema) throws SchemaCompilationException {
1197: if (content instanceof XmlSchemaComplexContent) {
1198: processComplexContent((XmlSchemaComplexContent) content,
1199: metaInfHolder, parentSchema);
1200: } else if (content instanceof XmlSchemaSimpleContent) {
1201: processSimpleContent((XmlSchemaSimpleContent) content,
1202: metaInfHolder, parentSchema);
1203: }
1204: }
1205:
1206: /**
1207: * Prcess the complex content
1208: */
1209: private void processComplexContent(
1210: XmlSchemaComplexContent complexContent,
1211: BeanWriterMetaInfoHolder metaInfHolder,
1212: XmlSchema parentSchema) throws SchemaCompilationException {
1213: XmlSchemaContent content = complexContent.getContent();
1214:
1215: if (content instanceof XmlSchemaComplexContentExtension) {
1216:
1217: // to handle extension we need to attach the extended items to the base type
1218: // and create a new type
1219: XmlSchemaComplexContentExtension extension = (XmlSchemaComplexContentExtension) content;
1220:
1221: //process the base type if it has not been processed yet
1222: if (!isAlreadyProcessed(extension.getBaseTypeName())) {
1223: //pick the relevant basetype from the schema and process it
1224: XmlSchemaType type = getType(parentSchema, extension
1225: .getBaseTypeName());
1226: if (type instanceof XmlSchemaComplexType) {
1227: XmlSchemaComplexType complexType = (XmlSchemaComplexType) type;
1228: if (complexType.getName() != null) {
1229: processNamedComplexSchemaType(complexType,
1230: parentSchema);
1231: } else {
1232: //this is not possible. The extension should always
1233: //have a name
1234: throw new SchemaCompilationException(
1235: "Unnamed complex type used in extension");//Internationlize this
1236: }
1237: } else if (type instanceof XmlSchemaSimpleType) {
1238: //process simple type
1239: processSimpleSchemaType((XmlSchemaSimpleType) type,
1240: null, parentSchema, null);
1241: }
1242: }
1243:
1244: // before actually processing this node, we need to recurse through the base types and add their
1245: // children (sometimes even preserving the order) to the metainfo holder of this type
1246: // the reason is that for extensions, the prefered way is to have the sequences of the base class
1247: //* before * the sequence of the child element.
1248: copyMetaInfoHierarchy(metaInfHolder, extension
1249: .getBaseTypeName(), parentSchema);
1250:
1251: //process the particle of this node
1252: if (extension.getParticle() != null) {
1253: processParticle(extension.getBaseTypeName(), extension
1254: .getParticle(), metaInfHolder, parentSchema);
1255: }
1256:
1257: // process attributes
1258: //process attributes - first look for the explicit attributes
1259: XmlSchemaObjectCollection attribs = extension
1260: .getAttributes();
1261: Iterator attribIterator = attribs.getIterator();
1262: while (attribIterator.hasNext()) {
1263: Object o = attribIterator.next();
1264: if (o instanceof XmlSchemaAttribute) {
1265: processAttribute((XmlSchemaAttribute) o,
1266: metaInfHolder, parentSchema);
1267:
1268: }
1269: }
1270:
1271: //process any attribute
1272: //somehow the xml schema parser does not seem to pickup the any attribute!!
1273: XmlSchemaAnyAttribute anyAtt = extension.getAnyAttribute();
1274: if (anyAtt != null) {
1275: processAnyAttribute(metaInfHolder, anyAtt);
1276: }
1277: String className = findClassName(extension
1278: .getBaseTypeName(), false);
1279:
1280: if (!writer.getDefaultClassName().equals(className)) {
1281: //the particle has been processed, However since this is an extension we need to
1282: //add the basetype as an extension to the complex type class.
1283: // The basetype has been processed already
1284: metaInfHolder.setExtension(true);
1285: metaInfHolder.setExtensionClassName(className);
1286: //Note - this is no array! so the array boolean is false
1287: }
1288: } else if (content instanceof XmlSchemaComplexContentRestriction) {
1289: XmlSchemaComplexContentRestriction restriction = (XmlSchemaComplexContentRestriction) content;
1290:
1291: //process the base type if it has not been processed yet
1292: if (!isAlreadyProcessed(restriction.getBaseTypeName())) {
1293: //pick the relevant basetype from the schema and process it
1294: XmlSchemaType type = getType(parentSchema, restriction
1295: .getBaseTypeName());
1296: if (type instanceof XmlSchemaComplexType) {
1297: XmlSchemaComplexType complexType = (XmlSchemaComplexType) type;
1298: if (complexType.getName() != null) {
1299: processNamedComplexSchemaType(complexType,
1300: parentSchema);
1301: } else {
1302: //this is not possible. The restriction should always
1303: //have a name
1304: throw new SchemaCompilationException(
1305: "Unnamed complex type used in restriction");//Internationlize this
1306: }
1307: } else if (type instanceof XmlSchemaSimpleType) {
1308:
1309: throw new SchemaCompilationException(
1310: "Not a valid restriction, complex content restriction base type cannot be a simple type.");
1311: }
1312: }
1313:
1314: copyMetaInfoHierarchy(metaInfHolder, restriction
1315: .getBaseTypeName(), parentSchema);
1316:
1317: //process the particle of this node
1318: processParticle(restriction.getBaseTypeName(), restriction
1319: .getParticle(), metaInfHolder, parentSchema);
1320:
1321: //process attributes - first look for the explicit attributes
1322: XmlSchemaObjectCollection attribs = restriction
1323: .getAttributes();
1324: Iterator attribIterator = attribs.getIterator();
1325: while (attribIterator.hasNext()) {
1326: Object o = attribIterator.next();
1327: if (o instanceof XmlSchemaAttribute) {
1328: processAttribute((XmlSchemaAttribute) o,
1329: metaInfHolder, parentSchema);
1330:
1331: }
1332: }
1333:
1334: //process any attribute
1335: //somehow the xml schema parser does not seem to pickup the any attribute!!
1336: XmlSchemaAnyAttribute anyAtt = restriction
1337: .getAnyAttribute();
1338: if (anyAtt != null) {
1339: processAnyAttribute(metaInfHolder, anyAtt);
1340: }
1341: String className = findClassName(restriction
1342: .getBaseTypeName(), false);
1343:
1344: if (!writer.getDefaultClassName().equals(className)) {
1345: metaInfHolder.setRestriction(true);
1346: metaInfHolder.setRestrictionClassName(findClassName(
1347: restriction.getBaseTypeName(), false));
1348: //Note - this is no array! so the array boolean is false
1349: }
1350: }
1351: }
1352:
1353: /**
1354: * Recursive method to populate the metainfo holders with info from the base types
1355: *
1356: * @param metaInfHolder
1357: * @param baseTypeName
1358: * @param parentSchema
1359: */
1360: private void copyMetaInfoHierarchy(
1361: BeanWriterMetaInfoHolder metaInfHolder, QName baseTypeName,
1362: XmlSchema parentSchema) throws SchemaCompilationException {
1363:
1364: XmlSchemaType type;
1365: type = parentSchema.getTypeByName(baseTypeName);
1366: if (type == null) {
1367: type = getType(parentSchema, baseTypeName);
1368: }
1369:
1370: BeanWriterMetaInfoHolder baseMetaInfoHolder = (BeanWriterMetaInfoHolder) processedTypeMetaInfoMap
1371: .get(baseTypeName);
1372:
1373: if (baseMetaInfoHolder != null) {
1374:
1375: // see whether this type is also extended from some other type first
1376: // if so proceed to set their parents as well.
1377: if (type instanceof XmlSchemaComplexType) {
1378: XmlSchemaComplexType complexType = (XmlSchemaComplexType) type;
1379: if (complexType.getContentModel() != null) {
1380: XmlSchemaContentModel content = complexType
1381: .getContentModel();
1382: if (content instanceof XmlSchemaComplexContent) {
1383: XmlSchemaComplexContent complexContent = (XmlSchemaComplexContent) content;
1384: if (complexContent.getContent() instanceof XmlSchemaComplexContentExtension) {
1385: XmlSchemaComplexContentExtension extension = (XmlSchemaComplexContentExtension) complexContent
1386: .getContent();
1387: //recursively call the copyMetaInfoHierarchy method
1388: copyMetaInfoHierarchy(baseMetaInfoHolder,
1389: extension.getBaseTypeName(),
1390: parentSchema);
1391:
1392: } else if (complexContent.getContent() instanceof XmlSchemaComplexContentRestriction) {
1393:
1394: XmlSchemaComplexContentRestriction restriction = (XmlSchemaComplexContentRestriction) complexContent
1395: .getContent();
1396: //recursively call the copyMetaInfoHierarchy method
1397: copyMetaInfoHierarchy(baseMetaInfoHolder,
1398: restriction.getBaseTypeName(),
1399: parentSchema);
1400:
1401: } else {
1402: throw new SchemaCompilationException(
1403: SchemaCompilerMessages
1404: .getMessage("schema.unknowncontenterror"));
1405: }
1406:
1407: } else if (content instanceof XmlSchemaSimpleContent) {
1408: throw new SchemaCompilationException(
1409: SchemaCompilerMessages
1410: .getMessage(
1411: "schema.unsupportedcontenterror",
1412: "Simple Content"));
1413: } else {
1414: throw new SchemaCompilationException(
1415: SchemaCompilerMessages
1416: .getMessage("schema.unknowncontenterror"));
1417: }
1418: }
1419: //Do the actual parent setting
1420: metaInfHolder.setAsParent(baseMetaInfoHolder);
1421:
1422: } else if (type instanceof XmlSchemaSimpleType) {
1423:
1424: // we have to copy the uion data if the parent simple type restriction
1425: // is an union
1426: // this union attribute is copied from the child to parent to genrate the parent
1427: // code as union
1428: if (baseMetaInfoHolder.isUnion()) {
1429: metaInfHolder.setUnion(true);
1430: Map memberTypes = baseMetaInfoHolder
1431: .getMemberTypes();
1432: Object qname;
1433: for (Iterator iter = memberTypes.keySet()
1434: .iterator(); iter.hasNext();) {
1435: qname = iter.next();
1436: metaInfHolder.addMemberType((QName) qname,
1437: (String) memberTypes.get(qname));
1438: }
1439: }
1440:
1441: // we have to copy the list type data to parent if it is a list
1442: if (baseMetaInfoHolder.isList()) {
1443: metaInfHolder.setList(true);
1444: metaInfHolder.setItemTypeQName(baseMetaInfoHolder
1445: .getItemTypeQName());
1446: metaInfHolder
1447: .setItemTypeClassName(baseMetaInfoHolder
1448: .getItemTypeClassName());
1449: }
1450: metaInfHolder.setAsParent(baseMetaInfoHolder);
1451: }
1452:
1453: }
1454: }
1455:
1456: /**
1457: * @param simpleContent
1458: * @param metaInfHolder
1459: * @throws SchemaCompilationException
1460: */
1461: private void processSimpleContent(
1462: XmlSchemaSimpleContent simpleContent,
1463: BeanWriterMetaInfoHolder metaInfHolder,
1464: XmlSchema parentSchema) throws SchemaCompilationException {
1465: XmlSchemaContent content;
1466: content = simpleContent.getContent();
1467: if (content instanceof XmlSchemaSimpleContentExtension) {
1468: XmlSchemaSimpleContentExtension extension = (XmlSchemaSimpleContentExtension) content;
1469:
1470: //process the base type if it has not been processed yet
1471: if (!isAlreadyProcessed(extension.getBaseTypeName())) {
1472: //pick the relevant basetype from the schema and process it
1473: XmlSchemaType type = getType(parentSchema, extension
1474: .getBaseTypeName());
1475: if (type instanceof XmlSchemaComplexType) {
1476: XmlSchemaComplexType complexType = (XmlSchemaComplexType) type;
1477: if (complexType.getName() != null) {
1478: processNamedComplexSchemaType(complexType,
1479: parentSchema);
1480: } else {
1481: //this is not possible. The extension should always
1482: //have a name
1483: throw new SchemaCompilationException(
1484: "Unnamed complex type used in extension");//Internationlize this
1485: }
1486: } else if (type instanceof XmlSchemaSimpleType) {
1487: //process simple type
1488: processSimpleSchemaType((XmlSchemaSimpleType) type,
1489: null, parentSchema, null);
1490: }
1491: }
1492:
1493: //process extension base type
1494: processSimpleExtensionBaseType(extension.getBaseTypeName(),
1495: metaInfHolder, parentSchema);
1496:
1497: //process attributes
1498: XmlSchemaObjectCollection attribs = extension
1499: .getAttributes();
1500: Iterator attribIterator = attribs.getIterator();
1501: while (attribIterator.hasNext()) {
1502: Object attr = attribIterator.next();
1503: if (attr instanceof XmlSchemaAttribute) {
1504: processAttribute((XmlSchemaAttribute) attr,
1505: metaInfHolder, parentSchema);
1506:
1507: }
1508: }
1509:
1510: //process any attribute
1511: XmlSchemaAnyAttribute anyAtt = extension.getAnyAttribute();
1512: if (anyAtt != null) {
1513: processAnyAttribute(metaInfHolder, anyAtt);
1514: }
1515:
1516: } else if (content instanceof XmlSchemaSimpleContentRestriction) {
1517: XmlSchemaSimpleContentRestriction restriction = (XmlSchemaSimpleContentRestriction) content;
1518:
1519: //process the base type if it has not been processed yet
1520: if (!isAlreadyProcessed(restriction.getBaseTypeName())) {
1521: //pick the relevant basetype from the schema and process it
1522: XmlSchemaType type = getType(parentSchema, restriction
1523: .getBaseTypeName());
1524: if (type instanceof XmlSchemaComplexType) {
1525: XmlSchemaComplexType complexType = (XmlSchemaComplexType) type;
1526: if (complexType.getName() != null) {
1527: processNamedComplexSchemaType(complexType,
1528: parentSchema);
1529: } else {
1530: //this is not possible. The extension should always
1531: //have a name
1532: throw new SchemaCompilationException(
1533: "Unnamed complex type used in restriction");//Internationlize this
1534: }
1535: } else if (type instanceof XmlSchemaSimpleType) {
1536: //process simple type
1537: processSimpleSchemaType((XmlSchemaSimpleType) type,
1538: null, parentSchema, null);
1539: }
1540: }
1541: //process restriction base type
1542: processSimpleRestrictionBaseType(restriction
1543: .getBaseTypeName(), restriction.getBaseTypeName(),
1544: metaInfHolder, parentSchema);
1545: metaInfHolder.setSimple(true);
1546: }
1547: }
1548:
1549: /**
1550: * Process Simple Extension Base Type.
1551: *
1552: * @param extBaseType
1553: * @param metaInfHolder
1554: */
1555: public void processSimpleExtensionBaseType(QName extBaseType,
1556: BeanWriterMetaInfoHolder metaInfHolder,
1557: XmlSchema parentSchema) throws SchemaCompilationException {
1558:
1559: //find the class name
1560: String className = findClassName(extBaseType, false);
1561:
1562: // if the base type is an primitive then we do not have to extend them
1563: // and it is considered as a property
1564: // on the otherhand if the base type is an generated class then we have to
1565: // extend from it
1566:
1567: if (baseSchemaTypeMap.containsKey(extBaseType)) {
1568: //this means the schema type actually returns a different QName
1569: if (changedTypeMap.containsKey(extBaseType)) {
1570: metaInfHolder.registerMapping(extBaseType,
1571: (QName) changedTypeMap.get(extBaseType),
1572: className, SchemaConstants.ELEMENT_TYPE);
1573: } else {
1574: metaInfHolder.registerMapping(extBaseType, extBaseType,
1575: className, SchemaConstants.ELEMENT_TYPE);
1576: }
1577: metaInfHolder.setSimple(true);
1578: // we have already process when it comes to this place
1579: } else if (processedTypemap.containsKey(extBaseType)) {
1580: //set the extension base class name
1581:
1582: XmlSchemaType type = getType(parentSchema, extBaseType);
1583: if (type instanceof XmlSchemaSimpleType) {
1584: metaInfHolder.setSimple(true);
1585: metaInfHolder.setExtension(true);
1586: metaInfHolder.setExtensionClassName(className);
1587:
1588: copyMetaInfoHierarchy(metaInfHolder, extBaseType,
1589: parentSchema);
1590: } else if (type instanceof XmlSchemaComplexType) {
1591: XmlSchemaComplexType complexType = (XmlSchemaComplexType) type;
1592: if (complexType.getContentModel() == null) {
1593: // do not set as a simple type since we want to
1594: // print the element names
1595: metaInfHolder.setExtension(true);
1596: metaInfHolder.setExtensionClassName(className);
1597: copyMetaInfoHierarchy(metaInfHolder, extBaseType,
1598: parentSchema);
1599: }
1600:
1601: }
1602: } else {
1603: metaInfHolder.setSimple(true);
1604: }
1605:
1606: //get the binary state and add that to the status map
1607: if (isBinary(extBaseType)) {
1608: metaInfHolder.addtStatus(extBaseType,
1609: SchemaConstants.BINARY_TYPE);
1610: }
1611: }
1612:
1613: /**
1614: * Process Simple Restriction Base Type.
1615: *
1616: * @param resBaseType
1617: * @param metaInfHolder
1618: */
1619: public void processSimpleRestrictionBaseType(QName qName,
1620: QName resBaseType, BeanWriterMetaInfoHolder metaInfHolder,
1621: XmlSchema parentSchema) throws SchemaCompilationException {
1622:
1623: //find the class name
1624: String className = findClassName(resBaseType, false);
1625:
1626: //this means the schema type actually returns a different QName
1627: if (baseSchemaTypeMap.containsKey(resBaseType)) {
1628: if (changedTypeMap.containsKey(resBaseType)) {
1629: metaInfHolder.registerMapping(qName,
1630: (QName) changedTypeMap.get(resBaseType),
1631: className, SchemaConstants.ELEMENT_TYPE);
1632: } else {
1633: metaInfHolder.registerMapping(qName, resBaseType,
1634: className, SchemaConstants.ELEMENT_TYPE);
1635: }
1636: } else if (processedTypemap.containsKey(resBaseType)) {
1637: //this is not a standared type
1638: // so the parent class must extend it
1639: metaInfHolder.setSimple(true);
1640: metaInfHolder.setRestriction(true);
1641: metaInfHolder.setRestrictionClassName(className);
1642: copyMetaInfoHierarchy(metaInfHolder, resBaseType,
1643: parentSchema);
1644: }
1645:
1646: metaInfHolder.setRestrictionBaseType(resBaseType);
1647:
1648: }
1649:
1650: /**
1651: * Process Facets.
1652: *
1653: * @param metaInfHolder
1654: */
1655: private void processFacets(
1656: XmlSchemaSimpleTypeRestriction restriction,
1657: BeanWriterMetaInfoHolder metaInfHolder,
1658: XmlSchema parentSchema) {
1659:
1660: XmlSchemaObjectCollection facets = restriction.getFacets();
1661: Iterator facetIterator = facets.getIterator();
1662:
1663: while (facetIterator.hasNext()) {
1664: Object obj = facetIterator.next();
1665:
1666: if (obj instanceof XmlSchemaPatternFacet) {
1667: XmlSchemaPatternFacet pattern = (XmlSchemaPatternFacet) obj;
1668: // some patterns contain \ so we have to replace them
1669: String patternString = pattern.getValue().toString();
1670: metaInfHolder.setPatternFacet(patternString.replaceAll(
1671: "\\\\", "\\\\\\\\"));
1672: }
1673:
1674: else if (obj instanceof XmlSchemaEnumerationFacet) {
1675: XmlSchemaEnumerationFacet enumeration = (XmlSchemaEnumerationFacet) obj;
1676: if (restriction.getBaseTypeName().equals(
1677: SchemaConstants.XSD_QNAME)) {
1678: // we have to process the qname here and shoud find the local part and namespace uri
1679: String value = enumeration.getValue().toString();
1680: String prefix = value.substring(0, value
1681: .indexOf(":"));
1682: String localPart = value.substring(value
1683: .indexOf(":") + 1);
1684:
1685: String namespaceUri = parentSchema
1686: .getNamespaceContext().getNamespaceURI(
1687: prefix);
1688: // set the string to suite for the convertQname method
1689: String qNameString = value + "\", \""
1690: + namespaceUri;
1691: metaInfHolder.addEnumFacet(qNameString);
1692: } else {
1693: metaInfHolder.addEnumFacet(enumeration.getValue()
1694: .toString());
1695: }
1696:
1697: }
1698:
1699: else if (obj instanceof XmlSchemaLengthFacet) {
1700: XmlSchemaLengthFacet length = (XmlSchemaLengthFacet) obj;
1701: metaInfHolder.setLengthFacet(Integer.parseInt(length
1702: .getValue().toString()));
1703: }
1704:
1705: else if (obj instanceof XmlSchemaMaxExclusiveFacet) {
1706: XmlSchemaMaxExclusiveFacet maxEx = (XmlSchemaMaxExclusiveFacet) obj;
1707: metaInfHolder.setMaxExclusiveFacet(maxEx.getValue()
1708: .toString());
1709: }
1710:
1711: else if (obj instanceof XmlSchemaMinExclusiveFacet) {
1712: XmlSchemaMinExclusiveFacet minEx = (XmlSchemaMinExclusiveFacet) obj;
1713: metaInfHolder.setMinExclusiveFacet(minEx.getValue()
1714: .toString());
1715: }
1716:
1717: else if (obj instanceof XmlSchemaMaxInclusiveFacet) {
1718: XmlSchemaMaxInclusiveFacet maxIn = (XmlSchemaMaxInclusiveFacet) obj;
1719: metaInfHolder.setMaxInclusiveFacet(maxIn.getValue()
1720: .toString());
1721: }
1722:
1723: else if (obj instanceof XmlSchemaMinInclusiveFacet) {
1724: XmlSchemaMinInclusiveFacet minIn = (XmlSchemaMinInclusiveFacet) obj;
1725: metaInfHolder.setMinInclusiveFacet(minIn.getValue()
1726: .toString());
1727: }
1728:
1729: else if (obj instanceof XmlSchemaMaxLengthFacet) {
1730: XmlSchemaMaxLengthFacet maxLen = (XmlSchemaMaxLengthFacet) obj;
1731: metaInfHolder.setMaxLengthFacet(Integer.parseInt(maxLen
1732: .getValue().toString()));
1733: }
1734:
1735: else if (obj instanceof XmlSchemaMinLengthFacet) {
1736: XmlSchemaMinLengthFacet minLen = (XmlSchemaMinLengthFacet) obj;
1737: metaInfHolder.setMinLengthFacet(Integer.parseInt(minLen
1738: .getValue().toString()));
1739: }
1740: }
1741: }
1742:
1743: /**
1744: * Handle any attribute
1745: *
1746: * @param metainf
1747: */
1748: private void processAnyAttribute(BeanWriterMetaInfoHolder metainf,
1749: XmlSchemaAnyAttribute anyAtt) {
1750:
1751: //The best thing we can do here is to add a set of OMAttributes
1752: //since attributes do not have the notion of minoccurs/maxoccurs the
1753: //safest option here is to have an OMAttribute array
1754: QName qName = new QName(EXTRA_ATTRIBUTE_FIELD_NAME);
1755: metainf.registerMapping(qName, null, writer
1756: .getDefaultAttribArrayClassName(),//always generate an array of
1757: //OMAttributes
1758: SchemaConstants.ANY_TYPE);
1759: metainf.addtStatus(qName, SchemaConstants.ATTRIBUTE_TYPE);
1760: metainf.addtStatus(qName, SchemaConstants.ARRAY_TYPE);
1761:
1762: }
1763:
1764: /**
1765: * Process the attribute
1766: *
1767: * @param att
1768: * @param metainf
1769: */
1770: public void processAttribute(XmlSchemaAttribute att,
1771: BeanWriterMetaInfoHolder metainf, XmlSchema parentSchema)
1772: throws SchemaCompilationException {
1773:
1774: QName schemaTypeName = att.getSchemaTypeName();
1775: if (schemaTypeName != null) {
1776: if (att.getQName() != null) {
1777: if (baseSchemaTypeMap.containsKey(schemaTypeName)) {
1778:
1779: metainf.registerMapping(att.getQName(),
1780: schemaTypeName, baseSchemaTypeMap.get(
1781: schemaTypeName).toString(),
1782: SchemaConstants.ATTRIBUTE_TYPE);
1783:
1784: // add optional attribute status if set
1785: String use = att.getUse().getValue();
1786: if (USE_NONE.equals(use)
1787: || USE_OPTIONAL.equals(use)) {
1788: metainf.addtStatus(att.getQName(),
1789: SchemaConstants.OPTIONAL_TYPE);
1790: }
1791:
1792: String className = findClassName(schemaTypeName,
1793: false);
1794:
1795: att
1796: .addMetaInfo(
1797: SchemaConstants.SchemaCompilerInfoHolder.CLASSNAME_KEY,
1798: className);
1799: // after
1800: } else {
1801: XmlSchemaType type = getType(parentSchema,
1802: schemaTypeName);
1803: if (type instanceof XmlSchemaSimpleType) {
1804: XmlSchemaSimpleType simpleType = (XmlSchemaSimpleType) type;
1805:
1806: if ((simpleType != null)
1807: && (simpleType.getContent() instanceof XmlSchemaSimpleTypeRestriction)) {
1808: // we only support simple type restriction
1809: if (!isAlreadyProcessed(schemaTypeName)) {
1810: //process simple type
1811: processSimpleSchemaType(simpleType,
1812: null, parentSchema, null);
1813: }
1814: metainf.registerMapping(att.getQName(),
1815: schemaTypeName, processedTypemap
1816: .get(schemaTypeName)
1817: .toString(),
1818: SchemaConstants.ATTRIBUTE_TYPE);
1819: // add optional attribute status if set
1820: String use = att.getUse().getValue();
1821: if (USE_NONE.equals(use)
1822: || USE_OPTIONAL.equals(use)) {
1823: metainf.addtStatus(att.getQName(),
1824: SchemaConstants.OPTIONAL_TYPE);
1825: }
1826: }
1827:
1828: }
1829: }
1830: } else {
1831: // this attribute has a type but does not have a name, seems to be invalid
1832: }
1833:
1834: } else if (att.getRefName() != null) {
1835: XmlSchema currentParentSchema = resolveParentSchema(att
1836: .getRefName(), parentSchema);
1837: XmlSchemaAttribute xmlSchemaAttribute = getXmlSchemaAttribute(
1838: att.getRefName(), currentParentSchema);
1839:
1840: if (xmlSchemaAttribute != null) {
1841: // call recursively to process the schema
1842: processAttribute(xmlSchemaAttribute, metainf,
1843: currentParentSchema);
1844: } else {
1845: throw new SchemaCompilationException(
1846: "Attribute QName reference refer to an invalid attribute "
1847: + att.getRefName());
1848: }
1849:
1850: } else {
1851: // this attribute refers to a custom type, probably one of the extended simple types.
1852: // with the inline scheam definition
1853: QName attributeQName = att.getQName();
1854: if (attributeQName != null) {
1855: XmlSchemaSimpleType attributeSimpleType = att
1856: .getSchemaType();
1857: if (attributeSimpleType == null) {
1858: // try to get the schema for using qname
1859: QName attributeSchemaQname = att
1860: .getSchemaTypeName();
1861: if (attributeSchemaQname != null) {
1862: attributeSimpleType = (XmlSchemaSimpleType) getType(
1863: parentSchema, attributeSchemaQname);
1864: }
1865: }
1866:
1867: if (attributeSimpleType != null) {
1868: QName schemaTypeQName = att.getSchemaTypeName();
1869: if (schemaTypeQName == null) {
1870: // set the parent schema target name space since attribute Qname uri is ""
1871: if (attributeSimpleType.getQName() != null) {
1872: schemaTypeQName = attributeSimpleType
1873: .getQName();
1874: } else {
1875: schemaTypeQName = new QName(
1876: parentSchema.getTargetNamespace(),
1877: attributeQName.getLocalPart()
1878: + getNextTypeSuffix(attributeQName
1879: .getLocalPart()));
1880:
1881: }
1882: }
1883: if (!isAlreadyProcessed(schemaTypeQName)) {
1884: // we have to process only if it has not processed
1885: processSimpleSchemaType(attributeSimpleType,
1886: null, parentSchema, schemaTypeQName);
1887: }
1888: metainf.registerMapping(att.getQName(),
1889: schemaTypeQName, processedTypemap.get(
1890: schemaTypeQName).toString(),
1891: SchemaConstants.ATTRIBUTE_TYPE);
1892: // add optional attribute status if set
1893: String use = att.getUse().getValue();
1894: if (USE_NONE.equals(use)
1895: || USE_OPTIONAL.equals(use)) {
1896: metainf.addtStatus(att.getQName(),
1897: SchemaConstants.OPTIONAL_TYPE);
1898: }
1899: } else {
1900: // TODO: handle the case when no attribute type specifed
1901: log
1902: .warn("No attribute type has defined to the Attribute "
1903: + attributeQName);
1904: }
1905:
1906: } else {
1907: throw new SchemaCompilationException(
1908: "Attribute QName reference refer to an invalid attribute "
1909: + attributeQName);
1910: }
1911:
1912: }
1913: }
1914:
1915: private XmlSchemaAttribute getXmlSchemaAttribute(
1916: QName attributeQName, XmlSchema parentSchema) {
1917: XmlSchemaAttribute xmlSchemaAttribute = (XmlSchemaAttribute) parentSchema
1918: .getAttributes().getItem(attributeQName);
1919: if (xmlSchemaAttribute == null) {
1920: // i.e this attribute can be in a included or imported schema
1921: xmlSchemaAttribute = (XmlSchemaAttribute) parentSchema
1922: .getAttributes().getItem(attributeQName);
1923: if (xmlSchemaAttribute == null) {
1924: // try to find in an import or an include
1925: XmlSchemaObjectCollection includes = parentSchema
1926: .getIncludes();
1927: if (includes != null) {
1928: Iterator includesIter = includes.getIterator();
1929: Object object = null;
1930: while (includesIter.hasNext()) {
1931: object = includesIter.next();
1932: if (object instanceof XmlSchemaImport) {
1933: XmlSchema schema1 = ((XmlSchemaImport) object)
1934: .getSchema();
1935: xmlSchemaAttribute = (XmlSchemaAttribute) schema1
1936: .getAttributes().getItem(
1937: attributeQName);
1938: }
1939: if (object instanceof XmlSchemaInclude) {
1940: XmlSchema schema1 = ((XmlSchemaInclude) object)
1941: .getSchema();
1942: xmlSchemaAttribute = (XmlSchemaAttribute) schema1
1943: .getAttributes().getItem(
1944: attributeQName);
1945: }
1946: if (xmlSchemaAttribute != null) {
1947: break;
1948: }
1949: }
1950: }
1951: }
1952: }
1953: return xmlSchemaAttribute;
1954: }
1955:
1956: /**
1957: * Process a particle- A particle may be a sequence,all or a choice
1958: * @param parentElementQName - this can either be parent element QName or parent Complex type qname
1959: * @param particle - particle being processed
1960: * @param metainfHolder -
1961: * @param parentSchema
1962: * @throws SchemaCompilationException
1963: */
1964: private void processParticle(QName parentElementQName,
1965: XmlSchemaParticle particle,
1966: BeanWriterMetaInfoHolder metainfHolder,
1967: XmlSchema parentSchema) throws SchemaCompilationException {
1968:
1969: if (particle instanceof XmlSchemaSequence) {
1970: XmlSchemaSequence xmlSchemaSequence = (XmlSchemaSequence) particle;
1971:
1972: XmlSchemaObjectCollection items = xmlSchemaSequence
1973: .getItems();
1974: //TODO: support parentElementQName null instances. i.e for extensions
1975: if ((xmlSchemaSequence.getMaxOccurs() > 1)
1976: && (parentElementQName != null)) {
1977: // we have to process many sequence types
1978: BeanWriterMetaInfoHolder beanWriterMetaInfoHolder = new BeanWriterMetaInfoHolder();
1979: process(parentElementQName, items,
1980: beanWriterMetaInfoHolder, true, parentSchema);
1981: beanWriterMetaInfoHolder.setParticleClass(true);
1982: QName sequenceQName = new QName(parentElementQName
1983: .getNamespaceURI(), parentElementQName
1984: .getLocalPart()
1985: + "Sequence");
1986: String javaClassName = writeComplexParticle(
1987: sequenceQName, beanWriterMetaInfoHolder);
1988: processedTypemap.put(sequenceQName, javaClassName);
1989:
1990: // add this as an array to the original class
1991: metainfHolder.registerMapping(sequenceQName,
1992: sequenceQName, findClassName(sequenceQName,
1993: true), SchemaConstants.ARRAY_TYPE);
1994: metainfHolder.setOrdered(true);
1995: metainfHolder.registerQNameIndex(sequenceQName,
1996: metainfHolder.getOrderStartPoint() + 1);
1997: metainfHolder.setHasParticleType(true);
1998: metainfHolder.addtStatus(sequenceQName,
1999: SchemaConstants.PARTICLE_TYPE_ELEMENT);
2000: metainfHolder.addMaxOccurs(sequenceQName,
2001: xmlSchemaSequence.getMaxOccurs());
2002: metainfHolder.addMinOccurs(sequenceQName,
2003: xmlSchemaSequence.getMinOccurs());
2004:
2005: } else {
2006: if (options.isBackwordCompatibilityMode()) {
2007: process(parentElementQName, items, metainfHolder,
2008: false, parentSchema);
2009: } else {
2010: process(parentElementQName, items, metainfHolder,
2011: true, parentSchema);
2012: }
2013: }
2014:
2015: } else if (particle instanceof XmlSchemaAll) {
2016: XmlSchemaObjectCollection items = ((XmlSchemaAll) particle)
2017: .getItems();
2018: process(parentElementQName, items, metainfHolder, false,
2019: parentSchema);
2020: } else if (particle instanceof XmlSchemaChoice) {
2021: XmlSchemaChoice xmlSchemaChoice = (XmlSchemaChoice) particle;
2022: XmlSchemaObjectCollection items = ((XmlSchemaChoice) particle)
2023: .getItems();
2024:
2025: if ((xmlSchemaChoice.getMaxOccurs() > 1)) {
2026: // we have to process many sequence types
2027: BeanWriterMetaInfoHolder beanWriterMetaInfoHolder = new BeanWriterMetaInfoHolder();
2028: beanWriterMetaInfoHolder.setChoice(true);
2029: process(parentElementQName, items,
2030: beanWriterMetaInfoHolder, false, parentSchema);
2031: beanWriterMetaInfoHolder.setParticleClass(true);
2032: QName choiceQName = new QName(parentElementQName
2033: .getNamespaceURI(), parentElementQName
2034: .getLocalPart()
2035: + "Choice");
2036: String javaClassName = writeComplexParticle(
2037: choiceQName, beanWriterMetaInfoHolder);
2038: processedTypemap.put(choiceQName, javaClassName);
2039:
2040: // add this as an array to the original class
2041: metainfHolder.registerMapping(choiceQName, choiceQName,
2042: findClassName(choiceQName, true),
2043: SchemaConstants.ARRAY_TYPE);
2044: metainfHolder.setOrdered(true);
2045: metainfHolder.setHasParticleType(true);
2046: metainfHolder.registerQNameIndex(choiceQName,
2047: metainfHolder.getOrderStartPoint() + 1);
2048: metainfHolder.addtStatus(choiceQName,
2049: SchemaConstants.PARTICLE_TYPE_ELEMENT);
2050: metainfHolder.addMaxOccurs(choiceQName, xmlSchemaChoice
2051: .getMaxOccurs());
2052: metainfHolder.addMinOccurs(choiceQName, xmlSchemaChoice
2053: .getMinOccurs());
2054:
2055: } else {
2056: metainfHolder.setChoice(true);
2057: process(parentElementQName, items, metainfHolder,
2058: false, parentSchema);
2059: }
2060:
2061: } else if (particle instanceof XmlSchemaGroupRef) {
2062:
2063: XmlSchemaGroupRef xmlSchemaGroupRef = (XmlSchemaGroupRef) particle;
2064: QName groupQName = xmlSchemaGroupRef.getRefName();
2065: if (groupQName != null) {
2066: if (!processedTypemap.containsKey(groupQName)) {
2067: // processe the schema here
2068: XmlSchema resolvedParentSchema = resolveParentSchema(
2069: groupQName, parentSchema);
2070: XmlSchemaGroup xmlSchemaGroup = getGroup(
2071: groupQName, resolvedParentSchema);
2072: if (xmlSchemaGroup != null) {
2073: processGroup(xmlSchemaGroup, groupQName,
2074: parentSchema);
2075: } else {
2076: throw new SchemaCompilationException(
2077: "Refered Group "
2078: + groupQName.getLocalPart()
2079: + " can not be found ");
2080: }
2081: }
2082: } else {
2083: throw new SchemaCompilationException(
2084: "Referenced name is null");
2085: }
2086: boolean isArray = xmlSchemaGroupRef.getMaxOccurs() > 1;
2087:
2088: // add this as an array to the original class
2089: metainfHolder.registerMapping(groupQName, groupQName,
2090: findClassName(groupQName, isArray));
2091: if (isArray) {
2092: metainfHolder.addtStatus(groupQName,
2093: SchemaConstants.ARRAY_TYPE);
2094: }
2095: metainfHolder.addtStatus(groupQName,
2096: SchemaConstants.PARTICLE_TYPE_ELEMENT);
2097: metainfHolder.addMaxOccurs(groupQName, xmlSchemaGroupRef
2098: .getMaxOccurs());
2099: metainfHolder.addMinOccurs(groupQName, xmlSchemaGroupRef
2100: .getMinOccurs());
2101: metainfHolder.setHasParticleType(true);
2102: metainfHolder.setOrdered(true);
2103: metainfHolder.registerQNameIndex(groupQName, metainfHolder
2104: .getOrderStartPoint() + 1);
2105:
2106: }
2107: }
2108:
2109: /**
2110: *
2111: * @param parentElementQName - this could either be the complex type parentElementQName or element parentElementQName
2112: * @param items
2113: * @param metainfHolder
2114: * @param order
2115: * @param parentSchema
2116: * @throws SchemaCompilationException
2117: */
2118: private void process(QName parentElementQName,
2119: XmlSchemaObjectCollection items,
2120: BeanWriterMetaInfoHolder metainfHolder, boolean order,
2121: XmlSchema parentSchema) throws SchemaCompilationException {
2122: int count = items.getCount();
2123: Map processedElementArrayStatusMap = new LinkedHashMap();
2124: Map processedElementTypeMap = new LinkedHashMap();
2125: List localNillableList = new ArrayList();
2126:
2127: Map particleQNameMap = new HashMap();
2128:
2129: // this list is used to keep the details of the
2130: // elements within a choice withing sequence
2131: List innerChoiceElementList = new ArrayList();
2132:
2133: Map elementOrderMap = new HashMap();
2134:
2135: int sequenceCounter = 0;
2136: for (int i = 0; i < count; i++) {
2137: XmlSchemaObject item = items.getItem(i);
2138:
2139: if (item instanceof XmlSchemaElement) {
2140: //recursively process the element
2141: XmlSchemaElement xsElt = (XmlSchemaElement) item;
2142:
2143: boolean isArray = isArray(xsElt);
2144: processElement(xsElt, processedElementTypeMap,
2145: localNillableList, parentSchema); //we know for sure this is not an outer type
2146: processedElementArrayStatusMap.put(xsElt,
2147: (isArray) ? Boolean.TRUE : Boolean.FALSE);
2148: if (order) {
2149: //we need to keep the order of the elements. So push the elements to another
2150: //hashmap with the order number
2151: elementOrderMap.put(xsElt, new Integer(
2152: sequenceCounter));
2153: }
2154:
2155: //handle xsd:any ! We place an OMElement (or an array of OMElements) in the generated class
2156: } else if (item instanceof XmlSchemaAny) {
2157: XmlSchemaAny any = (XmlSchemaAny) item;
2158: processedElementTypeMap.put(new QName(
2159: ANY_ELEMENT_FIELD_NAME), any);
2160: //any can also be inside a sequence
2161: if (order) {
2162: elementOrderMap.put(any, new Integer(
2163: sequenceCounter));
2164: }
2165: //we do not register the array status for the any type
2166: processedElementArrayStatusMap.put(any,
2167: isArray(any) ? Boolean.TRUE : Boolean.FALSE);
2168: } else if (item instanceof XmlSchemaSequence) {
2169: // we have to process many sequence types
2170:
2171: XmlSchemaSequence xmlSchemaSequence = (XmlSchemaSequence) item;
2172: if (xmlSchemaSequence.getItems().getCount() > 0) {
2173: BeanWriterMetaInfoHolder beanWriterMetaInfoHolder = new BeanWriterMetaInfoHolder();
2174: process(parentElementQName, xmlSchemaSequence
2175: .getItems(), beanWriterMetaInfoHolder,
2176: true, parentSchema);
2177: beanWriterMetaInfoHolder.setParticleClass(true);
2178: String localName = parentElementQName
2179: .getLocalPart()
2180: + "Sequence";
2181: QName sequenceQName = new QName(parentElementQName
2182: .getNamespaceURI(), localName
2183: + getNextTypeSuffix(localName));
2184: String javaClassName = writeComplexParticle(
2185: sequenceQName, beanWriterMetaInfoHolder);
2186: processedTypemap.put(sequenceQName, javaClassName);
2187:
2188: //put the partical to array
2189: Boolean isArray = xmlSchemaSequence.getMaxOccurs() > 1 ? Boolean.TRUE
2190: : Boolean.FALSE;
2191: processedElementArrayStatusMap.put(item, isArray);
2192: particleQNameMap.put(item, sequenceQName);
2193:
2194: if (order) {
2195: elementOrderMap.put(item, new Integer(
2196: sequenceCounter));
2197: }
2198: }
2199:
2200: } else if (item instanceof XmlSchemaChoice) {
2201: // we have to process many sequence types
2202:
2203: XmlSchemaChoice xmlSchemaChoice = (XmlSchemaChoice) item;
2204: if (xmlSchemaChoice.getItems().getCount() > 0) {
2205: BeanWriterMetaInfoHolder beanWriterMetaInfoHolder = new BeanWriterMetaInfoHolder();
2206: beanWriterMetaInfoHolder.setChoice(true);
2207: process(parentElementQName, xmlSchemaChoice
2208: .getItems(), beanWriterMetaInfoHolder,
2209: false, parentSchema);
2210: beanWriterMetaInfoHolder.setParticleClass(true);
2211: String localName = parentElementQName
2212: .getLocalPart()
2213: + "Choice";
2214: QName choiceQName = new QName(parentElementQName
2215: .getNamespaceURI(), localName
2216: + getNextTypeSuffix(localName));
2217: String javaClassName = writeComplexParticle(
2218: choiceQName, beanWriterMetaInfoHolder);
2219: processedTypemap.put(choiceQName, javaClassName);
2220:
2221: //put the partical to array
2222: Boolean isArray = xmlSchemaChoice.getMaxOccurs() > 1 ? Boolean.TRUE
2223: : Boolean.FALSE;
2224: processedElementArrayStatusMap.put(item, isArray);
2225: particleQNameMap.put(item, choiceQName);
2226:
2227: if (order) {
2228: elementOrderMap.put(item, new Integer(
2229: sequenceCounter));
2230: }
2231: }
2232:
2233: } else if (item instanceof XmlSchemaGroupRef) {
2234:
2235: XmlSchemaGroupRef xmlSchemaGroupRef = (XmlSchemaGroupRef) item;
2236: QName groupQName = xmlSchemaGroupRef.getRefName();
2237: if (groupQName != null) {
2238: if (!processedTypemap.containsKey(groupQName)) {
2239: // processe the schema here
2240: XmlSchema resolvedParentSchema = resolveParentSchema(
2241: groupQName, parentSchema);
2242: XmlSchemaGroup xmlSchemaGroup = getGroup(
2243: groupQName, resolvedParentSchema);
2244: if (xmlSchemaGroup != null) {
2245: processGroup(xmlSchemaGroup, groupQName,
2246: parentSchema);
2247: } else {
2248: throw new SchemaCompilationException(
2249: "Refered Group "
2250: + groupQName.getLocalPart()
2251: + " can not be found ");
2252: }
2253:
2254: }
2255:
2256: Boolean isArray = xmlSchemaGroupRef.getMaxOccurs() > 1 ? Boolean.TRUE
2257: : Boolean.FALSE;
2258: processedElementArrayStatusMap.put(item, isArray);
2259: particleQNameMap.put(item, groupQName);
2260:
2261: if (order) {
2262: elementOrderMap.put(item, new Integer(
2263: sequenceCounter));
2264: }
2265:
2266: } else {
2267: throw new SchemaCompilationException(
2268: "Referenced name is null");
2269: }
2270:
2271: } else if (order && (item instanceof XmlSchemaChoice)) {
2272:
2273: // this is a tempory patch for process only inner sequence choices
2274: // but we have do this with a proper design
2275: XmlSchemaChoice choice = (XmlSchemaChoice) item;
2276: XmlSchemaObject choiceChild;
2277: XmlSchemaObjectCollection schemaItems = choice
2278: .getItems();
2279: for (int j = 0; j < schemaItems.getCount(); j++) {
2280: choiceChild = schemaItems.getItem(j);
2281: if (choiceChild instanceof XmlSchemaElement) {
2282: // i.e this is an inner choice element
2283: //recursively process the element
2284: XmlSchemaElement xsElt = (XmlSchemaElement) choiceChild;
2285:
2286: boolean isArray = isArray(xsElt);
2287: processElement(xsElt, processedElementTypeMap,
2288: localNillableList, parentSchema); //we know for sure this is not an outer type
2289: processedElementArrayStatusMap.put(xsElt,
2290: (isArray) ? Boolean.TRUE
2291: : Boolean.FALSE);
2292: if (order) {
2293: //we need to keep the order of the elements. So push the elements to another
2294: //hashmap with the order number
2295: elementOrderMap.put(xsElt, new Integer(
2296: sequenceCounter));
2297: sequenceCounter++;
2298: }
2299: innerChoiceElementList.add(xsElt.getQName());
2300: }
2301: }
2302:
2303: } else {
2304: //there may be other types to be handled here. Add them
2305: //when we are ready
2306: }
2307: sequenceCounter++;
2308: }
2309:
2310: // loop through the processed items and add them to the matainf object
2311: Iterator processedElementsIterator = processedElementArrayStatusMap
2312: .keySet().iterator();
2313: int startingItemNumberOrder = metainfHolder
2314: .getOrderStartPoint();
2315: while (processedElementsIterator.hasNext()) {
2316: Object child = processedElementsIterator.next();
2317:
2318: // process the XmlSchemaElement
2319: if (child instanceof XmlSchemaElement) {
2320: XmlSchemaElement elt = (XmlSchemaElement) child;
2321: QName referencedQName = null;
2322:
2323: if (elt.getQName() != null) {
2324: referencedQName = elt.getQName();
2325: QName schemaTypeQName = elt.getSchemaType() != null ? elt
2326: .getSchemaType().getQName()
2327: : elt.getSchemaTypeName();
2328: if (schemaTypeQName != null) {
2329: String clazzName = (String) processedElementTypeMap
2330: .get(elt.getQName());
2331: metainfHolder
2332: .registerMapping(
2333: referencedQName,
2334: schemaTypeQName,
2335: clazzName,
2336: ((Boolean) processedElementArrayStatusMap
2337: .get(elt))
2338: .booleanValue() ? SchemaConstants.ARRAY_TYPE
2339: : SchemaConstants.ELEMENT_TYPE);
2340: if (innerChoiceElementList
2341: .contains(referencedQName)) {
2342: metainfHolder
2343: .addtStatus(
2344: referencedQName,
2345: SchemaConstants.INNER_CHOICE_ELEMENT);
2346: }
2347: }
2348: }
2349:
2350: if (elt.getRefName() != null) { //probably this is referenced
2351: referencedQName = elt.getRefName();
2352: boolean arrayStatus = ((Boolean) processedElementArrayStatusMap
2353: .get(elt)).booleanValue();
2354: String clazzName = findRefClassName(
2355: referencedQName, arrayStatus);
2356: if (clazzName == null) {
2357: clazzName = findClassName(referencedQName,
2358: arrayStatus);
2359: }
2360: XmlSchemaElement refElement = getReferencedElement(
2361: parentSchema, referencedQName);
2362:
2363: // register the mapping if we found the referenced element
2364: // else throw an exception
2365: if (refElement != null) {
2366: metainfHolder
2367: .registerMapping(
2368: referencedQName,
2369: refElement.getSchemaTypeName(),
2370: clazzName,
2371: arrayStatus ? SchemaConstants.ARRAY_TYPE
2372: : SchemaConstants.ELEMENT_TYPE);
2373: } else {
2374: if (referencedQName
2375: .equals(SchemaConstants.XSD_SCHEMA)) {
2376: metainfHolder.registerMapping(
2377: referencedQName, null, writer
2378: .getDefaultClassName(),
2379: SchemaConstants.ANY_TYPE);
2380: } else {
2381: throw new SchemaCompilationException(
2382: SchemaCompilerMessages
2383: .getMessage(
2384: "schema.referencedElementNotFound",
2385: referencedQName
2386: .toString()));
2387: }
2388: }
2389: }
2390:
2391: if (referencedQName == null) {
2392: throw new SchemaCompilationException(
2393: SchemaCompilerMessages
2394: .getMessage("schema.emptyName"));
2395: }
2396:
2397: //register the occurence counts
2398: metainfHolder.addMaxOccurs(referencedQName, elt
2399: .getMaxOccurs());
2400: // if the strict validation off then we consider all elements have minOccurs zero on it
2401: if (this .options.isOffStrictValidation()) {
2402: metainfHolder.addMinOccurs(referencedQName, 0);
2403: } else {
2404: metainfHolder.addMinOccurs(referencedQName, elt
2405: .getMinOccurs());
2406: }
2407: //we need the order to be preserved. So record the order also
2408: if (order) {
2409: //record the order in the metainf holder
2410: Integer integer = (Integer) elementOrderMap
2411: .get(elt);
2412: metainfHolder.registerQNameIndex(referencedQName,
2413: startingItemNumberOrder
2414: + integer.intValue());
2415: }
2416:
2417: //get the nillable state and register that on the metainf holder
2418: if (localNillableList.contains(elt.getQName())) {
2419: metainfHolder.registerNillableQName(elt.getQName());
2420: }
2421:
2422: //get the binary state and add that to the status map
2423: if (isBinary(elt)) {
2424: metainfHolder.addtStatus(elt.getQName(),
2425: SchemaConstants.BINARY_TYPE);
2426: }
2427: // process the XMLSchemaAny
2428: } else if (child instanceof XmlSchemaAny) {
2429: XmlSchemaAny any = (XmlSchemaAny) child;
2430:
2431: //since there is only one element here it does not matter
2432: //for the constant. However the problem occurs if the users
2433: //uses the same name for an element decalration
2434: QName anyElementFieldName = new QName(
2435: ANY_ELEMENT_FIELD_NAME);
2436:
2437: //this can be an array or a single element
2438: boolean isArray = ((Boolean) processedElementArrayStatusMap
2439: .get(any)).booleanValue();
2440: metainfHolder.registerMapping(anyElementFieldName,
2441: null, isArray ? writer
2442: .getDefaultClassArrayName() : writer
2443: .getDefaultClassName(),
2444: SchemaConstants.ANY_TYPE);
2445: //if it's an array register an extra status flag with the system
2446: if (isArray) {
2447: metainfHolder.addtStatus(anyElementFieldName,
2448: SchemaConstants.ARRAY_TYPE);
2449: }
2450: metainfHolder.addMaxOccurs(anyElementFieldName, any
2451: .getMaxOccurs());
2452: metainfHolder.addMinOccurs(anyElementFieldName, any
2453: .getMinOccurs());
2454:
2455: if (order) {
2456: //record the order in the metainf holder for the any
2457: Integer integer = (Integer) elementOrderMap
2458: .get(any);
2459: metainfHolder.registerQNameIndex(
2460: anyElementFieldName,
2461: startingItemNumberOrder
2462: + integer.intValue());
2463: }
2464: } else if (child instanceof XmlSchemaSequence) {
2465: XmlSchemaSequence xmlSchemaSequence = (XmlSchemaSequence) child;
2466: QName sequenceQName = (QName) particleQNameMap
2467: .get(child);
2468: boolean isArray = xmlSchemaSequence.getMaxOccurs() > 1;
2469:
2470: // add this as an array to the original class
2471: metainfHolder.registerMapping(sequenceQName,
2472: sequenceQName, findClassName(sequenceQName,
2473: isArray));
2474: if (isArray) {
2475: metainfHolder.addtStatus(sequenceQName,
2476: SchemaConstants.ARRAY_TYPE);
2477: }
2478: metainfHolder.addtStatus(sequenceQName,
2479: SchemaConstants.PARTICLE_TYPE_ELEMENT);
2480: metainfHolder.addMaxOccurs(sequenceQName,
2481: xmlSchemaSequence.getMaxOccurs());
2482: metainfHolder.addMinOccurs(sequenceQName,
2483: xmlSchemaSequence.getMinOccurs());
2484: metainfHolder.setHasParticleType(true);
2485:
2486: if (order) {
2487: //record the order in the metainf holder for the any
2488: Integer integer = (Integer) elementOrderMap
2489: .get(child);
2490: metainfHolder.registerQNameIndex(sequenceQName,
2491: startingItemNumberOrder
2492: + integer.intValue());
2493: }
2494: } else if (child instanceof XmlSchemaChoice) {
2495: XmlSchemaChoice xmlSchemaChoice = (XmlSchemaChoice) child;
2496: QName choiceQName = (QName) particleQNameMap.get(child);
2497: boolean isArray = xmlSchemaChoice.getMaxOccurs() > 1;
2498:
2499: // add this as an array to the original class
2500: metainfHolder.registerMapping(choiceQName, choiceQName,
2501: findClassName(choiceQName, isArray));
2502: if (isArray) {
2503: metainfHolder.addtStatus(choiceQName,
2504: SchemaConstants.ARRAY_TYPE);
2505: }
2506: metainfHolder.addtStatus(choiceQName,
2507: SchemaConstants.PARTICLE_TYPE_ELEMENT);
2508: metainfHolder.addMaxOccurs(choiceQName, xmlSchemaChoice
2509: .getMaxOccurs());
2510: metainfHolder.addMinOccurs(choiceQName, xmlSchemaChoice
2511: .getMinOccurs());
2512: metainfHolder.setHasParticleType(true);
2513:
2514: if (order) {
2515: //record the order in the metainf holder for the any
2516: Integer integer = (Integer) elementOrderMap
2517: .get(child);
2518: metainfHolder.registerQNameIndex(choiceQName,
2519: startingItemNumberOrder
2520: + integer.intValue());
2521: }
2522: } else if (child instanceof XmlSchemaGroupRef) {
2523: XmlSchemaGroupRef xmlSchemaGroupRef = (XmlSchemaGroupRef) child;
2524: QName groupQName = (QName) particleQNameMap.get(child);
2525: boolean isArray = xmlSchemaGroupRef.getMaxOccurs() > 1;
2526:
2527: // add this as an array to the original class
2528: metainfHolder.registerMapping(groupQName, groupQName,
2529: findClassName(groupQName, isArray));
2530: if (isArray) {
2531: metainfHolder.addtStatus(groupQName,
2532: SchemaConstants.ARRAY_TYPE);
2533: }
2534: metainfHolder.addtStatus(groupQName,
2535: SchemaConstants.PARTICLE_TYPE_ELEMENT);
2536: metainfHolder.addMaxOccurs(groupQName,
2537: xmlSchemaGroupRef.getMaxOccurs());
2538: metainfHolder.addMinOccurs(groupQName,
2539: xmlSchemaGroupRef.getMinOccurs());
2540: metainfHolder.setHasParticleType(true);
2541:
2542: if (order) {
2543: //record the order in the metainf holder for the any
2544: Integer integer = (Integer) elementOrderMap
2545: .get(child);
2546: metainfHolder.registerQNameIndex(groupQName,
2547: startingItemNumberOrder
2548: + integer.intValue());
2549: }
2550: }
2551: }
2552:
2553: //set the ordered flag in the metainf holder
2554: metainfHolder.setOrdered(order);
2555: }
2556:
2557: private XmlSchemaGroup getGroup(QName groupQName,
2558: XmlSchema parentSchema) {
2559: XmlSchemaGroup xmlSchemaGroup = (XmlSchemaGroup) parentSchema
2560: .getGroups().getItem(groupQName);
2561: if (xmlSchemaGroup == null) {
2562: // i.e this attribute can be in a included or imported schema
2563: xmlSchemaGroup = (XmlSchemaGroup) parentSchema.getGroups()
2564: .getItem(groupQName);
2565: if (xmlSchemaGroup == null) {
2566: // try to find in an import or an include
2567: XmlSchemaObjectCollection includes = parentSchema
2568: .getIncludes();
2569: if (includes != null) {
2570: Iterator includesIter = includes.getIterator();
2571: Object object = null;
2572: while (includesIter.hasNext()) {
2573: object = includesIter.next();
2574: if (object instanceof XmlSchemaImport) {
2575: XmlSchema schema1 = ((XmlSchemaImport) object)
2576: .getSchema();
2577: xmlSchemaGroup = (XmlSchemaGroup) schema1
2578: .getGroups().getItem(groupQName);
2579: }
2580: if (object instanceof XmlSchemaInclude) {
2581: XmlSchema schema1 = ((XmlSchemaInclude) object)
2582: .getSchema();
2583: xmlSchemaGroup = (XmlSchemaGroup) schema1
2584: .getGroups().getItem(groupQName);
2585: }
2586: if (xmlSchemaGroup != null) {
2587: break;
2588: }
2589: }
2590: }
2591: }
2592: }
2593: return xmlSchemaGroup;
2594: }
2595:
2596: /**
2597: *
2598: * @param xmlSchemaGroup
2599: * @param schemaGroupQName- we have to pass this since xml schema does not provide
2600: * this properly
2601: * @param parentSchema
2602: * @throws SchemaCompilationException
2603: */
2604:
2605: private void processGroup(XmlSchemaGroup xmlSchemaGroup,
2606: QName schemaGroupQName, XmlSchema parentSchema)
2607: throws SchemaCompilationException {
2608:
2609: // find the group base item
2610: XmlSchemaGroupBase xmlSchemaGroupBase = xmlSchemaGroup
2611: .getParticle();
2612: if (xmlSchemaGroupBase != null) {
2613: if (xmlSchemaGroupBase instanceof XmlSchemaSequence) {
2614: XmlSchemaSequence xmlSchemaSequence = (XmlSchemaSequence) xmlSchemaGroupBase;
2615: if (xmlSchemaSequence.getItems().getCount() > 0) {
2616: BeanWriterMetaInfoHolder beanWriterMetaInfoHolder = new BeanWriterMetaInfoHolder();
2617: process(schemaGroupQName, xmlSchemaSequence
2618: .getItems(), beanWriterMetaInfoHolder,
2619: true, parentSchema);
2620: beanWriterMetaInfoHolder.setParticleClass(true);
2621: String javaClassName = writeComplexParticle(
2622: schemaGroupQName, beanWriterMetaInfoHolder);
2623: processedTypemap.put(schemaGroupQName,
2624: javaClassName);
2625: }
2626:
2627: } else if (xmlSchemaGroupBase instanceof XmlSchemaChoice) {
2628: XmlSchemaChoice xmlSchemaChoice = (XmlSchemaChoice) xmlSchemaGroupBase;
2629: if (xmlSchemaChoice.getItems().getCount() > 0) {
2630: BeanWriterMetaInfoHolder beanWriterMetaInfoHolder = new BeanWriterMetaInfoHolder();
2631: beanWriterMetaInfoHolder.setChoice(true);
2632: process(schemaGroupQName, xmlSchemaChoice
2633: .getItems(), beanWriterMetaInfoHolder,
2634: false, parentSchema);
2635: beanWriterMetaInfoHolder.setParticleClass(true);
2636: String javaClassName = writeComplexParticle(
2637: schemaGroupQName, beanWriterMetaInfoHolder);
2638: processedTypemap.put(schemaGroupQName,
2639: javaClassName);
2640: }
2641: }
2642: }
2643: }
2644:
2645: private XmlSchemaType getType(XmlSchema schema, QName schemaTypeName)
2646: throws SchemaCompilationException {
2647: // first check with the current parent schema
2648: XmlSchemaType typeByName = schema.getTypeByName(schemaTypeName);
2649: if (typeByName == null) {
2650: // try to resolve schema using the target names space
2651: schema = resolveParentSchema(schemaTypeName, schema);
2652: typeByName = schema.getTypeByName(schemaTypeName);
2653: if (typeByName == null) {
2654: // The referenced element seems to come from an imported
2655: // schema.
2656: XmlSchemaObjectCollection includes = schema
2657: .getIncludes();
2658: if (includes != null) {
2659: Iterator tempIterator = includes.getIterator();
2660: while (tempIterator.hasNext()) {
2661: Object o = tempIterator.next();
2662: XmlSchema inclSchema = null;
2663: if (o instanceof XmlSchemaImport) {
2664: inclSchema = ((XmlSchemaImport) o)
2665: .getSchema();
2666: if (inclSchema == null) {
2667: inclSchema = (XmlSchema) loadedSchemaMap
2668: .get(((XmlSchemaImport) o)
2669: .getNamespace());
2670: }
2671: }
2672: if (o instanceof XmlSchemaInclude) {
2673: inclSchema = ((XmlSchemaInclude) o)
2674: .getSchema();
2675: }
2676: // get the element from the included schema
2677: if (inclSchema != null) {
2678: typeByName = inclSchema
2679: .getTypeByName(schemaTypeName);
2680: }
2681: if (typeByName != null) {
2682: // we found the referenced element an can break the loop
2683: break;
2684: }
2685: }
2686: }
2687: }
2688: }
2689: return typeByName;
2690: }
2691:
2692: private XmlSchemaElement getReferencedElement(
2693: XmlSchema parentSchema, QName referencedQName)
2694: throws SchemaCompilationException {
2695: XmlSchemaElement refElement = parentSchema
2696: .getElementByName(referencedQName);
2697: if (refElement == null) {
2698: XmlSchema schema = resolveParentSchema(referencedQName,
2699: parentSchema);
2700: refElement = schema.getElementByName(referencedQName);
2701: if (refElement == null) {
2702: // The referenced element seems to come from an imported
2703: // schema.
2704: refElement = getReferenceElementFromSchema(schema,
2705: referencedQName);
2706: }
2707: }
2708:
2709: return refElement;
2710: }
2711:
2712: private XmlSchemaElement getReferenceElementFromSchema(
2713: XmlSchema schema, QName referencedQName) {
2714: XmlSchemaElement refElement = null;
2715: XmlSchemaObjectCollection includes = schema.getIncludes();
2716: if (includes != null) {
2717: Iterator tempIterator = includes.getIterator();
2718: while (tempIterator.hasNext()) {
2719: Object o = tempIterator.next();
2720: XmlSchema inclSchema = null;
2721:
2722: if (o instanceof XmlSchemaInclude) {
2723: inclSchema = ((XmlSchemaInclude) o).getSchema();
2724: if (inclSchema != null) {
2725: // first check in the scheam
2726: refElement = inclSchema
2727: .getElementByName(referencedQName);
2728: if (refElement == null) {
2729: // try to find the element in an inner schema
2730: refElement = getReferenceElementFromSchema(
2731: inclSchema, referencedQName);
2732: }
2733: if (refElement != null) {
2734: // we have found the element so exit from while loop;
2735: break;
2736: }
2737: }
2738: }
2739:
2740: if (o instanceof XmlSchemaImport) {
2741: inclSchema = ((XmlSchemaImport) o).getSchema();
2742: if (inclSchema == null) {
2743: inclSchema = (XmlSchema) loadedSchemaMap
2744: .get(((XmlSchemaImport) o)
2745: .getNamespace());
2746: }
2747: if (inclSchema != null) {
2748: // first check in the scheam
2749: refElement = inclSchema
2750: .getElementByName(referencedQName);
2751: if (refElement == null) {
2752: // try to find the element in an inner schema
2753: refElement = getReferenceElementFromSchema(
2754: inclSchema, referencedQName);
2755: }
2756: if (refElement != null) {
2757: // we have found the element so exit from while loop;
2758: break;
2759: }
2760: }
2761: }
2762:
2763: }
2764: }
2765: return refElement;
2766: }
2767:
2768: /**
2769: * Checks whether a given element is a binary element
2770: *
2771: * @param elt
2772: */
2773: private boolean isBinary(XmlSchemaElement elt) {
2774: return elt.getSchemaType() != null
2775: && SchemaConstants.XSD_BASE64.equals(elt
2776: .getSchemaType().getQName());
2777: }
2778:
2779: /**
2780: * Checks whether a given qname is a binary
2781: *
2782: * @param qName
2783: */
2784: private boolean isBinary(QName qName) {
2785: return qName != null
2786: && SchemaConstants.XSD_BASE64.equals(qName);
2787: }
2788:
2789: /**
2790: * @param simpleType
2791: * @param xsElt
2792: * @param parentSchema
2793: * @param qname - fake Qname to use if the xsElt is null.
2794: * @throws SchemaCompilationException
2795: */
2796: private void processSimpleSchemaType(
2797: XmlSchemaSimpleType simpleType, XmlSchemaElement xsElt,
2798: XmlSchema parentSchema, QName qname)
2799: throws SchemaCompilationException {
2800:
2801: String fullyQualifiedClassName = null;
2802: if (simpleType.getQName() != null) {
2803: if (processedTypemap.containsKey(simpleType.getQName())
2804: || baseSchemaTypeMap.containsKey(simpleType
2805: .getQName())) {
2806: return;
2807: }
2808:
2809: // Must do this up front to support recursive types
2810: fullyQualifiedClassName = writer
2811: .makeFullyQualifiedClassName(simpleType.getQName());
2812: // we put the qname to processed type map it is only named type
2813: // otherwise we have to any way process that element.
2814: processedTypemap.put(simpleType.getQName(),
2815: fullyQualifiedClassName);
2816: } else {
2817:
2818: QName fakeQname;
2819: if (xsElt != null) {
2820: fakeQname = new QName(xsElt.getQName()
2821: .getNamespaceURI(), xsElt.getQName()
2822: .getLocalPart()
2823: + getNextTypeSuffix(xsElt.getQName()
2824: .getLocalPart()));
2825: // we have to set this otherwise the ours attribute would not set properly if refered to this simple
2826: // type from any other element
2827: xsElt.setSchemaTypeName(fakeQname);
2828: changedElementSet.add(xsElt);
2829:
2830: } else {
2831: fakeQname = qname;
2832: }
2833: if (processedTypemap.containsKey(fakeQname)
2834: || baseSchemaTypeMap.containsKey(fakeQname)) {
2835: return;
2836: }
2837: fullyQualifiedClassName = writer
2838: .makeFullyQualifiedClassName(fakeQname);
2839: simpleType
2840: .addMetaInfo(
2841: SchemaConstants.SchemaCompilerInfoHolder.FAKE_QNAME,
2842: fakeQname);
2843:
2844: // should put this to the processedTypemap to generate the code correctly
2845: processedTypemap.put(fakeQname, fullyQualifiedClassName);
2846: }
2847:
2848: //register that in the schema metainfo bag
2849: simpleType.addMetaInfo(
2850: SchemaConstants.SchemaCompilerInfoHolder.CLASSNAME_KEY,
2851: fullyQualifiedClassName);
2852:
2853: BeanWriterMetaInfoHolder metaInfHolder = processSimpleType(
2854: simpleType, parentSchema);
2855: metaInfHolder.setSimple(true);
2856:
2857: if (simpleType.getQName() == null) {
2858: this .processedAnonymousComplexTypesMap.put(xsElt,
2859: metaInfHolder);
2860: QName fakeQname;
2861: if (xsElt != null) {
2862: fakeQname = new QName(xsElt.getQName()
2863: .getNamespaceURI(), xsElt.getQName()
2864: .getLocalPart());
2865: } else {
2866: fakeQname = qname;
2867: simpleType.setName(fakeQname.getLocalPart());
2868: simpleType.setSourceURI(fakeQname.getNamespaceURI());
2869: }
2870: simpleTypesMap.put(fakeQname, fullyQualifiedClassName);
2871: }
2872: //add this information to the metainfo holder
2873: metaInfHolder.setOwnQname(simpleType.getQName());
2874: if (fullyQualifiedClassName != null) {
2875: metaInfHolder.setOwnClassName(fullyQualifiedClassName);
2876: }
2877: //write the class. This type mapping would have been populated right now
2878: //Note - We always write classes for named complex types
2879: writeSimpleType(simpleType, metaInfHolder);
2880: }
2881:
2882: private BeanWriterMetaInfoHolder processSimpleType(
2883: XmlSchemaSimpleType simpleType, XmlSchema parentSchema)
2884: throws SchemaCompilationException {
2885: BeanWriterMetaInfoHolder metaInfHolder = new BeanWriterMetaInfoHolder();
2886:
2887: // handle the restriction
2888: XmlSchemaSimpleTypeContent content = simpleType.getContent();
2889: QName parentSimpleTypeQname = simpleType.getQName();
2890: if (parentSimpleTypeQname == null) {
2891: parentSimpleTypeQname = (QName) simpleType
2892: .getMetaInfoMap()
2893: .get(
2894: SchemaConstants.SchemaCompilerInfoHolder.FAKE_QNAME);
2895: }
2896: if (content != null) {
2897: if (content instanceof XmlSchemaSimpleTypeRestriction) {
2898: XmlSchemaSimpleTypeRestriction restriction = (XmlSchemaSimpleTypeRestriction) content;
2899:
2900: QName baseTypeName = restriction.getBaseTypeName();
2901: //check whether the base type is one of the base schema types
2902:
2903: if (baseSchemaTypeMap.containsKey(baseTypeName)) {
2904: //process restriction base type
2905:
2906: processSimpleRestrictionBaseType(
2907: parentSimpleTypeQname, restriction
2908: .getBaseTypeName(), metaInfHolder,
2909: parentSchema);
2910: //process facets
2911: processFacets(restriction, metaInfHolder,
2912: parentSchema);
2913: } else {
2914: //recurse
2915: // this must be a xmlschema bug
2916: // it should return the schematype for restriction.getBaseType():
2917: XmlSchemaType restrictionBaseType = getType(
2918: parentSchema, baseTypeName);
2919: if (restrictionBaseType instanceof XmlSchemaSimpleType) {
2920: if ((restrictionBaseType != null)
2921: && (!isAlreadyProcessed(baseTypeName))) {
2922: processSimpleSchemaType(
2923: (XmlSchemaSimpleType) restrictionBaseType,
2924: null, parentSchema, null);
2925: }
2926: // process restriction
2927: processSimpleRestrictionBaseType(
2928: parentSimpleTypeQname, restriction
2929: .getBaseTypeName(),
2930: metaInfHolder, parentSchema);
2931: }
2932:
2933: }
2934: } else if (content instanceof XmlSchemaSimpleTypeUnion) {
2935: XmlSchemaSimpleTypeUnion simpleTypeUnion = (XmlSchemaSimpleTypeUnion) content;
2936: QName[] qnames = simpleTypeUnion.getMemberTypesQNames();
2937: if (qnames != null) {
2938: QName qname;
2939: for (int i = 0; i < qnames.length; i++) {
2940: qname = qnames[i];
2941: if (baseSchemaTypeMap.containsKey(qname)) {
2942: metaInfHolder.addMemberType(qname,
2943: (String) baseSchemaTypeMap
2944: .get(qname));
2945: } else {
2946: XmlSchemaType type = getType(parentSchema,
2947: qname);
2948: if (type instanceof XmlSchemaSimpleType) {
2949: XmlSchemaSimpleType memberSimpleType = (XmlSchemaSimpleType) type;
2950: if (!isAlreadyProcessed(qname)) {
2951: processSimpleSchemaType(
2952: memberSimpleType, null,
2953: parentSchema, null);
2954: }
2955: metaInfHolder.addMemberType(qname,
2956: (String) processedTypemap
2957: .get(qname));
2958: } else {
2959: throw new SchemaCompilationException(
2960: "Unions can not have complex types as a member type");
2961: }
2962: }
2963: }
2964: } else {
2965: XmlSchemaObjectCollection xmlSchemaObjectCollection = simpleTypeUnion
2966: .getBaseTypes();
2967: XmlSchemaObject xmlSchemaObject;
2968: QName childQname;
2969: int i = 1;
2970: for (Iterator iter = xmlSchemaObjectCollection
2971: .getIterator(); iter.hasNext();) {
2972: xmlSchemaObject = (XmlSchemaObject) iter.next();
2973: i++;
2974: if (xmlSchemaObject instanceof XmlSchemaSimpleType) {
2975: XmlSchemaSimpleType unionSimpleType = (XmlSchemaSimpleType) xmlSchemaObject;
2976: childQname = unionSimpleType.getQName();
2977: if (childQname == null) {
2978: // we create a fake Qname for all these simple types since most propably they don't have one
2979: childQname = new QName(
2980: parentSimpleTypeQname
2981: .getNamespaceURI(),
2982: parentSimpleTypeQname
2983: .getLocalPart()
2984: + getNextTypeSuffix(parentSimpleTypeQname
2985: .getLocalPart()));
2986: }
2987: // this is an inner simple type of the union so it shold not have
2988: // processed
2989: processSimpleSchemaType(unionSimpleType,
2990: null, parentSchema, childQname);
2991: metaInfHolder.addMemberType(childQname,
2992: (String) processedTypemap
2993: .get(childQname));
2994: }
2995:
2996: }
2997: }
2998:
2999: metaInfHolder.setUnion(true);
3000:
3001: } else if (content instanceof XmlSchemaSimpleTypeList) {
3002: XmlSchemaSimpleTypeList simpleTypeList = (XmlSchemaSimpleTypeList) content;
3003: QName itemTypeQName = simpleTypeList.getItemTypeName();
3004:
3005: if (itemTypeQName != null) {
3006: if (!isAlreadyProcessed(itemTypeQName)) {
3007: XmlSchemaType simpleSchemaType = getType(
3008: parentSchema, itemTypeQName);
3009: if (simpleSchemaType instanceof XmlSchemaSimpleType) {
3010: processSimpleSchemaType(
3011: (XmlSchemaSimpleType) simpleSchemaType,
3012: null, parentSchema, null);
3013: }
3014: }
3015: } else {
3016: XmlSchemaSimpleType listSimpleType = simpleTypeList
3017: .getItemType();
3018: itemTypeQName = listSimpleType.getQName();
3019: if (itemTypeQName == null) {
3020: // we create a fake Qname for all these simple types since most propably they don't have one
3021: itemTypeQName = new QName(parentSimpleTypeQname
3022: .getNamespaceURI(),
3023: parentSimpleTypeQname.getLocalPart()
3024: + "_type0");
3025: }
3026: processSimpleSchemaType(listSimpleType, null,
3027: parentSchema, itemTypeQName);
3028:
3029: }
3030:
3031: String className = findClassName(itemTypeQName, false);
3032: metaInfHolder.setList(true);
3033: metaInfHolder.setItemTypeQName(itemTypeQName);
3034: metaInfHolder.setItemTypeClassName(className);
3035:
3036: }
3037: }
3038: return metaInfHolder;
3039: }
3040:
3041: /**
3042: * Find whether a given particle is an array. The logic for deciding
3043: * whether a given particle is an array is depending on their minOccurs
3044: * and maxOccurs counts. If Maxoccurs is greater than one (1) then the
3045: * content is an array.
3046: * Also no higher level element will have the maxOccurs greater than one
3047: *
3048: * @param particle
3049: * @throws SchemaCompilationException
3050: */
3051: private boolean isArray(XmlSchemaParticle particle)
3052: throws SchemaCompilationException {
3053: long minOccurs = particle.getMinOccurs();
3054: long maxOccurs = particle.getMaxOccurs();
3055:
3056: if (maxOccurs < minOccurs) {
3057: throw new SchemaCompilationException();
3058: } else {
3059: return (maxOccurs > 1);
3060: }
3061:
3062: }
3063:
3064: HashMap mapTypeCount = new HashMap();
3065:
3066: private String getNextTypeSuffix(String localName) {
3067: Integer typeCounter = (Integer) mapTypeCount.get(localName);
3068: int count = 0;
3069: if (typeCounter != null) {
3070: if (typeCounter.intValue() == Integer.MAX_VALUE) {
3071: count = 0;
3072: } else {
3073: count = typeCounter.intValue();
3074: }
3075: }
3076: mapTypeCount.put(localName, new Integer(count + 1));
3077: return ("_type" + count);
3078: }
3079: }
|