/*
* JBoss, Home of Professional Open Source.
*
* See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing.
*
* See the AUTHORS.txt file distributed with this work for a full listing of individual contributors.
*/
package org.teiid.designer.metamodels.xsd;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.xsd.XSDAnnotation;
import org.eclipse.xsd.XSDAttributeDeclaration;
import org.eclipse.xsd.XSDAttributeGroupDefinition;
import org.eclipse.xsd.XSDAttributeUse;
import org.eclipse.xsd.XSDAttributeUseCategory;
import org.eclipse.xsd.XSDComplexTypeContent;
import org.eclipse.xsd.XSDComplexTypeDefinition;
import org.eclipse.xsd.XSDComponent;
import org.eclipse.xsd.XSDCompositor;
import org.eclipse.xsd.XSDConcreteComponent;
import org.eclipse.xsd.XSDElementDeclaration;
import org.eclipse.xsd.XSDFacet;
import org.eclipse.xsd.XSDFactory;
import org.eclipse.xsd.XSDFeature;
import org.eclipse.xsd.XSDIdentityConstraintDefinition;
import org.eclipse.xsd.XSDImport;
import org.eclipse.xsd.XSDModelGroup;
import org.eclipse.xsd.XSDModelGroupDefinition;
import org.eclipse.xsd.XSDNotationDeclaration;
import org.eclipse.xsd.XSDParticle;
import org.eclipse.xsd.XSDParticleContent;
import org.eclipse.xsd.XSDSchema;
import org.eclipse.xsd.XSDSchemaDirective;
import org.eclipse.xsd.XSDSimpleTypeDefinition;
import org.eclipse.xsd.XSDTerm;
import org.eclipse.xsd.XSDTypeDefinition;
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.teiid.core.designer.ModelerCoreException;
import org.teiid.core.designer.util.CoreArgCheck;
import org.teiid.core.designer.util.CoreStringUtil;
import org.teiid.designer.core.ModelerCore;
import org.teiid.designer.core.metamodel.aspect.sql.SqlAspect;
import org.teiid.designer.core.types.DatatypeConstants;
import org.teiid.designer.core.types.EnterpriseDatatypeInfo;
import org.teiid.designer.metamodels.xsd.aspects.sql.XsdSimpleTypeDefinitionAspect;
import org.w3c.dom.Attr;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
/**
* XsdUtil
*
* @since 8.0
*/
public class XsdUtil {
public static final String BUILT_IN_DATATYPE_NAMESPACE_URI = DatatypeConstants.BUILTIN_DATATYPES_URI;
/**
* Protected constructor to prevent instantiation.
*/
protected XsdUtil() {
super();
}
/**
* Get the compositor object (i.e., the <code>sequence</code>, <code>choice</code> or <code>all</code>) under the supplied
* complex type. The complex type definition contains a <code>complexContent</code> child, which contains a
* <code>complexContent</code>, and which contains a <code>restriction</code> or <code>extension</code>, and finally the
* compositor.
* <p>
* For example:
* </p>
* <p>
*
* <pre>
* <xsd:element name="internationalPrice">
* <xsd:complexType>
* <xsd:complexContent>
* <xsd:restriction base="xsd:anyType">
* <xsd:attribute name="currency" type="xsd:string"/>
* <xsd:attribute name="value" type="xsd:decimal"/>
* </xsd:restriction>
* </xsd:complexContent>
* </xsd:complexType>
* </xsd:element>
*
* </p>
* </pre>
*
* @param complexType
* @return the compositor
*/
public static XSDModelGroup getCompositor( final XSDComplexTypeDefinition complexType ) {
if (complexType != null) {
// Get the complex content ...
final XSDComplexTypeContent content = complexType.getContent();
if (content instanceof XSDParticle) {
// The complex content is a particle
final XSDParticle particle = (XSDParticle)content;
// Check the content of the particle ...
final XSDParticleContent particleContent = particle.getContent();
if (particleContent != null && particleContent instanceof XSDModelGroup) {
return (XSDModelGroup)particleContent;
}
// Check the term of the particle ...
final XSDTerm particleTerm = particle.getTerm();
if (particleTerm != null && particleTerm instanceof XSDModelGroup) {
return (XSDModelGroup)particleTerm;
}
}
}
return null;
}
/**
* Return true if the specified resource is an instanceof an XSDResourceImpl which contains XSDSchemaDirective instances that
* are not yet resolved. An XSDSchemaDirective is resolved because either the dependent resource was missing from the resource
* set when this resource was loaded or because the location information in the XSDSchemaDirective is invalid. before the
* dependent resource was added to the resource set.
*
* @param eResource the resource to check
* @return true if the resource contains unresolved directives
* @since 4.3
*/
public static boolean hasUnresolvedSchemaDirectives( final Resource eResource ) {
if (eResource instanceof XSDResourceImpl) {
final XSDResourceImpl xsdResource = (XSDResourceImpl)eResource;
final XSDSchemaImpl schema = (XSDSchemaImpl)xsdResource.getSchema();
// Iterate over the contents looking for SchemaDirective instances (import, include, redefine)
for (Iterator iter = schema.eContents().iterator(); iter.hasNext();) {
Object content = iter.next();
if (content instanceof XSDSchemaDirective) {
final XSDSchemaDirective directive = (XSDSchemaDirective)content;
// If the directive is not yet resolved ...
if (directive.getResolvedSchema() == null) {
return true;
}
}
}
}
return false;
}
/**
* If the specified resource is an instanceof an XSDResourceImpl and it is found to have XSDSchemaDirective instances that are
* not yet resolved, try to resolve them by reloading this resource and any other XSDResourceImpl instances in the resource
* set with unresolved directives. Invoking this method will not resolve a directive if the dependent resource is missing or
* if the location information in the XSDSchemaDirective is invalid.
*
* @param eResource the resource to operate on
* @return
* @since 4.3
*/
public static void resolveSchemaDirectives( final Resource eResource ) {
if (eResource instanceof XSDResourceImpl && hasUnresolvedSchemaDirectives(eResource)) {
final XSDResourceImpl xsdResource = (XSDResourceImpl)eResource;
// The specified XSD resource has unresolved directives then make a list of
// any other XSDs in the container with this same problem
final ResourceSet rs = xsdResource.getResourceSet();
if (rs != null) {
final List xsds = new ArrayList(rs.getResources().size());
for (Iterator iter = rs.getResources().iterator(); iter.hasNext();) {
final Resource r = (Resource)iter.next();
if (r instanceof XSDResourceImpl && hasUnresolvedSchemaDirectives(r)) {
xsds.add(r);
}
}
// Reload the XML Schema resources to ensure that the include, import, or redefine
// definitions are resolved correctly.
for (Iterator iter = xsds.iterator(); iter.hasNext();) {
final Resource r = (Resource)iter.next();
r.unload();
try {
r.load(rs.getLoadOptions());
} catch (IOException e) {
XsdPlugin.Util.log(e);
}
}
}
}
}
public static String getUniqueQNamePrefix( final XSDSchema schema ) {
if (schema == null) {
return null;
}
final Map qNameMap = schema.getQNamePrefixToNamespaceMap();
int increment = 1;
final String start = "Z"; //$NON-NLS-1$
String val = start + increment;
boolean done = false;
while (!done) {
if (qNameMap.get(val) != null) {
increment++;
val = start + increment;
} else {
done = true;
}
}
return val;
}
public static void removeNamespaceRef( final XSDSchema schema,
final String namespace ) {
CoreArgCheck.isNotNull(schema);
XsdUtil.CoreArgCheckIsResolved(schema);
CoreArgCheck.isNotNull(namespace);
final Map map = schema.getQNamePrefixToNamespaceMap();
final Set entrySet = map.entrySet();
for (final Iterator it = new ArrayList(entrySet).iterator(); it.hasNext();) {
Map.Entry entry = (Entry)it.next();
if (namespace.equals(entry.getValue())) {
try {
ModelerCore.getModelEditor().removeMapValue(schema, map, entry.getKey());
} catch (ModelerCoreException mce) {
String msg = XsdPlugin.Util.getString("XsdUtil.Unable_to_remove_the_namespace_reference", namespace); //$NON-NLS-1$
XsdPlugin.Util.log(IStatus.ERROR, mce, msg);
}
}
}
}
public static void removeImport( final XSDSchema schema,
final String namespace ) {
CoreArgCheck.isNotNull(schema);
XsdUtil.CoreArgCheckIsResolved(schema);
CoreArgCheck.isNotNull(namespace);
for (final Iterator it = new ArrayList(schema.getContents()).iterator(); it.hasNext();) {
final Object content = it.next();
if (content instanceof XSDImport && namespace.equals(((XSDImport)content).getNamespace())) {
try {
ModelerCore.getModelEditor().removeValue(schema, content, schema.getContents());
} catch (ModelerCoreException mce) {
String msg = XsdPlugin.Util.getString("XsdUtil.Unable_to_remove_the_xsd_import", namespace); //$NON-NLS-1$
XsdPlugin.Util.log(IStatus.ERROR, mce, msg);
}
}
}
}
public static void addImport( final XSDSimpleTypeDefinition simpleType,
final XSDSimpleTypeDefinition baseType ) {
CoreArgCheck.isNotNull(simpleType);
XsdUtil.CoreArgCheckIsResolved(simpleType);
CoreArgCheck.isNotNull(baseType);
XsdUtil.CoreArgCheckIsResolved(baseType);
final XSDSchema schema = simpleType.getSchema();
final String referencedNamespace = baseType.getTargetNamespace();
if (!XsdUtil.containsNamespaceDeclaration(schema, referencedNamespace)) {
addNamespaceRef(schema, referencedNamespace);
}
final XSDImport xsdImport = XSDFactory.eINSTANCE.createXSDImport();
xsdImport.setNamespace(referencedNamespace);
// if we're adding an import for the MM built-in datatype schema, we do NOT
// add the schema location; the mere presence of the namespace in an import
// will cause the schema location to be set correctly
if (!DatatypeConstants.BUILTIN_DATATYPES_URI.equals(referencedNamespace)) {
final URI schemaLocation = baseType.eResource().getURI().deresolve(simpleType.eResource().getURI());
xsdImport.setSchemaLocation(schemaLocation.toString());
}
try {
ModelerCore.getModelEditor().addValue(schema, xsdImport, schema.getContents(), 0);
} catch (ModelerCoreException mce) {
Object[] params = new Object[] {referencedNamespace, xsdImport.getSchemaLocation()};
String msg = XsdPlugin.Util.getString("XsdUtil.Unable_to_add_the_xsd_import", params); //$NON-NLS-1$
XsdPlugin.Util.log(IStatus.ERROR, mce, msg);
}
}
public static void addNamespaceRef( final XSDSchema schema,
final String namespace ) {
CoreArgCheck.isNotNull(schema);
XsdUtil.CoreArgCheckIsResolved(schema);
CoreArgCheck.isNotNull(namespace);
final String prefix = XsdUtil.getUniqueQNamePrefix(schema);
XsdUtil.addNamespaceRef(schema, prefix, namespace);
}
public static void addNamespaceRef( final XSDSchema schema,
final String prefix,
final String namespace ) {
CoreArgCheck.isNotNull(schema);
XsdUtil.CoreArgCheckIsResolved(schema);
CoreArgCheck.isNotNull(namespace);
final Map map = schema.getQNamePrefixToNamespaceMap();
try {
ModelerCore.getModelEditor().addMapValue(schema, map, prefix, namespace);
} catch (ModelerCoreException mce) {
Object[] params = new Object[] {prefix, namespace};
String msg = XsdPlugin.Util.getString("XsdUtil.Unable_to_add_the_namespace_reference", params); //$NON-NLS-1$
XsdPlugin.Util.log(IStatus.ERROR, mce, msg);
}
}
public static boolean containsImport( final XSDSchema schema,
final String namespace ) {
boolean containsImport = false;
if (schema != null) {
if (namespace != null) {
final List contents = schema.getContents();
for (int i = 0; i < contents.size(); i++) {
final Object content = contents.get(i);
if (content instanceof XSDImport) {
if (namespace.equals(((XSDImport)content).getNamespace())) {
containsImport = true;
break;
}
}
}
}
}
return containsImport;
}
public static boolean containsReferenceToNamespace( final XSDSchema schema,
final String namespace ) {
boolean containsReference = false;
if (schema != null && !schema.eIsProxy() && namespace != null) {
// we always will have a reference to the schema for schemas
if (XSDConstants.isSchemaForSchemaNamespace(namespace)) {
containsReference = true;
} else {
final List contents = schema.getContents();
for (int i = 0; i < contents.size(); i++) {
final Object o = contents.get(i);
if (o instanceof XSDSimpleTypeDefinition) {
XSDSimpleTypeDefinition simpleType = (XSDSimpleTypeDefinition)o;
if (namespace.equals(simpleType.getBaseTypeDefinition().getTargetNamespace())) {
containsReference = true;
break;
}
}
}
}
}
return containsReference;
}
public static boolean containsNamespaceDeclaration( final XSDSchema schema,
final String namespace ) {
boolean containsNamespaceDeclaration = false;
if (schema != null) {
final Map prefixesToNamespaces = schema.getQNamePrefixToNamespaceMap();
containsNamespaceDeclaration = prefixesToNamespaces.containsValue(namespace);
}
return containsNamespaceDeclaration;
}
public static boolean isEnterpriseSchema( final XSDSchema schema ) {
boolean success = false;
if ((schema != null) && (!schema.eIsProxy())) {
String namespace = schema.getQNamePrefixToNamespaceMap().get(XsdConstants.PREFIX_FOR_ENTERPRISE_DATATYPES_URI_2005);
success = XsdConstants.isSchemaEnterpriseDatatypeNamespace(namespace);
}
return success;
}
public static void setTargetNamespace( final XSDSchema schema,
String namespace ) {
CoreArgCheck.isNotNull(schema);
XsdUtil.CoreArgCheckIsResolved(schema);
CoreArgCheck.isNotNull(namespace);
String defaultNamespaceReference = schema.getQNamePrefixToNamespaceMap().get(null);
boolean assignDefaultReference = defaultNamespaceReference == null
|| schema.getTargetNamespace().equals(defaultNamespaceReference);
if (assignDefaultReference) {
addNamespaceRef(schema, null, namespace);
} else {
addNamespaceRef(schema, namespace);
}
schema.setTargetNamespace(namespace);
}
public static void setAsEnterpriseSchema( final XSDSchema schema ) {
CoreArgCheck.isNotNull(schema);
XsdUtil.CoreArgCheckIsResolved(schema);
addNamespaceRef(schema,
XsdConstants.PREFIX_FOR_ENTERPRISE_DATATYPES_URI_2005,
XsdConstants.SCHEMA_FOR_ENTERPRISE_DATATYPES_URI_2005);
schema.eResource().setModified(true);
}
public static void unsetAsEnterpriseSchema( final XSDSchema schema ) {
CoreArgCheck.isNotNull(schema);
XsdUtil.CoreArgCheckIsResolved(schema);
schema.getQNamePrefixToNamespaceMap().remove(XsdConstants.PREFIX_FOR_ENTERPRISE_DATATYPES_URI_2005);
schema.eResource().setModified(true);
}
public static void checkForEnterpriseConversion( final XSDSchema schema ) {
if ((schema != null) && (!isEnterpriseSchema(schema))) {
final List contents = schema.getContents();
for (int i = 0; i < contents.size(); i++) {
final Object o = contents.get(i);
if (o instanceof XSDSimpleTypeDefinition) {
final XSDSimpleTypeDefinition simpleType = (XSDSimpleTypeDefinition)o;
final XsdSimpleTypeDefinitionAspect aspect = (XsdSimpleTypeDefinitionAspect)ModelerCore.getMetamodelRegistry().getMetamodelAspect(simpleType,
SqlAspect.class);
aspect.convertEnterpriseDatatype(simpleType);
}
}
}
}
public static void checkForEnterpriseConversion( final XSDSimpleTypeDefinition simpleType ) {
final XSDSchema schema = simpleType.getSchema();
if ((schema != null) && (!isEnterpriseSchema(schema))) {
final XsdSimpleTypeDefinitionAspect aspect = (XsdSimpleTypeDefinitionAspect)ModelerCore.getMetamodelRegistry().getMetamodelAspect(simpleType,
SqlAspect.class);
EnterpriseDatatypeInfo edtInfo = aspect.getEnterpriseAttributesFromAppInfo(simpleType);
if (edtInfo.isValid()) {
checkForEnterpriseConversion(schema);
}
}
}
/**
* Return true if the specified XSDConcreteComponent is an entity that can be contain an XSDAnnotation, otherwise return
* false.
*/
public static boolean canAnnotate( final XSDConcreteComponent comp ) {
CoreArgCheck.isNotNull(comp);
if (comp instanceof XSDSchema || comp instanceof XSDAnnotation || comp instanceof XSDAttributeDeclaration
|| comp instanceof XSDAttributeGroupDefinition || comp instanceof XSDElementDeclaration
|| comp instanceof XSDNotationDeclaration || comp instanceof XSDModelGroup || comp instanceof XSDModelGroupDefinition
|| comp instanceof XSDIdentityConstraintDefinition || comp instanceof XSDTypeDefinition
|| comp instanceof XSDWildcard || comp instanceof XSDFacet) {
return true;
}
return false;
}
/**
* Return the XSDAnnotation instance associated with the XSDConcreteComponent or null if the component has no annotation.
*/
public static XSDAnnotation getAnnotation( final XSDConcreteComponent comp ) {
XSDAnnotation annotation = null;
if (comp instanceof XSDSchema) {
List annotations = ((XSDSchema)comp).getAnnotations();
if (annotations != null) {
for (Iterator iter = annotations.iterator(); iter.hasNext();) {
annotation = (XSDAnnotation)iter.next();
// Stop iterating if we find an annotation containing application info
// if (annotation != null && !annotation.getApplicationInformation().isEmpty()) {
if (annotation != null) {
break;
}
}
}
} else if (comp instanceof XSDAttributeDeclaration) {
annotation = ((XSDAttributeDeclaration)comp).getAnnotation();
} else if (comp instanceof XSDAttributeGroupDefinition) {
annotation = ((XSDAttributeGroupDefinition)comp).getAnnotation();
} else if (comp instanceof XSDElementDeclaration) {
annotation = ((XSDElementDeclaration)comp).getAnnotation();
} else if (comp instanceof XSDNotationDeclaration) {
annotation = ((XSDNotationDeclaration)comp).getAnnotation();
} else if (comp instanceof XSDModelGroup) {
annotation = ((XSDModelGroup)comp).getAnnotation();
} else if (comp instanceof XSDModelGroupDefinition) {
annotation = ((XSDModelGroupDefinition)comp).getAnnotation();
} else if (comp instanceof XSDIdentityConstraintDefinition) {
annotation = ((XSDIdentityConstraintDefinition)comp).getAnnotation();
} else if (comp instanceof XSDTypeDefinition) {
annotation = ((XSDTypeDefinition)comp).getAnnotation();
} else if (comp instanceof XSDWildcard) {
annotation = ((XSDWildcard)comp).getAnnotation();
} else if (comp instanceof XSDFacet) {
annotation = ((XSDFacet)comp).getAnnotation();
} else if (comp instanceof XSDAnnotation) {
annotation = (XSDAnnotation)comp;
}
return annotation;
}
/**
* Return the XSDAnnotation instance associated with the XSDConcreteComponent or null if the component has no annotation.
*/
public static XSDAnnotation getAnnotation( final XSDConcreteComponent comp,
boolean createIfNull ) {
CoreArgCheck.isNotNull(comp);
if (!createIfNull) {
return getAnnotation(comp);
}
XSDAnnotation annotation = null;
if (comp instanceof XSDSchema) {
List annotations = ((XSDSchema)comp).getAnnotations();
if (annotations == null || annotations.isEmpty()) {
annotation = XSDFactory.eINSTANCE.createXSDAnnotation();
((XSDSchema)comp).getContents().add(annotation);
} else {
for (Iterator iter = annotations.iterator(); iter.hasNext();) {
annotation = (XSDAnnotation)iter.next();
if (annotation != null) {
break;
}
}
}
} else if (comp instanceof XSDAttributeDeclaration) {
annotation = ((XSDAttributeDeclaration)comp).getAnnotation();
if (annotation == null) {
annotation = XSDFactory.eINSTANCE.createXSDAnnotation();
((XSDAttributeDeclaration)comp).setAnnotation(annotation);
}
} else if (comp instanceof XSDAttributeGroupDefinition) {
annotation = ((XSDAttributeGroupDefinition)comp).getAnnotation();
if (annotation == null) {
annotation = XSDFactory.eINSTANCE.createXSDAnnotation();
((XSDAttributeGroupDefinition)comp).setAnnotation(annotation);
}
} else if (comp instanceof XSDElementDeclaration) {
annotation = ((XSDElementDeclaration)comp).getAnnotation();
if (annotation == null) {
annotation = XSDFactory.eINSTANCE.createXSDAnnotation();
((XSDElementDeclaration)comp).setAnnotation(annotation);
}
} else if (comp instanceof XSDNotationDeclaration) {
annotation = ((XSDNotationDeclaration)comp).getAnnotation();
if (annotation == null) {
annotation = XSDFactory.eINSTANCE.createXSDAnnotation();
((XSDNotationDeclaration)comp).setAnnotation(annotation);
}
} else if (comp instanceof XSDModelGroup) {
annotation = ((XSDModelGroup)comp).getAnnotation();
if (annotation == null) {
annotation = XSDFactory.eINSTANCE.createXSDAnnotation();
((XSDModelGroup)comp).setAnnotation(annotation);
}
} else if (comp instanceof XSDModelGroupDefinition) {
annotation = ((XSDModelGroupDefinition)comp).getAnnotation();
if (annotation == null) {
annotation = XSDFactory.eINSTANCE.createXSDAnnotation();
((XSDModelGroupDefinition)comp).setAnnotation(annotation);
}
} else if (comp instanceof XSDIdentityConstraintDefinition) {
annotation = ((XSDIdentityConstraintDefinition)comp).getAnnotation();
if (annotation == null) {
annotation = XSDFactory.eINSTANCE.createXSDAnnotation();
((XSDIdentityConstraintDefinition)comp).setAnnotation(annotation);
}
} else if (comp instanceof XSDTypeDefinition) {
annotation = ((XSDTypeDefinition)comp).getAnnotation();
if (annotation == null) {
annotation = XSDFactory.eINSTANCE.createXSDAnnotation();
((XSDTypeDefinition)comp).setAnnotation(annotation);
}
} else if (comp instanceof XSDWildcard) {
annotation = ((XSDWildcard)comp).getAnnotation();
if (annotation == null) {
annotation = XSDFactory.eINSTANCE.createXSDAnnotation();
((XSDWildcard)comp).setAnnotation(annotation);
}
} else if (comp instanceof XSDFacet) {
annotation = ((XSDFacet)comp).getAnnotation();
if (annotation == null) {
annotation = XSDFactory.eINSTANCE.createXSDAnnotation();
((XSDFacet)comp).setAnnotation(annotation);
}
} else if (comp instanceof XSDAnnotation) {
annotation = (XSDAnnotation)comp;
}
return annotation;
}
/**
* Set the XSDAnnotation instance on the XSDConcreteComponent if the component can contain annotations otherwise do nothing.
*/
public static void setAnnotation( final XSDConcreteComponent comp,
final XSDAnnotation annotation ) {
CoreArgCheck.isNotNull(comp);
if (annotation == null) {
return;
}
if (comp instanceof XSDSchema) {
((XSDSchema)comp).getContents().add(annotation);
} else if (comp instanceof XSDAttributeDeclaration) {
((XSDAttributeDeclaration)comp).setAnnotation(annotation);
} else if (comp instanceof XSDAttributeGroupDefinition) {
((XSDAttributeGroupDefinition)comp).setAnnotation(annotation);
} else if (comp instanceof XSDElementDeclaration) {
((XSDElementDeclaration)comp).setAnnotation(annotation);
} else if (comp instanceof XSDNotationDeclaration) {
((XSDNotationDeclaration)comp).setAnnotation(annotation);
} else if (comp instanceof XSDModelGroup) {
((XSDModelGroup)comp).setAnnotation(annotation);
} else if (comp instanceof XSDModelGroupDefinition) {
((XSDModelGroupDefinition)comp).setAnnotation(annotation);
} else if (comp instanceof XSDIdentityConstraintDefinition) {
((XSDIdentityConstraintDefinition)comp).setAnnotation(annotation);
} else if (comp instanceof XSDTypeDefinition) {
((XSDTypeDefinition)comp).setAnnotation(annotation);
} else if (comp instanceof XSDWildcard) {
((XSDWildcard)comp).setAnnotation(annotation);
} else if (comp instanceof XSDFacet) {
((XSDFacet)comp).setAnnotation(annotation);
}
}
/**
* Add a documentation node with the specified text to the annotation of the XSDConcreteComponent. If the XSDConcreteComponent
* cannot contain annotations then do nothing.
*
* @param comp the XSDConcreteComponent to add the documentation node to; may not be null
* @param text the documentation text; may not be null or zero length
*/
public static void addUserInfoAttribute( final XSDConcreteComponent comp,
final String text ) {
CoreArgCheck.isNotNull(comp);
CoreArgCheck.isNotZeroLength(text);
// If the XSDConcreteComponent is not a type that can be annotated then return immediately
if (!canAnnotate(comp)) {
return;
}
// Get or create the annotation for the specified component
XSDAnnotation annotation = getAnnotation(comp);
if (annotation == null) {
annotation = XSDFactory.eINSTANCE.createXSDAnnotation();
setAnnotation(comp, annotation);
}
// Add the userInfo to the annotation
addUserInfoAttribute(annotation, text);
}
/**
* Add a documentation node with the specified text to this XSDAnnotation.
*
* @param comp the XSDAnnotation to add the documentation node to; may not be null
* @param text the documentation text; may not be null or zero length
*/
public static void addUserInfoAttribute( final XSDAnnotation annotation,
final String text ) {
CoreArgCheck.isNotNull(annotation);
CoreArgCheck.isNotZeroLength(text);
// if there are any documentation nodes already, remove them
if (!annotation.getUserInformation().isEmpty()) {
ArrayList nodesToRemove = new ArrayList();
final Iterator userInfos = annotation.getUserInformation().iterator();
while (userInfos.hasNext()) {
final Element userInfo = (Element)userInfos.next();
Node child = userInfo.getFirstChild();
if (child != null) {
accumulateTextNodes(child, nodesToRemove);
} else {
nodesToRemove.add(userInfo);
}
}
for (Iterator iter = nodesToRemove.iterator(); iter.hasNext();) {
Node node = (Node)iter.next();
try {
Node parent = node.getParentNode();
if (parent != null) {
parent.removeChild(node);
if (!parent.hasChildNodes()) {
Node infoNode = parent.getParentNode();
infoNode.removeChild(parent);
}
}
} catch (Exception e) {
XsdPlugin.Util.log(e);
}
}
}
// create a new documentation node text node for the annotation
final Element userInfo = annotation.createUserInformation(null);
annotation.getElement().appendChild(userInfo);
userInfo.appendChild(userInfo.getOwnerDocument().createTextNode(text));
return;
}
/**
* Add an Application Information attribute with the given name and value
*
* @param comp
* @param propName
* @param propValue
*/
public static void addApplicationInfoTag( final XSDConcreteComponent comp, // NO_UCD
final String propName,
final String propValue ) {
if (comp == null || propName == null) {
return;
}
XSDAnnotation annotation = getAnnotation(comp, true);
Element appinfo = null;
if (annotation.getApplicationInformation().isEmpty()) {
appinfo = annotation.createApplicationInformation(null);
annotation.getElement().appendChild(appinfo);
} else {
appinfo = annotation.getApplicationInformation().iterator().next();
}
Attr attr = appinfo.getOwnerDocument().createAttribute(propName);
attr.setNodeValue(propValue);
appinfo.getAttributes().setNamedItem(attr);
}
/**
* Return the string value of the App Info Attribute child with the given name.
*
* @param comp
* @param key
* @return
*/
public static String getAppInfoAttributeValue( final XSDConcreteComponent comp, // NO_UCD
final String key ) {
final XSDAnnotation annotation = getAnnotation(comp);
if (annotation == null || annotation.getApplicationInformation().isEmpty()) {
return null;
}
final Iterator elements = annotation.getApplicationInformation().iterator();
while (elements.hasNext()) {
final Element next = (Element)elements.next();
final Attr attr = next.getAttributeNode(key);
if (attr != null) {
return attr.getValue();
}
}
return null;
}
/**
* Get the compositor object (i.e., the <code>sequence</code>, <code>choice</code> or <code>all</code>) under the supplied
* <code>group</code>. The model group may directly contain a compositor.
* <p>
* For example:
* </p>
* <p>
*
* <pre>
* <xsd:group name="shipAndBill">
* <xsd:sequence>
* <xsd:element name="shipTo" type="USAddress"/>
* <xsd:element name="billTo" type="USAddress"/>
* </xsd:sequence>
* </xsd:group>
* </pre>
*
* </p>
*
* @param complexType
* @return
*/
public static XSDModelGroup getCompositor( final XSDModelGroupDefinition group ) {
if (group != null) {
// Get the content ...
return group.getModelGroup();
}
return null;
}
/**
* Determine whether the supplied component is an XSD attribute.
*
* @param component the XSDComponent
* @return true if the component is an attribute; false otherwise
*/
public static boolean isAttribute( final XSDComponent component ) {
if (component != null) {
if (component instanceof XSDAttributeDeclaration) {
return true;
}
}
return false;
}
/**
* Determine whether the supplied compositor is a <code>sequence</code>.
*
* @param modelGroup the model group
* @return true if the model group is not null and is a <code>sequence</code>; false otherwise
*/
public static boolean isSequence( final XSDModelGroup modelGroup ) { // NO_UCD
if (modelGroup != null) {
final XSDCompositor compositor = modelGroup.getCompositor();
return XSDCompositor.SEQUENCE == compositor.getValue();
}
return false;
}
/**
* Determine whether the supplied compositor is a <code>choice</code>.
*
* @param modelGroup the model group
* @return true if the model group is not null and is a <code>choice</code>; false otherwise
*/
public static boolean isChoice( final XSDModelGroup modelGroup ) {
if (modelGroup != null) {
final XSDCompositor compositor = modelGroup.getCompositor();
return XSDCompositor.CHOICE == compositor.getValue();
}
return false;
}
/**
* Determine whether the supplied compositor is an <code>all</code>.
*
* @param modelGroup the model group
* @return true if the model group is not null and is an <code>all</code>; false otherwise
*/
public static boolean isAll( final XSDModelGroup modelGroup ) { // NO_UCD
if (modelGroup != null) {
final XSDCompositor compositor = modelGroup.getCompositor();
return XSDCompositor.ALL == compositor.getValue();
}
return false;
}
public static boolean isWritable( final XSDComponent component ) { // NO_UCD
if (component == null) {
return false;
}
final XSDResourceImpl rsrc = (XSDResourceImpl)component.eResource();
return isWritable(rsrc);
}
public static boolean isWritable( final XSDResourceImpl rsrc ) {
if (rsrc == null) {
return false;
}
URI uri = rsrc.getURI();
if (uri != null && uri.toFileString() != null) {
final File file = new File(uri.toFileString());
if (file.exists()) {
return file.canWrite();
}
}
return true;
}
/**
* Determine whether the supplied component is a global component. A global component is one that is immediately under the
* schema node.
*
* @param xsdComponent the component
* @return true if the component is global, or false otherwise
*/
public static boolean isGlobal( final XSDComponent xsdComponent ) {
if (xsdComponent != null) {
// Get the parent ...
final XSDConcreteComponent parent = xsdComponent.getContainer();
if (parent instanceof XSDSchema) {
return true;
}
}
return false;
}
/**
* Generate the list of types and supertypes for the supplied schema component. The first type in the list will be the schema
* component if it is an XSDTypeDefinition, or the type of the schema component otherwise. The last type in the list will be
* the most root type (typically one of the built-ins).
*
* @param xsdComponent the schema component
* @return the list of types and supertypes; never null, but maybe empty if the supplied component doesn't have a type.
*/
public static List getSupertypes( XSDComponent xsdComponent ) {
final List superTypes = new ArrayList();// LinkedList();
while (xsdComponent != null) {
if (xsdComponent instanceof XSDTypeDefinition) {
superTypes.add(xsdComponent);
}
final XSDTypeDefinition type = getTypeOrBaseType(xsdComponent);
if (type == null || type == xsdComponent) { // base type of 'anyType' is 'anyType'
// No more, so return ...
return superTypes;
}
xsdComponent = type;
}
return superTypes;
}
/**
* Return the type definition that is common to all <code>element</code>s able to be placed under the supplied schema
* component.
*
* @param schemaComponent the schema component for which the common base type for contained elements is to be obtained; may
* not be null
* @return the common type definition, which may be the <code>anyType</code> type; never null
*/
public static XSDTypeDefinition getCommonBaseTypeForContained( final XSDComponent schemaComponent ) {
// Find all of the elements that can be contained by this component
final List childElements = new LinkedList();
addChildElements(schemaComponent, childElements, false);
if (childElements.size() == 1) {
// There is only one type, so return it ...
return (XSDTypeDefinition)childElements.get(0);
}
// For each element, find its hierarchy of types ...
final List supertypesLists = new ArrayList();
final Iterator iter = childElements.iterator();
while (iter.hasNext()) {
final XSDComponent childElement = (XSDComponent)iter.next();
final List supertypes = getSupertypes(childElement);
supertypesLists.add(supertypes);
}
return (XSDTypeDefinition)findFirstCommonObject(supertypesLists);
}
/**
* @param supertypesLists
* @return
*/
protected static Object findFirstCommonObject( final List supertypesLists ) {
if (supertypesLists.size() == 0) {
return null;
}
// if there is only one list of supertypes, then the common supertype is simply the first one
if (supertypesLists.size() == 1) {
final List supertypes = (List)supertypesLists.get(0);
if (supertypes.size() != 0) {
return supertypes.get(0);
}
return null;
}
// Find the most concrete supertype common to them all.
// This algorithm loops through the first list to get the candidate type,
// then loops over all of the remaining lists, and on each loops over the
// supertypes. If we reach the end of one of the remaining lists without a match,
// then break out of all but the outer loop (since that candidate type didn't match
// any in the next list).
final List candiateList = (List)supertypesLists.remove(0);
final Iterator candidateIter = candiateList.iterator();
while (candidateIter.hasNext()) {
boolean failedToFindAnyMatch = false;
final Object candidateType = candidateIter.next();
final Iterator listIter = supertypesLists.iterator();
while (listIter.hasNext()) {
final List supertypesOfAnotherChild = (List)listIter.next();
// Loop over this inner
boolean foundMatch = false;
final Iterator innerIter = supertypesOfAnotherChild.iterator();
while (innerIter.hasNext()) {
Object superOfAnotherChild = innerIter.next();
if (candidateType.equals(superOfAnotherChild)) {
foundMatch = true;
break;
}
}
if (!foundMatch) {
failedToFindAnyMatch = true;
break; // go on to the next list of supertypes
}
// Otherwise, we did find a match so continue with the next list
}
if (!failedToFindAnyMatch) {
// Then we went all the way through the lists and found a match!
return candidateType;
}
}
return null;
}
/**
* Build up the set of {@link XSDElementDeclaration element declarations}
*
* @param xsdComponent
* @param childElements
* @param includeSchemaComponent
*/
protected static void addChildElements( final XSDComponent xsdComponent,
final List childElements,
final boolean includeSchemaComponent ) {
if (xsdComponent instanceof XSDSimpleTypeDefinition) {
return;
}
if (xsdComponent instanceof XSDAnnotation) {
return;
}
if (xsdComponent instanceof XSDAttributeGroupDefinition) {
return;
}
if (xsdComponent instanceof XSDParticle) {
final XSDParticle particle = (XSDParticle)xsdComponent;
final XSDParticleContent content = particle.getContent();
if (content instanceof XSDComponent) {
addChildElements((XSDComponent)content, childElements, true);
}
}
if (xsdComponent instanceof XSDElementDeclaration) {
final XSDTypeDefinition type = getTypeOrBaseType(xsdComponent);
// Get the type ...
if (type != null) {
if (includeSchemaComponent) {
childElements.add(type);
} else {
addChildElements(type, childElements, true);
}
}
return;
}
if (xsdComponent instanceof XSDComplexTypeDefinition) {
final XSDComplexTypeDefinition complexType = (XSDComplexTypeDefinition)xsdComponent;
final XSDModelGroup compositor = getCompositor(complexType);
if (compositor != null) {
// Get the children ...
final List children = compositor.getContents();
final Iterator iter = children.iterator();
while (iter.hasNext()) {
final EObject child = (EObject)iter.next(); // may have XSDDiagnostics that are not XSDComponents!
if (child instanceof XSDComponent) {
addChildElements((XSDComponent)child, childElements, true);
}
}
}
// Add everything from it's super, too
final XSDTypeDefinition superType = getTypeOrBaseType(xsdComponent);
if (superType != null && superType != xsdComponent) { // superType of 'anyType' is 'anyType'
addChildElements(superType, childElements, true);
}
}
if (xsdComponent instanceof XSDModelGroupDefinition) {
final XSDModelGroupDefinition group = (XSDModelGroupDefinition)xsdComponent;
final XSDModelGroup compositor = getCompositor(group);
if (compositor != null) {
// Get the children ...
final List children = compositor.getContents();
final Iterator iter = children.iterator();
while (iter.hasNext()) {
final EObject child = (EObject)iter.next(); // may have XSDDiagnostics that are not XSDComponents!
if (child instanceof XSDComponent) {
addChildElements((XSDComponent)child, childElements, true);
}
}
}
}
}
/**
* Get the type of the supplied element declaration. Note that since the an <code>element</code> can be a reference to another
* <code>element</code> (which could be a reference, etc.), this method resolves all references until it finds a non-null and
* non-reference element declaration.
*
* @param element the element declaration; may not be null
* @return the type of the (resolved) element, or null if there is no type (i.e., the type or a reference could not be
* resolved).
*/
public static XSDTypeDefinition getType( XSDElementDeclaration element ) {
// Resolve, in case this is an element ref. Because refs and point to refs, we have
// to recursively do this until the element ref is the element ...
XSDElementDeclaration resolvedElement = element.getResolvedElementDeclaration();
while (resolvedElement != null && resolvedElement != element) {
element = resolvedElement; // set the element object to be the resolved
resolvedElement = element.getResolvedElementDeclaration(); // resolve again
}
return resolvedElement == null ? null : resolvedElement.getTypeDefinition();
}
/**
* Get the type of the supplied attribute declaration. Note that since the an <code>attribute</code> can be a reference to
* another <code>attribute</code> (which could be a reference, etc.), this method resolves all references until it finds a
* non-null and non-reference attribute declaration.
*
* @param attrib the attribute declaration; may not be null
* @return the type of the (resolved) attribute, or null if there is no type (i.e., the type or a reference could not be
* resolved).
*/
public static XSDTypeDefinition getType( XSDAttributeDeclaration attrib ) {
// Resolve, in case this is an attribute ref. Because refs and point to refs, we have
// to recursively do this until the attribute ref is the attribute ...
XSDAttributeDeclaration resolvedAttrib = attrib.getResolvedAttributeDeclaration();
while (resolvedAttrib != null && resolvedAttrib != attrib) {
attrib = resolvedAttrib; // set the attribute object to be the resolved
resolvedAttrib = attrib.getResolvedAttributeDeclaration(); // resolve again
}
return resolvedAttrib == null ? null : resolvedAttrib.getTypeDefinition();
}
/**
* If the supplied declaration is a reference to another declaration, resolve all references until it finds a non-null and
* non-reference declaration.
*
* @param feature the element or attribute declaration; may not be null
* @return the resolved element, <code>feature</code> if it wasn't a reference, or null if a reference could not be resolved.
*/
public static XSDFeature getResolved( XSDFeature feature ) {
if (feature instanceof XSDElementDeclaration) {
return getResolved((XSDElementDeclaration)feature);
}
if (feature instanceof XSDAttributeDeclaration) {
return getResolved((XSDAttributeDeclaration)feature);
}
return null; // should never happen
}
/**
* If the supplied declaration is a reference to another declaration, resolve all references until it finds a non-null and
* non-reference declaration.
*
* @param element the element declaration; may not be null
* @return the resolved element, <code>element</code> if it wasn't a reference, or null if a reference could not be resolved.
*/
public static XSDElementDeclaration getResolved( XSDElementDeclaration element ) {
// Resolve, in case this is an element ref. Because refs and point to refs, we have
// to recursively do this until the element ref is the element ...
XSDElementDeclaration resolvedElement = element.getResolvedElementDeclaration();
while (resolvedElement != null && resolvedElement != element) {
element = resolvedElement; // set the element object to be the resolved
resolvedElement = element.getResolvedElementDeclaration(); // resolve again
}
return resolvedElement;
}
/**
* If the supplied declaration is a reference to another declaration, resolve all references until it finds a non-null and
* non-reference declaration.
*
* @param attribute the attribute declaration; may not be null
* @return the resolved element, <code>attribute</code> if it wasn't a reference, or null if a reference could not be
* resolved.
*/
public static XSDAttributeDeclaration getResolved( XSDAttributeDeclaration attribute ) {
// Resolve, in case this is an element ref. Because refs and point to refs, we have
// to recursively do this until the element ref is the element ...
XSDAttributeDeclaration resolvedAttribute = attribute.getResolvedAttributeDeclaration();
while (resolvedAttribute != null && resolvedAttribute != attribute) {
attribute = resolvedAttribute; // set the element object to be the resolved
resolvedAttribute = attribute.getResolvedAttributeDeclaration(); // resolve again
}
return resolvedAttribute;
}
/**
* Get the XSDSimpleTypeDefinition for the supplied schema component.
*
* @param xsdComponent the component for which the simple type definition is to be returned
* @return the simple type definition, or null if there is none (or the component is not defined to have a type)
*/
public static XSDSimpleTypeDefinition getSimpleType( final XSDComponent xsdComponent ) {
XSDTypeDefinition xsdType = getType(xsdComponent);
if (xsdType != null) {
return getSimpleType(xsdType);
}
return null;
}
/**
* Get the XSDSimpleTypeDefinition for the XSDTypeDefinition or null if the XSDTypeDefinition is not a XSDSimpleTypeDefinition
* or does not extend or restrict a XSDSimpleTypeDefinition.
*
* @param xsdType
* @return the simple datatype or null if there is none.
*/
public static XSDSimpleTypeDefinition getSimpleType( final XSDTypeDefinition xsdType ) {
XSDSimpleTypeDefinition simpleType = null;
if (xsdType != null && xsdType instanceof XSDSimpleTypeDefinition) {
simpleType = (XSDSimpleTypeDefinition)xsdType;
return simpleType;
}
if (xsdType != null && xsdType instanceof XSDComplexTypeDefinition) {
XSDComplexTypeDefinition complexType = (XSDComplexTypeDefinition)xsdType;
XSDTypeDefinition type = complexType;
while (type != null) {
if (isAnySimpleType(type)) {
simpleType = (XSDSimpleTypeDefinition)type;
break;
} else if (isAnyType(type)) {
break;
} else if (type instanceof XSDSimpleTypeDefinition) {
simpleType = (XSDSimpleTypeDefinition)type;
break;
} else if (type instanceof XSDComplexTypeDefinition) {
XSDTypeDefinition baseType = ((XSDComplexTypeDefinition)type).getBaseTypeDefinition();
// Break any recursion
if (baseType == type) break;
type = baseType;
} else break;
}
return simpleType;
}
return null;
}
/**
* Get the type of the supplied schema component.
*
* @param xsdComponent the component for which the type definition is to be returned
* @return the type definition, or null if there is none (or the component is not defined to have a type)
*/
public static XSDTypeDefinition getType( final XSDComponent xsdComponent ) {
if (xsdComponent instanceof XSDElementDeclaration) {
return getType((XSDElementDeclaration)xsdComponent);
}
if (xsdComponent instanceof XSDAttributeDeclaration) {
return getType((XSDAttributeDeclaration)xsdComponent);
}
if (xsdComponent instanceof XSDTypeDefinition) {
return (XSDTypeDefinition)xsdComponent;
}
return null;
}
/**
* Get the Teiid Designer built-in datatype of the supplied type.
*
* @param type
* @return the built-in datatype or null if there is none.
*/
public static XSDSimpleTypeDefinition getBuiltInDatatype( final XSDTypeDefinition type ) {
XSDSimpleTypeDefinition builtInType = null;
if (type != null && type instanceof XSDComplexTypeDefinition) {
XSDComplexTypeDefinition complexType = (XSDComplexTypeDefinition)type;
try {
// Use the workspace datatype manager, since we're looking for a BUILT-IN TYPE
builtInType = (XSDSimpleTypeDefinition)ModelerCore.getWorkspaceDatatypeManager().getDatatypeForXsdType(complexType);
} catch (ModelerCoreException e) {
Object[] params = new Object[] {type.getURI()};
String msg = XsdPlugin.Util.getString("XsdUtil.Unable_to_get_the_MetaMatrix_built-in_datatype_for_1", params); //$NON-NLS-1$
XsdPlugin.Util.log(IStatus.ERROR, e, msg);
}
}
if (type != null && type instanceof XSDSimpleTypeDefinition) {
XSDSimpleTypeDefinition simpleType = (XSDSimpleTypeDefinition)type;
try {
// Use the workspace datatype manager, since we're looking for a BUILT-IN TYPE
builtInType = (XSDSimpleTypeDefinition)ModelerCore.getWorkspaceDatatypeManager().getDatatypeForXsdType(simpleType);
} catch (ModelerCoreException e) {
Object[] params = new Object[] {type.getURI()};
String msg = XsdPlugin.Util.getString("XsdUtil.Unable_to_get_the_MetaMatrix_built-in_datatype_for_2", params); //$NON-NLS-1$
XsdPlugin.Util.log(IStatus.ERROR, e, msg);
}
}
return builtInType;
}
/**
* Get the Teiid Designer built-in datatype of the supplied element declaration
*
* @param element the element declaration; may not be null
* @return the built-in datatype of the (resolved) element, or null if there is no type.
*/
public static XSDSimpleTypeDefinition getBuiltInDatatype( final XSDElementDeclaration element ) { // NO_UCD
XSDTypeDefinition type = getType(element);
return getBuiltInDatatype(type);
}
/**
* Get the Teiid Designer built-in datatype of the supplied supplied schema component
*
* @param xsdComponent the component for which the datatype is to be returned
* @return the built-in datatype or null if there is none.
*/
public static XSDSimpleTypeDefinition getBuiltInDatatype( final XSDComponent xsdComponent ) { // NO_UCD
XSDTypeDefinition type = getType(xsdComponent);
return getBuiltInDatatype(type);
}
/**
* Get the type or base type of the supplied schema component. For components like <code>element</code>, this returns the
* {@link #getType(XSDElementDeclaration) type} of the element. For {@link XSDTypeDefinition type definitions}, this method
* returns the {@link XSDTypeDefinition#getBaseType() base type}.
*
* @param xsdComponent the component for which the type definition is to be returned
* @return the type definition or base type definition, or null if there is none (or the component is not defined to have a
* type)
*/
public static XSDTypeDefinition getTypeOrBaseType( final XSDComponent xsdComponent ) {
if (xsdComponent instanceof XSDElementDeclaration) {
return getType((XSDElementDeclaration)xsdComponent);
}
if (xsdComponent instanceof XSDTypeDefinition) {
return ((XSDTypeDefinition)xsdComponent).getBaseType();
}
return null;
}
/**
* Returns whether the type definition is one of the flavours of the ur-type, i.e., complex <a
* href="http://www.w3.org/TR/xmlschema-1/#ur-type-itself">anyType</a>, simple <a
* href="http://www.w3.org/TR/xmlschema-2/#built-in-datatypes">anyType</a>, or <a
* href="http://www.w3.org/TR/xmlschema-2/#dt-anySimpleType">anySimpleType</a>.
*
* @param xsdTypeDefinition a simple or complex type definition.
* @return whether the type definition is one of the flavours of the ur-type.
*/
public static boolean isURType( final XSDTypeDefinition xsdType ) { // NO_UCD
if (xsdType != null) {
return XSDConstants.isURType(xsdType);
}
return false;
}
/**
* Returns whether the type definition is one of the flavours of the anyType, i.e., complex <a
* href="http://www.w3.org/TR/xmlschema-1/#ur-type-itself">anyType</a> or simple <a
* href="http://www.w3.org/TR/xmlschema-2/#built-in-datatypes">anyType</a>.
*
* @param xsdTypeDefinition a simple or complex type definition.
* @return whether the type definition is one of the flavours of the anyType.
*/
public static boolean isAnyType( final XSDTypeDefinition xsdType ) {
if (xsdType != null) {
return XSDConstants.isAnyType(xsdType);
}
return false;
}
/**
* Returns whether the type definition is the <a href="http://www.w3.org/TR/xmlschema-2/#dt-anySimpleType">anySimpleType</a>.
*
* @param xsdTypeDefinition a simple or complex type definition.
* @return whether the type definition is the anySimpleType.
*/
public static boolean isAnySimpleType( final XSDTypeDefinition xsdType ) {
if (xsdType != null) {
return XSDConstants.isAnySimpleType(xsdType);
}
return false;
}
/**
* Return whether the supplied schema component is a built-in datatype.
*
* @param xsdComponent the schema component
* @return true if the supplied schema component is a simple type and is one of the built-in simple types, or false otherwise
*/
public static boolean isBuiltInDatatype( final XSDComponent xsdComponent ) {
if (xsdComponent != null && xsdComponent instanceof XSDSimpleTypeDefinition) {
final XSDSimpleTypeDefinition simpleType = (XSDSimpleTypeDefinition)xsdComponent;
return isBuiltInDatatype(simpleType);
}
return false;
}
/**
* Return whether the supplied simple type is a built-in datatype.
*
* @param simpleType the simple type
* @return true if the supplied simple type is one of the built-in simple types, or false otherwise
*/
public static boolean isBuiltInDatatype( final XSDSimpleTypeDefinition simpleType ) {
final String namespaceUri = simpleType.getTargetNamespace();
if (BUILT_IN_DATATYPE_NAMESPACE_URI.equals(namespaceUri)) {
return true;
}
if (XSDConstants.SCHEMA_FOR_SCHEMA_URI_2001.equals(namespaceUri)) {
return true;
}
if (XSDConstants.SCHEMA_FOR_SCHEMA_URI_2000_10.equals(namespaceUri)) {
return true;
}
if (XSDConstants.SCHEMA_FOR_SCHEMA_URI_1999.equals(namespaceUri)) {
return true;
}
return false;
}
public static boolean isNillable( final XSDComponent component ) {
if (component instanceof XSDElementDeclaration) {
final XSDElementDeclaration element = (XSDElementDeclaration)component;
return element.isNillable();
}
return false;
}
/**
* This method returns the literal minOccurs on the XSDComponent.
*
* @param component
* @return
* @see #getMinOccurs(XSDComponent)
* @see #getMaxOccursLiteral(XSDComponent)
* @since 4.2
*/
public static int getMinOccursLiteral( final XSDComponent component ) { // NO_UCD
if (component instanceof XSDElementDeclaration) {
final XSDElementDeclaration element = (XSDElementDeclaration)component;
// Get the container ...
final XSDConcreteComponent container = element.getContainer();
if (container instanceof XSDSchema) {
return 0;
}
if (container instanceof XSDParticle) {
final XSDParticle particle = (XSDParticle)container;
return getMinOccursLiteral(particle);
}
}
if (component instanceof XSDModelGroupDefinition) {
final XSDModelGroupDefinition group = (XSDModelGroupDefinition)component;
// Get the container ...
final XSDConcreteComponent container = group.getContainer();
if (container instanceof XSDSchema) {
return 0;
}
if (container instanceof XSDParticle) {
final XSDParticle particle = (XSDParticle)container;
return getMinOccursLiteral(particle);
}
}
if (component instanceof XSDModelGroup) {
final XSDModelGroup group = (XSDModelGroup)component;
// Get the container ...
final XSDConcreteComponent container = group.getContainer();
if (container instanceof XSDSchema) {
return 0;
}
if (container instanceof XSDParticle) {
final XSDParticle particle = (XSDParticle)container;
return getMinOccursLiteral(particle);
}
}
if (component instanceof XSDWildcard) {
final XSDWildcard any = (XSDWildcard)component;
// Get the container ...
final XSDConcreteComponent container = any.getContainer();
if (container instanceof XSDSchema) {
return 0;
}
if (container instanceof XSDParticle) {
final XSDParticle particle = (XSDParticle)container;
return getMinOccursLiteral(particle);
}
}
if (component instanceof XSDParticle) {
final XSDParticle particle = (XSDParticle)component;
int minOccurs = particle.getMinOccurs();
return minOccurs;
}
return 0;
}
/**
* This method returns the literal maxOccurs on the XSDComponent.
*
* @param component
* @return
* @see #getMaxOccurs(XSDComponent)
* @see #getMinOccursLiteral(XSDComponent)
* @since 4.2
*/
public static int getMaxOccursLiteral( final XSDComponent component ) {
if (component instanceof XSDElementDeclaration) {
final XSDElementDeclaration element = (XSDElementDeclaration)component;
// Get the container ...
final XSDConcreteComponent container = element.getContainer();
if (container instanceof XSDSchema) {
return -1;
}
if (container instanceof XSDParticle) {
final XSDParticle particle = (XSDParticle)container;
return getMaxOccursLiteral(particle);
}
}
if (component instanceof XSDModelGroupDefinition) {
final XSDModelGroupDefinition group = (XSDModelGroupDefinition)component;
// Get the container ...
final XSDConcreteComponent container = group.getContainer();
if (container instanceof XSDSchema) {
return -1;
}
if (container instanceof XSDParticle) {
final XSDParticle particle = (XSDParticle)container;
return getMaxOccursLiteral(particle);
}
}
if (component instanceof XSDModelGroup) {
final XSDModelGroup group = (XSDModelGroup)component;
// Get the container ...
final XSDConcreteComponent container = group.getContainer();
if (container instanceof XSDSchema) {
return -1;
}
if (container instanceof XSDParticle) {
final XSDParticle particle = (XSDParticle)container;
return getMaxOccursLiteral(particle);
}
}
if (component instanceof XSDWildcard) {
final XSDWildcard any = (XSDWildcard)component;
// Get the container ...
final XSDConcreteComponent container = any.getContainer();
if (container instanceof XSDSchema) {
return -1;
}
if (container instanceof XSDParticle) {
final XSDParticle particle = (XSDParticle)container;
return getMaxOccursLiteral(particle);
}
}
if (component instanceof XSDParticle) {
final XSDParticle particle = (XSDParticle)component;
int maxOccurs = particle.getMaxOccurs();
return maxOccurs;
}
return -1;
}
/**
* This method computes the effective minimum occurs for an XSDComponent; that is, the minimum number of times that the
* component may appear in an XML document, not just the minimum number of times the component may appear in the context of
* it's parent (see {@link #getMaxOccursLiteral(XSDComponent)}. Note that the model groups (e.g., sequences, choices, and
* alls) have the ability to compound the minimum occurs. For example, the "author" element must appear at least zero times
* given the following fragment:
* <p>
* <code>
* <xsd:complexType name="typeA">
* <xsd:sequence minOccurs="0" maxOccurs="unbounded">
* <xsd:element name="author" type="typeB" />
* </xsd:sequence>
* </xsd:complexType>
* </code>
* </p>
* The following fragment actually requires the "author" element to appear at least 8 times (1x2x4) and the "publisher"
* element at least 0 times (0x4):
* <p>
* <code>
* <xsd:complexType name="typeA">
* <xsd:sequence minOccurs="4" maxOccurs="40">
* <xsd:sequence minOccurs="2" maxOccurs="20">
* <xsd:element minOccurs="1" name="author" type="typeB" />
* </xsd:sequence>
* <xsd:element minOccurs="0" name="publisher" type="typeC" />
* </xsd:sequence>
* </xsd:complexType>
* </code>
* </p>
*
* @param component
* @return
* @see #getMaxOccurs(XSDComponent)
* @see #getMinOccursLiteral(XSDComponent)
* @since 4.2
*/
public static int getMinOccurs( final XSDComponent component ) {
if (component instanceof XSDElementDeclaration) {
final XSDElementDeclaration element = (XSDElementDeclaration)component;
// Get the container ...
final XSDConcreteComponent container = element.getContainer();
if (container instanceof XSDSchema) {
return 0;
}
if (container instanceof XSDParticle) {
final XSDParticle particle = (XSDParticle)container;
return getMinOccurs(particle);
}
}
if (component instanceof XSDModelGroupDefinition) {
final XSDModelGroupDefinition group = (XSDModelGroupDefinition)component;
// Get the container ...
final XSDConcreteComponent container = group.getContainer();
if (container instanceof XSDSchema) {
return 0;
}
if (container instanceof XSDParticle) {
final XSDParticle particle = (XSDParticle)container;
return getMinOccurs(particle);
}
}
if (component instanceof XSDModelGroup) {
final XSDModelGroup group = (XSDModelGroup)component;
// Get the container ...
final XSDConcreteComponent container = group.getContainer();
if (container instanceof XSDSchema) {
return 0;
}
if (container instanceof XSDParticle) {
final XSDParticle particle = (XSDParticle)container;
return getMinOccurs(particle);
}
}
if (component instanceof XSDWildcard) {
final XSDWildcard any = (XSDWildcard)component;
// Get the container ...
final XSDConcreteComponent container = any.getContainer();
if (container instanceof XSDSchema) {
return 0;
}
if (container instanceof XSDParticle) {
final XSDParticle particle = (XSDParticle)container;
return getMinOccurs(particle);
}
}
if (component instanceof XSDParticle) {
final XSDParticle particle = (XSDParticle)component;
int minOccurs = particle.getMinOccurs();
if (minOccurs == 0) {
return minOccurs;
}
// It is not unlimited, so walk up the owners and compound (multiply) the minOccurs
// from sequences
XSDConcreteComponent particleParent = particle.getContainer();
while (particleParent instanceof XSDModelGroup || particleParent instanceof XSDModelGroupDefinition) {
// If the particleParent is a choice, then the minOccurs is 0 ...
if (particleParent instanceof XSDModelGroup && isChoice((XSDModelGroup)particleParent)) {
return 0;
}
// Get the particle of the model group (compositor) or model group definition (group) ...
final XSDConcreteComponent particleGrandparent = particleParent.getContainer();
if (particleGrandparent instanceof XSDParticle) {
final XSDParticle modelGroupParticle = (XSDParticle)particleGrandparent;
// Return the model group's min occurs, regardless of whether it is set (see defect 11343).
final int groupOccurs = modelGroupParticle.getMinOccurs();
minOccurs *= groupOccurs;
// Keep walking up to see if this sequence is contained by another sequence ...
particleParent = modelGroupParticle.getContainer();
} else {
// Stop
break;
}
if (minOccurs == 0) {
break;
}
}
return minOccurs;
}
return 0;
}
/**
* This method computes the effective maximum occurs for an XSDComponent; that is, the maximum number of times that the
* component may appear in an XML document, not just the maximum number of times the component may appear in the context of
* it's parent (see {@link #getMaxOccursLiteral(XSDComponent)}. Note that the model groups (e.g., sequences, choices, and
* alls) have the ability to compound the maximum occurs. For example, the "author" element may appear an unlimited number of
* times given the following fragment:
* <p>
* <code>
* <xsd:complexType name="typeA">
* <xsd:sequence minOccurs="0" maxOccurs="unbounded">
* <xsd:element name="author" type="typeB" />
* </xsd:sequence>
* </xsd:complexType>
* </code>
* </p>
* The following fragment actually allows the "author" element to appear up to 8 times (1x2x4) and the "publisher" element up
* to 4 times (1x4):
* <p>
* <code>
* <xsd:complexType name="typeA">
* <xsd:sequence maxOccurs="4">
* <xsd:sequence maxOccurs="2">
* <xsd:element name="author" type="typeB" />
* </xsd:sequence>
* <xsd:element name="publisher" type="typeC" />
* </xsd:sequence>
* </xsd:complexType>
* </code>
* </p>
*
* @param component
* @return
* @see #getMinOccurs(XSDComponent)
* @see #getMaxOccursLiteral(XSDComponent)
* @since 4.2
*/
public static int getMaxOccurs( final XSDComponent component ) {
if (component instanceof XSDElementDeclaration) {
final XSDElementDeclaration element = (XSDElementDeclaration)component;
// Get the container ...
final XSDConcreteComponent container = element.getContainer();
if (container instanceof XSDSchema) {
return 1;
}
if (container instanceof XSDParticle) {
final XSDParticle particle = (XSDParticle)container;
return getMaxOccurs(particle);
}
}
if (component instanceof XSDModelGroupDefinition) {
final XSDModelGroupDefinition group = (XSDModelGroupDefinition)component;
// Get the container ...
final XSDConcreteComponent container = group.getContainer();
if (container instanceof XSDSchema) {
return 1;
}
if (container instanceof XSDParticle) {
final XSDParticle particle = (XSDParticle)container;
return getMaxOccurs(particle);
}
}
if (component instanceof XSDModelGroup) {
final XSDModelGroup group = (XSDModelGroup)component;
// Get the container ...
final XSDConcreteComponent container = group.getContainer();
if (container instanceof XSDSchema) {
return 1;
}
if (container instanceof XSDParticle) {
final XSDParticle particle = (XSDParticle)container;
return getMaxOccurs(particle);
}
}
if (component instanceof XSDWildcard) {
final XSDWildcard any = (XSDWildcard)component;
// Get the container ...
final XSDConcreteComponent container = any.getContainer();
if (container instanceof XSDSchema) {
return 1;
}
if (container instanceof XSDParticle) {
final XSDParticle particle = (XSDParticle)container;
return getMaxOccurs(particle);
}
}
if (component instanceof XSDParticle) {
final XSDParticle particle = (XSDParticle)component;
int maxOccurs = particle.getMaxOccurs();
if (maxOccurs == -1) {
return maxOccurs;
}
// It is not unlimited, so walk up the owners and compound (multiply) the maxOccurs
// from sequences
XSDConcreteComponent particleParent = particle.getContainer();
while (particleParent instanceof XSDModelGroup || particleParent instanceof XSDModelGroupDefinition) {
// Get the particle of the model group (compositor) or model group definition (group) ...
final XSDConcreteComponent particleGrandparent = particleParent.getContainer();
if (particleGrandparent instanceof XSDParticle) {
final XSDParticle modelGroupParticle = (XSDParticle)particleGrandparent;
// Return the model group's max occurs, regardless of whether it is set (see defect 11343).
final int groupOccurs = modelGroupParticle.getMaxOccurs();
if (groupOccurs == -1) {
return groupOccurs;
}
maxOccurs *= groupOccurs;
// Keep walking up to see if this sequence is contained by another sequence ...
particleParent = modelGroupParticle.getContainer();
} else {
// Stop
break;
}
if (maxOccurs == -1) {
break;
}
}
return maxOccurs;
}
return 1;
}
/**
* This method computes the use for an XSD Attribute.
*
* @param component
* @return One of:
* <ul>
* <li>XSDAttributeUseCategory.OPTIONAL_LITERAL,</li>
* <li>XSDAttributeUseCategory.PROHIBITED_LITERAL, or</li>
* <li>XSDAttributeUseCategory.REQUIRED_LITERAL</li>
* </ul>
* @since 4.2
*/
public static XSDAttributeUseCategory getUse( final XSDComponent component ) {
XSDAttributeUse use = null;
if (component instanceof XSDAttributeUse) {
use = (XSDAttributeUse)component;
} else {
final XSDConcreteComponent parent = component.getContainer();
if (parent instanceof XSDAttributeUse) {
use = (XSDAttributeUse)parent;
}
}
return (use == null ? XSDAttributeUseCategory.OPTIONAL_LITERAL : use.getUse());
}
/**
* Returns the concatenated child text of the specified node. This method only looks at the immediate children of type
* <code>Node.TEXT_NODE</code> or the children of any child node that is of type <code>Node.CDATA_SECTION_NODE</code> for the
* concatenation. This method was copied from the org.apache.xerces.util.DOMUtil class.
*
* @param node The node to look at.
*/
public static String getChildText( final Node node ) {
// is there anything to do?
if (node == null) {
return null;
}
// concatenate children text
StringBuffer str = new StringBuffer();
Node child = node.getFirstChild();
while (child != null) {
short type = child.getNodeType();
if (type == Node.TEXT_NODE) {
str.append(child.getNodeValue());
} else if (type == Node.CDATA_SECTION_NODE) {
str.append(getChildText(child));
}
child = child.getNextSibling();
}
// return text value
return str.toString();
}
/**
* Given an AppInfo Node, recurse through all the children and build a Tag / value structure for all of the Element children.
*
* @param node The node to look at.
*/
public static String getAppInfoText( final Node node ) {
// is there anything to do?
if (node == null) {
return null;
}
// concatenate children text
StringBuffer str = new StringBuffer();
Node child = node.getFirstChild();
str.append("<Application Information>"); //$NON-NLS-1$
while (child != null) {
short type = child.getNodeType();
if (type == Node.ELEMENT_NODE) {
str.append("\n\t<"); //$NON-NLS-1$
str.append(child.getNodeName());
str.append(">"); //$NON-NLS-1$
str.append(getChildText(child));
str.append("</"); //$NON-NLS-1$
str.append(child.getNodeName());
str.append(">"); //$NON-NLS-1$
}
child = child.getNextSibling();
}
for (int i = 0; i < node.getAttributes().getLength(); i++) {
final Node next = node.getAttributes().item(i);
str.append("\n\t<"); //$NON-NLS-1$
str.append(next.getNodeName());
str.append(">"); //$NON-NLS-1$
str.append(getChildText(next));
str.append("</"); //$NON-NLS-1$
str.append(next.getNodeName());
}
str.append("\n</Application Information>"); //$NON-NLS-1$
// return text value
return str.toString();
}
/**
* Get the description from the annotation, if one exists, on the specified XSD object.
*
* @param eObject
* @return
* @since 4.2
*/
public static String getDescription( XSDConcreteComponent eObject ) {
XSDAnnotation annotation = null;
if (eObject instanceof XSDAnnotation) {
annotation = (XSDAnnotation)eObject;
} else {
annotation = getAnnotation(eObject);
}
if (annotation != null) {
final Iterator userInfos = annotation.getUserInformation().iterator();
while (userInfos.hasNext()) {
final Element userInfo = (Element)userInfos.next();
final String value = getChildText(userInfo);
if (value != null) {
return value;
}
}
final Iterator appInfos = annotation.getApplicationInformation().iterator();
while (appInfos.hasNext()) {
final Element appInfo = (Element)appInfos.next();
final String value = getAppInfoText(appInfo);
if (value != null) {
return value;
}
}
}
return CoreStringUtil.Constants.EMPTY_STRING;
}
/**
* Recursively accumulates all text and CDATA type nodes beneath the specified node.
*
* @param node
* @return
* @since 4.2
*/
private static void accumulateTextNodes( Node node,
List collection ) {
while (node != null) {
short type = node.getNodeType();
if (type == Node.TEXT_NODE) {
collection.add(node);
} else if (type == Node.CDATA_SECTION_NODE) {
// recurse
accumulateTextNodes(node.getFirstChild(), collection);
}
node = node.getNextSibling();
}
}
private static void CoreArgCheckIsResolved( EObject e ) {
if (e.eIsProxy()) {
throw new IllegalArgumentException(
XsdPlugin.Util.getString("XsdSimpleTypeDefinitionAspect.Error_EObject_can_not_be_a_proxy", e.toString())); //$NON-NLS-1$
}
}
}