| /** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.apache.tuscany.sdo.helper; |
| |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.OutputStream; |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.apache.tuscany.sdo.SDOExtendedMetaData; |
| import org.apache.tuscany.sdo.SDOFactory; |
| import org.apache.tuscany.sdo.SimpleAnyTypeDataObject; |
| import org.apache.tuscany.sdo.api.SDOHelper; |
| import org.apache.tuscany.sdo.api.XMLStreamHelper; |
| import org.apache.tuscany.sdo.api.EventListener; |
| import org.apache.tuscany.sdo.impl.ClassImpl; |
| import org.apache.tuscany.sdo.impl.DataGraphImpl; |
| import org.apache.tuscany.sdo.impl.DynamicDataObjectImpl; |
| import org.apache.tuscany.sdo.model.ModelFactory; |
| import org.apache.tuscany.sdo.model.impl.ModelFactoryImpl; |
| import org.apache.tuscany.sdo.spi.SDOHelperBase; |
| import org.apache.tuscany.sdo.util.DataObjectUtil; |
| import org.eclipse.emf.common.notify.Adapter; |
| import org.eclipse.emf.common.notify.Notifier; |
| import org.eclipse.emf.common.util.URI; |
| import org.eclipse.emf.common.util.UniqueEList; |
| import org.eclipse.emf.ecore.EAnnotation; |
| 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.EModelElement; |
| 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.ETypedElement; |
| import org.eclipse.emf.ecore.EcoreFactory; |
| import org.eclipse.emf.ecore.EcorePackage; |
| import org.eclipse.emf.ecore.resource.Resource; |
| import org.eclipse.emf.ecore.resource.ResourceSet; |
| import org.eclipse.emf.ecore.util.EcoreUtil; |
| import org.eclipse.emf.ecore.util.ExtendedMetaData; |
| import org.eclipse.emf.ecore.util.FeatureMap; |
| import org.eclipse.emf.ecore.util.FeatureMapUtil; |
| import org.eclipse.emf.ecore.xmi.XMLResource; |
| |
| import commonj.sdo.DataGraph; |
| import commonj.sdo.DataObject; |
| import commonj.sdo.Property; |
| import commonj.sdo.Sequence; |
| import commonj.sdo.Type; |
| import commonj.sdo.helper.CopyHelper; |
| import commonj.sdo.helper.HelperContext; |
| import commonj.sdo.helper.TypeHelper; |
| import commonj.sdo.impl.HelperProvider; |
| |
| public class SDOHelperImpl extends SDOHelperBase implements SDOHelper, SDOHelper.MetaDataBuilder { |
| |
| public DataObject createDataTypeWrapper(Type dataType, Object value) { |
| SimpleAnyTypeDataObject simpleAnyType = SDOFactory.eINSTANCE.createSimpleAnyTypeDataObject(); |
| simpleAnyType.setInstanceType((EDataType)dataType); |
| simpleAnyType.setValue(value); |
| return simpleAnyType; |
| } |
| |
| public Object createFromString(Type dataType, String literal) { |
| return EcoreUtil.createFromString((EDataType)dataType, literal); |
| } |
| |
| public String convertToString(Type dataType, Object value) { |
| return EcoreUtil.convertToString((EDataType)dataType, value); |
| } |
| |
| public Type getXSDSDOType(String xsdType) { |
| Type type = null; |
| String name = (String)xsdToSdoMappings.get(xsdType); |
| if (name != null) |
| type = (Type)((ModelFactoryImpl)ModelFactory.INSTANCE).getEClassifier(name); |
| return type; |
| } |
| |
| public Sequence getSubstitutionValues(DataObject dataObject, Property head) { |
| final EStructuralFeature group = ExtendedMetaData.INSTANCE.getGroup((EStructuralFeature)head); |
| return null == group ? null : (Sequence)((FeatureMap.Internal)((EObject)dataObject).eGet(group)).getWrapper(); |
| } |
| |
| public Type getJavaSDOType(Class javaClass) { |
| String name = (String)javaToSdoMappings.get(javaClass); |
| if (name != null) { |
| return (Type)((ModelFactoryImpl)ModelFactory.INSTANCE).getEClassifier(name); |
| } |
| return null; |
| } |
| |
| public boolean isRequired(Property property) { |
| return ((EStructuralFeature)property).isRequired(); |
| } |
| |
| public int getUpperBound(Property property) { |
| return ((EStructuralFeature)property).getUpperBound(); |
| } |
| |
| public int getLowerBound(Property property) { |
| return ((EStructuralFeature)property).getLowerBound(); |
| } |
| |
| public List getEnumerationFacet(Type type) { |
| List instProps = type.getInstanceProperties(); |
| String propertyName = "enumeration"; |
| Property enumProperty = null; |
| |
| for (int i = 0; i < instProps.size(); i++) |
| { |
| Property prop = (Property)instProps.get(i); |
| if (propertyName.equals(prop.getName())) |
| enumProperty = prop; |
| } |
| |
| return (List)DataObjectUtil.getMetaObjectInstanceProperty((EModelElement)type, enumProperty); |
| } |
| |
| public List getPatternFacet(Type type) { |
| List instProps = type.getInstanceProperties(); |
| String propertyName = "pattern"; |
| Property patternProperty = null; |
| |
| for (int i = 0; i < instProps.size(); i++) |
| { |
| Property prop = (Property)instProps.get(i); |
| if (propertyName.equals(prop.getName())) |
| patternProperty = prop; |
| } |
| |
| return (List)DataObjectUtil.getMetaObjectInstanceProperty((EModelElement)type, patternProperty); |
| } |
| |
| public boolean isMany(Property property, DataObject context) { |
| return FeatureMapUtil.isMany((EObject)context, (EStructuralFeature)property); |
| } |
| |
| public DataGraph createDataGraph() { |
| return SDOFactory.eINSTANCE.createDataGraph(); |
| } |
| |
| public void setRootObject(DataGraph dataGraph, DataObject rootObject) { |
| ((DataGraphImpl)dataGraph).setERootObject((EObject)rootObject); |
| } |
| |
| public static DataGraph loadDataGraph(InputStream inputStream, Map options) throws IOException { |
| ResourceSet resourceSet = DataObjectUtil.createResourceSet(); |
| Resource resource = resourceSet.createResource(URI.createURI("all.datagraph")); |
| resource.load(inputStream, options); |
| return (DataGraph)resource.getContents().get(0); |
| } |
| |
| static final Object LOADING_SCOPE = XMLResource.OPTION_EXTENDED_META_DATA; |
| |
| protected void registerLoadingScope(Map options, TypeHelper scope) { |
| Object extendedMetaData = ((TypeHelperImpl)scope).getExtendedMetaData(); |
| options.put(LOADING_SCOPE, extendedMetaData); |
| } |
| |
| public DataGraph loadDataGraph(InputStream inputStream, Map options, HelperContext scope) throws IOException { |
| if (scope == null) { |
| scope = HelperProvider.getDefaultContext(); |
| } |
| TypeHelper th = scope.getTypeHelper(); |
| DataGraph result = null; |
| if (th == null || th == TypeHelper.INSTANCE) { |
| result = loadDataGraph(inputStream, options); |
| } else if (options == null) { |
| options = new HashMap(); |
| registerLoadingScope(options, th); |
| result = loadDataGraph(inputStream, options); |
| } else if (options.containsKey(LOADING_SCOPE)) { |
| Object restore = options.get(LOADING_SCOPE); |
| registerLoadingScope(options, th); |
| try { |
| result = loadDataGraph(inputStream, options); |
| } finally { |
| options.put(LOADING_SCOPE, restore); |
| } |
| } else { |
| registerLoadingScope(options, th); |
| try { |
| result = loadDataGraph(inputStream, options); |
| } finally { |
| options.remove(LOADING_SCOPE); |
| } |
| } |
| return result; |
| } |
| |
| public void saveDataGraph(DataGraph dataGraph, OutputStream outputStream, Map options) throws IOException { |
| ((DataGraphImpl)dataGraph).getDataGraphResource().save(outputStream, options); |
| } |
| |
| public void registerDataGraphTypes(DataGraph dataGraph, List/* Type */types) { |
| // if (types == null) |
| // types = SDOUtil.getDataGraphTypes(dataGraph); |
| |
| Set/* EPackage */packages = new HashSet(); |
| for (final Iterator iterator = types.iterator(); iterator.hasNext();) { |
| EClassifier type = (EClassifier)iterator.next(); |
| packages.add(type.getEPackage()); |
| } |
| |
| ResourceSet resourceSet = ((DataGraphImpl)dataGraph).getResourceSet(); |
| |
| for (Iterator iterator = packages.iterator(); iterator.hasNext();) { |
| EPackage typePackage = (EPackage)iterator.next(); |
| Resource resource = typePackage.eResource(); |
| if (resource == null) { |
| resource = resourceSet.createResource(URI.createURI(".ecore")); |
| resource.setURI(URI.createURI(typePackage.getNsURI())); |
| resource.getContents().add(typePackage); |
| } else if (resource.getResourceSet() != resourceSet) |
| resourceSet.getResources().add(resource); |
| } |
| } |
| |
| public HelperContext createHelperContext() { |
| return new HelperContextImpl(false, null); |
| } |
| |
| public HelperContext createHelperContext(boolean extensibleNamespaces) { |
| return new HelperContextImpl(extensibleNamespaces); |
| } |
| |
| public HelperContext createHelperContext(Map options) { |
| return new HelperContextImpl(false, options); |
| } |
| |
| public HelperContext createHelperContext(boolean extensibleNamespaces, Map options) { |
| return new HelperContextImpl(extensibleNamespaces, options); |
| } |
| |
| |
| public CopyHelper createCrossScopeCopyHelper(HelperContext hc) { |
| return new CrossScopeCopyHelperImpl(hc.getTypeHelper()); |
| } |
| |
| |
| public XMLStreamHelper createXMLStreamHelper(HelperContext hc) { |
| return ((HelperContextImpl)hc).getXMLStreamHelper(); |
| } |
| |
| |
| public List getTypes(HelperContext hc, String uri) { |
| |
| EPackage ePackage = ((HelperContextImpl)hc).getExtendedMetaData().getPackage(uri); |
| if (ePackage != null) { |
| return new ArrayList(ePackage.getEClassifiers()); |
| } |
| return null; |
| } |
| |
| public List getOpenContentProperties(DataObject dataObject) { |
| List result = new UniqueEList(); |
| ((ClassImpl)dataObject.getType()).addOpenProperties((EObject)dataObject, result); |
| return result; |
| } |
| |
| public boolean isDocumentRoot(Type type) { |
| return "".equals(SDOExtendedMetaData.INSTANCE.getName((EClassifier)type)); |
| } |
| |
| |
| public Type createType(HelperContext hc, String uri, String name, boolean isDataType) { |
| ExtendedMetaData extendedMetaData = ((HelperContextImpl)hc).getExtendedMetaData(); |
| if ("".equals(uri)) |
| uri = null; // FB |
| |
| EPackage ePackage = extendedMetaData.getPackage(uri); |
| if (ePackage == null) { |
| ePackage = EcoreFactory.eINSTANCE.createEPackage(); |
| ePackage.setEFactoryInstance(new DynamicDataObjectImpl.FactoryImpl()); |
| ePackage.setNsURI(uri); |
| String packagePrefix = uri != null ? URI.createURI(uri).trimFileExtension().lastSegment() : ""; // FB |
| ePackage.setName(packagePrefix); |
| ePackage.setNsPrefix(packagePrefix); |
| extendedMetaData.putPackage(uri, ePackage); |
| } |
| |
| EClassifier eClassifier = ePackage.getEClassifier(name); |
| if (eClassifier != null) // already defined? |
| { |
| // throw new IllegalArgumentException(); |
| return null; |
| } |
| |
| if (name != null) { |
| eClassifier = |
| isDataType ? (EClassifier)SDOFactory.eINSTANCE.createDataType() : (EClassifier)SDOFactory.eINSTANCE |
| .createClass(); |
| eClassifier.setName(name); |
| } else { |
| eClassifier = DataObjectUtil.createDocumentRoot(); |
| } |
| |
| ePackage.getEClassifiers().add(eClassifier); |
| |
| return (Type)eClassifier; |
| } |
| |
| public void addBaseType(Type type, Type baseType) { |
| ((EClass)type).getESuperTypes().add((EClass) baseType); |
| } |
| |
| public void addAliasName(Type type, String aliasName) { |
| throw new UnsupportedOperationException(); // TODO: implement this |
| // method properly |
| // type.getAliasNames().add(aliasName); |
| } |
| |
| public void setOpen(Type type, boolean isOpen) { |
| if (isOpen == type.isOpen()) |
| return; |
| |
| if (isOpen) { |
| EAttribute eAttribute = (EAttribute)SDOFactory.eINSTANCE.createAttribute(); |
| ((EClass)type).getEStructuralFeatures().add(eAttribute); |
| |
| eAttribute.setName("any"); |
| eAttribute.setUnique(false); |
| eAttribute.setUpperBound(ETypedElement.UNBOUNDED_MULTIPLICITY); |
| eAttribute.setEType(EcorePackage.eINSTANCE.getEFeatureMapEntry()); |
| ExtendedMetaData.INSTANCE.setFeatureKind(eAttribute, ExtendedMetaData.ELEMENT_WILDCARD_FEATURE); |
| ExtendedMetaData.INSTANCE.setProcessingKind(eAttribute, ExtendedMetaData.LAX_PROCESSING); |
| ExtendedMetaData.INSTANCE.setWildcards(eAttribute, Collections.singletonList("##any")); |
| |
| // FB TBD Add an "anyAttribute" EAttribute as well. |
| |
| if (ExtendedMetaData.INSTANCE.getMixedFeature((EClass)type) != null) { |
| eAttribute.setDerived(true); |
| eAttribute.setTransient(true); |
| eAttribute.setVolatile(true); |
| } |
| } else { |
| EClass eClass = (EClass)type; |
| EAttribute any = (EAttribute)eClass.getEStructuralFeature("any"); |
| eClass.getEStructuralFeatures().remove(any); |
| } |
| } |
| |
| public void setSequenced(Type type, boolean isSequenced) { |
| // currently, we require setSequenced to be called first, before |
| // anything else is added to the type. |
| if (type.isDataType() || !type.getProperties().isEmpty()) { |
| if (type.getName() != "DocumentRoot") // document root is a |
| // special case |
| throw new IllegalArgumentException(); |
| } |
| |
| if (isSequenced) { |
| EClass eClass = (EClass)type; |
| ExtendedMetaData.INSTANCE.setContentKind(eClass, ExtendedMetaData.MIXED_CONTENT); |
| EAttribute mixedFeature = (EAttribute)SDOFactory.eINSTANCE.createAttribute(); |
| mixedFeature.setName("mixed"); |
| mixedFeature.setUnique(false); |
| mixedFeature.setEType(EcorePackage.eINSTANCE.getEFeatureMapEntry()); |
| mixedFeature.setLowerBound(0); |
| mixedFeature.setUpperBound(-1); |
| // eClass.getEStructuralFeatures().add(mixedFeature); |
| ((ClassImpl)eClass).setSequenceFeature(mixedFeature); |
| ExtendedMetaData.INSTANCE.setFeatureKind(mixedFeature, ExtendedMetaData.ELEMENT_WILDCARD_FEATURE); |
| ExtendedMetaData.INSTANCE.setName(mixedFeature, ":mixed"); |
| } else { |
| // nothing to do, because of current restriction that setSequence |
| // must be called first. |
| } |
| } |
| |
| public void setAbstract(Type type, boolean isAbstract) { |
| ((EClass)type).setAbstract(isAbstract); |
| } |
| |
| public void setJavaClassName(Type type, String javaClassName) { |
| ((EClassifier)type).setInstanceClassName(javaClassName); |
| } |
| |
| public Property createProperty(Type containingType, String name, Type propertyType) { |
| EStructuralFeature eStructuralFeature = |
| propertyType.isDataType() ? (EStructuralFeature)SDOFactory.eINSTANCE.createAttribute() |
| : (EStructuralFeature)SDOFactory.eINSTANCE.createReference(); |
| |
| eStructuralFeature.setName(name); |
| eStructuralFeature.setEType((EClassifier)propertyType); |
| ((EClass)containingType).getEStructuralFeatures().add(eStructuralFeature); |
| |
| if ("".equals(ExtendedMetaData.INSTANCE.getName((EClass)containingType))) // DocumentRoot |
| // containingType? |
| { |
| ExtendedMetaData.INSTANCE.setNamespace(eStructuralFeature, containingType.getURI()); |
| //FB???eStructuralFeature.setUnique(false); |
| //FB???eStructuralFeature.setUpperBound(ETypedElement.UNSPECIFIED_MULTIPLICITY); |
| } |
| |
| if (ExtendedMetaData.INSTANCE.getMixedFeature((EClass)containingType) != null) { |
| eStructuralFeature.setDerived(true); |
| eStructuralFeature.setTransient(true); |
| eStructuralFeature.setVolatile(true); |
| ExtendedMetaData.INSTANCE.setFeatureKind(eStructuralFeature, ExtendedMetaData.ELEMENT_FEATURE); |
| } else { |
| // By default, a SDO property is an XSD element |
| ExtendedMetaData.INSTANCE.setFeatureKind(eStructuralFeature, ExtendedMetaData.ELEMENT_FEATURE); |
| } |
| |
| return (Property)eStructuralFeature; |
| } |
| |
| public void setPropertyXMLKind(Property property, boolean isXmlElement) { |
| if (isXmlElement) { |
| ExtendedMetaData.INSTANCE.setFeatureKind((EStructuralFeature)property, ExtendedMetaData.ELEMENT_FEATURE); |
| } |
| else { |
| ExtendedMetaData.INSTANCE.setFeatureKind((EStructuralFeature)property, ExtendedMetaData.ATTRIBUTE_FEATURE); |
| } |
| } |
| |
| |
| public Property createOpenContentProperty(HelperContext hc, String uri, String name, Type type) |
| { |
| ExtendedMetaData extendedMetaData = ((HelperContextImpl)hc).getExtendedMetaData(); |
| |
| // get/create document root |
| EPackage ePackage = extendedMetaData.getPackage(uri); |
| Type documentRoot = ePackage != null ? (Type)extendedMetaData.getType(ePackage, "") : null; |
| if (documentRoot == null) { |
| documentRoot = createType(hc, uri, null, false); |
| } |
| |
| // Determine if property already exists |
| Property newProperty = documentRoot.getProperty(name); |
| if (newProperty == null) { |
| // Create the new property 'under' the document root..... |
| newProperty = createProperty(documentRoot, name, type); |
| } else { |
| // if property already exists, validate the expected type |
| if (!newProperty.getType().equals(type)) |
| throw new IllegalArgumentException(); |
| } |
| return newProperty; |
| } |
| |
| |
| public void addAliasName(Property property, String aliasName) { |
| throw new UnsupportedOperationException(); // TODO: implement this |
| // method properly |
| // property.getAliasNames().add(aliasName); |
| } |
| |
| public void setMany(Property property, boolean isMany) { |
| ((EStructuralFeature)property).setUpperBound(isMany ? EStructuralFeature.UNBOUNDED_MULTIPLICITY : 1); |
| } |
| |
| public void setContainment(Property property, boolean isContainment) { |
| ((EReference)property).setContainment(isContainment); |
| } |
| |
| public void setDefault(Property property, String defaultValue) { |
| ((EStructuralFeature)property).setDefaultValueLiteral(defaultValue); |
| } |
| |
| public void setReadOnly(Property property, boolean isReadOnly) { |
| ((EStructuralFeature)property).setChangeable(!isReadOnly); |
| } |
| |
| public void setOpposite(Property property, Property opposite) { |
| ((EReference)property).setEOpposite((EReference)opposite); |
| } |
| |
| public void addTypeInstanceProperty(Type definedType, Property instanceProperty, Object value) { |
| addInstanceProperty((EModelElement)definedType, instanceProperty, value); |
| } |
| |
| public void addPropertyInstanceProperty(Property definedProperty, Property instanceProperty, Object value) { |
| addInstanceProperty((EModelElement)definedProperty, instanceProperty, value); |
| } |
| |
| protected void addInstanceProperty(EModelElement metaObject, Property property, Object value) { |
| String uri = property.getContainingType().getURI(); |
| EAnnotation eAnnotation = metaObject.getEAnnotation(uri); |
| if (eAnnotation == null) { |
| eAnnotation = EcoreFactory.eINSTANCE.createEAnnotation(); |
| eAnnotation.setSource(uri); |
| metaObject.getEAnnotations().add(eAnnotation); |
| } |
| // TODO if (property.isMany()) ... // convert list of values |
| String stringValue = convertToString(property.getType(), value); |
| eAnnotation.getDetails().put(property.getName(), stringValue); |
| } |
| |
| |
| public void addChangeListener(DataObject dob, EventListener listener) { |
| // Adapter l = (Adapter)listener; |
| ((Notifier)dob).eAdapters().add((Adapter) listener); |
| } |
| |
| public void removeChangeListener(DataObject dob, EventListener listener) { |
| ((Notifier)dob).eAdapters().remove(listener); |
| } |
| |
| |
| } |