/******************************************************************************* * Copyright (c) 2010 SAP AG. * 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: * Emil Simeonov - initial API and implementation. * Dimitar Donchev - initial API and implementation. * Dimitar Tenev - initial API and implementation. * Nevena Manova - initial API and implementation. * Georgi Konstantinov - initial API and implementation. * Keshav Veerapaneni - initial API and implementation. *******************************************************************************/ package org.eclipse.wst.sse.sieditor.model.utils; import java.net.URISyntaxException; import java.text.CharacterIterator; import java.text.StringCharacterIterator; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.Assert; import org.eclipse.emf.common.util.EList; 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.emf.ecore.resource.impl.ResourceSetImpl; import org.eclipse.emf.ecore.xml.type.util.XMLTypeUtil; import org.eclipse.emf.query.conditions.eobjects.EObjectCondition; import org.eclipse.emf.query.conditions.eobjects.structuralfeatures.EObjectReferencerCondition; import org.eclipse.emf.query.statements.FROM; import org.eclipse.emf.query.statements.IQueryResult; import org.eclipse.emf.query.statements.SELECT; import org.eclipse.emf.query.statements.WHERE; import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion; import org.eclipse.wst.wsdl.Definition; import org.eclipse.wst.wsdl.WSDLElement; import org.eclipse.wst.xml.core.internal.document.NodeImpl; import org.eclipse.xsd.XSDAnnotation; import org.eclipse.xsd.XSDAttributeDeclaration; import org.eclipse.xsd.XSDAttributeGroupContent; import org.eclipse.xsd.XSDAttributeGroupDefinition; import org.eclipse.xsd.XSDAttributeUse; import org.eclipse.xsd.XSDComplexTypeContent; import org.eclipse.xsd.XSDComplexTypeDefinition; import org.eclipse.xsd.XSDConcreteComponent; import org.eclipse.xsd.XSDElementDeclaration; import org.eclipse.xsd.XSDFactory; import org.eclipse.xsd.XSDForm; import org.eclipse.xsd.XSDIdentityConstraintDefinition; import org.eclipse.xsd.XSDModelGroup; import org.eclipse.xsd.XSDModelGroupDefinition; import org.eclipse.xsd.XSDNamedComponent; import org.eclipse.xsd.XSDPackage; 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.impl.XSDSchemaImpl; import org.eclipse.xsd.util.XSDConstants; import org.eclipse.xsd.util.XSDResourceImpl; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.ProcessingInstruction; import org.eclipse.wst.sse.sieditor.core.common.Nil; import org.eclipse.wst.sse.sieditor.model.api.IModelObject; import org.eclipse.wst.sse.sieditor.model.api.IXSDModelRoot; import org.eclipse.wst.sse.sieditor.model.wsdl.api.IDescription; import org.eclipse.wst.sse.sieditor.model.xsd.api.ISchema; import org.eclipse.wst.sse.sieditor.model.xsd.api.ISimpleType; import org.eclipse.wst.sse.sieditor.model.xsd.api.IType; import org.eclipse.wst.sse.sieditor.model.xsd.impl.SimpleType; import org.eclipse.wst.sse.sieditor.model.xsd.impl.UnresolvedType; /** * EMF XSD Utils * * */ public final class EmfXsdUtils { private static ArrayList<String> _schemaTypes = new ArrayList<String>(); static { // Add all primitive types to list _schemaTypes.add("string"); //$NON-NLS-1$ _schemaTypes.add("boolean"); //$NON-NLS-1$ _schemaTypes.add("float"); //$NON-NLS-1$ _schemaTypes.add("double"); //$NON-NLS-1$ _schemaTypes.add("decimal"); //$NON-NLS-1$ _schemaTypes.add("duration"); //$NON-NLS-1$ _schemaTypes.add("dateTime"); //$NON-NLS-1$ _schemaTypes.add("time"); //$NON-NLS-1$ _schemaTypes.add("date"); //$NON-NLS-1$ _schemaTypes.add("gYearMonth"); //$NON-NLS-1$ _schemaTypes.add("gYear"); //$NON-NLS-1$ _schemaTypes.add("gMonthDay"); //$NON-NLS-1$ _schemaTypes.add("gDay"); //$NON-NLS-1$ _schemaTypes.add("gMonth"); //$NON-NLS-1$ _schemaTypes.add("hexBinary"); //$NON-NLS-1$ _schemaTypes.add("base64Binary"); //$NON-NLS-1$ _schemaTypes.add("anyURI"); //$NON-NLS-1$ _schemaTypes.add("QName"); //$NON-NLS-1$ _schemaTypes.add("NOTATION"); //$NON-NLS-1$ _schemaTypes.add("normalizedString"); //$NON-NLS-1$ _schemaTypes.add("token"); //$NON-NLS-1$ _schemaTypes.add("language"); //$NON-NLS-1$ _schemaTypes.add("IDREFS"); //$NON-NLS-1$ _schemaTypes.add("ENTITIES"); //$NON-NLS-1$ _schemaTypes.add("NMTOKEN"); //$NON-NLS-1$ _schemaTypes.add("NMTOKENS"); //$NON-NLS-1$ _schemaTypes.add("Name"); //$NON-NLS-1$ _schemaTypes.add("NCName"); //$NON-NLS-1$ _schemaTypes.add("ID"); //$NON-NLS-1$ _schemaTypes.add("IDREF"); //$NON-NLS-1$ _schemaTypes.add("ENTITY"); //$NON-NLS-1$ _schemaTypes.add("integer"); //$NON-NLS-1$ _schemaTypes.add("nonPositiveInteger"); //$NON-NLS-1$ _schemaTypes.add("negativeInteger"); //$NON-NLS-1$ _schemaTypes.add("long"); //$NON-NLS-1$ _schemaTypes.add("int"); //$NON-NLS-1$ _schemaTypes.add("short"); //$NON-NLS-1$ _schemaTypes.add("byte"); //$NON-NLS-1$ _schemaTypes.add("nonNegativeInteger"); //$NON-NLS-1$ _schemaTypes.add("unsignedInt"); //$NON-NLS-1$ _schemaTypes.add("unsignedLong"); //$NON-NLS-1$ _schemaTypes.add("unsignedShort"); //$NON-NLS-1$ _schemaTypes.add("unsignedByte"); //$NON-NLS-1$ _schemaTypes.add("positiveInteger"); //$NON-NLS-1$ } private static XSDSchema _schemaForSchema; private static final String EXAMPLE_SCHEMA_NS = "http://www.example.xsd"; //$NON-NLS-1$ private static final String TNS_PREFIX = "tns"; //$NON-NLS-1$ public static final String XSD_PREFIX = "xsd"; //$NON-NLS-1$ public static final String XMLNS_PREFIX = "xmlns"; //$NON-NLS-1$ private static final String NAMESPACE_PREFIX_PREFIX = "ns"; //$NON-NLS-1$ public static final String NAMESPACE_DELIMITER = ":"; //$NON-NLS-1$ public static final String TNS_ATTRIBUTE_NAME = "targetNamespace"; //$NON-NLS-1$ public static final String XML_TAG_NAME = "xml"; //$NON-NLS-1$ public static final String ATTRIBUTE_REF = "ref"; //$NON-NLS-1$ private EmfXsdUtils() { // Stop any instance creation } /** * Returns a Factory for creation of EMF XSD Objects * * @return */ public static final XSDFactory getXSDFactory() { return XSDFactory.eINSTANCE; } /** * Returns a Factory for creation of EMF XSD Objects * * @return */ public static final XSDPackage getXSDPackage() { return XSDFactory.eINSTANCE.getXSDPackage(); } /** * Wrap XSD type in SIE model ISimpleType and calls * getRootBaseType(ISimpleType type) * * @param type * which's hierarchy is being examined * @see EmfXsdUtils#getRootBaseType(ISimpleType) */ public static XSDTypeDefinition getRootBaseType(final XSDSimpleTypeDefinition type) { final XSDSchema xsdSchema = type.getSchema(); final IXSDModelRoot modelRoot = org.eclipse.wst.sse.sieditor.model.impl.XSDFactory.getInstance().createXSDModelRoot( xsdSchema); final ISchema schema = modelRoot.getSchema(); final ISimpleType simpleType = new SimpleType(modelRoot, schema, type); return (XSDTypeDefinition) getRootBaseType(simpleType).getComponent(); } /** * Drills down the base type hierarchy of a simple type,<br> * until root (primitive) type is reached. * * @param type * which's hierarchy is being examined * @return the primitive parent or null if the type is recursively defined * (contained in it's own hierarchy) */ public static ISimpleType getRootBaseType(final ISimpleType type) { if (EmfXsdUtils.isSchemaForSchemaNS(type.getNamespace())) { return type; } IType baseType = type; final Set<IType> typeHierarchySet = new HashSet<IType>(); typeHierarchySet.add(baseType); while (baseType instanceof ISimpleType && !EmfXsdUtils.isSchemaForSchemaNS(baseType.getNamespace())) { baseType = baseType.getBaseType(); if (!typeHierarchySet.add(baseType)) { return UnresolvedType.instance(); } } return baseType instanceof ISimpleType && EmfXsdUtils.isSchemaForSchemaNS(baseType.getNamespace()) ? (ISimpleType) baseType : UnresolvedType.instance(); } /** * Returns the all the components that are of type objectType * * @param <T> * - ? extends {@link XSDConcreteComponent} * @param components * - collection of input components * @param objectType * - type of objects to be returned * @return */ @SuppressWarnings("unchecked") public static final <T extends XSDSchemaContent> Collection<T> filterComponents( final Collection<? extends XSDSchemaContent> components, final Class<T> objectType) { Nil.checkNil(components, "components"); //$NON-NLS-1$ Nil.checkNil(objectType, "objectType"); //$NON-NLS-1$ final Collection<T> result = new HashSet<T>(1); for (final XSDConcreteComponent component : components) { if (objectType.isInstance(component)) result.add((T) component); } return result; } /** * Checks if the type is primitive or not * * @param type * - {@link XSDTypeDefinition} * @return <code>true</code> - if type is primitive <BR> * <code>false</code> - if its not primitive type or null * @pre type != null */ public static final boolean isPrimitiveType(final XSDTypeDefinition type) { Nil.checkNil(type, "type"); //$NON-NLS-1$ if (XSDConstants.isURType(type) || (XSDConstants.isSchemaForSchemaNamespace(type.getTargetNamespace()) && _schemaTypes.contains(type.getName()))) return true; return false; } /** * Checks if the type is primitive or not * * @param namespace * @param name * <code>true</code> if type is primitive <code>false</code> if * type is not primitive */ public static final boolean isPrimitiveType(final String namespace, final String name) { Nil.checkNil(namespace, "name"); //$NON-NLS-1$ Nil.checkNil(namespace, "namespace"); //$NON-NLS-1$ if (isURType(namespace, name) || (XSDConstants.isSchemaForSchemaNamespace(namespace) && _schemaTypes.contains(name))) return true; return false; } /** * 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 namespace * @param name * @return <code>true</code> if type is URType <code>false</code> if type is * not URType */ public static boolean isURType(final String namespace, final String name) { Nil.checkNil(namespace, "name"); //$NON-NLS-1$ Nil.checkNil(namespace, "namespace"); //$NON-NLS-1$ return XSDConstants.isSchemaForSchemaNamespace(namespace) && ("anyType".equals(name) || "anySimpleType".equals(name)); //$NON-NLS-1$ //$NON-NLS-2$ } /** * Returns the Schema for Schema Namespace * * @return */ public static final String getSchemaForSchemaNS() { return XSDConstants.SCHEMA_FOR_SCHEMA_URI_2001; } /** * Checks if the passed namespace if Schema for Schema Namespace * * @param nameSpace * @return <code>true</code> - input string is schema for schema namespace <BR> * <code>false</code> - input string is not schema for schema * namespace or <code>null</code> */ public static final boolean isSchemaForSchemaNS(final String nameSpace) { return nameSpace == null ? false : XSDConstants.isSchemaForSchemaNamespace(nameSpace); } /** * Returns EMF Model for Schema for Schema Namespace * * @return {@link XSDSchema} */ public static XSDSchema getSchemaForSchema() { if (null == _schemaForSchema) { synchronized (EmfXsdUtils.class) { if (null != _schemaForSchema) return _schemaForSchema; final XSDSchema xsdSchema = getXSDFactory().createXSDSchema(); xsdSchema.setTargetNamespace(EXAMPLE_SCHEMA_NS); xsdSchema.setElementFormDefault(XSDForm.QUALIFIED_LITERAL); xsdSchema.setAttributeFormDefault(XSDForm.QUALIFIED_LITERAL); xsdSchema.setSchemaForSchemaQNamePrefix(XSD_PREFIX); final Map<String, String> qNamePrefixToNamespaceMap = xsdSchema.getQNamePrefixToNamespaceMap(); qNamePrefixToNamespaceMap.put(TNS_PREFIX, xsdSchema.getTargetNamespace()); qNamePrefixToNamespaceMap.put(xsdSchema.getSchemaForSchemaQNamePrefix(), EmfXsdUtils.getSchemaForSchemaNS()); final XSDSchema schemaForSchema = xsdSchema.getSchemaForSchema(); if (null != schemaForSchema) _schemaForSchema = schemaForSchema; } } return _schemaForSchema; } /** * Returns a respt. {@link XSDSchema} model object for a given XSD * {@link IFile} * * @param file * @return */ /* GFB-POC Modified to take uri */ public static final XSDSchema resolveSchema(final java.net.URI uri) { final ResourceSet resourceSet = new ResourceSetImpl(); final Resource resource = resourceSet.getResource(URI.createURI(uri.toString()), true); if (resource instanceof XSDResourceImpl) { final XSDResourceImpl xsdr = (XSDResourceImpl) resource; return xsdr.getSchema(); } return null; } /** * Determine if the supplied name is a valid XML NCName. * * @param name * the string being checked * @return true if the supplied name is indeed a valid XML NCName, or false * otherwise */ public static boolean isValidNCName(final String name) { if (name == null || name.length() == 0) return false; final CharacterIterator iter = new StringCharacterIterator(name); char c = iter.first(); if (!XMLTypeUtil.isNCNameStart(c)) return false; while (c != CharacterIterator.DONE) { if (!XMLTypeUtil.isNCNamePart(c)) return false; c = iter.next(); } return true; } /** * Determine if the supplied name is a valid URI. * * @param namespace * the string being checked * @return true if the supplied name is indeed a valid URI, or false * otherwise */ public static boolean isValidURI(final String namespace) { if (namespace == null || namespace.length() == 0) return false; try { new java.net.URI(namespace); } catch (final URISyntaxException e) { return false; } return true; } public static final XSDAnnotation createXSDAnnotation() { final XSDAnnotation annotation = getXSDFactory().createXSDAnnotation(); return annotation; } /** * Creates a new clone for given component and ensures that the * {@link XSDAnnotation} objects and the form values for the local * {@link XSDElementDeclaration} and {@link XSDAttributeGroupDefinition} are * copied as well. <BR> * <BR> * This is a workaround until the issue reported at below locations gets * fixed - <BR> * <a href="http://www.eclipse.org/newsportal/article.php?id=2288&group=eclipse.technology.xsd#2288" * > http://www.eclipse.org/newsportal/article.php?id=2288&group=eclipse. * technology.xsd#2288</a><BR> * <a href="http://www.eclipse.org/newsportal/article.php?id=2218&group=eclipse.technology.xsd#2218" * > http://www.eclipse.org/newsportal/article.php?id=2218&group=eclipse. * technology.xsd#2218</a><BR> * * @param <T> * @param source * @param targetSchema * @return * @see XSDConcreteComponent#cloneConcreteComponent(boolean, boolean) */ public static <T extends XSDNamedComponent> T cloneWithAnnotation(final T source, final XSDSchema targetSchema) { return cloneWithAnnotation(source, targetSchema, -1); } /** * * @param <T> * @param source * @param targetSchema * @param index * @return */ public static <T extends XSDNamedComponent> T cloneWithAnnotation(final T source, final XSDSchema targetSchema, final int index) { T result = null; if (null != source && source instanceof XSDElementDeclaration) { result = createClone(source); if (index == -1) targetSchema.getContents().add((XSDSchemaContent) result); else targetSchema.getContents().add(index, (XSDSchemaContent) result); visitElementDeclaration((XSDElementDeclaration) source, (XSDElementDeclaration) result, targetSchema); } else if (null != source && source instanceof XSDTypeDefinition) { result = createClone(source); if (index == -1) targetSchema.getContents().add((XSDSchemaContent) result); else targetSchema.getContents().add(index, (XSDSchemaContent) result); visitTypeDefinition((XSDTypeDefinition) source, (XSDTypeDefinition) result, targetSchema); } else if (null != source && source instanceof XSDAttributeDeclaration) { result = createClone(source); if (index == -1) targetSchema.getContents().add((XSDSchemaContent) result); else targetSchema.getContents().add(index, (XSDSchemaContent) result); visitAttributeDeclaration((XSDAttributeDeclaration) source, (XSDAttributeDeclaration) result, targetSchema); } else if (null != source && source instanceof XSDAttributeGroupDefinition) { result = createClone(source); if (index == -1) targetSchema.getContents().add((XSDSchemaContent) result); else targetSchema.getContents().add(index, (XSDSchemaContent) result); visitAttributeGroupDefinition((XSDAttributeGroupDefinition) source, (XSDAttributeGroupDefinition) result, targetSchema); } else if (null != source && source instanceof XSDModelGroupDefinition) { result = createClone(source); if (index == -1) targetSchema.getContents().add((XSDSchemaContent) result); else targetSchema.getContents().add(index, (XSDSchemaContent) result); visitModelGroupDefinition((XSDModelGroupDefinition) source, (XSDModelGroupDefinition) result, targetSchema); } return result; } /** * Update all components from XSD model, which refers searchForComponent. * * @param baseComponent * where referencer will be searched for. This is used to be * XSDSchema, or Definition * @param searchForComponent * any XSD component */ public static void updateModelReferencers(final EObject baseComponent, final XSDConcreteComponent searchForComponent) { // update base component before searching for referencers if (baseComponent instanceof Definition) { final Element element = ((Definition) baseComponent).getElement(); ((Definition) baseComponent).elementChanged(element); } else if (baseComponent instanceof XSDSchema) { final Element element = ((XSDSchema) baseComponent).getElement(); ((XSDSchema) baseComponent).elementChanged(element); } final EObjectCondition refCondition = new EObjectReferencerCondition(searchForComponent); final IQueryResult result = new SELECT(new FROM(baseComponent), new WHERE(refCondition)).execute(); for (final Object next : result) { // These elements are expected to have inner elements which also // points to searchForComponent. So we skip the root ones, and will // update the inner ones - if such. if (next instanceof XSDSchema || next instanceof Definition) { continue; } // XSD API if (next instanceof XSDConcreteComponent) { final XSDConcreteComponent eObject = (XSDConcreteComponent) next; final Element element = eObject.getElement(); if (element != null && eObject != null && eObject.eResource() != null) { eObject.elementChanged(element); } } // WSDL API else if (next instanceof WSDLElement) { final WSDLElement eObject = (WSDLElement) next; final Element element = eObject.getElement(); if (element != null && eObject != null && eObject.eResource() != null) { eObject.elementChanged(element); } } } } @SuppressWarnings("unchecked") private static <T extends XSDNamedComponent> T createClone(final T object) { return (T) object.cloneConcreteComponent(true, false); } private static void visitElementDeclaration(final XSDElementDeclaration source, final XSDElementDeclaration target, final XSDSchema schema) { final XSDAnnotation annotation = source.getAnnotation(); if (null != annotation) { copyAnnotations(annotation, target.getAnnotation(), schema.getDocument()); } // process type definition if exists final XSDTypeDefinition typeDefinition = source.getAnonymousTypeDefinition(); if (null != typeDefinition) { visitTypeDefinition(typeDefinition, target.getAnonymousTypeDefinition(), schema); } visitIdentityConstraint(source.getIdentityConstraintDefinitions(), target.getIdentityConstraintDefinitions(), schema); if (source.isGlobal()) return; final XSDSchema sourceSchema = source.getSchema(); if (null == sourceSchema) throw new RuntimeException("Schema for source component is null"); //$NON-NLS-1$ XSDForm sourceForm = sourceSchema.isSetElementFormDefault() ? sourceSchema.getElementFormDefault() : null; if (source.isSetForm()) sourceForm = source.getForm(); final XSDForm targetForm = schema.isSetElementFormDefault() ? schema.getElementFormDefault() : null; if ((XSDForm.QUALIFIED_LITERAL == sourceForm && XSDForm.QUALIFIED_LITERAL != targetForm) || (XSDForm.QUALIFIED_LITERAL == targetForm && XSDForm.QUALIFIED_LITERAL != sourceForm)) { target.setForm(null == sourceForm ? XSDForm.UNQUALIFIED_LITERAL : sourceForm); } } private static void visitTypeDefinition(final XSDTypeDefinition srcType, final XSDTypeDefinition targetType, final XSDSchema schema) { if (srcType instanceof XSDSimpleTypeDefinition) { Assert.isTrue(targetType instanceof XSDSimpleTypeDefinition); visitSimpleTypeDefinition((XSDSimpleTypeDefinition) srcType, (XSDSimpleTypeDefinition) targetType, schema); } else { Assert.isTrue(targetType instanceof XSDComplexTypeDefinition); visitComplexTypeDefinition((XSDComplexTypeDefinition) srcType, (XSDComplexTypeDefinition) targetType, schema); } } private static void visitSimpleTypeDefinition(final XSDSimpleTypeDefinition srcType, final XSDSimpleTypeDefinition targetType, final XSDSchema schema) { final XSDAnnotation annotation = srcType.getAnnotation(); if (null != annotation) { copyAnnotations(annotation, targetType.getAnnotation(), schema.getDocument()); } final XSDAnnotation derivationAnnotation = srcType.getDerivationAnnotation(); if (null != derivationAnnotation) { copyAnnotations(derivationAnnotation, targetType.getDerivationAnnotation(), schema.getDocument()); } final XSDSimpleTypeDefinition baseType = srcType.getBaseTypeDefinition(); if (null == baseType.getName()) { visitSimpleTypeDefinition(baseType, targetType.getBaseTypeDefinition(), schema); } } private static void visitComplexTypeDefinition(final XSDComplexTypeDefinition srcType, final XSDComplexTypeDefinition targetType, final XSDSchema schema) { final XSDAnnotation annotation = srcType.getAnnotation(); if (null != annotation) { copyAnnotations(annotation, targetType.getAnnotation(), schema.getDocument()); } final XSDAnnotation derivationAnnotation = srcType.getDerivationAnnotation(); if (null != derivationAnnotation) { copyAnnotations(derivationAnnotation, targetType.getDerivationAnnotation(), schema.getDocument()); } final XSDAnnotation contentAnnotation = srcType.getContentAnnotation(); if (null != contentAnnotation) { copyAnnotations(contentAnnotation, targetType.getContentAnnotation(), schema.getDocument()); } final XSDTypeDefinition srcbaseType = srcType.getBaseType(); final XSDTypeDefinition targetbaseType = srcType.getBaseType(); if (null == srcbaseType.getName()) visitTypeDefinition(srcbaseType, targetbaseType, schema); // process content final XSDComplexTypeContent srcContent = srcType.getContent(); final XSDComplexTypeContent targetContent = targetType.getContent(); if (srcContent != null) { if (srcContent instanceof XSDParticle) { final XSDParticle srcParticle = (XSDParticle) srcContent; final XSDParticle targetParticle = (XSDParticle) targetContent; visitParticle(srcParticle, targetParticle, schema); } else if (srcContent instanceof XSDSimpleTypeDefinition) { visitSimpleTypeDefinition((XSDSimpleTypeDefinition) srcContent, (XSDSimpleTypeDefinition) targetContent, schema); } } // process attribute group content visitAttributeGroupContent(srcType.getAttributeContents(), targetType.getAttributeContents(), schema); } private static void visitAttributeDeclaration(final XSDAttributeDeclaration source, final XSDAttributeDeclaration target, final XSDSchema targetSchema) { final XSDAnnotation annotation = source.getAnnotation(); if (null != annotation) { copyAnnotations(annotation, target.getAnnotation(), targetSchema.getDocument()); } final XSDSimpleTypeDefinition typeDefinition = source.getAnonymousTypeDefinition(); if (null != typeDefinition) { visitSimpleTypeDefinition(typeDefinition, target.getAnonymousTypeDefinition(), targetSchema); } if (source.isGlobal()) return; final XSDSchema sourceSchema = source.getSchema(); if (null == sourceSchema) throw new RuntimeException("Schema for source component is null"); //$NON-NLS-1$ XSDForm sourceForm = sourceSchema.isSetAttributeFormDefault() ? sourceSchema.getAttributeFormDefault() : null; if (source.isSetForm()) sourceForm = source.getForm(); final XSDForm targetForm = targetSchema.isSetAttributeFormDefault() ? targetSchema.getAttributeFormDefault() : null; if ((XSDForm.QUALIFIED_LITERAL == sourceForm && XSDForm.QUALIFIED_LITERAL != targetForm) || (XSDForm.QUALIFIED_LITERAL == targetForm && XSDForm.QUALIFIED_LITERAL != sourceForm)) { target.setForm(null == sourceForm ? XSDForm.UNQUALIFIED_LITERAL : sourceForm); } } private static void visitAttributeGroupDefinition(final XSDAttributeGroupDefinition source, final XSDAttributeGroupDefinition target, final XSDSchema schema) { final XSDAnnotation annotation = source.getAnnotation(); if (null != annotation) { copyAnnotations(annotation, target.getAnnotation(), schema.getDocument()); } if (!source.isAttributeGroupDefinitionReference()) visitAttributeGroupContent(source.getContents(), target.getContents(), schema); } private static void visitModelGroupDefinition(final XSDModelGroupDefinition source, final XSDModelGroupDefinition target, final XSDSchema targetSchema) { final XSDAnnotation annotation = source.getAnnotation(); if (null != annotation) { copyAnnotations(annotation, target.getAnnotation(), targetSchema.getDocument()); } if (!source.isModelGroupDefinitionReference()) visitModelGroup(source.getModelGroup(), target.getModelGroup(), targetSchema); } private static void visitParticle(final XSDParticle srcParticle, final XSDParticle targetParticle, final XSDSchema schema) { final XSDParticleContent srcContent = srcParticle.getContent(); if (null != srcContent) { final XSDParticleContent targetContent = targetParticle.getContent(); if (srcContent instanceof XSDModelGroup) { visitModelGroup((XSDModelGroup) srcContent, (XSDModelGroup) targetContent, schema); } else if (srcContent instanceof XSDElementDeclaration) { visitElementDeclaration((XSDElementDeclaration) srcContent, (XSDElementDeclaration) targetContent, schema); } else if (srcContent instanceof XSDModelGroupDefinition) { visitModelGroupDefinition((XSDModelGroupDefinition) srcContent, (XSDModelGroupDefinition) targetContent, schema); } } } private static void visitModelGroup(final XSDModelGroup srcModelGroup, final XSDModelGroup targetModelGroup, final XSDSchema source) { final List<XSDParticle> srcParticles = (srcModelGroup).getContents(); final Iterator<XSDParticle> targetParticles = (targetModelGroup).getContents().iterator(); for (final XSDParticle srcParticle : srcParticles) { final XSDParticle targetParticle = targetParticles.next(); visitParticle(srcParticle, targetParticle, source); } } private static void visitAttributeGroupContent(final Collection<XSDAttributeGroupContent> source, final Collection<XSDAttributeGroupContent> target, final XSDSchema schema) { final Iterator<XSDAttributeGroupContent> targetAttributeContent = target.iterator(); XSDAttributeGroupDefinition targetAGContent = null; XSDAttributeGroupContent targetComp = null; for (final XSDAttributeGroupContent sourceComp : source) { targetComp = targetAttributeContent.next(); if (sourceComp instanceof XSDAttributeGroupDefinition) { targetAGContent = (XSDAttributeGroupDefinition) targetComp; visitAttributeGroupDefinition((XSDAttributeGroupDefinition) sourceComp, targetAGContent, schema); continue; } else if (sourceComp instanceof XSDAttributeUse) { visitAttributeDeclaration(((XSDAttributeUse) sourceComp).getContent(), ((XSDAttributeUse) targetComp) .getContent(), schema); } } } private static void visitIdentityConstraint(final EList<XSDIdentityConstraintDefinition> src, final EList<XSDIdentityConstraintDefinition> target, final XSDSchema schema) { final Iterator<XSDIdentityConstraintDefinition> targetIdentity = target.iterator(); for (final XSDIdentityConstraintDefinition identity : src) { final XSDAnnotation srcAnnotation = identity.getAnnotation(); if (null != srcAnnotation) { copyAnnotations(srcAnnotation, targetIdentity.next().getAnnotation(), schema.getDocument()); } } } public static void copyAnnotations(final XSDAnnotation annotation, final XSDAnnotation newAnnotation, final Document document) { if (newAnnotation == null || annotation == null) { return; } importDOMElements(annotation.getApplicationInformation(), newAnnotation.getElement(), document); importDOMElements(annotation.getUserInformation(), newAnnotation.getElement(), document); } private static void importDOMElements(final EList<Element> infos, final Element targetElement, final Document document) { if (document == null) { return; } for (final Element element : infos) { // internally these methods do casts to NodeImpl, so make a check // before using them if (element instanceof NodeImpl) { final Node importedNode = document.importNode(element, true); targetElement.appendChild(importedNode); } } } /** * Check whether eObject contains Element ref, or Attribute ref. */ public static boolean isReference(final IModelObject modelObject) { if (modelObject == null) { return false; } final EObject eObject = modelObject.getComponent(); if (eObject instanceof XSDParticle) { final XSDParticle particle = (XSDParticle) eObject; if (particle.getContent() instanceof XSDElementDeclaration) { final XSDElementDeclaration element = (XSDElementDeclaration) particle.getContent(); return element.isElementDeclarationReference(); } } else if (eObject instanceof XSDAttributeDeclaration) { final XSDAttributeDeclaration attribute = (XSDAttributeDeclaration) eObject; return attribute.isAttributeDeclarationReference(); } return false; } /** * Generates the name for a new xmlns:XXX attribute, to be added to the * given schema * * @param schema * for which the attribute name is generated * @return the newly generated name */ public static String generateSchemaNamespacePrefix(final XSDSchema schema) { for (int i = 0; i >= 0 && i < 10000; i++) { final String prefix = new StringBuilder(NAMESPACE_PREFIX_PREFIX).append(i).toString(); if (!schema.getQNamePrefixToNamespaceMap().containsKey(prefix)) { return prefix; } } return null; } public static boolean isSchemaForSchemaMissing(final IModelObject modelObject) { if (modelObject == null) { return false; } final EObject component = modelObject.getComponent(); if (component instanceof XSDConcreteComponent) { return isSchemaForSchemaMissing((XSDConcreteComponent) component); } return false; } public static boolean isSchemaForSchemaMissing(final XSDConcreteComponent component) { if (component == null) { return false; } final XSDSchemaImpl schema = (XSDSchemaImpl) (component).getSchema(); if (schema != null && schema.getSchemaForSchema() == null) { return true; } return false; } public static Collection<ISchema> getAllVisibleSchemas(ISchema schema) { final Collection<ISchema> result = new HashSet<ISchema>(schema.getAllReferredSchemas()); IModelObject parent = schema.getParent(); if (!(parent instanceof IDescription)) { return result; } for (ISchema currentSchema : ((IDescription) parent).getAllVisibleSchemas()) { if (currentSchema.getNamespace() == null || !currentSchema.getNamespace().equals(schema.getNamespace())) { continue; } result.add(currentSchema); } return result; } public static boolean isSchemaElementMissing(final ISchema schema) { if (schema == null) { return true; } final XSDSchema xsdSchema = schema.getComponent(); return isSchemaElementMissing(xsdSchema); } public static boolean isSchemaElementMissing(final XSDSchema schema) { return schema == null || schema.getElement() == null; } public static boolean hasXmlTag(final Document document) { if (document == null) { return false; } final Node firstChild = document.getFirstChild(); if (firstChild == null || Node.PROCESSING_INSTRUCTION_NODE != firstChild.getNodeType()) { return false; } return XML_TAG_NAME.equals(((ProcessingInstruction) firstChild).getTarget()); } public static ISchema getReferedSchema(final ISchema schema, final String namespace) { for (final ISchema refSchema : schema.getAllReferredSchemas()) { final boolean equalNS = refSchema.getNamespace() == null ? namespace == null : refSchema.getNamespace().equals( namespace); if (equalNS) { return refSchema; } } return null; } /** * Return the index in sourcePage for a given XSDConcreteComponent * * @param xsdComponent * must be NOT null * @return the start index for a given XSDConcreteComponent, or -1 otherwise */ public static int getIndexInSourcePage(final XSDConcreteComponent xsdComponent) { final Element element = xsdComponent.getElement(); return getIndexInSourcePage(element); } /** * Return the index in sourcePage for a given Element * * @param element * @return the start index for a given Element, or -1 otherwise */ public static int getIndexInSourcePage(final Element element) { IndexedRegion item = null; if (element instanceof IndexedRegion) { item = (IndexedRegion) element; return item.getStartOffset(); } return -1; } /** * Return true if the searched EMF object is a part of DataTypes UI tree, * otherwise false * * @param searchedObject * is an EMF object * @return boolean flag which value depends on the type of the * "searchObject" parameter */ public static boolean hasCorrespondingITreeNode(final EObject searchedObject) { if (searchedObject instanceof XSDSimpleTypeDefinition && ((XSDSimpleTypeDefinition) searchedObject).getName() != null) { return true; } if (searchedObject instanceof XSDComplexTypeDefinition && ((XSDComplexTypeDefinition) searchedObject).getName() != null) { return true; } if (searchedObject instanceof XSDAttributeDeclaration) { return true; } if (searchedObject instanceof XSDElementDeclaration) { return true; } if (searchedObject instanceof XSDSchemaImpl) { return true; } return false; } public static boolean isAnonymous(final XSDElementDeclaration elementDeclaration) { final XSDTypeDefinition anonymousTypeDefinition = elementDeclaration.getAnonymousTypeDefinition(); return isElementDeclarationTypeAnonymous(anonymousTypeDefinition); } private static boolean isElementDeclarationTypeAnonymous(final XSDTypeDefinition anonymousTypeDefinition) { if (anonymousTypeDefinition == null || anonymousTypeDefinition.getBaseType() == null) { return false; } final String baseTypeName = anonymousTypeDefinition.getBaseType().getName(); return "anyType".equals(baseTypeName) //$NON-NLS-1$ || anonymousTypeDefinition.getComplexType() instanceof XSDComplexTypeDefinition; } public static boolean isRestriction(final XSDSimpleTypeDefinition simpleType) { return simpleType != null && simpleType.getFacets() != null && !simpleType.getFacets().isEmpty(); } public static boolean isAnonymous(final XSDTypeDefinition typeDefinition) { final XSDTypeDefinition xsdTypeDefinition = typeDefinition; final XSDConcreteComponent container = xsdTypeDefinition.getContainer(); return null == xsdTypeDefinition.getName() && !(container instanceof XSDSchema); } }