blob: 904edca8bde911b4f863fb8e740db887222abc02 [file] [log] [blame]
/* Copyright 2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.xmlbeans.impl.schema;
import org.apache.xmlbeans.*;
import org.apache.xmlbeans.impl.common.QNameHelper;
import org.apache.xmlbeans.impl.values.*;
import javax.xml.namespace.QName;
import java.lang.reflect.Constructor;
import java.math.BigInteger;
import java.util.*;
public final class SchemaTypeImpl implements SchemaType, TypeStoreUserFactory {
// global types have names
private QName _name;
// annotation on the type
private SchemaAnnotation _annotation;
// compilation support
private int _resolvePhase;
private static final int UNRESOLVED = 0;
private static final int RESOLVING_SGS = 1; // For document types only
private static final int RESOLVED_SGS = 2; // For document types only
private static final int RESOLVING = 3;
private static final int RESOLVED = 4;
private static final int JAVAIZING = 5;
private static final int JAVAIZED = 6;
// anonymous type support
private SchemaType.Ref _outerSchemaTypeRef;
private volatile SchemaComponent.Ref _containerFieldRef;
private volatile SchemaField _containerField;
private volatile int _containerFieldCode;
private volatile int _containerFieldIndex;
private volatile QName[] _groupReferenceContext;
private SchemaType.Ref[] _anonymousTyperefs;
private boolean _isDocumentType;
private boolean _isAttributeType;
// private boolean _skippedAnonymousType;
// compiletime java type support
private boolean _isCompiled;
private String _shortJavaName;
private String _fullJavaName;
private String _shortJavaImplName;
private String _fullJavaImplName;
private InterfaceExtension[] _interfaces;
private PrePostExtension _prepost;
// runtime java type support: volatile because they're cached
private volatile Class<? extends XmlObject> _javaClass;
private volatile Class<? extends StringEnumAbstractBase> _javaEnumClass;
private volatile Class<? extends XmlObjectBase> _javaImplClass;
private volatile Constructor<? extends XmlObjectBase> _javaImplConstructor;
private volatile Constructor<? extends XmlObjectBase> _javaImplConstructor2;
private volatile boolean _implNotAvailable;
// user data objects not persisted
private volatile Object _userData;
private final Object[] _ctrArgs = new Object[]{this};
// reflective support
private SchemaContainer _container;
private String _filename;
// complex content support
private SchemaParticle _contentModel;
private volatile SchemaLocalElement[] _localElts; // lazily computed
private volatile Map<SchemaLocalElement, Integer> _eltToIndexMap; // lazily computed
private volatile Map<SchemaLocalAttribute, Integer> _attrToIndexMap; // lazily computed
private Map<QName, SchemaProperty> _propertyModelByElementName;
private Map<QName, SchemaProperty> _propertyModelByAttributeName;
private boolean _hasAllContent;
private boolean _orderSensitive;
private QNameSet _typedWildcardElements;
private QNameSet _typedWildcardAttributes;
private boolean _hasWildcardElements;
private boolean _hasWildcardAttributes;
// set of valid QNames that can be substituted for a property
private Set<QName> _validSubstitutions = Collections.emptySet();
// simple content support
private int _complexTypeVariety;
private SchemaAttributeModel _attributeModel;
// simple type support
private int _builtinTypeCode;
private int _simpleTypeVariety;
private boolean _isSimpleType;
private SchemaType.Ref _baseTyperef; // via restriction or extension
private int _baseDepth; // how many inheritance steps to AnyType
private int _derivationType;
// user type support
private String _userTypeName;
private String _userTypeHandler;
// for complex types with simple content
private SchemaType.Ref _contentBasedOnTyperef;
// facets
private XmlValueRef[] _facetArray;
private boolean[] _fixedFacetArray;
// fundamental facets
private int _ordered;
private boolean _isFinite;
private boolean _isBounded;
private boolean _isNumeric;
private boolean _abs;
private boolean _finalExt;
private boolean _finalRest;
private boolean _finalList;
private boolean _finalUnion;
private boolean _blockExt;
private boolean _blockRest;
// whitespace facet
private int _whiteSpaceRule;
// regex patterns
private boolean _hasPatterns; // also takes into account base classes
private org.apache.xmlbeans.impl.regex.RegularExpression[] _patterns;
// enumerated values
private XmlValueRef[] _enumerationValues;
private SchemaType.Ref _baseEnumTyperef;
private boolean _stringEnumEnsured;
private volatile Map<String, StringEnumAbstractBase> _lookupStringEnum;
private volatile List<StringEnumAbstractBase> _listOfStringEnum;
private volatile Map<String, SchemaStringEnumEntry> _lookupStringEnumEntry;
private SchemaStringEnumEntry[] _stringEnumEntries;
// for lists only
private SchemaType.Ref _listItemTyperef;
// for unions only
private boolean _isUnionOfLists;
private SchemaType.Ref[] _unionMemberTyperefs;
private int _anonymousUnionMemberOrdinal;
private volatile SchemaType[] _unionConstituentTypes;
private volatile SchemaType[] _unionSubTypes;
private volatile SchemaType _unionCommonBaseType;
// for atomic types only
private SchemaType.Ref _primitiveTypeRef;
// for decimal restrictions only
private int _decimalSize;
// lazy loading support
private volatile boolean _unloaded;
// for document types only - only valid during compilation
private QName _sg;
private final List<QName> _sgMembers = new ArrayList<>();
public boolean isUnloaded() {
return _unloaded;
}
public void finishLoading() {
_unloaded = false;
}
SchemaTypeImpl(SchemaContainer container) {
_container = container;
}
SchemaTypeImpl(SchemaContainer container, boolean unloaded) {
_container = container;
_unloaded = unloaded;
if (unloaded) {
finishQuick();
}
}
public boolean isSGResolved() {
return _resolvePhase >= RESOLVED_SGS;
}
public boolean isSGResolving() {
return _resolvePhase >= RESOLVING_SGS;
}
public boolean isResolved() {
return _resolvePhase >= RESOLVED;
}
public boolean isResolving() {
return _resolvePhase == RESOLVING;
}
public boolean isUnjavaized() {
return _resolvePhase < JAVAIZED;
}
public boolean isJavaized() {
return _resolvePhase == JAVAIZED;
}
public void startResolvingSGs() {
if (_resolvePhase != UNRESOLVED) {
throw new IllegalStateException();
}
_resolvePhase = RESOLVING_SGS;
}
public void finishResolvingSGs() {
if (_resolvePhase != RESOLVING_SGS) {
throw new IllegalStateException();
}
_resolvePhase = RESOLVED_SGS;
}
public void startResolving() {
if ((_isDocumentType && _resolvePhase != RESOLVED_SGS) ||
(!_isDocumentType && _resolvePhase != UNRESOLVED)) {
throw new IllegalStateException();
}
_resolvePhase = RESOLVING;
}
public void finishResolving() {
if (_resolvePhase != RESOLVING) {
throw new IllegalStateException();
}
_resolvePhase = RESOLVED;
}
public void startJavaizing() {
if (_resolvePhase != RESOLVED) {
throw new IllegalStateException();
}
_resolvePhase = JAVAIZING;
}
public void finishJavaizing() {
if (_resolvePhase != JAVAIZING) {
throw new IllegalStateException();
}
_resolvePhase = JAVAIZED;
}
private void finishQuick() {
_resolvePhase = JAVAIZED;
}
private void assertUnresolved() {
if (_resolvePhase != UNRESOLVED && !_unloaded) {
throw new IllegalStateException();
}
}
private void assertSGResolving() {
if (_resolvePhase != RESOLVING_SGS && !_unloaded) {
throw new IllegalStateException();
}
}
private void assertSGResolved() {
if (_resolvePhase != RESOLVED_SGS && !_unloaded) {
throw new IllegalStateException();
}
}
private void assertResolving() {
if (_resolvePhase != RESOLVING && !_unloaded) {
throw new IllegalStateException();
}
}
private void assertResolved() {
if (_resolvePhase != RESOLVED && !_unloaded) {
throw new IllegalStateException();
}
}
private void assertJavaizing() {
if (_resolvePhase != JAVAIZING && !_unloaded) {
throw new IllegalStateException();
}
}
public QName getName() {
return _name;
}
public void setName(QName name) {
assertUnresolved();
_name = name;
}
public String getSourceName() {
if (_filename != null) {
return _filename;
}
if (getOuterType() != null) {
return getOuterType().getSourceName();
}
SchemaField field = getContainerField();
if (field != null) {
if (field instanceof SchemaGlobalElement) {
return ((SchemaGlobalElement) field).getSourceName();
}
if (field instanceof SchemaGlobalAttribute) {
return ((SchemaGlobalAttribute) field).getSourceName();
}
}
return null;
}
public void setFilename(String filename) {
assertUnresolved();
_filename = filename;
}
public int getComponentType() {
return SchemaComponent.TYPE;
}
public boolean isAnonymousType() {
return _name == null;
}
public boolean isDocumentType() {
return _isDocumentType;
}
public boolean isAttributeType() {
return _isAttributeType;
}
public QName getDocumentElementName() {
if (_isDocumentType) {
SchemaParticle sp = getContentModel();
if (sp != null) {
return sp.getName();
}
}
return null;
}
public QName getAttributeTypeAttributeName() {
if (_isAttributeType) {
SchemaAttributeModel sam = getAttributeModel();
if (sam != null) {
SchemaLocalAttribute[] slaArray = sam.getAttributes();
if (slaArray != null && slaArray.length > 0) {
SchemaLocalAttribute sla = slaArray[0];
return sla.getName();
}
}
}
return null;
}
public void setAnnotation(SchemaAnnotation ann) {
assertUnresolved();
_annotation = ann;
}
public SchemaAnnotation getAnnotation() {
return _annotation;
}
public void setDocumentType(boolean isDocument) {
assertUnresolved();
_isDocumentType = isDocument;
}
public void setAttributeType(boolean isAttribute) {
assertUnresolved();
_isAttributeType = isAttribute;
}
public int getContentType() {
return _complexTypeVariety;
}
public void setComplexTypeVariety(int complexTypeVariety) {
assertResolving();
_complexTypeVariety = complexTypeVariety;
}
public SchemaTypeElementSequencer getElementSequencer() {
if (_complexTypeVariety == NOT_COMPLEX_TYPE) {
return new SequencerImpl(null);
}
return new SequencerImpl(new SchemaTypeVisitorImpl(_contentModel));
}
/**
* Set the abstract and final flags for a complex type
*/
void setAbstractFinal(
boolean abs, boolean finalExt, boolean finalRest, boolean finalList, boolean finalUnion) {
assertResolving();
_abs = abs;
_finalExt = finalExt;
_finalRest = finalRest;
_finalList = finalList;
_finalUnion = finalUnion;
}
/**
* Set the final flags for a simple type
*/
void setSimpleFinal(boolean finalRest, boolean finalList, boolean finalUnion) {
assertResolving();
_finalRest = finalRest;
_finalList = finalList;
_finalUnion = finalUnion;
}
void setBlock(boolean blockExt, boolean blockRest) {
assertResolving();
_blockExt = blockExt;
_blockRest = blockRest;
}
public boolean blockRestriction() {
return _blockRest;
}
public boolean blockExtension() {
return _blockExt;
}
public boolean isAbstract() {
return _abs;
}
public boolean finalExtension() {
return _finalExt;
}
public boolean finalRestriction() {
return _finalRest;
}
public boolean finalList() {
return _finalList;
}
public boolean finalUnion() {
return _finalUnion;
}
public synchronized SchemaField getContainerField() {
if (_containerFieldCode != -1) {
SchemaType outer = getOuterType();
if (_containerFieldCode == 0) {
_containerField = _containerFieldRef == null ? null : (SchemaField) _containerFieldRef.getComponent();
} else if (_containerFieldCode == 1) {
assert (outer != null);
_containerField = outer.getAttributeModel().getAttributes()[_containerFieldIndex];
} else {
assert (outer != null);
_containerField = ((SchemaTypeImpl) outer).getLocalElementByIndex(_containerFieldIndex);
}
_containerFieldCode = -1;
}
return _containerField;
}
public void setContainerField(SchemaField field) {
assertUnresolved();
_containerField = field;
_containerFieldCode = -1;
}
public void setContainerFieldRef(SchemaComponent.Ref ref) {
assertUnresolved();
_containerFieldRef = ref;
_containerFieldCode = 0;
}
public void setContainerFieldIndex(short code, int index) {
assertUnresolved();
_containerFieldCode = code;
_containerFieldIndex = index;
}
/* package */ void setGroupReferenceContext(QName[] groupNames) {
assertUnresolved();
_groupReferenceContext = groupNames;
}
/* package */ QName[] getGroupReferenceContext() {
return _groupReferenceContext;
}
public SchemaType getOuterType() {
return _outerSchemaTypeRef == null ? null : _outerSchemaTypeRef.get();
}
public void setOuterSchemaTypeRef(SchemaType.Ref typeref) {
assertUnresolved();
_outerSchemaTypeRef = typeref;
}
public boolean isCompiled() {
return _isCompiled;
}
public void setCompiled(boolean f) {
assertJavaizing();
_isCompiled = f;
}
public boolean isSkippedAnonymousType() {
SchemaType outerType = getOuterType();
return (outerType != null && (outerType.getBaseType() == this ||
outerType.getContentBasedOnType() == this));
}
public String getShortJavaName() {
return _shortJavaName;
}
public void setShortJavaName(String name) {
assertResolved();
_shortJavaName = name;
SchemaType outer = _outerSchemaTypeRef.get();
while (outer.getFullJavaName() == null) {
outer = outer.getOuterType();
}
_fullJavaName = outer.getFullJavaName() + "$" + _shortJavaName;
}
public String getFullJavaName() {
return _fullJavaName;
}
public void setFullJavaName(String name) {
assertResolved();
_fullJavaName = name;
int index = Math.max(_fullJavaName.lastIndexOf('$'),
_fullJavaName.lastIndexOf('.')) + 1;
_shortJavaName = _fullJavaName.substring(index);
}
public void setShortJavaImplName(String name) {
assertResolved();
_shortJavaImplName = name;
SchemaType outer = _outerSchemaTypeRef.get();
while (outer.getFullJavaImplName() == null) {
outer = outer.getOuterType();
}
_fullJavaImplName = outer.getFullJavaImplName() + "$" + _shortJavaImplName;
}
public void setFullJavaImplName(String name) {
assertResolved();
_fullJavaImplName = name;
int index = Math.max(_fullJavaImplName.lastIndexOf('$'),
_fullJavaImplName.lastIndexOf('.')) + 1;
_shortJavaImplName = _fullJavaImplName.substring(index);
}
public String getFullJavaImplName() {
return _fullJavaImplName;
}
public String getShortJavaImplName() {
return _shortJavaImplName;
}
public String getUserTypeName() {
return _userTypeName;
}
public void setUserTypeName(String userTypeName) {
_userTypeName = userTypeName;
}
public String getUserTypeHandlerName() {
return _userTypeHandler;
}
public void setUserTypeHandlerName(String typeHandler) {
_userTypeHandler = typeHandler;
}
public void setInterfaceExtensions(InterfaceExtension[] interfaces) {
assertResolved();
_interfaces = (interfaces == null) ? null : interfaces.clone();
}
public InterfaceExtension[] getInterfaceExtensions() {
return _interfaces;
}
public void setPrePostExtension(PrePostExtension prepost) {
assertResolved();
_prepost = prepost;
}
public PrePostExtension getPrePostExtension() {
return _prepost;
}
public Object getUserData() {
return _userData;
}
public void setUserData(Object data) {
_userData = data;
}
/* Only used for asserts */
SchemaContainer getContainer() {
return _container;
}
void setContainer(SchemaContainer container) {
_container = container;
}
public SchemaTypeSystem getTypeSystem() {
return _container.getTypeSystem();
}
public SchemaParticle getContentModel() {
return _contentModel;
}
private static void buildEltList(List<SchemaLocalElement> eltList, SchemaParticle contentModel) {
if (contentModel == null) {
return;
}
switch (contentModel.getParticleType()) {
case SchemaParticle.ELEMENT:
eltList.add((SchemaLocalElement) contentModel);
break;
case SchemaParticle.ALL:
case SchemaParticle.CHOICE:
case SchemaParticle.SEQUENCE:
for (int i = 0; i < contentModel.countOfParticleChild(); i++) {
buildEltList(eltList, contentModel.getParticleChild(i));
}
break;
default:
break;
}
}
private void buildLocalElts() {
List<SchemaLocalElement> eltList = new ArrayList<>();
buildEltList(eltList, _contentModel);
_localElts = eltList.toArray(new SchemaLocalElement[0]);
}
public SchemaLocalElement getLocalElementByIndex(int i) {
SchemaLocalElement[] elts = _localElts;
if (elts == null) {
buildLocalElts();
elts = _localElts;
}
return elts[i];
}
public int getIndexForLocalElement(SchemaLocalElement elt) {
Map<SchemaLocalElement, Integer> localEltMap = _eltToIndexMap;
if (localEltMap == null) {
if (_localElts == null) {
buildLocalElts();
}
localEltMap = new HashMap<>();
for (int i = 0; i < _localElts.length; i++) {
localEltMap.put(_localElts[i], i);
}
_eltToIndexMap = localEltMap;
}
return localEltMap.get(elt);
}
public int getIndexForLocalAttribute(SchemaLocalAttribute attr) {
Map<SchemaLocalAttribute, Integer> localAttrMap = _attrToIndexMap;
if (localAttrMap == null) {
localAttrMap = new HashMap<>();
SchemaLocalAttribute[] attrs = this._attributeModel.getAttributes();
for (int i = 0; i < attrs.length; i++) {
localAttrMap.put(attrs[i], i);
}
_attrToIndexMap = localAttrMap;
}
return localAttrMap.get(attr);
}
public SchemaAttributeModel getAttributeModel() {
return _attributeModel;
}
public SchemaProperty[] getProperties() {
if (_propertyModelByElementName == null) {
return getAttributeProperties();
}
if (_propertyModelByAttributeName == null) {
return getElementProperties();
}
List<SchemaProperty> list = new ArrayList<>();
list.addAll(_propertyModelByElementName.values());
list.addAll(_propertyModelByAttributeName.values());
return list.toArray(new SchemaProperty[0]);
}
private static final SchemaProperty[] NO_PROPERTIES = new SchemaProperty[0];
public SchemaProperty[] getDerivedProperties() {
SchemaType baseType = getBaseType();
if (baseType == null) {
return getProperties();
}
List<SchemaProperty> results = new ArrayList<>();
if (_propertyModelByElementName != null) {
results.addAll(_propertyModelByElementName.values());
}
if (_propertyModelByAttributeName != null) {
results.addAll(_propertyModelByAttributeName.values());
}
for (Iterator<SchemaProperty> it = results.iterator(); it.hasNext(); ) {
SchemaProperty prop = it.next();
SchemaProperty baseProp = prop.isAttribute() ?
baseType.getAttributeProperty(prop.getName()) :
baseType.getElementProperty(prop.getName());
// Remove the derived property from the results if it is
// A) present in the base type and
// B) all the details are the same (cardinality, nillability, default)
if (baseProp != null) {
if (eq(prop.getMinOccurs(), baseProp.getMinOccurs()) &&
eq(prop.getMaxOccurs(), baseProp.getMaxOccurs()) &&
prop.hasNillable() == baseProp.hasNillable() &&
eq(prop.getDefaultText(), baseProp.getDefaultText())) {
it.remove();
}
}
}
return results.toArray(new SchemaProperty[0]);
}
private static boolean eq(BigInteger a, BigInteger b) {
if (a == null && b == null) {
return true;
}
if (a == null || b == null) {
return false;
}
return a.equals(b);
}
private static boolean eq(String a, String b) {
if (a == null && b == null) {
return true;
}
if (a == null || b == null) {
return false;
}
return a.equals(b);
}
public SchemaProperty[] getElementProperties() {
if (_propertyModelByElementName == null) {
return NO_PROPERTIES;
}
return _propertyModelByElementName.values().toArray(new SchemaProperty[0]);
}
public SchemaProperty[] getAttributeProperties() {
if (_propertyModelByAttributeName == null) {
return NO_PROPERTIES;
}
return _propertyModelByAttributeName.values().toArray(new SchemaProperty[0]);
}
public SchemaProperty getElementProperty(QName eltName) {
return _propertyModelByElementName == null ? null : _propertyModelByElementName.get(eltName);
}
public SchemaProperty getAttributeProperty(QName attrName) {
return _propertyModelByAttributeName == null ? null : _propertyModelByAttributeName.get(attrName);
}
public boolean hasAllContent() {
return _hasAllContent;
}
public boolean isOrderSensitive() {
return _orderSensitive;
}
public void setOrderSensitive(boolean sensitive) {
assertJavaizing();
_orderSensitive = sensitive;
}
public void setContentModel(
SchemaParticle contentModel,
SchemaAttributeModel attrModel,
Map<QName, SchemaProperty> propertyModelByElementName,
Map<QName, SchemaProperty> propertyModelByAttributeName,
boolean isAll) {
assertResolving();
_contentModel = contentModel;
_attributeModel = attrModel;
_propertyModelByElementName = propertyModelByElementName;
_propertyModelByAttributeName = propertyModelByAttributeName;
_hasAllContent = isAll;
// Add entries for each element property for substitution group members
if (_propertyModelByElementName != null) {
_validSubstitutions = new LinkedHashSet<>();
Collection<SchemaProperty> eltProps = _propertyModelByElementName.values();
for (SchemaProperty prop : eltProps) {
QName[] names = prop.acceptedNames();
for (QName name : names) {
if (!_propertyModelByElementName.containsKey(name)) {
_validSubstitutions.add(name);
}
}
}
}
}
private boolean containsElements() {
return getContentType() == ELEMENT_CONTENT ||
getContentType() == MIXED_CONTENT;
}
public boolean hasAttributeWildcards() {
return _hasWildcardAttributes;
}
public boolean hasElementWildcards() {
return _hasWildcardElements;
}
public boolean isValidSubstitution(QName name) {
return _validSubstitutions.contains(name);
}
public SchemaType getElementType(QName eltName, QName xsiType, SchemaTypeLoader wildcardTypeLoader) {
if (isSimpleType() || !containsElements() || isNoType()) {
return BuiltinSchemaTypeSystem.ST_NO_TYPE;
}
SchemaType type;
SchemaProperty prop = _propertyModelByElementName.get(eltName);
if (prop != null) {
type = prop.getType();
} else {
if (wildcardTypeLoader == null) {
return BuiltinSchemaTypeSystem.ST_NO_TYPE;
}
if (_typedWildcardElements.contains(eltName) ||
_validSubstitutions.contains(eltName)) {
SchemaGlobalElement elt = wildcardTypeLoader.findElement(eltName);
if (elt == null) {
return BuiltinSchemaTypeSystem.ST_NO_TYPE;
}
// According to http://www.w3.org/TR/xmlschema-1/#key-lva,
// the line above should return ST_ANY_TYPE.
type = elt.getType();
} else {
// Substitution groups
// Actually, better not enable this yet
/*SchemaGlobalElement elt = wildcardTypeLoader.findElement(eltName);
SchemaGlobalElement sghead = elt == null ? null : elt.substitutionGroup();
while (sghead != null)
{
prop = (SchemaProperty)_propertyModelByElementName.get(sghead.getName());
if (prop != null)
{
type = elt.getType();
break;
}
sghead = sghead.substitutionGroup();
}
*/
return BuiltinSchemaTypeSystem.ST_NO_TYPE;
}
}
if (xsiType != null && wildcardTypeLoader != null) {
SchemaType itype = wildcardTypeLoader.findType(xsiType);
// NOTE: a previous version of XMLBeans used ST_NO_TYPE if the
// xsiType was not derived from 'type', but this results in a
// ClassCastException. Instead we ignore xsi:type if it's not
// found or a derived type.
if (itype != null && type.isAssignableFrom(itype)) {
return itype;
}
}
return type;
}
public SchemaType getAttributeType(QName attrName, SchemaTypeLoader wildcardTypeLoader) {
if (isSimpleType() || isNoType()) {
return BuiltinSchemaTypeSystem.ST_NO_TYPE;
}
if (isURType()) {
return BuiltinSchemaTypeSystem.ST_ANY_SIMPLE;
}
SchemaProperty prop = _propertyModelByAttributeName.get(attrName);
if (prop != null) {
return prop.getType();
}
if (!_typedWildcardAttributes.contains(attrName) || wildcardTypeLoader == null) {
return BuiltinSchemaTypeSystem.ST_NO_TYPE;
}
// For symmetry with the element case (as well as with URType), perhaps
// the above line should be returning ST_ANY_SIMPLE
SchemaGlobalAttribute attr = wildcardTypeLoader.findAttribute(attrName);
if (attr == null) {
return BuiltinSchemaTypeSystem.ST_NO_TYPE;
}
return attr.getType();
}
/* These two methods, createElementType and getElementType have to stay
* synchronized, because they create an XmlObject and return the type
* for that object, respectively. But since they do slightly different
* things, they can't be refactored to share code, so exercise caution
*/
public XmlObject createElementType(QName eltName, QName xsiType, SchemaTypeLoader wildcardTypeLoader) {
SchemaType type;
SchemaProperty prop = null;
if (isSimpleType() || !containsElements() || isNoType()) {
type = BuiltinSchemaTypeSystem.ST_NO_TYPE;
} else {
prop = _propertyModelByElementName.get(eltName);
if (prop != null) {
type = prop.getType();
} else if (_typedWildcardElements.contains(eltName) ||
_validSubstitutions.contains(eltName)) {
SchemaGlobalElement elt = wildcardTypeLoader.findElement(eltName);
if (elt != null) {
type = elt.getType();
SchemaType docType = wildcardTypeLoader.findDocumentType(eltName);
if (docType != null) {
prop = docType.getElementProperty(eltName);
}
} else {
type = BuiltinSchemaTypeSystem.ST_NO_TYPE;
}
} else {
// Check if the requested element isn't by any chance part of a
// substitution group headed by one of the declared elements
// Better not enable this yet
/*
SchemaGlobalElement elt = wildcardTypeLoader.findElement(eltName);
SchemaGlobalElement sghead = elt == null ? null : elt.substitutionGroup();
while (sghead != null)
{
if (_propertyModelByElementName.containsKey(sghead.getName()))
{
type = elt.getType();
SchemaType docType = wildcardTypeLoader.findDocumentType(elt.getName());
if (docType != null)
prop = docType.getElementProperty(elt.getName());
break;
}
sghead = sghead.substitutionGroup();
}
*/
type = BuiltinSchemaTypeSystem.ST_NO_TYPE;
}
if (xsiType != null) {
SchemaType itype = wildcardTypeLoader.findType(xsiType);
// NOTE: a previous version of XMLBeans used ST_NO_TYPE if the
// xsiType was not derived from 'type', but this results in a
// ClassCastException. Instead we ignore xsi:type if it's not
// found or a derived type.
if (itype != null && type.isAssignableFrom(itype)) {
type = itype;
}
}
}
if (type != null) {
return ((SchemaTypeImpl) type).createUnattachedNode(prop);
}
return null;
}
public XmlObject createAttributeType(QName attrName, SchemaTypeLoader wildcardTypeLoader) {
SchemaTypeImpl type;
SchemaProperty prop = null;
if (isSimpleType() || isNoType()) {
type = BuiltinSchemaTypeSystem.ST_NO_TYPE;
} else if (isURType()) {
type = BuiltinSchemaTypeSystem.ST_ANY_SIMPLE;
} else {
prop = _propertyModelByAttributeName.get(attrName);
if (prop != null) {
type = (SchemaTypeImpl) prop.getType();
} else if (!_typedWildcardAttributes.contains(attrName)) {
type = BuiltinSchemaTypeSystem.ST_NO_TYPE;
} else {
SchemaGlobalAttribute attr = wildcardTypeLoader.findAttribute(attrName);
if (attr != null) {
type = (SchemaTypeImpl) attr.getType();
} else {
type = BuiltinSchemaTypeSystem.ST_NO_TYPE;
}
}
}
if (type != null) {
return type.createUnattachedNode(prop);
}
return null;
}
public void setWildcardSummary(QNameSet elementSet, boolean haswcElt, QNameSet attributeSet, boolean haswcAtt) {
assertResolving();
_typedWildcardElements = elementSet;
_hasWildcardElements = haswcElt;
_typedWildcardAttributes = attributeSet;
_hasWildcardAttributes = haswcAtt;
}
public SchemaType[] getAnonymousTypes() {
SchemaType[] result = new SchemaType[_anonymousTyperefs.length];
for (int i = 0; i < result.length; i++) {
result[i] = _anonymousTyperefs[i].get();
}
return result;
}
public void setAnonymousTypeRefs(SchemaType.Ref[] anonymousTyperefs) {
_anonymousTyperefs = anonymousTyperefs == null ? null : anonymousTyperefs.clone();
}
private static SchemaType[] staCopy(SchemaType[] a) {
if (a == null) {
return null;
}
SchemaType[] result = new SchemaType[a.length];
System.arraycopy(a, 0, result, 0, a.length);
return result;
}
private static boolean[] boaCopy(boolean[] a) {
if (a == null) {
return null;
}
boolean[] result = new boolean[a.length];
System.arraycopy(a, 0, result, 0, a.length);
return result;
}
public void setSimpleTypeVariety(int variety) {
assertResolving();
_simpleTypeVariety = variety;
}
public int getSimpleVariety() {
return _simpleTypeVariety;
}
public boolean isURType() {
return _builtinTypeCode == BTC_ANY_TYPE || _builtinTypeCode == BTC_ANY_SIMPLE;
}
public boolean isNoType() {
return this == BuiltinSchemaTypeSystem.ST_NO_TYPE;
}
public boolean isSimpleType() {
return _isSimpleType;
}
public void setSimpleType(boolean f) {
assertUnresolved();
_isSimpleType = f;
}
public boolean isUnionOfLists() {
return _isUnionOfLists;
}
public void setUnionOfLists(boolean f) {
assertResolving();
_isUnionOfLists = f;
}
public SchemaType getPrimitiveType() {
return _primitiveTypeRef == null ? null : _primitiveTypeRef.get();
}
public void setPrimitiveTypeRef(SchemaType.Ref typeref) {
assertResolving();
_primitiveTypeRef = typeref;
}
public int getDecimalSize() {
return _decimalSize;
}
public void setDecimalSize(int bits) {
assertResolving();
_decimalSize = bits;
}
public SchemaType getBaseType() {
return _baseTyperef == null ? null : _baseTyperef.get();
}
public void setBaseTypeRef(SchemaType.Ref typeref) {
assertResolving();
_baseTyperef = typeref;
}
public int getBaseDepth() {
return _baseDepth;
}
public void setBaseDepth(int depth) {
assertResolving();
_baseDepth = depth;
}
public SchemaType getContentBasedOnType() {
return _contentBasedOnTyperef == null ? null : _contentBasedOnTyperef.get();
}
public void setContentBasedOnTypeRef(SchemaType.Ref typeref) {
assertResolving();
_contentBasedOnTyperef = typeref;
}
public int getDerivationType() {
return _derivationType;
}
public void setDerivationType(int type) {
assertResolving();
_derivationType = type;
}
public SchemaType getListItemType() {
return _listItemTyperef == null ? null : _listItemTyperef.get();
}
public void setListItemTypeRef(SchemaType.Ref typeref) {
assertResolving();
_listItemTyperef = typeref;
}
public SchemaType[] getUnionMemberTypes() {
SchemaType[] result = new SchemaType[_unionMemberTyperefs == null ? 0 : _unionMemberTyperefs.length];
for (int i = 0; i < result.length; i++) {
result[i] = _unionMemberTyperefs[i].get();
}
return result;
}
public void setUnionMemberTypeRefs(SchemaType.Ref[] typerefs) {
assertResolving();
_unionMemberTyperefs = typerefs == null ? null : typerefs.clone();
}
public int getAnonymousUnionMemberOrdinal() {
return _anonymousUnionMemberOrdinal;
}
public void setAnonymousUnionMemberOrdinal(int i) {
assertUnresolved();
_anonymousUnionMemberOrdinal = i;
}
public synchronized SchemaType[] getUnionConstituentTypes() {
if (_unionCommonBaseType == null) {
computeFlatUnionModel();
}
return staCopy(_unionConstituentTypes);
}
private void setUnionConstituentTypes(SchemaType[] types) {
_unionConstituentTypes = types;
}
public synchronized SchemaType[] getUnionSubTypes() {
if (_unionCommonBaseType == null) {
computeFlatUnionModel();
}
return staCopy(_unionSubTypes);
}
private void setUnionSubTypes(SchemaType[] types) {
_unionSubTypes = types;
}
public synchronized SchemaType getUnionCommonBaseType() {
if (_unionCommonBaseType == null) {
computeFlatUnionModel();
}
return _unionCommonBaseType;
}
private void setUnionCommonBaseType(SchemaType type) {
_unionCommonBaseType = type;
}
private void computeFlatUnionModel() {
if (getSimpleVariety() != SchemaType.UNION) {
throw new IllegalStateException("Operation is only supported on union types");
}
Set<SchemaType> constituentMemberTypes = new LinkedHashSet<>();
Set<SchemaType> allSubTypes = new LinkedHashSet<>();
SchemaType commonBaseType = null;
allSubTypes.add(this);
for (Ref unionMemberTyperef : _unionMemberTyperefs) {
SchemaTypeImpl mImpl = (SchemaTypeImpl) unionMemberTyperef.get();
switch (mImpl.getSimpleVariety()) {
case SchemaType.LIST:
constituentMemberTypes.add(mImpl);
allSubTypes.add(mImpl);
commonBaseType = mImpl.getCommonBaseType(commonBaseType);
break;
case SchemaType.UNION:
constituentMemberTypes.addAll(Arrays.asList(mImpl.getUnionConstituentTypes()));
allSubTypes.addAll(Arrays.asList(mImpl.getUnionSubTypes()));
SchemaType otherCommonBaseType = mImpl.getUnionCommonBaseType();
if (otherCommonBaseType != null) {
commonBaseType = otherCommonBaseType.getCommonBaseType(commonBaseType);
}
break;
case SchemaType.ATOMIC:
constituentMemberTypes.add(mImpl);
allSubTypes.add(mImpl);
commonBaseType = mImpl.getCommonBaseType(commonBaseType);
break;
default:
assert (false);
}
}
setUnionConstituentTypes(constituentMemberTypes.toArray(StscState.EMPTY_ST_ARRAY));
setUnionSubTypes(allSubTypes.toArray(StscState.EMPTY_ST_ARRAY));
setUnionCommonBaseType(commonBaseType);
}
public QName getSubstitutionGroup() {
return _sg;
}
public void setSubstitutionGroup(QName sg) {
assertSGResolving();
_sg = sg;
}
public void addSubstitutionGroupMember(QName member) {
assertSGResolved();
_sgMembers.add(member);
}
public QName[] getSubstitutionGroupMembers() {
return _sgMembers.toArray(new QName[0]);
}
public int getWhiteSpaceRule() {
return _whiteSpaceRule;
}
public void setWhiteSpaceRule(int ws) {
assertResolving();
_whiteSpaceRule = ws;
}
public XmlAnySimpleType getFacet(int facetCode) {
if (_facetArray == null) {
return null;
}
XmlValueRef ref = _facetArray[facetCode];
if (ref == null) {
return null;
}
return ref.get();
}
public boolean isFacetFixed(int facetCode) {
return _fixedFacetArray[facetCode];
}
public XmlAnySimpleType[] getBasicFacets() {
XmlAnySimpleType[] result = new XmlAnySimpleType[SchemaType.LAST_FACET + 1];
for (int i = 0; i <= SchemaType.LAST_FACET; i++) {
result[i] = getFacet(i);
}
return result;
}
public boolean[] getFixedFacets() {
return boaCopy(_fixedFacetArray);
}
public void setBasicFacets(XmlValueRef[] values, boolean[] fixed) {
assertResolving();
_facetArray = values == null ? null : values.clone();
_fixedFacetArray = fixed == null ? null : fixed.clone();
}
public int ordered() {
return _ordered;
}
public void setOrdered(int ordering) {
assertResolving();
_ordered = ordering;
}
public boolean isBounded() {
return _isBounded;
}
public void setBounded(boolean f) {
assertResolving();
_isBounded = f;
}
public boolean isFinite() {
return _isFinite;
}
public void setFinite(boolean f) {
assertResolving();
_isFinite = f;
}
public boolean isNumeric() {
return _isNumeric;
}
public void setNumeric(boolean f) {
assertResolving();
_isNumeric = f;
}
public boolean hasPatternFacet() {
return _hasPatterns;
}
public void setPatternFacet(boolean hasPatterns) {
assertResolving();
_hasPatterns = hasPatterns;
}
public boolean matchPatternFacet(String s) {
if (!_hasPatterns) {
return true;
}
if (_patterns != null && _patterns.length > 0) {
int i;
for (i = 0; i < _patterns.length; i++) {
if (_patterns[i].matches(s)) {
break;
}
}
if (i >= _patterns.length) {
return false;
}
}
return getBaseType().matchPatternFacet(s);
}
public String[] getPatterns() {
if (_patterns == null) {
return new String[0];
}
String[] patterns = new String[_patterns.length];
for (int i = 0; i < _patterns.length; i++) {
patterns[i] = _patterns[i].getPattern();
}
return patterns;
}
public org.apache.xmlbeans.impl.regex.RegularExpression[] getPatternExpressions() {
if (_patterns == null) {
return new org.apache.xmlbeans.impl.regex.RegularExpression[0];
}
org.apache.xmlbeans.impl.regex.RegularExpression[] result = new org.apache.xmlbeans.impl.regex.RegularExpression[_patterns.length];
System.arraycopy(_patterns, 0, result, 0, _patterns.length);
return result;
}
public void setPatterns(org.apache.xmlbeans.impl.regex.RegularExpression[] list) {
assertResolving();
_patterns = list == null ? null : list.clone();
}
public XmlAnySimpleType[] getEnumerationValues() {
if (_enumerationValues == null) {
return null;
}
XmlAnySimpleType[] result = new XmlAnySimpleType[_enumerationValues.length];
for (int i = 0; i < result.length; i++) {
XmlValueRef ref = _enumerationValues[i];
result[i] = (ref == null ? null : ref.get());
}
return result;
}
public void setEnumerationValues(XmlValueRef[] a) {
assertResolving();
_enumerationValues = a == null ? null : a.clone();
}
public StringEnumAbstractBase enumForString(String s) {
ensureStringEnumInfo();
if (_lookupStringEnum == null) {
return null;
}
return _lookupStringEnum.get(s);
}
public StringEnumAbstractBase enumForInt(int i) {
ensureStringEnumInfo();
if (_listOfStringEnum == null || i < 0 || i >= _listOfStringEnum.size()) {
return null;
}
return _listOfStringEnum.get(i);
}
public SchemaStringEnumEntry enumEntryForString(String s) {
ensureStringEnumInfo();
if (_lookupStringEnumEntry == null) {
return null;
}
return _lookupStringEnumEntry.get(s);
}
public SchemaType getBaseEnumType() {
return _baseEnumTyperef == null ? null : _baseEnumTyperef.get();
}
public void setBaseEnumTypeRef(SchemaType.Ref baseEnumTyperef) {
_baseEnumTyperef = baseEnumTyperef;
}
public SchemaStringEnumEntry[] getStringEnumEntries() {
if (_stringEnumEntries == null) {
return null;
}
SchemaStringEnumEntry[] result = new SchemaStringEnumEntry[_stringEnumEntries.length];
System.arraycopy(_stringEnumEntries, 0, result, 0, result.length);
return result;
}
public void setStringEnumEntries(SchemaStringEnumEntry[] sEnums) {
assertJavaizing();
_stringEnumEntries = sEnums == null ? null : sEnums.clone();
}
private void ensureStringEnumInfo() {
if (_stringEnumEnsured) {
return;
}
SchemaStringEnumEntry[] sEnums = _stringEnumEntries;
if (sEnums == null) {
_stringEnumEnsured = true;
return;
}
Map<String, StringEnumAbstractBase> lookupStringEnum = new HashMap<>(sEnums.length);
List<StringEnumAbstractBase> listOfStringEnum = new ArrayList<>(sEnums.length + 1);
Map<String, SchemaStringEnumEntry> lookupStringEnumEntry = new HashMap<>(sEnums.length);
for (SchemaStringEnumEntry sEnum : sEnums) {
lookupStringEnumEntry.put(sEnum.getString(), sEnum);
}
Class<? extends StringEnumAbstractBase> jc = _baseEnumTyperef.get().getEnumJavaClass();
if (jc != null) {
try {
StringEnumAbstractBase.Table table = (StringEnumAbstractBase.Table) jc.getField("table").get(null);
for (SchemaStringEnumEntry sEnum : sEnums) {
int j = sEnum.getIntValue();
StringEnumAbstractBase enumVal = table.forInt(j);
lookupStringEnum.put(sEnum.getString(), enumVal);
while (listOfStringEnum.size() <= j) {
listOfStringEnum.add(null);
}
listOfStringEnum.set(j, enumVal);
}
} catch (Exception e) {
System.err.println("Something wrong: could not locate enum table for " + jc);
jc = null;
lookupStringEnum.clear();
listOfStringEnum.clear();
}
}
if (jc == null) {
for (SchemaStringEnumEntry sEnum : sEnums) {
int j = sEnum.getIntValue();
String s = sEnum.getString();
StringEnumAbstractBase enumVal = new StringEnumValue(s, j);
lookupStringEnum.put(s, enumVal);
while (listOfStringEnum.size() <= j) {
listOfStringEnum.add(null);
}
listOfStringEnum.set(j, enumVal);
}
}
synchronized (this) {
if (!_stringEnumEnsured) {
_lookupStringEnum = lookupStringEnum;
_listOfStringEnum = listOfStringEnum;
_lookupStringEnumEntry = lookupStringEnumEntry;
}
}
// HACKHACK: two syncrhonized blocks force a memory barrier:
// BUGBUG: this behavior is likely to change in future VMs
synchronized (this) {
_stringEnumEnsured = true;
}
}
public boolean hasStringEnumValues() {
return _stringEnumEntries != null;
}
public void copyEnumerationValues(SchemaTypeImpl baseImpl) {
assertResolving();
_enumerationValues = baseImpl._enumerationValues;
_baseEnumTyperef = baseImpl._baseEnumTyperef;
}
public int getBuiltinTypeCode() {
return _builtinTypeCode;
} // special: set up pre-init
public void setBuiltinTypeCode(int builtinTypeCode) {
assertResolving();
_builtinTypeCode = builtinTypeCode;
}
synchronized void assignJavaElementSetterModel() {
// To compute the element setter model, we need to compute the
// delimiting elements for each element.
SchemaProperty[] eltProps = getElementProperties();
SchemaParticle contentModel = getContentModel();
Map<SchemaParticle, QNameSet> state = new HashMap<>();
QNameSet allContents = computeAllContainedElements(contentModel, state);
for (SchemaProperty eltProp : eltProps) {
SchemaPropertyImpl sImpl = (SchemaPropertyImpl) eltProp;
QNameSet nde = computeNondelimitingElements(sImpl.getName(), contentModel, state);
QNameSetBuilder builder = new QNameSetBuilder(allContents);
builder.removeAll(nde);
sImpl.setJavaSetterDelimiter(builder.toQNameSet());
}
}
/**
* Used to compute setter model.
* <p>
* 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.
*/
private static QNameSet computeNondelimitingElements(QName target, SchemaParticle contentModel, Map<SchemaParticle, QNameSet> 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(computeNondelimitingElements(target, contentModel.getParticleChild(i), state));
seenTarget = true;
}
}
return builder.toQNameSet();
}
}
/**
* Used to compute the setter model.
* <p>
* 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.
*/
private static QNameSet computeAllContainedElements(SchemaParticle contentModel, Map<SchemaParticle, QNameSet> state) {
// Remember previously computed results to avoid complexity explosion
QNameSet result = 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:
// Fix for XMLBEANS-228
result = contentModel.acceptedStartNames();
break;
}
state.put(contentModel, result);
return result;
}
@SuppressWarnings("unchecked")
public Class<? extends XmlObject> getJavaClass() {
// This field is declared volatile and Class is immutable so this is allowed.
if (_javaClass == null && getFullJavaName() != null) {
try {
_javaClass = (Class<? extends XmlObject>) Class.forName(getFullJavaName(), false, getTypeSystem().getClassLoader());
} catch (ClassNotFoundException e) {
// This is a legitimate use, when users get a SchemaTypeSystem without compiling classes
_javaClass = null;
}
}
return _javaClass;
}
@SuppressWarnings("unchecked")
public Class<? extends XmlObjectBase> getJavaImplClass() {
if (_implNotAvailable) {
return null;
}
if (_javaImplClass == null) {
try {
if (getFullJavaImplName() != null) {
_javaImplClass = (Class<? extends XmlObjectBase>) Class.forName(getFullJavaImplName(), false, getTypeSystem().getClassLoader());
} else {
_implNotAvailable = true;
}
} catch (ClassNotFoundException e) {
_implNotAvailable = true;
}
}
return _javaImplClass;
}
public Constructor<? extends XmlObjectBase> getJavaImplConstructor() {
if (_javaImplConstructor == null && !_implNotAvailable) {
final Class<? extends XmlObjectBase> impl = getJavaImplClass();
if (impl == null) {
return null;
}
try {
_javaImplConstructor = impl.getConstructor(SchemaType.class);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
return _javaImplConstructor;
}
public Constructor<? extends XmlObjectBase> getJavaImplConstructor2() {
if (_javaImplConstructor2 == null && !_implNotAvailable) {
final Class<? extends XmlObjectBase> impl = getJavaImplClass();
if (impl == null) {
return null;
}
try {
_javaImplConstructor2 = impl.getDeclaredConstructor(SchemaType.class, boolean.class);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
return _javaImplConstructor2;
}
@SuppressWarnings("unchecked")
@Override
public Class<? extends StringEnumAbstractBase> getEnumJavaClass() {
// This field is declared volatile and Class is immutable so this is allowed.
if (_javaEnumClass == null) {
if (getBaseEnumType() != null) {
try {
_javaEnumClass = (Class<? extends StringEnumAbstractBase>) Class.forName(getBaseEnumType().getFullJavaName() + "$Enum", false, getTypeSystem().getClassLoader());
} catch (ClassNotFoundException e) {
_javaEnumClass = null;
}
}
}
return _javaEnumClass;
}
public void setJavaClass(Class<? extends XmlObject> javaClass) {
assertResolved();
_javaClass = javaClass;
setFullJavaName(javaClass.getName());
}
public boolean isPrimitiveType() {
return (getBuiltinTypeCode() >= BTC_FIRST_PRIMITIVE &&
getBuiltinTypeCode() <= BTC_LAST_PRIMITIVE);
}
public boolean isBuiltinType() {
return getBuiltinTypeCode() != 0;
}
public XmlObject createUnwrappedNode() {
// Todo: attach a new xml store!
return createUnattachedNode(null);
}
/**
* TypeStoreUserFactory implementation
*/
public TypeStoreUser createTypeStoreUser() {
return (TypeStoreUser) createUnattachedNode(null);
}
public XmlAnySimpleType newValidatingValue(Object obj) {
return newValue(obj, true);
}
/**
* Creates an immutable simple value.
*/
public XmlAnySimpleType newValue(Object obj) {
return newValue(obj, false);
}
public XmlAnySimpleType newValue(Object obj, boolean validateOnSet) {
if (!isSimpleType() && getContentType() != SchemaType.SIMPLE_CONTENT) {
throw new XmlValueOutOfRangeException(); // values must be simple
}
XmlObjectBase result = (XmlObjectBase) createUnattachedNode(null);
if (validateOnSet) {
result.setValidateOnSet();
}
// In the case of tree copy, need to call a specla setter to avoid
// set(XmlObject)
if (obj instanceof XmlObject) {
result.set_newValue((XmlObject) obj);
} else {
result.setObjectValue(obj);
}
result.check_dated();
result.setImmutable();
return (XmlAnySimpleType) result;
}
/**
* Creates an instance of this type.
*/
private XmlObject createUnattachedNode(SchemaProperty prop) {
XmlObject result = null;
if (!isBuiltinType() && !isNoType()) {
// System.out.println("Attempting to load impl class: " + getFullJavaImplName());
Constructor<? extends XmlObjectBase> ctr = getJavaImplConstructor();
if (ctr != null) {
try {
return ctr.newInstance(_ctrArgs);
} catch (Exception e) {
System.out.println("Exception trying to instantiate impl class.");
e.printStackTrace();
}
}
} else {
result = createBuiltinInstance();
}
// if no result, we must be a restriction of some compiled type
for (SchemaType sType = this; result == null; sType = sType.getBaseType()) {
result = ((SchemaTypeImpl) sType).createUnattachedSubclass(this);
}
((XmlObjectBase) result).init_flags(prop);
return result;
}
private XmlObject createUnattachedSubclass(SchemaType sType) {
if (!isBuiltinType() && !isNoType()) {
// System.out.println("Attempting to load impl class: " + getFullJavaImplName());
Constructor<? extends XmlObjectBase> ctr = getJavaImplConstructor2();
if (ctr != null) {
boolean accessible = ctr.isAccessible();
try {
ctr.setAccessible(true);
try {
return ctr.newInstance(sType, !sType.isSimpleType());
} catch (Exception e) {
System.out.println("Exception trying to instantiate impl class.");
e.printStackTrace();
} finally {
// Make a best-effort try to set the accessibility back to what it was
try {
ctr.setAccessible(accessible);
} catch (SecurityException ignored) {
}
}
} catch (Exception e) {
System.out.println("Exception trying to instantiate impl class.");
e.printStackTrace();
}
}
return null;
} else {
return createBuiltinSubclass(sType);
}
}
private XmlObject createBuiltinInstance() {
switch (getBuiltinTypeCode()) {
case BTC_NOT_BUILTIN:
return new XmlAnyTypeImpl(BuiltinSchemaTypeSystem.ST_NO_TYPE);
case BTC_ANY_TYPE:
return new XmlAnyTypeImpl();
case BTC_ANY_SIMPLE:
return new XmlAnySimpleTypeImpl();
case BTC_BOOLEAN:
return new XmlBooleanImpl();
case BTC_BASE_64_BINARY:
return new XmlBase64BinaryImpl();
case BTC_HEX_BINARY:
return new XmlHexBinaryImpl();
case BTC_ANY_URI:
return new XmlAnyUriImpl();
case BTC_QNAME:
return new XmlQNameImpl();
case BTC_NOTATION:
return new XmlNotationImpl();
case BTC_FLOAT:
return new XmlFloatImpl();
case BTC_DOUBLE:
return new XmlDoubleImpl();
case BTC_DECIMAL:
return new XmlDecimalImpl();
case BTC_STRING:
return new XmlStringImpl();
case BTC_DURATION:
return new XmlDurationImpl();
case BTC_DATE_TIME:
return new XmlDateTimeImpl();
case BTC_TIME:
return new XmlTimeImpl();
case BTC_DATE:
return new XmlDateImpl();
case BTC_G_YEAR_MONTH:
return new XmlGYearMonthImpl();
case BTC_G_YEAR:
return new XmlGYearImpl();
case BTC_G_MONTH_DAY:
return new XmlGMonthDayImpl();
case BTC_G_DAY:
return new XmlGDayImpl();
case BTC_G_MONTH:
return new XmlGMonthImpl();
case BTC_INTEGER:
return new XmlIntegerImpl();
case BTC_LONG:
return new XmlLongImpl();
case BTC_INT:
return new XmlIntImpl();
case BTC_SHORT:
return new XmlShortImpl();
case BTC_BYTE:
return new XmlByteImpl();
case BTC_NON_POSITIVE_INTEGER:
return new XmlNonPositiveIntegerImpl();
case BTC_NEGATIVE_INTEGER:
return new XmlNegativeIntegerImpl();
case BTC_NON_NEGATIVE_INTEGER:
return new XmlNonNegativeIntegerImpl();
case BTC_POSITIVE_INTEGER:
return new XmlPositiveIntegerImpl();
case BTC_UNSIGNED_LONG:
return new XmlUnsignedLongImpl();
case BTC_UNSIGNED_INT:
return new XmlUnsignedIntImpl();
case BTC_UNSIGNED_SHORT:
return new XmlUnsignedShortImpl();
case BTC_UNSIGNED_BYTE:
return new XmlUnsignedByteImpl();
case BTC_NORMALIZED_STRING:
return new XmlNormalizedStringImpl();
case BTC_TOKEN:
return new XmlTokenImpl();
case BTC_NAME:
return new XmlNameImpl();
case BTC_NCNAME:
return new XmlNCNameImpl();
case BTC_LANGUAGE:
return new XmlLanguageImpl();
case BTC_ID:
return new XmlIdImpl();
case BTC_IDREF:
return new XmlIdRefImpl();
case BTC_IDREFS:
return new XmlIdRefsImpl();
case BTC_ENTITY:
return new XmlEntityImpl();
case BTC_ENTITIES:
return new XmlEntitiesImpl();
case BTC_NMTOKEN:
return new XmlNmTokenImpl();
case BTC_NMTOKENS:
return new XmlNmTokensImpl();
default:
throw new IllegalStateException("Unrecognized builtin type: " + getBuiltinTypeCode());
}
}
private XmlObject createBuiltinSubclass(SchemaType sType) {
boolean complex = !sType.isSimpleType();
switch (getBuiltinTypeCode()) {
case BTC_NOT_BUILTIN:
return new XmlAnyTypeImpl(BuiltinSchemaTypeSystem.ST_NO_TYPE);
case BTC_ANY_TYPE:
case BTC_ANY_SIMPLE:
switch (sType.getSimpleVariety()) {
case NOT_SIMPLE:
return new XmlComplexContentImpl(sType);
case ATOMIC:
return new XmlAnySimpleTypeRestriction(sType, complex);
case LIST:
return new XmlListImpl(sType, complex);
case UNION:
return new XmlUnionImpl(sType, complex);
default:
throw new IllegalStateException();
}
case BTC_BOOLEAN:
return new XmlBooleanRestriction(sType, complex);
case BTC_BASE_64_BINARY:
return new XmlBase64BinaryRestriction(sType, complex);
case BTC_HEX_BINARY:
return new XmlHexBinaryRestriction(sType, complex);
case BTC_ANY_URI:
return new XmlAnyUriRestriction(sType, complex);
case BTC_QNAME:
return new XmlQNameRestriction(sType, complex);
case BTC_NOTATION:
return new XmlNotationRestriction(sType, complex);
case BTC_FLOAT:
return new XmlFloatRestriction(sType, complex);
case BTC_DOUBLE:
return new XmlDoubleRestriction(sType, complex);
case BTC_DECIMAL:
return new XmlDecimalRestriction(sType, complex);
case BTC_STRING:
if (sType.hasStringEnumValues()) {
return new XmlStringEnumeration(sType, complex);
} else {
return new XmlStringRestriction(sType, complex);
}
case BTC_DURATION:
return new XmlDurationImpl(sType, complex);
case BTC_DATE_TIME:
return new XmlDateTimeImpl(sType, complex);
case BTC_TIME:
return new XmlTimeImpl(sType, complex);
case BTC_DATE:
return new XmlDateImpl(sType, complex);
case BTC_G_YEAR_MONTH:
return new XmlGYearMonthImpl(sType, complex);
case BTC_G_YEAR:
return new XmlGYearImpl(sType, complex);
case BTC_G_MONTH_DAY:
return new XmlGMonthDayImpl(sType, complex);
case BTC_G_DAY:
return new XmlGDayImpl(sType, complex);
case BTC_G_MONTH:
return new XmlGMonthImpl(sType, complex);
case BTC_INTEGER:
return new XmlIntegerRestriction(sType, complex);
case BTC_LONG:
return new XmlLongRestriction(sType, complex);
case BTC_INT:
return new XmlIntRestriction(sType, complex);
case BTC_SHORT:
return new XmlShortImpl(sType, complex);
case BTC_BYTE:
return new XmlByteImpl(sType, complex);
case BTC_NON_POSITIVE_INTEGER:
return new XmlNonPositiveIntegerImpl(sType, complex);
case BTC_NEGATIVE_INTEGER:
return new XmlNegativeIntegerImpl(sType, complex);
case BTC_NON_NEGATIVE_INTEGER:
return new XmlNonNegativeIntegerImpl(sType, complex);
case BTC_POSITIVE_INTEGER:
return new XmlPositiveIntegerImpl(sType, complex);
case BTC_UNSIGNED_LONG:
return new XmlUnsignedLongImpl(sType, complex);
case BTC_UNSIGNED_INT:
return new XmlUnsignedIntImpl(sType, complex);
case BTC_UNSIGNED_SHORT:
return new XmlUnsignedShortImpl(sType, complex);
case BTC_UNSIGNED_BYTE:
return new XmlUnsignedByteImpl(sType, complex);
case BTC_NORMALIZED_STRING:
return new XmlNormalizedStringImpl(sType, complex);
case BTC_TOKEN:
return new XmlTokenImpl(sType, complex);
case BTC_NAME:
return new XmlNameImpl(sType, complex);
case BTC_NCNAME:
return new XmlNCNameImpl(sType, complex);
case BTC_LANGUAGE:
return new XmlLanguageImpl(sType, complex);
case BTC_ID:
return new XmlIdImpl(sType, complex);
case BTC_IDREF:
return new XmlIdRefImpl(sType, complex);
case BTC_IDREFS:
return new XmlIdRefsImpl(sType, complex);
case BTC_ENTITY:
return new XmlEntityImpl(sType, complex);
case BTC_ENTITIES:
return new XmlEntitiesImpl(sType, complex);
case BTC_NMTOKEN:
return new XmlNmTokenImpl(sType, complex);
case BTC_NMTOKENS:
return new XmlNmTokensImpl(sType, complex);
default:
throw new IllegalStateException("Unrecognized builtin type: " + getBuiltinTypeCode());
}
}
public SchemaType getCommonBaseType(SchemaType type) {
// null type is treated as the no-type
if (this == BuiltinSchemaTypeSystem.ST_ANY_TYPE || type == null || type.isNoType()) {
return this;
}
// any type is the universal base type; noType is the universal derived type
if (type == BuiltinSchemaTypeSystem.ST_ANY_TYPE || isNoType()) {
return type;
}
// the regular case:
SchemaTypeImpl sImpl1 = (SchemaTypeImpl) type;
while (sImpl1.getBaseDepth() > getBaseDepth()) {
sImpl1 = (SchemaTypeImpl) sImpl1.getBaseType();
}
SchemaTypeImpl sImpl2 = this;
while (sImpl2.getBaseDepth() > sImpl1.getBaseDepth()) {
sImpl2 = (SchemaTypeImpl) sImpl2.getBaseType();
}
while (!sImpl1.equals(sImpl2)) {
sImpl1 = (SchemaTypeImpl) sImpl1.getBaseType();
sImpl2 = (SchemaTypeImpl) sImpl2.getBaseType();
assert (sImpl1 != null && sImpl2 != null); // must meet at anyType
}
return sImpl1;
}
public boolean isAssignableFrom(SchemaType type) {
if (type == null || type.isNoType()) {
return true;
}
if (isNoType()) {
return false;
}
if (getSimpleVariety() == UNION) {
SchemaType[] members = getUnionMemberTypes();
for (SchemaType member : members) {
if (member.isAssignableFrom(type)) {
return true;
}
}
}
int depth = ((SchemaTypeImpl) type).getBaseDepth() - getBaseDepth();
if (depth < 0) {
return false;
}
while (depth > 0) {
type = type.getBaseType();
depth -= 1;
}
return (type != null && type.equals(this));
}
public String toString() {
if (getName() != null) {
return "T=" + QNameHelper.pretty(getName());
}
if (isDocumentType()) {
return "D=" + QNameHelper.pretty(getDocumentElementName());
}
if (isAttributeType()) {
return "R=" + QNameHelper.pretty(getAttributeTypeAttributeName());
}
String prefix;
if (getContainerField() != null) {
prefix = (getContainerField().getName().getNamespaceURI().length() > 0 ?
(getContainerField().isAttribute() ? "Q=" : "E=") :
(getContainerField().isAttribute() ? "A=" : "U="))
+ getContainerField().getName().getLocalPart();
if (getOuterType() == null) {
return prefix + "@" + getContainerField().getName().getNamespaceURI();
}
} else if (isNoType()) {
return "N=";
} else if (getOuterType() == null) {
return "noouter";
} else if (getOuterType().getBaseType() == this) {
prefix = "B=";
} else if (getOuterType().getContentBasedOnType() == this) {
prefix = "S=";
} else if (getOuterType().getSimpleVariety() == SchemaType.LIST) {
prefix = "I=";
} else if (getOuterType().getSimpleVariety() == SchemaType.UNION) {
prefix = "M=" + getAnonymousUnionMemberOrdinal();
} else {
prefix = "strange=";
}
return prefix + "|" + getOuterType().toString();
}
private XmlObject _parseObject;
private String _parseTNS;
private String _elemFormDefault;
private String _attFormDefault;
private boolean _chameleon;
private boolean _redefinition;
public void setParseContext(XmlObject parseObject, String targetNamespace, boolean chameleon, String elemFormDefault, String attFormDefault, boolean redefinition) {
_parseObject = parseObject;
_parseTNS = targetNamespace;
_chameleon = chameleon;
_elemFormDefault = elemFormDefault;
_attFormDefault = attFormDefault;
_redefinition = redefinition;
}
public XmlObject getParseObject() {
return _parseObject;
}
public String getTargetNamespace() {
return _parseTNS;
}
public boolean isChameleon() {
return _chameleon;
}
public String getElemFormDefault() {
return _elemFormDefault;
}
public String getAttFormDefault() {
return _attFormDefault;
}
public String getChameleonNamespace() {
return _chameleon ? _parseTNS : null;
}
public boolean isRedefinition() {
return _redefinition;
}
private final SchemaType.Ref _selfref = new SchemaType.Ref(this);
public SchemaType.Ref getRef() {
return _selfref;
}
public SchemaComponent.Ref getComponentRef() {
return getRef();
}
/**
* Gives access to the internals of element validation
*/
private static class SequencerImpl implements SchemaTypeElementSequencer {
private final SchemaTypeVisitorImpl _visitor;
private SequencerImpl(SchemaTypeVisitorImpl visitor) {
_visitor = visitor;
}
public boolean next(QName elementName) {
if (_visitor == null) {
return false;
}
return _visitor.visit(elementName);
}
public boolean peek(QName elementName) {
if (_visitor == null) {
return false;
}
return _visitor.testValid(elementName);
}
}
/**
* Returns a QNameSet of elements that may exist in wildcard
* buchets and are not explicitly defined in this schema type.
* Note: In this example:
* <xs:complexType name="exampleType">
* <xs:sequence>
* <xs:element name="someElement" type='xs:string' />
* <xs:any namespace="##targetNamespace" />
* </xs:sequence>
* </xs:complexType>
* the returned QNameSet will not contain the qname of 'someElement'.
*
* @return the constructed QNameSet
*/
public QNameSet qnameSetForWildcardElements() {
SchemaParticle model = this.getContentModel();
QNameSetBuilder wildcardSet = new QNameSetBuilder();
computeWildcardSet(model, wildcardSet);
QNameSetBuilder qnsb = new QNameSetBuilder(wildcardSet);
SchemaProperty[] props = this.getElementProperties();
for (SchemaProperty prop : props) {
qnsb.remove(prop.getName());
}
return qnsb.toQNameSet();
}
private static void computeWildcardSet(SchemaParticle model, QNameSetBuilder result) {
if (model.getParticleType() == SchemaParticle.WILDCARD) {
QNameSet cws = model.getWildcardSet();
result.addAll(cws);
return;
}
for (int i = 0; i < model.countOfParticleChild(); i++) {
SchemaParticle child = model.getParticleChild(i);
computeWildcardSet(child, result);
}
}
/**
* Returns a QNameSet of attributes that may exist in wildcard
* buchets and are not explicitly defined in this schema type.
* Note: In this example:
* <xs:complexType name="exampleType">
* ...
* <xs:attribute name='someAttribute' type='xs:string' />
* <xs:anyAttribute namespace="##targetNamespace" />
* </xs:complexType>
* the returned QNameSet will not contain the qname of 'someAttribute'.
*
* @return the constructed QNameSet
*/
public QNameSet qnameSetForWildcardAttributes() {
SchemaAttributeModel model = this.getAttributeModel();
QNameSet wildcardSet = model.getWildcardSet();
if (wildcardSet == null) {
return QNameSet.EMPTY;
}
QNameSetBuilder qnsb = new QNameSetBuilder(wildcardSet);
SchemaProperty[] props = this.getAttributeProperties();
for (SchemaProperty prop : props) {
qnsb.remove(prop.getName());
}
return qnsb.toQNameSet();
}
}