| /** |
| * Copyright (c) 2002-2006 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v2.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v20.html |
| * |
| * Contributors: |
| * IBM - Initial API and implementation |
| */ |
| package org.eclipse.xsd.ecore; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| import org.w3c.dom.Node; |
| |
| import org.eclipse.emf.ecore.EAttribute; |
| import org.eclipse.emf.ecore.EClass; |
| import org.eclipse.emf.ecore.EClassifier; |
| import org.eclipse.emf.ecore.EDataType; |
| import org.eclipse.emf.ecore.EEnum; |
| import org.eclipse.emf.ecore.EEnumLiteral; |
| import org.eclipse.emf.ecore.EModelElement; |
| import org.eclipse.emf.ecore.ENamedElement; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.EPackage; |
| import org.eclipse.emf.ecore.EReference; |
| import org.eclipse.emf.ecore.EStructuralFeature; |
| import org.eclipse.emf.ecore.util.EcoreUtil; |
| |
| import org.eclipse.xsd.XSDAnnotation; |
| import org.eclipse.xsd.XSDAttributeDeclaration; |
| import org.eclipse.xsd.XSDAttributeUse; |
| import org.eclipse.xsd.XSDAttributeUseCategory; |
| import org.eclipse.xsd.XSDComplexTypeDefinition; |
| import org.eclipse.xsd.XSDComponent; |
| import org.eclipse.xsd.XSDCompositor; |
| import org.eclipse.xsd.XSDConcreteComponent; |
| import org.eclipse.xsd.XSDConstraint; |
| import org.eclipse.xsd.XSDDerivationMethod; |
| import org.eclipse.xsd.XSDElementDeclaration; |
| import org.eclipse.xsd.XSDEnumerationFacet; |
| import org.eclipse.xsd.XSDFacet; |
| import org.eclipse.xsd.XSDFactory; |
| import org.eclipse.xsd.XSDImport; |
| import org.eclipse.xsd.XSDModelGroup; |
| import org.eclipse.xsd.XSDParticle; |
| import org.eclipse.xsd.XSDSchema; |
| import org.eclipse.xsd.XSDSimpleTypeDefinition; |
| import org.eclipse.xsd.XSDTypeDefinition; |
| import org.eclipse.xsd.util.XSDConstants; |
| import org.eclipse.xsd.util.XSDParser; |
| |
| |
| /** |
| * This class produces an XSDSchema given an Ecore EPackage. |
| * The XSDSchema is an XML schema. |
| */ |
| public class EcoreXMLSchemaBuilder extends MapBuilder |
| { |
| public interface QNameMap |
| { |
| String getName(ENamedElement element); |
| } |
| public static final String OPTION_TO_ENFORCE_LOWERBOUND = "ENFORCE_LOWERBOUND"; |
| public static final String OPTION_USE_ENCODED_ATTRIBUTE_STYLE = "USE_ENCODE_ATTRIBUTE_STYLE"; |
| |
| protected static final String EMF_SCHEMA_URI = "http://org.eclipse.emf/xsd"; |
| protected static final String EMF_SCHEMA_PREFIX = "emf"; |
| protected static final String EMF_SCHEMA_NAME = "EMF.xsd"; |
| protected static final String REFERENCE_TYPE_NAME = "string"; |
| |
| protected XSDSchema xsdSchema; |
| protected XSDSchema emfSchema; |
| protected EPackage ePackage; |
| protected Map<String, String> ecoreToSchemaName; |
| protected Map<EPackage, XSDSchema> ePackageToXSDSchemaMap = new HashMap<EPackage, XSDSchema>(); |
| protected Map<EPackage, String> ePackageToNsPrefixMap = new HashMap<EPackage, String>(); |
| protected QNameMap qNameMap; |
| |
| protected boolean minimizedXMI; |
| protected boolean useEncodedAttributeStyle; |
| protected boolean enforceLowerBound; |
| protected List<EClass> rootClasses; |
| protected XSDParser xsdParser; |
| |
| public EcoreXMLSchemaBuilder() |
| { |
| // Make sure the xsd prefix isn't used by a package. |
| // |
| ePackageToNsPrefixMap.put(null, "xsd"); |
| } |
| |
| public Collection<EObject> generate(EPackage ePackage) |
| { |
| return generate(ePackage, null); |
| } |
| |
| public Collection<EObject> generate(EPackage ePackage, QNameMap qNameMap) |
| { |
| this.qNameMap = qNameMap; |
| |
| addInput(ePackage); |
| |
| this.ePackage = ePackage; |
| createSchema(); |
| processEnums(); |
| processClasses(); |
| Collection<EObject> result = new ArrayList<EObject>(); |
| result.add(xsdSchema); |
| if (emfSchema != null) |
| { |
| result.add(emfSchema); |
| } |
| if (mapper != null) |
| { |
| result.add(mapper.getRoot()); |
| } |
| |
| // Add model documentation. |
| // |
| for (Map.Entry<XSDComponent, EModelElement> entry : xsdComponentToEModelElementMap.entrySet()) |
| { |
| addDocumentation(entry.getKey(), entry.getValue()); |
| } |
| |
| return result; |
| } |
| |
| protected String getUniqueNsPrefix(EPackage ePackage) |
| { |
| if (ePackageToNsPrefixMap.containsKey(ePackage)) |
| { |
| return ePackageToNsPrefixMap.get(ePackage); |
| } |
| else |
| { |
| String nsPrefix = ePackage.getNsPrefix(); |
| String uniqueNsPrefix = nsPrefix; |
| for (int i = 1; ePackageToNsPrefixMap.values().contains(uniqueNsPrefix); ++i) |
| { |
| uniqueNsPrefix = nsPrefix + "_" + i; |
| } |
| ePackageToNsPrefixMap.put(ePackage, uniqueNsPrefix); |
| return uniqueNsPrefix; |
| } |
| } |
| |
| protected void createSchema() |
| { |
| xsdSchema = XSDFactory.eINSTANCE.createXSDSchema(); |
| addOutput(xsdSchema); |
| // addInput(xsdSchema); |
| |
| xsdSchema.setTargetNamespace(ePackage.getNsURI()); |
| xsdSchema.setSchemaForSchemaQNamePrefix("xsd"); |
| |
| Map<String, String> namespaces = xsdSchema.getQNamePrefixToNamespaceMap(); |
| namespaces.put(getUniqueNsPrefix(ePackage), xsdSchema.getTargetNamespace()); |
| namespaces.put(xsdSchema.getSchemaForSchemaQNamePrefix(), XSDConstants.SCHEMA_FOR_SCHEMA_URI_2001); |
| |
| map(xsdSchema, ePackage); |
| } |
| |
| protected void createEMFSchema() |
| { |
| emfSchema = XSDFactory.eINSTANCE.createXSDSchema(); |
| |
| emfSchema.setTargetNamespace(EMF_SCHEMA_URI); |
| emfSchema.setSchemaForSchemaQNamePrefix("xsd"); |
| |
| Map<String, String> namespaces = emfSchema.getQNamePrefixToNamespaceMap(); |
| namespaces.put(EMF_SCHEMA_PREFIX, emfSchema.getTargetNamespace()); |
| namespaces.put(emfSchema.getSchemaForSchemaQNamePrefix(), XSDConstants.SCHEMA_FOR_SCHEMA_URI_2001); |
| |
| XSDSimpleTypeDefinition list = XSDFactory.eINSTANCE.createXSDSimpleTypeDefinition(); |
| list.setName(REFERENCE_TYPE_NAME); |
| |
| XSDSimpleTypeDefinition union = XSDFactory.eINSTANCE.createXSDSimpleTypeDefinition(); |
| union.getMemberTypeDefinitions().add(emfSchema.getSchemaForSchema().resolveSimpleTypeDefinition("IDREF")); |
| union.getMemberTypeDefinitions().add(emfSchema.getSchemaForSchema().resolveSimpleTypeDefinition("QName")); |
| union.getMemberTypeDefinitions().add(emfSchema.getSchemaForSchema().resolveSimpleTypeDefinition("anyURI")); |
| |
| list.setItemTypeDefinition(union); |
| list.getContents().add(union); |
| |
| emfSchema.getContents().add(list); |
| } |
| |
| protected void addEMFSchema() |
| { |
| // Do nothing. |
| } |
| |
| protected XSDTypeDefinition typeInOtherSchema(EClassifier classifier) |
| { |
| EPackage typePkg = classifier.getEPackage(); |
| Map<String, String> namespaces = xsdSchema.getQNamePrefixToNamespaceMap(); |
| |
| String nsPrefix = getUniqueNsPrefix(typePkg); |
| if (namespaces.get(nsPrefix) == null) |
| { |
| namespaces.put(nsPrefix, typePkg.getNsURI()); |
| addImport(typePkg.getNsURI(), getName(typePkg) + ".xsd"); |
| createOtherSchema(typePkg); |
| } |
| |
| XSDSchema otherXSDSchema = ePackageToXSDSchemaMap.get(typePkg); |
| return otherXSDSchema.resolveTypeDefinition(getName(classifier)); |
| } |
| |
| protected void addImport(String namespace, String schemaLocation) |
| { |
| XSDImport xsdImport = XSDFactory.eINSTANCE.createXSDImport(); |
| xsdImport.setNamespace(namespace); |
| xsdImport.setSchemaLocation(schemaLocation); |
| xsdSchema.getContents().add(0, xsdImport); |
| } |
| |
| protected void createOtherSchema(EPackage ePackage) |
| { |
| XSDSchema otherSchema = XSDFactory.eINSTANCE.createXSDSchema(); |
| |
| otherSchema.setTargetNamespace(ePackage.getNsURI()); |
| otherSchema.setSchemaForSchemaQNamePrefix("xsd"); |
| |
| Map<String, String> namespaces = otherSchema.getQNamePrefixToNamespaceMap(); |
| namespaces.put(getUniqueNsPrefix(ePackage), otherSchema.getTargetNamespace()); |
| namespaces.put(otherSchema.getSchemaForSchemaQNamePrefix(), XSDConstants.SCHEMA_FOR_SCHEMA_URI_2001); |
| |
| ePackageToXSDSchemaMap.put(ePackage, otherSchema); |
| |
| // map(otherSchema, ePackage); |
| } |
| |
| protected void processClasses() |
| { |
| for (EClassifier classifier : ePackage.getEClassifiers()) |
| { |
| if (classifier instanceof EClass) |
| { |
| processClass((EClass)classifier); |
| } |
| } |
| } |
| |
| protected void processEnums() |
| { |
| for (EClassifier classifier : ePackage.getEClassifiers()) |
| { |
| if (classifier instanceof EEnum) |
| { |
| processEnum((EEnum)classifier); |
| } |
| } |
| } |
| |
| /** |
| * Return the given name, or the name from the XMLMap, if there is one. |
| */ |
| protected String getName(ENamedElement element) |
| { |
| if (qNameMap == null) |
| { |
| return element.getName(); |
| } |
| else |
| { |
| return qNameMap.getName(element); |
| } |
| } |
| |
| /** |
| * Each EEnum is mapped to a schema simple type that restricts the string simple type; |
| * the schema type has an enumeration facet for each EEnumLiteral. |
| */ |
| protected void processEnum(EEnum eEnum) |
| { |
| XSDSimpleTypeDefinition enumType = XSDFactory.eINSTANCE.createXSDSimpleTypeDefinition(); |
| enumType.setName(getName(eEnum)); |
| enumType.setBaseTypeDefinition(xsdSchema.getSchemaForSchema().resolveSimpleTypeDefinition("NCName")); |
| xsdSchema.getContents().add(enumType); |
| |
| map(enumType, eEnum); |
| |
| for (EEnumLiteral literal : eEnum.getELiterals()) |
| { |
| XSDEnumerationFacet facet = XSDFactory.eINSTANCE.createXSDEnumerationFacet(); |
| facet.setLexicalValue(getName(literal)); |
| enumType.getFacetContents().add(facet); |
| |
| map(facet, literal); |
| } |
| } |
| |
| /** |
| * Map each EClass to a schema complex type and an element declaration of that type; |
| * the names of the complex type and element declaration are the name of the class. |
| * If the class is abstract, only a complex type is created from it; there is no |
| * corresponding element declaration. |
| */ |
| protected void processClass(EClass eClass) |
| { |
| XSDComplexTypeDefinition xsdComplexTypeDefinition = XSDFactory.eINSTANCE.createXSDComplexTypeDefinition(); |
| xsdComplexTypeDefinition.setName(getName(eClass)); |
| if (eClass.isAbstract()) |
| { |
| xsdComplexTypeDefinition.setAbstract(true); |
| } |
| List<EClass> superClasses = eClass.getESuperTypes(); |
| |
| if (superClasses.size() > 0) |
| { |
| xsdComplexTypeDefinition.setDerivationMethod(XSDDerivationMethod.EXTENSION_LITERAL); |
| EClass superClass = superClasses.get(0); |
| |
| if (superClass.getEPackage() == ePackage) |
| { |
| xsdComplexTypeDefinition.setBaseTypeDefinition(xsdSchema.resolveTypeDefinition(getName(superClass))); |
| } |
| else |
| { |
| xsdComplexTypeDefinition.setBaseTypeDefinition(typeInOtherSchema(superClass)); |
| } |
| } |
| |
| xsdSchema.getContents().add(xsdComplexTypeDefinition); |
| map(xsdComplexTypeDefinition, eClass); |
| |
| List<EStructuralFeature> features = getFeatures(eClass, superClasses); |
| for (EStructuralFeature f : features) |
| { |
| if (f instanceof EAttribute) |
| { |
| processAttribute((EAttribute)f, xsdComplexTypeDefinition); |
| } |
| else if (f instanceof EReference) |
| { |
| processReference((EReference)f, xsdComplexTypeDefinition); |
| } |
| } |
| |
| if (makeClassElementDeclaration(eClass)) |
| { |
| XSDElementDeclaration xsdElementDeclaration = XSDFactory.eINSTANCE.createXSDElementDeclaration(); |
| xsdElementDeclaration.setName(getName(eClass)); |
| xsdElementDeclaration.setTypeDefinition(xsdComplexTypeDefinition); |
| xsdSchema.getContents().add(xsdElementDeclaration); |
| |
| map(xsdElementDeclaration, eClass); |
| } |
| |
| additionalProcessing(eClass, xsdComplexTypeDefinition); |
| } |
| |
| protected boolean makeClassElementDeclaration(EClass eClass) |
| { |
| return !eClass.isAbstract(); |
| } |
| |
| protected void additionalProcessing(EClass cls, XSDComplexTypeDefinition xsdComplexTypeDefinition) |
| { |
| // Do nothing |
| } |
| |
| /** |
| * Return the inherited features from the super classes (except the first one, which |
| * is the base type for the generated schema type for the class), and the local |
| * features. |
| */ |
| protected List<EStructuralFeature> getFeatures(EClass eClass, List<EClass> superClasses) |
| { |
| List<EStructuralFeature> features = new ArrayList<EStructuralFeature>(); |
| |
| if (superClasses.size() > 0) |
| { |
| List<EClass> allSupers = superClasses.get(0).getEAllSuperTypes(); |
| Set<EClass> allSuperClasses = new HashSet<EClass>(); |
| allSuperClasses.addAll(allSupers); |
| allSuperClasses.add(superClasses.get(0)); |
| |
| for (int i = 1; i < superClasses.size(); i++) |
| { |
| EClass superClass = superClasses.get(i); |
| if (!allSuperClasses.contains(superClass)) |
| { |
| features.addAll(getAllFeatures(superClass, allSuperClasses)); |
| } |
| } |
| } |
| |
| features.addAll(eClass.getEAttributes()); |
| features.addAll(eClass.getEReferences()); |
| return features; |
| } |
| |
| /** |
| * This method returns the list of features for the given class and all inherited |
| * features; ignoring features from classes in the classesToIgnore set. |
| */ |
| protected List<EStructuralFeature> getAllFeatures(EClass eClass, Set<EClass> classesToIgnore) |
| { |
| List<EStructuralFeature> features = new ArrayList<EStructuralFeature>(); |
| List<EClass> superClasses = eClass.getESuperTypes(); |
| |
| for (int i = 0; i < superClasses.size(); i++) |
| { |
| if (!classesToIgnore.contains(superClasses.get(i))) |
| { |
| features.addAll(getAllFeatures(superClasses.get(i), classesToIgnore)); |
| } |
| } |
| |
| features.addAll(eClass.getEAttributes()); |
| features.addAll(eClass.getEReferences()); |
| |
| // the class has been processed and should be ignored if seen again in the hierarchy |
| classesToIgnore.add(eClass); |
| return features; |
| } |
| |
| /** |
| * Map each EAttribute to an XML attribute declaration in the complex type |
| * corresponding to the class, or an XML element declaration, depending on |
| * the multiplicity of the EAttribute. |
| * <p> |
| * The types are mapped as follows: |
| * Ecore type Schema type |
| * ------------ ------------- |
| * EBoolean boolean |
| * EBooleanObject boolean |
| * EInt int |
| * EIntegerObject int |
| * ELong long |
| * ELongObject long |
| * EFloat float |
| * EFloatObject float |
| * EDouble double |
| * EDoubleObject double |
| * EString string |
| * <p> |
| * If the attribute has no type or if the type is an EDataType that is not |
| * an EEnum, the schema string type is used. |
| * <p> |
| * If the EAttribute is required, the attribute declaration includes |
| * use="required". |
| * <p> |
| * If the EAttribute has a defaultValueLiteral, the attribute declaration |
| * has a default attribute whose value is the defaultValueLiteral. |
| * <p> |
| * If the EAttribute is transient, or its type is not serializable, an |
| * attribute declaration is not generated. |
| * <p> |
| * If the EAttribute can have many values, an element declaration is created |
| * rather than an attribute declaration. The lower bound of the attribute is set |
| * to the minOccurs value of the element declaration. The upper bound of the |
| * attribute is set to the maxOccurs value of the element declaration (converting |
| * -1 to unbounded as appropriate). The type of the element is set as above for |
| * attribute declarations. |
| */ |
| protected void processAttribute(EAttribute attribute, XSDComplexTypeDefinition xsdComplexTypeDefinition) |
| { |
| if (processAttribute(attribute)) |
| { |
| if (makeAttributeDeclaration(attribute)) |
| { |
| createAttributeDeclaration(attribute, xsdComplexTypeDefinition); |
| } |
| |
| if (makeAttributeElementDeclaration(attribute)) |
| { |
| createAttributeElementDeclaration(attribute, xsdComplexTypeDefinition); |
| } |
| } |
| } |
| |
| protected void createAttributeDeclaration(EAttribute attribute, XSDComplexTypeDefinition xsdComplexTypeDefinition) |
| { |
| XSDAttributeDeclaration attrDecl = XSDFactory.eINSTANCE.createXSDAttributeDeclaration(); |
| attrDecl.setName(getName(attribute)); |
| setAttributeType(attribute, attrDecl); |
| setDefaultValue(attribute, attrDecl); |
| |
| XSDAttributeUse attrUse = XSDFactory.eINSTANCE.createXSDAttributeUse(); |
| setUseToRequired(attribute, attrUse); |
| attrUse.setContent(attrDecl); |
| xsdComplexTypeDefinition.getAttributeContents().add(attrUse); |
| |
| map(attrUse, attribute); |
| } |
| |
| protected void createAttributeElementDeclaration(EAttribute attribute, XSDComplexTypeDefinition xsdComplexTypeDefinition) |
| { |
| XSDModelGroup modelGroup = getModelGroup(xsdComplexTypeDefinition); |
| XSDElementDeclaration xsdElementDeclaration = XSDFactory.eINSTANCE.createXSDElementDeclaration(); |
| xsdElementDeclaration.setName(getName(attribute)); |
| |
| // If the attribute can have a null value (primitives and enums can't), and |
| // if the attribute can hold many nulls or |
| // it can hold only a single value that is allowed to be null |
| // and it can be considered set when it has the null value... |
| // |
| if (attribute.getEType().getDefaultValue() == null |
| && (attribute.isMany() || (!attribute.isRequired() && (attribute.getDefaultValueLiteral() != null || attribute.isUnsettable())))) |
| { |
| xsdElementDeclaration.setNillable(true); |
| } |
| |
| if (xsdElementDeclaration.isNillable() || attribute.isMany() || !minimizedXMI) |
| { |
| XSDSimpleTypeDefinition attrType = getType(attribute.getEAttributeType()); |
| |
| if (attrType != null) |
| { |
| xsdElementDeclaration.setTypeDefinition(attrType); |
| } |
| |
| XSDParticle particle = XSDFactory.eINSTANCE.createXSDParticle(); |
| particle.setContent(xsdElementDeclaration); |
| setAttributeElementMultiplicity(attribute, particle); |
| modelGroup.getContents().add(particle); |
| map(particle, attribute); |
| } |
| } |
| |
| protected void setAttributeElementMultiplicity(EAttribute attribute, XSDParticle particle) |
| { |
| if (enforceLowerBound) |
| { |
| particle.setMinOccurs(attribute.getLowerBound()); |
| } |
| else |
| { |
| particle.setMinOccurs(0); |
| } |
| |
| particle.setMaxOccurs(attribute.getUpperBound()); |
| } |
| |
| protected boolean processAttribute(EAttribute attribute) |
| { |
| if (attribute.isTransient()) |
| { |
| return false; |
| } |
| |
| EDataType type = attribute.getEAttributeType(); |
| |
| if (type != null && !type.isSerializable()) |
| { |
| return false; |
| } |
| |
| return true; |
| } |
| |
| protected boolean makeAttributeDeclaration(EAttribute attribute) |
| { |
| return !attribute.isMany(); |
| } |
| |
| protected boolean makeAttributeElementDeclaration(EAttribute attribute) |
| { |
| return attribute.isMany(); |
| } |
| |
| /** |
| * Returns the model group for the given complex type definition. If there |
| * is no model group, a model group is created and added to the complex |
| * type definition. |
| */ |
| protected XSDModelGroup getModelGroup(XSDComplexTypeDefinition xsdComplexTypeDefinition) |
| { |
| if (xsdComplexTypeDefinition.getContent() == null) |
| { |
| return createModelGroup(xsdComplexTypeDefinition); |
| } |
| else |
| { |
| XSDParticle particle = (XSDParticle)xsdComplexTypeDefinition.getContent(); |
| return (XSDModelGroup)particle.getContent(); |
| } |
| } |
| |
| protected XSDModelGroup createModelGroup(XSDComplexTypeDefinition xsdComplexTypeDefinition) |
| { |
| XSDModelGroup modelGroup = XSDFactory.eINSTANCE.createXSDModelGroup(); |
| modelGroup.setCompositor(XSDCompositor.SEQUENCE_LITERAL); |
| XSDParticle particle = XSDFactory.eINSTANCE.createXSDParticle(); |
| particle.setContent(modelGroup); |
| xsdComplexTypeDefinition.setContent(particle); |
| return modelGroup; |
| } |
| |
| protected void setAttributeType(EAttribute attribute, XSDAttributeDeclaration attrDecl) |
| { |
| XSDSimpleTypeDefinition attrType = getType(attribute.getEAttributeType()); |
| |
| if (attrType != null) |
| { |
| attrDecl.setTypeDefinition(attrType); |
| } |
| } |
| |
| protected void setUseToRequired(EAttribute attribute, XSDAttributeUse attrUse) |
| { |
| if (attribute.isRequired()) |
| { |
| attrUse.setUse(XSDAttributeUseCategory.REQUIRED_LITERAL); |
| } |
| } |
| |
| protected void setDefaultValue(EAttribute attribute, XSDAttributeDeclaration attrDecl) |
| { |
| if (attribute.getDefaultValueLiteral() != null) |
| { |
| attrDecl.setConstraint(XSDConstraint.DEFAULT_LITERAL); |
| attrDecl.setLexicalValue(attribute.getDefaultValueLiteral()); |
| } |
| } |
| |
| protected void processReference(EReference reference, XSDComplexTypeDefinition xsdComplexTypeDefinition) |
| { |
| if (!skipReference(reference)) |
| { |
| if (makeReferenceAttribute(reference)) |
| { |
| makeReferenceAttribute(reference, xsdComplexTypeDefinition); |
| } |
| |
| if (makeReferenceElement(reference)) |
| { |
| makeReferenceElement(reference, xsdComplexTypeDefinition); |
| } |
| } |
| } |
| |
| protected boolean makeReferenceAttribute(EReference reference) |
| { |
| return !reference.isContainment(); |
| } |
| |
| protected boolean makeReferenceElement(EReference reference) |
| { |
| return reference.isContainment() && !reference.isContainer(); |
| } |
| |
| protected boolean skipReference(EReference reference) |
| { |
| return reference.isTransient(); |
| } |
| |
| protected void makeReferenceAttribute(EReference reference, XSDComplexTypeDefinition xsdComplexTypeDefinition) |
| { |
| XSDAttributeDeclaration attrDecl = XSDFactory.eINSTANCE.createXSDAttributeDeclaration(); |
| attrDecl.setName(getName(reference)); |
| setReferenceAttribType(attrDecl); |
| XSDAttributeUse attrUse = XSDFactory.eINSTANCE.createXSDAttributeUse(); |
| attrUse.setContent(attrDecl); |
| xsdComplexTypeDefinition.getAttributeContents().add(attrUse); |
| |
| map(attrUse, reference); |
| } |
| |
| protected void setReferenceAttribType(XSDAttributeDeclaration xsdAttributeDeclaration) |
| { |
| addEMFSchema(); |
| xsdAttributeDeclaration.setTypeDefinition(xsdSchema.getSchemaForSchema().resolveSimpleTypeDefinition(REFERENCE_TYPE_NAME)); |
| } |
| |
| protected void makeReferenceElement(EReference reference, XSDComplexTypeDefinition xsdComplexTypeDefinition) |
| { |
| XSDModelGroup modelGroup = getModelGroup(xsdComplexTypeDefinition); |
| XSDElementDeclaration xsdElementDeclaration = XSDFactory.eINSTANCE.createXSDElementDeclaration(); |
| xsdElementDeclaration.setName(getName(reference)); |
| |
| if (reference.isUnsettable() && !reference.isMany()) |
| { |
| xsdElementDeclaration.setNillable(true); |
| } |
| |
| setReferenceElementType(reference, xsdElementDeclaration); |
| |
| XSDParticle particle = XSDFactory.eINSTANCE.createXSDParticle(); |
| particle.setContent(xsdElementDeclaration); |
| |
| setReferenceElementMultiplicity(reference, particle); |
| |
| modelGroup.getContents().add(particle); |
| map(particle, reference); |
| } |
| |
| protected void setReferenceElementType(EReference reference, XSDElementDeclaration xsdElementDeclaration) |
| { |
| if (reference.getEType() != null) |
| { |
| XSDTypeDefinition type; |
| |
| if (reference.getEType().getEPackage() == ePackage) |
| { |
| type = xsdSchema.resolveTypeDefinition(getName(reference.getEType())); |
| } |
| else |
| { |
| type = typeInOtherSchema(reference.getEType()); |
| } |
| |
| if (type != null) |
| { |
| xsdElementDeclaration.setTypeDefinition(type); |
| } |
| } |
| } |
| |
| protected void setReferenceElementMultiplicity(EReference reference, XSDParticle particle) |
| { |
| particle.setMinOccurs(reference.getLowerBound()); |
| particle.setMaxOccurs(reference.getUpperBound()); |
| } |
| |
| protected XSDSimpleTypeDefinition getType(EDataType dataType) |
| { |
| if (dataType instanceof EEnum) |
| { |
| EPackage typePkg = dataType.getEPackage(); |
| |
| if (typePkg == ePackage) |
| { |
| return xsdSchema.resolveSimpleTypeDefinition(getName(dataType)); |
| } |
| else |
| { |
| return (XSDSimpleTypeDefinition)typeInOtherSchema(dataType); |
| } |
| } |
| |
| String name = null; |
| |
| if (dataType != null) |
| { |
| name = getName(dataType); |
| } |
| |
| return xsdSchema.getSchemaForSchema().resolveSimpleTypeDefinition(getSchemaName(name)); |
| } |
| |
| private String getSchemaName(String name) |
| { |
| if (ecoreToSchemaName == null) |
| { |
| ecoreToSchemaName = new HashMap<String, String>(); |
| ecoreToSchemaName.put("EBoolean", "boolean"); |
| ecoreToSchemaName.put("EBooleanObject", "boolean"); |
| ecoreToSchemaName.put("EInt", "int"); |
| ecoreToSchemaName.put("EIntegerObject", "int"); |
| ecoreToSchemaName.put("ELong", "long"); |
| ecoreToSchemaName.put("ELongObject", "long"); |
| ecoreToSchemaName.put("EFloat", "float"); |
| ecoreToSchemaName.put("EFloatObject", "float"); |
| ecoreToSchemaName.put("EDouble", "double"); |
| ecoreToSchemaName.put("EDoubleObject", "double"); |
| ecoreToSchemaName.put("EString", "string"); |
| } |
| |
| String schemaName = ecoreToSchemaName.get(name); |
| |
| if (schemaName != null) |
| { |
| return schemaName; |
| } |
| else |
| { |
| return "string"; |
| } |
| } |
| |
| protected void addDocumentation(XSDConcreteComponent xsdComponent, EModelElement eModelElement) |
| { |
| if (EcoreUtil.isAncestor(ePackage, eModelElement)) |
| { |
| String documentation = EcoreUtil.getDocumentation(eModelElement); |
| if (documentation != null) |
| { |
| XSDAnnotation xsdAnnotation = null; |
| if (xsdComponent instanceof XSDAttributeUse) |
| { |
| xsdComponent = ((XSDAttributeUse)xsdComponent).getContent(); |
| } |
| else if (xsdComponent instanceof XSDParticle) |
| { |
| xsdComponent = ((XSDParticle)xsdComponent).getContent(); |
| } |
| |
| if (xsdComponent instanceof XSDSchema) |
| { |
| ((XSDSchema)xsdComponent).getContents().add(0, xsdAnnotation = XSDFactory.eINSTANCE.createXSDAnnotation()); |
| } |
| else if (xsdComponent instanceof XSDTypeDefinition) |
| { |
| ((XSDTypeDefinition)xsdComponent).setAnnotation(xsdAnnotation = XSDFactory.eINSTANCE.createXSDAnnotation()); |
| } |
| else if (xsdComponent instanceof XSDFacet) |
| { |
| ((XSDFacet)xsdComponent).setAnnotation(xsdAnnotation = XSDFactory.eINSTANCE.createXSDAnnotation()); |
| } |
| else if (xsdComponent instanceof XSDElementDeclaration) |
| { |
| ((XSDElementDeclaration)xsdComponent).setAnnotation(xsdAnnotation = XSDFactory.eINSTANCE.createXSDAnnotation()); |
| } |
| else if (xsdComponent instanceof XSDAttributeDeclaration) |
| { |
| ((XSDAttributeDeclaration)xsdComponent).setAnnotation(xsdAnnotation = XSDFactory.eINSTANCE.createXSDAnnotation()); |
| } |
| |
| if (xsdAnnotation != null) |
| { |
| Element userInformation = xsdAnnotation.createUserInformation(null); |
| |
| // Try to parse the documentation and use the parsed version if it's successful. |
| // |
| if (xsdParser == null) |
| { |
| xsdParser = new XSDParser(null); |
| } |
| xsdParser.parseString("<documentation>" + documentation + "</documentation>"); |
| Document document = xsdParser.getDocument(); |
| Document xsdDocument = userInformation.getOwnerDocument(); |
| if (xsdParser.getDiagnostics().isEmpty() && document.getDocumentElement().getFirstChild() != null) |
| { |
| for (Node node = document.getDocumentElement().getFirstChild(); node != null; node = node.getNextSibling()) |
| { |
| userInformation.appendChild(xsdDocument.importNode(node, true)); |
| } |
| } |
| else |
| { |
| userInformation.appendChild(xsdDocument.createTextNode(documentation)); |
| } |
| |
| xsdAnnotation.getElement().appendChild(userInformation); |
| } |
| } |
| } |
| } |
| } |