| /* |
| * The Apache Software License, Version 1.1 |
| * |
| * |
| * Copyright (c) 2003 The Apache Software Foundation. All rights |
| * reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in |
| * the documentation and/or other materials provided with the |
| * distribution. |
| * |
| * 3. The end-user documentation included with the redistribution, |
| * if any, must include the following acknowledgment: |
| * "This product includes software developed by the |
| * Apache Software Foundation (http://www.apache.org/)." |
| * Alternately, this acknowledgment may appear in the software itself, |
| * if and wherever such third-party acknowledgments normally appear. |
| * |
| * 4. The names "Apache" and "Apache Software Foundation" must |
| * not be used to endorse or promote products derived from this |
| * software without prior written permission. For written |
| * permission, please contact apache@apache.org. |
| * |
| * 5. Products derived from this software may not be called "Apache |
| * XMLBeans", nor may "Apache" appear in their name, without prior |
| * written permission of the Apache Software Foundation. |
| * |
| * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
| * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR |
| * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
| * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
| * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
| * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT |
| * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
| * SUCH DAMAGE. |
| * ==================================================================== |
| * |
| * This software consists of voluntary contributions made by many |
| * individuals on behalf of the Apache Software Foundation and was |
| * originally based on software copyright (c) 2000-2003 BEA Systems |
| * Inc., <http://www.bea.com/>. For more information on the Apache Software |
| * Foundation, please see <http://www.apache.org/>. |
| */ |
| |
| package org.apache.xmlbeans.impl.schema; |
| |
| import org.apache.xmlbeans.impl.common.NameUtil; |
| import org.apache.xmlbeans.QNameSetBuilder; |
| import org.apache.xmlbeans.SchemaField; |
| import org.apache.xmlbeans.SchemaType; |
| import org.apache.xmlbeans.SchemaParticle; |
| import org.apache.xmlbeans.SchemaProperty; |
| import org.apache.xmlbeans.QNameSet; |
| import org.apache.xmlbeans.XmlAnySimpleType; |
| import org.apache.xmlbeans.SchemaStringEnumEntry; |
| import org.apache.xmlbeans.XmlByte; |
| import org.apache.xmlbeans.XmlShort; |
| |
| import java.util.*; |
| import java.math.BigInteger; |
| |
| import javax.xml.namespace.QName; |
| |
| public class StscJavaizer |
| { |
| /** |
| * Does a topo walk of all the types to resolve them. |
| */ |
| public static void javaizeAllTypes(boolean javaize) |
| { |
| StscState state = StscState.get(); |
| |
| List allSeenTypes = new ArrayList(); |
| allSeenTypes.addAll(Arrays.asList(state.documentTypes())); |
| allSeenTypes.addAll(Arrays.asList(state.attributeTypes())); |
| allSeenTypes.addAll(Arrays.asList(state.globalTypes())); |
| |
| // First distribute the global names among the top entities. |
| if (javaize) |
| assignGlobalJavaNames(allSeenTypes); |
| |
| // now fully javaize everything deeply. |
| for (int i = 0; i < allSeenTypes.size(); i++) |
| { |
| SchemaType gType = (SchemaType)allSeenTypes.get(i); |
| if (javaize) |
| { |
| javaizeType((SchemaTypeImpl)gType); |
| String className = gType.getFullJavaName(); |
| if (className != null) |
| state.addClassname(className.replace('$', '.'), gType); |
| } |
| else |
| skipJavaizingType((SchemaTypeImpl)gType); |
| allSeenTypes.addAll(Arrays.asList(gType.getAnonymousTypes())); |
| } |
| } |
| |
| static void assignGlobalJavaNames(Collection schemaTypes) |
| { |
| HashSet usedNames = new HashSet(); |
| StscState state = StscState.get(); |
| |
| for (Iterator i = schemaTypes.iterator(); i.hasNext(); ) |
| { |
| SchemaTypeImpl sImpl = (SchemaTypeImpl)i.next(); |
| QName topName = findTopName(sImpl); |
| String pickedName = state.getJavaname(topName); |
| if (sImpl.isUnjavaized()) |
| { |
| sImpl.setFullJavaName(pickFullJavaClassName(usedNames, findTopName(sImpl), pickedName, sImpl.isDocumentType(), sImpl.isAttributeType())); |
| sImpl.setFullJavaImplName(pickFullJavaImplName(usedNames, sImpl.getFullJavaName())); |
| } |
| } |
| } |
| |
| private static boolean isStringType(SchemaType type) |
| { |
| if (type == null || type.getSimpleVariety() != SchemaType.ATOMIC) |
| return false; |
| return (type.getPrimitiveType().getBuiltinTypeCode() == SchemaType.BTC_STRING); |
| } |
| |
| static String pickConstantName(Set usedNames, String words) |
| { |
| String base = NameUtil.upperCaseUnderbar(words); |
| |
| if (base.length() == 0) |
| { |
| base = "X"; |
| } |
| |
| if (base.startsWith("INT_")) // reserved for int codes |
| { |
| base = "X_" + base; |
| } |
| |
| String uniqName; |
| int index = 1; |
| for (uniqName = base; usedNames.contains(uniqName); ) |
| { |
| index++; |
| uniqName = base + "_" + index; |
| } |
| |
| usedNames.add(uniqName); |
| |
| return uniqName; |
| } |
| |
| static void skipJavaizingType(SchemaTypeImpl sImpl) |
| { |
| if (sImpl.isJavaized()) |
| return; |
| sImpl.startJavaizing(); |
| secondPassProcessType(sImpl); |
| sImpl.finishJavaizing(); |
| } |
| |
| static void secondPassProcessType(SchemaTypeImpl sImpl) |
| { |
| if (isStringType(sImpl)) |
| { |
| XmlAnySimpleType[] enumVals = sImpl.getEnumerationValues(); |
| |
| // if this is an enumerated string type, values are to be |
| // javaized as constants. |
| if (enumVals != null) |
| { |
| SchemaStringEnumEntry[] entryArray = new SchemaStringEnumEntry[enumVals.length]; |
| SchemaType basedOn = sImpl.getBaseEnumType(); |
| if (basedOn == sImpl) |
| { |
| Set usedNames = new HashSet(); |
| for (int i = 0; i < enumVals.length; i++) |
| { |
| String val = enumVals[i].getStringValue(); |
| |
| entryArray[i] = new SchemaStringEnumEntryImpl(val, i + 1, pickConstantName(usedNames, val)); |
| } |
| } |
| else |
| { |
| for (int i = 0; i < enumVals.length; i++) |
| { |
| String val = enumVals[i].getStringValue(); |
| entryArray[i] = basedOn.enumEntryForString(val); |
| } |
| } |
| sImpl.setStringEnumEntries(entryArray); |
| } |
| } |
| } |
| |
| static void javaizeType(SchemaTypeImpl sImpl) |
| { |
| if (sImpl.isJavaized()) |
| return; |
| |
| SchemaTypeImpl baseType = (SchemaTypeImpl)sImpl.getBaseType(); |
| if (baseType != null) |
| javaizeType(baseType); |
| |
| sImpl.startJavaizing(); |
| |
| sImpl.setCompiled(true); |
| |
| secondPassProcessType(sImpl); |
| |
| if (!sImpl.isSimpleType()) |
| { |
| SchemaProperty[] eltProps = sImpl.getElementProperties(); |
| SchemaProperty[] attrProps = sImpl.getAttributeProperties(); |
| |
| // element setters result from a computation |
| if (eltProps.length > 0) |
| assignJavaElementSetterModel(eltProps, sImpl.getContentModel()); |
| |
| // Handing out java names - this permits us to avoid collisions. |
| Set usedPropNames = new HashSet(); |
| |
| // Assign names in two passes: first inherited names, then others. |
| for (boolean doInherited = true; ; doInherited = false) |
| { |
| if (eltProps.length > 0) |
| assignJavaPropertyNames(usedPropNames, eltProps, baseType, doInherited); |
| |
| assignJavaPropertyNames(usedPropNames, attrProps, baseType, doInherited); |
| |
| if (doInherited == false) |
| break; |
| } |
| |
| SchemaProperty[] allprops = sImpl.getProperties(); |
| |
| // determine whether order insensitive |
| boolean insensitive = isPropertyModelOrderInsensitive(allprops); |
| |
| // Fill in the java type codes now. |
| // This depends on recursive type information, so it's done in typechecking |
| assignJavaTypeCodes(allprops); |
| |
| sImpl.setOrderSensitive(!insensitive); |
| } |
| |
| // assign java type names to anonymous types |
| assignJavaAnonymousTypeNames(sImpl); |
| |
| sImpl.finishJavaizing(); |
| } |
| |
| static void assignJavaAnonymousTypeNames(SchemaTypeImpl outerType) |
| { |
| Set usedTypeNames = new HashSet(); |
| SchemaType[] anonymousTypes = outerType.getAnonymousTypes(); |
| StscState state = StscState.get(); |
| |
| // Because we generate nested java interfaces, and nested |
| // interface names must not be the same as an ancestor, use up |
| // the ancestors |
| |
| for ( SchemaType scanOuterType = outerType ; |
| scanOuterType != null ; |
| scanOuterType = scanOuterType.getOuterType() ) |
| { |
| usedTypeNames.add( scanOuterType.getShortJavaName() ); |
| } |
| |
| for ( SchemaType scanOuterType = outerType ; |
| scanOuterType != null ; |
| scanOuterType = scanOuterType.getOuterType() ) |
| { |
| usedTypeNames.add( scanOuterType.getShortJavaImplName() ); |
| } |
| |
| // and because things are problematic if an inner type name |
| // is the same as a top-level package name, also get rid of that |
| // collision |
| usedTypeNames.add(getOutermostPackage(outerType.getFullJavaName())); |
| |
| // assign names |
| for (int i = 0; i < anonymousTypes.length; i++) |
| { |
| SchemaTypeImpl sImpl = (SchemaTypeImpl)anonymousTypes[i]; |
| if (sImpl == null) // already handled in first pass |
| continue; |
| if (sImpl.isSkippedAnonymousType()) |
| continue; |
| String localname = null; |
| String javaname = null; |
| |
| SchemaField containerField = sImpl.getContainerField(); |
| if (containerField != null) |
| { |
| QName qname = sImpl.getContainerField().getName(); |
| localname = qname.getLocalPart(); |
| javaname = state.getJavaname(sImpl.getContainerField().getName()); |
| } |
| else |
| { |
| // not defined inside an Elt or Attr: must be a nested simple type |
| switch (sImpl.getOuterType().getSimpleVariety()) |
| { |
| case SchemaType.UNION: |
| javaname = "Member"; break; |
| case SchemaType.LIST: |
| javaname = "Item"; break; |
| case SchemaType.ATOMIC: |
| default: |
| assert(false) : "Weird type " + sImpl.toString(); |
| javaname = "Base"; break; |
| } |
| } |
| sImpl.setShortJavaName( |
| pickInnerJavaClassName(usedTypeNames, localname, javaname)); |
| sImpl.setShortJavaImplName( |
| pickInnerJavaImplName(usedTypeNames, localname, javaname == null ? null : javaname + "Impl")); |
| } |
| } |
| |
| /** |
| * Used to compute the setter model. |
| * |
| * Returns the set of all QNames of elements that could possibly be |
| * contained in the given contentModel. The state variable is used |
| * to record the results, so that if they are needed again later, |
| * they do not need to be recomputed. |
| */ |
| static QNameSet computeAllContainedElements(SchemaParticle contentModel, Map state) |
| { |
| // Remember previously computed results to avoid complexity explosion |
| QNameSet result = (QNameSet)state.get(contentModel); |
| if (result != null) |
| return result; |
| |
| QNameSetBuilder builder; |
| |
| switch (contentModel.getParticleType()) |
| { |
| case SchemaParticle.ALL: |
| case SchemaParticle.CHOICE: |
| case SchemaParticle.SEQUENCE: |
| default: |
| builder = new QNameSetBuilder(); |
| for (int i = 0; i < contentModel.countOfParticleChild(); i++) |
| { |
| builder.addAll(computeAllContainedElements(contentModel.getParticleChild(i), state)); |
| } |
| result = builder.toQNameSet(); |
| break; |
| |
| case SchemaParticle.WILDCARD: |
| result = contentModel.getWildcardSet(); |
| break; |
| |
| case SchemaParticle.ELEMENT: |
| result = QNameSet.singleton(contentModel.getName()); |
| break; |
| } |
| state.put(contentModel, result); |
| return result; |
| } |
| |
| /** |
| * Used to compute setter model. |
| * |
| * Returns the QNameSet of all elements that can possibly come before an |
| * element whose name is given by the target in a valid instance of the |
| * contentModel. When appending an element, it comes before the first |
| * one that is not in this set. |
| */ |
| static QNameSet computeNondelimitingElements(QName target, SchemaParticle contentModel, Map state) |
| { |
| QNameSet allContents = computeAllContainedElements(contentModel, state); |
| if (!allContents.contains(target)) |
| return QNameSet.EMPTY; |
| |
| // If iterated, then all contents are delimiting. |
| if (contentModel.getMaxOccurs() == null || |
| contentModel.getMaxOccurs().compareTo(BigInteger.ONE) > 0) |
| return allContents; |
| |
| QNameSetBuilder builder; |
| |
| switch (contentModel.getParticleType()) |
| { |
| case SchemaParticle.ALL: |
| case SchemaParticle.ELEMENT: |
| default: |
| return allContents; |
| |
| case SchemaParticle.WILDCARD: |
| return QNameSet.singleton(target); |
| |
| case SchemaParticle.CHOICE: |
| builder = new QNameSetBuilder(); |
| for (int i = 0; i < contentModel.countOfParticleChild(); i++) |
| { |
| QNameSet childContents = computeAllContainedElements(contentModel.getParticleChild(i), state); |
| if (childContents.contains(target)) |
| builder.addAll(computeNondelimitingElements(target, contentModel.getParticleChild(i), state)); |
| } |
| return builder.toQNameSet(); |
| |
| case SchemaParticle.SEQUENCE: |
| builder = new QNameSetBuilder(); |
| boolean seenTarget = false; |
| for (int i = contentModel.countOfParticleChild(); i > 0; ) |
| { |
| i--; |
| QNameSet childContents = computeAllContainedElements(contentModel.getParticleChild(i), state); |
| if (seenTarget) |
| { |
| builder.addAll(childContents); |
| } |
| else if (childContents.contains(target)) |
| { |
| builder.addAll(computeAllContainedElements(contentModel.getParticleChild(i), state)); |
| seenTarget = true; |
| } |
| } |
| return builder.toQNameSet(); |
| } |
| } |
| |
| static void assignJavaElementSetterModel(SchemaProperty[] eltProps, SchemaParticle contentModel) |
| { |
| // To compute the element setter model, we need to compute the |
| // delimiting elements for each element. |
| |
| Map state = new HashMap(); |
| QNameSet allContents = computeAllContainedElements(contentModel, state); |
| |
| for (int i = 0; i < eltProps.length; i++) |
| { |
| SchemaPropertyImpl sImpl = (SchemaPropertyImpl)eltProps[i]; |
| QNameSet nde = computeNondelimitingElements(sImpl.getName(), contentModel, state); |
| QNameSetBuilder builder = new QNameSetBuilder(allContents); |
| builder.removeAll(nde); |
| sImpl.setJavaSetterDelimiter(builder.toQNameSet()); |
| } |
| } |
| |
| static void assignJavaPropertyNames(Set usedNames, SchemaProperty[] props, SchemaType baseType, boolean doInherited) |
| { |
| StscState state = StscState.get(); |
| |
| // two passes: first deal with inherited properties, then with new ones. |
| // this ensures that we match up with base class definitions cleanly |
| |
| for (int i = 0; i < props.length; i++) |
| { |
| SchemaPropertyImpl sImpl = (SchemaPropertyImpl)props[i]; |
| |
| SchemaProperty baseProp = |
| (sImpl.isAttribute() ? |
| baseType.getAttributeProperty(sImpl.getName()) : |
| baseType.getElementProperty(sImpl.getName())); |
| |
| if ((baseProp != null) != doInherited) |
| continue; |
| |
| QName propQName = sImpl.getName(); |
| |
| String theName; |
| |
| if (baseProp == null) |
| theName = pickJavaPropertyName(usedNames, propQName.getLocalPart(), state.getJavaname(propQName)); |
| else |
| { |
| theName = baseProp.getJavaPropertyName(); |
| assert(!usedNames.contains(theName)); |
| usedNames.add(theName); |
| } |
| |
| sImpl.setJavaPropertyName(theName); |
| |
| boolean isArray = (sImpl.getMaxOccurs() == null || |
| sImpl.getMaxOccurs().compareTo(BigInteger.ONE) > 0); |
| boolean isSingleton = !isArray && (sImpl.getMaxOccurs().signum() > 0); |
| boolean isOption = isSingleton && (sImpl.getMinOccurs().signum() == 0); |
| SchemaType javaBasedOnType = sImpl.getType(); |
| |
| if (baseProp != null) |
| { |
| if (baseProp.extendsJavaArray()) |
| { |
| isSingleton = false; |
| isOption = false; |
| isArray = true; |
| } |
| if (baseProp.extendsJavaSingleton()) |
| { |
| isSingleton = true; |
| } |
| if (baseProp.extendsJavaOption()) |
| { |
| isOption = true; |
| } |
| javaBasedOnType = baseProp.javaBasedOnType(); |
| } |
| |
| sImpl.setExtendsJava(javaBasedOnType.getRef(), isSingleton, isOption, isArray); |
| } |
| |
| } |
| |
| static void assignJavaTypeCodes(SchemaProperty[] properties) |
| { |
| for (int i = 0; i < properties.length; i++) |
| { |
| SchemaPropertyImpl sImpl = (SchemaPropertyImpl)properties[i]; |
| SchemaType sType = sImpl.javaBasedOnType(); |
| sImpl.setJavaTypeCode(javaTypeCodeForType(sType)); |
| } |
| } |
| |
| static int javaTypeCodeInCommon(SchemaType[] types) |
| { |
| if (types == null || types.length == 0) |
| return SchemaProperty.XML_OBJECT; |
| |
| int code = javaTypeCodeForType(types[0]); |
| if (code == SchemaProperty.JAVA_OBJECT) |
| return code; |
| for (int i = 1; i < types.length; i++) |
| { |
| // if any two are different, the answer is java.lang.Object |
| if (code != javaTypeCodeForType(types[i])) |
| return SchemaProperty.JAVA_OBJECT; |
| } |
| return code; |
| } |
| |
| static int javaTypeCodeForType(SchemaType sType) |
| { |
| if (!sType.isSimpleType()) |
| return SchemaProperty.XML_OBJECT; |
| |
| if (sType.getSimpleVariety() == SchemaType.UNION) |
| { |
| // see if we can find an interesting common base type, e.g., for string enums |
| SchemaType baseType = sType.getUnionCommonBaseType(); |
| if (baseType != null && !baseType.isURType()) |
| sType = baseType; |
| else |
| return javaTypeCodeInCommon(sType.getUnionConstituentTypes()); |
| } |
| |
| if (sType.getSimpleVariety() == SchemaType.LIST) |
| return SchemaProperty.JAVA_LIST; |
| |
| if (sType.isURType()) |
| return SchemaProperty.XML_OBJECT; |
| |
| switch (sType.getPrimitiveType().getBuiltinTypeCode()) |
| { |
| case SchemaType.BTC_ANY_SIMPLE: |
| // return SchemaProperty.XML_OBJECT; |
| return SchemaProperty.JAVA_STRING; |
| |
| case SchemaType.BTC_BOOLEAN: |
| return SchemaProperty.JAVA_BOOLEAN; |
| |
| case SchemaType.BTC_BASE_64_BINARY: |
| return SchemaProperty.JAVA_BYTE_ARRAY; |
| |
| case SchemaType.BTC_HEX_BINARY: |
| return SchemaProperty.JAVA_BYTE_ARRAY; |
| |
| case SchemaType.BTC_ANY_URI: |
| return SchemaProperty.JAVA_STRING; |
| |
| case SchemaType.BTC_QNAME: |
| return SchemaProperty.JAVA_QNAME; |
| |
| case SchemaType.BTC_NOTATION: |
| return SchemaProperty.XML_OBJECT; |
| |
| case SchemaType.BTC_FLOAT: |
| return SchemaProperty.JAVA_FLOAT; |
| |
| case SchemaType.BTC_DOUBLE: |
| return SchemaProperty.JAVA_DOUBLE; |
| |
| case SchemaType.BTC_DECIMAL: |
| switch (sType.getDecimalSize()) |
| { |
| case SchemaType.SIZE_BYTE: |
| return SchemaProperty.JAVA_BYTE; |
| case SchemaType.SIZE_SHORT: |
| return SchemaProperty.JAVA_SHORT; |
| case SchemaType.SIZE_INT: |
| return SchemaProperty.JAVA_INT; |
| case SchemaType.SIZE_LONG: |
| return SchemaProperty.JAVA_LONG; |
| case SchemaType.SIZE_BIG_INTEGER: |
| return SchemaProperty.JAVA_BIG_INTEGER; |
| case SchemaType.SIZE_BIG_DECIMAL: |
| default: |
| return SchemaProperty.JAVA_BIG_DECIMAL; |
| } |
| |
| case SchemaType.BTC_STRING: |
| if (isStringType(sType.getBaseEnumType())) |
| return SchemaProperty.JAVA_ENUM; |
| return SchemaProperty.JAVA_STRING; |
| |
| case SchemaType.BTC_DURATION: |
| return SchemaProperty.JAVA_GDURATION; |
| |
| case SchemaType.BTC_DATE_TIME: |
| case SchemaType.BTC_DATE: |
| // return SchemaProperty.JAVA_DATE; // converted to calendar |
| |
| case SchemaType.BTC_TIME: |
| case SchemaType.BTC_G_YEAR_MONTH: |
| case SchemaType.BTC_G_YEAR: |
| case SchemaType.BTC_G_MONTH_DAY: |
| case SchemaType.BTC_G_DAY: |
| case SchemaType.BTC_G_MONTH: |
| // return SchemaProperty.JAVA_GDATE; // converted to calendar (JAX-B) |
| return SchemaProperty.JAVA_CALENDAR; |
| |
| default: |
| assert(false) : "unrecognized code " + sType.getPrimitiveType().getBuiltinTypeCode(); |
| throw new IllegalStateException("unrecognized code " + sType.getPrimitiveType().getBuiltinTypeCode() + " of " + sType.getPrimitiveType().getName()); |
| } |
| } |
| |
| static boolean isPropertyModelOrderInsensitive(SchemaProperty[] properties) |
| { |
| for (int i = 0; i < properties.length; i++) |
| { |
| SchemaProperty prop = properties[i]; |
| if (prop.hasNillable() == SchemaProperty.VARIABLE) |
| return false; |
| if (prop.hasDefault() == SchemaProperty.VARIABLE) |
| return false; |
| if (prop.hasFixed() == SchemaProperty.VARIABLE) |
| return false; |
| if (prop.hasDefault() != SchemaProperty.NEVER && |
| prop.getDefaultText() == null) |
| return false; |
| } |
| return true; |
| } |
| |
| static boolean protectReservedGlobalClassNames(String name) |
| { |
| int i = name.lastIndexOf('.'); |
| String lastSegment = name.substring(i + 1); |
| if (lastSegment.endsWith("Document") && !lastSegment.equals("Document")) |
| return true; |
| return false; |
| } |
| |
| static boolean protectReservedInnerClassNames(String name) |
| { |
| return (name.equals("Enum") || name.equals("Factory")); |
| } |
| |
| static String[] PROTECTED_PROPERTIES = { |
| "StringValue", |
| "BooleanValue", |
| "ByteValue", |
| "ShortValue", |
| "IntValue", |
| "LongValue", |
| "BigIntegerValue", |
| "BigDecimalValue", |
| "FloatValue", |
| "DoubleValue", |
| "ByteArrayValue", |
| "EnumValue", |
| "CalendarValue", |
| "DateValue", |
| "GDateValue", |
| "GDurationValue", |
| "QNameValue", |
| "ListValue", |
| "ObjectValue", |
| "Class", |
| }; |
| static Set PROTECTED_PROPERTIES_SET = new HashSet(Arrays.asList(PROTECTED_PROPERTIES)); |
| |
| static boolean protectReservedPropertyNames(String name) |
| { |
| return PROTECTED_PROPERTIES_SET.contains(name) || |
| (name.endsWith("Array") && !name.equals("Array")); |
| } |
| |
| static String pickFullJavaClassName(Set usedNames, QName qName, String configname, boolean isDocument, boolean isAttrType) |
| { |
| String base; |
| boolean protect; |
| |
| if (configname != null && configname.indexOf('.') >= 0) |
| { |
| // a configname with dots defines the fully qualified java class name |
| base = configname; |
| protect = protectReservedGlobalClassNames(base); |
| } |
| else |
| { |
| StscState state = StscState.get(); |
| String uri = qName.getNamespaceURI(); |
| |
| base = NameUtil.getClassNameFromQName(qName); |
| |
| // Check to see if we have a mapping from namespace URI to Java package |
| // name. If so, apply the mapped package prefix at the beginning of |
| // the base name |
| |
| String pkgPrefix = state.getPackageOverride(uri); |
| |
| if (pkgPrefix != null) |
| { |
| // Form the new qualified class name from the new package name |
| // and the old class name |
| base = pkgPrefix + "." + base.substring(base.lastIndexOf('.') + 1); |
| } |
| |
| // See if there is a prefix... |
| String javaPrefix = state.getJavaPrefix(uri); |
| if (javaPrefix != null) |
| base = base.substring(0, base.lastIndexOf('.') + 1) + javaPrefix + base.substring(base.lastIndexOf('.') + 1); |
| |
| // a configname without dots may override the shortname part. |
| if (configname != null) |
| { |
| base = base.substring(0, base.lastIndexOf('.') + 1) + configname; |
| } |
| |
| protect = protectReservedGlobalClassNames(base); |
| if (configname == null) |
| { |
| // add special suffix |
| if (isDocument) |
| base = base + "Document"; |
| else if (isAttrType) |
| base = base + "Attribute"; |
| |
| // add configured suffix |
| String javaSuffix = state.getJavaSuffix(uri); |
| if (javaSuffix != null) |
| base = base + javaSuffix; |
| } |
| } |
| |
| String outermostPkg = getOutermostPackage(base); |
| |
| int index = 1; |
| String uniqName; |
| if (protect) |
| uniqName = base + index; |
| else |
| uniqName = base; |
| while (usedNames.contains(uniqName.toLowerCase()) || uniqName.equals(outermostPkg)) |
| { |
| index++; |
| uniqName = base + index; |
| } |
| |
| usedNames.add(uniqName.toLowerCase()); |
| |
| return uniqName; |
| } |
| |
| static String getOutermostPackage(String fqcn) |
| { |
| if (fqcn == null) |
| return ""; |
| |
| // remove class name |
| int lastdot = fqcn.indexOf('.'); |
| if (lastdot < 0) |
| return ""; |
| |
| // remove outer package names |
| return fqcn.substring(0, lastdot); |
| } |
| |
| static String pickFullJavaImplName(Set usedNames, String intfName) |
| { |
| // Strip off the package from the class name so we can replace it |
| String className = intfName; |
| String pkgName = null; |
| int index = intfName.lastIndexOf('.'); |
| if (index >= 0) |
| { |
| className = intfName.substring(index + 1); |
| pkgName = intfName.substring(0, index); |
| } |
| |
| // Form the new qualified class name from the new package name |
| // and the old class name |
| String base = pkgName + ".impl." + className + "Impl"; |
| |
| index = 1; |
| String uniqName = base; |
| while (usedNames.contains(uniqName.toLowerCase())) |
| { |
| index++; |
| uniqName = base + index; |
| } |
| |
| usedNames.add(uniqName.toLowerCase()); |
| |
| return uniqName; |
| } |
| |
| static String pickJavaPropertyName(Set usedNames, String localName, String javaName) |
| { |
| if (javaName == null) |
| javaName = NameUtil.upperCamelCase(localName); |
| boolean protect = protectReservedPropertyNames(javaName); |
| String uniqName; |
| int index = 1; |
| if (protect) |
| uniqName = javaName + index; |
| else |
| uniqName = javaName; |
| while (usedNames.contains(uniqName)) |
| { |
| index++; |
| uniqName = javaName + index; |
| } |
| |
| usedNames.add(uniqName); |
| |
| return uniqName; |
| } |
| |
| static String pickInnerJavaClassName(Set usedNames, String localName, String javaName) |
| { |
| if (javaName == null) |
| javaName = NameUtil.upperCamelCase(localName); |
| boolean protect = protectReservedInnerClassNames(javaName); |
| String uniqName; |
| int index = 1; |
| if (protect) |
| uniqName = javaName + index; |
| else |
| uniqName = javaName; |
| while (usedNames.contains(uniqName)) |
| { |
| index++; |
| uniqName = javaName + index; |
| } |
| |
| usedNames.add(uniqName); |
| |
| return uniqName; |
| } |
| |
| static String pickInnerJavaImplName(Set usedNames, String localName, String javaName) |
| { |
| if (javaName == null) |
| javaName = NameUtil.upperCamelCase(localName) + "Impl"; |
| String uniqName = javaName; |
| int index = 1; |
| while (usedNames.contains(uniqName)) |
| { |
| index++; |
| uniqName = javaName + index; |
| } |
| |
| usedNames.add(uniqName); |
| |
| return uniqName; |
| } |
| |
| static QName findTopName(SchemaType sType) |
| { |
| if (sType.getName() != null) |
| return sType.getName(); |
| |
| if (sType.isDocumentType()) |
| { |
| // A document type must have a content model consisting of a single elt |
| if (sType.getContentModel() == null || sType.getContentModel().getParticleType() != SchemaParticle.ELEMENT) |
| throw new IllegalStateException(); |
| return (sType.getDocumentElementName()); |
| } |
| |
| if (sType.isAttributeType()) |
| { |
| if (sType.getAttributeModel() == null || sType.getAttributeModel().getAttributes().length != 1) |
| throw new IllegalStateException(); |
| return sType.getAttributeTypeAttributeName(); |
| } |
| |
| SchemaField sElt = sType.getContainerField(); |
| assert(sElt != null); |
| assert(sType.getOuterType() == null); |
| return sElt.getName(); |
| } |
| |
| } |