blob: 531055a1cc65749e14bf2720c9b74e1a1714ff35 [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.QNameSet;
import org.apache.xmlbeans.QNameSetBuilder;
import org.apache.xmlbeans.SchemaAnnotation;
import org.apache.xmlbeans.SchemaAttributeModel;
import org.apache.xmlbeans.SchemaComponent;
import org.apache.xmlbeans.SchemaField;
import org.apache.xmlbeans.SchemaGlobalAttribute;
import org.apache.xmlbeans.SchemaGlobalElement;
import org.apache.xmlbeans.SchemaLocalAttribute;
import org.apache.xmlbeans.SchemaLocalElement;
import org.apache.xmlbeans.SchemaParticle;
import org.apache.xmlbeans.SchemaProperty;
import org.apache.xmlbeans.SchemaStringEnumEntry;
import org.apache.xmlbeans.SchemaType;
import org.apache.xmlbeans.SchemaTypeElementSequencer;
import org.apache.xmlbeans.SchemaTypeLoader;
import org.apache.xmlbeans.SchemaTypeSystem;
import org.apache.xmlbeans.StringEnumAbstractBase;
import org.apache.xmlbeans.XmlAnySimpleType;
import org.apache.xmlbeans.XmlObject;
import org.apache.xmlbeans.InterfaceExtension;
import org.apache.xmlbeans.PrePostExtension;
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.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
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 _javaClass;
private volatile Class _javaEnumClass;
private volatile Class _javaImplClass;
private volatile Constructor _javaImplConstructor;
private volatile Constructor _javaImplConstructor2;
private volatile boolean _implNotAvailable;
private volatile Class _userTypeClass;
private volatile Class _userTypeHandlerClass;
// 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 _eltToIndexMap; // lazily computed
private volatile Map _attrToIndexMap; // lazily computed
private Map _propertyModelByElementName;
private Map _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 _validSubstitutions = Collections.EMPTY_SET;
// 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 _lookupStringEnum;
private volatile List _listOfStringEnum;
private volatile Map _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 List _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)
_containerField = outer.getAttributeModel().getAttributes()[_containerFieldIndex];
else
_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) ? false :
(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;
}
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 eltList, SchemaParticle contentModel)
{
if (contentModel == null)
return;
switch (contentModel.getParticleType())
{
case SchemaParticle.ELEMENT:
eltList.add(contentModel);
return;
case SchemaParticle.ALL:
case SchemaParticle.CHOICE:
case SchemaParticle.SEQUENCE:
for (int i = 0; i < contentModel.countOfParticleChild(); i++)
buildEltList(eltList, contentModel.getParticleChild(i));
return;
default:
return;
}
}
private void buildLocalElts()
{
List eltList = new ArrayList();
buildEltList(eltList, _contentModel);
_localElts = (SchemaLocalElement[])eltList.toArray(new SchemaLocalElement[eltList.size()]);
}
public SchemaLocalElement getLocalElementByIndex(int i)
{
SchemaLocalElement[] elts = _localElts;
if (elts == null)
{
buildLocalElts();
elts = _localElts;
}
return elts[i];
}
public int getIndexForLocalElement(SchemaLocalElement elt)
{
Map localEltMap = _eltToIndexMap;
if (localEltMap == null)
{
if (_localElts == null)
buildLocalElts();
localEltMap = new HashMap();
for (int i = 0; i < _localElts.length; i++)
{
localEltMap.put(_localElts[i], new Integer(i));
}
_eltToIndexMap = localEltMap;
}
return ((Integer)localEltMap.get(elt)).intValue();
}
public int getIndexForLocalAttribute(SchemaLocalAttribute attr)
{
Map 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], new Integer(i));
}
_attrToIndexMap = localAttrMap;
}
return ((Integer)localAttrMap.get(attr)).intValue();
}
public SchemaAttributeModel getAttributeModel()
{ return _attributeModel; }
public SchemaProperty[] getProperties()
{
if (_propertyModelByElementName == null)
return getAttributeProperties();
if (_propertyModelByAttributeName == null)
return getElementProperties();
List list = new ArrayList();
list.addAll(_propertyModelByElementName.values());
list.addAll(_propertyModelByAttributeName.values());
return (SchemaProperty[])list.toArray(new SchemaProperty[list.size()]);
}
private static final SchemaProperty[] NO_PROPERTIES = new SchemaProperty[0];
public SchemaProperty[] getDerivedProperties()
{
SchemaType baseType = getBaseType();
if (baseType == null)
return getProperties();
List results = new ArrayList();
if (_propertyModelByElementName != null)
results.addAll(_propertyModelByElementName.values());
if (_propertyModelByAttributeName != null)
results.addAll(_propertyModelByAttributeName.values());
for (Iterator it = results.iterator() ; it.hasNext() ; )
{
SchemaProperty prop = (SchemaProperty)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 (SchemaProperty[])results.toArray(new SchemaProperty[results.size()]);
}
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 (SchemaProperty[])
_propertyModelByElementName.values().toArray(new SchemaProperty[_propertyModelByElementName.size()]);
}
public SchemaProperty[] getAttributeProperties()
{
if (_propertyModelByAttributeName == null)
return NO_PROPERTIES;
return (SchemaProperty[])
_propertyModelByAttributeName.values().toArray(new SchemaProperty[_propertyModelByAttributeName.size()]);
}
public SchemaProperty getElementProperty(QName eltName)
{ return _propertyModelByElementName == null ? null : (SchemaProperty)_propertyModelByElementName.get(eltName); }
public SchemaProperty getAttributeProperty(QName attrName)
{ return _propertyModelByAttributeName == null ? null : (SchemaProperty)_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 propertyModelByElementName,
Map 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 eltProps = _propertyModelByElementName.values();
for (Iterator it = eltProps.iterator() ; it.hasNext() ; )
{
SchemaProperty prop = (SchemaProperty)it.next();
QName[] names = prop.acceptedNames();
for (int i = 0 ; i < names.length ; i++)
{
if (! _propertyModelByElementName.containsKey(names[i]))
_validSubstitutions.add(names[i]);
}
}
}
}
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 = null;
SchemaProperty prop = (SchemaProperty)_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();
}
*/
if (type == null)
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 = (SchemaProperty)_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 = null;
SchemaProperty prop = null;
if (isSimpleType() || !containsElements() || isNoType())
{
type = BuiltinSchemaTypeSystem.ST_NO_TYPE;
}
else
{
prop = (SchemaProperty)_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();
}
*/
if (type == null)
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 = null;
SchemaProperty prop = null;
if (isSimpleType() || isNoType())
{
type = BuiltinSchemaTypeSystem.ST_NO_TYPE;
}
else if (isURType())
{
type = BuiltinSchemaTypeSystem.ST_ANY_SIMPLE;
}
else
{
prop = (SchemaProperty)_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;
}
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; }
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 constituentMemberTypes = new LinkedHashSet();
Set allSubTypes = new LinkedHashSet();
SchemaType commonBaseType = null;
allSubTypes.add(this);
for (int i = 0; i < _unionMemberTyperefs.length; i++)
{
SchemaTypeImpl mImpl = (SchemaTypeImpl)_unionMemberTyperefs[i].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((SchemaType[])
constituentMemberTypes.toArray(StscState.EMPTY_ST_ARRAY));
setUnionSubTypes((SchemaType[])
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()
{
QName[] result = new QName[_sgMembers.size()];
return (QName[])_sgMembers.toArray(result);
}
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;
_fixedFacetArray = fixed;
}
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; }
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; }
public StringEnumAbstractBase enumForString(String s)
{
ensureStringEnumInfo();
if (_lookupStringEnum == null)
return null;
return (StringEnumAbstractBase)_lookupStringEnum.get(s);
}
public StringEnumAbstractBase enumForInt(int i)
{
ensureStringEnumInfo();
if (_listOfStringEnum == null || i < 0 || i >= _listOfStringEnum.size())
return null;
return (StringEnumAbstractBase)_listOfStringEnum.get(i);
}
public SchemaStringEnumEntry enumEntryForString(String s)
{
ensureStringEnumInfo();
if (_lookupStringEnumEntry == null)
return null;
return (SchemaStringEnumEntry)_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;
}
private void ensureStringEnumInfo()
{
if (_stringEnumEnsured)
return;
SchemaStringEnumEntry[] sEnums = _stringEnumEntries;
if (sEnums == null)
{
_stringEnumEnsured = true;
return;
}
Map lookupStringEnum = new HashMap(sEnums.length);
List listOfStringEnum = new ArrayList(sEnums.length + 1);
Map lookupStringEnumEntry = new HashMap(sEnums.length);
for (int i = 0; i < sEnums.length; i++)
{
lookupStringEnumEntry.put(sEnums[i].getString(), sEnums[i]);
}
Class jc = _baseEnumTyperef.get().getEnumJavaClass();
if (jc != null)
{
try
{
StringEnumAbstractBase.Table table = (StringEnumAbstractBase.Table)jc.getField("table").get(null);
for (int i = 0; i < sEnums.length; i++)
{
int j = sEnums[i].getIntValue();
StringEnumAbstractBase enumVal = table.forInt(j);
lookupStringEnum.put(sEnums[i].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 (int i = 0; i < sEnums.length; i++)
{
int j = sEnums[i].getIntValue();
String s = sEnums[i].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 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());
}
}
/**
* 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.
*/
private 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(computeNondelimitingElements(target, contentModel.getParticleChild(i), state));
seenTarget = true;
}
}
return builder.toQNameSet();
}
}
/**
* 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.
*/
private 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:
// Fix for XMLBEANS-228
result = ((SchemaLocalElementImpl) contentModel).acceptedStartNames();
break;
}
state.put(contentModel, result);
return result;
}
public Class getJavaClass()
{
// This field is declared volatile and Class is immutable so this is allowed.
if (_javaClass == null && getFullJavaName() != null)
{
try
{ _javaClass = Class.forName(getFullJavaName(), false, getTypeSystem().getClassLoader()); }
catch (ClassNotFoundException e)
{
// This is a legitimate use, when users get a SchemaTypeSystem without compiling classes
// System.err.println("Could not find class name " + getFullJavaName());
// System.err.println("Searched in classloader " + getTypeSystem().getClassLoader());
// e.printStackTrace(System.err);
_javaClass = null;
}
}
return _javaClass;
}
public Class getJavaImplClass() {
if (_implNotAvailable)
return null;
if (_javaImplClass == null)
{
try {
if (getFullJavaImplName() != null)
_javaImplClass = Class.forName(getFullJavaImplName(), false, getTypeSystem().getClassLoader());
else
_implNotAvailable = true;
}
catch (ClassNotFoundException e) {
_implNotAvailable = true;
}
}
return _javaImplClass;
}
public Class getUserTypeClass()
{
// This field is declared volatile and Class is immutable so this is allowed.
if (_userTypeClass == null && getUserTypeName() != null)
{
try
{
_userTypeClass = Class.forName(_userTypeName, false,
getTypeSystem().getClassLoader());
}
catch (ClassNotFoundException e)
{
_userTypeClass = null;
}
}
return _userTypeClass;
}
public Class getUserTypeHandlerClass()
{
// This field is declared volatile and Class is immutable so this is allowed.
if (_userTypeHandlerClass == null && getUserTypeHandlerName() != null)
{
try
{
_userTypeHandlerClass = Class.forName(_userTypeHandler, false,
getTypeSystem().getClassLoader());
}
catch (ClassNotFoundException e)
{
_userTypeHandlerClass = null;
}
}
return _userTypeHandlerClass;
}
public Constructor getJavaImplConstructor()
{
if (_javaImplConstructor == null && !_implNotAvailable)
{
final Class impl = getJavaImplClass();
if (impl == null) return null;
try
{
_javaImplConstructor = impl.getConstructor(new Class[] { SchemaType.class });
}
catch (NoSuchMethodException e)
{
e.printStackTrace();
}
}
return _javaImplConstructor;
}
public Constructor getJavaImplConstructor2()
{
if (_javaImplConstructor2 == null && !_implNotAvailable)
{
final Class impl = getJavaImplClass();
if (impl == null) return null;
try
{
_javaImplConstructor2 = impl.getDeclaredConstructor(new Class[] { SchemaType.class, boolean.class });
}
catch (NoSuchMethodException e)
{
e.printStackTrace();
}
}
return _javaImplConstructor2;
}
public Class getEnumJavaClass()
{
// This field is declared volatile and Class is immutable so this is allowed.
if (_javaEnumClass == null)
{
if ( getBaseEnumType() != null )
{
try
{
_javaEnumClass = Class.forName(getBaseEnumType().getFullJavaName() + "$Enum", false, getTypeSystem().getClassLoader());
}
catch (ClassNotFoundException e)
{
_javaEnumClass = null;
}
}
}
return _javaEnumClass;
}
public void setJavaClass(Class 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!
XmlObject result = createUnattachedNode(null);
return result;
}
/**
* 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.objectSet(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 ctr = getJavaImplConstructor();
if (ctr != null)
{
try
{
// System.out.println("Succeeded!");
return (XmlObject)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 ctr = getJavaImplConstructor2();
if (ctr != null)
{
boolean accessible = ctr.isAccessible();
try
{
ctr.setAccessible(true);
// System.out.println("Succeeded!");
try
{
return (XmlObject)ctr.newInstance(new Object[] { sType, sType.isSimpleType() ? Boolean.FALSE : Boolean.TRUE });
}
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 se)
{ }
}
}
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();
for (;;)
{
if (sImpl1.equals(sImpl2))
break;
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 (int i = 0; i < members.length; i++)
if (members[i].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 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 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 (int i = 0; i < props.length; i++)
{
SchemaProperty prop = props[i];
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 (int i = 0; i < props.length; i++)
{
SchemaProperty prop = props[i];
qnsb.remove(prop.getName());
}
return qnsb.toQNameSet();
}
}