/******************************************************************************* * 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.command.emf.xsd; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.xml.namespace.QName; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Status; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.ecore.EObject; import org.eclipse.wst.wsdl.Definition; import org.eclipse.wst.wsdl.Types; import org.eclipse.wst.wsdl.XSDSchemaExtensibilityElement; 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.XSDElementDeclaration; import org.eclipse.xsd.XSDFactory; import org.eclipse.xsd.XSDForm; import org.eclipse.xsd.XSDImport; import org.eclipse.xsd.XSDInclude; import org.eclipse.xsd.XSDModelGroup; import org.eclipse.xsd.XSDModelGroupDefinition; import org.eclipse.xsd.XSDNamedComponent; import org.eclipse.xsd.XSDParticle; import org.eclipse.xsd.XSDParticleContent; import org.eclipse.xsd.XSDSchema; import org.eclipse.xsd.XSDSchemaContent; import org.eclipse.xsd.XSDSchemaDirective; import org.eclipse.xsd.XSDSimpleTypeDefinition; import org.eclipse.xsd.XSDTypeDefinition; import org.eclipse.xsd.util.XSDConstants; import org.eclipse.wst.sse.sieditor.command.common.AbstractWSDLNotificationOperation; import org.eclipse.wst.sse.sieditor.core.common.CollectionTypeUtils; import org.eclipse.wst.sse.sieditor.core.common.Condition; import org.eclipse.wst.sse.sieditor.core.common.Logger; import org.eclipse.wst.sse.sieditor.model.Activator; import org.eclipse.wst.sse.sieditor.model.api.IModelObject; import org.eclipse.wst.sse.sieditor.model.api.IWsdlModelRoot; import org.eclipse.wst.sse.sieditor.model.i18n.Messages; import org.eclipse.wst.sse.sieditor.model.search.DocumentType; import org.eclipse.wst.sse.sieditor.model.utils.EmfWsdlUtils; import org.eclipse.wst.sse.sieditor.model.utils.EmfXsdUtils; import org.eclipse.wst.sse.sieditor.model.utils.ResourceUtils; import org.eclipse.wst.sse.sieditor.model.wsdl.impl.Description; import org.eclipse.wst.sse.sieditor.model.xsd.impl.AbstractType; /** * Command for making a type inline * * */ public class MakeTypeResolvableCommand extends AbstractWSDLNotificationOperation { private final AbstractType _sourceType; private AbstractType _clone; private final IModelObject _parent; // private ArrayList<ICommand> _commandStack; private Map<String, XSDSchema> _schemasUsed; public MakeTypeResolvableCommand(IWsdlModelRoot root, IModelObject modelObject, AbstractType typeToBeCopied) { super(root, modelObject, Messages.MakeTypeResolvableCommand_make_type_resolvable_command_label); this._sourceType = typeToBeCopied; this._parent = modelObject; } public boolean canExecute() { return !(null == getModelRoot() || null == _parent || null == _sourceType); } @SuppressWarnings("unchecked") private ArrayList<XSDSchema> getInlineSchemas() { boolean debug = Logger.isDebugEnabled(); if (debug) Logger.getDebugTrace().traceEntry(""); //$NON-NLS-1$ final Definition definition = ((Description) getModelRoot().getDescription()).getComponent(); final Types types = definition.getETypes(); if (null == types) return new ArrayList<XSDSchema>(); if (debug) Logger.getDebugTrace().traceExit(""); //$NON-NLS-1$ return new ArrayList<XSDSchema>(types.getSchemas()); } public org.eclipse.core.runtime.IStatus run(org.eclipse.core.runtime.IProgressMonitor monitor, org.eclipse.core.runtime.IAdaptable info) throws org.eclipse.core.commands.ExecutionException { boolean debug = Logger.isDebugEnabled(); if (debug) Logger.getDebugTrace().traceEntry(""); //$NON-NLS-1$ _schemasUsed = new HashMap<String, XSDSchema>(); final XSDNamedComponent component = _sourceType.getComponent(); // source in visit methods can be null only when call is from this // method if (component instanceof XSDElementDeclaration) { Logger.getDebugTrace().trace("", "Resolve Element " + _sourceType.getName()); //$NON-NLS-1$ //$NON-NLS-2$ visitElementDeclaration((XSDElementDeclaration) component, null); } else if (component instanceof XSDTypeDefinition) { if (debug) Logger.getDebugTrace().trace("", "Begin Type " + _sourceType.getName()); //$NON-NLS-1$ //$NON-NLS-2$ visitTypeDefinition((XSDTypeDefinition) component, null); } final Description description = (Description) getModelRoot().getDescription(); if (debug) Logger.getDebugTrace().trace("", "Finally Refresh Schemas for all the components that are copied or are created"); //$NON-NLS-1$ //$NON-NLS-2$ description.refreshSchemas(); if (debug) Logger.getDebugTrace().trace("", "Return the copied Type"); //$NON-NLS-1$ //$NON-NLS-2$ _clone = (AbstractType) description.resolveType(component); if (debug) Logger.getDebugTrace().traceExit(""); //$NON-NLS-1$ return null != _clone ? Status.OK_STATUS : new Status(IStatus.ERROR, Activator.PLUGIN_ID, MessageFormat.format(Messages.MakeTypeResolvableCommand_mesg_can_not_resolve_type_X, _sourceType.getName())); } public AbstractType getCopiedType() { boolean debug = Logger.isDebugEnabled(); if (debug) Logger.getDebugTrace().traceEntry(""); //$NON-NLS-1$ if (debug) Logger.getDebugTrace().traceExit(""); //$NON-NLS-1$ return _clone; } private void visitAttributeGroup(final XSDAttributeGroupDefinition attributeGroup, XSDSchema source) { boolean debug = Logger.isDebugEnabled(); if (debug) Logger.getDebugTrace().traceEntry(""); //$NON-NLS-1$ XSDSchema copiedTo; if (!attributeGroup.isAttributeGroupDefinitionReference()) { // check if attributeGroup already exists if (debug) Logger.getDebugTrace().trace("", "transversing Global AttributeGroup '" + attributeGroup.getName() + "'"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ final XSDAttributeGroupDefinition match = contains(new QName(attributeGroup.getTargetNamespace(), attributeGroup .getName()), XSDAttributeGroupDefinition.class); if (null != match) { if (debug) Logger.getDebugTrace().trace("", "AttributeGroup '" + attributeGroup.getName() + "' already visible"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ // return if source is null if (null == source) { if (debug) Logger.getDebugTrace().traceExit(""); //$NON-NLS-1$ return; } else { // ensure import and return, no need to transverse // attributeGroup here ensureImport(source, attributeGroup.getTargetNamespace(), null); if (debug) Logger.getDebugTrace().traceExit(""); //$NON-NLS-1$ return; } } else { if (ensureImport(source, attributeGroup.getTargetNamespace(), attributeGroup)) { if (debug) Logger.getDebugTrace().traceExit(""); //$NON-NLS-1$ return; } } // copy and create reference in source copiedTo = createClone(attributeGroup); if (null != source) ensureImport(source, attributeGroup.getTargetNamespace(), null); } else { // this is a local element so we need to add imports to // @localvar(source) copiedTo = source; } if (debug) Logger.getDebugTrace().trace("", "Visit Referred components"); //$NON-NLS-1$ //$NON-NLS-2$ if (attributeGroup.isAttributeGroupDefinitionReference()) { final XSDAttributeGroupDefinition resolvedAttributeGroupDefinition = attributeGroup .getResolvedAttributeGroupDefinition(); if (!(null == resolvedAttributeGroupDefinition || isSynthetic(resolvedAttributeGroupDefinition))) { visitAttributeGroup(resolvedAttributeGroupDefinition, copiedTo); } } else { visitAttributeGroupContent(attributeGroup.getContents(), copiedTo); } if (debug) Logger.getDebugTrace().traceExit(""); //$NON-NLS-1$ } private void visitAttributeDeclaration(final XSDAttributeDeclaration attribute, XSDSchema source) { boolean debug = Logger.isDebugEnabled(); if (debug) Logger.getDebugTrace().traceEntry(""); //$NON-NLS-1$ XSDSchema copiedTo; if (attribute.isGlobal()) { if (debug) Logger.getDebugTrace().trace("", "transversing Global Attribute '" + attribute.getName() + "'"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ // check if element already exists final XSDAttributeDeclaration match = contains(new QName(attribute.getTargetNamespace(), attribute.getName()), XSDAttributeDeclaration.class); if (null != match) { if (debug) Logger.getDebugTrace().trace("", "Attribute '" + attribute.getName() + "' already visible"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ // return if source is null if (null == source) { if (debug) Logger.getDebugTrace().traceExit(""); //$NON-NLS-1$ return; } else { // ensure import and return, no need to transverse type here ensureImport(source, attribute.getTargetNamespace(), null); if (debug) Logger.getDebugTrace().traceExit(""); //$NON-NLS-1$ return; } } else { if (ensureImport(source, attribute.getTargetNamespace(), attribute)) { if (debug) Logger.getDebugTrace().traceExit(""); //$NON-NLS-1$ return; } } // copy and create reference in source copiedTo = createClone(attribute); if (null != source) ensureImport(source, attribute.getTargetNamespace(), null); } else { // this is a local attribute so we need to add imports to // @localvar(source) copiedTo = source; } if (debug) Logger.getDebugTrace().trace("", "Visit Referred components"); //$NON-NLS-1$ //$NON-NLS-2$ XSDSimpleTypeDefinition typeDefinition = attribute.getAnonymousTypeDefinition(); if (null == typeDefinition) typeDefinition = attribute.getTypeDefinition(); if (!(null == typeDefinition || isSynthetic(typeDefinition))) visitTypeDefinition(typeDefinition, copiedTo); // process referred element declaration if exists if (attribute.isAttributeDeclarationReference()) { final XSDAttributeDeclaration resolvedAttribute = attribute.getResolvedAttributeDeclaration(); if (!(null == resolvedAttribute || isSynthetic(resolvedAttribute))) visitAttributeDeclaration(resolvedAttribute, copiedTo); } if (debug) Logger.getDebugTrace().traceExit(""); //$NON-NLS-1$ } private void visitElementDeclaration(final XSDElementDeclaration element, XSDSchema source) { boolean debug = Logger.isDebugEnabled(); if (debug) Logger.getDebugTrace().traceEntry(""); //$NON-NLS-1$ XSDSchema copiedTo; if (element.isGlobal()) { if (debug) Logger.getDebugTrace().trace("", "transversing Global Element Declaration'" + element.getName() + "'"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ // check if element already exists final XSDElementDeclaration match = contains(new QName(element.getTargetNamespace(), element.getName()), XSDElementDeclaration.class); if (null != match) { if (debug) Logger.getDebugTrace().trace("", "Element '" + element.getName() + "' already visible"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ // return if source is null if (null == source) { if (debug) Logger.getDebugTrace().traceExit(""); //$NON-NLS-1$ return; } else { // ensure import and return, no need to transverse type here ensureImport(source, element.getTargetNamespace(), null); if (debug) Logger.getDebugTrace().traceExit(""); //$NON-NLS-1$ return; } } else { if (ensureImport(source, element.getTargetNamespace(), element)) { if (debug) Logger.getDebugTrace().traceExit(""); //$NON-NLS-1$ return; } } // copy and create reference in source copiedTo = createClone(element); if (null != source) ensureImport(source, element.getTargetNamespace(), null); } else { // this is a local element so we need to add imports to // @localvar(source) copiedTo = source; } if (debug) Logger.getDebugTrace().trace("", "Visit Referred components"); //$NON-NLS-1$ //$NON-NLS-2$ // process type definition if exists XSDTypeDefinition typeDefinition = element.getAnonymousTypeDefinition(); if (null == typeDefinition) typeDefinition = element.getTypeDefinition(); if (!(null == typeDefinition || isSynthetic(typeDefinition))) visitTypeDefinition(typeDefinition, copiedTo); // process referred element declaration if exists if (element.isElementDeclarationReference()) { final XSDElementDeclaration resolvedElementDeclaration = element.getResolvedElementDeclaration(); if (!(null == resolvedElementDeclaration || isSynthetic(resolvedElementDeclaration))) visitElementDeclaration(resolvedElementDeclaration, copiedTo); } if (debug) Logger.getDebugTrace().traceExit(""); //$NON-NLS-1$ } private void visitModelGroupDefinition(final XSDModelGroupDefinition modelGroupDefinition, XSDSchema source) { boolean debug = Logger.isDebugEnabled(); if (debug) Logger.getDebugTrace().traceEntry(""); //$NON-NLS-1$ XSDSchema copiedTo; if (!modelGroupDefinition.isModelGroupDefinitionReference()) { if (debug) Logger.getDebugTrace().trace("", "transversing Global ModelGroup Definition'" + modelGroupDefinition.getName() + "'"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ // check if attributeGroup already exists final XSDModelGroupDefinition match = contains(new QName(modelGroupDefinition.getTargetNamespace(), modelGroupDefinition.getName()), XSDModelGroupDefinition.class); if (null != match) { if (debug) Logger.getDebugTrace().trace("", "ModelGroupDefinition '" + modelGroupDefinition.getName() + "' already visible"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ // return if source is null if (null == source) { if (debug) Logger.getDebugTrace().traceExit(""); //$NON-NLS-1$ return; } else { // ensure import and return, no need to transverse // attributeGroup here ensureImport(source, modelGroupDefinition.getTargetNamespace(), null); if (debug) Logger.getDebugTrace().traceExit(""); //$NON-NLS-1$ return; } } else { if (ensureImport(source, modelGroupDefinition.getTargetNamespace(), modelGroupDefinition)) { if (debug) Logger.getDebugTrace().traceExit(""); //$NON-NLS-1$ return; } } // copy and create reference in source copiedTo = createClone(modelGroupDefinition); if (null != source) ensureImport(source, modelGroupDefinition.getTargetNamespace(), null); } else { // this is a local element so we need to add imports to // @localvar(source) copiedTo = source; } if (debug) Logger.getDebugTrace().trace("", "Visit Referred components"); //$NON-NLS-1$ //$NON-NLS-2$ if (modelGroupDefinition.isModelGroupDefinitionReference()) { final XSDModelGroupDefinition resolvedModelGroupDefinition = modelGroupDefinition.getResolvedModelGroupDefinition(); if (!(null == resolvedModelGroupDefinition.eContainer() || isSynthetic(resolvedModelGroupDefinition))) { visitModelGroupDefinition(resolvedModelGroupDefinition, copiedTo); } } else { final XSDModelGroup content = modelGroupDefinition.getModelGroup(); if (null != content) visitModelGroup(content, copiedTo); } if (debug) Logger.getDebugTrace().traceExit(""); //$NON-NLS-1$ } private void visitTypeDefinition(final XSDTypeDefinition type, XSDSchema source) { boolean debug = Logger.isDebugEnabled(); if (debug) Logger.getDebugTrace().traceEntry(""); //$NON-NLS-1$ if (null != type) { if (XSDConstants.isSchemaForSchemaNamespace(type.getTargetNamespace())) { if (debug) Logger.getDebugTrace().trace("", "Primitive Type - " + type.getName()); //$NON-NLS-1$ //$NON-NLS-2$ if (debug) Logger.getDebugTrace().traceExit(""); //$NON-NLS-1$ return; } } if (type instanceof XSDSimpleTypeDefinition) { visitSimpleTypeDefinition((XSDSimpleTypeDefinition) type, source); } else { visitComplexTypeDefinition((XSDComplexTypeDefinition) type, source); } if (debug) Logger.getDebugTrace().traceExit(""); //$NON-NLS-1$ } private void visitSimpleTypeDefinition(final XSDSimpleTypeDefinition simpleType, XSDSchema source) { boolean debug = Logger.isDebugEnabled(); if (debug) Logger.getDebugTrace().traceEntry(""); //$NON-NLS-1$ // holds the schema where the clone is created so that imports can be // added to it for // referred components XSDSchema copiedTo; // if global complexType if (null != simpleType.getName()) { if (debug) Logger.getDebugTrace().trace("", "transversing Global SimpleTypeDefinition'" + simpleType.getName() + "'"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ // check if type already exists final XSDTypeDefinition match = contains(new QName(simpleType.getTargetNamespace(), simpleType.getName()), XSDTypeDefinition.class); if (null != match) { if (debug) Logger.getDebugTrace().trace("", "SimpleType '" + simpleType.getName() + "' already visible"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ // return if source is null if (null == source) { if (debug) Logger.getDebugTrace().traceExit(""); //$NON-NLS-1$ return; } else { // ensure import and return, no need to transverse type here ensureImport(source, simpleType.getTargetNamespace(), null); if (debug) Logger.getDebugTrace().traceExit(""); //$NON-NLS-1$ return; } } else { if (ensureImport(source, simpleType.getTargetNamespace(), simpleType)) { if (debug) Logger.getDebugTrace().traceExit(""); //$NON-NLS-1$ return; } } // copy and create reference in @localvar(source) copiedTo = createClone(simpleType); if (null != source) ensureImport(source, simpleType.getTargetNamespace(), null); } else { // this is a anonymous type so we need to add imports to // @localvar(source) copiedTo = source; } if (debug) Logger.getDebugTrace().trace("", "Visit Referred components"); //$NON-NLS-1$ //$NON-NLS-2$ final XSDTypeDefinition baseType = simpleType.getBaseType(); if (null != baseType && !isSynthetic(baseType)) visitTypeDefinition(baseType, copiedTo); for (XSDSimpleTypeDefinition member : simpleType.getMemberTypeDefinitions()) { if (!isSynthetic(member)) visitTypeDefinition(member, copiedTo); } final XSDSimpleTypeDefinition itemType = simpleType.getItemTypeDefinition(); if (null != itemType && !isSynthetic(itemType)) visitTypeDefinition(itemType, copiedTo); if (debug) Logger.getDebugTrace().traceExit(""); //$NON-NLS-1$ } private void visitComplexTypeDefinition(final XSDComplexTypeDefinition complexType, XSDSchema source) { boolean debug = Logger.isDebugEnabled(); if (debug) Logger.getDebugTrace().traceEntry(""); //$NON-NLS-1$ // holds the schema where the clone is created so that imports can be // added to it for // referred components XSDSchema copiedTo; // if global complexType if (null != complexType.getName()) { if (debug) Logger.getDebugTrace().trace("", "transversing Global ComplexTypeDefinition'" + complexType.getName() + "'"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ // check if type already exists final XSDTypeDefinition match = contains(new QName(complexType.getTargetNamespace(), complexType.getName()), XSDTypeDefinition.class); if (null != match) { if (debug) Logger.getDebugTrace().trace("", "ComplexType '" + complexType.getName() + "' already visible"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ // return if source is null if (null == source) { if (debug) Logger.getDebugTrace().traceExit(""); //$NON-NLS-1$ return; } else { // ensure import and return, no need to transverse type here ensureImport(source, complexType.getTargetNamespace(), null); if (debug) Logger.getDebugTrace().traceExit(""); //$NON-NLS-1$ return; } } else { if (ensureImport(source, complexType.getTargetNamespace(), complexType)) { if (debug) Logger.getDebugTrace().traceExit(""); //$NON-NLS-1$ return; } } // copy and create reference in @localvar(source) copiedTo = createClone(complexType); if (null != source) ensureImport(source, complexType.getTargetNamespace(), null); } else { // this is a anonymous type so we need to add imports to // @localvar(source) copiedTo = source; } // process content final XSDComplexTypeContent content = complexType.getContent(); if (content != null) { if (content instanceof XSDParticle) { final XSDParticle particle = (XSDParticle) content; visitParticle(particle, copiedTo); final XSDTypeDefinition baseType = complexType.getBaseType(); if (!isSynthetic(baseType)) visitTypeDefinition(baseType, copiedTo); } else { visitSimpleTypeDefinition((XSDSimpleTypeDefinition) content, copiedTo); final XSDTypeDefinition baseType = complexType.getBaseType(); if (!(null == baseType || isSynthetic(baseType))) visitTypeDefinition(baseType, copiedTo); } } final List<XSDAttributeGroupContent> attributeContents = complexType.getAttributeContents(); visitAttributeGroupContent(attributeContents, copiedTo); if (debug) Logger.getDebugTrace().traceExit(""); //$NON-NLS-1$ } private void visitParticle(final XSDParticle particle, final XSDSchema source) { boolean debug = Logger.isDebugEnabled(); if (debug) Logger.getDebugTrace().traceEntry(""); //$NON-NLS-1$ final XSDParticleContent content = particle.getContent(); if (content instanceof XSDModelGroup) { visitModelGroup((XSDModelGroup) content, source); } else if (content instanceof XSDElementDeclaration) { visitElementDeclaration((XSDElementDeclaration) content, source); } else if (content instanceof XSDModelGroupDefinition) { visitModelGroupDefinition((XSDModelGroupDefinition) content, source); } if (debug) Logger.getDebugTrace().traceExit(""); //$NON-NLS-1$ } private void visitModelGroup(final XSDModelGroup modelGroup, final XSDSchema source) { boolean debug = Logger.isDebugEnabled(); if (debug) Logger.getDebugTrace().traceEntry(""); //$NON-NLS-1$ final List<XSDParticle> particles = ((XSDModelGroup) modelGroup).getContents(); for (XSDParticle particle : particles) { visitParticle(particle, source); } if (debug) Logger.getDebugTrace().traceExit(""); //$NON-NLS-1$ } private void visitAttributeGroupContent(Collection<XSDAttributeGroupContent> attributeContents, XSDSchema source) { boolean debug = Logger.isDebugEnabled(); if (debug) Logger.getDebugTrace().traceEntry(""); //$NON-NLS-1$ for (final XSDAttributeGroupContent attributeGroupContent : attributeContents) { if (attributeGroupContent instanceof XSDAttributeGroupDefinition) { visitAttributeGroup((XSDAttributeGroupDefinition) attributeGroupContent, source); continue; } final XSDAttributeUse attributeUse = (XSDAttributeUse) attributeGroupContent; final XSDAttributeDeclaration attributeDeclaration = attributeUse.getContent(); if (null != attributeDeclaration) { visitAttributeDeclaration(attributeDeclaration, source); } } if (debug) Logger.getDebugTrace().traceExit(""); //$NON-NLS-1$ } /** * Creates a clone of given component in given schema and returns the clone * * @param <T> * @param schema * @param component * @return */ private XSDSchema createClone(XSDNamedComponent component) { boolean debug = Logger.isDebugEnabled(); if (debug) Logger.getDebugTrace().traceEntry(""); //$NON-NLS-1$ // use this code to also clone annotations but be careful that schema is // updated final XSDSchema schema = ensureSchema(component.getTargetNamespace()); /* * final Element element = component.getElement(); * * if (element != null) { final Node newComponent = * schema.getDocument().importNode(element, true); * schema.getElement().appendChild(newComponent); * schema.getDocument().normalizeDocument(); } schema.update(); * schema.getDocument().normalizeDocument(); */ /* * This doesnt clone the annotations of the component final * XSDConcreteComponent clone = component.cloneConcreteComponent(true, * false); * * if(clone instanceof XSDSchemaContent) * schema.getContents().add((XSDSchemaContent) clone); */ // This utility copies the component ensuring that the annotations are // also copied if (debug) Logger.getDebugTrace().trace("", "Copying " + component.eClass().getName() + " '" + component.getName() + "'"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ EmfXsdUtils.cloneWithAnnotation(component, schema); if (debug) Logger.getDebugTrace().traceExit(""); //$NON-NLS-1$ return schema; } private <T extends XSDNamedComponent> T contains(final QName qName, final Class<T> metaClass) { boolean debug = Logger.isDebugEnabled(); if (debug) Logger.getDebugTrace().traceEntry(""); //$NON-NLS-1$ final String namespace = qName.getNamespaceURI(); final String name = qName.getLocalPart(); // Get schemas with same namespace final Collection<XSDSchema> schemas = CollectionTypeUtils.findAll(getInlineSchemas(), new Condition<XSDSchema>() { public boolean isSatisfied(XSDSchema in) { return namespace.equals(in.getTargetNamespace()); } }); // Check is type is visible in contained schemas or included schemas in // contained schemas T result = null; for (XSDSchema schema : schemas) { result = contains(schema, name, new ArrayList<String>(), metaClass); if (null != result) return result; } if (debug) Logger.getDebugTrace().traceExit(""); //$NON-NLS-1$ return result; } @SuppressWarnings("unchecked") private <T extends XSDNamedComponent> T contains(XSDSchema schema, String name, Collection<String> locations, final Class<T> metaClass) { boolean debug = Logger.isDebugEnabled(); if (debug) Logger.getDebugTrace().traceEntry(""); //$NON-NLS-1$ final EList<XSDSchemaContent> contents = schema.getContents(); final ArrayList<XSDInclude> includes = new ArrayList<XSDInclude>(); for (XSDSchemaContent schemaContent : contents) { if (metaClass.isInstance(schemaContent)) { if (name.equals(((XSDNamedComponent) schemaContent).getName())) { if (debug) Logger.getDebugTrace().trace("", "Found " + metaClass.getSimpleName() + " '" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + name + "' in inline schema '" + schema.getTargetNamespace() + "'"); //$NON-NLS-1$ //$NON-NLS-2$ return (T) schemaContent; } } } T result = null; for (XSDInclude include : includes) { final XSDSchema includedSchema = include.getResolvedSchema(); if (null != includedSchema && !locations.contains(includedSchema.getSchemaLocation())) { locations.add(includedSchema.getSchemaLocation()); result = contains(includedSchema, name, locations, metaClass); if (null != result) { if (debug) Logger.getDebugTrace().trace("", "Found " + metaClass.getSimpleName() + " '" //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + name + "' in included schema '" //$NON-NLS-1$ + includedSchema.getSchemaLocation() + "'"); //$NON-NLS-1$ return result; } } } if (debug) Logger.getDebugTrace().traceExit(""); //$NON-NLS-1$ return result; } private boolean ensureImport(final XSDSchema schema, final String nameSpace, final XSDNamedComponent component) { boolean debug = Logger.isDebugEnabled(); if (debug) Logger.getDebugTrace().traceEntry(""); //$NON-NLS-1$ if (null == component) { if (debug) Logger.getDebugTrace().trace("", "Component exists in the same document"); //$NON-NLS-1$ //$NON-NLS-2$ // for cloned components or visible components using includes if (schema.getTargetNamespace().equals(nameSpace)) { if (debug) Logger.getDebugTrace().trace("", "Schema and component have same namespace so no include is needed"); //$NON-NLS-1$ //$NON-NLS-2$ if (debug) Logger.getDebugTrace().traceExit(""); //$NON-NLS-1$ return false; } final Collection<XSDImport> imports = EmfXsdUtils.filterComponents(schema.getContents(), XSDImport.class); for (XSDImport importObj : imports) { if (nameSpace.equals(importObj.getNamespace()) && null == importObj.getSchemaLocation()) { // Import already exists if (debug) Logger.getDebugTrace().trace("", "Import already exists"); //$NON-NLS-1$ //$NON-NLS-2$ if (debug) Logger.getDebugTrace().traceExit(""); //$NON-NLS-1$ return true; } } // we need to add an import if (debug) Logger.getDebugTrace().trace("", "Adding Import for namespace '" + nameSpace + "'"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ final XSDImport xsdImport = XSDFactory.eINSTANCE.createXSDImport(); xsdImport.setNamespace(nameSpace); schema.getContents().add(0, xsdImport); if (debug) Logger.getDebugTrace().traceExit(""); //$NON-NLS-1$ return true; } else { // for components in schemas final EObject parent = component.eContainer(); if (null != parent && parent instanceof XSDSchema) { final String location = ((XSDSchema) parent).getSchemaLocation(); final IFile file = ResourceUtils.getWorkSpaceFile(new Path(location)); if (null != file && ResourceUtils.checkContentType(file, DocumentType.XSD_SHEMA.getResourceID())) { if (debug) Logger.getDebugTrace().trace("", "Component exists in the external Schema document"); //$NON-NLS-1$ //$NON-NLS-2$ final Definition definition = ((Description) getModelRoot().getDescription()).getComponent(); final String schemaRelativePath = ResourceUtils.makeRelativeLocation(definition.getLocation(), file .getLocationURI()); XSDSchemaDirective directive = null; if (null == nameSpace || schema.getTargetNamespace().equals(nameSpace)) { final Collection<XSDInclude> includes = EmfXsdUtils.filterComponents(schema.getContents(), XSDInclude.class); for (XSDInclude include : includes) { if (null != schemaRelativePath && schemaRelativePath.equals(include.getSchemaLocation())) { // Include already exists if (debug) Logger.getDebugTrace().trace("", "Include already exists"); //$NON-NLS-1$ //$NON-NLS-2$ if (debug) Logger.getDebugTrace().traceExit(""); //$NON-NLS-1$ return true; } } if (debug) Logger.getDebugTrace().trace("", "Add Include"); //$NON-NLS-1$ //$NON-NLS-2$ directive = XSDFactory.eINSTANCE.createXSDInclude(); } else { final Collection<XSDImport> imports = EmfXsdUtils.filterComponents(schema.getContents(), XSDImport.class); for (XSDImport importObj : imports) { if (nameSpace.equals(importObj.getNamespace()) && (null != schemaRelativePath && schemaRelativePath.equals(importObj.getSchemaLocation()))) { // Import already exists if (debug) Logger.getDebugTrace().trace("", "Import already exists"); //$NON-NLS-1$ //$NON-NLS-2$ if (debug) Logger.getDebugTrace().traceExit(""); //$NON-NLS-1$ return true; } } if (debug) Logger.getDebugTrace().trace("", "Add Import"); //$NON-NLS-1$ //$NON-NLS-2$ directive = XSDFactory.eINSTANCE.createXSDImport(); ((XSDImport) directive).setNamespace(nameSpace); } directive.setSchemaLocation(schemaRelativePath); XSDSchema resolvedSchema = directive.getResolvedSchema(); if (null == resolvedSchema) { /* * GFB-POC Modified to take uri resolvedSchema = * EmfXsdUtils.resolveSchema(file); */ resolvedSchema = EmfXsdUtils.resolveSchema(file.getLocationURI()); if (null != resolvedSchema) { directive.setResolvedSchema(resolvedSchema); schema.getContents().add(0, directive); if (debug) Logger.getDebugTrace().traceExit(""); //$NON-NLS-1$ return true; } if (debug) Logger.getDebugTrace().trace("", "Could not resolve schema for the component"); //$NON-NLS-1$ //$NON-NLS-2$ } else { schema.getContents().add(0, directive); if (debug) Logger.getDebugTrace().traceExit(""); //$NON-NLS-1$ return true; } } } } if (debug) Logger.getDebugTrace().traceExit(""); //$NON-NLS-1$ return false; } @SuppressWarnings("unchecked") private XSDSchema ensureSchema(final String namespace) { boolean debug = Logger.isDebugEnabled(); if (debug) Logger.getDebugTrace().traceEntry(""); //$NON-NLS-1$ XSDSchema schema = _schemasUsed.get(namespace); if (null == schema) { final Collection<XSDSchema> schemas = CollectionTypeUtils.findAll(getInlineSchemas(), new Condition<XSDSchema>() { public boolean isSatisfied(XSDSchema in) { return namespace.equals(in.getTargetNamespace()); } }); if (schemas.size() > 0) { if (debug) Logger.getDebugTrace().trace("", "Schema for namespace '" + namespace + "' already exists"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ schema = schemas.iterator().next(); } else { if (debug) Logger.getDebugTrace().trace("", "Adding Schema for namespace '" + namespace + "'"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ schema = EmfXsdUtils.getXSDFactory().createXSDSchema(); schema.setElementFormDefault(XSDForm.UNQUALIFIED_LITERAL); schema.setAttributeFormDefault(XSDForm.UNQUALIFIED_LITERAL); schema.setSchemaForSchemaQNamePrefix(EmfXsdUtils.XSD_PREFIX); schema.setTargetNamespace(namespace); final Map<String, String> qNamePrefixToNamespaceMap = schema.getQNamePrefixToNamespaceMap(); qNamePrefixToNamespaceMap.put(schema.getSchemaForSchemaQNamePrefix(), EmfXsdUtils.getSchemaForSchemaNS()); final XSDSchemaExtensibilityElement schemaExtensibilityEntity = EmfWsdlUtils.getWSDLFactory() .createXSDSchemaExtensibilityElement(); schemaExtensibilityEntity.setSchema(schema); final Description description = (Description) getModelRoot().getDescription(); final Definition definition = description.getComponent(); schema.setSchemaLocation(definition.getDocumentBaseURI()); final String xmlnsPrefix = generateXmlnsPrefix(definition.getNamespaces(), qNamePrefixToNamespaceMap); qNamePrefixToNamespaceMap.put(xmlnsPrefix, namespace); Types types = definition.getETypes(); if (types == null) { types = EmfWsdlUtils.getWSDLFactory().createTypes(); definition.setTypes(types); } types.addExtensibilityElement(schemaExtensibilityEntity); schemaExtensibilityEntity.setEnclosingDefinition(definition); schema.updateElement(); schema.getDocument().normalizeDocument(); final String wsdlXmlnsPrefix = generateXmlnsPrefix(definition.getNamespaces(), qNamePrefixToNamespaceMap); definition.addNamespace(wsdlXmlnsPrefix, namespace); } _schemasUsed.put(namespace, schema); } else if (debug) Logger.getDebugTrace().trace("", "Schema for namespace '" + namespace + "' already exists"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ if (debug) Logger.getDebugTrace().traceExit(""); //$NON-NLS-1$ return schema; } private boolean isSynthetic(final XSDNamedComponent component) { boolean debug = Logger.isDebugEnabled(); if (debug) Logger.getDebugTrace().traceEntry(""); //$NON-NLS-1$ if (debug) Logger.getDebugTrace().traceExit(""); //$NON-NLS-1$ return null == component.eContainer(); } private static final String XMLNS_PREFIX_BASE = "imp"; //$NON-NLS-1$ private static String generateXmlnsPrefix(final Map<String, String> wsdlNamespacesMap, Map<String, String> xsdNamespaceMap) { boolean debug = Logger.isDebugEnabled(); if (debug) Logger.getDebugTrace().traceEntry(""); //$NON-NLS-1$ for (int i = 0; i < 10000; i++) { final String key = XMLNS_PREFIX_BASE + String.valueOf(i); if (wsdlNamespacesMap.containsKey(key) || xsdNamespaceMap.containsKey(key)) { continue; } return key; } if (debug) Logger.getDebugTrace().traceExit(""); //$NON-NLS-1$ throw new IllegalStateException("Cannot generate xmlns prefix"); //$NON-NLS-1$ } }