blob: 7b120d6d9c02e483e01db29f6690b0810888fa8e [file] [log] [blame]
/*
* 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;
SchemaTypeImpl baseType = (SchemaTypeImpl)sImpl.getBaseType();
if (baseType != null)
skipJavaizingType(baseType);
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();
}
}