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.writer;
0020:
0021: import org.w3c.dom.Document;
0022: import org.w3c.dom.Element;
0023: import org.apache.axis2.schema.typemap.JavaTypeMap;
0024: import org.apache.axis2.schema.CompilerOptions;
0025: import org.apache.axis2.schema.SchemaCompilationException;
0026: import org.apache.axis2.schema.BeanWriterMetaInfoHolder;
0027: import org.apache.axis2.schema.SchemaCompiler;
0028: import org.apache.axis2.schema.util.SchemaPropertyLoader;
0029: import org.apache.axis2.schema.util.PrimitiveTypeFinder;
0030: import org.apache.axis2.schema.util.PrimitiveTypeWrapper;
0031: import org.apache.axis2.schema.i18n.SchemaCompilerMessages;
0032: import org.apache.axis2.util.XSLTUtils;
0033: import org.apache.axis2.util.JavaUtils;
0034: import org.apache.axis2.util.XSLTTemplateProcessor;
0035: import org.apache.axis2.wsdl.databinding.CUtils;
0036: import org.apache.ws.commons.schema.XmlSchemaElement;
0037: import org.apache.ws.commons.schema.XmlSchemaComplexType;
0038: import org.apache.ws.commons.schema.XmlSchemaSimpleType;
0039:
0040: import javax.xml.transform.Templates;
0041: import javax.xml.transform.TransformerFactory;
0042: import javax.xml.transform.TransformerConfigurationException;
0043: import javax.xml.transform.stream.StreamSource;
0044: import javax.xml.parsers.ParserConfigurationException;
0045: import javax.xml.namespace.QName;
0046: import java.util.*;
0047: import java.io.*;
0048:
0049: import com.ibm.wsdl.util.xml.DOM2Writer;
0050:
0051: /**
0052: * Java Bean writer for the schema compiler.
0053: */
0054: public class CStructWriter implements BeanWriter {
0055:
0056: public static final String WRAPPED_DATABINDING_CLASS_NAME = "WrappedDatabinder";
0057: public static final String AXIS2_PREFIX = "adb_";
0058: private String javaBeanTemplateName = null;
0059: private boolean templateLoaded = false;
0060: private Templates sourceTemplateCache;
0061: private Templates headerTemplateCache;
0062:
0063: private List namesList;
0064: private static int count = 0;
0065: private boolean wrapClasses = false;
0066: private boolean writeClasses = false;
0067:
0068: protected File rootDir;
0069:
0070: private Document globalWrappedSourceDocument;
0071: private Document globalWrappedHeaderDocument;
0072:
0073: private Map modelMap = new HashMap();
0074: private static final String DEFAULT_PACKAGE = "adb";
0075: private static final String DEFAULT_C_CLASS_NAME = "axiom_node_t*";
0076:
0077: private Map baseTypeMap = new JavaTypeMap().getTypeMap();
0078:
0079: // a list of externally identified QNames to be processed. This becomes
0080: // useful when only a list of external elements need to be processed
0081:
0082: public static final String DEFAULT_CLASS_NAME = "axiom_node_t*";
0083: public static final String DEFAULT_CLASS_ARRAY_NAME = "axis2_array_list_t";
0084:
0085: public static final String DEFAULT_ATTRIB_CLASS_NAME = "axiom_attribute_t*";
0086: public static final String DEFAULT_ATTRIB_ARRAY_CLASS_NAME = "axis2_array_list_t";
0087:
0088: /**
0089: * Default constructor
0090: */
0091: public CStructWriter() {
0092: }
0093:
0094: /**
0095: * This returns a map of Qnames vs DOMDocument models. One can use this method to
0096: * obtain the raw DOMmodels used to write the classes.
0097: * This has no meaning when the classes are supposed to be wrapped so the
0098: *
0099: * @return Returns Map.
0100: * @see BeanWriter#getModelMap()
0101: */
0102: public Map getModelMap() {
0103: return modelMap;
0104: }
0105:
0106: public String getDefaultClassName() {
0107: return DEFAULT_CLASS_NAME;
0108: }
0109:
0110: public String getDefaultClassArrayName() {
0111: return DEFAULT_CLASS_ARRAY_NAME;
0112: }
0113:
0114: public String getDefaultAttribClassName() {
0115: return DEFAULT_ATTRIB_CLASS_NAME;
0116: }
0117:
0118: public String getDefaultAttribArrayClassName() {
0119: return DEFAULT_ATTRIB_ARRAY_CLASS_NAME;
0120: }
0121:
0122: public void init(CompilerOptions options)
0123: throws SchemaCompilationException {
0124: try {
0125: initWithFile(options.getOutputLocation());
0126:
0127: writeClasses = options.isWriteOutput();
0128: if (!writeClasses) {
0129: wrapClasses = false;
0130: } else {
0131: wrapClasses = options.isWrapClasses();
0132: }
0133:
0134: //if the wrap mode is set then create a global document to keep the wrapped
0135: //element models
0136: if (options.isWrapClasses()) {
0137: globalWrappedSourceDocument = XSLTUtils.getDocument();
0138: Element rootElement = XSLTUtils.getElement(
0139: globalWrappedSourceDocument, "beans");
0140: globalWrappedSourceDocument.appendChild(rootElement);
0141: XSLTUtils.addAttribute(globalWrappedSourceDocument,
0142: "name",
0143: CStructWriter.WRAPPED_DATABINDING_CLASS_NAME,
0144: rootElement);
0145:
0146: globalWrappedHeaderDocument = XSLTUtils.getDocument();
0147: rootElement = XSLTUtils.getElement(
0148: globalWrappedHeaderDocument, "beans");
0149: globalWrappedHeaderDocument.appendChild(rootElement);
0150: XSLTUtils.addAttribute(globalWrappedHeaderDocument,
0151: "name",
0152: CStructWriter.WRAPPED_DATABINDING_CLASS_NAME,
0153: rootElement);
0154:
0155: }
0156:
0157: } catch (IOException e) {
0158: throw new SchemaCompilationException(e);
0159: } catch (ParserConfigurationException e) {
0160: throw new SchemaCompilationException(e); //todo need to put correct error messages
0161: }
0162: }
0163:
0164: /**
0165: * @param element
0166: * @param typeMap
0167: * @param metainf
0168: * @return Returns String.
0169: * @throws org.apache.axis2.schema.SchemaCompilationException
0170: *
0171: */
0172: public String write(XmlSchemaElement element, Map typeMap,
0173: BeanWriterMetaInfoHolder metainf)
0174: throws SchemaCompilationException {
0175:
0176: try {
0177: QName qName = element.getQName();
0178:
0179: return process(qName, metainf, typeMap, true);
0180: } catch (Exception e) {
0181: throw new SchemaCompilationException(e);
0182: }
0183:
0184: }
0185:
0186: /**
0187: * @param qName
0188: * @param typeMap
0189: * @param metainf
0190: * @param isAbstract
0191: * @throws org.apache.axis2.schema.SchemaCompilationException
0192: *
0193: * @see org.apache.axis2.schema.writer.BeanWriter
0194: */
0195: public String write(QName qName, Map typeMap,
0196: BeanWriterMetaInfoHolder metainf, boolean isAbstract)
0197: throws SchemaCompilationException {
0198:
0199: try {
0200: //determine the package for this type.
0201: return process(qName, metainf, typeMap, false);
0202:
0203: } catch (SchemaCompilationException e) {
0204: throw e;
0205: } catch (Exception e) {
0206: throw new SchemaCompilationException(e);
0207: }
0208:
0209: }
0210:
0211: /**
0212: * @throws SchemaCompilationException
0213: * @see org.apache.axis2.schema.writer.BeanWriter#writeBatch()
0214: */
0215: public void writeBatch() throws SchemaCompilationException {
0216: try {
0217: if (wrapClasses) {
0218:
0219: File outSource = createOutFile(
0220: CStructWriter.WRAPPED_DATABINDING_CLASS_NAME,
0221: ".c");
0222: File outHeader = createOutFile(
0223: CStructWriter.WRAPPED_DATABINDING_CLASS_NAME,
0224: ".h");
0225: //parse with the template and create the files
0226: parseSource(globalWrappedSourceDocument, outSource);
0227: parseHeader(globalWrappedHeaderDocument, outHeader);
0228: }
0229: } catch (Exception e) {
0230: throw new SchemaCompilationException(e);
0231: }
0232: }
0233:
0234: /**
0235: * @param simpleType
0236: * @param typeMap
0237: * @param metainf
0238: * @return Returns String.
0239: * @throws org.apache.axis2.schema.SchemaCompilationException
0240: *
0241: * @see BeanWriter#write(org.apache.ws.commons.schema.XmlSchemaSimpleType, java.util.Map, org.apache.axis2.schema.BeanWriterMetaInfoHolder)
0242: */
0243: public String write(XmlSchemaSimpleType simpleType, Map typeMap,
0244: BeanWriterMetaInfoHolder metainf)
0245: throws SchemaCompilationException {
0246: try {
0247: //determine the package for this type.
0248: QName qName = simpleType.getQName();
0249: return process(qName, metainf, typeMap, false);
0250:
0251: } catch (SchemaCompilationException e) {
0252: throw e;
0253: } catch (Exception e) {
0254: throw new SchemaCompilationException(e);
0255: }
0256: }
0257:
0258: /**
0259: * @param rootDir
0260: * @throws java.io.IOException
0261: * @see org.apache.axis2.schema.writer.BeanWriter
0262: */
0263: private void initWithFile(File rootDir) throws IOException {
0264: if (rootDir == null) {
0265: this .rootDir = new File(".");
0266: } else if (!rootDir.isDirectory()) {
0267: throw new IOException(SchemaCompilerMessages
0268: .getMessage("schema.rootnotfolderexception"));
0269: } else {
0270: this .rootDir = rootDir;
0271: }
0272:
0273: namesList = new ArrayList();
0274: javaBeanTemplateName = SchemaPropertyLoader.getBeanTemplate();
0275: }
0276:
0277: /**
0278: * Make the fully qualified class name for an element or named type
0279: *
0280: * @param qName the qualified Name for this element or type in the schema
0281: * @return the appropriate fully qualified class name to use in generated code
0282: */
0283: public String makeFullyQualifiedClassName(QName qName) {
0284:
0285: String originalName = qName.getLocalPart();
0286:
0287: return makeUniqueCStructName(this .namesList, originalName);
0288: }
0289:
0290: /**
0291: * A util method that holds common code
0292: * for the complete schema that the generated XML complies to
0293: * look under other/beanGenerationSchema.xsd
0294: *
0295: * @param qName
0296: * @param metainf
0297: * @param typeMap
0298: * @param isElement
0299: * @return Returns String.
0300: * @throws Exception
0301: */
0302: private String process(QName qName,
0303: BeanWriterMetaInfoHolder metainf, Map typeMap,
0304: boolean isElement) throws Exception {
0305: String fullyQualifiedClassName = metainf.getOwnClassName();
0306: if (fullyQualifiedClassName == null)
0307: fullyQualifiedClassName = makeFullyQualifiedClassName(qName);
0308: String className = fullyQualifiedClassName;
0309:
0310: String originalName = qName.getLocalPart();
0311: ArrayList propertyNames = new ArrayList();
0312:
0313: if (!templateLoaded) {
0314: loadTemplate();
0315: }
0316:
0317: //if wrapped then do not write the classes now but add the models to a global document. However in order to write the
0318: //global class that is generated, one needs to call the writeBatch() method
0319: if (wrapClasses) {
0320: globalWrappedSourceDocument.getDocumentElement()
0321: .appendChild(
0322: getBeanElement(globalWrappedSourceDocument,
0323: className, originalName, qName,
0324: isElement, metainf, propertyNames,
0325: typeMap));
0326: globalWrappedHeaderDocument.getDocumentElement()
0327: .appendChild(
0328: getBeanElement(globalWrappedHeaderDocument,
0329: className, originalName, qName,
0330: isElement, metainf, propertyNames,
0331: typeMap));
0332:
0333: } else {
0334: //create the model
0335: Document modelSource = XSLTUtils.getDocument();
0336: Document modelHeader = XSLTUtils.getDocument();
0337: //make the XML
0338: modelSource.appendChild(getBeanElement(modelSource,
0339: className, originalName, qName, isElement, metainf,
0340: propertyNames, typeMap));
0341: modelHeader.appendChild(getBeanElement(modelHeader,
0342: className, originalName, qName, isElement, metainf,
0343: propertyNames, typeMap));
0344:
0345: if (writeClasses) {
0346: //create the file
0347: File outSource = createOutFile(className, ".c");
0348: File outHeader = createOutFile(className, ".h");
0349: //parse with the template and create the files
0350: parseSource(modelSource, outSource);
0351: parseHeader(modelHeader, outHeader);
0352: }
0353:
0354: //add the model to the model map
0355: modelMap.put(new QName(qName.getNamespaceURI(), className),
0356: modelSource);
0357: modelMap.put(new QName(qName.getNamespaceURI(), className),
0358: modelHeader);
0359:
0360: }
0361:
0362: //return the fully qualified class name
0363: return fullyQualifiedClassName;
0364:
0365: }
0366:
0367: /**
0368: * @param model
0369: * @param className
0370: * @param originalName
0371: * @param qName
0372: * @param isElement
0373: * @param metainf
0374: * @param propertyNames
0375: * @param typeMap
0376: * @return Returns Element.
0377: * @throws org.apache.axis2.schema.SchemaCompilationException
0378: *
0379: */
0380: private Element getBeanElement(Document model, String className,
0381: String originalName, QName qName, boolean isElement,
0382: BeanWriterMetaInfoHolder metainf, ArrayList propertyNames,
0383: Map typeMap) throws SchemaCompilationException {
0384:
0385: Element rootElt = XSLTUtils.getElement(model, "class");
0386: XSLTUtils.addAttribute(model, "name", className, rootElt);
0387: XSLTUtils.addAttribute(model, "caps-name", className
0388: .toUpperCase(), rootElt);
0389: XSLTUtils.addAttribute(model, "originalName", originalName,
0390: rootElt);
0391: XSLTUtils.addAttribute(model, "nsuri", qName.getNamespaceURI(),
0392: rootElt);
0393: XSLTUtils.addAttribute(model, "nsprefix", getPrefixForURI(qName
0394: .getNamespaceURI(), qName.getPrefix()), rootElt);
0395:
0396: /* use caps for macros */
0397: String capsName = className.toUpperCase();
0398: XSLTUtils.addAttribute(model, "caps-name", capsName, rootElt);
0399:
0400: if (!wrapClasses) {
0401: XSLTUtils.addAttribute(model, "unwrapped", "yes", rootElt);
0402: }
0403:
0404: if (!writeClasses) {
0405: XSLTUtils.addAttribute(model, "skip-write", "yes", rootElt);
0406: }
0407:
0408: if (!isElement) {
0409: XSLTUtils.addAttribute(model, "type", "yes", rootElt);
0410: }
0411:
0412: if (metainf.isAnonymous()) {
0413: XSLTUtils.addAttribute(model, "anon", "yes", rootElt);
0414: }
0415:
0416: if (metainf.isExtension()) {
0417: XSLTUtils.addAttribute(model, "extension", metainf
0418: .getExtensionClassName(), rootElt);
0419: }
0420:
0421: if (metainf.isRestriction()) {
0422: XSLTUtils.addAttribute(model, "restriction", metainf
0423: .getRestrictionClassName(), rootElt);
0424: }
0425:
0426: if (metainf.isChoice()) {
0427: XSLTUtils.addAttribute(model, "choice", "yes", rootElt);
0428: }
0429:
0430: if (metainf.isSimple()) {
0431: XSLTUtils.addAttribute(model, "simple", "yes", rootElt);
0432: }
0433:
0434: if (metainf.isUnion()) {
0435: XSLTUtils.addAttribute(model, "union", "yes", rootElt);
0436: }
0437:
0438: if (metainf.isList()) {
0439: XSLTUtils.addAttribute(model, "list", "yes", rootElt);
0440: }
0441:
0442: if (metainf.isOrdered()) {
0443: XSLTUtils.addAttribute(model, "ordered", "yes", rootElt);
0444: }
0445:
0446: if (isElement && metainf.isNillable(qName)) {
0447: XSLTUtils.addAttribute(model, "nillable", "yes", rootElt);
0448: }
0449:
0450: //populate all the information
0451: populateInfo(metainf, model, rootElt, propertyNames, typeMap,
0452: false);
0453:
0454: if (metainf.isSimple() && metainf.isUnion()) {
0455: populateMemberInfo(metainf, model, rootElt, typeMap);
0456: }
0457:
0458: if (metainf.isSimple() && metainf.isList()) {
0459: populateListInfo(metainf, model, rootElt, typeMap);
0460: }
0461:
0462: return rootElt;
0463: }
0464:
0465: protected void populateListInfo(BeanWriterMetaInfoHolder metainf,
0466: Document model, Element rootElement, Map typeMap) {
0467:
0468: String cName = makeUniqueCStructName(new ArrayList(), metainf
0469: .getItemTypeQName().getLocalPart());
0470: Element itemType = XSLTUtils.addChildElement(model, "itemtype",
0471: rootElement);
0472: XSLTUtils.addAttribute(model, "type", metainf
0473: .getItemTypeClassName(), itemType);
0474: XSLTUtils.addAttribute(model, "nsuri", metainf
0475: .getItemTypeQName().getNamespaceURI(), itemType);
0476: XSLTUtils.addAttribute(model, "originalName", metainf
0477: .getItemTypeQName().getLocalPart(), itemType);
0478: XSLTUtils.addAttribute(model, "cname", cName, itemType);
0479:
0480: if (typeMap.containsKey(metainf.getItemTypeQName())) {
0481: XSLTUtils.addAttribute(model, "ours", "true", itemType);
0482: }
0483: if (PrimitiveTypeFinder.isPrimitive(metainf
0484: .getItemTypeClassName())) {
0485: XSLTUtils.addAttribute(model, "primitive", "yes", itemType);
0486: }
0487:
0488: }
0489:
0490: protected void populateMemberInfo(BeanWriterMetaInfoHolder metainf,
0491: Document model, Element rootElement, Map typeMap) {
0492: Map memberTypes = metainf.getMemberTypes();
0493: QName memberQName;
0494: for (Iterator iter = memberTypes.keySet().iterator(); iter
0495: .hasNext();) {
0496: memberQName = (QName) iter.next();
0497: String memberClass = (String) memberTypes.get(memberQName);
0498: if (PrimitiveTypeFinder.isPrimitive(memberClass)) {
0499: memberClass = PrimitiveTypeWrapper
0500: .getWrapper(memberClass);
0501: }
0502:
0503: // add member type element
0504: Element memberType = XSLTUtils.addChildElement(model,
0505: "memberType", rootElement);
0506: XSLTUtils.addAttribute(model, "type", memberClass,
0507: memberType);
0508: XSLTUtils.addAttribute(model, "nsuri", memberQName
0509: .getNamespaceURI(), memberType);
0510: XSLTUtils.addAttribute(model, "originalName", memberQName
0511: .getLocalPart(), memberType);
0512: XSLTUtils.addAttribute(model, "caps-originalName",
0513: memberQName.getLocalPart().toUpperCase(),
0514: memberType);
0515: if (typeMap.containsKey(memberQName)) {
0516: XSLTUtils.addAttribute(model, "ours", "true",
0517: memberType);
0518: }
0519:
0520: }
0521: }
0522:
0523: /**
0524: * @param metainf
0525: * @param model
0526: * @param rootElt
0527: * @param propertyNames
0528: * @param typeMap
0529: * @throws org.apache.axis2.schema.SchemaCompilationException
0530: *
0531: */
0532: private void populateInfo(BeanWriterMetaInfoHolder metainf,
0533: Document model, Element rootElt, ArrayList propertyNames,
0534: Map typeMap, boolean isInherited)
0535: throws SchemaCompilationException {
0536: if (metainf.getParent() != null) {
0537: populateInfo(metainf.getParent(), model, rootElt,
0538: propertyNames, typeMap, true);
0539: }
0540: addPropertyEntries(metainf, model, rootElt, propertyNames,
0541: typeMap, isInherited);
0542:
0543: }
0544:
0545: /**
0546: * @param metainf
0547: * @param model
0548: * @param rootElt
0549: * @param propertyNames
0550: * @param typeMap
0551: * @throws org.apache.axis2.schema.SchemaCompilationException
0552: - *
0553: */
0554: private void addPropertyEntries(BeanWriterMetaInfoHolder metainf,
0555: Document model, Element rootElt, ArrayList propertyNames,
0556: Map typeMap, boolean isInherited)
0557: throws SchemaCompilationException {
0558: // go in the loop and add the part elements
0559: QName[] qName;
0560: ArrayList missingQNames = new ArrayList();
0561: ArrayList qNames = new ArrayList();
0562: BeanWriterMetaInfoHolder parentMetaInf = metainf.getParent();
0563:
0564: if (metainf.isOrdered()) {
0565: qName = metainf.getOrderedQNameArray();
0566: } else {
0567: qName = metainf.getQNameArray();
0568: }
0569:
0570: for (int i = 0; i < qName.length; i++) {
0571: qNames.add(qName[i]);
0572: }
0573: //adding missing QNames to the end, including elements & attributes.
0574: // for the simple types we have already add the parent elements
0575: // it is almost consider as an extension
0576: if (metainf.isRestriction() && !metainf.isSimple()) {
0577: addMissingQNames(metainf, qNames, missingQNames);
0578: }
0579:
0580: QName name;
0581: for (int i = 0; i < qName.length; i++) {
0582: Element property = XSLTUtils.addChildElement(model,
0583: "property", rootElt);
0584: name = qName[i];
0585: String xmlName = makeUniqueCStructName(new ArrayList(),
0586: name.getLocalPart());
0587:
0588: XSLTUtils.addAttribute(model, "name", xmlName, property);
0589: XSLTUtils.addAttribute(model, "originalName", name
0590: .getLocalPart(), property);
0591:
0592: XSLTUtils.addAttribute(model, "nsuri", name
0593: .getNamespaceURI(), property);
0594: XSLTUtils.addAttribute(model, "prefix", name.getPrefix(),
0595: property);
0596:
0597: XSLTUtils.addAttribute(model, "cname", xmlName, property);
0598:
0599: String CClassNameForElement = metainf
0600: .getClassNameForQName(name);
0601:
0602: if (CClassNameForElement == null) {
0603: CClassNameForElement = CStructWriter.DEFAULT_C_CLASS_NAME;
0604: }
0605: CClassNameForElement = getShortTypeName(CClassNameForElement);
0606:
0607: XSLTUtils.addAttribute(model, "type", CClassNameForElement,
0608: property);
0609:
0610: /**
0611: * Caps for use in C macros
0612: */
0613: XSLTUtils.addAttribute(model, "caps-cname", xmlName
0614: .toUpperCase(), property);
0615: XSLTUtils.addAttribute(model, "caps-type",
0616: CClassNameForElement.toUpperCase(), property);
0617:
0618: if (PrimitiveTypeFinder.isPrimitive(CClassNameForElement)) {
0619: XSLTUtils.addAttribute(model, "primitive", "yes",
0620: property);
0621: }
0622: //add an attribute that says the type is default
0623: if (isDefault(CClassNameForElement)) {
0624: XSLTUtils.addAttribute(model, "default", "yes",
0625: property);
0626: }
0627:
0628: if (typeMap.containsKey(metainf
0629: .getSchemaQNameForQName(name))) {
0630: XSLTUtils.addAttribute(model, "ours", "yes", property);
0631: }
0632:
0633: if (metainf.getAttributeStatusForQName(name)) {
0634: XSLTUtils.addAttribute(model, "attribute", "yes",
0635: property);
0636: } else {
0637: XSLTUtils.addAttribute(model, "notattribute", "yes",
0638: property);
0639: }
0640:
0641: if (metainf.isNillable(name)) {
0642: XSLTUtils.addAttribute(model, "nillable", "yes",
0643: property);
0644: }
0645:
0646: String shortTypeName;
0647: if (metainf.getSchemaQNameForQName(name) != null) {
0648: //see whether the QName is a basetype
0649: if (baseTypeMap.containsKey(metainf
0650: .getSchemaQNameForQName(name))) {
0651: shortTypeName = metainf
0652: .getSchemaQNameForQName(name)
0653: .getLocalPart();
0654: } else {
0655: shortTypeName = getShortTypeName(CClassNameForElement);
0656: }
0657: } else {
0658: shortTypeName = getShortTypeName(CClassNameForElement);
0659: }
0660: XSLTUtils.addAttribute(model, "shorttypename",
0661: shortTypeName, property);
0662:
0663: if (isInherited) {
0664: XSLTUtils.addAttribute(model, "inherited", "yes",
0665: property);
0666: }
0667:
0668: QName schemaQName = metainf.getSchemaQNameForQName(name);
0669: if (!schemaQName.getNamespaceURI().equals(
0670: name.getNamespaceURI())) {
0671: XSLTUtils.addAttribute(model, "child-nsuri",
0672: schemaQName.getNamespaceURI(), property);
0673: XSLTUtils.addAttribute(model, "child-nsprefix",
0674: getPrefixForURI(schemaQName.getNamespaceURI(),
0675: null), property);
0676:
0677: }
0678:
0679: if (metainf.getAnyStatusForQName(name)) {
0680: XSLTUtils.addAttribute(model, "any", "yes", property);
0681: }
0682:
0683: if (metainf.getBinaryStatusForQName(name)) {
0684: XSLTUtils
0685: .addAttribute(model, "binary", "yes", property);
0686: }
0687:
0688: if (metainf.getSimpleStatusForQName(name)) {
0689: XSLTUtils
0690: .addAttribute(model, "simple", "yes", property);
0691: }
0692:
0693: //put the min occurs count irrespective of whether it's an array or not
0694: long minOccurs = metainf.getMinOccurs(name);
0695: XSLTUtils.addAttribute(model, "minOccurs", minOccurs + "",
0696: property);
0697:
0698: if (metainf.getArrayStatusForQName(name)) {
0699: String attrName = name.getLocalPart();
0700: int arrayTokenStart = attrName.indexOf("Array");
0701: if (arrayTokenStart >= 0) {
0702: String arrayEle = attrName.substring(0,
0703: arrayTokenStart);
0704: XSLTUtils.addAttribute(model, "arrayele", arrayEle,
0705: property);
0706: }
0707: XSLTUtils.addAttribute(model, "isarray", "yes",
0708: property);
0709: XSLTUtils.addAttribute(model, "arrayBaseType",
0710: CClassNameForElement, property);
0711:
0712: long maxOccurs = metainf.getMaxOccurs(name);
0713: if (maxOccurs == Long.MAX_VALUE) {
0714: XSLTUtils.addAttribute(model, "unbound", "yes",
0715: property);
0716: }
0717: XSLTUtils.addAttribute(model, "maxOccurs", maxOccurs
0718: + "", property);
0719:
0720: }
0721:
0722: if ((parentMetaInf != null) && metainf.isRestriction()
0723: && missingQNames.contains(name)) {
0724: // this element details should be there with the parent meta Inf
0725: addAttributesToProperty(parentMetaInf, name, model,
0726: property, typeMap, CClassNameForElement);
0727:
0728: } else {
0729: addAttributesToProperty(metainf, name, model, property,
0730: typeMap, CClassNameForElement);
0731: }
0732: }
0733: }
0734:
0735: private void addAttributesToProperty(
0736: BeanWriterMetaInfoHolder metainf, QName name,
0737: Document model, Element property, Map typeMap,
0738: String javaClassNameForElement) {
0739: // add an attribute that says the type is default
0740: if (metainf.getDefaultStatusForQName(name)) {
0741: XSLTUtils.addAttribute(model, "default", "yes", property);
0742: }
0743:
0744: if (typeMap.containsKey(metainf.getSchemaQNameForQName(name))) {
0745: XSLTUtils.addAttribute(model, "ours", "yes", property);
0746: }
0747:
0748: if (metainf.getAttributeStatusForQName(name)) {
0749: XSLTUtils.addAttribute(model, "attribute", "yes", property);
0750: }
0751:
0752: if (metainf.isNillable(name)) {
0753: XSLTUtils.addAttribute(model, "nillable", "yes", property);
0754: }
0755:
0756: if (metainf.getOptionalAttributeStatusForQName(name)) {
0757: XSLTUtils.addAttribute(model, "optional", "yes", property);
0758: }
0759:
0760: String shortTypeName;
0761: if (metainf.getSchemaQNameForQName(name) != null) {
0762: // see whether the QName is a basetype
0763: if (baseTypeMap.containsKey(metainf
0764: .getSchemaQNameForQName(name))) {
0765: shortTypeName = metainf.getSchemaQNameForQName(name)
0766: .getLocalPart();
0767: } else {
0768: shortTypeName = getShortTypeName(javaClassNameForElement);
0769: }
0770: } else {
0771: shortTypeName = getShortTypeName(javaClassNameForElement);
0772: }
0773: XSLTUtils.addAttribute(model, "shorttypename", shortTypeName,
0774: property);
0775:
0776: if (metainf.getAnyStatusForQName(name)) {
0777: XSLTUtils.addAttribute(model, "any", "yes", property);
0778: }
0779:
0780: if (metainf.getBinaryStatusForQName(name)) {
0781: XSLTUtils.addAttribute(model, "binary", "yes", property);
0782: }
0783:
0784: if (metainf.isSimple() || metainf.getSimpleStatusForQName(name)) {
0785: XSLTUtils.addAttribute(model, "simple", "yes", property);
0786: }
0787:
0788: // put the min occurs count irrespective of whether it's an array or
0789: // not
0790: long minOccurs = metainf.getMinOccurs(name);
0791: XSLTUtils.addAttribute(model, "minOccurs", minOccurs + "",
0792: property);
0793:
0794: if (metainf.getArrayStatusForQName(name)) {
0795:
0796: XSLTUtils.addAttribute(model, "array", "yes", property);
0797:
0798: int endIndex = javaClassNameForElement.indexOf("[");
0799: if (endIndex >= 0) {
0800: XSLTUtils.addAttribute(model, "arrayBaseType",
0801: javaClassNameForElement.substring(0, endIndex),
0802: property);
0803: } else {
0804: XSLTUtils.addAttribute(model, "arrayBaseType",
0805: javaClassNameForElement, property);
0806: }
0807:
0808: long maxOccurs = metainf.getMaxOccurs(name);
0809: if (maxOccurs == Long.MAX_VALUE) {
0810: XSLTUtils.addAttribute(model, "unbound", "yes",
0811: property);
0812: } else {
0813: XSLTUtils.addAttribute(model, "maxOccurs", maxOccurs
0814: + "", property);
0815: }
0816: }
0817: if (metainf.isRestrictionBaseType(name)) {
0818: XSLTUtils.addAttribute(model, "restrictionBaseType", "yes",
0819: property);
0820: }
0821:
0822: if (metainf.isExtensionBaseType(name)) {
0823: XSLTUtils.addAttribute(model, "extensionBaseType", "yes",
0824: property);
0825: }
0826:
0827: if (metainf.isRestrictionBaseType(name)
0828: && metainf.getLengthFacet() != -1) {
0829: XSLTUtils.addAttribute(model, "lenFacet", metainf
0830: .getLengthFacet()
0831: + "", property);
0832: }
0833:
0834: if (metainf.isRestrictionBaseType(name)
0835: && metainf.getMaxLengthFacet() != -1) {
0836: XSLTUtils.addAttribute(model, "maxLenFacet", metainf
0837: .getMaxLengthFacet()
0838: + "", property);
0839: }
0840:
0841: if (metainf.isRestrictionBaseType(name)
0842: && metainf.getMinLengthFacet() != -1) {
0843: XSLTUtils.addAttribute(model, "minLenFacet", metainf
0844: .getMinLengthFacet()
0845: + "", property);
0846: }
0847:
0848: if (metainf.isRestrictionBaseType(name)
0849: && metainf.getMaxExclusiveFacet() != null) {
0850: XSLTUtils.addAttribute(model, "maxExFacet", metainf
0851: .getMaxExclusiveFacet()
0852: + "", property);
0853: }
0854:
0855: if (metainf.isRestrictionBaseType(name)
0856: && metainf.getMinExclusiveFacet() != null) {
0857: XSLTUtils.addAttribute(model, "minExFacet", metainf
0858: .getMinExclusiveFacet()
0859: + "", property);
0860: }
0861:
0862: if (metainf.isRestrictionBaseType(name)
0863: && metainf.getMaxInclusiveFacet() != null) {
0864: XSLTUtils.addAttribute(model, "maxInFacet", metainf
0865: .getMaxInclusiveFacet()
0866: + "", property);
0867: }
0868:
0869: if (metainf.isRestrictionBaseType(name)
0870: && metainf.getMinInclusiveFacet() != null) {
0871: XSLTUtils.addAttribute(model, "minInFacet", metainf
0872: .getMinInclusiveFacet()
0873: + "", property);
0874: }
0875:
0876: if (!metainf.getEnumFacet().isEmpty()) {
0877: boolean validJava = true; // Assume all enum values are valid ids
0878:
0879: Iterator iterator = metainf.getEnumFacet().iterator();
0880: // Walk the values looking for invalid ids
0881: while (iterator.hasNext()) {
0882: String value = (String) iterator.next();
0883: if (!JavaUtils.isJavaId(value)) {
0884: validJava = false;
0885: }
0886: }
0887:
0888: int id = 0;
0889: iterator = metainf.getEnumFacet().iterator();
0890: while (iterator.hasNext()) {
0891: Element enumFacet = XSLTUtils.addChildElement(model,
0892: "enumFacet", property);
0893: String attribValue = (String) iterator.next();
0894: XSLTUtils.addAttribute(model, "value", attribValue,
0895: enumFacet);
0896: if (validJava) {
0897: XSLTUtils.addAttribute(model, "id", attribValue,
0898: enumFacet);
0899: } else {
0900: id++;
0901: XSLTUtils.addAttribute(model, "id", "value" + id,
0902: enumFacet);
0903: }
0904: }
0905: }
0906:
0907: if (metainf.isRestrictionBaseType(name)
0908: && metainf.getPatternFacet() != null) {
0909: XSLTUtils.addAttribute(model, "patternFacet", metainf
0910: .getPatternFacet(), property);
0911: }
0912: }
0913:
0914: private void addMissingQNames(BeanWriterMetaInfoHolder metainf,
0915: ArrayList qName, ArrayList missingQNames) {
0916:
0917: QName[] qNames = null;
0918: QName[] pQNames = null;
0919:
0920: BeanWriterMetaInfoHolder parentMetaInf = metainf.getParent();
0921:
0922: if (metainf.isOrdered()) {
0923: qNames = metainf.getOrderedQNameArray();
0924: } else {
0925: qNames = metainf.getQNameArray();
0926: }
0927:
0928: if (parentMetaInf != null) {
0929: if (parentMetaInf.isOrdered()) {
0930: pQNames = parentMetaInf.getOrderedQNameArray();
0931: } else {
0932: pQNames = parentMetaInf.getQNameArray();
0933: }
0934: }
0935:
0936: for (int i = 0; pQNames != null && i < pQNames.length; i++) {
0937: if (qNameNotFound(pQNames[i], metainf)) {
0938: missingQNames.add(pQNames[i]);
0939: }
0940: }
0941: //adding missing QNames to the end of list.
0942: if (!missingQNames.isEmpty()) {
0943: for (int i = 0; i < missingQNames.size(); i++) {
0944: qName.add(missingQNames.get(i));
0945: }
0946: }
0947:
0948: }
0949:
0950: private boolean qNameNotFound(QName qname,
0951: BeanWriterMetaInfoHolder metainf) {
0952:
0953: boolean found = false;
0954: QName[] qNames;
0955:
0956: if (metainf.isOrdered()) {
0957: qNames = metainf.getOrderedQNameArray();
0958: } else {
0959: qNames = metainf.getQNameArray();
0960: }
0961:
0962: for (int j = 0; j < qNames.length; j++) {
0963: if (qname.getLocalPart().equals(qNames[j].getLocalPart())) {
0964: found = true;
0965: }
0966: }
0967: return !found;
0968: }
0969:
0970: /**
0971: * Test whether the given class name matches the default
0972: *
0973: * @param javaClassNameForElement
0974: * @return bool
0975: */
0976: private boolean isDefault(String javaClassNameForElement) {
0977: return getDefaultClassName().equals(javaClassNameForElement)
0978: || getDefaultClassArrayName().equals(
0979: javaClassNameForElement);
0980: }
0981:
0982: /**
0983: * Given the xml name, make a unique class name taking into account that some
0984: * file systems are case sensitive and some are not.
0985: * -Consider the Jax-WS spec for this
0986: *
0987: * @param listOfNames
0988: * @param xmlName
0989: * @return Returns String.
0990: */
0991: private String makeUniqueCStructName(List listOfNames,
0992: String xmlName) {
0993: String cName;
0994: if (CUtils.isCKeyword(xmlName)) {
0995: cName = CUtils.makeNonCKeyword(xmlName);
0996: } else {
0997: //javaName = JavaUtils.capitalizeFirstChar(JavaUtils.xmlNameToJava(xmlName));
0998: cName = xmlName;
0999: }
1000:
1001: while (listOfNames.contains(cName.toLowerCase())) {
1002: cName = cName + CStructWriter.count++;
1003: }
1004:
1005: String intName = cName.replace('.', '_');
1006: String outName = intName.replace('-', '_');
1007: listOfNames.add(outName.toLowerCase());
1008: return outName;
1009: }
1010:
1011: /**
1012: * A bit of code from the old code generator. We are better off using the template
1013: * engines and such stuff that's already there. But the class writers are hard to be
1014: * reused so some code needs to be repeated (atleast a bit)
1015: */
1016: private void loadTemplate() throws SchemaCompilationException {
1017:
1018: //first get the language specific property map
1019: Class clazz = this .getClass();
1020: InputStream xslStream;
1021: String templateName = javaBeanTemplateName;
1022: if (templateName != null) {
1023: try {
1024: String sourceTemplateName = templateName + "Source.xsl";
1025: xslStream = clazz
1026: .getResourceAsStream(sourceTemplateName);
1027: sourceTemplateCache = TransformerFactory.newInstance()
1028: .newTemplates(new StreamSource(xslStream));
1029:
1030: String headerTemplateName = templateName + "Header.xsl";
1031: xslStream = clazz
1032: .getResourceAsStream(headerTemplateName);
1033: headerTemplateCache = TransformerFactory.newInstance()
1034: .newTemplates(new StreamSource(xslStream));
1035:
1036: templateLoaded = true;
1037: } catch (TransformerConfigurationException e) {
1038: throw new SchemaCompilationException(
1039: SchemaCompilerMessages
1040: .getMessage("schema.templateLoadException"),
1041: e);
1042: }
1043: } else {
1044: throw new SchemaCompilationException(SchemaCompilerMessages
1045: .getMessage("schema.templateNotFoundException"));
1046: }
1047: }
1048:
1049: /**
1050: * Creates the output file
1051: *
1052: * @param fileName
1053: * @param extension
1054: * @throws Exception
1055: */
1056: protected File createOutFile(String fileName, String extension)
1057: throws Exception {
1058: return org.apache.axis2.util.FileWriter.createClassFile(
1059: this .rootDir, "", AXIS2_PREFIX + fileName, extension);
1060: }
1061:
1062: /**
1063: * Writes the output file
1064: *
1065: * @param doc
1066: * @param outputFile
1067: * @throws Exception
1068: */
1069: private void parseSource(Document doc, File outputFile)
1070: throws Exception {
1071: OutputStream outStream = new FileOutputStream(outputFile);
1072: XSLTTemplateProcessor.parse(outStream, doc,
1073: this .sourceTemplateCache.newTransformer());
1074: outStream.write('\n');
1075: outStream.write('\n');
1076: outStream.flush();
1077: outStream.close();
1078:
1079: }
1080:
1081: /**
1082: * Writes the output file
1083: *
1084: * @param doc
1085: * @param outputFile
1086: * @throws Exception
1087: */
1088: private void parseHeader(Document doc, File outputFile)
1089: throws Exception {
1090: OutputStream outStream = new FileOutputStream(outputFile);
1091: XSLTTemplateProcessor.parse(outStream, doc,
1092: this .headerTemplateCache.newTransformer());
1093: outStream.write('\n');
1094: outStream.write('\n');
1095: outStream.flush();
1096: outStream.close();
1097:
1098: }
1099:
1100: /**
1101: * Get a prefix for a namespace URI. This method will ALWAYS
1102: * return a valid prefix - if the given URI is already mapped in this
1103: * serialization, we return the previous prefix. If it is not mapped,
1104: * we will add a new mapping and return a generated prefix of the form
1105: * "ns<num>".
1106: *
1107: * @param uri is the namespace uri
1108: * @return Returns prefix.
1109: */
1110: public String getPrefixForURI(String uri) {
1111: return getPrefixForURI(uri, null);
1112: }
1113:
1114: /**
1115: * Last used index suffix for "ns"
1116: */
1117: private int lastPrefixIndex = 1;
1118:
1119: /**
1120: * Map of namespaces URI to prefix(es)
1121: */
1122: HashMap mapURItoPrefix = new HashMap();
1123: HashMap mapPrefixtoURI = new HashMap();
1124:
1125: /**
1126: * Get a prefix for the given namespace URI. If one has already been
1127: * defined in this serialization, use that. Otherwise, map the passed
1128: * default prefix to the URI, and return that. If a null default prefix
1129: * is passed, use one of the form "ns<num>"
1130: */
1131: public String getPrefixForURI(String uri, String defaultPrefix) {
1132: if ((uri == null) || (uri.length() == 0))
1133: return null;
1134: String prefix = (String) mapURItoPrefix.get(uri);
1135: if (prefix == null) {
1136: if (defaultPrefix == null || defaultPrefix.length() == 0) {
1137: prefix = "ns" + lastPrefixIndex++;
1138: while (mapPrefixtoURI.get(prefix) != null) {
1139: prefix = "ns" + lastPrefixIndex++;
1140: }
1141: } else {
1142: prefix = defaultPrefix;
1143: }
1144: mapPrefixtoURI.put(prefix, uri);
1145: mapURItoPrefix.put(uri, prefix);
1146: }
1147: return prefix;
1148: }
1149:
1150: private String getShortTypeName(String typeClassName) {
1151: if (typeClassName.endsWith("[]")) {
1152: typeClassName = typeClassName.substring(0, typeClassName
1153: .lastIndexOf("["));
1154: }
1155: return typeClassName;
1156:
1157: }
1158:
1159: /**
1160: * Keep unimplemented
1161: *
1162: * @param mapperPackageName
1163: * @see BeanWriter#registerExtensionMapperPackageName(String)
1164: */
1165: public void registerExtensionMapperPackageName(
1166: String mapperPackageName) {
1167: //unimplemented
1168: }
1169:
1170: /**
1171: * Keep unimplemented
1172: *
1173: * @param metainfArray
1174: * @see BeanWriter#writeExtensionMapper(org.apache.axis2.schema.BeanWriterMetaInfoHolder[])
1175: */
1176: public void writeExtensionMapper(
1177: BeanWriterMetaInfoHolder[] metainfArray)
1178: throws SchemaCompilationException {
1179: //unimplemented
1180: }
1181:
1182: /**
1183: * Keep unimplemented
1184: *
1185: * @see BeanWriter#getExtensionMapperPackageName()
1186: */
1187: public String getExtensionMapperPackageName() {
1188: return null;
1189: }
1190: }
|