| /* 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.XmlErrorCodes; |
| import org.apache.xmlbeans.impl.common.QNameHelper; |
| import org.apache.xmlbeans.impl.common.ResolverUtil; |
| import org.apache.xmlbeans.XmlObject; |
| import org.apache.xmlbeans.SchemaGlobalElement; |
| import org.apache.xmlbeans.SchemaComponent; |
| import org.apache.xmlbeans.SchemaType; |
| import org.apache.xmlbeans.SchemaGlobalAttribute; |
| import org.apache.xmlbeans.SchemaIdentityConstraint; |
| import org.apache.xmlbeans.SchemaAttributeGroup; |
| import org.apache.xmlbeans.SchemaModelGroup; |
| import org.apache.xmlbeans.SchemaTypeLoader; |
| import org.apache.xmlbeans.SystemProperties; |
| import org.apache.xmlbeans.XmlError; |
| import org.apache.xmlbeans.XmlBeans; |
| import org.apache.xmlbeans.XmlOptions; |
| import org.apache.xmlbeans.BindingConfig; |
| import org.apache.xmlbeans.impl.values.XmlStringImpl; |
| import org.apache.xmlbeans.impl.values.XmlValueOutOfRangeException; |
| import org.apache.xmlbeans.impl.util.HexBin; |
| |
| import java.util.*; |
| import java.net.URISyntaxException; |
| import java.net.URI; |
| import java.net.URL; |
| import java.io.File; |
| |
| |
| import javax.xml.namespace.QName; |
| |
| import org.apache.xmlbeans.impl.xb.xsdschema.SchemaDocument; |
| import org.xml.sax.EntityResolver; |
| |
| /** |
| * This class represents the state of the SchemaTypeSystemCompiler as it's |
| * going. |
| */ |
| public class StscState |
| { |
| private String _givenStsName; |
| private Collection _errorListener; |
| private SchemaTypeSystemImpl _target; |
| private BindingConfig _config; |
| private Map _compatMap; |
| private boolean _doingDownloads; |
| private byte[] _digest = null; |
| private boolean _noDigest = false; |
| |
| // EXPERIMENTAL: recovery from compilation errors and partial type systems |
| private boolean _allowPartial = false; |
| private int _recoveredErrors = 0; |
| |
| private SchemaTypeLoader _importingLoader; |
| |
| private Map _containers = new LinkedHashMap(); |
| private SchemaDependencies _dependencies; |
| |
| private Map _redefinedGlobalTypes = new LinkedHashMap(); |
| private Map _redefinedModelGroups = new LinkedHashMap(); |
| private Map _redefinedAttributeGroups = new LinkedHashMap(); |
| |
| private Map _globalTypes = new LinkedHashMap(); |
| private Map _globalElements = new LinkedHashMap(); |
| private Map _globalAttributes = new LinkedHashMap(); |
| private Map _modelGroups = new LinkedHashMap(); |
| private Map _attributeGroups = new LinkedHashMap(); |
| private Map _documentTypes = new LinkedHashMap(); |
| private Map _attributeTypes = new LinkedHashMap(); |
| private Map _typesByClassname = new LinkedHashMap(); |
| private Map _misspelledNames = new HashMap(); |
| private Set _processingGroups = new LinkedHashSet(); |
| private Map _idConstraints = new LinkedHashMap(); |
| private Set _namespaces = new HashSet(); |
| private List _annotations = new ArrayList(); |
| private boolean _noUpa; |
| private boolean _noPvr; |
| private boolean _noAnn; |
| private boolean _mdefAll; |
| private Set _mdefNamespaces = buildDefaultMdefNamespaces(); |
| private EntityResolver _entityResolver; |
| private File _schemasDir; |
| |
| private static Set buildDefaultMdefNamespaces() |
| { |
| // namespaces which are known to appear in WSDLs redundantly |
| return new HashSet( |
| Arrays.asList( new String[] { |
| "http://www.openuri.org/2002/04/soap/conversation/", |
| })); |
| } |
| |
| /** |
| * Used to store the new target namespace for a chameleon |
| * included schema. |
| */ |
| public static final Object CHAMELEON_INCLUDE_URI = new Object(); |
| |
| /** |
| * Only constructed via StscState.start(). |
| */ |
| private StscState() |
| { |
| } |
| |
| /** |
| * Initializer for incremental compilation |
| */ |
| public void initFromTypeSystem(SchemaTypeSystemImpl system, Set newNamespaces) |
| { |
| // setGivenTypeSystemName(system.getName().substring(14)); |
| |
| SchemaContainer[] containers = system.containers(); |
| for (int i = 0; i < containers.length; i++) |
| { |
| if (!newNamespaces.contains(containers[i].getNamespace())) |
| { |
| // Copy data from the given container |
| addContainer(containers[i]); |
| } |
| } |
| } |
| |
| |
| /* CONTAINERS ================================================================*/ |
| |
| void addNewContainer(String namespace) |
| { |
| if (_containers.containsKey(namespace)) |
| return; |
| |
| SchemaContainer container = new SchemaContainer(namespace); |
| container.setTypeSystem(sts()); |
| addNamespace(namespace); |
| _containers.put(namespace, container); |
| } |
| |
| private void addContainer(SchemaContainer container) |
| { |
| _containers.put(container.getNamespace(), container); |
| List redefModelGroups = container.redefinedModelGroups(); |
| for (int i = 0; i < redefModelGroups.size(); i++) |
| { |
| QName name = ((SchemaModelGroup) redefModelGroups.get(i)).getName(); |
| _redefinedModelGroups.put(name, redefModelGroups.get(i)); |
| } |
| |
| List redefAttrGroups = container.redefinedAttributeGroups(); |
| for (int i = 0; i < redefAttrGroups.size(); i++) |
| { |
| QName name = ((SchemaAttributeGroup) redefAttrGroups.get(i)).getName(); |
| _redefinedAttributeGroups.put(name, redefAttrGroups.get(i)); |
| } |
| |
| List redefTypes = container.redefinedGlobalTypes(); |
| for (int i = 0; i < redefTypes.size(); i++) |
| { |
| QName name = ((SchemaType) redefTypes.get(i)).getName(); |
| _redefinedGlobalTypes.put(name, redefTypes.get(i)); |
| } |
| |
| List globalElems = container.globalElements(); |
| for (int i = 0; i < globalElems.size(); i++) |
| { |
| QName name = ((SchemaGlobalElement) globalElems.get(i)).getName(); |
| _globalElements.put(name, globalElems.get(i)); |
| } |
| |
| List globalAtts = container.globalAttributes(); |
| for (int i = 0; i < globalAtts.size(); i++) |
| { |
| QName name = ((SchemaGlobalAttribute) globalAtts.get(i)).getName(); |
| _globalAttributes.put(name, globalAtts.get(i)); |
| } |
| |
| List modelGroups = container.modelGroups(); |
| for (int i = 0; i < modelGroups.size(); i++) |
| { |
| QName name = ((SchemaModelGroup) modelGroups.get(i)).getName(); |
| _modelGroups.put(name, modelGroups.get(i)); |
| } |
| |
| List attrGroups = container.attributeGroups(); |
| for (int i = 0; i < attrGroups.size(); i++) |
| { |
| QName name = ((SchemaAttributeGroup) attrGroups.get(i)).getName(); |
| _attributeGroups.put(name, attrGroups.get(i)); |
| } |
| |
| List globalTypes = container.globalTypes(); |
| for (int i = 0; i < globalTypes.size(); i++) |
| { |
| SchemaType t = (SchemaType) globalTypes.get(i); |
| QName name = t.getName(); |
| _globalTypes.put(name, t); |
| if (t.getFullJavaName() != null) |
| addClassname(t.getFullJavaName(), t); |
| } |
| |
| List documentTypes = container.documentTypes(); |
| for (int i = 0; i < documentTypes.size(); i++) |
| { |
| SchemaType t = (SchemaType) documentTypes.get(i); |
| QName name = t.getProperties()[0].getName(); |
| _documentTypes.put(name, t); |
| if (t.getFullJavaName() != null) |
| addClassname(t.getFullJavaName(), t); |
| } |
| |
| List attributeTypes = container.attributeTypes(); |
| for (int i = 0; i < attributeTypes.size(); i++) |
| { |
| SchemaType t = (SchemaType) attributeTypes.get(i); |
| QName name = t.getProperties()[0].getName(); |
| _attributeTypes.put(name, t); |
| if (t.getFullJavaName() != null) |
| addClassname(t.getFullJavaName(), t); |
| } |
| |
| List identityConstraints = container.identityConstraints(); |
| for (int i = 0; i < identityConstraints.size(); i++) |
| { |
| QName name = ((SchemaIdentityConstraint) identityConstraints.get(i)).getName(); |
| _idConstraints.put(name, identityConstraints.get(i)); |
| } |
| |
| _annotations.addAll(container.annotations()); |
| _namespaces.add(container.getNamespace()); |
| container.unsetImmutable(); |
| } |
| |
| SchemaContainer getContainer(String namespace) |
| { |
| return (SchemaContainer) _containers.get(namespace); |
| } |
| |
| Map getContainerMap() |
| { |
| return Collections.unmodifiableMap(_containers); |
| } |
| |
| /* DEPENDENCIES ================================================================*/ |
| |
| void registerDependency(String sourceNs, String targetNs) |
| { |
| _dependencies.registerDependency(sourceNs, targetNs); |
| } |
| |
| void registerContribution(String ns, String fileUrl) |
| { |
| _dependencies.registerContribution(ns, fileUrl); |
| } |
| |
| SchemaDependencies getDependencies() |
| { |
| return _dependencies; |
| } |
| |
| void setDependencies(SchemaDependencies deps) |
| { |
| _dependencies = deps; |
| } |
| |
| boolean isFileProcessed(String url) |
| { |
| return _dependencies.isFileRepresented(url); |
| } |
| |
| |
| /** |
| * Initializer for schematypepath |
| */ |
| public void setImportingTypeLoader(SchemaTypeLoader loader) |
| { |
| _importingLoader = loader; |
| } |
| |
| /** |
| * Initializer for error handling. |
| */ |
| public void setErrorListener(Collection errorListener) |
| { _errorListener = errorListener; } |
| |
| /** |
| * Passes an error on to the current error listener. |
| * KHK: remove this |
| */ |
| public void error(String message, int code, XmlObject loc) |
| { addError(_errorListener, message, code, loc); } |
| |
| /** |
| * Passes an error on to the current error listener. |
| */ |
| public void error(String code, Object[] args, XmlObject loc) |
| { addError(_errorListener, code, args, loc); } |
| |
| /** |
| * Passes a recovered error on to the current error listener. |
| */ |
| public void recover(String code, Object[] args, XmlObject loc) |
| { addError(_errorListener, code, args, loc); _recoveredErrors++; } |
| |
| /** |
| * Passes an error on to the current error listener. |
| */ |
| public void warning(String message, int code, XmlObject loc) |
| { |
| addWarning(_errorListener, message, code, loc); |
| } |
| |
| /** |
| * Passes an error on to the current error listener. |
| */ |
| public void warning(String code, Object[] args, XmlObject loc) |
| { |
| // it's OK for XMLSchema.xsd itself to have reserved type names |
| if (code == XmlErrorCodes.RESERVED_TYPE_NAME && |
| loc.documentProperties().getSourceName() != null && |
| loc.documentProperties().getSourceName().indexOf("XMLSchema.xsd") > 0) |
| return; |
| |
| addWarning(_errorListener, code, args, loc); |
| } |
| |
| /** |
| * Passes a warning on to the current error listener. |
| */ |
| public void info(String message) |
| { addInfo(_errorListener, message); } |
| |
| /** |
| * Passes a warning on to the current error listener. |
| */ |
| public void info(String code, Object[] args) |
| { addInfo(_errorListener, code, args); } |
| |
| // KHK: remove this |
| public static void addError(Collection errorListener, String message, int code, XmlObject location) |
| { |
| XmlError err = |
| XmlError.forObject( |
| message, |
| XmlError.SEVERITY_ERROR, |
| location); |
| errorListener.add(err); |
| } |
| |
| public static void addError(Collection errorListener, String code, Object[] args, XmlObject location) |
| { |
| XmlError err = |
| XmlError.forObject( |
| code, |
| args, |
| XmlError.SEVERITY_ERROR, |
| location); |
| errorListener.add(err); |
| } |
| |
| public static void addError(Collection errorListener, String code, Object[] args, File location) |
| { |
| XmlError err = |
| XmlError.forLocation( |
| code, |
| args, |
| XmlError.SEVERITY_ERROR, |
| location.toURI().toString(), 0, 0, 0); |
| errorListener.add(err); |
| } |
| |
| public static void addError(Collection errorListener, String code, Object[] args, URL location) |
| { |
| XmlError err = |
| XmlError.forLocation( |
| code, |
| args, |
| XmlError.SEVERITY_ERROR, |
| location.toString(), 0, 0, 0); |
| errorListener.add(err); |
| } |
| |
| // KHK: remove this |
| public static void addWarning(Collection errorListener, String message, int code, XmlObject location) |
| { |
| XmlError err = |
| XmlError.forObject( |
| message, |
| XmlError.SEVERITY_WARNING, |
| location); |
| errorListener.add(err); |
| } |
| |
| public static void addWarning(Collection errorListener, String code, Object[] args, XmlObject location) |
| { |
| XmlError err = |
| XmlError.forObject( |
| code, |
| args, |
| XmlError.SEVERITY_WARNING, |
| location); |
| errorListener.add(err); |
| } |
| |
| public static void addInfo(Collection errorListener, String message) |
| { |
| XmlError err = XmlError.forMessage(message, XmlError.SEVERITY_INFO); |
| errorListener.add(err); |
| } |
| |
| public static void addInfo(Collection errorListener, String code, Object[] args) |
| { |
| XmlError err = XmlError.forMessage(code, args, XmlError.SEVERITY_INFO); |
| errorListener.add(err); |
| } |
| |
| public void setGivenTypeSystemName(String name) |
| { _givenStsName = name; } |
| |
| /** |
| * Initializer for references to the SchemaTypeLoader |
| */ |
| public void setTargetSchemaTypeSystem(SchemaTypeSystemImpl target) |
| { _target = target; } |
| |
| /** |
| * Accumulates a schema digest... |
| */ |
| public void addSchemaDigest(byte[] digest) |
| { |
| if (_noDigest) |
| return; |
| |
| if (digest == null) |
| { |
| _noDigest = true; |
| _digest = null; |
| return; |
| } |
| |
| if (_digest == null) |
| _digest = new byte[128/8]; // 128 bits. |
| int len = _digest.length; |
| if (digest.length < len) |
| len = digest.length; |
| for (int i = 0; i < len; i++) |
| _digest[i] ^= digest[i]; |
| } |
| |
| /** |
| * The SchemaTypeSystem which we're building types on behalf of. |
| */ |
| public SchemaTypeSystemImpl sts() |
| { |
| if (_target != null) |
| return _target; |
| |
| String name = _givenStsName; |
| if (name == null && _digest != null) |
| name = "s" + new String(HexBin.encode(_digest)); |
| |
| _target = new SchemaTypeSystemImpl(name); |
| return _target; |
| } |
| |
| /** |
| * True if the given URI is a local file |
| */ |
| public boolean shouldDownloadURI(String uriString) |
| { |
| if (_doingDownloads) |
| return true; |
| |
| if (uriString == null) |
| return false; |
| |
| try |
| { |
| URI uri = new URI(uriString); |
| if (uri.getScheme().equalsIgnoreCase("jar") || |
| uri.getScheme().equalsIgnoreCase("zip")) |
| { |
| // It may be local or not, depending on the embedded URI |
| String s = uri.getSchemeSpecificPart(); |
| int i = s.lastIndexOf('!'); |
| return shouldDownloadURI(i > 0 ? s.substring(0, i) : s); |
| } |
| return uri.getScheme().equalsIgnoreCase("file"); |
| } |
| catch (Exception e) |
| { |
| return false; |
| } |
| } |
| |
| /** |
| * Initializer for compatMap. |
| */ |
| public void setOptions(XmlOptions options) |
| { |
| if (options == null) |
| { |
| return; // defaults are all false. |
| } |
| |
| _allowPartial = options.hasOption("COMPILE_PARTIAL_TYPESYSTEM"); |
| |
| _compatMap = (Map)options.get(XmlOptions.COMPILE_SUBSTITUTE_NAMES); |
| _noUpa = options.hasOption(XmlOptions.COMPILE_NO_UPA_RULE) ? true : |
| !"true".equals(SystemProperties.getProperty("xmlbean.uniqueparticleattribution", "true")); |
| _noPvr = options.hasOption(XmlOptions.COMPILE_NO_PVR_RULE) ? true : |
| !"true".equals(SystemProperties.getProperty("xmlbean.particlerestriction", "true")); |
| _noAnn = options.hasOption(XmlOptions.COMPILE_NO_ANNOTATIONS) ? true : |
| !"true".equals(SystemProperties.getProperty("xmlbean.schemaannotations", "true")); |
| _doingDownloads = options.hasOption(XmlOptions.COMPILE_DOWNLOAD_URLS) ? true : |
| "true".equals(SystemProperties.getProperty("xmlbean.downloadurls", "false")); |
| _entityResolver = (EntityResolver)options.get(XmlOptions.ENTITY_RESOLVER); |
| |
| if (_entityResolver == null) |
| _entityResolver = ResolverUtil.getGlobalEntityResolver(); |
| |
| if (_entityResolver != null) |
| _doingDownloads = true; |
| |
| if (options.hasOption(XmlOptions.COMPILE_MDEF_NAMESPACES)) |
| { |
| _mdefNamespaces.addAll((Collection)options.get(XmlOptions.COMPILE_MDEF_NAMESPACES)); |
| |
| String local = "##local"; |
| String any = "##any"; |
| |
| if (_mdefNamespaces.contains(local)) |
| { |
| _mdefNamespaces.remove(local); |
| _mdefNamespaces.add(""); |
| } |
| if (_mdefNamespaces.contains(any)) |
| { |
| _mdefNamespaces.remove(any); |
| _mdefAll = true; |
| } |
| } |
| } |
| |
| /** |
| * May return null if there is no custom entity resolver. |
| */ |
| public EntityResolver getEntityResolver() |
| { |
| return _entityResolver; |
| } |
| |
| /** |
| * True if no unique particle attribution option is set |
| */ |
| public boolean noUpa() |
| { |
| return _noUpa; |
| } |
| |
| /** |
| * True if no particle valid (restriciton) option is set |
| */ |
| public boolean noPvr() |
| { |
| return _noPvr; |
| } |
| |
| /** |
| * True if annotations should be skipped |
| */ |
| public boolean noAnn() |
| { |
| return _noAnn; |
| } |
| |
| /** |
| * True if a partial SchemaTypeSystem should be produced |
| */ |
| // EXPERIMENTAL |
| public boolean allowPartial() |
| { |
| return _allowPartial; |
| } |
| |
| /** |
| * Get count of recovered errors. Not for public. |
| */ |
| // EXPERIMENTAL |
| public int getRecovered() |
| { |
| return _recoveredErrors; |
| } |
| |
| /** |
| * Intercepts XML names and translates them |
| * through the compat map, if any. |
| * |
| * Also looks for a default namespace for global definitions. |
| */ |
| private QName compatName(QName name, String chameleonNamespace) |
| { |
| // first check for a chameleonNamespace namespace |
| if (name.getNamespaceURI().length() == 0 && chameleonNamespace != null && chameleonNamespace.length() > 0) |
| name = new QName(chameleonNamespace, name.getLocalPart()); |
| |
| if (_compatMap == null) |
| return name; |
| |
| QName subst = (QName)_compatMap.get(name); |
| if (subst == null) |
| return name; |
| return subst; |
| } |
| |
| /** |
| * Initializer for the schema config object. |
| */ |
| public void setBindingConfig(BindingConfig config) |
| throws IllegalArgumentException |
| { |
| _config = config; |
| } |
| |
| public BindingConfig getBindingConfig() |
| throws IllegalArgumentException |
| { |
| return _config; |
| } |
| |
| /** |
| * Looks up package override for a namespace URI |
| */ |
| public String getPackageOverride(String namespace) |
| { |
| if (_config == null) |
| return null; |
| return _config.lookupPackageForNamespace(namespace); |
| } |
| |
| /** |
| * Looks up package override for a namespace URI |
| */ |
| public String getJavaPrefix(String namespace) |
| { |
| if (_config == null) |
| return null; |
| return _config.lookupPrefixForNamespace(namespace); |
| } |
| |
| /** |
| * Looks up package override for a namespace URI |
| */ |
| public String getJavaSuffix(String namespace) |
| { |
| if (_config == null) |
| return null; |
| return _config.lookupSuffixForNamespace(namespace); |
| } |
| |
| /** |
| * Looks up configured java name for the given qname. |
| */ |
| public String getJavaname(QName qname, int kind) |
| { |
| if (_config == null) |
| return null; |
| return _config.lookupJavanameForQName(qname, kind); |
| } |
| |
| /* SPELLINGS ======================================================*/ |
| |
| private static String crunchName(QName name) |
| { |
| // lowercase, and drop namespace. |
| return name.getLocalPart().toLowerCase(); |
| } |
| |
| void addSpelling(QName name, SchemaComponent comp) |
| { |
| _misspelledNames.put(crunchName(name), comp); |
| } |
| |
| SchemaComponent findSpelling(QName name) |
| { |
| return (SchemaComponent)_misspelledNames.get(crunchName(name)); |
| } |
| |
| /* NAMESPACES ======================================================*/ |
| |
| void addNamespace(String targetNamespace) |
| { |
| _namespaces.add(targetNamespace); |
| } |
| |
| String[] getNamespaces() |
| { |
| return (String[])_namespaces.toArray(new String[_namespaces.size()]); |
| } |
| |
| boolean linkerDefinesNamespace(String namespace) |
| { |
| return _importingLoader.isNamespaceDefined(namespace); |
| } |
| |
| /* TYPES ==========================================================*/ |
| |
| SchemaTypeImpl findGlobalType(QName name, String chameleonNamespace, String sourceNamespace) |
| { |
| name = compatName(name, chameleonNamespace); |
| SchemaTypeImpl result = (SchemaTypeImpl)_globalTypes.get(name); |
| boolean foundOnLoader = false; |
| if (result == null) |
| { |
| result = (SchemaTypeImpl)_importingLoader.findType(name); |
| foundOnLoader = result != null; |
| } |
| if (!foundOnLoader && sourceNamespace != null) |
| registerDependency(sourceNamespace, name.getNamespaceURI()); |
| return result; |
| } |
| |
| SchemaTypeImpl findRedefinedGlobalType(QName name, String chameleonNamespace, SchemaTypeImpl redefinedBy) |
| { |
| QName redefinedName = redefinedBy.getName(); |
| name = compatName(name, chameleonNamespace); |
| if (name.equals(redefinedName)) |
| { |
| return (SchemaTypeImpl)_redefinedGlobalTypes.get(redefinedBy); |
| // BUGBUG: should also link against _importingLoader.findRedefinedType |
| } |
| SchemaTypeImpl result = (SchemaTypeImpl)_globalTypes.get(name); |
| if (result == null) |
| result = (SchemaTypeImpl)_importingLoader.findType(name); |
| // no dependency is needed here, necause it's intra-namespace |
| return result; |
| } |
| |
| void addGlobalType(SchemaTypeImpl type, SchemaTypeImpl redefined) |
| { |
| if (type != null) |
| { |
| QName name = type.getName(); |
| SchemaContainer container = getContainer(name.getNamespaceURI()); |
| assert container != null && container == type.getContainer(); |
| |
| if (redefined != null) |
| { |
| if (_redefinedGlobalTypes.containsKey(redefined)) |
| { |
| if (!ignoreMdef(name)) { |
| if (_mdefAll) { |
| warning(XmlErrorCodes.SCHEMA_PROPERTIES$DUPLICATE, |
| new Object[] { "global type", QNameHelper.pretty(name), ((SchemaType) _redefinedGlobalTypes.get(redefined)).getSourceName() } , |
| type.getParseObject()); |
| } else { |
| error(XmlErrorCodes.SCHEMA_PROPERTIES$DUPLICATE, |
| new Object[] { "global type", QNameHelper.pretty(name), ((SchemaType) _redefinedGlobalTypes.get(redefined)).getSourceName() } , |
| type.getParseObject()); |
| } |
| } |
| } |
| else |
| { |
| _redefinedGlobalTypes.put(redefined, type); |
| container.addRedefinedType(type.getRef()); |
| } |
| } |
| else |
| { |
| if (_globalTypes.containsKey(name)) |
| { |
| if (!ignoreMdef(name)) { |
| if (_mdefAll) { |
| warning(XmlErrorCodes.SCHEMA_PROPERTIES$DUPLICATE, |
| new Object[] { "global type", QNameHelper.pretty(name), ((SchemaType) _globalTypes.get(name)).getSourceName() }, |
| type.getParseObject()); |
| } else { |
| error(XmlErrorCodes.SCHEMA_PROPERTIES$DUPLICATE, |
| new Object[] { "global type", QNameHelper.pretty(name), ((SchemaType) _globalTypes.get(name)).getSourceName() }, |
| type.getParseObject()); |
| } |
| } |
| } |
| else |
| { |
| _globalTypes.put(name, type); |
| container.addGlobalType(type.getRef()); |
| addSpelling(name, type); |
| } |
| } |
| } |
| } |
| |
| private boolean ignoreMdef(QName name) |
| { |
| return _mdefNamespaces.contains(name.getNamespaceURI()); |
| } |
| |
| SchemaType[] globalTypes() |
| { return (SchemaType[])_globalTypes.values().toArray(new SchemaType[_globalTypes.size()]); } |
| |
| SchemaType[] redefinedGlobalTypes() |
| { return (SchemaType[])_redefinedGlobalTypes.values().toArray(new SchemaType[_redefinedGlobalTypes.size()]); } |
| |
| /* DOCUMENT TYPES =================================================*/ |
| |
| SchemaTypeImpl findDocumentType(QName name, String chameleonNamespace, String sourceNamespace) |
| { |
| name = compatName(name, chameleonNamespace); |
| SchemaTypeImpl result = (SchemaTypeImpl)_documentTypes.get(name); |
| boolean foundOnLoader = false; |
| if (result == null) |
| { |
| result = (SchemaTypeImpl)_importingLoader.findDocumentType(name); |
| foundOnLoader = result != null; |
| } |
| if (!foundOnLoader && sourceNamespace != null) |
| registerDependency(sourceNamespace, name.getNamespaceURI()); |
| return result; |
| } |
| |
| void addDocumentType(SchemaTypeImpl type, QName name) |
| { |
| if (_documentTypes.containsKey(name)) |
| { |
| if (!ignoreMdef(name)) { |
| if (_mdefAll) { |
| warning(XmlErrorCodes.SCHEMA_PROPERTIES$DUPLICATE, |
| new Object[] { "global element", QNameHelper.pretty(name), ((SchemaComponent) _documentTypes.get(name)).getSourceName() }, |
| type.getParseObject()); |
| } else { |
| error(XmlErrorCodes.SCHEMA_PROPERTIES$DUPLICATE, |
| new Object[] { "global element", QNameHelper.pretty(name), ((SchemaComponent) _documentTypes.get(name)).getSourceName() }, |
| type.getParseObject()); |
| } |
| } |
| } |
| else |
| { |
| _documentTypes.put(name, type); |
| SchemaContainer container = getContainer(name.getNamespaceURI()); |
| assert container != null && container == type.getContainer(); |
| container.addDocumentType(type.getRef()); |
| } |
| } |
| |
| SchemaType[] documentTypes() |
| { return (SchemaType[])_documentTypes.values().toArray(new SchemaType[_documentTypes.size()]); } |
| |
| /* ATTRIBUTE TYPES =================================================*/ |
| |
| SchemaTypeImpl findAttributeType(QName name, String chameleonNamespace, String sourceNamespace) |
| { |
| name = compatName(name, chameleonNamespace); |
| SchemaTypeImpl result = (SchemaTypeImpl)_attributeTypes.get(name); |
| boolean foundOnLoader = false; |
| if (result == null) |
| { |
| result = (SchemaTypeImpl)_importingLoader.findAttributeType(name); |
| foundOnLoader = result != null; |
| } |
| if (!foundOnLoader && sourceNamespace != null) |
| registerDependency(sourceNamespace, name.getNamespaceURI()); |
| return result; |
| } |
| |
| void addAttributeType(SchemaTypeImpl type, QName name) |
| { |
| if (_attributeTypes.containsKey(name)) |
| { |
| if (!ignoreMdef(name)) { |
| if (_mdefAll) { |
| warning(XmlErrorCodes.SCHEMA_PROPERTIES$DUPLICATE, |
| new Object[] { "global attribute", QNameHelper.pretty(name), ((SchemaComponent) _attributeTypes.get(name)).getSourceName() }, |
| type.getParseObject()); |
| } else { |
| error(XmlErrorCodes.SCHEMA_PROPERTIES$DUPLICATE, |
| new Object[] { "global attribute", QNameHelper.pretty(name), ((SchemaComponent) _attributeTypes.get(name)).getSourceName() }, |
| type.getParseObject()); |
| } |
| } |
| } |
| else |
| { |
| _attributeTypes.put(name, type); |
| SchemaContainer container = getContainer(name.getNamespaceURI()); |
| assert container != null && container == type.getContainer(); |
| container.addAttributeType(type.getRef()); |
| } |
| } |
| |
| SchemaType[] attributeTypes() |
| { return (SchemaType[])_attributeTypes.values().toArray(new SchemaType[_attributeTypes.size()]); } |
| |
| /* ATTRIBUTES =====================================================*/ |
| |
| SchemaGlobalAttributeImpl findGlobalAttribute(QName name, String chameleonNamespace, String sourceNamespace) |
| { |
| name = compatName(name, chameleonNamespace); |
| SchemaGlobalAttributeImpl result = (SchemaGlobalAttributeImpl)_globalAttributes.get(name); |
| boolean foundOnLoader = false; |
| if (result == null) |
| { |
| result = (SchemaGlobalAttributeImpl)_importingLoader.findAttribute(name); |
| foundOnLoader = result != null; |
| } |
| if (!foundOnLoader && sourceNamespace != null) |
| registerDependency(sourceNamespace, name.getNamespaceURI()); |
| return result; |
| } |
| |
| void addGlobalAttribute(SchemaGlobalAttributeImpl attribute) |
| { |
| if (attribute != null) |
| { |
| QName name = attribute.getName(); |
| _globalAttributes.put(name, attribute); |
| addSpelling(name, attribute); |
| SchemaContainer container = getContainer(name.getNamespaceURI()); |
| assert container != null && container == attribute.getContainer(); |
| container.addGlobalAttribute(attribute.getRef()); |
| } |
| } |
| |
| SchemaGlobalAttribute[] globalAttributes() |
| { return (SchemaGlobalAttribute[])_globalAttributes.values().toArray(new SchemaGlobalAttribute[_globalAttributes.size()]); } |
| |
| /* ELEMENTS =======================================================*/ |
| |
| SchemaGlobalElementImpl findGlobalElement(QName name, String chameleonNamespace, String sourceNamespace) |
| { |
| name = compatName(name, chameleonNamespace); |
| SchemaGlobalElementImpl result = (SchemaGlobalElementImpl)_globalElements.get(name); |
| boolean foundOnLoader = false; |
| if (result == null) |
| { |
| result = (SchemaGlobalElementImpl)_importingLoader.findElement(name); |
| foundOnLoader = result != null; |
| } |
| if (!foundOnLoader && sourceNamespace != null) |
| registerDependency(sourceNamespace, name.getNamespaceURI()); |
| return result; |
| } |
| |
| void addGlobalElement(SchemaGlobalElementImpl element) |
| { |
| if (element != null) |
| { |
| QName name = element.getName(); |
| _globalElements.put(name, element); |
| SchemaContainer container = getContainer(name.getNamespaceURI()); |
| assert container != null && container == element.getContainer(); |
| container.addGlobalElement(element.getRef()); |
| addSpelling(name, element); |
| } |
| } |
| |
| SchemaGlobalElement[] globalElements() |
| { return (SchemaGlobalElement[])_globalElements.values().toArray(new SchemaGlobalElement[_globalElements.size()]); } |
| |
| /* ATTRIBUTE GROUPS ===============================================*/ |
| |
| SchemaAttributeGroupImpl findAttributeGroup(QName name, String chameleonNamespace, String sourceNamespace) |
| { |
| name = compatName(name, chameleonNamespace); |
| SchemaAttributeGroupImpl result = (SchemaAttributeGroupImpl)_attributeGroups.get(name); |
| boolean foundOnLoader = false; |
| if (result == null) |
| { |
| result = (SchemaAttributeGroupImpl)_importingLoader.findAttributeGroup(name); |
| foundOnLoader = result != null; |
| } |
| if (!foundOnLoader && sourceNamespace != null) |
| registerDependency(sourceNamespace, name.getNamespaceURI()); |
| return result; |
| } |
| |
| SchemaAttributeGroupImpl findRedefinedAttributeGroup(QName name, String chameleonNamespace, SchemaAttributeGroupImpl redefinedBy) |
| { |
| QName redefinitionFor = redefinedBy.getName(); |
| name = compatName(name, chameleonNamespace); |
| if (name.equals(redefinitionFor)) |
| { |
| return (SchemaAttributeGroupImpl)_redefinedAttributeGroups.get(redefinedBy); |
| // BUGBUG: should also link against _importingLoader.findRedefinedAttributeGroup |
| } |
| SchemaAttributeGroupImpl result = (SchemaAttributeGroupImpl)_attributeGroups.get(name); |
| if (result == null) |
| result = (SchemaAttributeGroupImpl)_importingLoader.findAttributeGroup(name); |
| return result; |
| } |
| |
| void addAttributeGroup(SchemaAttributeGroupImpl attributeGroup, SchemaAttributeGroupImpl redefined) |
| { |
| if (attributeGroup != null) |
| { |
| QName name = attributeGroup.getName(); |
| SchemaContainer container = getContainer(name.getNamespaceURI()); |
| assert container != null && container == attributeGroup.getContainer(); |
| if (redefined != null) |
| { |
| if (_redefinedAttributeGroups.containsKey(redefined)) |
| { |
| if (!ignoreMdef(name)) { |
| if (_mdefAll) { |
| warning(XmlErrorCodes.SCHEMA_PROPERTIES$DUPLICATE, |
| new Object[] { "attribute group", QNameHelper.pretty(name), ((SchemaComponent) _redefinedAttributeGroups.get(redefined)).getSourceName() }, |
| attributeGroup.getParseObject()); |
| } else { |
| error(XmlErrorCodes.SCHEMA_PROPERTIES$DUPLICATE, |
| new Object[] { "attribute group", QNameHelper.pretty(name), ((SchemaComponent) _redefinedAttributeGroups.get(redefined)).getSourceName() }, |
| attributeGroup.getParseObject()); |
| } |
| } |
| } |
| else |
| { |
| _redefinedAttributeGroups.put(redefined, attributeGroup); |
| container.addRedefinedAttributeGroup(attributeGroup.getRef()); |
| } |
| } |
| else |
| { |
| if (_attributeGroups.containsKey( name )) |
| { |
| if (!ignoreMdef(name)) { |
| if (_mdefAll) { |
| warning(XmlErrorCodes.SCHEMA_PROPERTIES$DUPLICATE, |
| new Object[] { "attribute group", QNameHelper.pretty(name), ((SchemaComponent) _attributeGroups.get(name)).getSourceName() }, |
| attributeGroup.getParseObject()); |
| } else { |
| error(XmlErrorCodes.SCHEMA_PROPERTIES$DUPLICATE, |
| new Object[] { "attribute group", QNameHelper.pretty(name), ((SchemaComponent) _attributeGroups.get(name)).getSourceName() }, |
| attributeGroup.getParseObject()); |
| } |
| } |
| } |
| else |
| { |
| _attributeGroups.put(attributeGroup.getName(), attributeGroup); |
| addSpelling(attributeGroup.getName(), attributeGroup); |
| container.addAttributeGroup(attributeGroup.getRef()); |
| } |
| } |
| } |
| } |
| |
| SchemaAttributeGroup[] attributeGroups() |
| { return (SchemaAttributeGroup[])_attributeGroups.values().toArray(new SchemaAttributeGroup[_attributeGroups.size()]); } |
| |
| SchemaAttributeGroup[] redefinedAttributeGroups() |
| { return (SchemaAttributeGroup[])_redefinedAttributeGroups.values().toArray(new SchemaAttributeGroup[_redefinedAttributeGroups.size()]); } |
| |
| /* MODEL GROUPS ===================================================*/ |
| |
| SchemaModelGroupImpl findModelGroup(QName name, String chameleonNamespace, String sourceNamespace) |
| { |
| name = compatName(name, chameleonNamespace); |
| SchemaModelGroupImpl result = (SchemaModelGroupImpl)_modelGroups.get(name); |
| boolean foundOnLoader = false; |
| if (result == null) |
| { |
| result = (SchemaModelGroupImpl)_importingLoader.findModelGroup(name); |
| foundOnLoader = result != null; |
| } |
| if (!foundOnLoader && sourceNamespace != null) |
| registerDependency(sourceNamespace, name.getNamespaceURI()); |
| return result; |
| } |
| |
| SchemaModelGroupImpl findRedefinedModelGroup(QName name, String chameleonNamespace, SchemaModelGroupImpl redefinedBy) |
| { |
| QName redefinitionFor = redefinedBy.getName(); |
| name = compatName(name, chameleonNamespace); |
| if (name.equals(redefinitionFor)) |
| { |
| return (SchemaModelGroupImpl)_redefinedModelGroups.get(redefinedBy); |
| // BUGBUG: should also link against _importingLoader.findRedefinedModelGroup |
| } |
| SchemaModelGroupImpl result = (SchemaModelGroupImpl)_modelGroups.get(name); |
| if (result == null) |
| result = (SchemaModelGroupImpl)_importingLoader.findModelGroup(name); |
| return result; |
| } |
| |
| void addModelGroup(SchemaModelGroupImpl modelGroup, SchemaModelGroupImpl redefined) |
| { |
| if (modelGroup != null) |
| { |
| QName name = modelGroup.getName(); |
| SchemaContainer container = getContainer(name.getNamespaceURI()); |
| assert container != null && container == modelGroup.getContainer(); |
| if (redefined != null) |
| { |
| if (_redefinedModelGroups.containsKey(redefined)) |
| { |
| if (!ignoreMdef(name)) { |
| if (_mdefAll) { |
| warning(XmlErrorCodes.SCHEMA_PROPERTIES$DUPLICATE, |
| new Object[] { "model group", QNameHelper.pretty(name), ((SchemaComponent) _redefinedModelGroups.get(redefined)).getSourceName() }, |
| modelGroup.getParseObject()); |
| } else { |
| error(XmlErrorCodes.SCHEMA_PROPERTIES$DUPLICATE, |
| new Object[] { "model group", QNameHelper.pretty(name), ((SchemaComponent) _redefinedModelGroups.get(redefined)).getSourceName() }, |
| modelGroup.getParseObject()); |
| } |
| } |
| } |
| else |
| { |
| _redefinedModelGroups.put(redefined, modelGroup); |
| container.addRedefinedModelGroup(modelGroup.getRef()); |
| } |
| } |
| else |
| { |
| if (_modelGroups.containsKey(name)) |
| { |
| if (!ignoreMdef(name)) { |
| if (_mdefAll) { |
| warning(XmlErrorCodes.SCHEMA_PROPERTIES$DUPLICATE, |
| new Object[] { "model group", QNameHelper.pretty(name), ((SchemaComponent) _modelGroups.get(name)).getSourceName() }, |
| modelGroup.getParseObject()); |
| } else { |
| error(XmlErrorCodes.SCHEMA_PROPERTIES$DUPLICATE, |
| new Object[] { "model group", QNameHelper.pretty(name), ((SchemaComponent) _modelGroups.get(name)).getSourceName() }, |
| modelGroup.getParseObject()); |
| } |
| } |
| } |
| else |
| { |
| _modelGroups.put(modelGroup.getName(), modelGroup); |
| addSpelling(modelGroup.getName(), modelGroup); |
| container.addModelGroup(modelGroup.getRef()); |
| } |
| } |
| } |
| } |
| |
| SchemaModelGroup[] modelGroups() |
| { return (SchemaModelGroup[])_modelGroups.values().toArray(new SchemaModelGroup[_modelGroups.size()]); } |
| |
| SchemaModelGroup[] redefinedModelGroups() |
| { return (SchemaModelGroup[])_redefinedModelGroups.values().toArray(new SchemaModelGroup[_redefinedModelGroups.size()]); } |
| |
| /* IDENTITY CONSTRAINTS ===========================================*/ |
| |
| SchemaIdentityConstraintImpl findIdConstraint(QName name, String chameleonNamespace, String sourceNamespace) |
| { |
| name = compatName(name, chameleonNamespace); |
| if (sourceNamespace != null) |
| registerDependency(sourceNamespace, name.getNamespaceURI()); |
| return (SchemaIdentityConstraintImpl)_idConstraints.get(name); |
| } |
| |
| void addIdConstraint(SchemaIdentityConstraintImpl idc) |
| { |
| if (idc != null) |
| { |
| QName name = idc.getName(); |
| SchemaContainer container = getContainer(name.getNamespaceURI()); |
| assert container != null && container == idc.getContainer(); |
| if (_idConstraints.containsKey(name)) |
| { |
| if (!ignoreMdef(name)) |
| warning(XmlErrorCodes.SCHEMA_PROPERTIES$DUPLICATE, |
| new Object[] { "identity constraint", QNameHelper.pretty(name), ((SchemaComponent) _idConstraints.get(name)).getSourceName() }, |
| idc.getParseObject()); |
| } |
| else |
| { |
| _idConstraints.put(name, idc); |
| addSpelling(idc.getName(), idc); |
| container.addIdentityConstraint(idc.getRef()); |
| } |
| } |
| } |
| |
| SchemaIdentityConstraintImpl[] idConstraints() |
| { return (SchemaIdentityConstraintImpl[])_idConstraints.values().toArray(new SchemaIdentityConstraintImpl[_idConstraints.size()]); } |
| |
| /* ANNOTATIONS ===========================================*/ |
| |
| void addAnnotation(SchemaAnnotationImpl ann, String targetNamespace) |
| { |
| if (ann != null) |
| { |
| SchemaContainer container = getContainer(targetNamespace); |
| assert container != null && container == ann.getContainer(); |
| _annotations.add(ann); |
| container.addAnnotation(ann); |
| } |
| } |
| |
| List annotations() |
| { return _annotations; } |
| |
| /* RECURSION AVOIDANCE ============================================*/ |
| boolean isProcessing(Object obj) |
| { |
| return _processingGroups.contains(obj); |
| } |
| |
| void startProcessing(Object obj) |
| { |
| assert(!_processingGroups.contains(obj)); |
| _processingGroups.add(obj); |
| } |
| |
| void finishProcessing(Object obj) |
| { |
| assert(_processingGroups.contains(obj)); |
| _processingGroups.remove(obj); |
| } |
| |
| Object[] getCurrentProcessing() |
| { |
| return _processingGroups.toArray(); |
| } |
| |
| /* JAVAIZATION ====================================================*/ |
| |
| Map typesByClassname() |
| { return Collections.unmodifiableMap(_typesByClassname); } |
| |
| void addClassname(String classname, SchemaType type) |
| { _typesByClassname.put(classname, type); } |
| |
| |
| |
| /** |
| * Stack management if (heaven help us) we ever need to do |
| * nested compilation of schema type system. |
| */ |
| private static final class StscStack |
| { |
| StscState current; |
| ArrayList stack = new ArrayList(); |
| final StscState push() |
| { |
| stack.add(current); |
| current = new StscState(); |
| return current; |
| } |
| final void pop() |
| { |
| current = (StscState)stack.get(stack.size() - 1); |
| stack.remove(stack.size() - 1); |
| } |
| } |
| |
| private static ThreadLocal tl_stscStack = new ThreadLocal(); |
| |
| public static void clearThreadLocals() { |
| tl_stscStack.remove(); |
| } |
| |
| public static StscState start() |
| { |
| StscStack stscStack = (StscStack) tl_stscStack.get(); |
| |
| if (stscStack==null) |
| { |
| stscStack = new StscStack(); |
| tl_stscStack.set(stscStack); |
| } |
| return stscStack.push(); |
| } |
| |
| public static StscState get() |
| { |
| return ((StscStack) tl_stscStack.get()).current; |
| } |
| |
| public static void end() |
| { |
| StscStack stscStack = (StscStack) tl_stscStack.get(); |
| stscStack.pop(); |
| if (stscStack.stack.size()==0) |
| tl_stscStack.set(null); // this is required to release all the references in this classloader |
| // which will enable class unloading and avoid OOM in PermGen |
| } |
| |
| private final static XmlValueRef XMLSTR_PRESERVE = buildString("preserve"); |
| private final static XmlValueRef XMLSTR_REPLACE = buildString("preserve"); |
| private final static XmlValueRef XMLSTR_COLLAPSE = buildString("preserve"); |
| |
| static final SchemaType[] EMPTY_ST_ARRAY = new SchemaType[0]; |
| static final SchemaType.Ref[] EMPTY_STREF_ARRAY = new SchemaType.Ref[0]; |
| |
| private final static XmlValueRef[] FACETS_NONE = new XmlValueRef[] |
| { null, null, null, null, null, null, null, null, null, |
| null, null, null }; |
| |
| private final static boolean[] FIXED_FACETS_NONE = new boolean[] |
| { false, false, false, false, false, false, false, false, false, |
| false, false, false }; |
| |
| private final static XmlValueRef[] FACETS_WS_COLLAPSE = new XmlValueRef[] |
| { null, null, null, null, null, null, null, null, null, |
| build_wsstring(SchemaType.WS_COLLAPSE), null, null }; |
| |
| private final static boolean[] FIXED_FACETS_WS = new boolean[] |
| { false, false, false, false, false, false, false, false, false, |
| true, false, false }; |
| |
| final static XmlValueRef[] FACETS_UNION = FACETS_NONE; |
| final static boolean[] FIXED_FACETS_UNION = FIXED_FACETS_NONE; |
| final static XmlValueRef[] FACETS_LIST = FACETS_WS_COLLAPSE; |
| final static boolean[] FIXED_FACETS_LIST = FIXED_FACETS_WS; |
| |
| static XmlValueRef build_wsstring(int wsr) |
| { |
| switch (wsr) |
| { |
| case SchemaType.WS_PRESERVE: |
| return XMLSTR_PRESERVE; |
| case SchemaType.WS_REPLACE: |
| return XMLSTR_REPLACE; |
| case SchemaType.WS_COLLAPSE: |
| return XMLSTR_COLLAPSE; |
| } |
| return null; |
| } |
| |
| static XmlValueRef buildString(String str) |
| { |
| if (str == null) |
| return null; |
| |
| try |
| { |
| XmlStringImpl i = new XmlStringImpl(); |
| i.set(str); |
| i.setImmutable(); |
| return new XmlValueRef(i); |
| } |
| catch (XmlValueOutOfRangeException e) |
| { |
| return null; |
| } |
| } |
| |
| public void notFoundError(QName itemName, int code, XmlObject loc, boolean recovered) |
| { |
| String expected; |
| String expectedName = QNameHelper.pretty(itemName); |
| String found = null; |
| String foundName = null; |
| String sourceName = null; |
| |
| if (recovered) |
| _recoveredErrors++; |
| |
| switch (code) |
| { |
| case SchemaType.TYPE: |
| expected = "type"; |
| break; |
| case SchemaType.ELEMENT: |
| expected = "element"; |
| break; |
| case SchemaType.ATTRIBUTE: |
| expected = "attribute"; |
| break; |
| case SchemaType.MODEL_GROUP: |
| expected = "model group"; |
| break; |
| case SchemaType.ATTRIBUTE_GROUP: |
| expected = "attribute group"; |
| break; |
| case SchemaType.IDENTITY_CONSTRAINT: |
| expected = "identity constraint"; |
| break; |
| default: |
| assert(false); |
| expected = "definition"; |
| break; |
| } |
| |
| SchemaComponent foundComponent = findSpelling(itemName); |
| QName name; |
| if (foundComponent != null) |
| { |
| name = foundComponent.getName(); |
| if (name != null) |
| { |
| switch (foundComponent.getComponentType()) |
| { |
| case SchemaComponent.TYPE: |
| found = "type"; |
| sourceName = ((SchemaType)foundComponent).getSourceName(); |
| break; |
| case SchemaComponent.ELEMENT: |
| found = "element"; |
| sourceName = ((SchemaGlobalElement)foundComponent).getSourceName(); |
| break; |
| case SchemaComponent.ATTRIBUTE: |
| found = "attribute"; |
| sourceName = ((SchemaGlobalAttribute)foundComponent).getSourceName(); |
| break; |
| case SchemaComponent.ATTRIBUTE_GROUP: |
| found = "attribute group"; |
| break; |
| case SchemaComponent.MODEL_GROUP: |
| found = "model group"; |
| break; |
| } |
| |
| if (sourceName != null) |
| { |
| sourceName = sourceName.substring(sourceName.lastIndexOf('/') + 1); |
| } |
| |
| if (!name.equals(itemName)) |
| { |
| foundName = QNameHelper.pretty(name); |
| } |
| } |
| } |
| |
| if (found == null) |
| { |
| // error with no help |
| error(XmlErrorCodes.SCHEMA_QNAME_RESOLVE, |
| new Object[] { expected, expectedName }, loc); |
| } |
| else { |
| // error with help |
| error(XmlErrorCodes.SCHEMA_QNAME_RESOLVE$HELP, |
| new Object[] { |
| expected, |
| expectedName, |
| found, |
| (foundName == null ? new Integer(0) : new Integer(1)), |
| foundName, |
| (sourceName == null ? new Integer(0) : new Integer(1)), |
| sourceName |
| }, |
| loc); |
| } |
| } |
| |
| |
| /** |
| * Produces the "sourceName" (to be used within the schema project |
| * source file copies) from the URI of the original source. |
| * |
| * Returns null if none. |
| */ |
| public String sourceNameForUri(String uri) |
| { |
| return (String)_sourceForUri.get(uri); |
| } |
| |
| /** |
| * Returns the whole sourceCopyMap, mapping URI's that have |
| * been read to "sourceName" local names that have been used |
| * to tag the types. |
| */ |
| public Map sourceCopyMap() |
| { |
| return Collections.unmodifiableMap(_sourceForUri); |
| } |
| |
| /** |
| * The base URI to use for nice filenames when saving sources. |
| */ |
| public void setBaseUri(URI uri) |
| { |
| _baseURI = uri; |
| } |
| |
| private final static String PROJECT_URL_PREFIX = "project://local"; |
| |
| public String relativize(String uri) |
| { |
| return relativize(uri, false); |
| } |
| |
| public String computeSavedFilename(String uri) |
| { |
| return relativize(uri, true); |
| } |
| |
| private String relativize(String uri, boolean forSavedFilename) |
| { |
| if (uri == null) |
| return null; |
| |
| // deal with things that do not look like absolute uris |
| if (uri.startsWith("/")) |
| { |
| uri = PROJECT_URL_PREFIX + uri.replace('\\', '/'); |
| } |
| else |
| { |
| // looks like a URL? |
| int colon = uri.indexOf(':'); |
| if (colon <= 1 || !uri.substring(0, colon).matches("^\\w+$")) |
| uri = PROJECT_URL_PREFIX + "/" + uri.replace('\\', '/'); |
| } |
| |
| // now relativize against that... |
| if (_baseURI != null) |
| { |
| try |
| { |
| URI relative = _baseURI.relativize(new URI(uri)); |
| if (!relative.isAbsolute()) |
| return relative.toString(); |
| else |
| uri = relative.toString(); |
| } |
| catch (URISyntaxException e) |
| { |
| } |
| } |
| |
| if (!forSavedFilename) |
| return uri; |
| |
| int lastslash = uri.lastIndexOf('/'); |
| String dir = QNameHelper.hexsafe(lastslash == -1 ? "" : uri.substring(0, lastslash)); |
| |
| int question = uri.indexOf('?', lastslash + 1); |
| if (question == -1) |
| return dir + "/" + uri.substring(lastslash + 1); |
| |
| String query = QNameHelper.hexsafe(question == -1 ? "" : uri.substring(question)); |
| |
| // if encoded query part is longer than 64 characters, just drop it |
| if (query.startsWith(QNameHelper.URI_SHA1_PREFIX)) |
| return dir + "/" + uri.substring(lastslash + 1, question); |
| else |
| return dir + "/" + uri.substring(lastslash + 1, question) + query; |
| } |
| |
| /** |
| * Notes another URI that has been consumed during compilation |
| * (this is the URI that is in the document .NAME property) |
| */ |
| public void addSourceUri(String uri, String nameToUse) |
| { |
| if (uri == null) |
| return; |
| |
| if (nameToUse == null) |
| nameToUse = computeSavedFilename(uri); |
| |
| _sourceForUri.put(uri, nameToUse); |
| } |
| |
| /** |
| * Returns the error listener being filled in during this compilation |
| */ |
| public Collection getErrorListener() |
| { |
| return _errorListener; |
| } |
| |
| /** |
| * Returns the schema type loader to use for processing s4s |
| */ |
| public SchemaTypeLoader getS4SLoader() |
| { |
| return _s4sloader; |
| } |
| |
| Map _sourceForUri = new HashMap(); |
| URI _baseURI = URI.create(PROJECT_URL_PREFIX + "/"); |
| SchemaTypeLoader _s4sloader = XmlBeans.typeLoaderForClassLoader(SchemaDocument.class.getClassLoader()); |
| |
| public File getSchemasDir() |
| { |
| return _schemasDir; |
| } |
| |
| public void setSchemasDir(File _schemasDir) |
| { |
| this._schemasDir = _schemasDir; |
| } |
| } |