/******************************************************************************* * Copyright (c) 2001, 2014 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * David Carver - STAR - bug 157254 - referenced Attributes and Elements * were not being checked to see if they had the annotations if * none were defined locally. (Initial fix modified - see bug) *******************************************************************************/ package org.eclipse.wst.xsd.contentmodel.internal; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Vector; import org.eclipse.emf.common.notify.Adapter; import org.eclipse.emf.common.notify.Notifier; import org.eclipse.emf.common.notify.impl.AdapterFactoryImpl; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; import org.eclipse.emf.ecore.resource.impl.URIConverterImpl; import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolverPlugin; import org.eclipse.wst.xml.core.internal.contentmodel.CMAnyElement; import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration; import org.eclipse.wst.xml.core.internal.contentmodel.CMContent; import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType; import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument; import org.eclipse.wst.xml.core.internal.contentmodel.CMDocumentation; import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration; import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup; import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap; import org.eclipse.wst.xml.core.internal.contentmodel.CMNamespace; import org.eclipse.wst.xml.core.internal.contentmodel.CMNode; import org.eclipse.wst.xml.core.internal.contentmodel.CMNodeList; import org.eclipse.wst.xml.core.internal.contentmodel.annotation.AnnotationMap; import org.eclipse.wst.xml.core.internal.contentmodel.basic.CMAttributeDeclarationImpl; import org.eclipse.wst.xml.core.internal.contentmodel.basic.CMDataTypeImpl; import org.eclipse.wst.xml.core.internal.contentmodel.basic.CMDocumentImpl; import org.eclipse.wst.xml.core.internal.contentmodel.basic.CMEntityDeclarationImpl; import org.eclipse.wst.xml.core.internal.contentmodel.basic.CMGroupImpl; import org.eclipse.wst.xml.core.internal.contentmodel.basic.CMNamedNodeMapImpl; import org.eclipse.wst.xml.core.internal.contentmodel.basic.CMNodeListImpl; import org.eclipse.wst.xml.core.internal.contentmodel.util.CMDescriptionBuilder; import org.eclipse.wst.xml.core.internal.contentmodel.util.NamespaceInfo; import org.eclipse.wst.xsd.contentmodel.internal.util.XSDSchemaLocatorAdapterFactory; import org.eclipse.xsd.XSDAnnotation; import org.eclipse.xsd.XSDAttributeDeclaration; import org.eclipse.xsd.XSDAttributeUse; import org.eclipse.xsd.XSDAttributeUseCategory; import org.eclipse.xsd.XSDComplexTypeDefinition; import org.eclipse.xsd.XSDCompositor; import org.eclipse.xsd.XSDConcreteComponent; import org.eclipse.xsd.XSDConstraint; import org.eclipse.xsd.XSDContentTypeCategory; import org.eclipse.xsd.XSDElementDeclaration; import org.eclipse.xsd.XSDEnumerationFacet; import org.eclipse.xsd.XSDForm; import org.eclipse.xsd.XSDImport; import org.eclipse.xsd.XSDModelGroup; import org.eclipse.xsd.XSDModelGroupDefinition; import org.eclipse.xsd.XSDParticle; import org.eclipse.xsd.XSDParticleContent; import org.eclipse.xsd.XSDSchema; import org.eclipse.xsd.XSDSchemaContent; import org.eclipse.xsd.XSDSimpleTypeDefinition; import org.eclipse.xsd.XSDTypeDefinition; import org.eclipse.xsd.XSDVariety; import org.eclipse.xsd.XSDWildcard; import org.eclipse.xsd.impl.XSDSchemaImpl; import org.eclipse.xsd.util.XSDConstants; import org.eclipse.xsd.util.XSDResourceImpl; import org.eclipse.xsd.util.XSDSwitch; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.w3c.dom.Text; /** * Utility class to build cmnodes from XML Schema nodes. The XML Schema model is * found in the org.eclipse.xsd plugin. * * TODO: getNamespaceURI()currently always returns '##any'. */ public class XSDImpl { /* * properties common to all cmnodes the following properties defined in * CMNodeImpl class: PROPERTY_DOCUMENTATION PROPERTY_DOCUMENTATION_SOURCE * PROPERTY_DOCUMENTATION_LANGUAGE PROPERTY_MOF_NOTIFIER * PROPERTY_DEFINITION_INFO PROPERTY_DEFINITION * * the following properties defined in this class, XSDImpl: * PROPERTY_CMDOCUMENT PROPERTY_USES_LOCAL_ELEMENT_DECLARATIONS * PROPERTY_IS_NAME_SPACE_AWARE PROPERTY_NS_PREFIX_QUALIFICATION * PROPERTY_NILLABLE PROPERTY_SPEC */ public static final String PROPERTY_CMDOCUMENT = "CMDocument"; public static final String PROPERTY_USES_LOCAL_ELEMENT_DECLARATIONS = "http://org.eclipse.wst/cm/properties/usesLocalElementDeclarations"; public static final String PROPERTY_IS_NAME_SPACE_AWARE = "http://org.eclipse.wst/cm/properties/isNameSpaceAware"; public static final String PROPERTY_NS_PREFIX_QUALIFICATION = "http://org.eclipse.wst/cm/properties/nsPrefixQualification"; public static final String PROPERTY_NILLABLE = "http://org.eclipse.wst/cm/properties/nillable"; public static final String PROPERTY_SPEC = "spec"; /* * properties common to all CMDocument nodes: PROPERTY_TARGET_NAMESPACE_URI * PROPERTY_IMPORTED_NAMESPACE_INFO PROPERTY_NAMESPACE_INFO * PROPERTY_ELEMENT_FORM_DEFAULT PROPERTY_ANNOTATION_MAP */ public static final String PROPERTY_TARGET_NAMESPACE_URI = "http://org.eclipse.wst/cm/properties/targetNamespaceURI"; public static final String PROPERTY_IMPORTED_NAMESPACE_INFO = "http://org.eclipse.wst/cm/properties/importedNamespaceInfo"; public static final String PROPERTY_NAMESPACE_INFO = "http://org.eclipse.wst/cm/properties/namespaceInfo"; public static final String PROPERTY_ELEMENT_FORM_DEFAULT = "http://org.eclipse.wst/cm/properties/elementFormDefault"; public static final String PROPERTY_ANNOTATION_MAP = "annotationMap"; public static final String PROPERTY_COMPLETE_NAMESPACE_INFO = "http://org.eclipse.wst/cm/properties/completeNamespaceInfo"; /* * properties common to all CMElementDeclaration nodes: PROPERTY_XSITYPES * PROPERTY_DERIVED_ELEMENT_DECLARATION PROPERTY_SUBSTITUTION_GROUP * PROPERTY_ABSTRACT */ public static final String PROPERTY_XSITYPES = "XSITypes"; public static final String PROPERTY_DERIVED_ELEMENT_DECLARATION = "DerivedElementDeclaration"; public static final String PROPERTY_EXTERNALLY_DERIVED_ELEMENT_DECLARATION = "ExternallyDerivedElementDeclaration"; public static final String PROPERTY_SUBSTITUTION_GROUP = "SubstitutionGroup"; public static final String PROPERTY_SUBSTITUTION_GROUP_VALUE = "SubstitutionGroupValue"; public static final String PROPERTY_ABSTRACT = "Abstract"; public static final String PROPERTY_WHITESPACE_FACET = "org.eclipse.wst.xsd.cm.properties/whitespace"; //$NON-NLS-1$ /** * Definition info for element declarations. */ public static final String DEFINITION_INFO_GLOBAL = "global"; public static final String DEFINITION_INFO_LOCAL = "local"; public static final String XML_LANG_ATTRIBUTE = "xml:lang"; public static final String PLATFORM_PROTOCOL = "platform:"; protected static XSDAdapterFactoryImpl xsdAdapterFactoryImpl = new XSDAdapterFactoryImpl(); protected static XSIDocument xsiDocument = new XSIDocument(); /** * Given uri for an XML Schema document, parse the document and build * corresponding CMDocument node. * * @param uri - * the uri for an XML Schema document * @param grammarErrorChecking - * grammar error checking flag * @param errorList - * the resulting error list * @return the corresponding CMDocument node. * @deprecated -- use buildCMDocument(String uri) */ public static CMDocument buildCMDocument(String uri, int grammarErrorChecking, List errorList) { return buildCMDocument(uri); } /** * Given uri for an XML Schema document, parse the document and build * corresponding CMDocument node. * * @param uri - * the uri for an XML Schema document * @return the corresponding CMDocument node. */ public static CMDocument buildCMDocument(String uri) { CMDocument cmDocument = null; XSDSchema xsdSchema = buildXSDModel(uri); if (xsdSchema != null) { cmDocument = (CMDocument) getAdapter(xsdSchema); } return cmDocument; } /** * Given uri for an XML Schema document, parse the document and build * corresponding CMDocument node. * * @param uri - * the uri for an XML Schema document * @return the corresponding CMDocument node. */ public static XSDSchema buildXSDModel(String uriString) { XSDSchema xsdSchema = null; try { // if XML Schema for Schema is requested, get it through schema model if (uriString.endsWith("2001/XMLSchema.xsd")) { xsdSchema = XSDSchemaImpl.getSchemaForSchema(XSDConstants.SCHEMA_FOR_SCHEMA_URI_2001); } else { ResourceSet resourceSet = new ResourceSetImpl(); //resourceSet.getAdapterFactories().add(new XSDSchemaLocationResolverAdapterFactory()); resourceSet.getAdapterFactories().add(new XSDSchemaLocatorAdapterFactory()); URI uri = createURI(uriString); // CS : bug 113537 ensure we perform physical resolution before opening a stream for the resource // String physicalLocation = URIResolverPlugin.createResolver().resolvePhysicalLocation("", "", uriString); InputStream inputStream = resourceSet.getURIConverter().createInputStream(URI.createURI(physicalLocation)); XSDResourceImpl resource = (XSDResourceImpl)resourceSet.createResource(URI.createURI("*.xsd")); resource.setURI(uri); resource.load(inputStream, null); xsdSchema = resource.getSchema(); } } catch (Exception e) { } return xsdSchema; } // TODO ... looks like we can remove this class? // static class InternalURIConverter extends URIConverterImpl { protected InputStream createURLInputStream(URI uri) throws IOException { if ("http".equals(uri.scheme())) { String theURI = uri.toString(); String mapped = URIResolverPlugin.createResolver().resolve(theURI, theURI, theURI); if (mapped != null) { uri = createURI(mapped); } } return super.createURLInputStream(uri); } } /** * Returns an appropriate URI based on a uri string. * * @param uriString - * a uri string. * @return an appropriate URI based on a uri string. */ public static URI createURI(String uriString) { if (hasProtocol(uriString)) return URI.createURI(uriString); else return URI.createFileURI(uriString); } private static boolean hasProtocol(String uri) { boolean result = false; if (uri != null) { int index = uri.indexOf(":"); if (index != -1 && index > 2) // assume protocol with be length 3 so that // the'C' in 'C:/' is not interpreted as a // protocol { result = true; } } return result; } /** * Returns true if string begins with platform protocol. * * @param uriString - * a uri string. * @return true if string begins with platform protocol. */ public static boolean withPlatformProtocol(String uriString) { return uriString.startsWith(PLATFORM_PROTOCOL); } /** * Returns the value of the 'Min Occurs' attribute. The default value is "1". * * @param component - * a concrete component. * @return the value of the 'Min Occurs' attribute. */ public static int getMinOccurs(XSDConcreteComponent component) { int minOccur = 1; if (component != null) { Object o = component.getContainer(); if (o instanceof XSDParticle) { if (((XSDParticle) o).isSetMinOccurs()) { try { minOccur = ((XSDParticle) o).getMinOccurs(); } catch (Exception e) { minOccur = 1; } } } } return minOccur; } /** * Returns the value of the 'Max Occurs' attribute. The default value is "1". * * @param component - * a concrete component. * @return the value of the 'Max Occurs' attribute. */ public static int getMaxOccurs(XSDConcreteComponent component) { int maxOccur = 1; if (component != null) { Object o = component.getContainer(); if (o instanceof XSDParticle) { if (((XSDParticle) o).isSetMaxOccurs()) { try { maxOccur = ((XSDParticle) o).getMaxOccurs(); } catch (Exception e) { maxOccur = 1; } } } } return maxOccur; } /** * Returns the enumerated values for the given type. * * @param type - * a type definition. * @return the enumerated values for the given type. */ private final static String TYPE_NAME_BOOLEAN = "boolean"; //$NON-NLS-1$ private final static String TYPE_VALUE_TRUE = "true"; //$NON-NLS-1$ private final static String TYPE_VALUE_FALSE= "false"; //$NON-NLS-1$ public static String[] getEnumeratedValuesForType(XSDTypeDefinition type) { List result = new ArrayList(); // See bug 214804 - Content assist not showing valid values when it's a complex // type with simple content if (type instanceof XSDComplexTypeDefinition) { type = ((XSDComplexTypeDefinition)type).getSimpleType(); } if (type instanceof XSDSimpleTypeDefinition) { if (TYPE_NAME_BOOLEAN.equals(type.getName()) && type.getSchema().getSchemaForSchema() == type.getSchema()) { result.add(TYPE_VALUE_TRUE); result.add(TYPE_VALUE_FALSE); } else { // Simple types can be one of: atomic, list or union. int varietyType = ((XSDSimpleTypeDefinition) type).getVariety().getValue(); switch (varietyType) { case XSDVariety.ATOMIC: { XSDTypeDefinition baseType = type.getBaseType(); if (baseType != null && !(type.getSchema().getSchemaForSchema() == baseType.getSchema())) { getEnumeratedValuesForSimpleType(baseType, result); // Bug 424276 - The above is not sufficient. First check if there are enumerations for the base type. // If there are none, then we should be able to add the enumerations for the current type if (result.isEmpty()) { getEnumeratedValuesForSimpleType(type, result); } else // There are enumerations on the base type { // If there are enumerations on the current type also, then we should just add the ones from the current type // since we're restricting the values List enumerationsForCurrentType = new ArrayList(); getEnumeratedValuesForSimpleType(type, enumerationsForCurrentType); if (!enumerationsForCurrentType.isEmpty()) { result.clear(); result.addAll(enumerationsForCurrentType); } // Otherwise, just use the enumerations on the base type } } else { getEnumeratedValuesForSimpleType(type, result); } } break; case XSDVariety.LIST: { XSDSimpleTypeDefinition itemTypeDefinition = ((XSDSimpleTypeDefinition) type).getItemTypeDefinition(); String[] values = getEnumeratedValuesForType(itemTypeDefinition); for (int j = 0; j < values.length; j++) { if(result.indexOf(values[j]) == -1) { result.add(values[j]); } } } break; case XSDVariety.UNION: { List memberTypes = ((XSDSimpleTypeDefinition) type).getMemberTypeDefinitions(); if (memberTypes != null && memberTypes.size() > 0) { Iterator i = memberTypes.iterator(); while (i.hasNext()) { XSDSimpleTypeDefinition simpleType = (XSDSimpleTypeDefinition) i.next(); String[] values = getEnumeratedValuesForType(simpleType); for (int j = 0; j < values.length; j++) { if(result.indexOf(values[j]) == -1) { result.add(values[j]); } } } } } break; } } } String[] array = new String[result.size()]; result.toArray(array); return array; } private static void getEnumeratedValuesForSimpleType(XSDTypeDefinition type, List result) { List enumerationFacets = ((XSDSimpleTypeDefinition) type).getEnumerationFacets(); for (Iterator i = enumerationFacets.iterator(); i.hasNext();) { XSDEnumerationFacet enumFacet = (XSDEnumerationFacet) i.next(); List values = enumFacet.getValue(); for (Iterator j = values.iterator(); j.hasNext();) { Object o = j.next(); if (o != null) { if (!result.contains(o)) { result.add(o.toString()); } } } } } /** * Return a list of documentation elements from the given annotation. Working * with documentation elements requires dropping down into the DOM model. * * @param annotation - * an XSDAnnotation node. * @return a list of documentation elements. */ public static CMNodeList getDocumentations(XSDAnnotation annotation) { CMNodeListImpl documentations = new CMNodeListImpl(); if (annotation != null) { List documentationsElements = annotation.getUserInformation(); for (Iterator i = documentationsElements.iterator(); i.hasNext();) { documentations.getList().add(new DocumentationImpl((Element) i.next())); } } return documentations; } /** * Adapted from public static List findTypesDerivedFrom(XSDSchema schema, * String namespace, String localName) in class XSDSchemaQueryTools found in * org.eclipse.xsd plugin. * * Find typeDefinitions that derive from a given type. * * @param type * the type derived from * @return List of any XSDTypeDefinitions found */ public static List findTypesDerivedFrom(XSDTypeDefinition type) { ArrayList typesDerivedFrom = new ArrayList(); if (type != null) { XSDSchema schema = type.getSchema(); String localName = type.getName(); if ((null != schema) && (null != localName)) { String namespace = schema.getTargetNamespace(); // A handy convenience method quickly gets all // typeDefinitions within our schema; note that // whether or not this returns types in included, // imported, or redefined schemas is subject to change List typedefs = schema.getTypeDefinitions(); for (Iterator iter = typedefs.iterator(); iter.hasNext();) { XSDTypeDefinition typedef = (XSDTypeDefinition) iter.next(); if (typedef instanceof XSDComplexTypeDefinition) { // Walk the baseTypes from this typedef seeing if any // of them match the requested one if (isTypeDerivedFrom(typedef, namespace, localName)) { // We found it, return the original one and continue typesDerivedFrom.add(typedef); continue; } } } } } return typesDerivedFrom; } /** * Adapted from protected static boolean isTypeDerivedFrom(XSDTypeDefinition * typedef, String namespace, String localName) in class XSDSchemaQueryTools * found in org.eclipse.xsd plugin. * * Recursive worker method to find typeDefinitions that derive from a named * type. * * @see #findTypesDerivedFrom(XSDSchema, String, String) * @param typeDef * to see if it's derived from * @param namespace * for the type derived from * @param localName * for the type derived from * @return true if it is; false otherwise */ protected static boolean isTypeDerivedFrom(XSDTypeDefinition typedef, String namespace, String localName) { // Walk the baseTypes from this typedef seeing if any // of them match the requested one XSDTypeDefinition baseType = typedef.getBaseType(); if (baseType == null) { // typedef is a root type like xsd:anyType, so it has no base return false; } // As this convenience method if our parameters match if (baseType.hasNameAndTargetNamespace(localName, namespace)) { return true; } XSDTypeDefinition rootType = typedef.getRootType(); if (rootType == baseType) { // If we've hit the root, we aren't derived from it return false; } else { // Need to check if the base type is redefined/circular // otherwise this will be an endless recursive call. // Moved. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=213543 // This method should be replaced with XSDConstants.isOrIsDerivedFrom(baseType, localName, namespace); if (rootType.isCircular()) { return true; } // Otherwise continue to traverse upwards return isTypeDerivedFrom(baseType, namespace, localName); } } /** * Returns the corresponding cmnode of the specified XML Schema node. * * @param target - * an XML Schema node * @return the corresponding cmnode. */ public static CMNode getAdapter(Notifier o) { return (CMNode) xsdAdapterFactoryImpl.adapt(o); } /** * Adapted from public String getPrefix(String ns, boolean withColon) in class * TypesHelper found in org.eclipse.wst.xsd.editor plugin. * * @param schema - * the relevant schema * @param ns - * the relevant namespace */ public static String getPrefix(XSDSchema schema, String ns) { String key = ""; if ((schema != null) && (ns != null)) { Map map = schema.getQNamePrefixToNamespaceMap(); Iterator iter = map.keySet().iterator(); while (iter.hasNext()) { Object keyObj = iter.next(); Object value = map.get(keyObj); if (value != null && value.toString().equals(ns)) { if (keyObj != null) { key = keyObj.toString(); } else { key = ""; } break; } } } return key; } /** * The Factory for the XSD adapter model. It provides a create method for each * non-abstract class of the model. */ public static class XSDAdapterFactoryImpl extends AdapterFactoryImpl { public Adapter createAdapter(Notifier target) { XSDSwitch xsdSwitch = new XSDSwitch() { public Object caseXSDWildcard(XSDWildcard object) { return new XSDWildcardAdapter(object); } public Object caseXSDModelGroupDefinition(XSDModelGroupDefinition object) { return new XSDModelGroupDefinitionAdapter(object); } public Object caseXSDAttributeUse(XSDAttributeUse object) { return new XSDAttributeUseAdapter(object); } public Object caseXSDElementDeclaration(XSDElementDeclaration object) { return new XSDElementDeclarationAdapter(object); } public Object caseXSDModelGroup(XSDModelGroup object) { return new XSDModelGroupAdapter(object); } public Object caseXSDSchema(XSDSchema object) { return new XSDSchemaAdapter(object); } }; Object o = xsdSwitch.doSwitch((EObject) target); Adapter result = null; if (o instanceof Adapter) { result = (Adapter) o; } else { Thread.dumpStack(); } return result; } public Adapter adapt(Notifier target) { return adapt(target, this); } } /** * XSDBaseAdapter -- an abstract base node in the model. All other model nodes * are derived from it. */ public static abstract class XSDBaseAdapter extends CMNodeImpl { protected CMNodeListImpl documentation = new CMNodeListImpl(); /** * Returns the name of the node. The default value is an empty string value. * All derived classes must override this method if they do not want the * default value. * * @return the name of the node. */ public String getNodeName() { return ""; } /** * Returns true of the given factory is the factory for this XSD adapter * model. * * @param type - * a factory * @return true if the type is the adapter factory for this model. */ public boolean isAdapterForType(Object type) { return type == xsdAdapterFactoryImpl; } /** * Returns true if the property is supported for this class. * * @param propertyName - * name of a property * @return true if the property is supported. */ public boolean supports(String propertyName) { return propertyName.equals(PROPERTY_NS_PREFIX_QUALIFICATION) || propertyName.equals(PROPERTY_NILLABLE) || propertyName.equals(PROPERTY_USES_LOCAL_ELEMENT_DECLARATIONS) || propertyName.equals(PROPERTY_DOCUMENTATION) || propertyName.equals(PROPERTY_DOCUMENTATION_SOURCE) || propertyName.equals(PROPERTY_DOCUMENTATION_LANGUAGE) || propertyName.equals(PROPERTY_MOF_NOTIFIER) || propertyName.equals(PROPERTY_DEFINITION_INFO) || propertyName.equals(PROPERTY_DEFINITION) || propertyName.equals(PROPERTY_CMDOCUMENT) || propertyName.equals(PROPERTY_IS_NAME_SPACE_AWARE) || propertyName.equals(PROPERTY_SPEC) || super.supports(propertyName); } /** * Returns the value of the 'Nillable' attribute. This represents the * nillable infoset property. The default value is false. All derived * classes must override this method if they do not want the default value. * * @return the value of the 'Nillable' attribute. */ public boolean isNillable() { return false; } /** * Returns the cmdocument that is the owner of this cmnode. The default * value is null; All derived classes must override this method if they do * not want the default value. * * @return the cmdocument corresponding to this cmnode. */ public CMDocument getCMDocument() { return null; } /** * Return a list of documentation elements. The default value is an empty * CMNodeList; All derived classes must override this method if they do not * want the default value. * * @return a list of documentation elements. */ protected CMNodeList getDocumentation() { return documentation; } /** * Returns the property value for the property name. Returns null if the * property is not supported. * * @param propertyName - * name of a property * @return the property value for the property name. */ public Object getProperty(String propertyName) { Object result = null; if (propertyName.equals(PROPERTY_CMDOCUMENT)) { result = getCMDocument(); } else if (propertyName.equals(PROPERTY_DOCUMENTATION)) { result = getDocumentation(); } else if (propertyName.equals(PROPERTY_USES_LOCAL_ELEMENT_DECLARATIONS)) { result = Boolean.TRUE; } else if (propertyName.equals(PROPERTY_IS_NAME_SPACE_AWARE)) { result = Boolean.TRUE; } else if (propertyName.equals(PROPERTY_NS_PREFIX_QUALIFICATION)) { result = getNSPrefixQualification(); } else if (propertyName.equals(PROPERTY_NILLABLE)) { result = isNillable() ? xsiDocument.nilAttribute : null; } else if (propertyName.equals(PROPERTY_MOF_NOTIFIER)) { result = getKey(); } else if (propertyName.equals(PROPERTY_SPEC)) { result = getSpec(); } else { result = super.getProperty(propertyName); { CMDocument cmDocument = getCMDocument(); if (cmDocument instanceof XSDSchemaAdapter) { AnnotationMap map = ((XSDSchemaAdapter) cmDocument).annotationMap; if (map != null) { String spec = getSpec(); if (spec != null) { result = map.getProperty(getSpec(), propertyName); } } } } } return result; } /* * Returns the value of the form [attribute] which affects the target * namespace of locally scoped features. The default value is null. All * derived classes must override this method if they do not want the default * value. @return the value of the form [attribute]. */ public Object getNSPrefixQualification() { return null; } /** * Returns a general XPath expression for the node. * * @return a general XPath expression for the node. */ public String getSpec() { return "//" + getNodeName(); } } /** * XSDSchemaAdapter implements CMDocument. A representation of the model * object 'Schema'. */ public static class XSDSchemaAdapter extends XSDBaseAdapter implements CMDocument { protected XSDSchema xsdSchema; protected CMNamedNodeMapImpl namedNodeMap; protected CMNamedNodeMapImpl entityNodeMap; protected AnnotationMap annotationMap = new AnnotationMap(); protected Hashtable substitutionGroupTable; /** * Constructor. * * @param xsdSchema - * the schema node. */ public XSDSchemaAdapter(XSDSchema xsdSchema) { this.xsdSchema = xsdSchema; } /** * Returns the key for this cmnode which is the corresponding XML Schema * node. * * @return the key for this cmnode. */ public Object getKey() { return xsdSchema; } /** * Returns the filename. * * @return the filename. */ public String getNodeName() { // See buildCMDocument() above. return xsdSchema.getSchemaLocation(); } /** * Returns true if the property is supported for this class. * * @param propertyName - * name of a property * @return true if the property is supported. */ public boolean supports(String propertyName) { return propertyName.equals(PROPERTY_TARGET_NAMESPACE_URI) || propertyName.equals(PROPERTY_IMPORTED_NAMESPACE_INFO) || propertyName.equals(PROPERTY_NAMESPACE_INFO) || propertyName.equals(PROPERTY_ELEMENT_FORM_DEFAULT) || propertyName.equals(PROPERTY_ANNOTATION_MAP) || super.supports(propertyName); } /** * Returns true if a prefix is globally required for elements. * * @param xsdSchema - * the corresponding schema node. * @return true if a prefix is globally required for elements. */ protected boolean isPrefixRequired(XSDSchema xsdSchema) { boolean result = true; if (xsdSchema.isSetElementFormDefault()) result = !(xsdSchema.getElementFormDefault().getValue() == XSDForm.QUALIFIED); return result; } /** * Returns the property value for the property name. Returns null if the * property is not supported. * * @param propertyName - * name of a property * @return the property value for the property name. */ public Object getProperty(String propertyName) { Object result = null; if (propertyName.equals(PROPERTY_TARGET_NAMESPACE_URI)) { result = xsdSchema.getTargetNamespace(); } else if (propertyName.equals(PROPERTY_IMPORTED_NAMESPACE_INFO)) { List list = new Vector(); getImportedNamespaceInfo(xsdSchema, list); result = list; } else if (propertyName.equals(PROPERTY_NAMESPACE_INFO)) { List list = new Vector(); NamespaceInfo info = new NamespaceInfo(); info.uri = xsdSchema.getTargetNamespace(); info.prefix = getPrefix(xsdSchema, info.uri); info.locationHint = null; // note that this locationHint info is null // for the root xsd file info.isPrefixRequired = isPrefixRequired(xsdSchema); list.add(info); getImportedNamespaceInfo(xsdSchema, list); result = list; } else if (propertyName.equals(PROPERTY_COMPLETE_NAMESPACE_INFO)) { result = getAllNamespaceInfo(); } else if (propertyName.equals(PROPERTY_ELEMENT_FORM_DEFAULT)) { result = xsdSchema.getElementFormDefault().getName(); } else if (propertyName.equals(PROPERTY_ANNOTATION_MAP)) { result = annotationMap; } else if (propertyName.equals("allElements")) { result = getAllElements(); } else if (propertyName.startsWith("getElementForType#")) { int index = propertyName.indexOf("#"); String typeName = propertyName.substring(index + 1, propertyName.length()); // // XSDTypeDefinition td = xsdSchema.resolveTypeDefinition(typeName); if (td != null) { LocalElementVisitor localElementVisitor = new LocalElementVisitor(); localElementVisitor.visitTypeDefinition(td); result = localElementVisitor.getCMNamedNodeMap(); } } else { result = super.getProperty(propertyName); } return result; } /** * Gather information on namespaces used in external references. * * @param theXSDSchema - * the corresponding schema node * @param list - * the list of imported namespaces. */ public void getImportedNamespaceInfo(XSDSchema theXSDSchema, List list) { for (Iterator iterator = theXSDSchema.getContents().iterator(); iterator.hasNext();) { XSDSchemaContent content = (XSDSchemaContent) iterator.next(); if (content instanceof XSDImport) { XSDImport xImport = (XSDImport) content; XSDSchema importedXSDSchema = xImport.getResolvedSchema(); NamespaceInfo info = new NamespaceInfo(); info.uri = xImport.getNamespace(); info.prefix = getPrefix(importedXSDSchema, info.uri); info.locationHint = xImport.getSchemaLocation(); if (importedXSDSchema != null) { info.isPrefixRequired = isPrefixRequired(importedXSDSchema); } list.add(info); } } } /** * Returns set of named (top-level) element declarations for this schema * node. * * @return a set of named (top-level) element declarations. */ public CMNamedNodeMap getElements() { if (namedNodeMap == null) { namedNodeMap = new CMNamedNodeMapImpl(); // Note that if we call xsdSchema.getElementDeclarations() // we get 'more' elements than we really want since we also // get 'imported' elements. Below we test to ensure the elements // actually have the same target namespace as the schema. String targetNamespace = xsdSchema.getTargetNamespace(); for (Iterator i = xsdSchema.getElementDeclarations().iterator(); i.hasNext();) { XSDElementDeclaration ed = (XSDElementDeclaration) i.next(); if (targetNamespace != null ? targetNamespace.equals(ed.getTargetNamespace()) : ed.getTargetNamespace() == null) { XSDElementDeclarationAdapter adapter = (XSDElementDeclarationAdapter) getAdapter(ed); namedNodeMap.getHashtable().put(adapter.getNodeName(), adapter); } } } return namedNodeMap; } /** * Returns the built-in entity declarations. * * @return the built-in entity declarations. */ public CMNamedNodeMap getEntities() { if (entityNodeMap == null) { entityNodeMap = new CMNamedNodeMapImpl(); // add the built in entity declarations entityNodeMap.getHashtable().put("amp", new CMEntityDeclarationImpl("amp", "&")); entityNodeMap.getHashtable().put("lt", new CMEntityDeclarationImpl("lt", "<")); entityNodeMap.getHashtable().put("gt", new CMEntityDeclarationImpl("gt", ">")); entityNodeMap.getHashtable().put("quot", new CMEntityDeclarationImpl("quot", "\"")); entityNodeMap.getHashtable().put("apos", new CMEntityDeclarationImpl("apos", "'")); } return entityNodeMap; } /** * Returns the type of the node. The types are defined in CMNode class * (ANY_ELEMENT, ATTRIBUTE_DECLARATION, DATA_TYPE, DOCUMENT, * ELEMENT_DECLARATION, ENTITY_DECLARATION, GROUP, NAME_SPACE or * DOCUMENTATION). * * @return the type of this node. */ public int getNodeType() { return DOCUMENT; } /* * Returns null. !!! Why are we not implementing this???? @return null. */ public CMNamespace getNamespace() { return null; } /** * Returns this. * * @return this. */ public CMDocument getCMDocument() { return this; } public CMNamedNodeMap getAllElements() { CMNamedNodeMapImpl map = new CMNamedNodeMapImpl(); for (Iterator i = getElements().iterator(); i.hasNext(); ) { CMElementDeclaration ed = (CMElementDeclaration)i.next(); map.put(ed); addLocalElementDefinitions(map, ed); } return map; } protected void addLocalElementDefinitions(CMNamedNodeMapImpl map, CMElementDeclaration parentElementDeclaration) { CMNamedNodeMap localElementMap = parentElementDeclaration.getLocalElements(); for (Iterator i = localElementMap.iterator(); i.hasNext(); ) { CMElementDeclaration ed = (CMElementDeclaration)i.next(); if (map.getNamedItem(ed.getNodeName()) == null) { map.put(ed); addLocalElementDefinitions(map, ed); } } } /** * Generates a List of NamespaceInfo objects corresponding to the target namespace of the given schema * and the target namespaces of all its recursively imported/included referenced schemas. All namespace * prefixes in the list are guaranteed to be unique. Prefix collitions are resolved by concatenating * integer numbers to each repeated prefix found i.e. tns, tns1, tns2... * All schema locations in the list are formated as encoded URIs relative to the given schema. * Schemas that are imported/included but not referenced will not appear in the list. * @return List of NamespaceInfo objects * */ public List getAllNamespaceInfo() { List namespaceList = new ArrayList(); List resources = xsdSchema.eResource().getResourceSet().getResources(); Iterator i = resources.iterator(); while(i.hasNext()) { XSDResourceImpl resource = (XSDResourceImpl) i.next(); if(resource.isLoaded()) { XSDSchema schema = resource.getSchema(); if(!isDataInNamespaceList(namespaceList, 0, schema.getTargetNamespace())) { NamespaceInfo info = new NamespaceInfo(); info.uri = schema.getTargetNamespace(); info.isPrefixRequired = isPrefixRequired(schema); info.prefix = getPrefix(schema,schema.getTargetNamespace()); if("http://www.w3.org/XML/1998/namespace".equals(info.uri)) { info.prefix = "xml"; } else if("http://www.w3.org/2000/xmlns".equals(info.uri)) { info.prefix = "xmlns"; } else { if(info.uri != null && info.uri != "") { int n = 1; if(info.prefix == null || info.prefix.equals("")) { info.prefix = "p"; } String prefix = info.prefix; while(isDataInNamespaceList(namespaceList, 1, info.prefix)) { info.prefix = prefix + n++; } } } URI relative = URI.createURI(xsdSchema.getSchemaLocation(), true); URI absolute = URI.createURI(schema.getSchemaLocation(), true); URI resolvedRelative = absolute.deresolve(relative); info.locationHint = resolvedRelative.toString(); namespaceList.add(info); } } } return namespaceList; } /** * Searches for a given value in a list of namespaces. * * @param namespaceList: List of NamespaceInfo objects * @param data: integer representing the data in the namespace as follows: * 0: uri * 1: prefix * 2: locationHint * @param value String containing the value for search * @return true if the value is found, false otherwise */ private boolean isDataInNamespaceList(List namespaceList, int data, String value) { if (namespaceList != null) { Iterator i = namespaceList.iterator(); while (i.hasNext()) { NamespaceInfo namespaceInfo = (NamespaceInfo) i.next(); switch(data) { case 0: if (namespaceInfo.uri != null && namespaceInfo.uri.equals(value)) { return true; } case 1: if (namespaceInfo.prefix != null && namespaceInfo.prefix.equals(value)) { return true; } case 2: if (namespaceInfo.locationHint != null && namespaceInfo.locationHint.equals(value)) { return true; } } } } return false; } } /** * XSDAttributeUseAdapter implements CMAttributeDeclaration. A representation * of the model object 'Attribute Use'. */ public static class XSDAttributeUseAdapter extends XSDBaseAdapter implements CMAttributeDeclaration { // provides access to the XML Schema node protected XSDAttributeUse xsdAttributeUse; // provides access to the type of the attribute protected CMDataType dataType = new DataTypeImpl(); /** * Constructor. * * @param xsdAttributeUse - * the XML Schema node. */ public XSDAttributeUseAdapter(XSDAttributeUse xsdAttributeUse) { this.xsdAttributeUse = xsdAttributeUse; } /** * Returns the key for this cmnode which is the corresponding XML Schema * node. * * @return the key for this cmnode. */ public Object getKey() { return xsdAttributeUse; } /** * Returns a general XPath expression for the node. * * @return a general XPath expression for the node. */ public String getSpec() { return "//@" + getAttrName(); } /** * Returns the type of the node. The types are defined in CMNode class * (ANY_ELEMENT, ATTRIBUTE_DECLARATION, DATA_TYPE, DOCUMENT, * ELEMENT_DECLARATION, ENTITY_DECLARATION, GROUP, NAME_SPACE or * DOCUMENTATION). * * @return the type of this node. */ public int getNodeType() { return ATTRIBUTE_DECLARATION; } /** * Returns the name of the node. Similar to getAttrName(). * * @return the name of the node. */ public String getNodeName() { return getAttrName(); } /** * getEnumAttr method * * @return java.util.Enumeration * @deprecated -- to be replaced in future with additional CMDataType * methods (currently found on CMDataTypeHelper) */ public Enumeration getEnumAttr() { return Collections.enumeration(Collections.EMPTY_LIST); } /** * Returns the name of this attribute. Similar to getNodeName(). * * @return the name of this attribute. */ public String getAttrName() { return xsdAttributeUse.getAttributeDeclaration().getName(); } /** * Returns the type of the attribute. * * @return the type of the attribute. */ public CMDataType getAttrType() { return dataType; } /** * Returns the value of the default or fixed constraint. * * @return the value of the default or fixed constraint. */ public String getDefaultValue() { return dataType.getImpliedValue(); } /** * Returns the usage constraint for this attribute. The usages are defined * in CMAttributeDeclaration class (OPTIONAL, REQUIRED, FIXED or * PROHIBITED). * * @return the usage constraint for this attribute. */ public int getUsage() { int useKind = OPTIONAL; switch (xsdAttributeUse.getUse().getValue()) { case XSDAttributeUseCategory.OPTIONAL : { useKind = OPTIONAL; break; } case XSDAttributeUseCategory.PROHIBITED : { useKind = PROHIBITED; break; } case XSDAttributeUseCategory.REQUIRED : { useKind = REQUIRED; break; } } return useKind; } /* * Returns the value of the form [attribute] which affects the target * namespace of locally scoped features. If the form is not set on this * attribute, then see if there is a globally defined default. @return the * value of the form [attribute]. */ public Object getNSPrefixQualification() { String form = null; if (xsdAttributeUse.getContent() != xsdAttributeUse.getAttributeDeclaration()) { form = "qualified"; } else if (xsdAttributeUse.getContent().isSetForm()) { form = xsdAttributeUse.getContent().getForm().getName(); } else { XSDSchema schema = xsdAttributeUse.getSchema(); if (schema != null) form = schema.getAttributeFormDefault().getName(); } return form; } /** * Return a list of documentation elements. * * @return a list of documentation elements. */ protected CMNodeList getDocumentation() { // Check if it is an attribute reference first XSDAttributeDeclaration xsdAttributeRef = xsdAttributeUse.getContent(); if (xsdAttributeRef != null && xsdAttributeRef.isAttributeDeclarationReference()) { // Determine if it has annotations boolean refHasDocumentation = false; XSDAnnotation refAnnotation = xsdAttributeRef.getAnnotation(); if (refAnnotation != null) { // Determine if there is documentation if (!refAnnotation.getUserInformation().isEmpty()) { refHasDocumentation = true; } } if (refHasDocumentation) return getDocumentations(refAnnotation); } // Otherwise proceed with getting the documentation as usual XSDAttributeDeclaration xsdAttributeDeclaration = xsdAttributeUse.getAttributeDeclaration(); XSDAnnotation annotation = xsdAttributeDeclaration.getAnnotation(); return getDocumentations(annotation); } /** * Returns the cmdocument that is the owner of this cmnode. * * @return the cmdocument corresponding to this cmnode. */ public CMDocument getCMDocument() { return (CMDocument) getAdapter(xsdAttributeUse.getSchema()); } /** * XSDAttributeUseAdapter.DataTypeImpl An inner class to hold type * information for this attribute. */ public class DataTypeImpl implements CMDataType { /** * Returns the type of the node. The types are defined in CMNode class * (ANY_ELEMENT, ATTRIBUTE_DECLARATION, DATA_TYPE, DOCUMENT, * ELEMENT_DECLARATION, ENTITY_DECLARATION, GROUP, NAME_SPACE or * DOCUMENTATION). * * @return the type of this node. */ public int getNodeType() { return CMNode.DATA_TYPE; } /** * Returns the name of the attribute type. Same as getDataTypeName(). * * @return the name of the attribute type. */ public String getNodeName() { return getDataTypeName(); } /** * Returns true if the property is supported for this class. * * @param propertyName - * name of a property * @return true if the property is supported. */ public boolean supports(String propertyName) { return (PROPERTY_WHITESPACE_FACET.equals(propertyName)); } /** * Returns the property value for the property name. Returns null if the * property is not supported. * * @param propertyName - * name of a property * @return the property value for the property name. */ public Object getProperty(String propertyName) { if(PROPERTY_WHITESPACE_FACET.equals(propertyName)) return getWhiteSpaceFacetValue(); return null; } /** * Returns the name of the attribute type. Same as getNodeName(). * * @return the name of the attribute type. */ public String getDataTypeName() { XSDSimpleTypeDefinition sc = xsdAttributeUse.getAttributeDeclaration().getTypeDefinition(); String typeName = sc.getName(); return typeName != null ? typeName : "string"; //$NON-NLS-1$ } /** * Returns the kind of constraint: none, default or fixed. The kinds are * defined in CMDataType class (IMPLIED_VALUE_NONE, IMPLIED_VALUE_FIXED or * IMPLIED_VALUE_DEFAULT). * * @return the kind of constraint: none, default or fixed. */ public int getImpliedValueKind() { int result = IMPLIED_VALUE_NONE; if (xsdAttributeUse.isSetConstraint()) { if (xsdAttributeUse.getConstraint().getValue() == XSDConstraint.DEFAULT) result = IMPLIED_VALUE_DEFAULT; else if (xsdAttributeUse.getConstraint().getValue() == XSDConstraint.FIXED) result = IMPLIED_VALUE_FIXED; } return result; } /** * Returns the value of the default or fixed constraint. * * @return the value of the default or fixed constraint. */ public String getImpliedValue() { String result = null; if (xsdAttributeUse.isSetConstraint()) { result = xsdAttributeUse.getLexicalValue(); } return result; } /** * Returns the enumerated values for the attribute type. * * @return the enumerated values for the attribute type. */ public String[] getEnumeratedValues() { return getEnumeratedValuesForType(getXSDType()); } /** * Generate a valid value for the attribute based on its type. * * @return a valid value for the attribute based on its type. */ public String generateInstanceValue() { XSDAttributeDeclaration attr = xsdAttributeUse.getAttributeDeclaration(); return XSDTypeUtil.getInstanceValue(attr.getResolvedAttributeDeclaration().getTypeDefinition()); } /** * Returns the corresponding XML Schema type definition. * * @return the corresponding XML Schema type definition. */ protected XSDTypeDefinition getXSDType() { XSDAttributeDeclaration attr = xsdAttributeUse.getAttributeDeclaration(); return attr.getResolvedAttributeDeclaration().getTypeDefinition(); } /** * Obtains the whitespace facet of the XSD simple type. * * @return The whitespace facet for the XSD type. If none is * defined, or it is a complex type, null. */ private String getWhiteSpaceFacetValue() { XSDSimpleTypeDefinition def = getXSDType().getSimpleType(); return (def != null && def.getEffectiveWhiteSpaceFacet() != null) ? def.getEffectiveWhiteSpaceFacet().getLexicalValue() : null ; } } } /** * ElementDeclarationBaseImpl implements CMElementDeclaration. This is the * base class for XSDElementDeclaration and DerivedElementDeclarationImpl. * * Abstract methods in this class are: public abstract Object getKey(); public * abstract Object getNSPrefixQualification(); public abstract * XSDElementDeclaration getXSDElementDeclaration(); public abstract * XSDTypeDefinition getXSDType(); public abstract List getXSITypes(); public * abstract CMElementDeclaration getDerivedElementDeclaration(String * uriQualifiedTypeName); public abstract CMNode getDefinition(); public * abstract String getDefinitionInfo(); public abstract CMNodeListImpl * getSubstitutionGroup(); */ public static abstract class ElementDeclarationBaseImpl extends XSDBaseAdapter implements CMElementDeclaration { protected CMDataType dataType = new DataTypeImpl(); protected CMNamedNodeMap namedNodeMap; /** * Returns corresponding XML Schema element declaration. * * @return corresponding XML Schema element declaration. */ protected abstract XSDElementDeclaration getXSDElementDeclaration(); /** * Returns corresponding XML Schema element declaration. * * @return corresponding XML Schema element declaration. */ protected abstract XSDElementDeclaration getResolvedXSDElementDeclaration(); /** * Returns the type of the node. The types are defined in CMNode class * (ANY_ELEMENT, ATTRIBUTE_DECLARATION, DATA_TYPE, DOCUMENT, * ELEMENT_DECLARATION, ENTITY_DECLARATION, GROUP, NAME_SPACE or * DOCUMENTATION). * * @return the type of this node. */ public int getNodeType() { return ELEMENT_DECLARATION; } /** * Returns the name of the node. The same as getElementName(). * * @return the name of the node. */ public String getNodeName() { return getElementName(); } /** * Returns the name of this element. The same as getNodeName(). * * @return the name of this element. */ public String getElementName() { String result = getResolvedXSDElementDeclaration().getName(); return result != null ? result : ""; } /** * Returns true if the property is supported for this class. * * @param propertyName - * name of a property * @return true if the property is supported. */ public boolean supports(String propertyName) { return propertyName.equals(PROPERTY_XSITYPES) || propertyName.equals(PROPERTY_DERIVED_ELEMENT_DECLARATION) || propertyName.equals(PROPERTY_SUBSTITUTION_GROUP) || propertyName.equals(PROPERTY_ABSTRACT) || propertyName.equals(PROPERTY_EXTERNALLY_DERIVED_ELEMENT_DECLARATION) || super.supports(propertyName); } /** * Returns the key for this cmnode which is the corresponding XML Schema * node. * * @return the key for this cmnode. */ public abstract Object getKey(); /** * Returns the set of attributes defined for this element. * * @return the set of attributes defined for this element. */ public CMNamedNodeMap getAttributes() { CMNamedNodeMapImpl map = new CMNamedNodeMapImpl(); XSDTypeDefinition td = getXSDType(); getAttributes(map, td); addXSITypeAttribute(map); return map; } /** * Gather the set of attributes defined for this element. * * @param map - * used for returning the set of attributes. * @param xsdTypeDefinition - * the type definition for this element. */ public void getAttributes(CMNamedNodeMapImpl map, XSDTypeDefinition xsdTypeDefinition) { if (xsdTypeDefinition instanceof XSDComplexTypeDefinition) { XSDComplexTypeDefinition ctd = (XSDComplexTypeDefinition) xsdTypeDefinition; for (Iterator i = ctd.getAttributeUses().iterator(); i.hasNext();) { XSDAttributeUse xsdAttributeUse = (XSDAttributeUse) i.next(); XSDAttributeUseAdapter adapter = (XSDAttributeUseAdapter) getAdapter(xsdAttributeUse); if (adapter != null && adapter.getNodeName() != null) { map.getHashtable().put(adapter.getNodeName(), adapter); } } } } /** * Returns the content for this element. * * @return the content for this element. */ public CMContent getContent() { CMContent result = null; XSDTypeDefinition td = getXSDType(); if (td instanceof XSDComplexTypeDefinition) { DerivedChildVisitor dcv = new DerivedChildVisitor(td); dcv.visitTypeDefinition(td); CMNodeList nodeList = dcv.getChildNodeList(); if (nodeList.getLength() > 1) { result = new CMGroupImpl(nodeList, CMGroup.SEQUENCE); } else if (nodeList.getLength() > 0) { result = (CMContent) nodeList.item(0); } } return result; } /** * Returns the content type of this element. The content type is defined in * CMElementDeclaration (ANY, EMPTY, ELEMENT, MIXED, PCDATA or CDATA). * * @return the content type of this element. */ public int getContentType() { int contentType = EMPTY; XSDTypeDefinition td = getXSDType(); if (td instanceof XSDSimpleTypeDefinition) { String typeName = td.getName(); if (typeName != null && typeName.equals("anyType")) { contentType = ANY; } else { contentType = PCDATA; } } else if (td instanceof XSDComplexTypeDefinition) { XSDContentTypeCategory category = ((XSDComplexTypeDefinition) td).getContentTypeCategory(); if (category != null) { switch (category.getValue()) { case XSDContentTypeCategory.ELEMENT_ONLY : contentType = ELEMENT; break; case XSDContentTypeCategory.EMPTY : contentType = EMPTY; break; case XSDContentTypeCategory.MIXED : contentType = MIXED; break; case XSDContentTypeCategory.SIMPLE : contentType = PCDATA; break; } } } return contentType; } /** * Returns the name of the element type. * * @return the name of the element type. */ public CMDataType getDataType() { CMDataType result = null; int contentType = getContentType(); boolean hasDataType = contentType == PCDATA || contentType == MIXED; if (hasDataType) { result = dataType; } return result; } /** * Returns the value of 'Min Occurs' attribute. The default value is "1". * * @return the value of the 'Min Occurs' attribute. */ public int getMinOccur() { return getMinOccurs(getXSDElementDeclaration()); } /** * Returns the value of the 'Max Occurs' attribute. The default value is * "1". * * @return the value of the 'Max Occurs' attribute. */ public int getMaxOccur() { return getMaxOccurs(getXSDElementDeclaration()); } /** * Returns the referenced element declaration if this is an element * reference. Otherwise it returns itself. * * @return an element declaration. */ protected abstract CMNode getDefinition(); /** * Returns a string indicating whether the element declaration is global or * local. Returns null if this is an element reference. * * @return a string indicating whether the element declaration is global or * local. */ protected abstract String getDefinitionInfo(); /** * Returns the elements local to this element declaration. * * @return the elements local to this element declaration. */ public CMNamedNodeMap getLocalElements() { if (namedNodeMap == null) { LocalElementVisitor localElementVisitor = new LocalElementVisitor(); localElementVisitor.visitTypeDefinition(getXSDType()); namedNodeMap = localElementVisitor.getCMNamedNodeMap(); } return namedNodeMap; } /** * Returns the property value for the property name. Returns null if the * property is not supported. * * @param propertyName - * name of a property * @return the property value for the property name. */ public Object getProperty(String propertyName) { Object result = null; if (propertyName.equals(PROPERTY_DEFINITION_INFO)) { result = getDefinitionInfo(); } else if (propertyName.equals(PROPERTY_DEFINITION)) { result = getDefinition(); } else if (propertyName.equals(PROPERTY_XSITYPES)) { result = getXSITypes(); } else if (propertyName.startsWith(PROPERTY_DERIVED_ELEMENT_DECLARATION)) { int index = propertyName.indexOf("="); if (index != -1) { String uriQualifiedTypeName = propertyName.substring(index + 1); result = getDerivedElementDeclaration(uriQualifiedTypeName); } } else if (propertyName.startsWith(PROPERTY_EXTERNALLY_DERIVED_ELEMENT_DECLARATION)) { int index = propertyName.indexOf("="); if (index != -1) { String reference = propertyName.substring(index + 1); result = getExternallyDerivedElementDeclaration(reference); } } else if (propertyName.equals(PROPERTY_SUBSTITUTION_GROUP)) { return getSubstitutionGroup(); } else if (propertyName.equals(PROPERTY_SUBSTITUTION_GROUP_VALUE)) { return getSubstitutionGroupValue(); } else if (propertyName.equals(PROPERTY_ABSTRACT)) { return getAbstract(); } else { result = super.getProperty(propertyName); } return result; } /** * Returns the value of the 'Nillable' attribute. This represents the * nillable infoset property. The default value is false. * * @return the value of the 'Nillable' attribute. */ public boolean isNillable() { if (getXSDElementDeclaration().isSetNillable()) return getXSDElementDeclaration().isNillable(); else return false; } /** * Returns the value of the substitutionGroup attribute. * * @return value of the substitutionGroup attribute */ public String getSubstitutionGroupValue() { XSDElementDeclaration xsdElementDeclaration = getResolvedXSDElementDeclaration(); if(xsdElementDeclaration != null) { Element element = xsdElementDeclaration.getElement(); if(element != null) { if (element.hasAttribute(XSDConstants.SUBSTITUTIONGROUP_ATTRIBUTE)) return element.getAttribute(XSDConstants.SUBSTITUTIONGROUP_ATTRIBUTE); else return null; } } return ""; } /** * Returns whether the element is 'Abstract'. * * @return true if the element is 'Abstract'. */ public Boolean getAbstract() { boolean result = getResolvedXSDElementDeclaration().isAbstract(); // TODO... how do we handle elements with abstract type's ? return result ? Boolean.TRUE : Boolean.FALSE; } /** * Returns a list of documentation elements. * * @return a list of documentation elements. */ protected CMNodeList getDocumentation() { XSDElementDeclaration xsdElementDeclaration = getXSDElementDeclaration(); XSDAnnotation annotation = xsdElementDeclaration.getAnnotation(); // Need to check to see if there are any documentation elements. Just because // there is an annotation element doesn't mean that the documentation element is // also there, as it could contain just appinfo elements. boolean hasDocumentation = false; if (annotation != null) { if (!annotation.getUserInformation().isEmpty()) { hasDocumentation = true; } } // The element may not have annotation and if it is referenced // check the referenced attribute for the annotations. if (hasDocumentation == false) { if (xsdElementDeclaration.isElementDeclarationReference()) { annotation = xsdElementDeclaration.getResolvedElementDeclaration().getAnnotation(); } } return getDocumentations(annotation); } /** * Returns the corresponding XML Schema type definition. * * @return the corresponding XML Schema type definition. */ protected abstract XSDTypeDefinition getXSDType(); /** * Returns a list of type names. * * @return a list of type names. */ protected abstract List getXSITypes(); /** * Return the element declaration corresponding to the given uri qualified * type name. * * @param uriQualifiedTypeName - * a uri qualified type name * @return corresponding element declaration. */ protected abstract CMElementDeclaration getDerivedElementDeclaration(String uriQualifiedTypeName); protected CMElementDeclaration getExternallyDerivedElementDeclaration(String reference) { return null; } /** * Returns a list of documentation elements. * * @return a list of documentation elements. */ protected void addXSITypeAttribute(CMNamedNodeMapImpl map) { List list = getXSITypes(); int listSize = list.size(); if (listSize > 1) { CMDataType dataType = new CMDataTypeImpl("typeNames", (String) null); CMAttributeDeclarationImpl attribute = new CMAttributeDeclarationImpl("type", CMAttributeDeclaration.OPTIONAL, dataType); attribute.setCMDocument(xsiDocument); attribute.setPrefixQualification(true); attribute.setXSITypes(list); // See https://bugs.eclipse.org/bugs/show_bug.cgi?id=225447 // For now, don't clobber the attribute with the same 'type' name defined in the grammar // with the xsi:type attribute. The impact of this change will be that for content assist, the non-xsi // type attribute will be presented; the generated XML from XSD will have this attribute created, and // not the xsi:type attribute. Hashtable hashTable = map.getHashtable(); String name = attribute.getNodeName(); if (!hashTable.containsKey(name)) hashTable.put(name, attribute); } } /** * Returns the cmdocument that is the owner of this cmnode. * * @return the cmdocument corresponding to this cmnode. */ public CMDocument getCMDocument() { XSDSchema schema = getResolvedXSDElementDeclaration().getSchema(); if (schema == null) return null; else return (CMDocument) getAdapter(schema); } /** * Returns the substitution group for this element. The group consists of: * 1. the element declaration itself 2. and any element declaration that has * a {substitution group affiliation} in the group * * @return the substitution group for this element. */ protected abstract CMNodeListImpl getSubstitutionGroup(); /* * XSDElementDeclarationAdapter.DataTypeImpl An inner class to hold type * information for this element. */ public class DataTypeImpl implements CMDataType { /** * Returns the type of the node. The types are defined in CMNode class * (ANY_ELEMENT, ATTRIBUTE_DECLARATION, DATA_TYPE, DOCUMENT, * ELEMENT_DECLARATION, ENTITY_DECLARATION, GROUP, NAME_SPACE or * DOCUMENTATION). * * @return the type of this node. */ public int getNodeType() { return CMNode.DATA_TYPE; } /** * Returns the name of the element type. Same as getDataTypeName(). * * @return the name of the element type. */ public String getNodeName() { return getDataTypeName(); } /** * Returns true if the property is supported for this class. * * @param propertyName - * name of a property * @return true if the property is supported. */ public boolean supports(String propertyName) { return (PROPERTY_WHITESPACE_FACET.equals(propertyName)); } /** * Returns the property value for the property name. Returns null if the * property is not supported. * * @param propertyName - * name of a property * @return the property value for the property name. */ public Object getProperty(String propertyName) { if(PROPERTY_WHITESPACE_FACET.equals(propertyName)) return getWhiteSpaceFacetValue(); return null; } /** * Returns the name of the element type. Same as getNodeName(). * * @return the name of the element type. */ public String getDataTypeName() { String typeName = null; XSDSimpleTypeDefinition std = getXSDType().getSimpleType(); if (std != null) typeName = std.getName(); return typeName != null ? typeName : "string"; //$NON-NLS-1$ } /** * Returns the kind of constraint: none, default or fixed. The kinds are * defined in CMDataType class (IMPLIED_VALUE_NONE, IMPLIED_VALUE_FIXED or * IMPLIED_VALUE_DEFAULT). * * @return the kind of constraint: none, default or fixed. */ public int getImpliedValueKind() { int result = IMPLIED_VALUE_NONE; if (getXSDElementDeclaration().isSetConstraint()) { if (getXSDElementDeclaration().getConstraint().getValue() == XSDConstraint.DEFAULT) result = IMPLIED_VALUE_DEFAULT; else if (getXSDElementDeclaration().getConstraint().getValue() == XSDConstraint.FIXED) result = IMPLIED_VALUE_FIXED; } return result; } /** * Returns the value of the default or fixed constraint. * * @return the value of the default or fixed constraint. */ public String getImpliedValue() { String result = null; if (getXSDElementDeclaration().isSetConstraint()) { result = getXSDElementDeclaration().getLexicalValue(); } return result; } /** * Returns the enumerated values for the attribute type. * * @return the enumerated values for the attribute type. */ public String[] getEnumeratedValues() { return getEnumeratedValuesForType(getXSDType()); } public String generateInstanceValue() { return XSDTypeUtil.getInstanceValue(getXSDType()); } /** * Returns the cmdocument that is the owner of this cmnode. * * @return the cmdocument corresponding to this cmnode. */ public CMDocument getCMDocument() { return (CMDocument) getAdapter(getXSDElementDeclaration().getSchema()); } /** * Obtains the whitespace facet of the XSD simple type. * * @return The whitespace facet for the XSD type. If none is * defined, or it is a complex type, null. */ private String getWhiteSpaceFacetValue() { XSDSimpleTypeDefinition def = getXSDType().getSimpleType(); return (def != null && def.getEffectiveWhiteSpaceFacet() != null) ? def.getEffectiveWhiteSpaceFacet().getLexicalValue() : null ; } } } /** * XSDElementDeclarationAdapter implements CMElementDeclaration. A * representation of the model object 'Element Declaration'. */ public static class XSDElementDeclarationAdapter extends ElementDeclarationBaseImpl { protected List derivedElementDeclarations = null; protected Map externallyDerivedElementDeclarationsMap = new HashMap(); protected List xsiTypes = null; protected XSDElementDeclaration xsdElementDeclaration; protected CMNodeListImpl substitutionGroup; /** * Constructor. * * @param xsdElementDeclaration - * the XML Schema node. */ public XSDElementDeclarationAdapter(XSDElementDeclaration xsdElementDeclaration) { this.xsdElementDeclaration = xsdElementDeclaration; } /** * Returns corresponding XML Schema element declaration. * * @return corresponding XML Schema element declaration. */ protected XSDElementDeclaration getXSDElementDeclaration() { return xsdElementDeclaration; } /** * Returns corresponding XML Schema element declaration. * * @return corresponding XML Schema element declaration. */ protected XSDElementDeclaration getResolvedXSDElementDeclaration() { return xsdElementDeclaration.getResolvedElementDeclaration(); } /** * Returns the key for this cmnode which is the corresponding XML Schema * node. * * @return the key for this cmnode. */ public Object getKey() { return xsdElementDeclaration; } /** * Returns the referenced element declaration if this is an element * reference. Otherwise it returns itself. * * @return an element declaration. */ public CMNode getDefinition() { return getAdapter(xsdElementDeclaration.getResolvedElementDeclaration()); } /** * Returns a string indicating whether the element declaration is global or * local. Returns null if this is an element reference. * * @return a string indicating whether the element declaration is global or * local. */ protected String getDefinitionInfo() { if (xsdElementDeclaration.isElementDeclarationReference()) return null; else if (xsdElementDeclaration.isGlobal()) return DEFINITION_INFO_GLOBAL; else return DEFINITION_INFO_LOCAL; } public Object getNSPrefixQualification() { String form = null; if (xsdElementDeclaration.isElementDeclarationReference()) { form = "qualified"; } else { if (xsdElementDeclaration.isSetForm()) { form = xsdElementDeclaration.getForm().getName(); } else { XSDSchema schema = xsdElementDeclaration.getSchema(); if (schema != null) form = schema.getElementFormDefault().getName(); } } return form; } /** * Returns the corresponding XML Schema type definition. * * @return the corresponding XML Schema type definition. */ protected XSDTypeDefinition getXSDType() { return xsdElementDeclaration.getResolvedElementDeclaration().getTypeDefinition(); } /** * Returns a list of type names. * * @return a list of type names. */ protected List getXSITypes() { if (xsiTypes == null) { computeDerivedTypeInfo(); } return xsiTypes; } protected void computeDerivedTypeInfo() { xsiTypes = new Vector(); derivedElementDeclarations = new Vector(); computeDerivedTypeInfoHelper(getXSDType(), xsiTypes, derivedElementDeclarations); } protected void computeDerivedTypeInfoHelper(XSDTypeDefinition type, List typeNameList, List edList) { if (type instanceof XSDComplexTypeDefinition) { List derivedTypes = findTypesDerivedFrom(type); ArrayList inclusiveDerivedTypes = new ArrayList(); inclusiveDerivedTypes.add(type); if ((derivedTypes != null) && (derivedTypes.size() > 0)) { inclusiveDerivedTypes.addAll(derivedTypes); } for (Iterator i = inclusiveDerivedTypes.iterator(); i.hasNext();) { XSDTypeDefinition derivedType = (XSDTypeDefinition) i.next(); XSDSchema schema = derivedType.getSchema(); if (schema != null) { String uri = schema.getTargetNamespace(); String name = derivedType.getName(); if (name != null) { name = uri != null ? ("[" + uri + "]" + name) : name; typeNameList.add(name); DerivedElementDeclarationImpl ed = new DerivedElementDeclarationImpl(this, derivedType, name); edList.add(ed); } } } } } /** * Return the element declaration corresponding to the given uri qualified * type name. * * @param uriQualifiedTypeName - * a uri qualified type name * @return corresponding element declaration. */ protected CMElementDeclaration getDerivedElementDeclaration(String uriQualifiedTypeName) { CMElementDeclaration result = null; if (derivedElementDeclarations == null) { computeDerivedTypeInfo(); } for (Iterator i = derivedElementDeclarations.iterator(); i.hasNext();) { DerivedElementDeclarationImpl ed = (DerivedElementDeclarationImpl) i.next(); if ((ed != null) && (ed.uriQualifiedTypeName != null)) { if (ed.uriQualifiedTypeName.equals(uriQualifiedTypeName)) { result = ed; break; } } } return result; } protected CMElementDeclaration getExternallyDerivedElementDeclaration(String reference) { Object declaration = externallyDerivedElementDeclarationsMap.get(reference); if(declaration instanceof CMElementDeclaration) { return (CMElementDeclaration)declaration; } String schemaLocation = null; String xsiType = null; if(reference != null) { int index = reference.indexOf("]"); //$NON-NLS-1$ if(index != -1) { schemaLocation = reference.substring(1, index); xsiType = reference.substring(index + 1); } } if(schemaLocation != null && xsiType != null) { XSDResourceImpl resource = null; try { XSDTypeDefinition baseType = getXSDType(); String baseTypeNamespace = getXSDElementDeclaration().getSchema().getTargetNamespace(); ResourceSet resourceSet = new ResourceSetImpl(); resourceSet.getAdapterFactories().add(new XSDSchemaLocatorAdapterFactory()); InputStream inputStream = resourceSet.getURIConverter().createInputStream(URI.createURI(schemaLocation)); resource = (XSDResourceImpl)resourceSet.createResource(URI.createURI("*.xsd")); //$NON-NLS-1$ resource.setURI(createURI(schemaLocation)); resource.load(inputStream, null); XSDSchema xsdSchema = resource.getSchema(); if(xsdSchema != null && baseType != null && xsiType != null) { String typeName = baseType.getName(); List typeDefinitions = xsdSchema.getTypeDefinitions(); Iterator iterator = typeDefinitions.iterator(); while(iterator.hasNext()) { Object object = iterator.next(); if(object instanceof XSDComplexTypeDefinition) { XSDComplexTypeDefinition xsdComplexTypeDefinition = (XSDComplexTypeDefinition)object; if(xsiType.equals(xsdComplexTypeDefinition.getName()) && isTypeDerivedFrom(xsdComplexTypeDefinition, baseTypeNamespace, typeName)) { DerivedElementDeclarationImpl derivedElementDeclaration = new DerivedElementDeclarationImpl(this, xsdComplexTypeDefinition, reference); externallyDerivedElementDeclarationsMap.put(reference, derivedElementDeclaration); return derivedElementDeclaration; } } } } } catch(Exception exception) { // Do nothing } finally { if(resource != null && resource.isLoaded()) { resource.unload(); } } } return null; } /** * Returns the substitution group for this element. The group consists of: * 1. the element declaration itself 2. and any element declaration that has * a {substitution group affiliation} in the group * * @return the substitution group for this element. */ protected CMNodeListImpl getSubstitutionGroup() { if (substitutionGroup == null) { substitutionGroup = new CMNodeListImpl(); List sgroup = getResolvedXSDElementDeclaration().getSubstitutionGroup(); for (Iterator i = sgroup.iterator(); i.hasNext();) { XSDElementDeclaration ed = (XSDElementDeclaration) i.next(); substitutionGroup.add(getAdapter(ed)); } } return substitutionGroup; } } /** * DerivedElementDeclarationImpl extends ElementDeclarationBaseImpl * */ public static class DerivedElementDeclarationImpl extends ElementDeclarationBaseImpl { protected XSDElementDeclarationAdapter owner; protected XSDTypeDefinition xsdType; public String uriQualifiedTypeName; /** * Constructor. * * @param owner - * @param xsdType - * @param uriQualifiedTypeName - */ public DerivedElementDeclarationImpl(XSDElementDeclarationAdapter owner, XSDTypeDefinition xsdType, String uriQualifiedTypeName) { this.owner = owner; this.xsdType = xsdType; this.uriQualifiedTypeName = uriQualifiedTypeName; } /** * Returns corresponding XML Schema element declaration. * * @return corresponding XML Schema element declaration. */ protected XSDElementDeclaration getXSDElementDeclaration() { return (XSDElementDeclaration) owner.getKey(); } /** * Returns corresponding XML Schema element declaration. * * @return corresponding XML Schema element declaration. */ protected XSDElementDeclaration getResolvedXSDElementDeclaration() { return ((XSDElementDeclaration) owner.getKey()).getResolvedElementDeclaration(); } /** * Returns the key for this cmnode which is the corresponding XML Schema * node. * * @return the key for this cmnode. */ public Object getKey() { return owner.getKey(); } /** * Returns the corresponding XML Schema type definition. * * @return the corresponding XML Schema type definition. */ protected XSDTypeDefinition getXSDType() { return xsdType; } /** * Returns a list of type names. * * @return a list of type names. */ protected List getXSITypes() { return owner.getXSITypes(); } /** * Return the element declaration corresponding to the given uri qualified * type name. * * @param uriQualifiedTypeName - * a uri qualified type name * @return corresponding element declaration. */ protected CMElementDeclaration getDerivedElementDeclaration(String uriQualifiedTypeName) { return owner.getDerivedElementDeclaration(uriQualifiedTypeName); } protected CMElementDeclaration getExternallyDerivedElementDeclaration(String reference) { return owner.getDerivedElementDeclaration(reference); } /** * Returns the referenced element declaration if this is an element * reference. Otherwise it returns itself. * * @return an element declaration. */ protected CMNode getDefinition() { return this; } /** * Returns a string indicating whether the element declaration is global or * local. Returns null if this is an element reference. * * @return a string indicating whether the element declaration is global or * local. */ protected String getDefinitionInfo() { return owner.getDefinitionInfo(); } /* * Returns the value of the form [attribute] which affects the target * namespace of locally scoped features. @return the value of the form * [attribute]. */ public Object getNSPrefixQualification() { return owner.getNSPrefixQualification(); } /** * Returns the substitution group for this element. The group consists of: * 1. the element declaration itself 2. and any element declaration that has * a {substitution group affiliation} in the group * * @return the substitution group for this element. */ protected CMNodeListImpl getSubstitutionGroup() { return owner.getSubstitutionGroup(); } } /** * XSDWildcardAdapter */ public static class XSDWildcardAdapter extends XSDBaseAdapter implements CMAnyElement { protected XSDWildcard xsdWildcard; public XSDWildcardAdapter(XSDWildcard xsdWildcard) { this.xsdWildcard = xsdWildcard; } /** * Returns the key for this cmnode which is the corresponding XML Schema * node. * * @return the key for this cmnode. */ public Object getKey() { return xsdWildcard; } /** * Returns the type of the node. The types are defined in CMNode class * (ANY_ELEMENT, ATTRIBUTE_DECLARATION, DATA_TYPE, DOCUMENT, * ELEMENT_DECLARATION, ENTITY_DECLARATION, GROUP, NAME_SPACE or * DOCUMENTATION). * * @return the type of this node. */ public int getNodeType() { return ANY_ELEMENT; } /** * Returns the name of the node. The default value is an empty string value. * All derived classes must override this method if they do not want the * default value. * * @return the name of the node. */ public String getNodeName() { return "any"; } public String getNamespaceURI() { if (xsdWildcard.getElement().hasAttribute(XSDConstants.NAMESPACE_ATTRIBUTE)) { return xsdWildcard.getElement().getAttribute(XSDConstants.NAMESPACE_ATTRIBUTE); } else return "##any"; } /** * Returns the value of 'Min Occurs' attribute. The default value is "1". * * @return the value of the 'Min Occurs' attribute. */ public int getMinOccur() { return getMinOccurs(xsdWildcard); } /** * Returns the value of the 'Max Occurs' attribute. The default value is * "1". * * @return the value of the 'Max Occurs' attribute. */ public int getMaxOccur() { return getMaxOccurs(xsdWildcard); } /** * Returns the cmdocument that is the owner of this cmnode. * * @return the cmdocument corresponding to this cmnode. */ public CMDocument getCMDocument() { return (CMDocument) getAdapter(xsdWildcard.getSchema()); } /** * Returns a list of documentation elements. * * @return a list of documentation elements. */ protected CMNodeList getDocumentation() { XSDAnnotation annotation = xsdWildcard.getAnnotation(); return getDocumentations(annotation); } } /** * XSDModelGroupAdapter */ public static class XSDModelGroupAdapter extends XSDBaseAdapter implements CMGroup { protected XSDModelGroup xsdModelGroup; public XSDModelGroupAdapter() { } public XSDModelGroupAdapter(XSDModelGroup xsdModelGroup) { this.xsdModelGroup = xsdModelGroup; } /** * Returns the type of the node. The types are defined in CMNode class * (ANY_ELEMENT, ATTRIBUTE_DECLARATION, DATA_TYPE, DOCUMENT, * ELEMENT_DECLARATION, ENTITY_DECLARATION, GROUP, NAME_SPACE or * DOCUMENTATION). * * @return the type of this node. */ public int getNodeType() { return GROUP; } /** * Returns the key for this cmnode which is the corresponding XML Schema * node. * * @return the key for this cmnode. */ public Object getKey() { return xsdModelGroup; } /** * Returns a list of the children of this group. * * @return a list of the children of this group. */ public CMNodeList getChildNodes() { CMNodeListImpl nodeList = new CMNodeListImpl(); if (xsdModelGroup != null) { for (Iterator i = xsdModelGroup.getParticles().iterator(); i.hasNext();) { XSDParticle particle = (XSDParticle) i.next(); XSDParticleContent content = particle.getContent(); CMNode adapter = getAdapter(content); if (adapter != null) { nodeList.getList().add(adapter); } } } return nodeList; } /** * Returns the name of the node. The default value is an empty string value. * All derived classes must override this method if they do not want the * default value. * * @return the name of the node. */ public String getNodeName() { CMDescriptionBuilder descriptionBuilder = new CMDescriptionBuilder(); return descriptionBuilder.buildDescription(this); } /** * Returns the value of 'Min Occurs' attribute. The default value is "1". * * @return the value of the 'Min Occurs' attribute. */ public int getMinOccur() { return getMinOccurs(xsdModelGroup); } /** * Returns the value of the 'Max Occurs' attribute. The default value is * "1". * * @return the value of the 'Max Occurs' attribute. */ public int getMaxOccur() { return getMaxOccurs(xsdModelGroup); } /** * Return operator of this group -- CHOICE, SEQUENCE or ALL value. * * @return the operator of this group. */ public int getOperator() { int result = 0; //todo... handle ALONE case by checkig if child count == 1 if (xsdModelGroup != null) { switch (xsdModelGroup.getCompositor().getValue()) { case XSDCompositor.CHOICE : { result = CHOICE; break; } case XSDCompositor.SEQUENCE : { result = SEQUENCE; break; } case XSDCompositor.ALL : { result = ALL; break; } } } return result; } /** * Returns a list of documentation elements. * * @return a list of documentation elements. */ protected CMNodeList getDocumentation() { XSDAnnotation annotation = xsdModelGroup.getAnnotation(); return getDocumentations(annotation); } /** * Returns the cmdocument that is the owner of this cmnode. * * @return the cmdocument corresponding to this cmnode. */ public CMDocument getCMDocument() { return (CMDocument) getAdapter(xsdModelGroup.getSchema()); } } /** * XSDModelGroupDefinitionAdapter */ public static class XSDModelGroupDefinitionAdapter extends XSDBaseAdapter implements CMGroup { protected XSDModelGroupDefinition xsdModelGroupDefinition; public XSDModelGroupDefinitionAdapter(XSDModelGroupDefinition xsdModelGroupDefinition) { this.xsdModelGroupDefinition = xsdModelGroupDefinition; } /** * Returns the type of the node. The types are defined in CMNode class * (ANY_ELEMENT, ATTRIBUTE_DECLARATION, DATA_TYPE, DOCUMENT, * ELEMENT_DECLARATION, ENTITY_DECLARATION, GROUP, NAME_SPACE or * DOCUMENTATION). * * @return the type of this node. */ public int getNodeType() { return GROUP; } /** * Returns the key for this cmnode which is the corresponding XML Schema * node. * * @return the key for this cmnode. */ public Object getKey() { return xsdModelGroupDefinition; } /** * Returns a list of the children of this group. * * @return a list of the children of this group. */ public CMNodeList getChildNodes() { CMNodeListImpl nodeList = new CMNodeListImpl(); XSDModelGroup modelGroup = xsdModelGroupDefinition.getResolvedModelGroupDefinition().getModelGroup(); if (modelGroup != null) { CMNode adapter = getAdapter(modelGroup); nodeList.add(adapter); } return nodeList; } /** * Returns the name of the node. The default value is an empty string value. * All derived classes must override this method if they do not want the * default value. * * @return the name of the node. */ public String getNodeName() { CMDescriptionBuilder descriptionBuilder = new CMDescriptionBuilder(); return descriptionBuilder.buildDescription(this); } /** * Returns the value of 'Min Occurs' attribute. The default value is "1". * * @return the value of the 'Min Occurs' attribute. */ public int getMinOccur() { return getMinOccurs(xsdModelGroupDefinition); } /** * Returns the value of the 'Max Occurs' attribute. The default value is * "1". * * @return the value of the 'Max Occurs' attribute. */ public int getMaxOccur() { return getMaxOccurs(xsdModelGroupDefinition); } /** * Return operator of this group -- CHOICE, SEQUENCE or ALL value. * * @return the operator of this group. */ public int getOperator() { return XSDCompositor.SEQUENCE; } /** * Returns a list of documentation elements. * * @return a list of documentation elements. */ protected CMNodeList getDocumentation() { XSDAnnotation annotation = xsdModelGroupDefinition.getAnnotation(); return getDocumentations(annotation); } /** * Returns the cmdocument that is the owner of this cmnode. * * @return the cmdocument corresponding to this cmnode. */ public CMDocument getCMDocument() { return (CMDocument) getAdapter(xsdModelGroupDefinition.getSchema()); } } /** * DocumentationImpl implements CMDocumentation. A representation of the * documentation element part of the 'User Information' feature. Working with * the documentation element requires dropping down into the DOM model. */ public static class DocumentationImpl implements CMDocumentation { protected Element documentation; /** * Constructor. * * @param documentation - * a documentation element. */ public DocumentationImpl(Element documentation) { this.documentation = documentation; } /** * Returns the type of the node. The types are defined in CMNode class * (ANY_ELEMENT, ATTRIBUTE_DECLARATION, DATA_TYPE, DOCUMENT, * ELEMENT_DECLARATION, ENTITY_DECLARATION, GROUP, NAME_SPACE or * DOCUMENTATION). * * @return the type of this node. */ public int getNodeType() { return DOCUMENTATION; } /** * Returns an empty string value. * * @return an empty string value. */ public String getNodeName() { return ""; } /** * Returns false. This class does not support any properties. * * @param propertyName - * name of a property * @return false. */ public boolean supports(String propertyName) { return false; } /** * Returns null. This class does not support any properties. * * @param propertyName - * name of a property * @return null. */ public Object getProperty(String propertyName) { return null; } /** * Returns the content of the documentation element. * * @return the content of the documentation element. */ public String getValue() { String content = ""; boolean contentFound = false; NodeList nodes = documentation.getChildNodes(); for (int i = 0; i < nodes.getLength(); i++) { Node node = nodes.item(i); if (node instanceof Text) { contentFound = true; content += node.getNodeValue(); } } return contentFound ? content : null; } /** * Returns the xml:lang attribute value of the documentation element. * * @return the xml:lang attribute value of the documentation element. */ public String getLanguage() { return documentation.hasAttributeNS(XSDConstants.XML_NAMESPACE_URI_1998, XML_LANG_ATTRIBUTE) ? documentation.getAttributeNS(XSDConstants.XML_NAMESPACE_URI_1998, XML_LANG_ATTRIBUTE) : null; } /** * Returns the source attribute value of the documentation element. * * @return the source attribute value of the documentation element. */ public String getSource() { return documentation.hasAttributeNS(null, XSDConstants.SOURCE_ATTRIBUTE) ? documentation.getAttributeNS(null, XSDConstants.SOURCE_ATTRIBUTE) : null; } } /** * XSIDocument extends CMDocumentImpl. This class is used to hold those * attributes that are for direct use in any XML documents. These attributes * are in a different namespace, which has the namespace name * http://www.w3.org/2001/XMLSchema-instance. Attributes in this namespace * include: xsi:type xsi:nil xsi:schemaLocation xsi:noNamespaceSchemaLocation */ public static class XSIDocument extends CMDocumentImpl { public CMAttributeDeclarationImpl nilAttribute; /** * Constructor. Creates the 'xsi:nil' */ public XSIDocument() { super(XSDConstants.SCHEMA_INSTANCE_URI_2001); // create the 'nill' attribute String[] values = {"false", "true"}; nilAttribute = new CMAttributeDeclarationImpl("nil", CMAttributeDeclaration.REQUIRED, new CMDataTypeImpl("boolean", values)); nilAttribute.setPrefixQualification(true); nilAttribute.setCMDocument(this); } } /** * Note this XSD model visitor differs from the XSD model visitor in * org.eclipse.wst.xsd.editor plugin. In visitModelGroup method we call * getParticles() instead of getContents(). This gathers all of the content of * a derived type. */ public static class XSDCMVisitor extends XSDVisitor { public void visitSimpleTypeDefinition(XSDSimpleTypeDefinition type) { XSDParticle ctd = type.getComplexType(); if (ctd != null) visitParticle(ctd); } public void visitModelGroup(XSDModelGroup modelGroup) { if (modelGroup.getParticles() != null) { for (Iterator iterator = modelGroup.getParticles().iterator(); iterator.hasNext();) { XSDParticle particle = (XSDParticle) iterator.next(); visitParticle(particle); } } } public void visitModelGroupDefinition(XSDModelGroupDefinition modelGroupDef) { XSDModelGroup modelGroup = modelGroupDef.getResolvedModelGroupDefinition().getModelGroup(); if (modelGroup != null) { visitModelGroup(modelGroup); } } } /** * A visitor class that walks the xsd model and computes the list of children * that belong to the initially visited element type. */ public static class DerivedChildVisitor extends XSDCMVisitor { protected CMNodeListImpl childNodeList = new CMNodeListImpl(); protected List baseTypeList = new Vector(); Object root; DerivedChildVisitor(Object root) { this.root = root; } public CMNodeListImpl getChildNodeList() { return childNodeList; } public void visitWildcard(XSDWildcard wildcard) { childNodeList.getList().add(getAdapter(wildcard)); } public void visitElementDeclaration(XSDElementDeclaration element) { childNodeList.getList().add(getAdapter(element)); } public void visitModelGroup(XSDModelGroup modelGroup) { childNodeList.getList().add(getAdapter(modelGroup)); } public void visitModelGroupDefinition(XSDModelGroupDefinition modelGroupDefinition) { childNodeList.getList().add(getAdapter(modelGroupDefinition)); } } /** * A visitor class that gathers all of the elements within a type definition. */ public static class LocalElementVisitor extends XSDCMVisitor { protected CMNamedNodeMapImpl namedNodeMap = new CMNamedNodeMapImpl(); protected List baseTypeList = new Vector(); public void visitElementDeclaration(XSDElementDeclaration element) { XSDElementDeclarationAdapter adapter = (XSDElementDeclarationAdapter) getAdapter(element); namedNodeMap.getHashtable().put(adapter.getNodeName(), adapter); } public CMNamedNodeMap getCMNamedNodeMap() { return namedNodeMap; } } }