diff options
Diffstat (limited to 'sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util')
29 files changed, 12673 insertions, 0 deletions
diff --git a/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/BasicSequence.java b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/BasicSequence.java new file mode 100644 index 0000000000..e25d30e61c --- /dev/null +++ b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/BasicSequence.java @@ -0,0 +1,176 @@ +/** + * + * 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.util; + +import org.eclipse.emf.ecore.EStructuralFeature; +import org.eclipse.emf.ecore.util.FeatureMap; +import org.eclipse.emf.ecore.util.FeatureMapUtil; +import org.eclipse.emf.ecore.xml.type.XMLTypePackage; + +import commonj.sdo.DataObject; +import commonj.sdo.Property; +import commonj.sdo.Sequence; +import commonj.sdo.Type; + +/** + * SDO Sequance implementation which delegates to a feature map. + */ +public class BasicSequence implements Sequence, FeatureMap.Internal.Wrapper +{ + protected FeatureMap.Internal featureMap; + + public BasicSequence(FeatureMap.Internal featureMap) + { + this.featureMap = featureMap; + featureMap.setWrapper(this); + } + + public FeatureMap featureMap() + { + return featureMap; + } + + public int size() + { + return featureMap.size(); + } + + public Property getProperty(int index) + { + EStructuralFeature feature = featureMap.getEStructuralFeature(index); + return getFeatureProperty(feature); + } + + public static Property getFeatureProperty(EStructuralFeature feature) + { + boolean isText = + feature == XMLTypePackage.Literals.XML_TYPE_DOCUMENT_ROOT__TEXT || + feature == XMLTypePackage.Literals.XML_TYPE_DOCUMENT_ROOT__CDATA || + feature == XMLTypePackage.Literals.XML_TYPE_DOCUMENT_ROOT__COMMENT; + return isText ? null : (Property)feature; + } + + public Object getValue(int index) + { + return featureMap.getValue(index); + } + + public Object setValue(int index, Object value) + { + return featureMap.setValue(index, value); + } + + /* + protected EStructuralFeature getEStructuralFeature(String propertyName) + { + return featureMap.getEObject().eClass().getEStructuralFeature(propertyName); + } + */ + + protected EStructuralFeature getEStructuralFeature(String propertyName, Object value) + { + EStructuralFeature result = featureMap.getEObject().eClass().getEStructuralFeature(propertyName); + if (result == null) + { + Type type = (Type)featureMap.getEObject().eClass(); + if (type.isOpen()) + { + result = (EStructuralFeature)DataObjectUtil.demandOpenProperty(type, propertyName, value, true); + } + } + return result; + } + + protected EStructuralFeature getEStructuralFeature(int propertyIndex) + { + return (EStructuralFeature)DataObjectUtil.getProperty((DataObject)featureMap.getEObject(), propertyIndex); + } + + public boolean add(String propertyName, Object value) + { + return featureMap.add(getEStructuralFeature(propertyName, value), value); + } + + public boolean add(int propertyIndex, Object value) + { + return featureMap.add(getEStructuralFeature(propertyIndex), value); + } + + public boolean add(Property property, Object value) + { + return featureMap.add((EStructuralFeature)property, value); + } + + public void add(int index, String propertyName, Object value) + { + featureMap.add(index, getEStructuralFeature(propertyName, value), value); + } + + public void add(int index, int propertyIndex, Object value) + { + featureMap.add(index, getEStructuralFeature(propertyIndex), value); + } + + public void add(int index, Property property, Object value) + { + featureMap.add(index, (EStructuralFeature)property, value); + } + + /** + * @deprecated + */ + public void add(String text) + { + FeatureMapUtil.addText(featureMap, text); + } + + /** + * @deprecated + */ + public void add(int index, String text) + { + FeatureMapUtil.addText(featureMap, index, text); + } + + public void addText(String text) + { + FeatureMapUtil.addText(featureMap, text); + } + + public void addText(int index, String text) + { + FeatureMapUtil.addText(featureMap, index, text); + } + + public void remove(int index) + { + featureMap.remove(index); + } + + public void move(int toIndex, int fromIndex) + { + featureMap.move(toIndex, fromIndex); + } + + public String toString() + { + return featureMap.toString(); + } +} diff --git a/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/DataGraphResourceFactoryImpl.java b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/DataGraphResourceFactoryImpl.java new file mode 100644 index 0000000000..c3f321d9f9 --- /dev/null +++ b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/DataGraphResourceFactoryImpl.java @@ -0,0 +1,705 @@ +/** + * + * 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.util; + + +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.tuscany.sdo.SDOFactory; +import org.apache.tuscany.sdo.SDOPackage; +import org.apache.tuscany.sdo.helper.TypeHelperImpl; +import org.apache.tuscany.sdo.impl.ChangeSummaryImpl; +import org.apache.tuscany.sdo.impl.DataGraphImpl; +import org.apache.tuscany.sdo.impl.DynamicDataObjectImpl; +import org.eclipse.emf.common.util.EMap; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EFactory; +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.EcorePackage; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.resource.impl.ResourceFactoryImpl; +import org.eclipse.emf.ecore.util.EcoreUtil; +import org.eclipse.emf.ecore.util.ExtendedMetaData; +import org.eclipse.emf.ecore.xmi.EcoreBuilder; +import org.eclipse.emf.ecore.xmi.NameInfo; +import org.eclipse.emf.ecore.xmi.XMLHelper; +import org.eclipse.emf.ecore.xmi.XMLLoad; +import org.eclipse.emf.ecore.xmi.XMLResource; +import org.eclipse.emf.ecore.xmi.XMLSave; +import org.eclipse.emf.ecore.xmi.impl.SAXXMLHandler; +import org.eclipse.emf.ecore.xmi.impl.XMLHelperImpl; +import org.eclipse.emf.ecore.xmi.impl.XMLLoadImpl; +import org.eclipse.emf.ecore.xmi.impl.XMLResourceImpl; +import org.eclipse.emf.ecore.xmi.impl.XMLSaveImpl; +import org.eclipse.emf.ecore.xmi.util.DefaultEcoreBuilder; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.xml.sax.InputSource; +import org.xml.sax.helpers.DefaultHandler; + +import commonj.sdo.ChangeSummary; +import commonj.sdo.helper.TypeHelper; + + +public class DataGraphResourceFactoryImpl extends ResourceFactoryImpl +{ + /** + * Constructor for DataGraphResourceFactoryImpl. + */ + public DataGraphResourceFactoryImpl() + { + super(); + } + + public Resource createResource(URI uri) + { + XMLResourceImpl result = new DataGraphResourceImpl(uri); + + ExtendedMetaData extendedMetaData = ((TypeHelperImpl)TypeHelper.INSTANCE).getExtendedMetaData(); + DataObjectUtil.configureXMLResource(result, extendedMetaData); + + result.getDefaultSaveOptions().put(XMLResource.OPTION_USE_ENCODED_ATTRIBUTE_STYLE, Boolean.TRUE); + result.getDefaultLoadOptions().put(XMLResource.OPTION_USE_DEPRECATED_METHODS, Boolean.TRUE); + //result.setEncoding("UTF-8"); + //result.getDefaultLoadOptions().put(XMLResource.OPTION_USE_LEXICAL_HANDLER, Boolean.TRUE); + //result.getDefaultSaveOptions().put(XMLResource.OPTION_LINE_WIDTH, new Integer(80)); + + return result; + } + + public static class DataGraphResourceImpl extends XMLResourceImpl + { + public DataGraphResourceImpl(URI uri) + { + super(uri); + } + + public static class HelperImpl extends XMLHelperImpl + { + protected DataGraphImpl eDataGraph; + + protected List resources; + protected List uris; + + public HelperImpl(XMLResource xmlResource) + { + super(xmlResource); + } + + public void setResource(XMLResource resource) + { + super.setResource(resource); + if (!resource.getContents().isEmpty()) + { + eDataGraph = (DataGraphImpl)resource.getContents().get(0); + + resources = new ArrayList(); + uris = new ArrayList(); + + resources.add(eDataGraph.getRootResource()); + uris.add("#" + resource.getURIFragment(eDataGraph) + "/@eRootObject"); + + if (eDataGraph.getEChangeSummary() != null) + { + // Ensure that resource exists. + // + resources.add(((EObject)eDataGraph.getChangeSummary()).eResource()); + uris.add("#" + resource.getURIFragment(eDataGraph) + "/@eChangeSummary"); + } + + if (eDataGraph.eResource() != null && eDataGraph.eResource().getResourceSet() != null) + { + int count = 0; + for (Iterator i = eDataGraph.eResource().getResourceSet().getResources().iterator(); i.hasNext();) + { + Resource ePackageResource = (Resource)i.next(); + List resourceContents = ePackageResource.getContents(); + if (resourceContents.size() == 1 && resourceContents.get(0) instanceof EPackage) + { + resources.add(ePackageResource); + uris.add("#" + resource.getURIFragment(eDataGraph) + "/@models." + count++); + } + } + } + } + } + + public String getID(EObject eObject) + { + return super.getID(eObject); + } + + public String getIDREF(EObject eObject) + { + String fragment = super.getIDREF(eObject); + if (fragment.startsWith("/")) + { + int index = resources.indexOf(eObject.eResource()); + if (index != -1) + { + fragment = ((String)uris.get(index)).substring(1) + fragment.substring(1); + } + } + return fragment; + } + + public String getHREF(EObject eObject) + { + return super.getHREF(eObject); + } + + protected URI getHREF(Resource otherResource, EObject obj) + { + int index = resources.indexOf(otherResource); + if (index == -1) + { + return super.getHREF(otherResource, obj); + } + else + { + return createHREF((String)uris.get(index), otherResource.getURIFragment(obj)); + } + } + + protected URI createHREF(String baseURI, String fragment) + { + if (fragment.startsWith("/")) + { + return URI.createURI(baseURI + fragment.substring(1)); + } + else + { + return URI.createURI("#" + fragment); + } + } + + public void populateNameInfo(NameInfo nameInfo, EClass c) + { + if (c == SDOPackage.eINSTANCE.getDataGraph()) + { + if (extendedMetaData != null) + { + extendedMetaData.demandPackage("commonj.sdo").setNsPrefix("sdo"); + } + nameInfo.setQualifiedName(getQName("commonj.sdo", "datagraph")); + nameInfo.setNamespaceURI("commonj.sdo"); + nameInfo.setLocalPart("datagraph"); + } + else if (c == SDOPackage.eINSTANCE.getChangeSummary()) + { + if (extendedMetaData != null) + { + extendedMetaData.demandPackage("commonj.sdo").setNsPrefix("sdo"); + } + nameInfo.setQualifiedName("changeSummary"); + nameInfo.setNamespaceURI(null); + nameInfo.setLocalPart("changeSummary"); + } + else + { + super.populateNameInfo(nameInfo, c); + } + } + + public String getQName(EClass c) + { + if (c == SDOPackage.eINSTANCE.getDataGraph()) + { + if (extendedMetaData != null) + { + extendedMetaData.demandPackage("commonj.sdo").setNsPrefix("sdo"); + } + return getQName("commonj.sdo", "datagraph"); + } + else if (c == SDOPackage.eINSTANCE.getChangeSummary()) + { + if (extendedMetaData != null) + { + extendedMetaData.demandPackage("commonj.sdo").setNsPrefix("sdo"); + } + return getQName((String)null, "changeSummary"); + } + else + { + return super.getQName(c); + } + } + } + + protected XMLHelper createXMLHelper() + { + return new HelperImpl(this); + } + + protected EObject getEObjectByID(String id) + { + List contents = getContents(); + if (contents.size() >= 1) + { + Object rootObject = contents.get(0); + if (rootObject instanceof DataGraphImpl) + { + DataGraphImpl eDataGraph = (DataGraphImpl)rootObject; + EObject result = eDataGraph.getRootResource().getEObject(id); + if (result != null) + { + return result; + } + else + { + ChangeSummary eChangeSummary = eDataGraph.getEChangeSummary(); + if (eChangeSummary != null) + { + result = ((EObject)eDataGraph.getChangeSummary()).eResource().getEObject(id); + if (result != null) + { + return result; + } + } + } + } + } + return super.getEObjectByID(id); + } + + public static class SaveImpl extends XMLSaveImpl + { + protected DataGraphImpl eDataGraph; + + public SaveImpl(XMLHelper xmlHelper) + { + super(xmlHelper); + } + + public void traverse(List contents) + { + if (contents.size() >= 1 && contents.get(0) instanceof DataGraphImpl) + { + eDataGraph = (DataGraphImpl)contents.get(0); + + Object datagraphMark = null; + if (!toDOM) + { + if (declareXML) + { + doc.add("<?xml version=\"" + xmlVersion + "\" encoding=\"" + encoding + "\"?>"); + doc.addLine(); + } + String elementName = helper.getQName(eDataGraph.eClass()); + doc.startElement(elementName); + datagraphMark = doc.mark(); + } + else + { + helper.populateNameInfo(nameInfo, eDataGraph.eClass()); + currentNode = document.createElementNS(nameInfo.getNamespaceURI(), nameInfo.getQualifiedName()); + document.appendChild(currentNode); + // not calling handler since there is no corresponding EObject + } + + if (eDataGraph.eResource() != null && eDataGraph.eResource().getResourceSet() != null) + { + List ePackages = new ArrayList(); + for (Iterator i = eDataGraph.eResource().getResourceSet().getResources().iterator(); i.hasNext();) + { + List resourceContents = ((Resource)i.next()).getContents(); + if (resourceContents.size() == 1 && resourceContents.get(0) instanceof EPackage) + { + ePackages.add(resourceContents.get(0)); + } + } + if (!ePackages.isEmpty()) + { + if (!toDOM) + { + doc.startElement("models"); + doc.addAttribute("xmlns", ""); + } + else + { + currentNode = currentNode.appendChild(document.createElementNS(null, "models")); + ((Element)currentNode).setAttributeNS(ExtendedMetaData.XMLNS_URI, ExtendedMetaData.XMLNS_PREFIX, ""); + // not calling handler since there is no corresponding EObject + } + for (Iterator i = ePackages.iterator(); i.hasNext();) + { + writeTopObject((EPackage)i.next()); + } + if (!toDOM) + { + doc.endElement(); + } + else + { + currentNode = currentNode.getParentNode(); + } + } + } + + // use namespace declarations defined in the document (if any) + EObject eRootObject = eDataGraph.getERootObject(); + EReference xmlnsPrefixMapFeature = extendedMetaData.getXMLNSPrefixMapFeature(eRootObject.eClass()); + if (xmlnsPrefixMapFeature != null) + { + EMap xmlnsPrefixMap = (EMap)eRootObject.eGet(xmlnsPrefixMapFeature); + helper.setPrefixToNamespaceMap(xmlnsPrefixMap); + } + ChangeSummary changeSummary = eDataGraph.getEChangeSummary(); + + if (changeSummary != null) + { + helper.setMustHavePrefix(true); + if (changeSummary.isLogging()) + { + ((ChangeSummaryImpl)changeSummary).summarize(); + writeTopObject((EObject)changeSummary); + } + else + { + writeTopObject((EObject)changeSummary); + } + helper.setMustHavePrefix(false); + } + + if (eRootObject != null && writeTopObject(eRootObject) == null && !toDOM) + { + doc.addLine(); + doc.setMixed(false); + } + if (!toDOM) + { + doc.endElement(); + // reset to add namespace declarations + // + doc.resetToMark(datagraphMark); + } + else + { + currentNode = document.getFirstChild(); + } + addNamespaceDeclarations(); + } + else + { + super.traverse(contents); + } + } + + protected void writeTopAttributes(EObject top) + { + if (top == eDataGraph.getEChangeSummary()) + { + if (!toDOM) + { + doc.addAttribute("xmlns", ""); + doc.addAttribute("logging", String.valueOf(eDataGraph.getEChangeSummary().isLogging())); + } + else + { + ((Element)currentNode).setAttributeNS(ExtendedMetaData.XMLNS_URI, ExtendedMetaData.XMLNS_PREFIX, ""); + ((Element)currentNode).setAttributeNS("", "logging", String.valueOf(eDataGraph.getEChangeSummary().isLogging())); + } + } + } + + protected EObject getSchemaLocationRoot(EObject eObject) + { + return eDataGraph.getERootObject(); + } + } + + protected XMLSave createXMLSave() + { + return new SaveImpl(createXMLHelper()); + } + + public static class LoadImpl extends XMLLoadImpl + { + protected boolean resumeLogging = false; + + public void load(XMLResource resource, InputSource inputSource, Map options) throws IOException + { + super.load(resource, inputSource, options); + if (resumeLogging) ((ChangeSummaryImpl)((DataGraphImpl)resource.getContents().get(0)).getChangeSummary()).resumeLogging(); + } + + public void load(XMLResource resource, InputStream inputStream, Map options) throws IOException + { + super.load(resource, inputStream, options); + if (resumeLogging) ((ChangeSummaryImpl)((DataGraphImpl)resource.getContents().get(0)).getChangeSummary()).resumeLogging(); + } + + public void load(XMLResource resource, Node node, Map options) throws IOException + { + super.load(resource, node, options); + if (resumeLogging) ((ChangeSummaryImpl)((DataGraphImpl)resource.getContents().get(0)).getChangeSummary()).resumeLogging(); + } + + public LoadImpl(XMLHelper xmlHelper) + { + super(xmlHelper); + } + + protected DefaultHandler makeDefaultHandler() + { + return new SAXXMLHandler(resource, helper, options) + { + protected DataGraphImpl eDataGraph; + + protected boolean isInModels; + + protected List ePackages = new ArrayList(); + + protected EObject createDocumentRoot(String prefix, String uri, String name, EFactory eFactory, boolean top) + { + return null; + } + + protected void setAttribValue(EObject object, String name, String value) + { + if ("logging".equals(name) && object instanceof ChangeSummaryImpl) + { + resumeLogging = Boolean.valueOf(value).booleanValue(); + } + else + { + super.setAttribValue(object, name, value); + } + } + + protected EMap recordNamespacesSchemaLocations(EObject root) + { + EObject dgroot = eDataGraph.getERootObject(); + if (dgroot == null) + { + return null; + } + EMap prefixToNamespaceMap = super.recordNamespacesSchemaLocations(dgroot); + if (prefixToNamespaceMap != null) + { + for (Iterator i = prefixToNamespaceMap.iterator(); i.hasNext();) + { + Map.Entry entry = (Map.Entry)i.next(); + String prefix = (String)entry.getKey(); + String namespace = (String)entry.getValue(); + if (namespace.equals("commonj.sdo")) + { + prefixToNamespaceMap.removeKey(prefix); + break; + } + } + } + return prefixToNamespaceMap; + } + + protected void handleFeature(String prefix, String name) + { + if (isInModels && objects.size() == 2) + { + EObject modelObject = createObjectByType(prefix, name, false); + processObject(modelObject); + ePackages.add(modelObject); + } + else if (objects.size() == 1) + { + eDataGraph = (DataGraphImpl)objects.peek(); + eDataGraph.getResourceSet(); + if ("".equals(prefix) && "changeSummary".equals(name)) + { + ChangeSummary eChangeSummary = (ChangeSummary)createObjectFromFactory(SDOFactory.eINSTANCE, "ChangeSummary"); + eDataGraph.setEChangeSummary(eChangeSummary); + processObject((EObject)eChangeSummary); + } + else if ("".equals(prefix) && "models".equals(name)) + { + isInModels = true; + types.push(OBJECT_TYPE); + objects.push(eDataGraph); + mixedTargets.push(null); + } + else if (eDataGraph.getERootObject() == null) + { + if (useNewMethods) + { + handleSchemaLocation(); + } + processSchemaLocations(prefix, name); + if (processAnyXML) + { + // Ensure that anything can be handled, even if it's not recognized. + // + String namespaceURI = helper.getURI(prefix); + if (extendedMetaData.getPackage(namespaceURI) == null) + { + EStructuralFeature rootFeature = extendedMetaData.demandFeature(namespaceURI, name, true); + rootFeature.getEContainingClass().getEPackage().setEFactoryInstance(new DynamicDataObjectImpl.FactoryImpl()); + } + } + + //FB TEMPORARY allow loading proper serialization (global element instead of type name) + //FB Proper fix is to reimplement DataGraph as proper DataObject, and remove this entire class + EStructuralFeature rootFeature = extendedMetaData.getElement(helper.getURI(prefix), name); + if (rootFeature != null) name = rootFeature.getEType().getName(); + + EObject rootObject = createObjectByType(prefix, name, false); + + eDataGraph.setERootObject(rootObject); + processObject(rootObject); + if (rootObject != null + && rootObject.eClass() == ExtendedMetaData.INSTANCE.getDocumentRoot(rootObject.eClass().getEPackage())) + { + super.handleFeature(prefix, name); + + // Remove the document root from the stack. + // + Object mixedTarget = mixedTargets.pop(); + Object object = objects.pop(); + mixedTargets.pop(); + objects.pop(); + mixedTargets.push(mixedTarget); + objects.push(object); + } + } + } + else + { + super.handleFeature(prefix, name); + } + } + + public void endElement(String uri, String localName, String name) + { + if (isInModels && objects.size() == 2) + { + if (!ePackages.isEmpty()) + { + for (Iterator i = ePackages.iterator(); i.hasNext();) + { + EPackage ePackage = (EPackage)i.next(); + ePackage.setEFactoryInstance(new DynamicDataObjectImpl.FactoryImpl()); + Resource resource = resourceSet.createResource(URI.createURI("*.ecore")); + resource.getContents().add(ePackage); + if (ePackage.getNsURI() != null) + { + resource.setURI(URI.createURI(ePackage.getNsURI())); + } + + if (extendedMetaData != null) + { + extendedMetaData.putPackage(extendedMetaData.getNamespace(ePackage), ePackage); + } + else + { + packageRegistry.put(ePackage.getNsURI(), ePackage); + } + } + handleForwardReferences(); + } + isInModels = false; + } + super.endElement(uri, localName, name); + } + + protected EPackage getPackageForURI(String uriString) + { + if ("commonj.sdo".equals(uriString)) + { + return SDOPackage.eINSTANCE; + } + else + { + return super.getPackageForURI(uriString); + } + } + + protected EObject createObjectFromFactory(EFactory factory, String typeName) + { + if (factory == SDOFactory.eINSTANCE) + { + if ("datagraph".equals(typeName)) + { + return super.createObjectFromFactory(factory, "DataGraph"); + } + } + return super.createObjectFromFactory(factory, typeName); + } + + protected EcoreBuilder createEcoreBuilder(Map options, ExtendedMetaData extendedMetaData) + { + return new DefaultEcoreBuilder(extendedMetaData) + { + public Collection generate(Map urisToLocations) throws Exception + { + Collection result = super.generate(urisToLocations); + return updateDynamicFactory(result); + } + + public Collection generate(Collection urisToLocations) throws Exception + { + Collection result = super.generate(urisToLocations); + return updateDynamicFactory(result); + } + + protected Collection updateDynamicFactory(Collection result) + { + for (Iterator i = result.iterator(); i.hasNext();) + { + Resource resource = (Resource)i.next(); + for (Iterator j = EcoreUtil.getObjectsByType(resource.getContents(), EcorePackage.eINSTANCE.getEPackage()).iterator(); j.hasNext();) + { + EPackage ePackage = (EPackage)j.next(); + ePackage.setEFactoryInstance(new DynamicDataObjectImpl.FactoryImpl()); + } + } + return result; + } + + }; + } + + protected EPackage handleMissingPackage(String uriString) + { + EPackage result = super.handleMissingPackage(uriString); + if (processAnyXML && objects.size() == 1) + { + result = extendedMetaData.demandPackage(uriString); + } + return result; + } + }; + } + } + + protected XMLLoad createXMLLoad() + { + return new LoadImpl(createXMLHelper()); + } + } +} diff --git a/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/DataObjectUtil.java b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/DataObjectUtil.java new file mode 100644 index 0000000000..01b511cd7d --- /dev/null +++ b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/DataObjectUtil.java @@ -0,0 +1,2870 @@ +/** + * + * 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.util; + + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +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 java.util.TimeZone; + +import org.apache.tuscany.sdo.SDOExtendedMetaData; +import org.apache.tuscany.sdo.SDOFactory; +import org.apache.tuscany.sdo.SDOPackage; +import org.apache.tuscany.sdo.impl.ClassImpl; +import org.apache.tuscany.sdo.impl.DataGraphImpl; +import org.apache.tuscany.sdo.model.ModelFactory; +import org.apache.tuscany.sdo.model.impl.ModelFactoryImpl; +import org.apache.tuscany.sdo.util.resource.SDOXMLResourceFactoryImpl; +import org.eclipse.emf.common.util.BasicEList; +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.EReference; +import org.eclipse.emf.ecore.EStructuralFeature; +import org.eclipse.emf.ecore.EcorePackage; +import org.eclipse.emf.ecore.impl.EStringToStringMapEntryImpl; +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.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.XMLOptions; +import org.eclipse.emf.ecore.xmi.XMLParserPool; +import org.eclipse.emf.ecore.xmi.XMLResource; +import org.eclipse.emf.ecore.xmi.impl.EMOFResourceFactoryImpl; +import org.eclipse.emf.ecore.xmi.impl.EcoreResourceFactoryImpl; +import org.eclipse.emf.ecore.xmi.impl.XMLOptionsImpl; +import org.eclipse.emf.ecore.xmi.impl.XMLParserPoolImpl; +import org.eclipse.emf.ecore.xml.type.XMLTypeFactory; +import org.eclipse.xsd.util.XSDResourceFactoryImpl; + +import commonj.sdo.ChangeSummary; +import commonj.sdo.DataGraph; +import commonj.sdo.DataObject; +import commonj.sdo.Property; +import commonj.sdo.Sequence; +import commonj.sdo.Type; +import commonj.sdo.helper.DataHelper; +import commonj.sdo.helper.TypeHelper; +import commonj.sdo.impl.HelperProvider; + + +public final class DataObjectUtil +{ + public static void setString(DataObject dataObject, Property property, String value) { + dataObject.set(property, getSetValue(property, value)); + } + + public static void setShort(DataObject dataObject, Property property, short value) { + dataObject.set(property, getSetValue(property, value)); + } + + public static void setLong(DataObject dataObject, Property property, long value) { + dataObject.set(property, getSetValue(property, value)); + } + + public static void setList(DataObject dataObject, Property property, List value) { + dataObject.set(property, value); + } + + public static void setInt(DataObject dataObject, Property property, int value) { + dataObject.set(property, getSetValue(property, value)); + } + + public static void setFloat(DataObject dataObject, Property property, float value) { + dataObject.set(property, getSetValue(property, value)); + } + + public static void setDouble(DataObject dataObject, Property property, double value) { + dataObject.set(property, getSetValue(property, value)); + } + + public static void setDate(DataObject dataObject, Property property, Date value) { + dataObject.set(property, getSetValue(property, value)); + } + + public static void setDataObject(DataObject dataObject, Property property, DataObject value) { + dataObject.set(property, value); + } + + public static void setChar(DataObject dataObject, Property property, char value) { + dataObject.set(property, getSetValue(property, value)); + } + + public static void setBytes(DataObject dataObject, Property property, byte[] value) { + dataObject.set(property, getSetValue(property, value)); + } + + public static void setByte(DataObject dataObject, Property property, byte value) { + dataObject.set(property, getSetValue(property, value)); + } + + public static void setBoolean(DataObject dataObject, Property property, boolean value) { + dataObject.set(property, getSetValue(property, value)); + } + + public static void setBigInteger(DataObject dataObject, Property property, BigInteger value) + { + dataObject.set(property, getSetValue(property, value)); + } + + public static void setBigDecimal(DataObject dataObject, Property property, BigDecimal value) + { + dataObject.set(property, getSetValue(property, value)); + } + + public static String getString(DataObject dataObject, Property property) + { + return getString(dataObject.get(property)); + } + + public static short getShort(DataObject dataObject, Property property) + { + return getShort(dataObject.get(property)); + } + + public static Sequence getSequence(DataObject dataObject, Property property) + { + return (Sequence)dataObject.get(property); + } + + public static long getLong(DataObject dataObject, Property property) + { + return getLong(dataObject.get(property)); + } + + public static List getList(DataObject dataObject, Property property) + { + return (List)dataObject.get(property); + } + + public static int getInt(DataObject dataObject, Property property) + { + return getInt(dataObject.get(property)); + } + + public static float getFloat(DataObject dataObject, Property property) + { + return getFloat(dataObject.get(property)); + } + + public static double getDouble(DataObject dataObject, Property property) + { + return getDouble(dataObject.get(property)); + } + + public static Date getDate(DataObject dataObject, Property property) + { + return getDate(dataObject.get(property)); + } + + public static DataObject getDataObject(DataObject dataObject, Property property) + { + return (DataObject)dataObject.get(property); + } + + public static char getChar(DataObject dataObject, Property property) + { + return getChar(dataObject.get(property)); + } + + public static byte[] getBytes(DataObject dataObject, Property property) + { + return getBytes(dataObject.get(property)); + } + + public static byte getByte(DataObject dataObject, Property property) + { + return getByte(dataObject.get(property)); + } + + public static boolean getBoolean(DataObject dataObject, Property property) + { + return getBoolean(dataObject.get(property)); + } + + public static BigInteger getBigInteger(DataObject dataObject, Property property) + { + return getBigInteger(dataObject.get(property)); + } + + public static BigDecimal getBigDecimal(DataObject dataObject, Property property) + { + return getBigDecimal(dataObject.get(property)); + } + + + public static void setString(DataObject dataObject, int propertyIndex, String value) { + setString(dataObject,getProperty(dataObject, propertyIndex), value); + } + + public static void setShort(DataObject dataObject, int propertyIndex, short value) { + setShort(dataObject,getProperty(dataObject, propertyIndex), value); + } + + public static void setLong(DataObject dataObject, int propertyIndex, long value) { + setLong(dataObject,getProperty(dataObject, propertyIndex), value); + } + + public static void setList(DataObject dataObject, int propertyIndex, List value) { + setList(dataObject,getProperty(dataObject, propertyIndex), value); + } + + public static void setInt(DataObject dataObject, int propertyIndex, int value) { + setInt(dataObject,getProperty(dataObject, propertyIndex), value); + } + + public static void setFloat(DataObject dataObject, int propertyIndex, float value) { + setFloat(dataObject,getProperty(dataObject, propertyIndex), value); + } + + public static void setDouble(DataObject dataObject, int propertyIndex, double value) { + setDouble(dataObject,getProperty(dataObject, propertyIndex), value); + } + + public static void setDate(DataObject dataObject, int propertyIndex, Date value) { + setDate(dataObject,getProperty(dataObject, propertyIndex), value); + } + + public static void setDataObject(DataObject dataObject, int propertyIndex, DataObject value) { + dataObject.set(getProperty(dataObject, propertyIndex), value); + } + + public static void setChar(DataObject dataObject, int propertyIndex, char value) { + setChar(dataObject,getProperty(dataObject, propertyIndex), value); + } + + public static void setBytes(DataObject dataObject, int propertyIndex, byte[] value) { + setBytes(dataObject,getProperty(dataObject, propertyIndex), value); + } + + public static void setByte(DataObject dataObject, int propertyIndex, byte value) { + setByte(dataObject,getProperty(dataObject, propertyIndex), value); + } + + public static void setBoolean(DataObject dataObject, int propertyIndex, boolean value) { + setBoolean(dataObject,getProperty(dataObject, propertyIndex), value); + } + + public static void setBigInteger(DataObject dataObject, int propertyIndex, BigInteger value) + { + setBigInteger(dataObject,getProperty(dataObject, propertyIndex), value); + } + + public static void setBigDecimal(DataObject dataObject, int propertyIndex, BigDecimal value) + { + setBigDecimal(dataObject,getProperty(dataObject, propertyIndex), value); + } + + public static String getString(DataObject dataObject, int propertyIndex) + { + return getString(dataObject.get(getProperty(dataObject, propertyIndex))); + } + + public static short getShort(DataObject dataObject, int propertyIndex) + { + return getShort(dataObject.get(getProperty(dataObject, propertyIndex))); + } + + + public static Sequence getSequence(DataObject dataObject, int propertyIndex) + { + return (Sequence)dataObject.get(propertyIndex); + } + + public static long getLong(DataObject dataObject, int propertyIndex) + { + return getLong(dataObject.get(getProperty(dataObject, propertyIndex))); + } + + public static List getList(DataObject dataObject, int propertyIndex) + { + return (List)dataObject.get(getProperty(dataObject, propertyIndex)); + } + + public static int getInt(DataObject dataObject, int propertyIndex) + { + return getInt(dataObject.get(getProperty(dataObject, propertyIndex))); + } + + public static float getFloat(DataObject dataObject, int propertyIndex) + { + return getFloat(dataObject.get(getProperty(dataObject, propertyIndex))); + } + + public static double getDouble(DataObject dataObject, int propertyIndex) + { + return getDouble(dataObject.get(getProperty(dataObject, propertyIndex))); + } + + public static Date getDate(DataObject dataObject, int propertyIndex) + { + return getDate(dataObject.get(getProperty(dataObject, propertyIndex))); + } + + public static DataObject getDataObject(DataObject dataObject, int propertyIndex) + { + return (DataObject)dataObject.get(getProperty(dataObject, propertyIndex)); + } + + public static char getChar(DataObject dataObject, int propertyIndex) + { + return getChar(dataObject.get(getProperty(dataObject, propertyIndex))); + } + + public static byte[] getBytes(DataObject dataObject, int propertyIndex) + { + return getBytes(dataObject.get(getProperty(dataObject, propertyIndex))); + } + + public static byte getByte(DataObject dataObject, int propertyIndex) + { + return getByte(dataObject.get(getProperty(dataObject, propertyIndex))); + } + + public static boolean getBoolean(DataObject dataObject, int propertyIndex) + { + return getBoolean(dataObject.get(getProperty(dataObject, propertyIndex))); + } + + public static BigInteger getBigInteger(DataObject dataObject, int propertyIndex) + { + return getBigInteger(dataObject.get(getProperty(dataObject, propertyIndex))); + } + + public static BigDecimal getBigDecimal(DataObject dataObject, int propertyIndex) + { + return getBigDecimal(dataObject.get(getProperty(dataObject, propertyIndex))); + } + + public static void detach(DataObject dataObject) { + EcoreUtil.remove((EObject)dataObject); + } + + public static DataObject getRootObject(DataObject dataObject) + { + return (DataObject)EcoreUtil.getRootContainer((EObject)dataObject); + } + + public static boolean isInternalProperty(EStructuralFeature eStructuralFeature) + { + //return FeatureMapUtil.isFeatureMap(eStructuralFeature); + return !(eStructuralFeature.getEType() instanceof Type); + } + + public static List getInstanceProperties(DataObject dataObject) + { + Type type = dataObject.getType(); + List result = new UniqueEList(type.getProperties()); + ((ClassImpl)type).addOpenProperties((EObject)dataObject, result); + return result; + } + + public static void delete(DataObject dataObject) + { + EObject eDataObject = (EObject)dataObject; + EcoreUtil.remove(eDataObject); + List contents = new ArrayList((eDataObject).eContents()); + for (int i = 0, size = contents.size(); i < size; ++i) + { + ((DataObject)contents.get(i)).delete(); + } + EClass eClass = eDataObject.eClass(); + for (int i = 0, size = eClass.getFeatureCount(); i < size; ++i) + { + EStructuralFeature eStructuralFeature = eClass.getEStructuralFeature(i); + if (eStructuralFeature.isChangeable() && !eStructuralFeature.isDerived() && !((Property)eStructuralFeature).isReadOnly()) + { + eDataObject.eUnset(eStructuralFeature); + } + } + } + + public static DataObject createDataObject(DataObject dataObject, Property property, Type type) + { + if (!property.isContainment()) + { + throw new IllegalArgumentException("The property '" + property.getName() + "' of '" + property.getContainingType().getName() + + "' isn't a containment"); + } + DataObject result = DataObjectUtil.create(type); + if (FeatureMapUtil.isMany((EObject)dataObject, (EStructuralFeature)property)) + { + ((List)dataObject.get(property)).add(result); + } + else + { + dataObject.set(property, result); + } + return result; + } + + public static DataObject createDataObject(DataObject dataObject, int propertyIndex, String namespaceURI, String typeName) + { + Property property = DataObjectUtil.getProperty(dataObject, propertyIndex); + Type type = DataObjectUtil.getType(dataObject, namespaceURI, typeName); + return createDataObject(dataObject, property, type); + } + + public static DataObject createDataObject(DataObject dataObject, String propertyName, String namespaceURI, String typeName) + { + Property property = getInstanceProperty(dataObject, propertyName); + Type type = DataObjectUtil.getType(dataObject, namespaceURI, typeName); + return createDataObject(dataObject, property, type); + } + + public static DataObject createDataObject(DataObject dataObject, Property property) + { + Type type = property.getType(); + return createDataObject(dataObject, property, type); + } + + public static DataObject createDataObject(DataObject dataObject, int propertyIndex) + { + Property property = getProperty(dataObject, propertyIndex); + Type type = property.getType(); + return createDataObject(dataObject,property, type); + } + + public static DataObject createDataObject(DataObject dataObject, String propertyName) + { + Property property = (Property)getInstanceProperty(dataObject, propertyName); + Type type = property.getType(); + return createDataObject(dataObject,property, type); + } + + public static void setString(DataObject dataObject, String path, String value) + { + Property property = dataObject.getType().getProperty(path); + if (property != null) + { + dataObject.set(property, DataObjectUtil.getSetValue(property, value)); + } + else + { + DataObjectUtil.Accessor accessor = DataObjectUtil.Accessor.create((EObject)dataObject, path); + accessor.setAndRecyle(DataObjectUtil.getSetValue(accessor.getProperty(), value)); + } + } + + + public static void setShort(DataObject dataObject, String path, short value) + { + Property property = dataObject.getType().getProperty(path); + if (property != null) + { + dataObject.set(property, DataObjectUtil.getSetValue(property, value)); + } + else + { + DataObjectUtil.Accessor accessor = DataObjectUtil.Accessor.create((EObject)dataObject, path); + accessor.setAndRecyle(DataObjectUtil.getSetValue(accessor.getProperty(), value)); + } + } + + public static void setLong(DataObject dataObject, String path, long value) + { + Property property = dataObject.getType().getProperty(path); + if (property != null) + { + dataObject.set(property, DataObjectUtil.getSetValue(property, value)); + } + else + { + DataObjectUtil.Accessor accessor = DataObjectUtil.Accessor.create((EObject)dataObject, path); + accessor.setAndRecyle(DataObjectUtil.getSetValue(accessor.getProperty(), value)); + } + } + + public static void setList(DataObject dataObject, String path, List value) + { + dataObject.set(path, value); + } + + public static void setInt(DataObject dataObject, String path, int value) + { + Property property = dataObject.getType().getProperty(path); + if (property != null) + { + dataObject.set(property, DataObjectUtil.getSetValue(property, value)); + } + else + { + DataObjectUtil.Accessor accessor = DataObjectUtil.Accessor.create((EObject)dataObject, path); + accessor.setAndRecyle(DataObjectUtil.getSetValue(accessor.getProperty(), value)); + } + } + + public static void setFloat(DataObject dataObject, String path, float value) + { + Property property = dataObject.getType().getProperty(path); + if (property != null) + { + dataObject.set(property, DataObjectUtil.getSetValue(property, value)); + } + else + { + DataObjectUtil.Accessor accessor = DataObjectUtil.Accessor.create((EObject)dataObject, path); + accessor.setAndRecyle(DataObjectUtil.getSetValue(accessor.getProperty(), value)); + } + } + + public static void setDouble(DataObject dataObject, String path, double value) + { + Property property = dataObject.getType().getProperty(path); + if (property != null) + { + dataObject.set(property, DataObjectUtil.getSetValue(property, value)); + } + else + { + DataObjectUtil.Accessor accessor = DataObjectUtil.Accessor.create((EObject)dataObject, path); + accessor.setAndRecyle(DataObjectUtil.getSetValue(accessor.getProperty(), value)); + } + } + + public static void setDate(DataObject dataObject, String path, Date value) + { + Property property = dataObject.getType().getProperty(path); + if (property != null) + { + dataObject.set(property, DataObjectUtil.getSetValue(property, value)); + } + else + { + DataObjectUtil.Accessor accessor = DataObjectUtil.Accessor.create((EObject)dataObject, path); + accessor.setAndRecyle(DataObjectUtil.getSetValue(accessor.getProperty(), value)); + } + } + + public static void setDataObject(DataObject dataObject, String path, DataObject value) + { + dataObject.set(path, value); + } + + public static void setChar(DataObject dataObject, String path, char value) + { + Property property = dataObject.getType().getProperty(path); + if (property != null) + { + dataObject.set(property, DataObjectUtil.getSetValue(property, value)); + } + else + { + DataObjectUtil.Accessor accessor = DataObjectUtil.Accessor.create((EObject)dataObject, path); + accessor.setAndRecyle(DataObjectUtil.getSetValue(accessor.getProperty(), value)); + } + } + + public static void setBytes(DataObject dataObject, String path, byte[] value) + { + Property property = dataObject.getType().getProperty(path); + if (property != null) + { + dataObject.set(property, DataObjectUtil.getSetValue(property, value)); + } + else + { + DataObjectUtil.Accessor accessor = DataObjectUtil.Accessor.create((EObject)dataObject, path); + accessor.setAndRecyle(DataObjectUtil.getSetValue(accessor.getProperty(), value)); + } + } + + public static void setByte(DataObject dataObject, String path, byte value) + { + Property property = dataObject.getType().getProperty(path); + if (property != null) + { + dataObject.set(property, DataObjectUtil.getSetValue(property, value)); + } + else + { + DataObjectUtil.Accessor accessor = DataObjectUtil.Accessor.create((EObject)dataObject, path); + accessor.setAndRecyle(DataObjectUtil.getSetValue(accessor.getProperty(), value)); + } + } + + public static void setBoolean(DataObject dataObject, String path, boolean value) + { + Property property = dataObject.getType().getProperty(path); + if (property != null) + { + dataObject.set(property, DataObjectUtil.getSetValue(property, value)); + } + else + { + DataObjectUtil.Accessor accessor = DataObjectUtil.Accessor.create((EObject)dataObject, path); + accessor.setAndRecyle(DataObjectUtil.getSetValue(accessor.getProperty(), value)); + } + } + + public static void setBigInteger(DataObject dataObject, String path, BigInteger value) + { + Property property = dataObject.getType().getProperty(path); + if (property != null) + { + dataObject.set(property, DataObjectUtil.getSetValue(property, value)); + } + else + { + DataObjectUtil.Accessor accessor = DataObjectUtil.Accessor.create((EObject)dataObject, path); + accessor.setAndRecyle(DataObjectUtil.getSetValue(accessor.getProperty(), value)); + } + } + + public static void setBigDecimal(DataObject dataObject, String path, BigDecimal value) + { + Property property = dataObject.getType().getProperty(path); + if (property != null) + { + dataObject.set(property, DataObjectUtil.getSetValue(property, value)); + } + else + { + DataObjectUtil.Accessor accessor = DataObjectUtil.Accessor.create((EObject)dataObject, path); + accessor.setAndRecyle(DataObjectUtil.getSetValue(accessor.getProperty(), value)); + } + } + + public static DataGraph getDataGraph(DataObject dataObject) + { + Resource resource = ((EObject)dataObject).eResource(); + if (resource != null) + { + ResourceSet resourceSet = resource.getResourceSet(); + if (resourceSet != null) + { + return (DataGraphImpl)EcoreUtil.getAdapter(resourceSet.eAdapters(), DataGraph.class); + } + } + return null; + } + + public static ChangeSummary getChangeSummary(DataObject dataObject) + { + DataGraph dataGraph = getDataGraph(dataObject); + if (dataGraph != null) + { + return dataGraph.getChangeSummary(); + } + else + { + for (DataObject csDataObject = dataObject; csDataObject != null; csDataObject = csDataObject.getContainer()) + { + Property csp = ((ClassImpl)csDataObject.getType()).getChangeSummaryProperty(); + if (csp != null) return (ChangeSummary)csDataObject.get(csp); + } + } + return null; + } + + public static void unset(DataObject dataObject, String path) + { + Property property = dataObject.getType().getProperty(path); + if (property != null) + { + dataObject.unset(property); + } + else + { + DataObjectUtil.Accessor.create((EObject)dataObject, path).unsetAndRecyle(); + } + } + + public static boolean isSet(DataObject dataObject, String path) + { + Property property = dataObject.getType().getProperty(path); + if (property != null) + { + return dataObject.isSet(property); + } + else + { + return DataObjectUtil.Accessor.create( + (EObject)dataObject, path).isSetAndRecyle(); + } + } + + public static void set(DataObject dataObject, String path, Object value) + { + Property property = dataObject.getType().getProperty(path); + if (property != null) + { + dataObject.set(property, value); + } + else + { + DataObjectUtil.Accessor.create( + (EObject)dataObject, path, value).setAndRecyle(value); + } + } + + public static Object get(DataObject dataObject, String path) + { + Property property = dataObject.getType().getProperty(path); + if (property != null) { + return dataObject.get(property); + } else { + return Accessor.create((EObject)dataObject, path).getAndRecyle(); + } + } + + public static BigDecimal getBigDecimal(Object value) + { + if (value instanceof BigDecimal) + { + return (BigDecimal)value; + } + + if (value instanceof BigInteger) + { + return new BigDecimal((BigInteger)value); + } + + if (value instanceof Long) + { + return new BigDecimal(((Long)value).longValue()); + } + + if (value instanceof Number) + { + return new BigDecimal(((Number)value).doubleValue()); + } + + if (value instanceof String) + { + return new BigDecimal((String)value); + } + + if (value == null) + { + return null; + } + + throw new ClassCastException("The value of type '" + value.getClass().getName() + "' cannot be converted to BigDecimal"); + } + + public static Object getSetValue(Property property, BigDecimal value) + { + EStructuralFeature eStructuralFeature = (EStructuralFeature)property; + EClassifier eType = eStructuralFeature.getEType(); + if (value == null) + { + return eType.getDefaultValue(); + } + + String name = eType.getInstanceClassName(); + if (name == "java.math.BigDecimal") + { + return value; + } + + if (name == "java.math.BigInteger") + { + return value.toBigInteger(); + } + + if (name == "java.lang.Byte" || name == "byte") + { + return new Byte(value.byteValue()); + } + + if (name == "java.lang.Double" || name == "double") + { + return new Double(value.doubleValue()); + } + + if (name == "java.lang.Float" || name == "float") + { + return new Float(value.floatValue()); + } + + if (name == "java.lang.Integer" || name == "int") + { + return new Integer(value.intValue()); + } + + if (name == "java.lang.Long" || name == "long") + { + return new Long(value.longValue()); + } + + if (name == "java.lang.Short" || name == "short") + { + return new Short(value.shortValue()); + } + + if (name == "java.lang.String") + { + return String.valueOf(value); + } + + //Instead of throwing an ClassCastException we will pass the value to the property + return value; + } + + public static BigInteger getBigInteger(Object value) + { + if (value instanceof BigInteger) + { + return (BigInteger)value; + } + + if (value instanceof BigDecimal) + { + return ((BigDecimal)value).toBigInteger(); + } + + if (value instanceof Number) + { + return BigInteger.valueOf(((Number)value).longValue()); + } + + if (value instanceof String) + { + return new BigInteger((String)value); + } + + if (value instanceof byte[]) + { + return new BigInteger((byte[])value); + } + + if (value == null) + { + return null; + } + + throw new ClassCastException("The value of type '" + value.getClass().getName() + "' cannot be converted to BigInteger"); + } + + public static Object getSetValue(Property property, BigInteger value) + { + EStructuralFeature eStructuralFeature = (EStructuralFeature)property; + EClassifier eType = eStructuralFeature.getEType(); + if (value == null) + { + return eType.getDefaultValue(); + } + + String name = eType.getInstanceClassName(); + if (name == "java.math.BigInteger") + { + return value; + } + + if (name == "java.math.BigDecimal") + { + return new BigDecimal(value); + } + + if (name == "java.lang.Byte" || name == "byte") + { + return new Byte(value.byteValue()); + } + + if (name == "java.lang.Double" || name == "double") + { + return new Double(value.doubleValue()); + } + + if (name == "java.lang.Float" || name == "float") + { + return new Float(value.floatValue()); + } + + if (name == "java.lang.Integer" || name == "int") + { + return new Integer(value.intValue()); + } + + if (name == "java.lang.Long" || name == "long") + { + return new Long(value.longValue()); + } + + if (name == "java.lang.Short" || name == "short") + { + return new Short(value.shortValue()); + } + + if (name == "java.lang.String") + { + return String.valueOf(value); + } + + if (name == "byte[]") + { + return value.toByteArray(); + } + + //Instead of throwing an ClassCastException we will pass the value to the property + return value; + } + + public static boolean getBoolean(Object value) + { + if (value instanceof Boolean) + { + return ((Boolean)value).booleanValue(); + } + + if (value instanceof String) + { + return Boolean.valueOf((String)value).booleanValue(); + } + + if (value == null) + { + return false; + } + + throw new ClassCastException("The value of type '" + value.getClass().getName() + "' cannot be converted to boolean"); + } + + public static Object getSetValue(Property property, boolean value) + { + EStructuralFeature eStructuralFeature = (EStructuralFeature)property; + String name = eStructuralFeature.getEType().getInstanceClassName(); + if (name == "java.lang.Boolean" || name == "boolean") + { + return value ? Boolean.TRUE : Boolean.FALSE; + } + + if (name == "java.lang.String") + { + return String.valueOf(value); + } + + //Instead of throwing an ClassCastException we will pass the value to the property + return value ? Boolean.TRUE : Boolean.FALSE; + } + + public static byte getByte(Object value) + { + if (value instanceof Number) + { + return ((Number)value).byteValue(); + } + + if (value instanceof String) + { + return Byte.parseByte((String)value); + } + + if (value == null) + { + return 0; + } + + throw new ClassCastException("The value of type '" + value.getClass().getName() + "' cannot be converted to byte"); + } + + public static Object getSetValue(Property property, byte value) + { + EStructuralFeature eStructuralFeature = (EStructuralFeature)property; + String name = eStructuralFeature.getEType().getInstanceClassName(); + if (name == "java.lang.Byte" || name == "byte") + { + return new Byte(value); + } + + if (name == "java.lang.Double" || name == "double") + { + return new Double(value); + } + + if (name == "java.lang.Float" || name == "float") + { + return new Float(value); + } + + if (name == "java.lang.Integer" || name == "int") + { + return new Integer(value); + } + + if (name == "java.lang.Long" || name == "long") + { + return new Long(value); + } + + if (name == "java.lang.Short" || name == "short") + { + return new Short(value); + } + + if (name == "java.math.BigDecimal") + { + return getBigDecimal(new Byte(value)); + } + + if (name == "java.math.BigInteger") + { + return getBigInteger(new Byte(value)); + } + + if (name == "java.lang.String") + { + return String.valueOf(value); + } + + //Instead of throwing an ClassCastException we will pass the value to the property + return new Byte(value); + } + + public static byte[] getBytes(Object value) + { + if (value instanceof byte[]) + { + return (byte[])value; + } + + if (value instanceof BigInteger) + { + return ((BigInteger)value).toByteArray(); + } + + if (value == null) + { + return null; + } + + throw new ClassCastException("The value of type '" + value.getClass().getName() + "' cannot be converted to byte array"); + } + + public static Object getSetValue(Property property, byte[] value) + { + EStructuralFeature eStructuralFeature = (EStructuralFeature)property; + EClassifier eType = eStructuralFeature.getEType(); + if (value == null) + { + return eType.getDefaultValue(); + } + + String name = eType.getInstanceClassName(); + if (name == "byte[]") + { + return value; + } + + if (name == "java.math.BigInteger") + { + return new BigInteger(value); + } + + //Instead of throwing an ClassCastException we will pass the value to the property + return value; + } + + public static char getChar(Object value) + { + if (value instanceof Character) + { + return ((Character)value).charValue(); + } + + if (value instanceof String) + { + return ((String)value).charAt(0); + } + + if (value == null) + { + return 0; + } + + throw new ClassCastException("The value of type '" + value.getClass().getName() + "' cannot be converted to char"); + } + + public static Object getSetValue(Property property, char value) + { + EStructuralFeature eStructuralFeature = (EStructuralFeature)property; + String name = eStructuralFeature.getEType().getInstanceClassName(); + if (name == "java.lang.Character" || name == "char") + { + return new Character(value); + } + + if (name == "java.lang.String") + { + return String.valueOf(value); + } + + //Instead of throwing an ClassCastException we will pass the value to the property + return new Character(value); + } + + public static Date getDate(Object value) + { + if (value instanceof String) { + return DataHelper.INSTANCE.toDate((String)value); + } + + //if (value instanceof XMLCalendar) + //{ + //return ((XMLCalendar)value).getDate(); + //} + + if (value instanceof Date) + { + return (Date)value; + } + + if (value instanceof Long) + { + return new Date(((Long)value).longValue()); + } + + if (value == null) + { + return null; + } + + throw new ClassCastException("The value of type '" + value.getClass().getName() + "' cannot be converted to Date"); + } + + public static Object getSetValue(Property property, Date value) + { + EStructuralFeature eStructuralFeature = (EStructuralFeature)property; + EClassifier eType = eStructuralFeature.getEType(); + if (value == null) + { + return eType.getDefaultValue(); + } + + String name = eType.getInstanceClassName(); + + if (name == "java.lang.String") + { + String typeName = getDateTypeName((EDataType)eType); + if ("DateTime".equals(typeName)) { + return DataHelper.INSTANCE.toDateTime(value); + } + else if ("Day".equals(typeName)) { + return DataHelper.INSTANCE.toDay(value); + } + else if ("Duration".equals(typeName)) { + return DataHelper.INSTANCE.toDuration(value); + } + else if ("Month".equals(typeName)) { + return DataHelper.INSTANCE.toMonth(value); + } + else if ("MonthDay".equals(typeName)) { + return DataHelper.INSTANCE.toMonthDay(value); + } + else if ("Time".equals(typeName)) { + return DataHelper.INSTANCE.toTime(value); + } + else if ("Year".equals(typeName)) { + return DataHelper.INSTANCE.toYear(value); + } + else if ("YearMonth".equals(typeName)) { + return DataHelper.INSTANCE.toYearMonth(value); + } + else if ("YearMonthDay".equals(typeName)) { + return DataHelper.INSTANCE.toYearMonthDay(value); + } + else if ("String".equals(typeName)) + { + return DataHelper.INSTANCE.toDateTime(value); + } + + // Instead of throwing an ClassCastException we will pass the value to the property + return value; + } + + //if (name == "java.util.Date") + //{ + //return new XMLCalendar(value, XMLCalendar.DATE); + //} + + if (name == "java.lang.Long" || name == "long") + { + return new Long(value.getTime()); + } + + // Instead of throwing an ClassCastException we will pass the value to the property + return value; + } + + protected static String getDateTypeName(EDataType eDataType) + { + String name = eDataType.getName(); + if (("DateTime".equals(name)) || + ("Day".equals(name)) || + ("Duration".equals(name)) || + ("Month".equals(name)) || + ("MonthDay".equals(name)) || + ("Time".equals(name)) || + ("Year".equals(name)) || + ("YearMonth".equals(name)) || + ("YearMonthDay".equals(name)) || + ("String".equals(name))) + { + return name; + } + + EDataType baseType = ExtendedMetaData.INSTANCE.getBaseType(eDataType); + if (baseType != null) + { + return getDateTypeName(baseType); + } + + List memberTypes = ExtendedMetaData.INSTANCE.getMemberTypes(eDataType); + if (!memberTypes.isEmpty()) + { + for (int i = 0, size = memberTypes.size(); i < size; ++i) + { + EDataType memberType = (EDataType)memberTypes.get(i); + String memberTypeName = getDateTypeName(memberType); + if (("DateTime".equals(memberTypeName)) || + ("Day".equals(memberTypeName)) || + ("Duration".equals(memberTypeName)) || + ("Month".equals(memberTypeName)) || + ("MonthDay".equals(memberTypeName)) || + ("Time".equals(memberTypeName)) || + ("Year".equals(memberTypeName)) || + ("YearMonth".equals(memberTypeName)) || + ("YearMonthDay".equals(memberTypeName)) || + ("String".equals(memberTypeName))) + { + return memberTypeName; + } + } + } + + return ""; + } + + public static double getDouble(Object value) + { + if (value instanceof Number) + { + return ((Number)value).doubleValue(); + } + + if (value instanceof String) + { + return Double.parseDouble((String)value); + } + + if (value == null) + { + return 0; + } + + throw new ClassCastException("The value of type '" + value.getClass().getName() + "' cannot be converted to double"); + } + + public static Object getSetValue(Property property, double value) + { + EStructuralFeature eStructuralFeature = (EStructuralFeature)property; + String name = eStructuralFeature.getEType().getInstanceClassName(); + if (name == "java.lang.Byte" || name == "byte") + { + return new Byte((byte)value); + } + + if (name == "java.lang.Double" || name == "double") + { + return new Double(value); + } + + if (name == "java.lang.Float" || name == "float") + { + return new Float(value); + } + + if (name == "java.lang.Integer" || name == "int") + { + return new Integer((int)value); + } + + if (name == "java.lang.Long" || name == "long") + { + return new Long((long)value); + } + + if (name == "java.lang.Short" || name == "short") + { + return new Short((short)value); + } + + if (name == "java.math.BigDecimal") + { + return getBigDecimal(new Double(value)); + } + + if (name == "java.math.BigInteger") + { + return getBigInteger(new Double(value)); + } + + if (name == "java.lang.String") + { + return String.valueOf(value); + } + + //Instead of throwing an ClassCastException we will pass the value to the property + return new Double(value); + } + + public static float getFloat(Object value) + { + if (value instanceof Number) + { + return ((Number)value).floatValue(); + } + + if (value instanceof String) + { + return Float.parseFloat((String)value); + } + + if (value == null) + { + return 0; + } + + throw new ClassCastException("The value of type '" + value.getClass().getName() + "' cannot be converted to float"); + } + + public static Object getSetValue(Property property, float value) + { + EStructuralFeature eStructuralFeature = (EStructuralFeature)property; + String name = eStructuralFeature.getEType().getInstanceClassName(); + if (name == "java.lang.Byte" || name == "byte") + { + return new Byte((byte)value); + } + + if (name == "java.lang.Double" || name == "double") + { + return new Double(value); + } + + if (name == "java.lang.Float" || name == "float") + { + return new Float(value); + } + + if (name == "java.lang.Integer" || name == "int") + { + return new Integer((int)value); + } + + if (name == "java.lang.Long" || name == "long") + { + return new Long((long)value); + } + + if (name == "java.lang.Short" || name == "short") + { + return new Short((short)value); + } + + if (name == "java.math.BigDecimal") + { + return getBigDecimal(new Float(value)); + } + + if (name == "java.math.BigInteger") + { + return getBigInteger(new Float(value)); + } + + if (name == "java.lang.String") + { + return String.valueOf(value); + } + + // Instead of throwing an ClassCastException we will pass the value to the property + return new Float(value); + } + + public static int getInt(Object value) + { + if (value instanceof Number) + { + return ((Number)value).intValue(); + } + + if (value instanceof String) + { + return Integer.parseInt((String)value); + } + + if (value == null) + { + return 0; + } + + throw new ClassCastException("The value of type '" + value.getClass().getName() + "' cannot be converted to int"); + } + + public static Object getSetValue(Property property, int value) + { + EStructuralFeature eStructuralFeature = (EStructuralFeature)property; + String name = eStructuralFeature.getEType().getInstanceClassName(); + if (name == "java.lang.Byte" || name == "byte") + { + return new Byte((byte)value); + } + + if (name == "java.lang.Double" || name == "double") + { + return new Double(value); + } + + if (name == "java.lang.Float" || name == "float") + { + return new Float(value); + } + + if (name == "java.lang.Integer" || name == "int") + { + return new Integer(value); + } + + if (name == "java.lang.Long" || name == "long") + { + return new Long(value); + } + + if (name == "java.lang.Short" || name == "short") + { + return new Short((short)value); + } + + if (name == "java.math.BigDecimal") + { + return getBigDecimal(new Integer(value)); + } + + if (name == "java.math.BigInteger") + { + return getBigInteger(new Integer(value)); + } + + if (name == "java.lang.String") + { + return String.valueOf(value); + } + + // Instead of throwing an ClassCastException we will pass the value to the property + return new Integer(value); + } + + public static long getLong(Object value) + { + if (value instanceof Number) + { + return ((Number)value).longValue(); + } + + if (value instanceof String) + { + return Long.parseLong((String)value); + } + + if (value instanceof Date) + { + return ((Date)value).getTime(); + } + + if (value == null) + { + return 0; + } + + throw new ClassCastException("The value of type '" + value.getClass().getName() + "' cannot be converted to long"); + } + + public static Object getSetValue(Property property, long value) + { + EStructuralFeature eStructuralFeature = (EStructuralFeature)property; + String name = eStructuralFeature.getEType().getInstanceClassName(); + if (name == "java.lang.Byte" || name == "byte") + { + return new Byte((byte)value); + } + + if (name == "java.lang.Double" || name == "double") + { + return new Double(value); + } + + if (name == "java.lang.Float" || name == "float") + { + return new Float(value); + } + + if (name == "java.lang.Integer" || name == "int") + { + return new Integer((int)value); + } + + if (name == "java.lang.Long" || name == "long") + { + return new Long(value); + } + + if (name == "java.lang.Short" || name == "short") + { + return new Short((short)value); + } + + if (name == "java.math.BigDecimal") + { + return getBigDecimal(new Long(value)); + } + + if (name == "java.math.BigInteger") + { + return getBigInteger(new Long(value)); + } + + if (name == "java.lang.String") + { + return String.valueOf(value); + } + + if (name == "java.util.Date") + { + return new Date(value); + } + + // Instead of throwing an ClassCastException we will pass the value to the property + return new Long(value); + } + + public static short getShort(Object value) + { + if (value instanceof Number) + { + return ((Number)value).shortValue(); + } + + if (value instanceof String) + { + return Short.parseShort((String)value); + } + + if (value == null) + { + return 0; + } + + throw new ClassCastException("The value of type '" + value.getClass().getName() + "' cannot be converted to short"); + } + + public static Object getSetValue(Property property, short value) + { + EStructuralFeature eStructuralFeature = (EStructuralFeature)property; + String name = eStructuralFeature.getEType().getInstanceClassName(); + if (name == "java.lang.Byte" || name == "byte") + { + return new Byte((byte)value); + } + + if (name == "java.lang.Double" || name == "double") + { + return new Double(value); + } + + if (name == "java.lang.Float" || name == "float") + { + return new Float(value); + } + + if (name == "java.lang.Integer" || name == "int") + { + return new Integer(value); + } + + if (name == "java.lang.Long" || name == "long") + { + return new Long(value); + } + + if (name == "java.lang.Short" || name == "short") + { + return new Short(value); + } + + if (name == "java.math.BigDecimal") + { + return getBigDecimal(new Short(value)); + } + + if (name == "java.math.BigInteger") + { + return getBigInteger(new Short(value)); + } + + if (name == "java.lang.String") + { + return String.valueOf(value); + } + + // Instead of throwing an ClassCastException we will pass the value to the property + return new Short(value); + } + + public static String getString(Object value) + { + if (value instanceof String) + { + return (String)value; + } + + if (value instanceof Number || value instanceof Boolean || value instanceof Character) + { + return String.valueOf(value); + } + + if (value instanceof Date) + { + SimpleDateFormat sdf = new SimpleDateFormat("yyyy'-'MM'-'dd'T'H':'mm':'ss.S'Z'"); + sdf.setTimeZone(TimeZone.getTimeZone("GMT")); + return sdf.format((Date) value); + } + + if (value instanceof byte[]) { + return XMLTypeFactory.eINSTANCE.convertHexBinary((byte[])value); + } + + if (value == null) + { + return null; + } + + throw new ClassCastException("The value of type '" + value.getClass().getName() + "' cannot be converted to String"); + } + + public static Object getSetValue(Property property, String value) + { + EStructuralFeature eStructuralFeature = (EStructuralFeature)property; + EClassifier eType = eStructuralFeature.getEType(); + if (value == null) + { + return eType.getDefaultValue(); + } + + String name = eType.getInstanceClassName(); + if (name == "java.lang.String") + { + return value; + } + + if (name == "java.lang.Byte" || name == "byte") + { + return Byte.valueOf(value); + } + + if (name == "java.util.Date") + { + return DataHelper.INSTANCE.toDate(value); + } + + if (name == "java.lang.Double" || name == "double" || name == "java.lang.Number") + { + return Double.valueOf(value); + } + + if (name == "java.lang.Float" || name == "float") + { + return new Float(value); + } + + if (name == "java.lang.Integer" || name == "int") + { + return Integer.valueOf(value); + } + + if (name == "java.lang.Long" || name == "long") + { + return Long.valueOf(value); + } + + if (name == "java.lang.Short" || name == "short") + { + return Short.valueOf(value); + } + + if (name == "java.lang.Character" || name == "char") + { + return new Character(value.charAt(0)); + } + + if (name == "java.math.BigDecimal") + { + return getBigDecimal(value); + } + + if (name == "java.math.BigInteger") + { + return getBigInteger(value); + } + + if (name == "java.lang.Boolean" || name == "boolean") + { + return Boolean.valueOf(value); + } + + // Instead of throwing an ClassCastException we will pass the value to the property + return value; + } + + public static EStructuralFeature getOpenFeature(EObject eObject, int featureID) + { + EClass eClass = eObject.eClass(); + int openFeatureCount = featureID - eClass.getFeatureCount(); + Set openFeatureSet = new HashSet(); + for (int i = 0, count = eClass.getEAllStructuralFeatures().size(); i < count; ++i) + { + EStructuralFeature eStructuralFeature = eClass.getEStructuralFeature(i); + if (!eStructuralFeature.isDerived() && FeatureMapUtil.isFeatureMap(eStructuralFeature)) + { + List features = (List)eObject.eGet(eStructuralFeature); + for (int j = 0, size = features.size(); j < size; ++j) + { + FeatureMap.Entry entry = (FeatureMap.Entry)features.get(j); + EStructuralFeature entryFeature = entry.getEStructuralFeature(); + if (openFeatureSet.add(entryFeature)) + { + if (--openFeatureCount < 0) return entryFeature; + } + } + } + } + throw new IndexOutOfBoundsException(); + } + + public static List getAliasNames(EStructuralFeature eStructuralFeature) + { + List list = SDOExtendedMetaData.INSTANCE.getAliasNames(eStructuralFeature); + if (list == null) { + list = new ArrayList(); + } + return list; + } + + public static List getAliasNames(EClassifier eClassifier) + { + List list = SDOExtendedMetaData.INSTANCE.getAliasNames(eClassifier); + if (list == null) { + list = new ArrayList(); + } + return list; + } + + protected static Property demandOpenProperty(Type type, String name, Object value, boolean isSequence) + { + TypeHelper typeHelper = TypeHelper.INSTANCE; //FB TODO: what TypeHelper to use? + + String uri = type.getURI() + "/" + type.getName(); // unique URI for open content properties on instances of the type + Property property = typeHelper.getOpenContentProperty(uri, name); + if (property != null) + return property; + + boolean isMany = isSequence; + boolean isContainment = false; + Type propertyType; + + if (value instanceof DataObject) + { + DataObject dataObject = (DataObject)value; + propertyType = dataObject.getType(); + isContainment = dataObject.getContainer() == null; + } + else if (value instanceof List && !((List)value).isEmpty()) + { + Object listValue = ((List)value).get(0); //TODO: get common base class if all values are not the same type? + if (listValue instanceof DataObject) + propertyType = ((DataObject)listValue).getType(); + else + propertyType = typeHelper.getType(listValue.getClass()); + isMany = true; + } + else + { + propertyType = typeHelper.getType(value.getClass()); + } + if (propertyType == null) + { + propertyType = ((ModelFactoryImpl)ModelFactory.INSTANCE).getObject(); + } + + Property newProperty = SDOUtil.createGlobalProperty(TypeHelper.INSTANCE, uri, name, propertyType); + if (isMany) + SDOUtil.setMany(newProperty, isMany); + if (isContainment) + SDOUtil.setContainment(newProperty, isContainment); + + return newProperty; + } + + /** + * Process the default EMF path and minimal XPath syntax. + * This design is still under review and construction. + * + * Syntax: + * + *<pre> + * path = /? (step '/')* step + * step = feature + * | feature '.' index_from_0 + * | feature '[' index_from_1 ']' + * | reference '[' attribute '=' value ']' + * | .. + * | '@' step + *</pre> + * + * feature = the name of an attribute or reference + * attribute = the name of an attribute + * reference = the name of a reference + * index = positive integer + * value = the string value of an attribute + * leading / begins at the root + * .. is containing object + * + * features must be multi-valued to use '.' and '[' operations. + * Only the last step may have an attribute as the feature. + */ + public static final class Accessor //TODO rewrite this using SDO APIs + { + /** + * Creates an accessor for the path of the object. + */ + public static Accessor create(EObject eObject, String path) + { + return create(eObject, path, null); + } + + public static Accessor create(EObject eObject, String path, Object value) + { + Accessor result = pool.get(); + result.init(eObject, path, value); + return result; + } + + /** + * Only the get and recycle methods should be call; they are the only synchronized methods. + */ + protected static class Pool extends BasicEList + { + protected Accessor[] accessors; + + public Pool() + { + super(10); + } + + protected Object[] newData(int capacity) + { + return accessors = new Accessor [capacity]; + } + + /** + * Returns a recyled instance or a new instance. + */ + public synchronized Accessor get() + { + if (size > 0) + { + return accessors[--size]; + } + else + { + return new Accessor(); + } + } + + /** Safely gives the accessor back for recycled use. + */ + public synchronized void recycle(Accessor accessor) + { + int minimumCapacity = size + 1; + if (minimumCapacity > data.length) + { + grow(minimumCapacity); + } + accessors[size++] = accessor; + } + } + + /** + * A static thread safe pool of Accessors. + */ + static final Pool pool = new Pool(); + + protected static final int NO_INDEX = -1; + + protected EObject eObject; + protected Object value; + + protected EStructuralFeature feature; + + protected int index; + + RuntimeException runtimeException; + + protected Accessor() + { + } + + //protected Accessor(EObject eObject, String path) + //{ + // init(eObject, path); + //} + + protected void init(EObject eObject, String path, Object value) + { + this.eObject = eObject; + this.value = value; + runtimeException = null; + + // This should only be called with a path right now. + // + //feature = getType(eObject).getProperty(path).getEStructuralFeature(); + //if (feature == null) + { + process(path); + } + //else + { + //index = NO_INDEX; + } + } + + public Object get() + { + if (feature == null) + { + return eObject; + } + else + { + Object value = eObject.eGet(feature, true); + if (index >= 0) + { + value = ((List)value).get(index); + if (value instanceof FeatureMap.Entry) + { + value = ((FeatureMap.Entry)value).getValue(); + } + } + else if (FeatureMapUtil.isFeatureMap(feature)) + { + value = new BasicSequence((FeatureMap.Internal)value); + } + return value; + } + } + + public Object getAndRecyle() + { + Object result = get(); + pool.recycle(this); + return result; + } + + protected final void assertSuccessfulProcess() + { + if (runtimeException != null) + throw runtimeException; + } + + public void set(Object newValue) + { + assertSuccessfulProcess(); + if (index >= 0) + { + List list = (List)eObject.eGet(feature, true); + list.set(index, newValue); + } + else + { + // EATM newValue = string2Enum(feature, newValue); + eObject.eSet(feature, newValue); + } + } + + public void setAndRecyle(Object newValue) + { + set(newValue); + pool.recycle(this); + } + + public boolean isSet() + { + return feature != null && eObject.eIsSet(feature); + } + + public boolean isSetAndRecyle() + { + boolean result = isSet(); + pool.recycle(this); + return result; + } + + public void unset() + { + assertSuccessfulProcess(); + eObject.eUnset(feature); + } + + public void unsetAndRecyle() + { + unset(); + pool.recycle(this); + } + + public void recycle() + { + pool.recycle(this); + } + + public EObject getEObject() + { + return eObject; + } + + protected void setEObject(EObject eObject) + { + this.eObject = eObject; + feature = null; + index = NO_INDEX; + } + + public EStructuralFeature getEStructuralFeature() + { + return feature; + } + + public Property getProperty() + { + assertSuccessfulProcess(); + return (Property)feature; + } + + protected void setFeatureName(String name) + { + if (name != null) + { + feature = (EStructuralFeature)((DataObject)eObject).getInstanceProperty(name); + if (feature == null) + { + int index = name.lastIndexOf('.'); + if (index == -1) + { + Type type = (Type)eObject.eClass(); + if (value != null && type.isOpen()) + { + feature = (EStructuralFeature)demandOpenProperty(type, name, value, false); + this.index = NO_INDEX; + return; + } + runtimeException = new IllegalArgumentException("Class '" + eObject.eClass().getName() + "' does not have a feature named '" + name + '\''); + } + else + { + int propertyNameEnd = index; + try + { + index = Integer.parseInt(name.substring(++index)); + // NumberFormatException may be thrown + String propertyName = name.substring(0, propertyNameEnd); + feature = (EStructuralFeature)((DataObject)eObject).getInstanceProperty(propertyName); + if (feature != null) + { + setIndex(index); + return; + } + runtimeException = new IllegalArgumentException("Class '" + eObject.eClass().getName() + "' does not have a feature named '" + name + "' or '" + propertyName + '\''); + } + catch(NumberFormatException eNumberFormat) + { + runtimeException = eNumberFormat; + } + } + setEObject(null); + } + } + else + { + feature = null; + } + index = NO_INDEX; + } + + protected int getIndex() + { + return index; + } + + /* + * calling constraint, this method is not to be used for semantic of setting index to NO_INDEX + */ + protected void setIndex(int index) + { + if (index < 0) { + // The index value should not be less than 0. + runtimeException = new IndexOutOfBoundsException("Index value is too low"); + setEObject(null); + return; + } + if (!FeatureMapUtil.isMany(eObject, feature)) + { + runtimeException = new IndexOutOfBoundsException("Index applies only to multi-valued features"); + setEObject(null); + return; + } + int size = ((List) eObject.eGet(feature)).size(); + if (index >= size) + { + // The index value should be less than size. + runtimeException = new IndexOutOfBoundsException("Index value should have been less than " + size); + setEObject(null); + } + this.index = index; + } + + protected void process(String pathString) + { + TokenList tokens = new TokenList(pathString.toCharArray()); + String token; + int size = tokens.size(); + int x = 0; + + if ("/".equals(tokens.peek(0))) + { + setEObject(EcoreUtil.getRootContainer(eObject)); + x++; + } + + for (; x < size; x++) + { + token = tokens.peek(x); + char c = token.charAt(0); + if ('/' == c) + { + setEObject((EObject)get()); + if (eObject == null) break; + } + else if ("..".equals(token)) + { + setEObject(eObject.eContainer()); + if (eObject == null) break; + } + else if ('[' == c) + { + x++; // skip [ + token = tokens.peek(x); // name or index + char following = tokens.peek(x + 1).charAt(0); + if ('=' != following) + { + try + { + setIndex(Integer.parseInt(token) - 1); + // runtimeException may be recorded + } + catch(NumberFormatException eNumberFormat) + { + runtimeException = eNumberFormat; + setEObject(null); + break; + } + if (runtimeException != null) + break; + x++; // skip ] + } + else + { + x++; // done name + x++; // skip = + String attributeValue = tokens.peek(x); // value + if ("\"".equals(attributeValue)) + { + x++; // skip " + attributeValue = tokens.peek(++x); + } + x++; // skip ] + int index = matchingIndex((List)get(), token, attributeValue); + if (index < 0) + { + setEObject(null); + break; + } + else + { + setIndex(index); + } + } + } + else if ('@' == c) + { + // skip @ + } + else + { + setFeatureName(token); + if (eObject == null) break; + } + } + } + + protected static int matchingIndex(List dataObjects, String attributeName, String attributeValue) + { + for (int i = 0, size = dataObjects.size(); i < size; i++) + { + DataObject dataObject = (DataObject)dataObjects.get(i); + Property property = getInstanceProperty(dataObject, attributeName); + if (property != null) + { + Object test = dataObject.get(property); + if (test != null) + { + String testString = EcoreUtil.convertToString((EDataType)property.getType(), test); + if (attributeValue.equals(testString)) + { + return i; + } + } + } + } + return -1; + } + + protected static class TokenList extends BasicEList + { + public TokenList(char[] path) + { + super(4); + + int pathLength = path.length; + StringBuffer token = new StringBuffer(); + char cPrev; + char c = 0; + char cNext; + char stringConstant = 0; + for (int pos = 0; pos < pathLength; pos++) + { + cPrev = c; + c = path[pos]; + cNext = pos < pathLength - 1 ? path[pos + 1] : 0; + + if (stringConstant != 0) + { + if (c == stringConstant) + { + endToken(token, true); + stringConstant = 0; + } + else + { + token.append(c); + } + } + else + { + switch (c) + { + case ' ': + case 0xA: + case 0xD: + case 0x9: + if (cPrev != ' ') + { + endToken(token, false); + } + c = ' '; + break; + + case '"': + case '\'': + endToken(token, false); + stringConstant = c; + break; + + // double or single tokens + case '/': + case ':': + if (cPrev != c) + { + endToken(token, false); + } + token.append(c); + if (cNext != c) + { + endToken(token, false); + } + break; + + // double token (..) + case '.': + if (cNext == '.') + endToken(token, false); + token.append(c); + if (cPrev == '.') + endToken(token, false); + break; + + // single tokens + case '*': + case '@': + case '[': + case ']': + case '(': + case ')': + case '|': + endToken(token, false); + add(String.valueOf(c)); + break; + + // TODO: < > <= >= + - != + case '!': + endToken(token, false); + token.append(c); + break; + + case '=': + endToken(token, false); + add(String.valueOf(c)); + break; + + default: + token.append(c); + } + } + } + endToken(token, false); + } + + public String peek() + { + return size > 0 ? (String)data[0] : " "; + } + + public String peek(int index) + { + return index < size ? (String)data[index] : " "; + } + + public TokenList pop() + { + remove(0); + return this; + } + + public TokenList pop(int count) + { + while (count-- > 0) + { + remove(count); + } + return this; + } + + protected void endToken(StringBuffer token, boolean includeEmpty) + { + if (includeEmpty || token.length() > 0) + { + add(token.toString()); + } + token.setLength(0); + } + + protected boolean canContainNull() + { + return false; + } + + protected Object[] newData(int capacity) + { + return new String [capacity]; + } + } + + public String toString() + { + StringBuffer result = new StringBuffer("Accessor (object:"); + result.append(eObject == null ? "null" : eObject.toString()); + result.append(", feature:"); + result.append(feature == null ? "null" : feature.getName()); + result.append(", index:"); + result.append(index); + result.append(")"); + return result.toString(); + } + } + + public static Type getType(DataObject dataObject, String namespaceURI, String typeName) + { + DataGraph dataGraph = dataObject.getDataGraph(); + if (dataGraph != null) + { + return dataGraph.getType(namespaceURI, typeName); + } + else + { + //TODO think about where else to find the type + return TypeHelper.INSTANCE.getType(namespaceURI, typeName); + } + } + + public static Property getInstanceProperty(DataObject dataObject, String propertyName) + { + ClassImpl type = (ClassImpl)dataObject.getType(); + Property property = type.getProperty(propertyName); + if (property == null) + { + property = type.getOpenProperty((EObject)dataObject, propertyName); + //throw new IllegalArgumentException("Type '" + dataObject.getType().getName() + "' does not have a property named '" + propertyName + "'"); + } + + return property; + } + + public static Property getProperty(DataObject dataObject, int propertyIndex) + { + List typeProperties = dataObject.getType().getProperties(); + + Property property = propertyIndex < typeProperties.size() ? + (Property)typeProperties.get(propertyIndex) : + (Property)dataObject.getInstanceProperties().get(propertyIndex); + + //FB maybe should catch bad index exception and throw IllegalArgumentException? + return property; + } + + public static Property getContainmentProperty(Property property) + { + if (property.isContainment()) + { + return property; + } + throw new IllegalArgumentException("The property '" + property.getName() + "' of '" + property.getContainingType().getName() + + "' isn't a containment"); + } + + public static DataObject create(Type type) + { + return (DataObject)EcoreUtil.create((EClass)type); + } + + public static ResourceSet createResourceSet() + { + ResourceSet result = new ResourceSetImpl(); + configureResourceSet(result); + return result; + } + + protected static Map registrations; + + protected static Map getRegistrations() + { + if (registrations == null) + { + Map result = new HashMap(); + + Resource.Factory factory = Resource.Factory.Registry.INSTANCE.getFactory(URI.createURI("*.datagraph")); + result.put("datagraph", factory instanceof DataGraphResourceFactoryImpl ? factory : new DataGraphResourceFactoryImpl()); + + factory = Resource.Factory.Registry.INSTANCE.getFactory(URI.createURI("*.ecore")); + result.put("ecore", factory instanceof EcoreResourceFactoryImpl ? factory : new EcoreResourceFactoryImpl()); + + factory = Resource.Factory.Registry.INSTANCE.getFactory(URI.createURI("*.emof")); + result.put("emof", factory instanceof EMOFResourceFactoryImpl ? factory : new EMOFResourceFactoryImpl()); + + factory = Resource.Factory.Registry.INSTANCE.getFactory(URI.createURI("*.xsd")); + result.put("xsd", factory instanceof XSDResourceFactoryImpl ? factory : new XSDResourceFactoryImpl()); + + factory = Resource.Factory.Registry.INSTANCE.getFactory(URI.createURI("*.wsdl")); + result.put("wsdl", factory instanceof XSDResourceFactoryImpl ? factory : new XSDResourceFactoryImpl()); + + factory = Resource.Factory.Registry.INSTANCE.getFactory(URI.createURI("*.*")); + result.put("*", factory instanceof SDOXMLResourceFactoryImpl ? factory : new SDOXMLResourceFactoryImpl()); + + registrations = result; + } + + return registrations; + } + + protected static void configureResourceSet(ResourceSet resourceSet) + { + resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap().putAll(getRegistrations()); +// resourceSet.setURIConverter(new SDOURIConverterImpl()); + } + + public static EClass createDocumentRoot() + { + EClass documentRootEClass = (EClass)SDOFactory.eINSTANCE.createClass(); + documentRootEClass.setName("DocumentRoot"); + ExtendedMetaData.INSTANCE.setName(documentRootEClass, ""); + ExtendedMetaData.INSTANCE.setContentKind(documentRootEClass, ExtendedMetaData.MIXED_CONTENT); + + EAttribute mixed = (EAttribute)SDOFactory.eINSTANCE.createAttribute(); + mixed.setName("mixed"); + mixed.setEType(EcorePackage.eINSTANCE.getEFeatureMapEntry()); + mixed.setUpperBound(EStructuralFeature.UNBOUNDED_MULTIPLICITY); + ExtendedMetaData.INSTANCE.setName(mixed, ":mixed"); + ExtendedMetaData.INSTANCE.setFeatureKind(mixed, ExtendedMetaData.ELEMENT_WILDCARD_FEATURE); + documentRootEClass.getEStructuralFeatures().add(mixed); + + EReference xmlnsPrefixMap = (EReference)SDOFactory.eINSTANCE.createReference(); + xmlnsPrefixMap.setName("xMLNSPrefixMap"); + xmlnsPrefixMap.setEType(EcorePackage.eINSTANCE.getEStringToStringMapEntry()); + xmlnsPrefixMap.setUpperBound(EStructuralFeature.UNBOUNDED_MULTIPLICITY); + xmlnsPrefixMap.setContainment(true); + xmlnsPrefixMap.setTransient(true); + ExtendedMetaData.INSTANCE.setName(xmlnsPrefixMap, "xmlns:prefix"); + ExtendedMetaData.INSTANCE.setFeatureKind(xmlnsPrefixMap, ExtendedMetaData.ATTRIBUTE_FEATURE); + documentRootEClass.getEStructuralFeatures().add(xmlnsPrefixMap); + + EReference xsiSchemaLocation = (EReference)SDOFactory.eINSTANCE.createReference(); + xsiSchemaLocation.setName("xSISchemaLocation"); + xsiSchemaLocation.setEType(EcorePackage.eINSTANCE.getEStringToStringMapEntry()); + xsiSchemaLocation.setUpperBound(EStructuralFeature.UNBOUNDED_MULTIPLICITY); + xsiSchemaLocation.setContainment(true); + xsiSchemaLocation.setTransient(true); + ExtendedMetaData.INSTANCE.setName(xsiSchemaLocation, "xsi:schemaLocation"); + ExtendedMetaData.INSTANCE.setFeatureKind(xsiSchemaLocation, ExtendedMetaData.ATTRIBUTE_FEATURE); + documentRootEClass.getEStructuralFeatures().add(xsiSchemaLocation); + + return documentRootEClass; + } + + /** + * Configure EMF to support the SDO runtime by registering a specialized Ecore factory, SDOEcoreFactory. + * This static initializion must run before any SDO metadata is created or loaded. + * As long as SDO helper classes (e.g., TypeHelper, XMLHelper, etc.) are accessed though their + * corresponding INSTANCE fields (e.g., TypeHelper.INSTANCE), or using the SDOUtil methods (e.g., + * SDOUtil.createTypeHelper(), this will always be the case. + */ + /* + static + { + EPackage.Registry.INSTANCE.put(EcorePackage.eNS_URI, new EPackage.Descriptor() + { + public EPackage getEPackage() + { + return EcorePackage.eINSTANCE; + } + + public EFactory getEFactory() + { + return new SDOFactoryImpl.SDOEcoreFactory(); + } + }); + } + */ + + protected static StringBuffer getXPath(DataObject dataObject, StringBuffer path, DataObject root) + { + DataObject container = dataObject.getContainer(); + if (container == null) return path; + + if (container == root) { + throw new IllegalStateException("There is a cycle in the containment hierarchy of " + root); + } + + boolean first = path.length() == 0; + Property property = dataObject.getContainmentProperty(); + if (SDOUtil.isMany(property, dataObject)) + { + List list = container.getList(property); + int pos = list.indexOf(dataObject); + path.insert(0, property.getName() + "." + pos + (first ? "" : "/")); + } + else + { + path.insert(0, property.getName() + (first ? "" : "/")); + } + + return getXPath(container, path, root); + } + + public static String getXPath(DataObject dataObject) + { + StringBuffer path = getXPath(dataObject, new StringBuffer(), dataObject); + return path.toString(); + } + + protected static XMLParserPool globalXMLParserPool = new XMLParserPoolImpl(); + + public static void configureXMLResource(XMLResource resource, ExtendedMetaData extendedMetaData) + { + XMLOptions xmlOptions = new XMLOptionsImpl(); + xmlOptions.setProcessAnyXML(true); + resource.getDefaultLoadOptions().put(XMLResource.OPTION_XML_OPTIONS, xmlOptions); + + resource.getDefaultSaveOptions().put(XMLResource.OPTION_EXTENDED_META_DATA, extendedMetaData); + resource.getDefaultLoadOptions().put(XMLResource.OPTION_EXTENDED_META_DATA, extendedMetaData); + + resource.getDefaultLoadOptions().put(XMLResource.OPTION_USE_PARSER_POOL, globalXMLParserPool); + + resource.getDefaultLoadOptions().put(XMLResource.OPTION_USE_DEPRECATED_METHODS, Boolean.FALSE); + + resource.getDefaultSaveOptions().put(XMLResource.OPTION_CONFIGURATION_CACHE, Boolean.TRUE); + resource.getDefaultLoadOptions().put(XMLResource.OPTION_CONFIGURATION_CACHE, Boolean.TRUE); + + resource.getDefaultLoadOptions().put(XMLResource.OPTION_ANY_TYPE, SDOPackage.eINSTANCE.getAnyTypeDataObject()); + resource.getDefaultSaveOptions().put(XMLResource.OPTION_ANY_TYPE, SDOPackage.eINSTANCE.getAnyTypeDataObject()); + + resource.getDefaultLoadOptions().put(XMLResource.OPTION_ANY_SIMPLE_TYPE, SDOPackage.eINSTANCE.getSimpleAnyTypeDataObject()); + resource.getDefaultSaveOptions().put(XMLResource.OPTION_ANY_SIMPLE_TYPE, SDOPackage.eINSTANCE.getSimpleAnyTypeDataObject()); + + //resource.getDefaultLoadOptions().put(XMLResource.OPTION_USE_XML_NAME_TO_FEATURE_MAP, globalHashMap); + + //resource.getDefaultSaveOptions().put(XMLResource.OPTION_FORMATTED, Boolean.FALSE); + } + + /** + * @deprecated SDO runtime initialization is no longer required + */ + public static void initRuntime() + { + // NOOP since init is done during static initialization of this class. See above. + } + + /* + public static Object get(org.apache.tuscany.sdo.model.Property property, int propertyIndex) { + switch(propertyIndex) + { + case ModelPackageImpl.PROPERTY__ALIAS_NAME: + return property.getAliasName(); + case ModelPackageImpl.PROPERTY__ANY: + return property.getAny(); + case ModelPackageImpl.PROPERTY__ANY_ATTRIBUTE: + return property.getAnyAttribute(); + case ModelPackageImpl.PROPERTY__CONTAINMENT: + return Boolean.valueOf(property.isContainment()); + case ModelPackageImpl.PROPERTY__DEFAULT: + return property.getDefault_(); + case ModelPackageImpl.PROPERTY__MANY: + return Boolean.valueOf(property.isMany()); + case ModelPackageImpl.PROPERTY__NAME: + return property.getName(); + case ModelPackageImpl.PROPERTY__OPPOSITE: + return property.getOpposite_(); + case ModelPackageImpl.PROPERTY__READ_ONLY: + return Boolean.valueOf(property.isReadOnly()); + case ModelPackageImpl.PROPERTY__TYPE: + return property.getType_(); + } + return null; + } + + public static boolean isSet(org.apache.tuscany.sdo.model.Property property, int propertyIndex) { + switch(propertyIndex) + { + case ModelPackageImpl.PROPERTY__ALIAS_NAME: + return !property.getAliasName().isEmpty(); + case ModelPackageImpl.PROPERTY__ANY: + return false; + case ModelPackageImpl.PROPERTY__ANY_ATTRIBUTE: + return false; + case ModelPackageImpl.PROPERTY__CONTAINMENT: + return property.isSetContainment(); + case ModelPackageImpl.PROPERTY__DEFAULT: + return property.getDefault_() != null; + case ModelPackageImpl.PROPERTY__MANY: + return property.isSetMany(); + case ModelPackageImpl.PROPERTY__NAME: + return property.getName() != null; + case ModelPackageImpl.PROPERTY__OPPOSITE: + return property.getOpposite_() != null; + case ModelPackageImpl.PROPERTY__READ_ONLY: + return property.isSetReadOnly(); + case ModelPackageImpl.PROPERTY__TYPE: + return property.getType_() != null; + } + return false; + } + + public static Object get(org.apache.tuscany.sdo.model.Type type, int propertyIndex) { + switch (propertyIndex) + { + case ModelPackageImpl.TYPE__BASE_TYPE: + return type.getBaseType(); + case ModelPackageImpl.TYPE__PROPERTY: + return type.getProperty(); + case ModelPackageImpl.TYPE__ALIAS_NAME: + return type.getAliasName(); + case ModelPackageImpl.TYPE__ANY: + return type.getAny(); + case ModelPackageImpl.TYPE__ABSTRACT: + return Boolean.valueOf(type.isAbstract()); + case ModelPackageImpl.TYPE__DATA_TYPE: + return Boolean.valueOf(type.isDataType()); + case ModelPackageImpl.TYPE__NAME: + return type.getName(); + case ModelPackageImpl.TYPE__OPEN: + return Boolean.valueOf(type.isOpen()); + case ModelPackageImpl.TYPE__SEQUENCED: + return Boolean.valueOf(type.isSequenced()); + case ModelPackageImpl.TYPE__URI: + return type.getUri(); + case ModelPackageImpl.TYPE__ANY_ATTRIBUTE: + return type.getAnyAttribute(); + } + return null; + } + + public static boolean isSet(org.apache.tuscany.sdo.model.Type type, int propertyIndex) { + //FB Note that this implementation has the undesirable effect of invoking lazy creation of feature lists + switch (propertyIndex) + { + case ModelPackageImpl.TYPE__BASE_TYPE: + return !type.getBaseType().isEmpty(); + case ModelPackageImpl.TYPE__PROPERTY: + return !type.getProperty().isEmpty(); + case ModelPackageImpl.TYPE__ALIAS_NAME: + return !type.getAliasName().isEmpty(); + case ModelPackageImpl.TYPE__ANY: + return false; + case ModelPackageImpl.TYPE__ABSTRACT: + return type.isSetAbstract(); + case ModelPackageImpl.TYPE__DATA_TYPE: + return type.isSetDataType(); + case ModelPackageImpl.TYPE__NAME: + return type.getName() != null; + case ModelPackageImpl.TYPE__OPEN: + return type.isSetOpen(); + case ModelPackageImpl.TYPE__SEQUENCED: + return type.isSetSequenced(); + case ModelPackageImpl.TYPE__URI: + return type.getUri() != null; + case ModelPackageImpl.TYPE__ANY_ATTRIBUTE: + return false; + } + return false; + } + */ + + /** + * Returns a unique list of meta object instance properties (stored in EAnnotations) + * + * @param metaObject - A Type or Property instance + * @return A list of commonj.sdo.Property instances + */ + public static List getMetaObjectInstanceProperties(EModelElement metaObject) + { + // Use the default helper context for now + TypeHelper typeHelper = HelperProvider.getDefaultContext().getTypeHelper(); + + List result = new UniqueEList(); + List annotations = metaObject.getEAnnotations(); + int size = annotations.size(); + for (int i=0; i<size; i++) + { + EAnnotation annotation = (EAnnotation)annotations.get(i); + String propertyURI = annotation.getSource(); + + for (Iterator iter = annotation.getDetails().iterator(); iter.hasNext(); ) + { + EStringToStringMapEntryImpl entry = (EStringToStringMapEntryImpl)iter.next(); + String propertyName = entry.getTypedKey(); + + Property globalProperty = getGlobalProperty(typeHelper, propertyURI, propertyName); + if (globalProperty != null) + { + result.add(globalProperty); + } + } + } + return result; + } + + /** + * Return the value of the specified mata object instance property (stored in EAnnotations) + * + * @param metaObject - A Type or Property instance + * @param property - The instance property to retrieve + * @return The value of the instance property + */ + public static Object getMetaObjectInstanceProperty(EModelElement metaObject, Property property) + { + String value = EcoreUtil.getAnnotation(metaObject, property.getContainingType().getURI(), property.getName()); + //TODO if (property.isMany()) ... // create list of values from from string + return SDOUtil.createFromString(property.getType(), value); + } + + protected static Property getGlobalProperty(TypeHelper typeHelper, String uri, String name) + { + Property property; + if (ExtendedMetaData.ANNOTATION_URI.equals(uri)) { + if ("minExclusive".equals(name) || + "minInclusive".equals(name) || + "maxExclusive".equals(name) || + "maxInclusive".equals(name) || + "totalDigits".equals(name) || + "fractionDigits".equals(name) || + "length".equals(name) || + "minLength".equals(name) || + "maxLength".equals(name) || + "enumeration".equals(name) || + "whiteSpace".equals(name) || + "pattern".equals(name)) + { + //TODO Use standard facet properties, once SDO defines them + //TODO property = getSDOFacetProperty(name); + //TEMP For now just expose a string property for the EMF (ExtendedMetaData) facets + property = SDOUtil.createGlobalProperty(typeHelper, uri, name, ((ModelFactoryImpl)ModelFactory.INSTANCE).getString()); + } + else + { + //TODO Should we consider exposing more ExtendedMetaData? + property = null; + } + } + else + { + property = typeHelper.getOpenContentProperty(uri, name); + if (property == null) + { + property = SDOUtil.createGlobalProperty(typeHelper, uri, name, ((ModelFactoryImpl)ModelFactory.INSTANCE).getString()); + } + } + return property; + } + +} diff --git a/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/SDOUtil.java b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/SDOUtil.java new file mode 100644 index 0000000000..f0769de2d5 --- /dev/null +++ b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/SDOUtil.java @@ -0,0 +1,922 @@ +/** + * + * 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.util; + +import java.io.IOException; +import java.io.InputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.OutputStream; +import java.lang.reflect.Field; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.security.AccessController; +import java.security.PrivilegedExceptionAction; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +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.helper.CrossScopeCopyHelperImpl; +import org.apache.tuscany.sdo.helper.DataFactoryImpl; +import org.apache.tuscany.sdo.helper.HelperContextImpl; +import org.apache.tuscany.sdo.helper.SDOExtendedMetaDataImpl; +import org.apache.tuscany.sdo.helper.TypeHelperImpl; +import org.apache.tuscany.sdo.helper.XMLHelperImpl; +import org.apache.tuscany.sdo.helper.XMLStreamHelper; +import org.apache.tuscany.sdo.helper.XMLStreamHelperImpl; +import org.apache.tuscany.sdo.helper.XSDHelperImpl; +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.util.resource.SDOObjectInputStream; +import org.apache.tuscany.sdo.util.resource.SDOObjectOutputStream; +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.impl.EPackageImpl; +import org.eclipse.emf.ecore.impl.EPackageRegistryImpl; +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 org.eclipse.emf.ecore.xml.type.XMLTypePackage; + +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.DataFactory; +import commonj.sdo.helper.HelperContext; +import commonj.sdo.helper.TypeHelper; +import commonj.sdo.helper.XMLHelper; +import commonj.sdo.helper.XSDHelper; + +/** + * This class provides some useful static utility functions which are not specified in the SDO + * specification itself. Use of the functions in this class is recommended, instead of resorting + * to low-level implementation-specific APIs. + */ +public final class SDOUtil +{ + /** + * Line Break String such as "\n", "\r\n", "\r" and "", absence/null is the default (line.separator System Property) + */ + static public final String XML_SAVE_LineBreak = "LineBreak", + /** + * Indent String such as "\t", "", etc. absence/null is the default (" ") + */ + XML_SAVE_INDENT = "indent", + /** + * Margin String such as " ", "\t\t", etc. Absence/null/"" is the default (no margin) + */ + XML_SAVE_MARGIN = "margin", + /** + * Attribute formatting that exceeds the specified width as Integer will cause a line break so that formatting will continue indented on the next line + */ + XML_SAVE_LineWidth = XMLResource.OPTION_LINE_WIDTH, + /** + * Boolean to save a doctype declaration + */ + XML_SAVE_DocType = XMLResource.OPTION_SAVE_DOCTYPE, + /** + * Boolean to process the schemaLocation/noNamespaceSchemaLocation attributes occurring in the instance document to {@link XSDHelper#define convert XSD(s) to Types} + */ + XML_LOAD_SCHEMA = "ProcessSchemaLocations", + /** + * To tolerate malformed elements and attributes (default unless set by System property XML.load.form.lax). 0 not to. + */ + XML_LOAD_LaxForm = "load malform"; + + /** + * Create a DataObject wrapper for an instance of the specified dataType. + * This method is typically used to create a root object that can be passed to the XMLHelper.save() + * method when the root element to be serialized is an XMLSchema simpleType. + * @param dataType a Type for which isDataType() returns true. + * @param value the instance value. + * @return a DataObject wrapper for the specified value. + */ + public static DataObject createDataTypeWrapper(Type dataType, Object value) + { + SimpleAnyTypeDataObject simpleAnyType = SDOFactory.eINSTANCE.createSimpleAnyTypeDataObject(); + simpleAnyType.setInstanceType((EDataType)dataType); + simpleAnyType.setValue(value); + return simpleAnyType; + } + + /** + * Creates an instance of a data type from the specified string. + * @param dataType a Type, for which isDataType() returns true, to instantiate. + * @param literal the string value of the dataType. + * @return an instance of the dataType. + * @see #convertToString(Type, Object) + */ + public static Object createFromString(Type dataType, String literal) + { + return EcoreUtil.createFromString((EDataType)dataType, literal); + } + + /** + * Converts an instance of a data type to a string literal representation. + * @param dataType the Type, for which isDataType() returns true, of the value to convert. + * @param value a value of the dataType. + * @return the string literal representation of the value. + * @see #createFromString(Type, String) + */ + public static String convertToString(Type dataType, Object value) + { + return EcoreUtil.convertToString((EDataType)dataType, value); + } + + /** + * Get the SDO built-in type corresponding to the specified XSD type in the XML Schema + * namespace ("http://www.w3.org/2001/XMLSchema"). + * @param xsdType a type name in the XML Schema namespace. + * @return the SDO built-in Type corresponding to the specified XSD type. + */ + public static Type getXSDSDOType(String xsdType) + { + Type type = null; + //if ("anyType".equals(xsdType)) { + // type = (Type)SDOPackage.eINSTANCE.getDataObject(); + //} else { + String name = (String)xsdToSdoMappings.get(xsdType); + if (name != null) { + type = (Type)((ModelFactoryImpl)ModelFactory.INSTANCE).getEClassifier(name); + } else { + type = (Type)SDOExtendedMetaData.INSTANCE.getType(XMLTypePackage.eINSTANCE, xsdType); + } + //} + return type; + } + + /** + * Gets the Sequence corresponding to the specified substitutable Property of the specified DataObject. + * @param dataObject the data object. + * @param head a substitution group head property. + * @return the Sequence corresponding to the specified substitutable Property of the specified DataObject or + * null if the specified Property isn't a substitution head. + */ + public static 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(); + } + + /** + * Get the SDO built-in type corresponding to the specified Java instanceClass. + * @param javaClass the Java instanceClass of the type. + * @return the SDO built-in Type corresponding to the specified instanceClass. + */ + public static Type getJavaSDOType(Class javaClass) + { + String name = (String)javaToSdoMappings.get(javaClass); + if (name != null) + { + return (Type)((ModelFactoryImpl)ModelFactory.INSTANCE).getEClassifier(name); + } + return null; + } + + /** + * Return whether at least one value is required for a valid instance of the specified property. + * @param the property in question. + * @return true if the property is required. + */ + public static boolean isRequired(Property property) + { + return ((EStructuralFeature)property).isRequired(); + } + + /** + * Returns whether the Property is many-valued given the specified context. + * @param property The Property in question + * @param context The context to check whether the specified Property is many-valued + * @return true if the Property is many-valued given the specified context. + */ + public static boolean isMany(Property property, DataObject context) + { + return FeatureMapUtil.isMany((EObject) context, (EStructuralFeature) property); + } + + /** + * Create an empty data graph. + * @return the new data graph instance. + */ + public static DataGraph createDataGraph() + { + return SDOFactory.eINSTANCE.createDataGraph(); + } + + /** + * Set the root object of a data graph. + * @param dataGraph the data graph in which to set the root object. + * @param rootObject the root object. + */ + public static void setRootObject(DataGraph dataGraph, DataObject rootObject) + { + ((DataGraphImpl)dataGraph).setERootObject((EObject)rootObject); + } + + /** + * Load a serialized data graph from the specified insputStream. + * @param inputStream the inputStream of the data graph. + * @param options loader control options, or null. + * @return the de-serialized data graph. + * @throws IOException + */ + 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 static void registerLoadingScope(Map options, TypeHelper scope) + { + Object extendedMetaData = ((TypeHelperImpl) scope).getExtendedMetaData(); + options.put(LOADING_SCOPE, extendedMetaData); + } + + /** + * Load a serialized data graph from the specified insputStream. + * + * @param inputStream + * the inputStream of the data graph. + * @param options + * loader control options, or null. + * @param scope + * To register deserialized Types and utilize already registered Types in order to instantiate expected DataObject instances, null for + * {@link TypeHelper.INSTANCE TypeHelper.INSTANCE}. + * @return the de-serialized data graph. + * @throws IOException + */ + public static DataGraph loadDataGraph(InputStream inputStream, Map options, TypeHelper scope) throws IOException + { + DataGraph result = null; + if (scope == null || scope == TypeHelper.INSTANCE) { + result = loadDataGraph(inputStream, options); + } else if (options == null) { + options = new HashMap(); + registerLoadingScope(options, scope); + result = loadDataGraph(inputStream, options); + } else if (options.containsKey(LOADING_SCOPE)) { + Object restore = options.get(LOADING_SCOPE); + registerLoadingScope(options, scope); + try + { + result = loadDataGraph(inputStream, options); + } + finally + { + options.put(LOADING_SCOPE, restore); + } + } else { + registerLoadingScope(options, scope); + try + { + result = loadDataGraph(inputStream, options); + } + finally + { + options.remove(LOADING_SCOPE); + } + } + return result; + } + + /** + * Serialize the specified data graph to the specified outputStream. + * @param dataGraph the data graph to save. + * @param outputStream the outputStream for the data graph. + * @param options serializer control options, or null. + * @throws IOException + */ + public static void saveDataGraph(DataGraph dataGraph, OutputStream outputStream, Map options) throws IOException + { + ((DataGraphImpl)dataGraph).getDataGraphResource().save(outputStream, options); + } + + /** + * Registers the specified {@link Type type}(s) to be serialized along with + * the {@link DataObject data object}(s) in the graph. For example, the list of types returned from + * {@link TypeHelper#define} can be registered with this method, allowing deserialization of + * instances of a dynamically defined model. + * @param dataGraph the DataGraph in which to register the specified type(s). + * @param types a list containing the type(s) to be registered (TBD or null to automatically register all + * types used by the objects in the DataGraph). + */ + public static 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); + } + } + + /** + * Create a HelperContext to provide access to a consistent set of + * Helpers which make use of a new TypeHelper instance to provide + * scope for type definitions. + * @param extensibleNamespaces true if the contents of a namespaces should be incrementally modifiable + * @return the new HelperContext + */ + public static HelperContext createHelperContext(boolean extensibleNamespaces) + { + return new HelperContextImpl(extensibleNamespaces); + } + + /** + * Create a HelperContext. + * @return the new HelperContext + * @see #createHelperContext(boolean) + */ + public static HelperContext createHelperContext() + { + return createHelperContext(false); + } + + /** + * Create a new TypeHelper instance. The returned type helper will have visibility of types registered + * directly by calling a define method on it or by calling define on an associated XSDHelper. It will + * also have visibility of static types registered by calling SDOUtil.registerStaticTypes in the + * same classLoader scope. + * @return the new TypeHelper. + * @deprecated see {@link #createHelperContext(TypeHelper)} + */ + public static TypeHelper createTypeHelper() + { + EPackage.Registry registry = new EPackageRegistryImpl(EPackage.Registry.INSTANCE); + ExtendedMetaData extendedMetaData = new SDOExtendedMetaDataImpl(registry); //TODO create subclass that makes demand() methods synchronous + return new TypeHelperImpl(extendedMetaData); + } + + /** + * Create a new DataFactory, with visibility to types in the specified TypeHelper scope. + * @param scope the TypeHelper to use for locating types. + * @return the new DataFactory. + * @deprecated see {@link #createHelperContext(TypeHelper)} + */ + public static DataFactory createDataFactory(TypeHelper scope) + { + return new DataFactoryImpl(scope); + } + + /** + * Create a new XMLHelper, with visibility to types in the specified TypeHelper scope. + * @param scope the TypeHelper to use for locating types. + * @return the new XMLHelper. + * @deprecated see {@link #createHelperContext(TypeHelper)} + */ + public static XMLHelper createXMLHelper(TypeHelper scope) + { + return new XMLHelperImpl(scope); + } + + /** + * Create a new XSDHelper, with visibility to types in the specified TypeHelper scope. + * @param scope the TypeHelper to use for locating and populating types. + * @return the new XSDHelper. + * @deprecated see {@link #createHelperContext(TypeHelper)} + */ + public static XSDHelper createXSDHelper(TypeHelper scope) + { + return new XSDHelperImpl(scope, false); + } + + /** + * Create a new XMLStreamHelper, with visibility to types in the specified TypeHelper scope. + * @param scope the TypeHelper to use for locating types. + * @return the new XMLStreamHelper. + */ + public static XMLStreamHelper createXMLStreamHelper(TypeHelper scope) + { + return new XMLStreamHelperImpl(scope); + } + + /** + * Create a new cross scope CopyHelper. + * @param targetScope the TypeHelper containing the Types to use to create the copy objects. + * @return the new CopyHelper. + */ + public static CopyHelper createCrossScopeCopyHelper(TypeHelper targetScope) + { + return new CrossScopeCopyHelperImpl(targetScope); + } + + /** + * Create a new ObjectInputStream, under the helperContextScope + * @param scope the TypeHelper to use for locating types. + * @return the new XMLStreamHelper. + */ + public static ObjectInputStream createObjectInputStream(InputStream inputStream, HelperContext helperContext) throws IOException + { + return new SDOObjectInputStream(inputStream, helperContext); + } + + /** + * Create a new ObjectOutputStream, under the helperContextScope. + * @param scope the TypeHelper to use for locating types. + * @return the new XMLStreamHelper. + */ + public static ObjectOutputStream createObjectOutputStream(OutputStream outputStream, HelperContext helperContext) throws IOException + { + return new SDOObjectOutputStream(outputStream, helperContext); + } + + /** + * Gets all of the types associated with a uri. + * + * @param scope + * the TypeHelper to use for locating types. + * @param uri. + * Uri of the Types + * @return List. List containing instances of Type, null if uri is not found. + */ + public static List getTypes(TypeHelper scope, String uri) { + + EPackage ePackage = ((TypeHelperImpl) scope).getExtendedMetaData().getPackage(uri); + if (ePackage != null) { + return new ArrayList(ePackage.getEClassifiers()); + } + return null; + } + + public static List getOpenContentProperties(DataObject dataObject) + { + List result = new UniqueEList(); + ((ClassImpl)dataObject.getType()).addOpenProperties((EObject)dataObject, result); + return result; + } + + public static boolean isDocumentRoot(Type type) + { + return "".equals(SDOExtendedMetaData.INSTANCE.getName((EClassifier)type)); + } + + public static Type createType(TypeHelper scope, String uri, String name, boolean isDataType) + { + ExtendedMetaData extendedMetaData = ((TypeHelperImpl)scope).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 static void addBaseType(Type type, Type baseType) + { + ((EClass)type).getESuperTypes().add(baseType); + } + + public static void addAliasName(Type type, String aliasName) + { + throw new UnsupportedOperationException(); // TODO: implement this method properly + //type.getAliasNames().add(aliasName); + } + + public static 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 (type.isSequenced()) { + 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 static void setSequenced(Type type, boolean isSequenced) + { + if (isSequenced == type.isSequenced()) return; + + // 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 static void setAbstract(Type type, boolean isAbstract) + { + ((EClass)type).setAbstract(isAbstract); + } + + public static void setJavaClassName(Type type, String javaClassName) + { + ((EClassifier)type).setInstanceClassName(javaClassName); + } + + public static 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 (containingType.isSequenced()) { + eStructuralFeature.setDerived(true); + eStructuralFeature.setTransient(true); + eStructuralFeature.setVolatile(true); + ExtendedMetaData.INSTANCE.setFeatureKind(eStructuralFeature, ExtendedMetaData.ELEMENT_FEATURE); + } + else + { + //FB TBD ... figure out how to decide whether to use ELEMENT_FEATURE or ATTRIBUTE_FEATURE + //ExtendedMetaData.INSTANCE.setFeatureKind(eStructuralFeature, ExtendedMetaData.ELEMENT_FEATURE); + } + + return (Property)eStructuralFeature; + } + + public static Property createGlobalProperty(TypeHelper scope, String uri, String name, Type type) + { + ExtendedMetaData extendedMetaData = ((TypeHelperImpl)scope).getExtendedMetaData(); + + // get/create document root + EPackage ePackage = extendedMetaData.getPackage(uri); + Type documentRoot = ePackage != null ? (Type)extendedMetaData.getType(ePackage, "") : null; + if (documentRoot == null) + { + documentRoot = SDOUtil.createType(scope, 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 = SDOUtil.createProperty(documentRoot, name, type); + } + else + { + // if property already exists, validate the expected type + if (!newProperty.getType().equals(type)) + throw new IllegalArgumentException(); + } + return newProperty; + } + + public static void addAliasName(Property property, String aliasName) + { + throw new UnsupportedOperationException(); // TODO: implement this method properly + //property.getAliasNames().add(aliasName); + } + + public static void setMany(Property property, boolean isMany) + { + ((EStructuralFeature)property).setUpperBound(isMany ? EStructuralFeature.UNBOUNDED_MULTIPLICITY : 1); + } + + public static void setContainment(Property property, boolean isContainment) + { + ((EReference)property).setContainment(isContainment); + } + + public static void setDefault(Property property, String defaultValue) + { + ((EStructuralFeature)property).setDefaultValueLiteral(defaultValue); + } + + public static void setReadOnly(Property property, boolean isReadOnly) + { + ((EStructuralFeature)property).setChangeable(!isReadOnly); + } + + public static void setOpposite(Property property, Property opposite) + { + ((EReference)property).setEOpposite((EReference)opposite); + } + + public static void addTypeInstanceProperties(Type definedType, DataObject modeledType) + { + addInstanceProperties((EModelElement)definedType, modeledType); + } + + public static void addPropertyInstanceProperties(Property definedProperty, DataObject modeledProperty) + { + addInstanceProperties((EModelElement)definedProperty, modeledProperty); + } + + protected static void addInstanceProperties(EModelElement metaObject, DataObject dataObject) + { + List instanceProperties = getOpenContentProperties(dataObject); + for (Iterator iter = instanceProperties.iterator(); iter.hasNext(); ) + { + Property property = (Property)iter.next(); + String uri = property.getContainingType().getURI(); + EAnnotation eAnnotation = metaObject.getEAnnotation(uri); + if (eAnnotation == null) + { + eAnnotation = EcoreFactory.eINSTANCE.createEAnnotation(); + eAnnotation.setSource(uri); + metaObject.getEAnnotations().add(eAnnotation); + } + Object value = dataObject.get(property); + //TODO if (property.isMany()) ... // convert list of values + String stringValue = SDOUtil.convertToString(property.getType(), value); + eAnnotation.getDetails().put(property.getName(), stringValue); + } + } + + /** + * Register and initialize the SDO types supported by the specified generated factory class. + * This function must be called before instances of the generated types can be created/used. + * The registered types will be visible in all TypeHelper's created in the same classLoader + * scope as the call to this function. + * @param factoryClass the generated factory class. + * @deprecated see the register(HelperContext) metods on generated Factory classes + */ + public static void registerStaticTypes(Class factoryClass) + { + //TODO this implementation is temporary, until the SDO generated factory pattern is decided + //TODO might want to clean this implementation in the light of the requirement to regenerate all classes + //after noEMF became the default, so we have no compatibility requirements (unless we + //cater for the simple hand edit that would make M2 generated classes work) -- as this is + //deprecated I'm going to do nothing for now + // + String temp = factoryClass.getName().replaceFirst("Factory$", "PackageImpl"); + int lastDot = temp.lastIndexOf('.'); + String packageName = temp.substring(0, lastDot) + ".impl" + temp.substring(lastDot); + + try // this case handles the old style EMF pattern + { + Class javaClass = getPackageClass(factoryClass, packageName); + Field field = javaClass.getField("eINSTANCE"); + EPackageImpl pkg = (EPackageImpl)field.get(null); + EPackage.Registry.INSTANCE.put(pkg.getNsURI(), pkg); + } + catch (Exception e1) + { + packageName = factoryClass.getName().replaceFirst("Factory$", "Package"); + try // this case handles the EMF -noInterfaces generator pattern + { + Class javaClass = getPackageClass(factoryClass, packageName); + Field field = javaClass.getField("eINSTANCE"); + EPackageImpl pkg = (EPackageImpl)field.get(null); + EPackage.Registry.INSTANCE.put(pkg.getNsURI(), pkg); + } + catch (Exception e2) + { + try // this case handles the default (was -noEMF) generator pattern + { + Field field = factoryClass.getField("INSTANCE"); + EPackageImpl pkg = (EPackageImpl)field.get(null); + EPackage.Registry.INSTANCE.put(pkg.getNsURI(), pkg); + // TODO -- decide if we should block global initialization of Factories with the new register method. + } + catch (Exception e3) + { + e3.printStackTrace(); + } + } + } + } + + + private static Class getPackageClass(Class factoryClass, String packageName) throws Exception + { + final Class factoryClassTemp = factoryClass; + final String packageNameTemp = packageName; + return (Class)AccessController.doPrivileged(new PrivilegedExceptionAction() { + public Object run() throws Exception { + return factoryClassTemp.getClassLoader().loadClass(packageNameTemp); + } + }); + } + + //Java instance class to SDO mappings (p.69 - p.71 of the SDO spec) + private static Map javaToSdoMappings = new HashMap(); + static { + javaToSdoMappings.put(boolean.class, "Boolean"); + javaToSdoMappings.put(byte.class, "Byte"); + javaToSdoMappings.put(char.class, "Character"); + javaToSdoMappings.put(Date.class, "Date"); + javaToSdoMappings.put(BigDecimal.class, "Decimal"); + javaToSdoMappings.put(double.class, "Double"); + javaToSdoMappings.put(float.class, "Float"); + javaToSdoMappings.put(int.class, "Int"); + javaToSdoMappings.put(BigInteger.class, "Integer"); + javaToSdoMappings.put(long.class, "Long"); + javaToSdoMappings.put(Object.class, "Object"); + javaToSdoMappings.put(short.class, "Short"); + javaToSdoMappings.put(String.class, "String"); + javaToSdoMappings.put(Boolean.class, "BooleanObject"); + javaToSdoMappings.put(Byte.class, "ByteObject"); + javaToSdoMappings.put(Character.class, "CharacterObject"); + javaToSdoMappings.put(Double.class, "DoubleObject"); + javaToSdoMappings.put(Float.class, "FloatObject"); + javaToSdoMappings.put(Integer.class, "IntObject"); + javaToSdoMappings.put(Long.class, "LongObject"); + javaToSdoMappings.put(Short.class, "ShortObject"); + } + + //XSD to SDO mappings (p.95 of the SDO spec) + private static Map xsdToSdoMappings = new HashMap(); + static { + xsdToSdoMappings.put("anySimpleType", "Object"); + xsdToSdoMappings.put("anyType", "DataObject"); + xsdToSdoMappings.put("anyURI", "URI"); + xsdToSdoMappings.put("base64Binary", "Base64Bytes"); + xsdToSdoMappings.put("boolean", "Boolean"); + xsdToSdoMappings.put("byte", "Byte"); + xsdToSdoMappings.put("date", "YearMonthDay"); + xsdToSdoMappings.put("dateTime", "DateTime"); + xsdToSdoMappings.put("decimal", "Decimal"); + xsdToSdoMappings.put("double", "Double"); + xsdToSdoMappings.put("duration", "Duration"); + xsdToSdoMappings.put("ENTITIES", "Strings"); + xsdToSdoMappings.put("ENTITY", "String"); + xsdToSdoMappings.put("float", "Float"); + xsdToSdoMappings.put("gDay", "Day"); + xsdToSdoMappings.put("gMonth", "Month"); + xsdToSdoMappings.put("gMonthDay", "MonthDay"); + xsdToSdoMappings.put("gYear", "Year"); + xsdToSdoMappings.put("gYearMonth", "YearMonth"); + xsdToSdoMappings.put("hexBinary", "Bytes"); + xsdToSdoMappings.put("ID","String"); + xsdToSdoMappings.put("IDREF","String"); + xsdToSdoMappings.put("IDREFS","Strings"); + xsdToSdoMappings.put("int","Int"); + xsdToSdoMappings.put("integer","Integer"); + xsdToSdoMappings.put("language","String"); + xsdToSdoMappings.put("long","Long"); + xsdToSdoMappings.put("Name","String"); + xsdToSdoMappings.put("NCName","String"); + xsdToSdoMappings.put("negativeInteger","Integer"); + xsdToSdoMappings.put("NMTOKEN","String"); + xsdToSdoMappings.put("NMTOKENS","Strings"); + xsdToSdoMappings.put("nonNegativeInteger","Integer"); + xsdToSdoMappings.put("nonPositiveInteger","Integer"); + xsdToSdoMappings.put("normalizedString","String"); + xsdToSdoMappings.put("NOTATION","String"); + xsdToSdoMappings.put("positiveInteger","Integer"); + xsdToSdoMappings.put("QName","URI"); + xsdToSdoMappings.put("short","Short"); + xsdToSdoMappings.put("string","String"); + xsdToSdoMappings.put("time","Time"); + xsdToSdoMappings.put("token","String"); + xsdToSdoMappings.put("unsignedByte","Short"); + xsdToSdoMappings.put("unsignedInt","Long"); + xsdToSdoMappings.put("unsignedLong","Integer"); + xsdToSdoMappings.put("unsignedShort","Int"); + } + + /** + * Initialize SDO runtime. + */ + static + { + DataObjectUtil.initRuntime(); + } + +} diff --git a/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/StAX2SAXAdapter.java b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/StAX2SAXAdapter.java new file mode 100644 index 0000000000..69dc53cefb --- /dev/null +++ b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/StAX2SAXAdapter.java @@ -0,0 +1,250 @@ +/** + * + * 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.util; + +import javax.xml.namespace.QName; +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.Locator; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.AttributesImpl; + +/** + * Adapter that converts from StAX to SAX event streams. Currently the following SAX events are not generated: + * <ul> + * <li>ignorableWhitespace</li> + * <li>skippedEntity</li> + * <ul> + * Also the following StAX events are not mapped: + * <ul> + * <li>CDATA</li> + * <li>COMMENT</li> + * <li>DTD</li> + * <li>ENTITY_DECLARATION</li> + * <li>ENTITY_REFERENCE</li> + * <li>NOTATION_DECLARATION</li> + * <li>SPACE</li> + * </ul> + * StAX ATTRIBUTE events are ignored but the equivalent attributes (derived from the START_ELEMENT event) are supplied in the SAX startElement event's + * Attributes parameter. If the adaptor is configured to pass namespace prefixes then namespace information will also be included in the Attributes; + * StAX NAMESPACE events are ignored. + * <p/> + * Another issue is namespace processing. If the reader is positioned at a sub-node, we cannot capture all the in-scope namespace bindings. Therefore + * we cannot re-create a proper SAX event stream from a StAX parser. + * <p/> + * For example + * <p/> + * <a:root xmlns:a="foo" xmlns:b="bar"><b:sub>a:foo</b:sub></a:root> + * <p/> + * And if you are handed a parser at <b:sub>, then your SAX events should look like: + * <p/> + * <b:sub xmlns:a="foo" xmlns:b="bar">a:foo</b:sub> + * <p/> + * not: + * <p/> + * <b:sub>a:foo</b:sub> + * <p/> + * <p/> + * Proposal: we change the receiver of SAX events (SDOXMLResourceImpl) so that it uses NamespaceContext to resolve prefix (as opposed to record + * start/endPrefixMappings and use it for resolution.) + * + * @version $Rev$ $Date$ + */ +public class StAX2SAXAdapter { + private final boolean namespacePrefixes; + + /** + * Construct a new StAX to SAX adapter that will convert a StAX event stream into a SAX event stream. + * + * @param namespacePrefixes whether xmlns attributes should be included in startElement events; + */ + public StAX2SAXAdapter(boolean namespacePrefixes) { + this.namespacePrefixes = namespacePrefixes; + } + + /** + * Pull events from the StAX stream and dispatch to the SAX ContentHandler. The StAX stream would typically be located on a START_DOCUMENT or + * START_ELEMENT event and when this method returns it will be located on the associated END_DOCUMENT or END_ELEMENT event. Behaviour with other + * start events is undefined. + * + * @param reader StAX event source to read + * @param handler SAX ContentHandler for processing events + * @throws XMLStreamException if there was a problem reading the stream + * @throws SAXException passed through from the ContentHandler + */ + public void parse(XMLStreamReader reader, ContentHandler handler) throws XMLStreamException, SAXException { + handler.setDocumentLocator(new LocatorAdaptor(reader.getLocation())); + + // remembers the nest level of elements to know when we are done + int level = 0; + int event = reader.getEventType(); + while (true) { + switch (event) { + case XMLStreamConstants.START_DOCUMENT: + level++; + handler.startDocument(); + break; + case XMLStreamConstants.START_ELEMENT: + level++; + handleStartElement(reader, handler); + break; + case XMLStreamConstants.PROCESSING_INSTRUCTION: + handler.processingInstruction(reader.getPITarget(), reader.getPIData()); + break; + case XMLStreamConstants.CHARACTERS: + handler.characters(reader.getTextCharacters(), reader.getTextStart(), reader.getTextLength()); + break; + case XMLStreamConstants.END_ELEMENT: + handleEndElement(reader, handler); + level--; + if (level == 1) { + return; + } + break; + case XMLStreamConstants.END_DOCUMENT: + handler.endDocument(); + return; + /* + * uncomment to handle all events rather than just mapped ones // StAX events that are not mapped to SAX case XMLStreamConstants.COMMENT: + * case XMLStreamConstants.SPACE: case XMLStreamConstants.ENTITY_REFERENCE: case XMLStreamConstants.DTD: case XMLStreamConstants.CDATA: + * case XMLStreamConstants.NOTATION_DECLARATION: case XMLStreamConstants.ENTITY_DECLARATION: break; // StAX events handled in + * START_ELEMENT case XMLStreamConstants.ATTRIBUTE: case XMLStreamConstants.NAMESPACE: break; default: throw new AssertionError("Unknown + * StAX event: " + event); + */ + } + event = reader.next(); + } + } + + private void handleStartElement(XMLStreamReader reader, ContentHandler handler) throws SAXException { + // send startPrefixMapping events immediately before startElement event + int nsCount = reader.getNamespaceCount(); + for (int i = 0; i < nsCount; i++) { + String prefix = reader.getNamespacePrefix(i); + if (prefix == null) { // true for default namespace + prefix = ""; + } + handler.startPrefixMapping(prefix, reader.getNamespaceURI(i)); + } + + // fire startElement + QName qname = reader.getName(); + String prefix = qname.getPrefix(); + String rawname; + if (prefix == null || prefix.length() == 0) { + rawname = qname.getLocalPart(); + } else { + rawname = prefix + ':' + qname.getLocalPart(); + } + Attributes attrs = getAttributes(reader); + handler.startElement(qname.getNamespaceURI(), qname.getLocalPart(), rawname, attrs); + } + + private static void handleEndElement(XMLStreamReader reader, ContentHandler handler) throws SAXException { + // fire endElement + QName qname = reader.getName(); + handler.endElement(qname.getNamespaceURI(), qname.getLocalPart(), qname.toString()); + + // send endPrefixMapping events immediately after endElement event + // we send them in the opposite order to that returned but this is not actually required by SAX + int nsCount = reader.getNamespaceCount(); + for (int i = nsCount - 1; i >= 0; i--) { + String prefix = reader.getNamespacePrefix(i); + if (prefix == null) { // true for default namespace + prefix = ""; + } + handler.endPrefixMapping(prefix); + } + } + + /** + * Get the attributes associated with the current START_ELEMENT event. + * + * @return the StAX attributes converted to org.xml.sax.Attributes + */ + private Attributes getAttributes(XMLStreamReader reader) { + assert reader.getEventType() == XMLStreamConstants.START_ELEMENT; + + AttributesImpl attrs = new AttributesImpl(); + + // add namespace declarations if required + if (namespacePrefixes) { + for (int i = 0; i < reader.getNamespaceCount(); i++) { + String prefix = reader.getNamespacePrefix(i); + String uri = reader.getNamespaceURI(i); + attrs.addAttribute(null, prefix, "xmlns:" + prefix, "CDATA", uri); + } + } + + // Regular attributes + for (int i = 0; i < reader.getAttributeCount(); i++) { + String uri = reader.getAttributeNamespace(i); + if (uri == null) { + uri = ""; + } + String localName = reader.getAttributeLocalName(i); + String prefix = reader.getAttributePrefix(i); + String qname; + if (prefix == null || prefix.length() == 0) { + qname = localName; + } else { + qname = prefix + ':' + localName; + } + String type = reader.getAttributeType(i); + String value = reader.getAttributeValue(i); + + attrs.addAttribute(uri, localName, qname, type, value); + } + + return attrs; + } + + /** + * Adaptor for mapping Locator information. + */ + private static class LocatorAdaptor implements Locator { + private final Location location; + + private LocatorAdaptor(Location location) { + this.location = location; + } + + public int getColumnNumber() { + return location == null ? 0 : location.getColumnNumber(); + } + + public int getLineNumber() { + return location == null ? 0 : location.getLineNumber(); + } + + public String getPublicId() { + return location == null ? "" : location.getPublicId(); + } + + public String getSystemId() { + return location == null ? "" : location.getSystemId(); + } + } +} diff --git a/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/StreamDeserializer.java b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/StreamDeserializer.java new file mode 100644 index 0000000000..5d7bee9c3f --- /dev/null +++ b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/StreamDeserializer.java @@ -0,0 +1,92 @@ +/**
+ *
+ * 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.util;
+
+import java.util.Comparator;
+
+import javax.xml.XMLConstants;
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.tuscany.sdo.util.resource.RecordedEventXMLStreamReader;
+import org.eclipse.emf.ecore.EDataType;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.emf.ecore.util.ExtendedMetaData;
+import org.eclipse.emf.ecore.xmi.XMLResource;
+import org.eclipse.emf.ecore.xml.type.internal.QName;
+
+/**
+ * StAX Deserializer. The instance isn't thread-safe, however it's safe to use the instance any times on the same thread.
+ */
+public class StreamDeserializer implements XMLStreamConstants {
+ protected XMLStreamReader reader;
+
+ protected final XMLStreamReader play(RecordedEventXMLStreamReader.Tag tag) {
+ return tag.play(reader);
+ }
+
+ protected String nameSpace, name;
+
+ protected final boolean typedXSI() {
+ name = reader.getAttributeValue(ExtendedMetaData.XSI_URI, XMLResource.TYPE);
+ if (name == null)
+ return false;
+ int index = name.indexOf(':');
+ if (index == -1)
+ nameSpace = reader.getNamespaceURI(XMLConstants.DEFAULT_NS_PREFIX); // may be XMLConstants.NULL_NS_URI
+ else {
+ nameSpace = reader.getNamespaceURI(name.substring(0, index));
+ name = name.substring(++index);
+ }
+ return true;
+ }
+
+ static protected Object value(Object type, String literal, NamespaceContext nameSpaces) {
+ Object value = EcoreUtil.createFromString((EDataType) type, literal);
+ if (!(value instanceof QName))
+ return value;
+ QName qName = (QName) value;
+ qName.setNamespaceURI(nameSpaces.getNamespaceURI(qName.getPrefix()));
+ return value;
+ }
+
+ static public class Attribute {
+ public String name, value;
+ }
+
+ static public final class QualifiedAttribute extends Attribute {
+ public String nameSpace;
+ }
+
+ static protected final Comparator EQUAL_NULL = new Comparator() {
+ public int compare(Object v, Object NULL) {
+ return v == null || v.equals(null) ? 0 : 1;
+ }
+ }, EQUAL = new Comparator() {
+ public int compare(Object v, Object value) {
+ return value.equals(v) ? 0 : -1;
+ }
+ }, SAME = new Comparator() {
+ public int compare(Object v, Object value) {
+ return value == v ? 0 : -1;
+ }
+ };
+}
diff --git a/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/metadata/JavaMetaData.java b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/metadata/JavaMetaData.java new file mode 100644 index 0000000000..f24b166f77 --- /dev/null +++ b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/metadata/JavaMetaData.java @@ -0,0 +1,90 @@ +/** + * + * 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.util.metadata; + +import java.io.Serializable; + +/** + * <!-- begin-user-doc --> + * A representation of the model object '<em><b>Java Meta Data</b></em>'. + * <!-- end-user-doc --> + * + * <p> + * The following features are supported: + * <ul> + * <li>{@link org.apache.tuscany.sdo.util.metadata.JavaMetaData#getFactoryInterface <em>Factory Interface</em>}</li> + * <li>{@link org.apache.tuscany.sdo.util.metadata.JavaMetaData#getTypeInterface <em>Type Interface</em>}</li> + * </ul> + * </p> + * + * @extends Serializable + * @generated + */ +public interface JavaMetaData extends Serializable +{ + /** + * Returns the value of the '<em><b>Factory Interface</b></em>' attribute. + * <!-- begin-user-doc --> + * <p> + * If the meaning of the '<em>Factory Interface</em>' attribute isn't clear, + * there really should be more of a description here... + * </p> + * <!-- end-user-doc --> + * @return the value of the '<em>Factory Interface</em>' attribute. + * @see #setFactoryInterface(String) + * @generated + */ + String getFactoryInterface(); + + /** + * Sets the value of the '{@link org.apache.tuscany.sdo.util.metadata.JavaMetaData#getFactoryInterface <em>Factory Interface</em>}' attribute. + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @param value the new value of the '<em>Factory Interface</em>' attribute. + * @see #getFactoryInterface() + * @generated + */ + void setFactoryInterface(String value); + + /** + * Returns the value of the '<em><b>Type Interface</b></em>' attribute. + * <!-- begin-user-doc --> + * <p> + * If the meaning of the '<em>Type Interface</em>' attribute isn't clear, + * there really should be more of a description here... + * </p> + * <!-- end-user-doc --> + * @return the value of the '<em>Type Interface</em>' attribute. + * @see #setTypeInterface(String) + * @generated + */ + String getTypeInterface(); + + /** + * Sets the value of the '{@link org.apache.tuscany.sdo.util.metadata.JavaMetaData#getTypeInterface <em>Type Interface</em>}' attribute. + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @param value the new value of the '<em>Type Interface</em>' attribute. + * @see #getTypeInterface() + * @generated + */ + void setTypeInterface(String value); + +} // JavaMetaData diff --git a/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/metadata/MetadataFactory.java b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/metadata/MetadataFactory.java new file mode 100644 index 0000000000..1f540afa2c --- /dev/null +++ b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/metadata/MetadataFactory.java @@ -0,0 +1,77 @@ +/** + * + * 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.util.metadata; + + +/** + * <!-- begin-user-doc --> + * The <b>Factory</b> for the model. + * It provides a create method for each non-abstract class of the model. + * <!-- end-user-doc --> + * @generated + */ +public interface MetadataFactory +{ + + /** + * The singleton instance of the factory. + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + MetadataFactory INSTANCE = org.apache.tuscany.sdo.util.metadata.impl.MetadataFactoryImpl.init(); + + /** + * Returns a new object of class '<em>Java Meta Data</em>'. + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @return a new object of class '<em>Java Meta Data</em>'. + * @generated + */ + JavaMetaData createJavaMetaData(); + + /** + * Returns a new object of class '<em>SDO Meta Data Group</em>'. + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @return a new object of class '<em>SDO Meta Data Group</em>'. + * @generated + */ + SDOMetaDataGroup createSDOMetaDataGroup(); + + /** + * Returns a new object of class '<em>Type Meta Data</em>'. + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @return a new object of class '<em>Type Meta Data</em>'. + * @generated + */ + TypeMetaData createTypeMetaData(); + + /** + * Returns a new object of class '<em>XSD Meta Data</em>'. + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @return a new object of class '<em>XSD Meta Data</em>'. + * @generated + */ + XSDMetaData createXSDMetaData(); + +} //MetadataFactory diff --git a/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/metadata/SDOMetaDataGroup.java b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/metadata/SDOMetaDataGroup.java new file mode 100644 index 0000000000..5657f26ca5 --- /dev/null +++ b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/metadata/SDOMetaDataGroup.java @@ -0,0 +1,87 @@ +/** + * + * 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.util.metadata; + +import java.io.Serializable; + +import java.util.List; + +/** + * <!-- begin-user-doc --> + * A representation of the model object '<em><b>SDO Meta Data Group</b></em>'. + * <!-- end-user-doc --> + * + * <p> + * The following features are supported: + * <ul> + * <li>{@link org.apache.tuscany.sdo.util.metadata.SDOMetaDataGroup#getJavaMetaData <em>Java Meta Data</em>}</li> + * <li>{@link org.apache.tuscany.sdo.util.metadata.SDOMetaDataGroup#getXsdMetaData <em>Xsd Meta Data</em>}</li> + * <li>{@link org.apache.tuscany.sdo.util.metadata.SDOMetaDataGroup#getTypeMetaData <em>Type Meta Data</em>}</li> + * </ul> + * </p> + * + * @extends Serializable + * @generated + */ +public interface SDOMetaDataGroup extends Serializable +{ + /** + * Returns the value of the '<em><b>Java Meta Data</b></em>' containment reference list. + * The list contents are of type {@link org.apache.tuscany.sdo.util.metadata.JavaMetaData}. + * <!-- begin-user-doc --> + * <p> + * If the meaning of the '<em>Java Meta Data</em>' containment reference list isn't clear, + * there really should be more of a description here... + * </p> + * <!-- end-user-doc --> + * @return the value of the '<em>Java Meta Data</em>' containment reference list. + * @generated + */ + List getJavaMetaData(); + + /** + * Returns the value of the '<em><b>Xsd Meta Data</b></em>' containment reference list. + * The list contents are of type {@link org.apache.tuscany.sdo.util.metadata.XSDMetaData}. + * <!-- begin-user-doc --> + * <p> + * If the meaning of the '<em>Xsd Meta Data</em>' containment reference list isn't clear, + * there really should be more of a description here... + * </p> + * <!-- end-user-doc --> + * @return the value of the '<em>Xsd Meta Data</em>' containment reference list. + * @generated + */ + List getXsdMetaData(); + + /** + * Returns the value of the '<em><b>Type Meta Data</b></em>' containment reference list. + * The list contents are of type {@link org.apache.tuscany.sdo.util.metadata.TypeMetaData}. + * <!-- begin-user-doc --> + * <p> + * If the meaning of the '<em>Type Meta Data</em>' containment reference list isn't clear, + * there really should be more of a description here... + * </p> + * <!-- end-user-doc --> + * @return the value of the '<em>Type Meta Data</em>' containment reference list. + * @generated + */ + List getTypeMetaData(); + +} // SDOMetaDataGroup diff --git a/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/metadata/TypeMetaData.java b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/metadata/TypeMetaData.java new file mode 100644 index 0000000000..c3d67a8318 --- /dev/null +++ b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/metadata/TypeMetaData.java @@ -0,0 +1,65 @@ +/** + * + * 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.util.metadata; + +import java.io.Serializable; + +/** + * <!-- begin-user-doc --> + * A representation of the model object '<em><b>Type Meta Data</b></em>'. + * <!-- end-user-doc --> + * + * <p> + * The following features are supported: + * <ul> + * <li>{@link org.apache.tuscany.sdo.util.metadata.TypeMetaData#getLocation <em>Location</em>}</li> + * </ul> + * </p> + * + * @extends Serializable + * @generated + */ +public interface TypeMetaData extends Serializable +{ + /** + * Returns the value of the '<em><b>Location</b></em>' attribute. + * <!-- begin-user-doc --> + * <p> + * If the meaning of the '<em>Location</em>' attribute isn't clear, + * there really should be more of a description here... + * </p> + * <!-- end-user-doc --> + * @return the value of the '<em>Location</em>' attribute. + * @see #setLocation(String) + * @generated + */ + String getLocation(); + + /** + * Sets the value of the '{@link org.apache.tuscany.sdo.util.metadata.TypeMetaData#getLocation <em>Location</em>}' attribute. + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @param value the new value of the '<em>Location</em>' attribute. + * @see #getLocation() + * @generated + */ + void setLocation(String value); + +} // TypeMetaData diff --git a/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/metadata/XSDMetaData.java b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/metadata/XSDMetaData.java new file mode 100644 index 0000000000..09bffece71 --- /dev/null +++ b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/metadata/XSDMetaData.java @@ -0,0 +1,66 @@ +/** + * + * 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.util.metadata; + +import java.io.Serializable; + +/** + * <!-- begin-user-doc --> + * A representation of the model object '<em><b>XSD Meta Data</b></em>'. + * <!-- end-user-doc --> + * + * <p> + * The following features are supported: + * <ul> + * <li>{@link org.apache.tuscany.sdo.util.metadata.XSDMetaData#getLocation <em>Location</em>}</li> + * </ul> + * </p> + * + * @extends Serializable + * @generated + */ +public interface XSDMetaData extends Serializable +{ + /** + * Returns the value of the '<em><b>Location</b></em>' attribute. + * <!-- begin-user-doc --> + * <p> + * If the meaning of the '<em>Location</em>' attribute isn't clear, + * there really should be more of a description here... + * </p> + * <!-- end-user-doc --> + * @return the value of the '<em>Location</em>' attribute. + * @see #setLocation(String) + * @generated + */ + String getLocation(); + + /** + * Sets the value of the '{@link org.apache.tuscany.sdo.util.metadata.XSDMetaData#getLocation <em>Location</em>}' attribute. + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @param value the new value of the '<em>Location</em>' attribute. + * @see #getLocation() + * @generated + */ + void setLocation(String value); + +} // XSDMetaData diff --git a/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/metadata/impl/JavaMetaDataImpl.java b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/metadata/impl/JavaMetaDataImpl.java new file mode 100644 index 0000000000..ea55034299 --- /dev/null +++ b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/metadata/impl/JavaMetaDataImpl.java @@ -0,0 +1,267 @@ +/** + * + * 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.util.metadata.impl; + +import commonj.sdo.Type; + +import org.apache.tuscany.sdo.impl.DataObjectBase; + +import org.apache.tuscany.sdo.util.metadata.JavaMetaData; +import org.apache.tuscany.sdo.util.metadata.MetadataFactory; + +/** + * <!-- begin-user-doc --> + * An implementation of the model object '<em><b>Java Meta Data</b></em>'. + * <!-- end-user-doc --> + * <p> + * The following features are implemented: + * <ul> + * <li>{@link org.apache.tuscany.sdo.util.metadata.impl.JavaMetaDataImpl#getFactoryInterface <em>Factory Interface</em>}</li> + * <li>{@link org.apache.tuscany.sdo.util.metadata.impl.JavaMetaDataImpl#getTypeInterface <em>Type Interface</em>}</li> + * </ul> + * </p> + * + * @generated + */ +public class JavaMetaDataImpl extends DataObjectBase implements JavaMetaData +{ + /** + * The feature id for the '<em><b>Factory Interface</b></em>' attribute. + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + * @ordered + */ + public final static int FACTORY_INTERFACE = 0; + + /** + * The feature id for the '<em><b>Type Interface</b></em>' attribute. + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + * @ordered + */ + public final static int TYPE_INTERFACE = 1; + + /** + * This represents the number of properties for this type. + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + * @ordered + */ + + public final static int SDO_PROPERTY_COUNT = 2; + + /** + * The default value of the '{@link #getFactoryInterface() <em>Factory Interface</em>}' attribute. + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @see #getFactoryInterface() + * @generated + * @ordered + */ + protected static final String FACTORY_INTERFACE_DEFAULT_ = null; + + /** + * The cached value of the '{@link #getFactoryInterface() <em>Factory Interface</em>}' attribute. + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @see #getFactoryInterface() + * @generated + * @ordered + */ + protected String factoryInterface = FACTORY_INTERFACE_DEFAULT_; + + /** + * The default value of the '{@link #getTypeInterface() <em>Type Interface</em>}' attribute. + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @see #getTypeInterface() + * @generated + * @ordered + */ + protected static final String TYPE_INTERFACE_DEFAULT_ = null; + + /** + * The cached value of the '{@link #getTypeInterface() <em>Type Interface</em>}' attribute. + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @see #getTypeInterface() + * @generated + * @ordered + */ + protected String typeInterface = TYPE_INTERFACE_DEFAULT_; + + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + protected JavaMetaDataImpl() + { + super(); + } + + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + public Type getType() + { + return ((MetadataFactoryImpl)MetadataFactory.INSTANCE).getJavaMetaData(); + } + + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + public String getFactoryInterface() + { + return factoryInterface; + } + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + public void setFactoryInterface(String newFactoryInterface) + { + String oldFactoryInterface = factoryInterface; + factoryInterface = newFactoryInterface; + if (isNotifying()) + notify(ChangeKind.SET, FACTORY_INTERFACE, oldFactoryInterface, factoryInterface); + } + + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + public String getTypeInterface() + { + return typeInterface; + } + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + public void setTypeInterface(String newTypeInterface) + { + String oldTypeInterface = typeInterface; + typeInterface = newTypeInterface; + if (isNotifying()) + notify(ChangeKind.SET, TYPE_INTERFACE, oldTypeInterface, typeInterface); + } + + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + public Object get(int propertyIndex, boolean resolve) + { + switch (propertyIndex) + { + case FACTORY_INTERFACE: + return getFactoryInterface(); + case TYPE_INTERFACE: + return getTypeInterface(); + } + return super.get(propertyIndex, resolve); + } + + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + public void set(int propertyIndex, Object newValue) + { + switch (propertyIndex) + { + case FACTORY_INTERFACE: + setFactoryInterface((String)newValue); + return; + case TYPE_INTERFACE: + setTypeInterface((String)newValue); + return; + } + super.set(propertyIndex, newValue); + } + + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + public void unset(int propertyIndex) + { + switch (propertyIndex) + { + case FACTORY_INTERFACE: + setFactoryInterface(FACTORY_INTERFACE_DEFAULT_); + return; + case TYPE_INTERFACE: + setTypeInterface(TYPE_INTERFACE_DEFAULT_); + return; + } + super.unset(propertyIndex); + } + + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + public boolean isSet(int propertyIndex) + { + switch (propertyIndex) + { + case FACTORY_INTERFACE: + return FACTORY_INTERFACE_DEFAULT_ == null ? factoryInterface != null : !FACTORY_INTERFACE_DEFAULT_.equals(factoryInterface); + case TYPE_INTERFACE: + return TYPE_INTERFACE_DEFAULT_ == null ? typeInterface != null : !TYPE_INTERFACE_DEFAULT_.equals(typeInterface); + } + return super.isSet(propertyIndex); + } + + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + public String toString() + { + if (isProxy(this)) return super.toString(); + + StringBuffer result = new StringBuffer(super.toString()); + result.append(" (factoryInterface: "); + result.append(factoryInterface); + result.append(", typeInterface: "); + result.append(typeInterface); + result.append(')'); + return result.toString(); + } + +} //JavaMetaDataImpl diff --git a/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/metadata/impl/MetadataFactoryImpl.java b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/metadata/impl/MetadataFactoryImpl.java new file mode 100644 index 0000000000..a4ea322549 --- /dev/null +++ b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/metadata/impl/MetadataFactoryImpl.java @@ -0,0 +1,367 @@ +/** + * + * 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.util.metadata.impl; + +import commonj.sdo.DataObject; +import commonj.sdo.Property; +import commonj.sdo.Type; + +import org.apache.tuscany.sdo.SDOFactory; + +import org.apache.tuscany.sdo.impl.FactoryBase; + +import org.apache.tuscany.sdo.model.ModelFactory; + +import org.apache.tuscany.sdo.model.impl.ModelFactoryImpl; + +import org.apache.tuscany.sdo.util.SDOUtil; + +import org.apache.tuscany.sdo.util.metadata.*; + +/** + * <!-- begin-user-doc --> + * An implementation of the model <b>Factory</b>. + * <!-- end-user-doc --> + * @generated + */ +public class MetadataFactoryImpl extends FactoryBase implements MetadataFactory +{ + + /** + * The package namespace URI. + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + public static final String NAMESPACE_URI = "org.apache.tuscany.sdo/metadata"; + + /** + * The package namespace name. + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + public static final String NAMESPACE_PREFIX = "metadata"; + public static final int JAVA_META_DATA = 1; + public static final int SDO_META_DATA_GROUP = 2; + public static final int TYPE_META_DATA = 3; + public static final int XSD_META_DATA = 4; + + /** + * Creates an instance of the factory. + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + public MetadataFactoryImpl() + { + super(NAMESPACE_URI, NAMESPACE_PREFIX); + } + + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + public DataObject create(int typeNumber) + { + switch (typeNumber) + { + case JAVA_META_DATA: return (DataObject)createJavaMetaData(); + case SDO_META_DATA_GROUP: return (DataObject)createSDOMetaDataGroup(); + case TYPE_META_DATA: return (DataObject)createTypeMetaData(); + case XSD_META_DATA: return (DataObject)createXSDMetaData(); + default: + return super.create(typeNumber); + } + } + + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + public JavaMetaData createJavaMetaData() + { + JavaMetaDataImpl javaMetaData = new JavaMetaDataImpl(); + return javaMetaData; + } + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + public SDOMetaDataGroup createSDOMetaDataGroup() + { + SDOMetaDataGroupImpl sdoMetaDataGroup = new SDOMetaDataGroupImpl(); + return sdoMetaDataGroup; + } + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + public TypeMetaData createTypeMetaData() + { + TypeMetaDataImpl typeMetaData = new TypeMetaDataImpl(); + return typeMetaData; + } + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + public XSDMetaData createXSDMetaData() + { + XSDMetaDataImpl xsdMetaData = new XSDMetaDataImpl(); + return xsdMetaData; + } + + // Following creates and initializes SDO metadata for the supported types. + protected Type javaMetaDataType = null; + + public Type getJavaMetaData() + { + return javaMetaDataType; + } + + protected Type sdoMetaDataGroupType = null; + + public Type getSDOMetaDataGroup() + { + return sdoMetaDataGroupType; + } + + protected Type typeMetaDataType = null; + + public Type getTypeMetaData() + { + return typeMetaDataType; + } + + protected Type xsdMetaDataType = null; + + public Type getXSDMetaData() + { + return xsdMetaDataType; + } + + + private static boolean isInited = false; + + public static MetadataFactoryImpl init() + { + if (isInited) return (MetadataFactoryImpl)FactoryBase.getStaticFactory(MetadataFactoryImpl.NAMESPACE_URI); + MetadataFactoryImpl theMetadataFactoryImpl = new MetadataFactoryImpl(); + isInited = true; + + // Initialize simple dependencies + SDOUtil.registerStaticTypes(SDOFactory.class); + SDOUtil.registerStaticTypes(ModelFactory.class); + + // Create package meta-data objects + theMetadataFactoryImpl.createMetaData(); + + // Initialize created meta-data + theMetadataFactoryImpl.initializeMetaData(); + + // Mark meta-data to indicate it can't be changed + //theMetadataFactoryImpl.freeze(); //FB do we need to freeze / should we freeze ???? + + return theMetadataFactoryImpl; + } + + private boolean isCreated = false; + + public void createMetaData() + { + if (isCreated) return; + isCreated = true; + + + javaMetaDataType = createType(false, JAVA_META_DATA); + createProperty(true, javaMetaDataType, JavaMetaDataImpl.FACTORY_INTERFACE); + createProperty(true, javaMetaDataType, JavaMetaDataImpl.TYPE_INTERFACE); + + sdoMetaDataGroupType = createType(false, SDO_META_DATA_GROUP); + createProperty(false, sdoMetaDataGroupType, SDOMetaDataGroupImpl.JAVA_META_DATA); + createProperty(false, sdoMetaDataGroupType, SDOMetaDataGroupImpl.XSD_META_DATA); + createProperty(false, sdoMetaDataGroupType, SDOMetaDataGroupImpl.TYPE_META_DATA); + + typeMetaDataType = createType(false, TYPE_META_DATA); + createProperty(true, typeMetaDataType, TypeMetaDataImpl.LOCATION); + + xsdMetaDataType = createType(false, XSD_META_DATA); + createProperty(true, xsdMetaDataType, XSDMetaDataImpl.LOCATION); + } + + private boolean isInitialized = false; + + public void initializeMetaData() + { + if (isInitialized) return; + isInitialized = true; + + // Obtain other dependent packages + ModelFactoryImpl theModelPackageImpl = (ModelFactoryImpl)FactoryBase.getStaticFactory(ModelFactoryImpl.NAMESPACE_URI); + Property property = null; + + // Add supertypes to classes + + // Initialize classes and features; add operations and parameters + initializeType(javaMetaDataType, JavaMetaData.class, "JavaMetaData"); + + property = (Property)javaMetaDataType.getProperties().get(JavaMetaDataImpl.FACTORY_INTERFACE); + initializeProperty(property, theModelPackageImpl.getString(), "factoryInterface", null, 0, 1, JavaMetaData.class, false, false, false); + + property = (Property)javaMetaDataType.getProperties().get(JavaMetaDataImpl.TYPE_INTERFACE); + initializeProperty(property, theModelPackageImpl.getString(), "typeInterface", null, 0, 1, JavaMetaData.class, false, false, false); + + initializeType(sdoMetaDataGroupType, SDOMetaDataGroup.class, "SDOMetaDataGroup"); + + property = (Property)sdoMetaDataGroupType.getProperties().get(SDOMetaDataGroupImpl.JAVA_META_DATA); + initializeProperty(property, this.getJavaMetaData(), "javaMetaData", null, 0, -1, SDOMetaDataGroup.class, false, false, false, true , null); + + property = (Property)sdoMetaDataGroupType.getProperties().get(SDOMetaDataGroupImpl.XSD_META_DATA); + initializeProperty(property, this.getXSDMetaData(), "xsdMetaData", null, 0, -1, SDOMetaDataGroup.class, false, false, false, true , null); + + property = (Property)sdoMetaDataGroupType.getProperties().get(SDOMetaDataGroupImpl.TYPE_META_DATA); + initializeProperty(property, this.getTypeMetaData(), "typeMetaData", null, 0, -1, SDOMetaDataGroup.class, false, false, false, true , null); + + initializeType(typeMetaDataType, TypeMetaData.class, "TypeMetaData"); + + property = (Property)typeMetaDataType.getProperties().get(TypeMetaDataImpl.LOCATION); + initializeProperty(property, theModelPackageImpl.getString(), "location", null, 1, 1, TypeMetaData.class, false, false, false); + + initializeType(xsdMetaDataType, XSDMetaData.class, "XSDMetaData"); + + property = (Property)xsdMetaDataType.getProperties().get(XSDMetaDataImpl.LOCATION); + initializeProperty(property, theModelPackageImpl.getString(), "location", null, 1, 1, XSDMetaData.class, false, false, false); + + createXSDMetaData(theModelPackageImpl); + } + + protected void createXSDMetaData(ModelFactoryImpl theModelPackageImpl) + { + super.initXSD(); + + Property property = null; + + property = createGlobalProperty + ("sdoMetaDataGroup", + this.getSDOMetaDataGroup(), + new String[] + { + "kind", "element", + "name", "sdoMetaDataGroup", + "namespace", "##targetNamespace" + }); + + addXSDMapping + (javaMetaDataType, + new String[] + { + "name", "JavaMetaData", + "kind", "empty" + }); + + addXSDMapping + ((Property)javaMetaDataType.getProperties().get(JavaMetaDataImpl.FACTORY_INTERFACE), + new String[] + { + "kind", "attribute", + "name", "factoryInterface" + }); + + addXSDMapping + ((Property)javaMetaDataType.getProperties().get(JavaMetaDataImpl.TYPE_INTERFACE), + new String[] + { + "kind", "attribute", + "name", "typeInterface" + }); + + addXSDMapping + (sdoMetaDataGroupType, + new String[] + { + "name", "SDOMetaDataGroup", + "kind", "elementOnly" + }); + + addXSDMapping + ((Property)sdoMetaDataGroupType.getProperties().get(SDOMetaDataGroupImpl.JAVA_META_DATA), + new String[] + { + "kind", "element", + "name", "javaMetaData" + }); + + addXSDMapping + ((Property)sdoMetaDataGroupType.getProperties().get(SDOMetaDataGroupImpl.XSD_META_DATA), + new String[] + { + "kind", "element", + "name", "xsdMetaData" + }); + + addXSDMapping + ((Property)sdoMetaDataGroupType.getProperties().get(SDOMetaDataGroupImpl.TYPE_META_DATA), + new String[] + { + "kind", "element", + "name", "typeMetaData" + }); + + addXSDMapping + (typeMetaDataType, + new String[] + { + "name", "TypeMetaData", + "kind", "empty" + }); + + addXSDMapping + ((Property)typeMetaDataType.getProperties().get(TypeMetaDataImpl.LOCATION), + new String[] + { + "kind", "attribute", + "name", "location" + }); + + addXSDMapping + (xsdMetaDataType, + new String[] + { + "name", "XSDMetaData", + "kind", "empty" + }); + + addXSDMapping + ((Property)xsdMetaDataType.getProperties().get(XSDMetaDataImpl.LOCATION), + new String[] + { + "kind", "attribute", + "name", "location" + }); + + } + +} //MetadataFactoryImpl diff --git a/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/metadata/impl/SDOMetaDataGroupImpl.java b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/metadata/impl/SDOMetaDataGroupImpl.java new file mode 100644 index 0000000000..3714eb7124 --- /dev/null +++ b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/metadata/impl/SDOMetaDataGroupImpl.java @@ -0,0 +1,285 @@ +/** + * + * 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.util.metadata.impl; + +import commonj.sdo.Type; + +import java.util.Collection; +import java.util.List; + +import org.apache.tuscany.sdo.impl.DataObjectBase; + +import org.apache.tuscany.sdo.util.metadata.JavaMetaData; +import org.apache.tuscany.sdo.util.metadata.MetadataFactory; +import org.apache.tuscany.sdo.util.metadata.SDOMetaDataGroup; +import org.apache.tuscany.sdo.util.metadata.TypeMetaData; +import org.apache.tuscany.sdo.util.metadata.XSDMetaData; + +/** + * <!-- begin-user-doc --> + * An implementation of the model object '<em><b>SDO Meta Data Group</b></em>'. + * <!-- end-user-doc --> + * <p> + * The following features are implemented: + * <ul> + * <li>{@link org.apache.tuscany.sdo.util.metadata.impl.SDOMetaDataGroupImpl#getJavaMetaData <em>Java Meta Data</em>}</li> + * <li>{@link org.apache.tuscany.sdo.util.metadata.impl.SDOMetaDataGroupImpl#getXsdMetaData <em>Xsd Meta Data</em>}</li> + * <li>{@link org.apache.tuscany.sdo.util.metadata.impl.SDOMetaDataGroupImpl#getTypeMetaData <em>Type Meta Data</em>}</li> + * </ul> + * </p> + * + * @generated + */ +public class SDOMetaDataGroupImpl extends DataObjectBase implements SDOMetaDataGroup +{ + /** + * The feature id for the '<em><b>Java Meta Data</b></em>' containment reference list. + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + * @ordered + */ + public final static int JAVA_META_DATA = 0; + + /** + * The feature id for the '<em><b>Xsd Meta Data</b></em>' containment reference list. + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + * @ordered + */ + public final static int XSD_META_DATA = 1; + + /** + * The feature id for the '<em><b>Type Meta Data</b></em>' containment reference list. + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + * @ordered + */ + public final static int TYPE_META_DATA = 2; + + /** + * This represents the number of properties for this type. + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + * @ordered + */ + + public final static int SDO_PROPERTY_COUNT = 3; + + /** + * The cached value of the '{@link #getJavaMetaData() <em>Java Meta Data</em>}' containment reference list. + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @see #getJavaMetaData() + * @generated + * @ordered + */ + + protected List javaMetaData = null; + + /** + * The cached value of the '{@link #getXsdMetaData() <em>Xsd Meta Data</em>}' containment reference list. + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @see #getXsdMetaData() + * @generated + * @ordered + */ + + protected List xsdMetaData = null; + + /** + * The cached value of the '{@link #getTypeMetaData() <em>Type Meta Data</em>}' containment reference list. + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @see #getTypeMetaData() + * @generated + * @ordered + */ + + protected List typeMetaData = null; + + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + protected SDOMetaDataGroupImpl() + { + super(); + } + + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + public Type getType() + { + return ((MetadataFactoryImpl)MetadataFactory.INSTANCE).getSDOMetaDataGroup(); + } + + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + public List getJavaMetaData() + { + if (javaMetaData == null) + { + javaMetaData = createPropertyList(ListKind.CONTAINMENT, JavaMetaData.class, JAVA_META_DATA); + } + return javaMetaData; + } + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + public List getXsdMetaData() + { + if (xsdMetaData == null) + { + xsdMetaData = createPropertyList(ListKind.CONTAINMENT, XSDMetaData.class, XSD_META_DATA); + } + return xsdMetaData; + } + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + public List getTypeMetaData() + { + if (typeMetaData == null) + { + typeMetaData = createPropertyList(ListKind.CONTAINMENT, TypeMetaData.class, TYPE_META_DATA); + } + return typeMetaData; + } + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + public ChangeContext inverseRemove(Object otherEnd, int propertyIndex, ChangeContext changeContext) + { + switch (propertyIndex) + { + case JAVA_META_DATA: + return removeFromList(getJavaMetaData(), otherEnd, changeContext); + case XSD_META_DATA: + return removeFromList(getXsdMetaData(), otherEnd, changeContext); + case TYPE_META_DATA: + return removeFromList(getTypeMetaData(), otherEnd, changeContext); + } + return super.inverseRemove(otherEnd, propertyIndex, changeContext); + } + + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + public Object get(int propertyIndex, boolean resolve) + { + switch (propertyIndex) + { + case JAVA_META_DATA: + return getJavaMetaData(); + case XSD_META_DATA: + return getXsdMetaData(); + case TYPE_META_DATA: + return getTypeMetaData(); + } + return super.get(propertyIndex, resolve); + } + + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + public void set(int propertyIndex, Object newValue) + { + switch (propertyIndex) + { + case JAVA_META_DATA: + getJavaMetaData().clear(); + getJavaMetaData().addAll((Collection)newValue); + return; + case XSD_META_DATA: + getXsdMetaData().clear(); + getXsdMetaData().addAll((Collection)newValue); + return; + case TYPE_META_DATA: + getTypeMetaData().clear(); + getTypeMetaData().addAll((Collection)newValue); + return; + } + super.set(propertyIndex, newValue); + } + + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + public void unset(int propertyIndex) + { + switch (propertyIndex) + { + case JAVA_META_DATA: + getJavaMetaData().clear(); + return; + case XSD_META_DATA: + getXsdMetaData().clear(); + return; + case TYPE_META_DATA: + getTypeMetaData().clear(); + return; + } + super.unset(propertyIndex); + } + + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + public boolean isSet(int propertyIndex) + { + switch (propertyIndex) + { + case JAVA_META_DATA: + return javaMetaData != null && !javaMetaData.isEmpty(); + case XSD_META_DATA: + return xsdMetaData != null && !xsdMetaData.isEmpty(); + case TYPE_META_DATA: + return typeMetaData != null && !typeMetaData.isEmpty(); + } + return super.isSet(propertyIndex); + } + +} //SDOMetaDataGroupImpl diff --git a/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/metadata/impl/TypeMetaDataImpl.java b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/metadata/impl/TypeMetaDataImpl.java new file mode 100644 index 0000000000..a1fddf6f95 --- /dev/null +++ b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/metadata/impl/TypeMetaDataImpl.java @@ -0,0 +1,203 @@ +/** + * + * 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.util.metadata.impl; + +import commonj.sdo.Type; + +import org.apache.tuscany.sdo.impl.DataObjectBase; + +import org.apache.tuscany.sdo.util.metadata.MetadataFactory; +import org.apache.tuscany.sdo.util.metadata.TypeMetaData; + +/** + * <!-- begin-user-doc --> + * An implementation of the model object '<em><b>Type Meta Data</b></em>'. + * <!-- end-user-doc --> + * <p> + * The following features are implemented: + * <ul> + * <li>{@link org.apache.tuscany.sdo.util.metadata.impl.TypeMetaDataImpl#getLocation <em>Location</em>}</li> + * </ul> + * </p> + * + * @generated + */ +public class TypeMetaDataImpl extends DataObjectBase implements TypeMetaData +{ + /** + * The feature id for the '<em><b>Location</b></em>' attribute. + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + * @ordered + */ + public final static int LOCATION = 0; + + /** + * This represents the number of properties for this type. + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + * @ordered + */ + + public final static int SDO_PROPERTY_COUNT = 1; + + /** + * The default value of the '{@link #getLocation() <em>Location</em>}' attribute. + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @see #getLocation() + * @generated + * @ordered + */ + protected static final String LOCATION_DEFAULT_ = null; + + /** + * The cached value of the '{@link #getLocation() <em>Location</em>}' attribute. + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @see #getLocation() + * @generated + * @ordered + */ + protected String location = LOCATION_DEFAULT_; + + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + protected TypeMetaDataImpl() + { + super(); + } + + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + public Type getType() + { + return ((MetadataFactoryImpl)MetadataFactory.INSTANCE).getTypeMetaData(); + } + + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + public String getLocation() + { + return location; + } + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + public void setLocation(String newLocation) + { + String oldLocation = location; + location = newLocation; + if (isNotifying()) + notify(ChangeKind.SET, LOCATION, oldLocation, location); + } + + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + public Object get(int propertyIndex, boolean resolve) + { + switch (propertyIndex) + { + case LOCATION: + return getLocation(); + } + return super.get(propertyIndex, resolve); + } + + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + public void set(int propertyIndex, Object newValue) + { + switch (propertyIndex) + { + case LOCATION: + setLocation((String)newValue); + return; + } + super.set(propertyIndex, newValue); + } + + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + public void unset(int propertyIndex) + { + switch (propertyIndex) + { + case LOCATION: + setLocation(LOCATION_DEFAULT_); + return; + } + super.unset(propertyIndex); + } + + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + public boolean isSet(int propertyIndex) + { + switch (propertyIndex) + { + case LOCATION: + return LOCATION_DEFAULT_ == null ? location != null : !LOCATION_DEFAULT_.equals(location); + } + return super.isSet(propertyIndex); + } + + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + public String toString() + { + if (isProxy(this)) return super.toString(); + + StringBuffer result = new StringBuffer(super.toString()); + result.append(" (location: "); + result.append(location); + result.append(')'); + return result.toString(); + } + +} //TypeMetaDataImpl diff --git a/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/metadata/impl/XSDMetaDataImpl.java b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/metadata/impl/XSDMetaDataImpl.java new file mode 100644 index 0000000000..68b68fbaac --- /dev/null +++ b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/metadata/impl/XSDMetaDataImpl.java @@ -0,0 +1,203 @@ +/** + * + * 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.util.metadata.impl; + +import commonj.sdo.Type; + +import org.apache.tuscany.sdo.impl.DataObjectBase; + +import org.apache.tuscany.sdo.util.metadata.MetadataFactory; +import org.apache.tuscany.sdo.util.metadata.XSDMetaData; + +/** + * <!-- begin-user-doc --> + * An implementation of the model object '<em><b>XSD Meta Data</b></em>'. + * <!-- end-user-doc --> + * <p> + * The following features are implemented: + * <ul> + * <li>{@link org.apache.tuscany.sdo.util.metadata.impl.XSDMetaDataImpl#getLocation <em>Location</em>}</li> + * </ul> + * </p> + * + * @generated + */ +public class XSDMetaDataImpl extends DataObjectBase implements XSDMetaData +{ + /** + * The feature id for the '<em><b>Location</b></em>' attribute. + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + * @ordered + */ + public final static int LOCATION = 0; + + /** + * This represents the number of properties for this type. + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + * @ordered + */ + + public final static int SDO_PROPERTY_COUNT = 1; + + /** + * The default value of the '{@link #getLocation() <em>Location</em>}' attribute. + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @see #getLocation() + * @generated + * @ordered + */ + protected static final String LOCATION_DEFAULT_ = null; + + /** + * The cached value of the '{@link #getLocation() <em>Location</em>}' attribute. + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @see #getLocation() + * @generated + * @ordered + */ + protected String location = LOCATION_DEFAULT_; + + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + protected XSDMetaDataImpl() + { + super(); + } + + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + public Type getType() + { + return ((MetadataFactoryImpl)MetadataFactory.INSTANCE).getXSDMetaData(); + } + + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + public String getLocation() + { + return location; + } + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + public void setLocation(String newLocation) + { + String oldLocation = location; + location = newLocation; + if (isNotifying()) + notify(ChangeKind.SET, LOCATION, oldLocation, location); + } + + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + public Object get(int propertyIndex, boolean resolve) + { + switch (propertyIndex) + { + case LOCATION: + return getLocation(); + } + return super.get(propertyIndex, resolve); + } + + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + public void set(int propertyIndex, Object newValue) + { + switch (propertyIndex) + { + case LOCATION: + setLocation((String)newValue); + return; + } + super.set(propertyIndex, newValue); + } + + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + public void unset(int propertyIndex) + { + switch (propertyIndex) + { + case LOCATION: + setLocation(LOCATION_DEFAULT_); + return; + } + super.unset(propertyIndex); + } + + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + public boolean isSet(int propertyIndex) + { + switch (propertyIndex) + { + case LOCATION: + return LOCATION_DEFAULT_ == null ? location != null : !LOCATION_DEFAULT_.equals(location); + } + return super.isSet(propertyIndex); + } + + /** + * <!-- begin-user-doc --> + * <!-- end-user-doc --> + * @generated + */ + public String toString() + { + if (isProxy(this)) return super.toString(); + + StringBuffer result = new StringBuffer(super.toString()); + result.append(" (location: "); + result.append(location); + result.append(')'); + return result.toString(); + } + +} //XSDMetaDataImpl diff --git a/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/ChangeSummaryStreamDeserializer.java b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/ChangeSummaryStreamDeserializer.java new file mode 100644 index 0000000000..6dc461a2fe --- /dev/null +++ b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/ChangeSummaryStreamDeserializer.java @@ -0,0 +1,663 @@ +/**
+ *
+ * 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.util.resource;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.tuscany.sdo.SDOFactory;
+import org.apache.tuscany.sdo.helper.SDOAnnotations;
+import org.apache.tuscany.sdo.impl.ChangeSummaryImpl;
+import org.apache.tuscany.sdo.impl.ClassImpl;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.ETypedElement;
+import org.eclipse.emf.ecore.change.ChangeDescription;
+import org.eclipse.emf.ecore.change.ChangeFactory;
+import org.eclipse.emf.ecore.change.ChangeKind;
+import org.eclipse.emf.ecore.change.FeatureChange;
+import org.eclipse.emf.ecore.change.FeatureMapEntry;
+import org.eclipse.emf.ecore.change.ListChange;
+import org.eclipse.emf.ecore.util.FeatureMap;
+import org.eclipse.emf.ecore.util.FeatureMapUtil;
+
+import commonj.sdo.ChangeSummary;
+import commonj.sdo.DataObject;
+import commonj.sdo.Property;
+import commonj.sdo.Type;
+import commonj.sdo.helper.HelperContext;
+
+/**
+ * ChangeSummary StAX Deserializer whose input conforms to the SDO Java/C++/PHP specifications. The instance isn't thread-safe, however it's safe to
+ * use the instance any times on the same thread.
+ */
+public class ChangeSummaryStreamDeserializer extends SDODeserializer {
+ static final class ForwardReference extends Ref {
+ final String unset;
+
+ ForwardReference(String ref, NamespaceContext nameSpaces, String u) {
+ super(ref, nameSpaces);
+ unset = u;
+ }
+
+ Collection attributes/* = null */, qualifiedAttributes/* = null */, tags/* = null */; // may be null, never empty
+ }
+
+ protected Collection forwardReferences/* = null */;
+
+ static private final class ElementChange extends Ref {
+ private final Object containing, containment;
+ private ElementChange(String ref, NamespaceContext nameSpaces, Object property, Object propertyInSequence) {
+ super(ref, nameSpaces);
+ containing = property;
+ containment = propertyInSequence;
+ }
+ }
+
+ static private class PropertyMapChanges {
+ Map/* Property,List */lists/* = null */;// may be null
+
+ Collection put(Object property) {
+ Collection list = new ArrayList();
+ lists.put(property, list);
+ return list;
+ }
+
+ protected final Collection get(Object property) {
+ Object list = lists.get(property);
+ return list == null ? put(property) : (Collection) list;
+ }
+
+ protected final Collection newList(Object property) {
+ lists = new HashMap();
+ return put(property);
+ }
+ }
+
+ static final class ObjectChanges extends PropertyMapChanges {
+ Collection elementChanges/* = null */,// may be null, never empty
+ featureChanges;
+
+ protected final void newElementChanges() {
+ elementChanges = new ArrayList();
+ }
+ }
+
+ Collection objectChangesCollection/* = null */, objectMapChanges, deletedDataObjects;
+
+ protected final ObjectChanges newObjectChanges(Collection featureChanges) {
+ ObjectChanges objectChanges = new ObjectChanges();
+ objectChanges.featureChanges = featureChanges;
+ if (objectChangesCollection == null)
+ objectChangesCollection = new ArrayList();
+ objectChangesCollection.add(objectChanges);
+ return objectChanges;
+ }
+
+ private ChangeFactory changeFactory;
+
+ private SDOFactory changeSettingFactory;
+
+ private void logPropertyChange(Collection featureChanges, EStructuralFeature feature, Object value, boolean set) {
+ if (changeSettingFactory == null)
+ featureChanges.add(changeFactory.createFeatureChange(feature, value, set));
+ else
+ featureChanges.add(changeSettingFactory.createChangeSummarySetting(feature, value, set));
+ }
+
+ void unsetProperty(Collection featureChanges, String unset, int begin, int index, Type type) {
+ logPropertyChange(featureChanges, (EStructuralFeature) type.getProperty(unset.substring(begin, index)), null, false);
+ }
+
+ static boolean isWhitespace(String unset, int index) {
+ return Character.isWhitespace(unset.charAt(index));
+ }
+
+ protected final Collection unsetProperties(EObject referent, String unset, Type type) {
+ Map.Entry entry = changeFactory.createEObjectToChangesMapEntry(referent);
+ objectMapChanges.add(entry);
+ Collection featureChanges = (Collection) entry.getValue();
+ if (unset == null)
+ return featureChanges;
+ int end = unset.length();
+ if (end != 0)
+ for (int begin = 0, index = 1;/* true */; ++index) {
+ if (index == end) {
+ unsetProperty(featureChanges, unset, begin, index, type);
+ break;
+ }
+ if (isWhitespace(unset, index)) {
+ unsetProperty(featureChanges, unset, begin, index, type);
+ while (true) {
+ if (++index != end)
+ return featureChanges;
+ if (!isWhitespace(unset, index)) {
+ begin = index;
+ break;
+ }
+ }
+ }
+ }
+ return featureChanges;
+ }
+
+ private Object value(EStructuralFeature containing, Object containment, Object value) {
+ return FeatureMapUtil.isFeatureMap(containing) ? changeFactory.createFeatureMapEntry((EStructuralFeature) containment, value) : value;
+ }
+
+ private void logPropertyChange(Collection featureChanges, Object containing, Object containment, Object value) {
+ EStructuralFeature feature = (EStructuralFeature) containing;
+ logPropertyChange(featureChanges, feature, value(feature, containment, value), true);
+ }
+
+ private void logPropertyChange(Collection featureChanges, Object property, Object value) {
+ logPropertyChange(featureChanges, property, propertyInSequence, value);
+ }
+
+ void logAttributeChange(Collection featureChanges, Property property, String literal, NamespaceContext nameSpaces) {
+ logPropertyChange(featureChanges, property, value(property.getType(), literal, nameSpaces));
+ }
+
+ protected final void logAttributeChange(Collection featureChanges, String property, Type type, String value, NamespaceContext nameSpaces) {
+ logAttributeChange(featureChanges, getProperty(type, property), value, nameSpaces);
+ }
+
+ protected final void logAttributeChange(Collection featureChanges, String nameSpace, String name, Type type, String value,
+ NamespaceContext nameSpaces) {
+ logAttributeChange(featureChanges, getProperty(type, nameSpace, name, false), value, nameSpaces);
+ }
+
+ protected final String ref() {
+ return reader.getAttributeValue(SDOAnnotations.COMMONJ_SDO_NS, ChangeSummaryStreamSerializer.REF_ATTRIBUTE);
+ }
+
+ ChangeSummaryImpl changeSummary;
+
+ protected Object load(XMLStreamReader reader, Map options) throws XMLStreamException {
+ Object value = super.load(reader, options);
+ deletedDataObjects.add(value);
+ return value;
+ }
+
+ protected final void getChangeSummary(DataObject rootObject) {
+ changeSummary = (ChangeSummaryImpl) rootObject.getChangeSummary(); // DynamicDataObjectImpl(EClass)
+ }
+
+ static protected final class Tag extends RecordedEventXMLStreamReader.Tag {
+ protected String ref;
+
+ protected Object value;
+
+ protected Tag(XMLStreamReader reader) {
+ super(reader);
+ }
+ }
+
+ protected final void addPropertyChange(Collection list, Object value, Object containing) {
+ list.add(value((EStructuralFeature) containing, propertyInSequence, value));
+ }
+
+ protected boolean logging;
+
+ /**
+ * Imports ChangeSummary 2-1. Forward references will be resolved by {@link #end()}.
+ *
+ * @param reader
+ * Never null
+ * @throws XMLStreamException
+ */
+ public final void begin(DataObject rootObject, HelperContext scope, XMLStreamReader reader) throws XMLStreamException {
+ /*
+ * 3-1. Instantiate ChangeSummary input: reader (xsi:type), factory, rootObject output: changeSummary, changeDescription
+ */
+ initialize(reader, scope, rootObject);
+ if (typedXSI()) {
+ changeSummary = (ChangeSummaryImpl) scope.getDataFactory().create(nameSpace, name);
+ if (changeSummary == null)
+ getChangeSummary(rootObject);
+ else {
+ Property csp = ((ClassImpl) rootObject.getType()).getChangeSummaryProperty();
+ rootObject.set(csp, changeSummary);
+ changeSummary.setDataObject(rootObject);
+ }
+ } else
+ getChangeSummary(rootObject);
+ ChangeDescription changeDescription = (ChangeDescription) changeSummary;
+
+ /*
+ * 3-2. "logging" attribute input: reader output: logging
+ */
+ logging = Boolean.valueOf(reader.getAttributeValue(null, "logging")).booleanValue();
+
+ /*
+ * 3-3. Modified DataObjects input: changeDescription
+ */
+ if (forwardReferences != null)
+ forwardReferences.clear();
+ if (objectChangesCollection != null)
+ objectChangesCollection.clear();
+ if (START_ELEMENT == reader.nextTag()) {
+ objectMapChanges = changeDescription.getObjectChanges();
+ deletedDataObjects = changeDescription.getObjectsToAttach();
+ Object factory = changeDescription.eClass().getEPackage().getEFactoryInstance();
+ changeFactory = factory instanceof ChangeFactory ? (ChangeFactory) factory : ChangeFactory.eINSTANCE;
+ changeSettingFactory = factory instanceof SDOFactory ? (SDOFactory) factory : null;
+ do {
+ /*
+ * Modified DataObject
+ */
+ String ref = ref(), unset = reader.getAttributeValue(SDOAnnotations.COMMONJ_SDO_NS, ChangeSummaryStreamSerializer.UNSET);
+ int attributes = reader.getAttributeCount();
+ NamespaceContext nameSpaces = reader.getNamespaceContext();
+ EObject referent = referent(ref, nameSpaces);
+ if (referent == null) {
+ /*
+ * Forward-referenced(unresolved) modified DataObject
+ */
+ ForwardReference forwardReference = new ForwardReference(ref, nameSpaces, unset);
+ if (forwardReferences == null)
+ forwardReferences = new ArrayList();
+ forwardReferences.add(forwardReference);
+ do // what about xmlns="NS1" a1="qName" xmlns="NS2" a2="qName" ?
+ {
+ /*
+ * Record property old value as attribute for end()
+ */
+ String nameSpace = reader.getAttributeNamespace(--attributes), name = reader.getAttributeLocalName(attributes), value = reader
+ .getAttributeValue(attributes);
+ if (nameSpace == null) {
+ /*
+ * Local attribute
+ */
+ Attribute attribute = new Attribute();
+ attribute.name = name;
+ attribute.value = value;
+ if (forwardReference.attributes == null)
+ forwardReference.attributes = new ArrayList();
+ forwardReference.attributes.add(attribute);
+ } else if (!SDOAnnotations.COMMONJ_SDO_NS.equals(nameSpace) || !ChangeSummaryStreamSerializer.REF_ATTRIBUTE.equals(name)
+ && !ChangeSummaryStreamSerializer.UNSET.equals(name)) {
+ /*
+ * Qualified(global) attribute
+ */
+ QualifiedAttribute attribute = new QualifiedAttribute();
+ attribute.name = name;
+ attribute.value = value;
+ attribute.nameSpace = nameSpace;
+ if (forwardReference.qualifiedAttributes == null)
+ forwardReference.qualifiedAttributes = new ArrayList();
+ forwardReference.qualifiedAttributes.add(attribute);
+ }
+ } while (attributes != 0);
+ while (START_ELEMENT == reader.nextTag()) {
+ /*
+ * Record property old value as element for end()
+ */
+ Tag tag = new Tag(reader);
+ if (forwardReference.tags == null)
+ forwardReference.tags = new ArrayList();
+ forwardReference.tags.add(tag);
+ tag.ref = ref();
+ if (tag.ref != null)
+ continue;
+ Type xsi = typeXSI();
+ if (xsi == null) {
+ if (tag.nameSpace != null)
+ tag.value = value(globalElementType(tag.nameSpace, tag.name.getLocalPart())); // TODO substitutionGroup type if null
+ else if (tag.record(reader))
+ break;
+ } else
+ tag.value = value(xsi);
+ }
+ } else {
+ /*
+ * Resolved(back-referenced) modified DataObject
+ */
+ Type type = ((DataObject) referent).getType();
+ Collection featureChanges = unsetProperties(referent, unset, type);
+ do // what about xmlns="NS1" a1="qName" xmlns="NS2" a2="qName" ?
+ {
+ /*
+ * Log property old value as attribute
+ */
+ String nameSpace = reader.getAttributeNamespace(--attributes), name = reader.getAttributeLocalName(attributes), value = reader
+ .getAttributeValue(attributes);
+ if (nameSpace == null)
+ logAttributeChange(featureChanges, name, type, value, nameSpaces);
+ else if (!SDOAnnotations.COMMONJ_SDO_NS.equals(nameSpace) || !ChangeSummaryStreamSerializer.REF_ATTRIBUTE.equals(name)
+ && !ChangeSummaryStreamSerializer.UNSET.equals(name))
+ logAttributeChange(featureChanges, nameSpace, name, type, value, nameSpaces);
+ } while (attributes != 0);
+ if (START_ELEMENT == reader.nextTag()) {
+ ObjectChanges objectChanges = null;
+ do {
+ /*
+ * Log property old value as element
+ */
+ String nameSpace = reader.getNamespaceURI(), name = reader.getLocalName();
+ Property property = getProperty(nameSpace, name, type);
+ boolean many = property.isMany();
+ Object value;
+ ref = ref();
+ if (ref == null) {
+ /*
+ * Contained property old value
+ */
+ Type xsi = typeXSI();
+ if (xsi != null)
+ value = value(xsi);
+ else if (nameSpace == null)
+ value = value(reader);
+ else {
+ xsi = globalElementType(nameSpace, name);
+ value = value(xsi == null ? propertyInSequence.getType() : xsi);
+ }
+ } else {
+ /*
+ * Referenced child DataObject
+ */
+ nameSpaces = reader.getNamespaceContext();
+ reader.nextTag()/* END_ELEMENT */;
+ value = referent(ref, nameSpaces);
+ if (value == null) {
+ /*
+ * Forward-referenced(unresolved) child DataObject
+ */
+ if (!many) {
+ ElementChange elementChange = new ElementChange(ref, nameSpaces, property, propertyInSequence);
+ if (objectChanges == null) {
+ objectChanges = newObjectChanges(featureChanges);
+ objectChanges.newElementChanges();
+ } else if (objectChanges.elementChanges == null)
+ objectChanges.newElementChanges();
+ objectChanges.elementChanges.add(elementChange);
+ continue;
+ }
+ value = new Ref(ref, nameSpaces);
+ }
+ }
+ if (many) {
+ Collection list;
+ if (objectChanges == null) {
+ objectChanges = newObjectChanges(featureChanges);
+ list = objectChanges.newList(property);
+ } else if (objectChanges.lists == null)
+ list = objectChanges.newList(property);
+ else
+ list = objectChanges.get(property);
+ addPropertyChange(list, value, property);
+ } else
+ logPropertyChange(featureChanges, property, value);
+ } while (START_ELEMENT == reader.nextTag());
+ }
+ }
+ } while (START_ELEMENT == reader.nextTag());
+ }
+ }
+
+ static private boolean sequence(Object listChanges) {
+ return FeatureMapUtil.isFeatureMap(((FeatureChange) ((EStructuralFeature.Setting) listChanges).getEObject()).getFeature());
+ }
+
+ private ListChange createListChange(ChangeKind changeKind, int index, Collection listChanges) {
+ ListChange listChange = changeFactory.createListChange();
+ listChange.setKind(changeKind);
+ listChange.setIndex(index);
+ listChanges.add(listChange);
+ return listChange;
+ }
+
+ Collection add(Collection adds, int change, Collection listChanges, Object value) {
+ if (adds == null) {
+ ListChange listChange = createListChange(ChangeKind.ADD_LITERAL, change, listChanges);
+ adds = sequence(listChanges) ? listChange.getFeatureMapEntryValues() : listChange.getValues();
+ }
+ adds.add(value);
+ return adds;
+ }
+
+ private int remove(int change, Collection listChanges, List list, int begin, int end) {
+ ListChange listChange = createListChange(ChangeKind.REMOVE_LITERAL, change, listChanges);
+ if (sequence(listChanges)) {
+ Collection removes = listChange.getFeatureMapEntryValues();
+ do {
+ FeatureMap.Entry fme = (FeatureMap.Entry) list.get(begin);
+ removes.add(changeFactory.createFeatureMapEntry(fme.getEStructuralFeature(), fme.getValue()));
+ } while (++begin != end);
+ return begin;
+ }
+ Collection removes = listChange.getValues();
+ do
+ removes.add(list.get(begin));
+ while (++begin != end);
+ return begin;
+ }
+
+ int remove(int begin, int end, int change, Collection listChanges, List list) {
+ return begin == end ? begin : remove(change, listChanges, list, begin, end);
+ }
+
+ protected final void logManyChanges(PropertyMapChanges propertyMapChanges, EObject referent, Collection featureChanges) {
+ for (Iterator lists = propertyMapChanges.lists.entrySet().iterator(); lists.hasNext();) {
+ /*
+ * Compute ListChanges out of comparision of old and new list
+ */
+ Map.Entry entry = (Map.Entry) lists.next();
+ EStructuralFeature property = (EStructuralFeature) entry.getKey();
+ Iterator values = ((Collection) entry.getValue()).iterator(); // old list
+ Object value = referent.eGet(property);
+ List list = value instanceof FeatureMap.Internal.Wrapper ? ((FeatureMap.Internal.Wrapper) value).featureMap() : (List) value; // new
+ int change = 0;
+ FeatureChange featureChange = changeSettingFactory == null ? changeFactory.createFeatureChange() : (FeatureChange) changeSettingFactory
+ .createChangeSummarySetting();
+ featureChange.setFeature(property);
+ Collection listChanges = featureChange.getListChanges(), adds = null;
+ featureChanges.add(featureChange);
+ if (property.getEType() instanceof EClass) {
+ /*
+ * Log child DataObject changes
+ */
+ int begin = 0, end = list.size();
+ while (values.hasNext()) {
+ value = values.next();
+ if (value.getClass() == Ref.class) {
+ value = referent((Ref) value);
+ if (value == null)
+ continue;// report error?
+ }
+ // values.remove();
+ for (int index = begin;/* true */; ++index)
+ if (index == end) {
+ adds = add(adds, change, listChanges, value);
+ break;
+ } else if (list.get(index) == value) // List#indexOf uses equals
+ {
+ begin = remove(begin, index, change, listChanges, list);
+ ++begin;
+ adds = null;
+ break;
+ }
+ ++change;
+ }
+ remove(begin, end, change, listChanges, list);
+ } else if (FeatureMapUtil.isFeatureMap(property)) {
+ /*
+ * Log Sequence changes
+ */
+ int begin = 0, end = list.size();
+ while (values.hasNext()) {
+ FeatureMapEntry featureMapEntry = (FeatureMapEntry) values.next();
+ value = featureMapEntry.getValue();
+ if (value.getClass() == Ref.class) {
+ value = referent((Ref) value);
+ if (value == null)
+ continue;// report error?
+ }
+ // values.remove();
+ Comparator equality;
+ ETypedElement feature = featureMapEntry.getFeature();
+ if (((Type) feature.getEType()).isDataType())
+ if (value == null)
+ equality = EQUAL_NULL;
+ else
+ equality = EQUAL;
+ else
+ equality = SAME;
+ for (int index = begin;/* true */; ++index)
+ if (index == end) {
+ adds = add(adds, change, listChanges, featureMapEntry);
+ break;
+ } else {
+ FeatureMap.Entry fme = (FeatureMap.Entry) list.get(index);
+ if (feature == fme.getEStructuralFeature() && equality.compare(fme.getValue(), value) == 0) {
+ begin = remove(begin, index, change, listChanges, list);
+ ++begin;
+ adds = null;
+ break;
+ }
+ }
+ ++change;
+ }
+ remove(begin, end, change, listChanges, list);
+ } else {
+ /*
+ * Log simple value changes
+ */
+ while (values.hasNext()) {
+ value = values.next();
+ // values.remove();
+ int index = list.indexOf(value);
+ switch (index) {
+ case -1:
+ adds = add(adds, change, listChanges, value);
+ break;
+ default:
+ remove(change, listChanges, list, 0, index);
+ case 0:
+ list = list.subList(++index, list.size());
+ adds = null;
+ }
+ ++change;
+ }
+ remove(0, list.size(), change, listChanges, list);
+ }
+ }
+ }
+
+ protected PropertyMapChanges propertyMapChanges/* = null */;
+
+ /**
+ * Imports ChangeSummary 2-2. Resolves forward references from {@link #begin} and resumes logging if necessary. If it's invoked from
+ * patching/resolving, try to make it last since logging may be turned on.
+ *
+ * @see #begin
+ */
+ public final ChangeSummary end() throws XMLStreamException {
+ if (forwardReferences != null)
+ for (Iterator iterator = forwardReferences.iterator(); iterator.hasNext();) {
+ /*
+ * Forward-referenced(unresolved) modified DataObject from begin(...)
+ */
+ ForwardReference forwardReference = (ForwardReference) iterator.next();
+ EObject referent = referent(forwardReference);
+ if (referent == null)
+ continue; // report error?
+ // iterator.remove();
+ Type type = ((DataObject) referent).getType();
+ Collection featureChanges = unsetProperties(referent, forwardReference.unset, type);
+ if (forwardReference.attributes != null)
+ for (Iterator attributes = forwardReference.attributes.iterator(); attributes.hasNext();) {
+ /*
+ * Log property old value as local attribute from begin(...)
+ */
+ Attribute attribute = (Attribute) attributes.next();
+ logAttributeChange(featureChanges, attribute.name, type, attribute.value, forwardReference.nameSpaces);
+ }
+ if (forwardReference.qualifiedAttributes != null)
+ for (Iterator attributes = forwardReference.qualifiedAttributes.iterator(); attributes.hasNext();) {
+ /*
+ * Log property old value as qualified/global attribute from begin(...)
+ */
+ QualifiedAttribute attribute = (QualifiedAttribute) attributes.next();
+ logAttributeChange(featureChanges, attribute.nameSpace, attribute.name, type, attribute.value, forwardReference.nameSpaces);
+ }
+ if (forwardReference.tags != null) {
+ if (propertyMapChanges != null)
+ propertyMapChanges.lists.clear();
+ for (Iterator tags = forwardReference.tags.iterator(); tags.hasNext();) {
+ /*
+ * Log property old value as element from begin(...)
+ */
+ Tag tag = (Tag) tags.next();
+ Property property = getProperty(tag.nameSpace, tag.name.getLocalPart(), type);
+ if (tag.ref != null)
+ tag.value = referent(tag.ref, tag.nameSpaceContext);
+ // if (tag.value == null) report error?
+ else if (tag.events != null)
+ tag.value = value(play(tag));
+ if (property.isMany()) {
+ Collection list;
+ if (propertyMapChanges == null) {
+ propertyMapChanges = new PropertyMapChanges();
+ list = propertyMapChanges.newList(property);
+ } else
+ list = propertyMapChanges.get(property);
+ addPropertyChange( list, tag.value, property);
+ } else
+ logPropertyChange(featureChanges, property, tag.value);
+ }
+ if (propertyMapChanges != null)
+ logManyChanges(propertyMapChanges, referent, featureChanges);
+ }
+ }
+ if (objectChangesCollection != null)
+ for (Iterator iterator = objectChangesCollection.iterator(); iterator.hasNext();) {
+ /*
+ * Forward-referenced(unresolved) child DataObject from begin(...)
+ */
+ ObjectChanges objectChanges = (ObjectChanges) iterator.next();
+ if (objectChanges.elementChanges != null)
+ for (Iterator elementChanges = objectChanges.elementChanges.iterator(); elementChanges.hasNext();) {
+ ElementChange elementChange = (ElementChange) elementChanges.next();
+ Object value = referent(elementChange);
+ if (value == null)
+ continue; // report error?
+ // iterator.remove();
+ logPropertyChange(objectChanges.featureChanges, elementChange.containing, elementChange.containment, value);
+ }
+ if (objectChanges.lists != null)
+ logManyChanges(objectChanges, (EObject) ((Map.Entry) ((EStructuralFeature.Setting) objectChanges.featureChanges).getEObject())
+ .getKey(), objectChanges.featureChanges);
+ }
+ if (logging)
+ changeSummary.resumeLogging();
+ return changeSummary;
+ }
+}
diff --git a/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/ChangeSummaryStreamSerializer.java b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/ChangeSummaryStreamSerializer.java new file mode 100644 index 0000000000..c41e55655a --- /dev/null +++ b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/ChangeSummaryStreamSerializer.java @@ -0,0 +1,688 @@ +/**
+ *
+ * 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.util.resource;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+
+import org.apache.tuscany.sdo.SDOPackage;
+import org.apache.tuscany.sdo.helper.SDOAnnotations;
+import org.apache.tuscany.sdo.helper.XSDHelperImpl;
+import org.apache.tuscany.sdo.impl.ChangeSummaryImpl;
+import org.apache.tuscany.sdo.model.ModelFactory;
+import org.apache.tuscany.sdo.model.impl.ModelFactoryImpl;
+import org.apache.tuscany.sdo.util.SDOUtil;
+import org.eclipse.emf.common.util.EMap;
+import org.eclipse.emf.ecore.EClassifier;
+import org.eclipse.emf.ecore.EDataType;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.change.ChangeDescription;
+import org.eclipse.emf.ecore.change.ChangeKind;
+import org.eclipse.emf.ecore.change.FeatureChange;
+import org.eclipse.emf.ecore.change.ListChange;
+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.ChangeSummary;
+import commonj.sdo.DataObject;
+import commonj.sdo.Property;
+import commonj.sdo.helper.XSDHelper;
+
+/**
+ * ChangeSummary StAX Serializer whose output conforms to the SDO Java/C++/PHP specifications. The instance isn't thread-safe, however it's safe to
+ * use the instance any times on the same thread.
+ */
+public class ChangeSummaryStreamSerializer {
+ private XMLStreamWriter writer;
+
+ private String writeNamespace(String prefix, String nameSpace) throws XMLStreamException {
+ writer.writeNamespace(prefix, nameSpace);
+ writer.setPrefix(prefix, nameSpace);
+ return prefix;
+ }
+
+ private int nsPrefixSuffix;
+
+ private String prefix(String nameSpace, String preference) throws XMLStreamException {
+ if (preference != null) {
+ String bound = writer.getNamespaceContext().getNamespaceURI(preference);
+ if (bound == null) {
+ String prefix = writer.getPrefix(nameSpace);
+ return prefix == null ? writeNamespace(preference, nameSpace) : prefix/* or null */;
+ }
+ if (bound.equals(nameSpace))
+ return preference;
+ }
+ Object automaticNsPrefix = writer.getProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES);
+ if (automaticNsPrefix != null && automaticNsPrefix.getClass() == Boolean.class // faster than instanceof since Boolean is final
+ && ((Boolean) automaticNsPrefix).booleanValue())
+ return null;
+ String prefix = writer.getPrefix(nameSpace);
+ if (prefix != null)
+ return prefix; // or null
+ NamespaceContext nameSpaces = writer.getNamespaceContext();
+ do
+ prefix = "CS" + nsPrefixSuffix++;
+ while (nameSpaces.getNamespaceURI(prefix) != null);
+ return writeNamespace(prefix, nameSpace);
+ }
+
+ void writeGlobalAttribute(String prefix, String nameSpace, String name, String value) throws XMLStreamException {
+ prefix = prefix(nameSpace, prefix);
+ if (prefix == null)
+ writer.writeAttribute(nameSpace, name, value);
+ else
+ writer.writeAttribute(prefix, nameSpace, name, value);
+ }
+
+ XSDHelper xsdHelper;
+
+ protected final void writeAttribute(Property property, String value) throws XMLStreamException {
+ String name = xsdHelper.getLocalName(property), nameSpace = xsdHelper.getNamespaceURI(property);
+ // TODO "" for no-NameSpace global attribute
+ if (nameSpace == null)
+ writer.writeAttribute(name, value);
+ else
+ writeGlobalAttribute(null, nameSpace, name, value);
+ }
+
+ private String lineBreak, indent, margin;
+
+ private int nest;
+
+ private void breakLine() throws XMLStreamException {
+ writer.writeCharacters(lineBreak);
+
+ if (margin != null)
+ writer.writeCharacters(margin);
+
+ if (indent != null)
+ for (int count = nest; count != 0; --count)
+ writer.writeCharacters(indent);
+ }
+
+ private Map options;
+
+ static private final String STRING_OPTION = "String option";
+
+ void startElement() throws XMLStreamException {
+ if (options == null)
+ return;
+ if (lineBreak == STRING_OPTION)
+ lineBreak = (String) options.get(SDOUtil.XML_SAVE_LineBreak);
+ if (lineBreak == null)
+ return;
+ if (margin == STRING_OPTION)
+ margin = (String) options.get(SDOUtil.XML_SAVE_MARGIN);
+ if (indent == STRING_OPTION)
+ indent = (String) options.get(SDOUtil.XML_SAVE_INDENT);
+ breakLine();
+ }
+
+ void writeStartElement(String prefix, String nameSpace, String name) throws XMLStreamException {
+ startElement();
+ if (nameSpace == null)
+ writer.writeStartElement(name);
+ else {
+ prefix = prefix(nameSpace, prefix);
+ if (prefix == null)
+ writer.writeStartElement(nameSpace, name);
+ else
+ writer.writeStartElement(prefix, name, nameSpace);
+ }
+ }
+
+ void writeStartElement(Property property) throws XMLStreamException {
+ ++nest;
+ writeStartElement(null, xsdHelper.getNamespaceURI(property),// TODO "" for no-NameSpace global element
+ xsdHelper.getLocalName(property));
+ }
+
+ static protected final String CREATE_ATTRIBUTE = "create", DELETE_ATTRIBUTE = "delete", LOGGING_ATTRIBUTE = "logging", REF_ATTRIBUTE = "ref", UNSET = "unset";
+
+ private StringBuffer step(String nameSpace, String name, StringBuffer path) throws XMLStreamException {
+ if (nameSpace != null) {
+ nameSpace = writer.getPrefix(nameSpace);
+ if (nameSpace != null && nameSpace.length() != 0)
+ return path.append(nameSpace).append(':').append(name); // *:name[namespace-uri()='nameSpace']
+ }
+ return path.append(name);
+ }
+
+ private StringBuffer step(Property containmentProperty, StringBuffer path) throws XMLStreamException {
+ return step(xsdHelper.getNamespaceURI(containmentProperty),// TODO "" for no-NameSpace global element
+ xsdHelper.getLocalName(containmentProperty), path);
+ }
+
+ private StringBuffer step(Property containmentProperty) throws XMLStreamException {
+ return step(containmentProperty, new StringBuffer());
+ }
+
+ private DataObject dataObject;
+
+ private StringBuffer step(Object container) throws XMLStreamException {
+ Property containmentProperty = dataObject.getContainmentProperty();
+ StringBuffer step = step(containmentProperty);
+ if (containmentProperty.isMany() || ((EObject) dataObject).eContainingFeature() != containmentProperty)
+ step.append('[').append(((DataObject) container).getList(containmentProperty).indexOf(dataObject) + 1).append(']');
+ return step;
+ }
+
+ private String pathRootObject;
+ private DataObject rootObject;
+
+ private EObject container(EObject object) {
+ final EObject container = object.eContainer();
+ if (!(container instanceof DataObject))
+ return null;
+ String name = extendedMetaData.getName(container.eClass());
+ return name != null && name.length() == 0 // DocumentRoot
+ ? null : container;
+ }
+
+ private String path() throws XMLStreamException {
+ if (pathRootObject == STRING_OPTION)
+ pathRootObject = options == null ? null : (String) options.get(OPTION_RootObject_PATH);
+ if (pathRootObject != null && dataObject == rootObject)
+ return null;
+ EObject container = container((EObject) dataObject);
+ if (container == null)
+ return null;
+ StringBuffer step = step(container);
+ while (true) {
+ String path = step.toString();
+ dataObject = (DataObject) container;
+ if (pathRootObject != null && container == rootObject)
+ return path;
+ container = container(container);
+ if (container == null)
+ return path;
+ step = step(container).append('/').append(path);
+ }
+ }
+
+ /*
+ * not to support DataGraph 3-1 private org.eclipse.emf.ecore.resource.Resource rootResource;
+ */
+
+ protected String rootElementNS;
+
+ String rootElementName;
+
+ ExtendedMetaData extendedMetaData;
+
+ protected final String rootElementName() {
+ if (rootElementNS != null)
+ return rootElementName;
+ QName rootElement = (QName) options.get(OPTION_ROOT_ELEMENT);
+ if (rootElement != null) {
+ rootElementNS = rootElement.getNamespaceURI();
+ return rootElementName = rootElement.getLocalPart();
+ }
+ EStructuralFeature element = ((EObject) rootObject).eContainingFeature();
+ if (element == null) {
+ rootElementNS = "";
+ return rootElementName = "descendant-or-self::node()";
+ }
+ rootElementNS = extendedMetaData.getNamespace(element);
+ if (rootElementNS == null)
+ rootElementNS = "";
+ return rootElementName = extendedMetaData.getName(element);
+ }
+
+ String ref() throws XMLStreamException {
+ /*
+ * not to support DataGraph 3-2 if (rootResource != null) return rootResource.getURIFragment((EObject) dataObject);
+ */
+ String id = EcoreUtil.getID((EObject) dataObject);
+ if (id != null)
+ return id;
+ id = path();
+ if (pathRootObject == null)
+ return id == null ? "#/" + rootElementName() // descendant-or-self::node()
+ : "#//" + id;
+ return id == null ? pathRootObject/* + "."*/ : pathRootObject + id;
+ }
+
+ void writeRef(String ref) throws XMLStreamException {
+ writer.writeAttribute(SDOAnnotations.COMMONJ_SDO_NS, REF_ATTRIBUTE, ref);
+ }
+
+ void writeRef() throws XMLStreamException {
+ writeRef(ref());
+ }
+
+ void writeEndElement(String lineBreak) throws XMLStreamException {
+ if (lineBreak != null)
+ breakLine();
+ writer.writeEndElement();
+ --nest;
+ }
+
+ private StringBuffer pathDeleted/* = null */;
+
+ private Collection modifiedDataObjects;
+
+ private int lengthDeleted;
+
+ private String changeSummaryElementNS, changeSummaryElementName;
+
+ private ChangeSummary changeSummary;
+
+ protected boolean skipDeletedModification(DataObject modifiedDataObject) {
+ return changeSummary.isDeleted(modifiedDataObject);
+ }
+
+ String refDeleted() throws XMLStreamException {
+ String id = EcoreUtil.getID((EObject) dataObject);
+ if (id != null)
+ return id;
+ id = path(); // "dataObject" is updated too!!
+ DataObject deletedDataObject = dataObject;
+
+ /*
+ * construct "#//...changeSummary/"
+ * output: pathDeleted
+ */
+ if (lengthDeleted == -1) {
+ String path = pathRootObject == null ? "#//" : pathRootObject;
+ if (pathDeleted == null)
+ pathDeleted = new StringBuffer(path);
+ else
+ pathDeleted.replace(0, pathDeleted.length(), path);
+ dataObject = rootObject;
+ path = path();
+ if (path != null)
+ pathDeleted.append(path).append('/');
+ step(changeSummaryElementNS, changeSummaryElementName, pathDeleted).append('/');
+ lengthDeleted = pathDeleted.length();
+ } else
+ pathDeleted.delete(lengthDeleted, pathDeleted.length());
+
+ dataObject = changeSummary.getOldContainer(deletedDataObject);
+ Property containmentProperty = dataObject.getContainmentProperty();
+ String name = containmentProperty == null ? rootElementName() : xsdHelper.getLocalName(containmentProperty);
+ int index = 1;
+ for (Iterator iterator = modifiedDataObjects.iterator(); iterator.hasNext();) {
+ DataObject modifiedDataObject = (DataObject) iterator.next();
+ if (skipDeletedModification(modifiedDataObject))
+ continue;
+ if (modifiedDataObject == dataObject)
+ break;
+ Property property = modifiedDataObject.getContainmentProperty();
+ if (property == containmentProperty || name.equals(property == null ? rootElementName() : xsdHelper.getLocalName(property)))
+ ++index;
+ }
+ pathDeleted/*.append("*:")*/.append(name).append('[').append(index).append("]/");
+ containmentProperty = changeSummary.getOldContainmentProperty(deletedDataObject);
+ // assert containmentProperty != null;
+ step(containmentProperty, pathDeleted);
+ Object f;
+ if (containmentProperty.isMany()
+ || (f = extendedMetaData.getAffiliation(((EObject) dataObject).eClass(), (EStructuralFeature) containmentProperty)) != null
+ && f != containmentProperty)
+ pathDeleted.append('[').append(
+ ((List) changeSummary.getOldValue(dataObject, containmentProperty).getValue()).indexOf(deletedDataObject) + 1).append(']');
+ if (id != null)
+ pathDeleted.append('/').append(id);
+ return pathDeleted.toString();
+ }
+
+ static String convertToString(Property property, Object value) {
+ return EcoreUtil.convertToString((EDataType) property.getType(), value);
+ }
+
+ void writeRefDeleted() throws XMLStreamException {
+ writeRef(refDeleted());
+ }
+
+ protected final void writeDeletedObject(Property property) throws XMLStreamException {
+ ++nest;
+ startElement();
+ --nest;
+ DataObject oldDataObject = ((ChangeSummaryImpl)changeSummary).getOldDataObject(dataObject);
+ XMLStreamReader reader = new DataObjectXMLStreamReader(property, oldDataObject, null, xsdHelper);
+ new XMLStreamSerializer().serialize(new XMLDocumentStreamReader(reader), writer);
+ }
+
+ static public final Object ChangeSummary_TYPE = ((ModelFactoryImpl) ModelFactory.INSTANCE).getChangeSummaryType();
+
+ Collection deletedDataObjects;
+
+ protected final void writeElement(Object value, Property property) throws XMLStreamException {
+ if (value == null) {
+ writeStartElement(property);
+ writeGlobalAttribute(ExtendedMetaData.XSI_PREFIX, ExtendedMetaData.XSI_URI, XMLResource.NIL, "true");
+ writeEndElement(null);
+ } else if (value instanceof DataObject) {
+ dataObject = (DataObject) value;
+ if (!changeSummary.isDeleted(dataObject)) {
+ writeStartElement(property);
+ writeRef();
+ writeEndElement(null);
+ } else if (property.isContainment() && deletedDataObjects.contains(dataObject)) {
+ writeDeletedObject(property);
+ } else {
+ writeStartElement(property);
+ writeRefDeleted();
+ writeEndElement(null);
+ }
+ } else {
+ Object type = property.getType();
+ if (type == ChangeSummary_TYPE)
+ return;
+ writeStartElement(property);
+ writer.writeCharacters(EcoreUtil.convertToString((EDataType) type, value));
+ writeEndElement(null);
+ }
+ }
+
+ protected final void writeElement(Object value) throws XMLStreamException {
+ FeatureMap.Entry entry = (FeatureMap.Entry) value;
+ writeElement(entry.getValue(), (Property)entry.getEStructuralFeature());
+ }
+
+ static protected List optimize(List values, Object featureChange, int size) {
+ int fromIndex = size, toIndex = 0;
+ for (Iterator changes = ((FeatureChange) featureChange).getListChanges().iterator(); changes.hasNext();) {
+ ListChange change = (ListChange) changes.next();
+ Object kind = change.getKind();
+ if (kind == ChangeKind.MOVE_LITERAL)
+ return values;
+ int index = change.getIndex();
+ if (kind == ChangeKind.ADD_LITERAL) {
+ if (index == 0) {
+ fromIndex = 0;
+ if (toIndex == 0)
+ toIndex = 1;
+ } else {
+ int to = index;
+ if (--index < fromIndex)
+ fromIndex = index;
+ if (++to > toIndex)
+ toIndex = to;
+ else if (to < toIndex)
+ ++toIndex;
+ }
+ ++size;
+ } else {
+ --size;
+ if (index < fromIndex)
+ fromIndex = index;
+ if (index < toIndex)
+ --toIndex;
+ else if (index > toIndex && index != size)
+ toIndex = index;
+ }
+ }
+ return values.subList(fromIndex, toIndex);
+ }
+
+ static protected final Object CHANGE_SUMMARY = SDOPackage.eINSTANCE.getChangeSummary();
+
+ /**
+ * Root Object path String such as "#", etc. Absent/null is the default (automatic computation)
+ */
+ static public final String OPTION_RootObject_PATH = "RootObject path",
+ /**
+ * Boolean to optimize sequence/list/array. Absent/null/Boolean.FALSE is the default (no optimization)
+ */
+ OPTION_OPTIMIZE_LIST = "optimize sequence/list/array",
+ /**
+ * Element QName if the changeSummary Root Object is a XML root; the NameSpace can be empty, never null; the prefix is ignored.
+ * Absent/null is the default (automatic computation from DocumentRoot if any)
+ */
+ OPTION_ROOT_ELEMENT = "Root Element";
+
+ /**
+ * Exports ChangeSummary
+ *
+ * @param changeSummary
+ * Never null
+ * @param changeSummaryElement
+ * changeSummary element; the NameSpace can be empty if no NameSpace, or null if local element; the prefix can be null(no preference)
+ * @param writer
+ * Never null
+ * @param options
+ * {@link SDOUtil#XML_SAVE_LineBreak} (absence/null is the default i.e. no Line Breaking), {@link SDOUtil#XML_SAVE_INDENT} (absence/null is the default i.e. no indentation), {@link SDOUtil#XML_SAVE_MARGIN}, {@link #OPTION_RootObject_PATH}, {@link #OPTION_OPTIMIZE_LIST} and XMLResource.OPTION_EXTENDED_META_DATA; can be null or empty
+ */
+ public final void saveChangeSummary(ChangeSummary changeSummary, QName changeSummaryElement, XMLStreamWriter writer, Map options)
+ throws XMLStreamException {
+ /*
+ * 6-1. Group created, deleted and modified DataObjects
+ * input: changeSummary output: createdDataObjects, deletedDataObjects & modifiedDataObjects
+ * implement: careful if compute from changeSummary.getChangedDataObjects() since it also includes children of deleted objects (thank Frank)
+ */
+ if (changeSummary.isLogging())
+ ((ChangeSummaryImpl) changeSummary).summarize();
+ ChangeDescription changeDescription = (ChangeDescription) changeSummary;
+ Iterator createdDataObjects = changeDescription.getObjectsToDetach().iterator();
+ deletedDataObjects = changeDescription.getObjectsToAttach();
+ EMap objectChanges = changeDescription.getObjectChanges();
+ modifiedDataObjects = objectChanges.keySet(); // may contain DO(s) from createdDataObjects and/or deletedDataObjects
+
+ /*
+ * 6-2. Prepare to compute (X)Path
+ * input: changeSummary
+ * output: rootResource
+ */
+ /*not to support DataGraph 3-3
+ Object dataGraph = changeSummary.getDataGraph();
+ if (dataGraph == null) {
+ DataObject rootObject = changeSummary.getRootObject();
+ // assert rootObject != null;
+ rootResource = rootObject.getContainer() == null ? ((EObject) rootObject).eResource() // Can be null since this *StAX* writer does NOT
+ // require rootObject contained by an *EMF* Resource
+ : null; // eResource() direct content may not necessarily always be the XML document
+ } else
+ // assert dataGraph instanceof DataGraphImpl;
+ rootResource = ((org.apache.tuscany.sdo.impl.DataGraphImpl) dataGraph).getRootResource(); */
+
+ /*
+ * 6-2. Start ChangeSummary element
+ * input: writer, options, elementCS, changeSummary & changeDescription (6-1)
+ */
+ nsPrefixSuffix = 0;
+ this.writer = writer;
+ this.options = options;
+ lineBreak = "";
+ indent = margin = pathRootObject = STRING_OPTION;
+ nest = 0;
+ changeSummaryElementNS = changeSummaryElement.getNamespaceURI();
+ changeSummaryElementName = changeSummaryElement.getLocalPart();
+ writeStartElement(changeSummaryElement.getPrefix(), changeSummaryElementNS, changeSummaryElementName);
+ lineBreak = STRING_OPTION;
+ rootObject = changeSummary.getRootObject();
+ extendedMetaData = (ExtendedMetaData) options.get(XMLResource.OPTION_EXTENDED_META_DATA);
+ if (extendedMetaData == null)
+ {
+ extendedMetaData = ExtendedMetaData.INSTANCE;
+ xsdHelper = XSDHelper.INSTANCE;
+ }
+ else
+ xsdHelper = new XSDHelperImpl(extendedMetaData, null);
+ Property declaration = changeSummaryElementNS == null
+ ? rootObject.getType().getProperty(changeSummaryElementName)
+ : xsdHelper.getGlobalProperty(changeSummaryElementNS, changeSummaryElementName, true);
+ if (declaration != null)
+ {
+ EClassifier type = changeDescription.eClass();
+ if (type != declaration.getType() && type != CHANGE_SUMMARY)
+ writeGlobalAttribute(ExtendedMetaData.XSI_PREFIX, ExtendedMetaData.XSI_URI, XMLResource.TYPE, new StringBuffer(prefix(extendedMetaData.getNamespace(type), null))
+ .append(':').append(extendedMetaData.getName(type)).toString());
+ }
+
+ /*
+ * 6-3. "create" attribute
+ * input: createdDataObjects (6-1), rootResource (6-2), changeSummary & writer
+ */
+ rootElementNS = null;
+ this.changeSummary = changeSummary;
+ if (createdDataObjects.hasNext()) {
+ StringBuffer buffer = new StringBuffer();
+ while (true) {
+ dataObject = (DataObject) createdDataObjects.next();
+ buffer.append(ref());
+ if (!createdDataObjects.hasNext())
+ break;
+ buffer.append(' ');
+ }
+ writer.writeAttribute(CREATE_ATTRIBUTE, buffer.toString());
+ }
+
+ /*
+ * 6-4. "delete" attribute
+ * input: deletedDataObjects (6-1), modifiedDataObjects (6-1) & writer
+ */
+ Iterator iterator = deletedDataObjects.iterator();
+ if (iterator.hasNext()) {
+ lengthDeleted = -1;
+ StringBuffer buffer = null;
+ do {
+ dataObject = (DataObject) iterator.next();
+ if (skipDeletedModification(changeSummary.getOldContainer(dataObject)))
+ continue;
+ if (buffer == null)
+ buffer = new StringBuffer();
+ else
+ buffer.append(' ');
+ buffer.append(refDeleted());
+ } while (iterator.hasNext());
+ writer.writeAttribute(DELETE_ATTRIBUTE, buffer.toString());
+ }
+
+ /*
+ * 6-5. "logging" attribute
+ * input: changeSummary & writer
+ */
+ writer.writeAttribute(LOGGING_ATTRIBUTE, changeSummary.isLogging() ? "true" : "false");
+
+ /*
+ * 6-6. Modified DataObjects
+ * input: modifiedDataObjects (6-1), rootResource (6-2), changeSummary & writer
+ */
+ iterator = modifiedDataObjects.iterator();
+ if (iterator.hasNext()) {
+ boolean optimizeList;
+ if (options == null)
+ optimizeList = false;
+ else
+ {
+ Object option = options.get(OPTION_OPTIMIZE_LIST);
+ optimizeList = option == null ? false : ((Boolean)option).booleanValue();
+ }
+ prefix(SDOAnnotations.COMMONJ_SDO_NS, SDOPackage.eNS_PREFIX);
+ do {
+ DataObject dataObject = (DataObject) iterator.next();
+ if (skipDeletedModification(dataObject))
+ continue;
+ Property containmentProperty = dataObject.getContainmentProperty();
+ if (containmentProperty == null) {
+ ++nest;
+ startElement();
+ rootElementName();
+ writer.writeStartElement(rootElementNS, rootElementName);
+ } else
+ writeStartElement(containmentProperty);
+ this.dataObject = dataObject;
+ writeRef();
+
+ String lineBreak = null;
+ Collection oldValues = (Collection) objectChanges.get(dataObject); // changeSummary.getOldValues repeats Sequence changes
+ Iterator settings = oldValues.iterator();
+ if (settings.hasNext()) {
+ do {
+ ChangeSummary.Setting oldValue = (ChangeSummary.Setting) settings.next();
+ if (oldValue.isSet())
+ continue;
+ StringBuffer unset = step(oldValue.getProperty());
+ while (settings.hasNext()) {
+ oldValue = (ChangeSummary.Setting) settings.next();
+ if (!oldValue.isSet())
+ step(oldValue.getProperty(), unset.append(' '));
+ }
+ writer.writeAttribute(SDOAnnotations.COMMONJ_SDO_NS, UNSET, unset.toString());
+ break;
+ } while (settings.hasNext());
+ for (settings = oldValues.iterator(); settings.hasNext();) {
+ ChangeSummary.Setting oldValue = (ChangeSummary.Setting) settings.next();
+ Property property = oldValue.getProperty();
+ if (oldValue.isSet() && xsdHelper.isAttribute(property))
+ // assert ! property.isMany();
+ writeAttribute(property, convertToString(property, oldValue.getValue()));
+ }
+ for (settings = oldValues.iterator(); settings.hasNext();) {
+ ChangeSummary.Setting oldValue = (ChangeSummary.Setting) settings.next();
+ Property property = oldValue.getProperty();
+ if (!xsdHelper.isAttribute(property))
+ if (property.isMany()) {
+ Object value = oldValue.getValue();
+ List list = (List) value;
+ if (FeatureMapUtil.isFeatureMap((EStructuralFeature) property)) {
+ if (optimizeList)
+ list = optimize(list, oldValue, dataObject.getSequence(property).size());
+ Iterator values = list.iterator();
+ if (!values.hasNext())
+ continue;
+ do
+ writeElement(values.next());
+ while (values.hasNext());
+ } else {
+ if (optimizeList)
+ list = optimize(list, oldValue, dataObject.getList(property).size());
+ Iterator values = list.iterator();
+ if (!values.hasNext())
+ continue;
+ do
+ writeElement(values.next(), property);
+ while (values.hasNext());
+ }
+ lineBreak = this.lineBreak;
+ } else if (oldValue.isSet()) {
+ Object value = oldValue.getValue();
+ if (value instanceof FeatureMap.Entry)
+ writeElement(value);
+ else
+ writeElement(value, property);
+ lineBreak = this.lineBreak;
+ }
+ }
+ }
+ writeEndElement(lineBreak);
+ } while (iterator.hasNext());
+ writeEndElement(lineBreak);
+ } else
+ writeEndElement(null);
+ writer.flush();
+ }
+}
diff --git a/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/DataObjectXMLStreamReader.java b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/DataObjectXMLStreamReader.java new file mode 100644 index 0000000000..9df5c43ac2 --- /dev/null +++ b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/DataObjectXMLStreamReader.java @@ -0,0 +1,1547 @@ +/** + * + * 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.util.resource; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamException; + +import org.apache.tuscany.sdo.impl.AttributeImpl; +import org.apache.tuscany.sdo.impl.ReferenceImpl; +import org.apache.tuscany.sdo.util.SDOUtil; +import org.eclipse.emf.ecore.EClass; +import org.eclipse.emf.ecore.EDataType; +import org.eclipse.emf.ecore.EReference; +import org.eclipse.emf.ecore.EStructuralFeature; +import org.eclipse.emf.ecore.util.ExtendedMetaData; + +import commonj.sdo.DataObject; +import commonj.sdo.Property; +import commonj.sdo.Sequence; +import commonj.sdo.Type; +import commonj.sdo.helper.TypeHelper; +import commonj.sdo.helper.XMLDocument; +import commonj.sdo.helper.XSDHelper; + +public class DataObjectXMLStreamReader implements XMLFragmentStreamReader { + private static final QName XSI_TYPE_QNAME = new QName("http://www.w3.org/2001/XMLSchema-instance", "type", "xsi"); + private Property rootElement = null; + private DataObject dataObject; + + private String rootElementURI; + + private String rootElementName; + + private DataObject serializeRoot; + + private TypeHelper typeHelper; + + private XSDHelper xsdHelper; + + private Map.Entry[] properties; + + private Map.Entry[] attributes; + + private QName elementQName; + + // we always create a new namespace context + private NameSpaceContext namespaceContext; + + private Map declaredNamespaceMap = new HashMap(); + + // states for this pullparser - it can only have three states + private static final int START_ELEMENT_STATE = 0; + + private static final int END_ELEMENT_STATE = 1; + + private static final int DELEGATED_STATE = 2; + + private static final int TEXT_STATE = 3; + + // integer field that keeps the state of this + // parser. + private int state = START_ELEMENT_STATE; + + // reference to the child reader + private XMLFragmentStreamReader childReader; + + // current property index + // initialized at zero + private int currentPropertyIndex = 0; + + public DataObjectXMLStreamReader(DataObject dataObject, String rootElmentURI, String rootElementName) { + this(dataObject, rootElmentURI, rootElementName, null, null); + } + + public DataObjectXMLStreamReader(DataObject dataObject, String rootElmentURI, String rootElementName, TypeHelper typeHelper) { + this(dataObject, rootElmentURI, rootElementName, typeHelper, null); + } + + public DataObjectXMLStreamReader(DataObject dataObject, String rootElmentURI, String rootElementName, TypeHelper typeHelper, XSDHelper xsdHelper) { + this.dataObject = dataObject; + this.rootElementURI = rootElmentURI; + this.rootElementName = rootElementName; + this.serializeRoot = dataObject; + this.typeHelper = typeHelper == null ? TypeHelper.INSTANCE : typeHelper; + this.xsdHelper = (xsdHelper != null) ? xsdHelper : ((typeHelper == null) ? XSDHelper.INSTANCE : SDOUtil.createXSDHelper(typeHelper)); + rootElement = this.xsdHelper.getGlobalProperty(rootElmentURI, rootElementName, true); + namespaceContext = new NameSpaceContext(); + populateProperties(); + } + + protected DataObjectXMLStreamReader(TypeHelper typeHelper, XSDHelper xsdHelper, Property rootElement, DataObject dataObject) { + this.typeHelper = typeHelper == null ? TypeHelper.INSTANCE : typeHelper; + this.xsdHelper = (xsdHelper != null) ? xsdHelper : ((typeHelper == null) ? XSDHelper.INSTANCE : SDOUtil.createXSDHelper(typeHelper)); + this.rootElement = rootElement; + this.dataObject = dataObject; + this.rootElementURI = xsdHelper.getNamespaceURI(rootElement); + this.rootElementName = xsdHelper.getLocalName(rootElement); + } + + protected DataObjectXMLStreamReader(TypeHelper typeHelper, XSDHelper xsdHelper, Property rootElement, DataObject dataObject, DataObject serializeRoot) { + this.typeHelper = typeHelper == null ? TypeHelper.INSTANCE : typeHelper; + this.xsdHelper = (xsdHelper != null) ? xsdHelper : ((typeHelper == null) ? XSDHelper.INSTANCE : SDOUtil.createXSDHelper(typeHelper)); + this.rootElement = rootElement; + this.dataObject = dataObject; + this.serializeRoot = serializeRoot; + this.rootElementURI = xsdHelper.getNamespaceURI(rootElement); + this.rootElementName = xsdHelper.getLocalName(rootElement); + } + public DataObjectXMLStreamReader(Property rootElement, DataObject dataObject, TypeHelper typeHelper, XSDHelper xsdHelper) { + this(typeHelper, xsdHelper, rootElement, dataObject); + namespaceContext = new NameSpaceContext(); + populateProperties(); + } + + public DataObjectXMLStreamReader(XMLDocument document, TypeHelper typeHelper) { + this.dataObject = document.getRootObject(); + this.rootElementName = document.getRootElementName(); + this.rootElementURI = document.getRootElementURI(); + this.serializeRoot = this.dataObject; + this.typeHelper = typeHelper; + this.xsdHelper = typeHelper == null ? XSDHelper.INSTANCE : SDOUtil.createXSDHelper(typeHelper); + namespaceContext = new NameSpaceContext(); + populateProperties(); + } + + /* + * we need to pass in a namespace context since when delegated, we've no idea of the current namespace context. So it needs to be passed on here! + */ + protected DataObjectXMLStreamReader(QName elementQName, Map.Entry[] properties, Map.Entry[] attributes) { + // validate the lengths, since both the arrays are supposed + // to have + this.properties = properties; + this.elementQName = elementQName; + this.attributes = attributes; + namespaceContext = new NameSpaceContext(); + } + + private void addProperty(Property property, Object value, List propertyList) { + if (property.isMany() && property.getContainingType().isOpen() && value instanceof Sequence) { + addSequenceValue(propertyList, (Sequence) value); + } else if (SDOUtil.isMany(property, dataObject) && value instanceof List) { + addListValue(propertyList, property, (List) value); + } else { + // Complex Type + addSingleValue(propertyList, property, value); + } + } + + void addProperty(List propertyList, Property property, Object value, Object type) { + if (!isTransient(property, type)) + addProperty(property, value, propertyList); + } + + private void addSequenceValue(List elements, Sequence seq) { + if (seq != null && seq.size() > 0) { + for (int j = 0; j < seq.size(); j++) { + Object o = seq.getValue(j); + Property p = seq.getProperty(j); + addSingleValue(elements, p, o); + } + } + } + + static private boolean isTransient(Property property, Object type) { + // HACK: We need some SDOUtil extension to understand a property is derived + EStructuralFeature feature = (EStructuralFeature) property; + if (ExtendedMetaData.INSTANCE.getGroup(feature) != null) + return false; + feature = ExtendedMetaData.INSTANCE.getAffiliation((EClass) type, feature); + if (feature != null && feature != property) + return false; + if (property instanceof ReferenceImpl) { + ReferenceImpl r = (ReferenceImpl) property; + if (r.isTransient()) + return true; + EReference opposite = r.getEOpposite(); + if (opposite != null && opposite.isContainment()) { + return true; + } + } else if (property instanceof AttributeImpl) { + AttributeImpl a = (AttributeImpl) property; + if (a.isTransient()) + return true; + EDataType d = (EDataType) a.getEType(); + if (!d.isSerializable()) { + return true; + } + } + return false; + } + + private void addListValue(List propertyList, Property property, List objList) { + if (objList != null) { + for (int j = 0; j < objList.size(); j++) { + Object object = objList.get(j); + addSingleValue(propertyList, property, object); + } + } + } + + private void addSingleValue(List propertyList, Property property, Object value) { + String uri = xsdHelper.getNamespaceURI(property); + String name = xsdHelper.getLocalName(property); + QName qname = namespaceContext.createQName(uri, name); + Type propertyType = property.getType(); + + if (property.getName().equals("value") && uri == null && name.equals(":0")) { + // "value" is special property containing the value of simpleContent + Map.Entry entry = new NameValuePair(ELEMENT_TEXT, value); + propertyList.add(entry); + } else + + // FIXME: We need to deal with non-containment properties + if (value == null) { + // Creating xsi:nil="true" for elements + Map.Entry entry = new NameValuePair(qname, null); + propertyList.add(entry); + } else if (propertyType.isDataType()) { + Map.Entry entry = new NameValuePair(qname, SDOUtil.convertToString(propertyType, value)); + propertyList.add(entry); + } else if (property.isContainment() && value == serializeRoot) { + // do not create the childReader because a containmentCycle exists and this is the second + // time this DataObject has been encountered + } else { + DataObjectXMLStreamReader childReader = new DataObjectXMLStreamReader(typeHelper, xsdHelper, property, (DataObject) value, serializeRoot); + childReader.namespaceContext = namespaceContext; + childReader.populateProperties(); + childReader.rootElement = property; + Map.Entry entry = new NameValuePair(qname, childReader); + propertyList.add(entry); + } + } + + public void populateProperties() { + /*declaredNamespaceMap.put("xml", "http://www.w3.org/XML/1998/namespace"); + declaredNamespaceMap.put("xmlns", "http://www.w3.org/2000/xmlns/"); + declaredNamespaceMap.put("xsi", "http://www.w3.org/2001/XMLSchema-instance"); + */ + + if (properties != null) + return; + if (elementQName == null) + elementQName = namespaceContext.createQName(this.rootElementURI, this.rootElementName); + else + elementQName = namespaceContext.createQName(elementQName.getNamespaceURI(), elementQName.getLocalPart()); + + List elementList = new ArrayList(); + List attributeList = new ArrayList(); + Type type = dataObject.getType(); + if (rootElement != null) { + Type modelType = rootElement.getType(); + if (type != modelType) { + // FIXME: XSDHelper.getLocalName() for annoymous type returns null? + String typeName = xsdHelper.getLocalName(type); + if (typeName != null) { + QName realTypeName = namespaceContext.createQName(type.getURI(), typeName); + String typeQName = realTypeName.getPrefix() + ":" + realTypeName.getLocalPart(); + declaredNamespaceMap.put(realTypeName.getPrefix(), realTypeName.getNamespaceURI()); + attributeList.add(new NameValuePair(XSI_TYPE_QNAME, typeQName)); + } + } + } + + if (type.isSequenced()) { + Sequence sequence = dataObject.getSequence(); + for (int i = 0; i < sequence.size(); i++) { + Property property = sequence.getProperty(i); + Object value = sequence.getValue(i); + if (property == null) { + // property == null for text in mixed content + elementList.add(new NameValuePair(ELEMENT_TEXT, value)); + } else { + addProperty(property, value, elementList); + } + } + // Attributes are not in the sequence + List properties = dataObject.getInstanceProperties(); + for (Iterator i = properties.iterator(); i.hasNext();) { + Property property = (Property) i.next(); + if (xsdHelper.isAttribute(property)) { + // FIXME: How to handle nilable=true? + if (!dataObject.isSet(property)) + continue; + Object value = dataObject.get(property); + addProperty(attributeList, property, value, type); + } + } + } else { + List properties = dataObject.getInstanceProperties(); + for (Iterator i = properties.iterator(); i.hasNext();) { + Property property = (Property) i.next(); + // FIXME: How to handle nilable=true? + if (!dataObject.isSet(property)) + continue; + Object value = dataObject.get(property); + if (xsdHelper.isAttribute(property)) + addProperty(attributeList, property, value, type); + else + addProperty(elementList, property, value, type); + } + } + properties = (Map.Entry[]) elementList.toArray(new Map.Entry[0]); + attributes = (Map.Entry[]) attributeList.toArray(new Map.Entry[0]); + } + + public DataObject getDataObject() { + return dataObject; + } + + /** + * we need to split out the calling to the populate namespaces seperately since this needs to be done *after* setting the parent namespace + * context. We cannot assume it will happen at construction! + */ + public void init() { + // here we have an extra issue to attend to. we need to look at the + // prefixes and uris (the combination) and populate a hashmap of + // namespaces. The hashmap of namespaces will be used to serve the + // namespace context + + populateNamespaceContext(); + } + + /** + * + * @param key + * @return + * @throws IllegalArgumentException + */ + public Object getProperty(String key) throws IllegalArgumentException { + if (state == START_ELEMENT_STATE || state == END_ELEMENT_STATE) { + return null; + } else if (state == TEXT_STATE) { + return null; + } else if (state == DELEGATED_STATE) { + return childReader.getProperty(key); + } else { + return null; + } + + } + + public int next() throws XMLStreamException { + return updateStatus(); + } + + public void require(int i, String string, String string1) throws XMLStreamException { + throw new UnsupportedOperationException(); + } + + /** + * todo implement the right contract for this + * + * @return + * @throws XMLStreamException + */ + public String getElementText() throws XMLStreamException { + if (state == DELEGATED_STATE) { + return childReader.getElementText(); + } else { + return null; + } + + } + + /** + * todo implement this + * + * @return + * @throws XMLStreamException + */ + public int nextTag() throws XMLStreamException { + return 0; + } + + /** + * @return + * @throws XMLStreamException + */ + public boolean hasNext() throws XMLStreamException { + if (state == DELEGATED_STATE) { + if (childReader.isEndOfFragment()) { + // the child reader is done. We shouldn't be getting the + // hasnext result from the child pullparser then + return true; + } else { + return childReader.hasNext(); + } + } else { + return (state == START_ELEMENT_STATE || state == TEXT_STATE); + + } + } + + public void close() throws XMLStreamException { + // do nothing here - we have no resources to free + } + + public String getNamespaceURI(String prefix) { + return namespaceContext.getNamespaceURI(prefix); + } + + public boolean isStartElement() { + if (state == START_ELEMENT_STATE) { + return true; + } else if (state == END_ELEMENT_STATE) { + return false; + } + return childReader.isStartElement(); + } + + public boolean isEndElement() { + if (state == START_ELEMENT_STATE) { + return false; + } else if (state == END_ELEMENT_STATE) { + return true; + } + return childReader.isEndElement(); + } + + public boolean isCharacters() { + if (state == START_ELEMENT_STATE || state == END_ELEMENT_STATE) { + return false; + } + return childReader.isCharacters(); + } + + public boolean isWhiteSpace() { + if (state == START_ELEMENT_STATE || state == END_ELEMENT_STATE) { + return false; + } + return childReader.isWhiteSpace(); + } + + // ///////////////////////////////////////////////////////////////////////// + // / attribute handling + // ///////////////////////////////////////////////////////////////////////// + + public String getAttributeValue(String nsUri, String localName) { + + int attribCount = getAttributeCount(); + String returnValue = null; + QName attribQualifiedName; + for (int i = 0; i < attribCount; i++) { + attribQualifiedName = getAttributeName(i); + if (nsUri == null) { + if (localName.equals(attribQualifiedName.getLocalPart())) { + returnValue = getAttributeValue(i); + break; + } + } else { + if (localName.equals(attribQualifiedName.getLocalPart()) && nsUri.equals(attribQualifiedName.getNamespaceURI())) { + returnValue = getAttributeValue(i); + break; + } + } + + } + + return returnValue; + } + + public int getAttributeCount() { + return (state == DELEGATED_STATE) ? childReader.getAttributeCount() + : ((attributes != null) && (state == START_ELEMENT_STATE) ? attributes.length : 0); + } + + /** + * @param i + * @return + */ + public QName getAttributeName(int i) { + if (state == DELEGATED_STATE) { + return childReader.getAttributeName(i); + } else if (state == START_ELEMENT_STATE) { + if (attributes == null) { + return null; + } else { + if ((i >= (attributes.length)) || i < 0) { // out of range + return null; + } else { + // get the attribute pointer + Object attribPointer = attributes[i].getKey(); + // case one - attrib name is null + // this should be the pointer to the OMAttribute then + if (attribPointer instanceof String) { + return new QName((String) attribPointer); + } else if (attribPointer instanceof QName) { + return (QName) attribPointer; + } else { + return null; + } + } + } + } else { + throw new IllegalStateException();// as per the api contract + } + + } + + public String getAttributeNamespace(int i) { + if (state == DELEGATED_STATE) { + return childReader.getAttributeNamespace(i); + } else if (state == START_ELEMENT_STATE) { + QName name = getAttributeName(i); + if (name == null) { + return null; + } else { + return name.getNamespaceURI(); + } + } else { + throw new IllegalStateException(); + } + } + + public String getAttributeLocalName(int i) { + if (state == DELEGATED_STATE) { + return childReader.getAttributeLocalName(i); + } else if (state == START_ELEMENT_STATE) { + QName name = getAttributeName(i); + if (name == null) { + return null; + } else { + return name.getLocalPart(); + } + } else { + throw new IllegalStateException(); + } + } + + public String getAttributePrefix(int i) { + if (state == DELEGATED_STATE) { + return childReader.getAttributePrefix(i); + } else if (state == START_ELEMENT_STATE) { + QName name = getAttributeName(i); + if (name == null) { + return null; + } else { + return name.getPrefix(); + } + } else { + throw new IllegalStateException(); + } + } + + public String getAttributeType(int i) { + return null; // not supported + } + + public String getAttributeValue(int i) { + if (state == DELEGATED_STATE) { + return childReader.getAttributeValue(i); + } else if (state == START_ELEMENT_STATE) { + if (attributes == null) { + return null; + } else { + if ((i >= (attributes.length)) || i < 0) { // out of range + return null; + } else { + // get the attribute pointer + Object attribPointer = attributes[i].getKey(); + Object omAttribObj = attributes[i].getValue(); + // case one - attrib name is null + // this should be the pointer to the OMAttribute then + if (attribPointer instanceof String) { + return (String) omAttribObj; + } else if (attribPointer instanceof QName) { + return (String) omAttribObj; + } else { + return null; + } + } + } + } else { + throw new IllegalStateException(); + } + + } + + public boolean isAttributeSpecified(int i) { + return false; // not supported + } + + // ///////////////////////////////////////////////////////////////////////// + // //////////// end of attribute handling + // ///////////////////////////////////////////////////////////////////////// + + // ////////////////////////////////////////////////////////////////////////// + // //////////// namespace handling + // ////////////////////////////////////////////////////////////////////////// + + public int getNamespaceCount() { + if (state == DELEGATED_STATE) { + return childReader.getNamespaceCount(); + } else { + return declaredNamespaceMap.size(); + } + } + + /** + * @param i + * @return + */ + public String getNamespacePrefix(int i) { + if (state == DELEGATED_STATE) { + return childReader.getNamespacePrefix(i); + } else if (state != TEXT_STATE) { + // order the prefixes + String[] prefixes = makePrefixArray(); + if ((i >= prefixes.length) || (i < 0)) { + return null; + } else { + return prefixes[i]; + } + + } else { + throw new IllegalStateException(); + } + + } + + /** + * Get the prefix list from the hastable and take that into an array + * + * @return + */ + private String[] makePrefixArray() { + String[] prefixes = (String[]) declaredNamespaceMap.keySet().toArray(new String[declaredNamespaceMap.size()]); + Arrays.sort(prefixes); + return prefixes; + } + + public String getNamespaceURI(int i) { + if (state == DELEGATED_STATE) { + return childReader.getNamespaceURI(i); + } else if (state != TEXT_STATE) { + String namespacePrefix = getNamespacePrefix(i); + return namespacePrefix == null ? null : (String) declaredNamespaceMap.get(namespacePrefix); + } else { + throw new IllegalStateException(); + } + + } + + public NamespaceContext getNamespaceContext() { + if (state == DELEGATED_STATE) { + return childReader.getNamespaceContext(); + } else { + return namespaceContext; + } + + } + + // ///////////////////////////////////////////////////////////////////////// + // /////// end of namespace handling + // ///////////////////////////////////////////////////////////////////////// + + public int getEventType() { + if (state == START_ELEMENT_STATE) { + return START_ELEMENT; + } else if (state == END_ELEMENT_STATE) { + return END_ELEMENT; + } else { // this is the delegated state + return childReader.getEventType(); + } + + } + + public String getText() { + if (state == DELEGATED_STATE) { + return childReader.getText(); + } else if (state == TEXT_STATE) { + return (String) properties[currentPropertyIndex - 1].getValue(); + } else { + throw new IllegalStateException(); + } + } + + public char[] getTextCharacters() { + if (state == DELEGATED_STATE) { + return childReader.getTextCharacters(); + } else if (state == TEXT_STATE) { + return getTextData(); + } else { + throw new IllegalStateException(); + } + } + + private char[] getTextData() { + return properties[currentPropertyIndex - 1].getValue() == null ? new char[0] : ((String) properties[currentPropertyIndex - 1].getValue()) + .toCharArray(); + } + + private int copy(int sourceStart, char[] target, int targetStart, int length) { + char[] source = getTextData(); + if (sourceStart > source.length) + throw new IndexOutOfBoundsException("source start > source length"); + int sourceLen = source.length - sourceStart; + if (length > sourceLen) + length = sourceLen; + System.arraycopy(source, sourceStart, target, targetStart, length); + return sourceLen; + } + + public int getTextCharacters(int i, char[] chars, int i1, int i2) throws XMLStreamException { + if (state == DELEGATED_STATE) { + return childReader.getTextCharacters(i, chars, i1, i2); + } else if (state == TEXT_STATE) { + return copy(i, chars, i1, i2); + } else { + throw new IllegalStateException(); + } + } + + public int getTextStart() { + if (state == DELEGATED_STATE) { + return childReader.getTextStart(); + } else if (state == TEXT_STATE) { + return 0;// assume text always starts at 0 + } else { + throw new IllegalStateException(); + } + } + + public int getTextLength() { + if (state == DELEGATED_STATE) { + return childReader.getTextLength(); + } else if (state == TEXT_STATE) { + return getTextData().length; + } else { + throw new IllegalStateException(); + } + } + + public String getEncoding() { + if (state == DELEGATED_STATE) { + return childReader.getEncoding(); + } else { + // we've no idea what the encoding is going to be in this case + // perhaps we ought to return some constant here, which the user might + // have access to change! + return null; + } + } + + /** + * check the validity of this implementation + * + * @return + */ + public boolean hasText() { + if (state == DELEGATED_STATE) { + return childReader.hasText(); + } else if (state == TEXT_STATE) { + return true; + } else { + return false; + } + + } + + /** + * @return + */ + public Location getLocation() { + // return a default location + return new Location() { + public int getLineNumber() { + return 0; + } + + public int getColumnNumber() { + return 0; + } + + public int getCharacterOffset() { + return 0; + } + + public String getPublicId() { + return null; + } + + public String getSystemId() { + return null; + } + }; + } + + public QName getName() { + if (state == DELEGATED_STATE) { + return childReader.getName(); + } else if (state != TEXT_STATE) { + return elementQName; + } else { + throw new IllegalStateException(); + } + + } + + public String getLocalName() { + if (state == DELEGATED_STATE) { + return childReader.getLocalName(); + } else if (state != TEXT_STATE) { + return elementQName.getLocalPart(); + } else { + throw new IllegalStateException(); + } + } + + public boolean hasName() { + // since this parser always has a name, the hasname + // has to return true if we are still navigating this element + // if not we should ask the child reader for it. + if (state == DELEGATED_STATE) { + return childReader.hasName(); + } else if (state != TEXT_STATE) { + return true; + } else { + return false; + } + } + + public String getNamespaceURI() { + if (state == DELEGATED_STATE) { + return childReader.getNamespaceURI(); + } else if (state == TEXT_STATE) { + return null; + } else { + return elementQName.getNamespaceURI(); + } + } + + public String getPrefix() { + if (state == DELEGATED_STATE) { + return childReader.getPrefix(); + } else if (state == TEXT_STATE) { + return null; + } else { + return elementQName.getPrefix(); + } + } + + public String getVersion() { + return null; + } + + public boolean isStandalone() { + return true; + } + + public boolean standaloneSet() { + return true; + } + + public String getCharacterEncodingScheme() { + return null; // todo - should we return something for this ? + } + + public String getPITarget() { + throw new UnsupportedOperationException("Yet to be implemented !!"); + } + + public String getPIData() { + throw new UnsupportedOperationException("Yet to be implemented !!"); + } + + // ///////////////////////////////////////////////////////////////////////// + // / Other utility methods + // //////////////////////////////////////////////////////////////////////// + + /** + * Populates a namespace context + */ + private void populateNamespaceContext() { + + // first add the current element namespace to the namespace context + // declare it if not found + registerNamespace(elementQName.getPrefix(), elementQName.getNamespaceURI()); + + // traverse through the attributes and populate the namespace context + // the attrib list can be of many combinations + // the valid combinations are + // String - String + // QName - QName + // null - OMAttribute + + if (attributes != null) { + for (int i = 0; i < attributes.length; i++) { // jump in two + Object attribName = attributes[i].getKey(); + if (attribName instanceof String) { + // ignore this case - Nothing to do + } else if (attribName instanceof QName) { + QName attribQName = ((QName) attribName); + registerNamespace(attribQName.getPrefix(), attribQName.getNamespaceURI()); + + } + } + } + + } + + /** + * @param prefix + * @param uri + */ + private void registerNamespace(String prefix, String uri) { + if (!uri.equals(namespaceContext.getNamespaceURI(prefix))) { + namespaceContext.registerMapping(prefix, uri); + declaredNamespaceMap.put(prefix, uri); + } + } + + /** + * By far this should be the most important method in this class this method changes the state of the parser according to the change in the + */ + private int updateStatus() throws XMLStreamException { + int returnEvent = -1; // invalid state is the default state + switch (state) { + case START_ELEMENT_STATE: + // current element is start element. We should be looking at the + // property list and making a pullparser for the property value + if (properties == null || properties.length == 0) { + // no properties - move to the end element state straightaway + state = END_ELEMENT_STATE; + returnEvent = END_ELEMENT; + } else { + // there are properties. now we should delegate this task to a + // child reader depending on the property type + returnEvent = processProperties(); + + } + break; + case END_ELEMENT_STATE: + // we've reached the end element already. If the user tries to push + // further ahead then it is an exception + throw new XMLStreamException("Trying to go beyond the end of the pullparser"); + + case DELEGATED_STATE: + if (childReader.isEndOfFragment()) { + // we've reached the end! + if (currentPropertyIndex > (properties.length - 1)) { + state = END_ELEMENT_STATE; + returnEvent = END_ELEMENT; + } else { + returnEvent = processProperties(); + } + } else { + returnEvent = childReader.next(); + } + break; + + case TEXT_STATE: + // if there are any more event we should be delegating to + // processProperties. if not we just return an end element + if (currentPropertyIndex > (properties.length - 1)) { + state = END_ELEMENT_STATE; + returnEvent = END_ELEMENT; + } else { + returnEvent = processProperties(); + } + break; + } + return returnEvent; + } + + /** + * A convenient method to reuse the properties + * + * @return event to be thrown + * @throws XMLStreamException + */ + private int processProperties() throws XMLStreamException { + // move to the next property depending on the current property + // index + Object propPointer = properties[currentPropertyIndex].getKey(); + QName propertyQName = null; + boolean textFound = false; + if (propPointer == null) { + throw new XMLStreamException("property key cannot be null!"); + } else if (propPointer instanceof String) { + // propPointer being a String has a special case + // that is it can be a the special constant ELEMENT_TEXT that + // says this text event + if (ELEMENT_TEXT.equals(propPointer)) { + textFound = true; + } else { + propertyQName = new QName((String) propPointer); + } + } else if (propPointer instanceof QName) { + propertyQName = (QName) propPointer; + } else { + // oops - we've no idea what kind of key this is + throw new XMLStreamException("unidentified property key!!!" + propPointer); + } + + // ok! we got the key. Now look at the value + Object propertyValue = properties[currentPropertyIndex].getValue(); + // cater for the special case now + if (textFound) { + // no delegation here - make the parser null and immediately + // return with the event characters + childReader = null; + state = TEXT_STATE; + currentPropertyIndex++; + return CHARACTERS; + } else if (propertyValue == null || propertyValue instanceof String) { + // strings are handled by the NameValuePairStreamReader + childReader = new SimpleElementStreamReader(propertyQName, (String) propertyValue, namespaceContext); + childReader.init(); + } else if (propertyValue instanceof DataObjectXMLStreamReader) { + // ADBbean has it's own method to get a reader + XMLFragmentStreamReader reader = (DataObjectXMLStreamReader) propertyValue; + // we know for sure that this is an ADB XMLStreamreader. + // However we need to make sure that it is compatible + childReader = reader; + childReader.init(); + } else { + // all special possiblilities has been tried! Let's treat + // the thing as a bean and try generating events from it + throw new UnsupportedOperationException("Not supported"); + // childReader = new WrappingXMLStreamReader(BeanUtil.getPullParser(propertyValue, propertyQName)); + // we cannot register the namespace context here + } + + // set the state here + state = DELEGATED_STATE; + // we are done with the delegation + // increment the property index + currentPropertyIndex++; + return childReader.getEventType(); + } + + /** + * are we done ? + * + * @return + */ + public boolean isEndOfFragment() { + return (state == END_ELEMENT_STATE); + } + + protected static class NameValuePair implements Map.Entry { + private Object key; + + private Object value; + + public NameValuePair(Object key, Object value) { + this.key = key; + this.value = value; + } + + public Object getKey() { + return key; + } + + public Object getValue() { + return value; + } + + public Object setValue(Object value) { + Object v = this.value; + this.value = value; + return v; + } + + } + + protected static class SimpleElementStreamReader implements XMLFragmentStreamReader { + + private static final int START_ELEMENT_STATE = 0; + + private static final int TEXT_STATE = 1; + + private static final int END_ELEMENT_STATE = 2; + + private static final int START_ELEMENT_STATE_WITH_NULL = 3; + + private static final QName XSI_NIL_QNAME = new QName("http://www.w3.org/2001/XMLSchema-instance", "nil", "xsi"); + + private final NameSpaceContext namespaceContext; + + private QName name; + + private String value; + + private int state = START_ELEMENT_STATE; + + public SimpleElementStreamReader(QName name, String value, NameSpaceContext nameSpaces) { + this.name = name; + this.value = value; + if (value == null) + state = START_ELEMENT_STATE_WITH_NULL; + namespaceContext = nameSpaces; + } + + public Object getProperty(String key) throws IllegalArgumentException { + return null; + } + + public int next() throws XMLStreamException { + switch (state) { + case START_ELEMENT_STATE: + state = TEXT_STATE; + return CHARACTERS; + case START_ELEMENT_STATE_WITH_NULL: + state = END_ELEMENT_STATE; + return END_ELEMENT; + case END_ELEMENT_STATE: + // oops, not supposed to happen! + throw new XMLStreamException("end already reached!"); + case TEXT_STATE: + state = END_ELEMENT_STATE; + return END_ELEMENT; + default: + throw new XMLStreamException("unknown event type!"); + } + } + + public void require(int i, String string, String string1) throws XMLStreamException { + // not implemented + } + + public String getElementText() throws XMLStreamException { + if (state == START_ELEMENT) { + // move to the end state and return the value + state = END_ELEMENT_STATE; + return value; + } else { + throw new XMLStreamException(); + } + + } + + public int nextTag() throws XMLStreamException { + return 0;// todo + } + + public boolean hasNext() throws XMLStreamException { + return (state != END_ELEMENT_STATE); + } + + public void close() throws XMLStreamException { + // Do nothing - we've nothing to free here + } + + public String getNamespaceURI(String prefix) { + return namespaceContext.getNamespaceURI(prefix); + } + + public boolean isStartElement() { + return (state == START_ELEMENT_STATE || state == START_ELEMENT_STATE_WITH_NULL); + } + + public boolean isEndElement() { + return (state == END_ELEMENT_STATE); + } + + public boolean isCharacters() { + return (state == TEXT_STATE); + } + + public boolean isWhiteSpace() { + return false; // no whitespaces here + } + + public boolean isAttributeSpecified(int i) { + return false; // no attribs here + } + + public NamespaceContext getNamespaceContext() { + return this.namespaceContext; + } + + public int getEventType() { + switch (state) { + case START_ELEMENT_STATE: + case START_ELEMENT_STATE_WITH_NULL: + return START_ELEMENT; + case END_ELEMENT_STATE: + return END_ELEMENT; + case TEXT_STATE: + return CHARACTERS; + default: + throw new UnsupportedOperationException(); + // we've no idea what this is!!!!! + } + + } + + public String getText() { + if (state == TEXT_STATE) { + return value; + } else { + throw new IllegalStateException(); + } + } + + public char[] getTextCharacters() { + if (state == TEXT_STATE) { + return value.toCharArray(); + } else { + throw new IllegalStateException(); + } + } + + public int getTextCharacters(int i, char[] chars, int i1, int i2) throws XMLStreamException { + // not implemented + throw new UnsupportedOperationException(); + } + + public int getTextStart() { + if (state == TEXT_STATE) { + return 0; + } else { + throw new IllegalStateException(); + } + } + + public int getTextLength() { + if (state == TEXT_STATE) { + return value.length(); + } else { + throw new IllegalStateException(); + } + + } + + public String getEncoding() { + return "UTF-8"; + } + + public boolean hasText() { + return (state == TEXT_STATE); + } + + public Location getLocation() { + return new Location() { + public int getLineNumber() { + return 0; + } + + public int getColumnNumber() { + return 0; + } + + public int getCharacterOffset() { + return 0; + } + + public String getPublicId() { + return null; + } + + public String getSystemId() { + return null; + } + }; + } + + public QName getName() { + if (state != TEXT_STATE) { + return name; + } else { + return null; + } + } + + public String getLocalName() { + if (state != TEXT_STATE) { + return name.getLocalPart(); + } else { + return null; + } + } + + public boolean hasName() { + return (state != TEXT_STATE); + + } + + public String getNamespaceURI() { + if (state != TEXT_STATE) { + return name.getNamespaceURI(); + } else { + return null; + } + + } + + public String getPrefix() { + if (state != TEXT_STATE) { + return name.getPrefix(); + } else { + return null; + } + } + + public String getVersion() { + return null; // todo 1.0 ? + } + + public boolean isStandalone() { + return false; + } + + public boolean standaloneSet() { + return false; + } + + public String getCharacterEncodingScheme() { + return null; + } + + public String getPITarget() { + return null; + } + + public String getPIData() { + return null; + } + + public boolean isEndOfFragment() { + return (state == END_ELEMENT_STATE); + } + + public void init() { + // just add the current elements namespace and prefix to the this + // elements nscontext + registerNamespace(name.getPrefix(), name.getNamespaceURI()); + + } + + /** + * @param prefix + * @param uri + */ + private void registerNamespace(String prefix, String uri) { + // todo - need to fix this up to cater for cases where + // namespaces are having no prefixes + if (!uri.equals(namespaceContext.getNamespaceURI(prefix))) { + // this namespace is not there. Need to declare it + namespaceContext.registerMapping(prefix, uri); + } + } + + public int getAttributeCount() { + if (state == START_ELEMENT_STATE_WITH_NULL) + return 1; + if (state == START_ELEMENT_STATE) { + return 0; + } else { + throw new IllegalStateException(); + } + + } + + public String getAttributeLocalName(int i) { + if (state == START_ELEMENT_STATE_WITH_NULL && i == 0) + return XSI_NIL_QNAME.getLocalPart(); + if (state == START_ELEMENT_STATE) { + return null; + } else { + throw new IllegalStateException(); + } + } + + public QName getAttributeName(int i) { + if (state == START_ELEMENT_STATE_WITH_NULL && i == 0) + return XSI_NIL_QNAME; + if (state == START_ELEMENT_STATE) { + return null; + } else { + throw new IllegalStateException(); + } + } + + public String getAttributeNamespace(int i) { + if (state == START_ELEMENT_STATE_WITH_NULL && i == 0) + return XSI_NIL_QNAME.getNamespaceURI(); + if (state == START_ELEMENT_STATE) { + return null; + } else { + throw new IllegalStateException(); + } + } + + public String getAttributePrefix(int i) { + if (state == START_ELEMENT_STATE_WITH_NULL && i == 0) + return XSI_NIL_QNAME.getPrefix(); + if (state == START_ELEMENT_STATE) { + return null; + } else { + throw new IllegalStateException(); + } + } + + public String getAttributeType(int i) { + return null; // not implemented + } + + public String getAttributeValue(int i) { + if (state == START_ELEMENT_STATE_WITH_NULL && i == 0) + return "true"; + if (state == START_ELEMENT_STATE) { + return null; + } else { + throw new IllegalStateException(); + } + } + + public String getAttributeValue(String string, String string1) { + if (state == TEXT_STATE) { + // todo something + return null; + } else { + return null; + } + + } + + public int getNamespaceCount() { + if (state == START_ELEMENT_STATE_WITH_NULL && isXsiNamespacePresent()) + return 1; + else + return 0; + + } + + public String getNamespacePrefix(int i) { + if (state == START_ELEMENT_STATE_WITH_NULL && isXsiNamespacePresent() && i == 0) + return XSI_NIL_QNAME.getPrefix(); + else + return null; + } + + public String getNamespaceURI(int i) { + if (state == START_ELEMENT_STATE_WITH_NULL && isXsiNamespacePresent() && i == 0) + return XSI_NIL_QNAME.getNamespaceURI(); + else + return null; + } + + /** + * Test whether the xsi namespace is present + * + * @return + */ + private boolean isXsiNamespacePresent() { + return (namespaceContext.getNamespaceURI(XSI_NIL_QNAME.getPrefix()) != null); + } + + } + + protected class NameSpaceContext implements NamespaceContext { + private Map prefixToNamespaceMapping = new HashMap(); + + public NameSpaceContext() { + prefixToNamespaceMapping.put("xml", "http://www.w3.org/XML/1998/namespace"); + prefixToNamespaceMapping.put("xmlns", "http://www.w3.org/2000/xmlns/"); + prefixToNamespaceMapping.put("xsi", "http://www.w3.org/2001/XMLSchema-instance"); + } + + public String getNamespaceURI(String prefix) { + if (prefix == null) + throw new IllegalArgumentException("Prefix is null"); + + String ns = (String) prefixToNamespaceMapping.get(prefix); + if (ns != null) + return ns; + else + return null; + } + + public String getPrefix(String nsURI) { + if (nsURI == null) + throw new IllegalArgumentException("Namespace is null"); + for (Iterator i = prefixToNamespaceMapping.entrySet().iterator(); i.hasNext();) { + Map.Entry entry = (Map.Entry) i.next(); + if (entry.getValue().equals(nsURI)) { + return (String) entry.getKey(); + } + } + return null; + } + + public Iterator getPrefixes(String nsURI) { + List prefixList = new ArrayList(); + for (Iterator i = prefixToNamespaceMapping.entrySet().iterator(); i.hasNext();) { + Map.Entry entry = (Map.Entry) i.next(); + if (entry.getValue().equals(nsURI)) { + prefixList.add(entry.getKey()); + } + } + return prefixList.iterator(); + } + + public void registerMapping(String prefix, String nsURI) { + prefixToNamespaceMapping.put(prefix, nsURI); + } + + private int counter = 0; + + public synchronized QName createQName(String nsURI, String name) { + String prefix = nsURI != null ? (String) getPrefix(nsURI) : null; + if (prefix == null && nsURI != null && !nsURI.equals("")) + prefix = "p" + (counter++); + if (prefix == null) + prefix = ""; + if (nsURI != null) { + prefixToNamespaceMapping.put(prefix, nsURI); + declaredNamespaceMap.put(prefix, nsURI); + } + return new QName(nsURI, name, prefix); + } + + public void removeMapping(String prefix) { + prefixToNamespaceMapping.remove(prefix); + } + } + +} diff --git a/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/RecordedEventXMLStreamReader.java b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/RecordedEventXMLStreamReader.java new file mode 100644 index 0000000000..b2b3036692 --- /dev/null +++ b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/RecordedEventXMLStreamReader.java @@ -0,0 +1,868 @@ +/**
+ *
+ * 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.util.resource;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+import javax.xml.XMLConstants;
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.namespace.QName;
+import javax.xml.stream.Location;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.eclipse.emf.ecore.xmi.XMLResource;
+import org.xml.sax.Attributes;
+import org.xml.sax.Locator;
+
+/**
+ * This special purpose XMLStreamReader is used to produce a StAX event stream corresponding to a list of events
+ * recorded earlier. The recorded events are generated by the inner class RecordedEventXMLStreamReader.Tag,
+ * which records the events in either of 2 ways:
+ *
+ * 1) in conjunction with class SDOXMLLoadImpl, it records events corresponding to the SAX events being
+ * handled by the SDOXMLLoadImpl when loading XML using SDOXMLResourceImpl.
+ * 2) when Tag.record() is called (see class ChangeSummaryStreamDeserializer), it walks through and records
+ * the StAX events produced by another XMLStreamReader.
+ *
+ * This class is used by the SDO StAX-based ChangeSummaryType-property loader, class
+ * ChangeSummaryStreamDeserializer, which is inoked by and uses (for loading deleted object XML fragments)
+ * the SAX-based loader class XMLResourceImpl.
+ */
+public abstract class RecordedEventXMLStreamReader implements XMLStreamReader {
+
+ static private class Event {
+ int type;
+
+ public NamespaceContext nameSpaceContext;
+
+ Location location;
+
+ protected final void initialize(XMLStreamReader reader) {
+ nameSpaceContext = reader.getNamespaceContext();
+ location = reader.getLocation();
+ }
+
+ protected final void location(final Locator locator) {
+ location = new Location() {
+ public int getCharacterOffset() {
+ return -1;
+ }
+
+ public int getColumnNumber() {
+ return locator.getColumnNumber();
+ }
+
+ public int getLineNumber() {
+ return locator.getLineNumber();
+ }
+
+ public String getPublicId() {
+ return locator.getPublicId();
+ }
+
+ public String getSystemId() {
+ return locator.getSystemId();
+ }
+ };
+ }
+ }
+
+ static class ValueEvent extends Event {
+ final String value;
+
+ protected ValueEvent(String v) {
+ value = v;
+ }
+ }
+
+ static protected class Reference extends ValueEvent {
+ final String target;
+
+ protected Reference(String name, String data) {
+ super(data);
+ target = name;
+ }
+ }
+
+ static protected final class AttributeEvent extends Reference {
+ final QName name;
+
+ final String nameSpace, prefix;
+
+ int attributes;
+
+ final boolean specified;
+
+ protected AttributeEvent(XMLStreamReader reader) {
+ super(reader.getAttributeType(0), reader.getAttributeValue(0));
+ attributes = reader.getAttributeCount();
+ name = reader.getAttributeName(0);
+ nameSpace = reader.getAttributeNamespace(0);
+ prefix = reader.getAttributePrefix(0);
+ specified = reader.isAttributeSpecified(0);
+ }
+ }
+
+ static protected final class NameSpaceEvent extends Reference {
+ int nameSpaces;
+
+ protected NameSpaceEvent(XMLStreamReader reader) {
+ super(reader.getNamespacePrefix(0), reader.getNamespaceURI(0));
+ nameSpaces = reader.getNamespaceCount();
+ }
+ }
+
+ static protected String prefix(String qName, String nameSpace) {
+ int delimiter = qName.indexOf(':');
+ if (delimiter != -1)
+ return qName.substring(0, delimiter);
+ if (nameSpace.length() != 0)
+ return XMLConstants.DEFAULT_NS_PREFIX;
+ // if (nameSpaceContext.getNamespaceURI(XMLConstants.DEFAULT_NS_PREFIX) != null || xsdHelper.getGlobalProperty(null, name, element) == null)
+ return null;
+ }
+
+ static class EndElement extends Event {
+ List nameSpaces/* = null */;
+
+ public final QName name;
+
+ public final String nameSpace;
+
+ final String prefix;
+
+ protected EndElement(XMLStreamReader reader) {
+ name = reader.getName();
+ nameSpace = reader.getNamespaceURI();
+ prefix = reader.getPrefix();
+ int count = reader.getNamespaceCount();
+ if (count == 0)
+ return;
+ nameSpaces = new ArrayList(count);
+ int index = 0;
+ do
+ Tag.bind(reader.getNamespacePrefix(index), reader.getNamespaceURI(index), nameSpaces);
+ while (++index != count);
+ }
+
+ protected EndElement(String uri, String local, String p, Locator locator) {
+ if (p == null) {
+ name = new QName(uri, local, XMLConstants.DEFAULT_NS_PREFIX);
+ nameSpace = null;
+ } else {
+ name = new QName(uri, local, p);
+ nameSpace = uri;
+ }
+ prefix = p;
+ location(locator);
+ }
+ }
+
+ static class NameSpace {
+ final String prefix, uri;
+
+ protected NameSpace(String p, String nameSpace) {
+ prefix = p;
+ uri = nameSpace;
+ }
+ }
+
+ static final class Attribute extends NameSpace {
+ final String type, value;
+
+ final QName qName;
+
+ boolean specified/* = false */;
+
+ protected Attribute(String t, String v, QName name, String prefix, String nameSpace) {
+ super(prefix, nameSpace);
+ type = t;
+ value = v;
+ qName = name;
+ }
+ }
+
+ static final class AttributeList /* implements Attributes */{// TODO exclude XMLConstants.XMLNS_ATTRIBUTE
+ final List attributes;
+
+ protected AttributeList(int size) {
+ attributes = new ArrayList(size);
+ }
+
+ /*
+ * @param uri Never null
+ */
+ public final int getIndex(String uri, String localName) {
+ for (int index = getLength(); index != 0;)
+ if (getLocalName(--index).equals(localName) && uri.equals(getURI(index)))
+ return index;
+ return -1;
+ }
+
+ public final int getLength() {
+ return attributes.size();
+ }
+
+ protected final Attribute attribute(int index) {
+ return (Attribute) attributes.get(index);
+ }
+
+ public final String getLocalName(int index) {
+ return attribute(index).qName.getLocalPart();
+ }
+
+ public final String getType(int index) {
+ return attribute(index).type;
+ }
+
+ /*public String getType(String uri, String localName) {
+ int index = getIndex(uri, localName);
+ return index == -1 ? null: getType(index);
+ } */
+
+ public final String getURI(int index) {
+ return attribute(index).uri;
+ }
+
+ public final String getValue(int index) {
+ return attribute(index).value;
+ }
+
+ /*
+ * @param uri Never null
+ */
+ public final String getValue(String uri, String localName) {
+ int index = getIndex(uri, localName);
+ return index == -1 ? null : getValue(index);
+ }
+ }
+
+ static protected class StartElement extends EndElement {
+ final AttributeList attributes;
+
+ protected StartElement(XMLStreamReader reader) {
+ super(reader);
+ int count = reader.getAttributeCount();
+ if (count == 0)
+ attributes = null;
+ else {
+ attributes = new AttributeList(count);
+ int index = 0;
+ do {
+ Attribute attribute = new Attribute(reader.getAttributeType(index), reader.getAttributeValue(index), reader
+ .getAttributeName(index), reader.getAttributePrefix(index), reader.getAttributeNamespace(index));
+ attribute.specified = reader.isAttributeSpecified(index);
+ attributes.attributes.add(attribute);
+ } while (++index != count);
+ }
+ }
+
+ protected StartElement(String nameSpace, String local, String prefix, Attributes attributeArray, Locator locator, List bindings,
+ final NamespaceContext context) {
+ super(nameSpace, local, prefix, locator);
+ nameSpaces = bindings;
+ nameSpaceContext = bindings == null || bindings.isEmpty() ? context : new NamespaceContext() {
+ public String getNamespaceURI(String prefix) {
+ for (int index = nameSpaces.size(); index != 0;) {
+ NameSpace binding = (NameSpace) nameSpaces.get(--index);
+ if (binding.prefix.equals(prefix))
+ return binding.uri;
+ }
+ return context.getNamespaceURI(prefix);
+ }
+
+ public String getPrefix(String namespaceURI) {
+ for (int index = nameSpaces.size(); index != 0;) {
+ NameSpace binding = (NameSpace) nameSpaces.get(--index);
+ if (binding.uri.equals(namespaceURI))
+ return binding.prefix;
+ }
+ return context.getPrefix(namespaceURI);
+ }
+
+ public Iterator getPrefixes(final String namespaceURI) {
+ final Iterator iterator = context.getPrefixes(namespaceURI);
+ return new Iterator() {
+ Iterator bindings = nameSpaces.iterator();
+
+ NameSpace binding/* = null */;
+
+ protected final boolean prefix() {
+ while (bindings.hasNext()) {
+ binding = (NameSpace) bindings.next();
+ if (binding.uri.equals(namespaceURI))
+ return true;
+ }
+ bindings = null;
+ return false;
+ }
+
+ public boolean hasNext() {
+ return bindings != null && prefix() || iterator.hasNext();
+ }
+
+ protected NameSpace nameSpace;
+
+ public Object next() {
+ if (bindings == null || binding == null && !prefix())
+ return iterator.next();
+ nameSpace = binding;
+ binding = null;
+ return nameSpace.prefix;
+ }
+
+ public void remove() {
+ if (bindings == null)
+ iterator.remove();
+ else
+ nameSpaces.remove(nameSpace);
+ }
+ };
+ }
+ };
+ int count = attributeArray.getLength();
+ if (count == 0)
+ attributes = null;
+ else {
+ attributes = new AttributeList(count);
+ int index = 0;
+ do {
+ QName name;
+ nameSpace = attributeArray.getURI(index);
+ local = attributeArray.getLocalName(index);
+ prefix = prefix(attributeArray.getQName(index), nameSpace);
+ if (prefix == null) {
+ name = new QName(nameSpace, local, XMLConstants.DEFAULT_NS_PREFIX);
+ nameSpace = null;
+ } else
+ name = new QName(nameSpace, local, prefix);
+ attributes.attributes.add(new Attribute(attributeArray.getType(index), attributeArray.getValue(index), name, prefix, nameSpace));
+ } while (++index != count);
+ }
+ }
+ }
+
+ static public class Tag extends StartElement {
+ public Tag(XMLStreamReader reader) {
+ super(reader);
+ initialize(reader);
+ }
+
+ public List events/* = null */; // may be empty
+
+ protected final void events() {
+ events = new ArrayList();
+ }
+
+ public Tag(String nameSpace, String local, String prefix, Attributes attributes, Locator locator, NamespaceContext context, List bindings) {
+ super(nameSpace, local, prefix, attributes, locator, bindings, context);
+ events();
+ }
+
+ static public void bind(String prefix, String nameSpace, Collection nameSpaces) {
+ nameSpaces.add(new NameSpace(prefix, nameSpace));
+ }
+
+ protected int nest/* = 0 */;
+
+ public final void start(String nameSpace, String local, String qName, Attributes attributes, Locator locator, List bindings) {
+ Event event;
+ for (int index = events.size();/* true */;) {
+ if (index == 0) {
+ event = this;
+ break;
+ }
+ event = (Event) events.get(--index);
+ if (event.type != END_ELEMENT)
+ break;
+ siblings: for (int nest = 0;/* true */;)
+ switch (((Event) events.get(--index)).type) {
+ case START_ELEMENT:
+ if (nest == 0)
+ break siblings;
+ --nest;
+ break;
+ case END_ELEMENT:
+ ++nest;
+ }
+ }
+ Event start = new StartElement(nameSpace, local, prefix(qName, nameSpace), attributes, locator, bindings, event.nameSpaceContext);
+ start.type = START_ELEMENT;
+ events.add(start);
+ ++nest;
+ }
+
+ protected final void add (Event event)
+ {
+ int index = events.size();
+ event.nameSpaceContext = index == 0 ? nameSpaceContext : ((Event) events.get(--index)).nameSpaceContext;
+ events.add(event);
+ }
+
+ public final void text(int type, String value, Locator locator) {
+ Event event = new ValueEvent(value);
+ event.type = type;
+ event.location(locator);
+ //int index = events.size();
+ add(event);
+ }
+
+ public final boolean end(String nameSpace, String local, String qName, Locator locator) {
+ Event end = new EndElement(nameSpace, local, prefix(qName, nameSpace), locator);
+ end.type = END_ELEMENT;
+ add(end);
+ if (nest == 0)
+ return true;
+ --nest;
+ return false;
+ }
+
+ public final XMLStreamReader play(final XMLResource resource) {
+ return new RecordedEventXMLStreamReader(this) {
+ public void close() {
+ }
+
+ public String getCharacterEncodingScheme() {
+ return null; // TODO
+ }
+
+ public String getEncoding() {
+ return resource.getEncoding();
+ }
+
+ public Object getProperty(String property) {
+ return null; // TODO javax.xml.stream.notations & javax.xml.stream.entities for DTD
+ }
+
+ public String getVersion() {
+ return resource.getXMLVersion();
+ }
+
+ public boolean isStandalone() {
+ return false; // TODO
+ }
+
+ public boolean standaloneSet() {
+ return false; // TODO
+ }
+ };
+ }
+
+ protected final void add(Event event, int type, XMLStreamReader reader) {
+ event.type = type;
+ event.initialize(reader);
+ events.add(event);
+ }
+
+ public final boolean record(XMLStreamReader reader) throws XMLStreamException {
+ events();
+ for (int nest = 0; reader.hasNext();) {
+ Event event;
+ int type = reader.next();
+ switch (type) {
+ case CHARACTERS:
+ case CDATA:
+ case COMMENT:
+ case SPACE:
+ case DTD:
+ event = new ValueEvent(reader.getText());
+ break;
+ case ENTITY_REFERENCE:
+ event = new Reference(reader.getLocalName(), reader.getText());
+ break;
+ case PROCESSING_INSTRUCTION:
+ event = new Reference(reader.getPITarget(), reader.getPIData());
+ break;
+ case ATTRIBUTE:
+ event = new AttributeEvent(reader);
+ break;
+ case NAMESPACE:
+ event = new NameSpaceEvent(reader);
+ break;
+ case START_ELEMENT:
+ ++nest;
+ event = new StartElement(reader);
+ break;
+ case END_ELEMENT:
+ add(new EndElement(reader), type, reader);
+ if (nest == 0)
+ return false;
+ --nest;
+ continue;
+ case END_DOCUMENT:
+ return true; // report error?
+ default: // new type
+ event = new Event();
+ }
+ add(event, type, reader);
+ }
+ return true; // report error?
+ }
+
+ public final XMLStreamReader play(final XMLStreamReader reader) {
+ return new RecordedEventXMLStreamReader(this) {
+ public void close() throws XMLStreamException {
+ reader.close();
+ }
+
+ public String getCharacterEncodingScheme() {
+ return reader.getCharacterEncodingScheme();
+ }
+
+ public String getEncoding() {
+ return reader.getEncoding();
+ }
+
+ public Object getProperty(String property) {
+ return reader.getProperty(property); // TODO javax.xml.stream.notations & javax.xml.stream.entities for DTD
+ }
+
+ public String getVersion() {
+ return reader.getVersion();
+ }
+
+ public boolean isStandalone() {
+ return reader.isStandalone();
+ }
+
+ public boolean standaloneSet() {
+ return reader.standaloneSet();
+ }
+ };
+ }
+ }
+
+ Event event;
+
+ final List events;
+
+ final int size;
+
+ protected RecordedEventXMLStreamReader(Tag tag) {
+ event = tag;
+ tag.type = START_ELEMENT;
+ events = tag.events;
+ size = events.size();
+ }
+
+ public int getAttributeCount() {
+ switch (getEventType()) {
+ case START_ELEMENT:
+ AttributeList attributes = ((StartElement) event).attributes;
+ return attributes == null ? 0 : attributes.getLength();
+ case ATTRIBUTE:
+ return ((AttributeEvent) event).attributes;
+ }
+ throw new IllegalStateException("Neither START_ELEMENT nor ATTRIBUTE");
+ }
+
+ protected final AttributeList attributes() {
+ if (getEventType() == START_ELEMENT)
+ return ((StartElement) event).attributes;
+ throw new IllegalStateException("Neither START_ELEMENT nor ATTRIBUTE");
+ }
+
+ public String getAttributeLocalName(int index) {
+ return attributes().getLocalName(index);
+ }
+
+ static Attribute attribute(AttributeList attributes, int index) {
+ return (Attribute) attributes.attributes.get(index);
+ }
+
+ public QName getAttributeName(int index) {
+ return getEventType() == ATTRIBUTE ? ((AttributeEvent) event).name : attribute(attributes(), index).qName;
+ }
+
+ public String getAttributeNamespace(int index) {
+ return getEventType() == ATTRIBUTE ? ((AttributeEvent) event).nameSpace : attributes().getURI(index);
+ }
+
+ public String getAttributePrefix(int index) {
+ return getEventType() == ATTRIBUTE ? ((AttributeEvent) event).prefix : attribute(attributes(), index).prefix;
+ }
+
+ public String getAttributeType(int index) {
+ return getEventType() == ATTRIBUTE ? ((Reference) event).target : attributes().getType(index);
+ }
+
+ public String getAttributeValue(int index) {
+ return getEventType() == ATTRIBUTE ? ((ValueEvent) event).value : attributes().getValue(index);
+ }
+
+ public boolean isAttributeSpecified(int index) {
+ if (getEventType() == ATTRIBUTE)
+ return ((AttributeEvent) event).specified;
+ AttributeList attributes = attributes();
+ return attribute(attributes, index).specified;
+ }
+
+ public String getAttributeValue(String nameSpace, String name) {
+ if (getEventType() == ATTRIBUTE) {
+ AttributeEvent attribute = (AttributeEvent) event;
+ return !attribute.name.getLocalPart().equals(name) ? null : nameSpace == null ? (attribute.nameSpace == null ? attribute.value : null)
+ : nameSpace.equals(attribute.nameSpace) ? attribute.value : null;
+ }
+ AttributeList attributes = attributes();
+ return attributes == null ? null : attributes.getValue(nameSpace == null ? "" : nameSpace, name);
+ }
+
+ protected StringBuffer buffer/* = null */;
+
+ public String getElementText() {
+ if (buffer != null)
+ buffer.delete(0, buffer.length());
+ for (;;)
+ switch (next()) {
+ case END_ELEMENT:
+ return buffer == null ? null : buffer.toString();
+ default:
+ if (buffer == null)
+ buffer = new StringBuffer();
+ buffer.append(getText());
+ case PROCESSING_INSTRUCTION:
+ case COMMENT:
+ }
+ }
+
+ public final int getEventType() {
+ return event.type;
+ }
+
+ public String getLocalName() {
+ if (getEventType() == ENTITY_REFERENCE)
+ return ((Reference) event).target;
+ if (event instanceof EndElement)
+ return ((EndElement) event).name.getLocalPart();
+ throw new IllegalStateException("Neither START_ELEMENT, END_ELEMENT nor ENTITY_REFERENCE");
+ }
+
+ public final Location getLocation() {
+ return event.location;
+ }
+
+ public QName getName() {
+ if (hasName())
+ return ((EndElement) event).name;
+ throw new IllegalStateException("Neither START_ELEMENT nor END_ELEMENT");
+ }
+
+ public final NamespaceContext getNamespaceContext() {
+ return event.nameSpaceContext;
+ }
+
+ public int getNamespaceCount() {
+ if (getEventType() == NAMESPACE)
+ return ((NameSpaceEvent) event).nameSpaces;
+ if (!(event instanceof EndElement))
+ throw new IllegalStateException("Neither START_ELEMENT, END_ELEMENT nor NAMESPACE");
+ Collection nameSpaces = ((EndElement) event).nameSpaces;
+ return nameSpaces == null ? 0 : nameSpaces.size();
+ }
+
+ protected final NameSpace getNameSpace(int index) {
+ if (event instanceof EndElement)
+ return (NameSpace) ((EndElement) event).nameSpaces.get(index);
+ throw new IllegalStateException("Neither START_ELEMENT, END_ELEMENT nor NAMESPACE");
+ }
+
+ public String getNamespacePrefix(int index) {
+ return getEventType() == NAMESPACE ? ((Reference) event).target : getNameSpace(index).prefix;
+ }
+
+ public final String getNamespaceURI() {
+ switch (getEventType()) {
+ case ATTRIBUTE:
+ return ((AttributeEvent) event).nameSpace;
+ case NAMESPACE:
+ return ((ValueEvent) event).value;
+ }
+ return event instanceof EndElement ? ((EndElement) event).nameSpace : null;
+ }
+
+ public String getNamespaceURI(String prefix) {
+ return getNamespaceContext().getNamespaceURI(prefix);
+ }
+
+ public String getNamespaceURI(int index) {
+ return getEventType() == NAMESPACE ? ((ValueEvent) event).value : getNameSpace(index).uri;
+ }
+
+ public String getPIData() {
+ return getEventType() == PROCESSING_INSTRUCTION ? ((ValueEvent) event).value : null;
+ }
+
+ public String getPITarget() {
+ return getEventType() == PROCESSING_INSTRUCTION ? ((Reference) event).target : null;
+ }
+
+ public String getPrefix() {
+ switch (getEventType()) {
+ case ATTRIBUTE:
+ return ((AttributeEvent) event).prefix;
+ case NAMESPACE:
+ return ((Reference) event).target;
+ }
+ return event instanceof EndElement ? ((EndElement) event).prefix : null;
+ }
+
+ public final String getText() {
+ if (hasText())
+ return ((ValueEvent) event).value;
+ throw new IllegalStateException("Neither CHARACTERS, CDATA, COMMENT, SPACE, ENTITY_REFERENCE nor DTD");
+ }
+
+ public final char[] getTextCharacters() {
+ switch (getEventType()) {
+ case CHARACTERS:
+ case CDATA:
+ case COMMENT:
+ case SPACE:
+ return ((ValueEvent) event).value.toCharArray();
+ }
+ throw new IllegalStateException("Neither CHARACTERS, CDATA, COMMENT nor SPACE");
+ }
+
+ public int getTextCharacters(int sourceStart, char[] target, int targetStart, int length) {
+ char[] source = getTextCharacters();
+ if (sourceStart > source.length)
+ throw new IndexOutOfBoundsException("source start > source length");
+ int sourceLen = source.length - sourceStart;
+ if (length > sourceLen)
+ length = sourceLen;
+ System.arraycopy(source, sourceStart, target, targetStart, length);
+ return sourceLen;
+ }
+
+ public int getTextLength() {
+ return getTextCharacters().length;
+ }
+
+ public int getTextStart() {
+ return 0;
+ }
+
+ public final boolean hasName() {
+ return event instanceof EndElement;
+ }
+
+ protected int next/* = 0 */;
+
+ public final boolean hasNext() {
+ return next != size;
+ }
+
+ public final boolean hasText() {
+ switch (getEventType()) {
+ case CHARACTERS:
+ case CDATA:
+ case COMMENT:
+ case SPACE:
+ case ENTITY_REFERENCE:
+ case DTD:
+ return true;
+ }
+ return false;
+ }
+
+ public boolean isCharacters() {
+ switch (getEventType()) {
+ case CHARACTERS:
+ case CDATA:
+ case SPACE:
+ return true;
+ }
+ return false;
+ }
+
+ public boolean isEndElement() {
+ return getEventType() == END_ELEMENT;
+ }
+
+ public boolean isStartElement() {
+ return getEventType() == START_ELEMENT;
+ }
+
+ protected final boolean areWhiteSpace() {
+ String text = getText();
+ for (int index = text.length(); index != 0;)
+ if (!Character.isWhitespace(text.charAt(--index)))
+ return false;
+ return true;
+ }
+
+ public boolean isWhiteSpace() {
+ switch (getEventType()) {
+ case CHARACTERS:
+ case CDATA:
+ return areWhiteSpace();
+ case SPACE:
+ return true;
+ }
+ return false;
+ }
+
+ public final int next() {
+ if (!hasNext())
+ throw new NoSuchElementException();
+ event = (Event) events.get(next++);
+ return event.type;
+ }
+
+ protected final void throwXMLStreamException(String message) throws XMLStreamException {
+ throw new XMLStreamException(message, getLocation());
+ }
+
+ public int nextTag() throws XMLStreamException {
+ for (;;) {
+ int type = next();
+ switch (type) {
+ case CHARACTERS:
+ case CDATA:
+ if (!areWhiteSpace())
+ break;
+ case SPACE:
+ case PROCESSING_INSTRUCTION:
+ case COMMENT:
+ continue;
+ case START_ELEMENT:
+ case END_ELEMENT:
+ return type;
+ }
+ throwXMLStreamException("expected start or end tag");
+ }
+ }
+
+ public void require(int type, String nameSpace, String name) throws XMLStreamException {
+ if (getEventType() != type)
+ throwXMLStreamException("type not matched");
+ if (nameSpace != null && !nameSpace.equals(getNamespaceURI()))
+ throwXMLStreamException("Name Space not matched");
+ if (name != null
+ && !(getEventType() == ATTRIBUTE ? name.equals(((AttributeEvent) event).name.getLocalPart()) : event instanceof EndElement
+ && name.equals(((EndElement) event).name.getLocalPart())))
+ throwXMLStreamException("name not matched");
+ }
+}
diff --git a/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/SDODeserializer.java b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/SDODeserializer.java new file mode 100644 index 0000000000..a4ee4eaf96 --- /dev/null +++ b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/SDODeserializer.java @@ -0,0 +1,339 @@ +/**
+ *
+ * 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.util.resource;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.tuscany.sdo.helper.TypeHelperImpl;
+import org.apache.tuscany.sdo.helper.XMLStreamHelper;
+import org.apache.tuscany.sdo.helper.XMLStreamHelperImpl;
+import org.apache.tuscany.sdo.util.StreamDeserializer;
+import org.eclipse.emf.common.notify.Notification;
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.common.util.TreeIterator;
+import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.EReference;
+import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.eclipse.emf.ecore.util.ExtendedMetaData;
+import org.eclipse.emf.ecore.xmi.XMLResource;
+
+import commonj.sdo.Property;
+import commonj.sdo.Type;
+import commonj.sdo.helper.HelperContext;
+import commonj.sdo.helper.TypeHelper;
+import commonj.sdo.helper.XSDHelper;
+
+/**
+ * SDO StAX Deserializer. The instance isn't thread-safe, however it's safe to use the instance any times on the same thread.
+ */
+public class SDODeserializer extends StreamDeserializer {
+ protected final void initialize(XMLStreamReader stream, HelperContext scope, Object rootObject) {
+ reader = stream;
+ xsdHelper = scope.getXSDHelper();
+ typeHelper = scope.getTypeHelper();
+ extendedMetaData = ((TypeHelperImpl) typeHelper).getExtendedMetaData();
+ deserializer = null;
+ root = (EObject) rootObject;
+ }
+
+ XSDHelper xsdHelper;
+
+ protected Property propertyInSequence;
+
+ Property getProperty(Object type) {
+ EClass c = (EClass) type;
+ EStructuralFeature containment = (EStructuralFeature) propertyInSequence;
+ Object containing = extendedMetaData.getAffiliation(c, containment);
+ // if (containing == null) report error?
+ if (containment == containing && containment.isDerived()) {
+ containing = extendedMetaData.getMixedFeature(c);
+ if (containing == null) {
+ containing = extendedMetaData.getGroup(containment);
+ if (containing == null)
+ return propertyInSequence;
+ }
+ }
+ return (Property) containing;
+ }
+
+ protected final Property getProperty(Type type, String nameSpace, String name, boolean element) {
+ for (Iterator iterator = type.getProperties().iterator(); iterator.hasNext();) {
+ propertyInSequence = (Property) iterator.next();
+ if (name.equals(xsdHelper.getLocalName(propertyInSequence))
+ && nameSpace.equals(xsdHelper.getNamespaceURI(propertyInSequence)))
+ return getProperty(type);
+ }
+ propertyInSequence = xsdHelper.getGlobalProperty(nameSpace, name, element);
+ // if (propertyInSequence == null) report error?
+ return getProperty(type);
+ }
+
+ protected final Property getProperty(Type type, String name) {
+ propertyInSequence = type.getProperty(name);
+ // if (propertyInSequence == null) report error?
+ return getProperty(type);
+ }
+
+ protected final Property getProperty(String nameSpace, String name, Type type) {
+ return null == nameSpace ? getProperty(type, name) : getProperty(type, nameSpace, name, true);
+ }
+
+ XMLStreamHelperImpl deserializer;
+
+ TypeHelper typeHelper;
+
+ protected Object load(XMLStreamReader reader, Map options) throws XMLStreamException {
+ if (deserializer == null)
+ deserializer = new XMLStreamHelperImpl(typeHelper);
+ return deserializer.loadObject(reader, options);
+ }
+
+ static Object value(Type type, XMLStreamReader reader) throws XMLStreamException {
+ return value(type, reader.getElementText(), reader.getNamespaceContext());
+ }
+
+ protected final Object value(Type type) throws XMLStreamException {
+ return "true".equals(reader.getAttributeValue(ExtendedMetaData.XSI_URI, XMLResource.NIL)) ? null : type.isDataType() ? value(type, reader)
+ : load(reader, null);
+ }
+
+ Map options/* = null */;
+
+ protected final Object value(XMLStreamReader reader) throws XMLStreamException {
+ Type propertyType = propertyInSequence.getType();
+ if (propertyType.isDataType())
+ return value(propertyType, reader);
+ if (options == null)
+ options = new HashMap();
+ options.put(XMLStreamHelper.OPTION_DEFAULT_ROOT_TYPE, propertyType);
+ return load(reader, options);
+ }
+
+ private boolean match(String name, String space, EStructuralFeature feature) {
+ return name.equals(extendedMetaData.getName(feature)) && space.equals(extendedMetaData.getNamespace(feature));
+ }
+
+ EObject step(String ref, int step, int index, EObject container, String prefix, NamespaceContext nameSpaces) {
+ String name = ref.substring(step, index);
+ Iterator iterator = container.eContents().iterator();
+ if (iterator.hasNext())
+ if (prefix == null)
+ do {
+ container = (EObject) iterator.next();
+ // if( container == null )continue;
+ if (name.equals(extendedMetaData.getName(container.eContainmentFeature())))
+ return container;
+ } while (iterator.hasNext());
+ else {
+ prefix = nameSpaces.getNamespaceURI(prefix);
+ do {
+ container = (EObject) iterator.next();
+ // if( container == null )continue;
+ if (match(name, prefix, container.eContainmentFeature()))
+ return container;
+ } while (iterator.hasNext());
+ }
+ return null;
+ }
+
+ EObject root;
+
+ ExtendedMetaData extendedMetaData;
+
+ protected final EObject referent(String ref, NamespaceContext nameSpaces) {
+ int length = ref.length();
+ switch (length) {
+ case 0:
+ return null;
+ case 1: // #
+ return root;
+ }
+ EObject container;
+ int step;
+ if (ref.charAt(1) == '/') {
+ container = EcoreUtil.getRootContainer(root);
+ if (length == 2)
+ return container;
+ if (ref.charAt(2) == '/') {
+ for (Iterator iterator = container.eContents().iterator();/* true */;) {
+ if (!iterator.hasNext())
+ return null;
+ container = (EObject) iterator.next();
+ // if( container != null )
+ break;
+ }
+ /*#// is invalid
+ if (length == 3)
+ return container; */
+ step = 3;
+ } else
+ step = 2;
+ } else {
+ container = root;
+ step = 1;
+ }
+ String prefix = null;
+ for (int index = step; ++index != length;) {
+ switch (ref.charAt(index)) {
+ case '/':
+ container = step(ref, step, index, container, prefix, nameSpaces);
+ if (container == null)
+ return null;
+ break;
+ case ':':
+ prefix = ref.substring(step, index);
+ if (++index == length)
+ return container; // report error?
+ step = index;
+ default:
+ continue;
+ case '[':
+ name = ref.substring(step, index);
+ step = ref.indexOf(']', index + 2);
+ if (step == -1)
+ return container; // report error?
+ index = Integer.parseInt(ref.substring(++index, step));
+ EStructuralFeature feature;
+ Iterator iterator = container.eContents().iterator();
+ if (prefix == null)
+ do {
+ if (!iterator.hasNext())
+ return null;
+ EObject content = (EObject) iterator.next();
+ // if( content == null )continue;
+ feature = content.eContainmentFeature();
+ } while (!name.equals(extendedMetaData.getName(feature)));
+ else {
+ prefix = nameSpaces.getNamespaceURI(prefix);
+ do {
+ if (!iterator.hasNext())
+ return null;
+ EObject content = (EObject) iterator.next();
+ // if( content == null )continue;
+ feature = content.eContainmentFeature();
+ } while (!match(name, prefix, feature));
+ }
+ Object value = container.eGet(feature);
+ if (value instanceof List) {
+ List values = (List) value;
+ if (index > values.size())
+ return null;
+ container = (EObject) values.get(--index);
+ } else if (index == 1)
+ container = (EObject) value;
+ else
+ return null;
+ index = ref.indexOf('/', ++step);
+ if (index == -1)
+ return container;
+ }
+ if (++index == length)
+ return container;
+ step = index;
+ prefix = null;
+ }
+ return step(ref, step, length, container, prefix, nameSpaces);
+ }
+
+ static protected class Ref implements EObject // FeatureMapEntry value
+ {
+ protected Ref(String path, NamespaceContext context) {
+ ref = path;
+ nameSpaces = context;
+ }
+
+ final String ref;
+
+ final NamespaceContext nameSpaces;
+
+ public TreeIterator eAllContents() {
+ return null;
+ }
+ public EClass eClass() {
+ return null;
+ }
+ public EObject eContainer() {
+ return null;
+ }
+ public EStructuralFeature eContainingFeature() {
+ return null;
+ }
+ public EReference eContainmentFeature() {
+ return null;
+ }
+ public EList eContents() {
+ return null;
+ }
+ public EList eCrossReferences() {
+ return null;
+ }
+ public Object eGet(EStructuralFeature feature) {
+ return null;
+ }
+ public Object eGet(EStructuralFeature feature, boolean resolve) {
+ return null;
+ }
+ public boolean eIsProxy() {
+ return false;
+ }
+ public boolean eIsSet(EStructuralFeature feature) {
+ return false;
+ }
+ public Resource eResource() {
+ return null;
+ }
+ public void eSet(EStructuralFeature feature, Object newValue) {
+ }
+ public void eUnset(EStructuralFeature feature) {
+ }
+ public EList eAdapters() {
+ return null;
+ }
+ public boolean eDeliver() {
+ return false;
+ }
+ public void eNotify(Notification notification) {
+ }
+ public void eSetDeliver(boolean deliver) {
+ }
+ }
+
+ protected final EObject referent(Ref path) {
+ return referent(path.ref, path.nameSpaces);
+ }
+
+ protected final Type typeXSI() {
+ return typedXSI() ? typeHelper.getType(nameSpace, name) : null;
+ }
+
+ protected final Type globalElementType(String nameSpace, String name) {
+ return xsdHelper.getGlobalProperty(nameSpace, name, true).getType();
+ }
+}
diff --git a/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/SDOObjectInputStream.java b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/SDOObjectInputStream.java new file mode 100644 index 0000000000..ddb0803a19 --- /dev/null +++ b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/SDOObjectInputStream.java @@ -0,0 +1,51 @@ +/**
+ *
+ * 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.util.resource;
+
+/**
+ * This class inherites off of ObjectInputStream providing a way to store the scope under which
+ * this inputStream has been created.
+ *
+ */
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+
+import commonj.sdo.helper.HelperContext;
+
+public class SDOObjectInputStream extends ObjectInputStream {
+
+ private HelperContext helperContext;
+
+ public SDOObjectInputStream(InputStream in, HelperContext helperContext) throws IOException{
+ super(in);
+ this.helperContext = helperContext;
+ }
+
+ public HelperContext getHelperContext() {
+ return helperContext;
+ }
+
+ public void setHelperContext(HelperContext helperContext) {
+ this.helperContext = helperContext;
+ }
+
+}
diff --git a/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/SDOObjectOutputStream.java b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/SDOObjectOutputStream.java new file mode 100644 index 0000000000..2250ee24d8 --- /dev/null +++ b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/SDOObjectOutputStream.java @@ -0,0 +1,51 @@ +/**
+ *
+ * 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.util.resource;
+
+/**
+ * This class inherites off of ObjectInputStream providing a way to store the scope under which
+ * this inputStream has been created.
+ *
+ */
+
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+
+import commonj.sdo.helper.HelperContext;
+
+public class SDOObjectOutputStream extends ObjectOutputStream {
+
+ private HelperContext helperContext;
+
+ public SDOObjectOutputStream(OutputStream os, HelperContext helperContext) throws IOException{
+ super(os);
+ this.helperContext = helperContext;
+ }
+
+ public HelperContext getHelperContext() {
+ return helperContext;
+ }
+
+ public void setHelperContext(HelperContext helperContext) {
+ this.helperContext = helperContext;
+ }
+
+}
diff --git a/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/SDOURIConverterImpl.java b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/SDOURIConverterImpl.java new file mode 100644 index 0000000000..639c556c83 --- /dev/null +++ b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/SDOURIConverterImpl.java @@ -0,0 +1,55 @@ +/**
+ *
+ * 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.util.resource;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.resource.impl.URIConverterImpl;
+
+public class SDOURIConverterImpl extends URIConverterImpl
+{
+ /**
+ * Disable going out to the wire.
+ */
+ protected InputStream createURLInputStream(URI uri) throws IOException {
+ String scheme = uri.scheme();
+ if ("http".equalsIgnoreCase(scheme) || "https".equalsIgnoreCase(scheme)) {
+ throw new Resource.IOWrappedException(
+ new RuntimeException("Reading remote URL not supported."));
+ }
+ return super.createURLInputStream(uri);
+ }
+
+ /**
+ * Disable going out to the wire.
+ */
+ protected OutputStream createURLOutputStream(URI uri) throws IOException {
+ String scheme = uri.scheme();
+ if ("http".equalsIgnoreCase(scheme) || "https".equalsIgnoreCase(scheme)) {
+ throw new Resource.IOWrappedException(
+ new RuntimeException("Writing remote URL not supported."));
+ }
+ return super.createURLOutputStream(uri);
+ }
+}
diff --git a/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/SDOXMLResourceFactoryImpl.java b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/SDOXMLResourceFactoryImpl.java new file mode 100644 index 0000000000..c8189f9766 --- /dev/null +++ b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/SDOXMLResourceFactoryImpl.java @@ -0,0 +1,47 @@ +/** + * + * 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.util.resource; + + +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.resource.impl.ResourceFactoryImpl; + +/** + * This class creates SDOXMLResourceImpl objects. + */ +public class SDOXMLResourceFactoryImpl extends ResourceFactoryImpl +{ + /** + * Constructor for SDOXMLResourceFactoryImpl. + */ + public SDOXMLResourceFactoryImpl() + { + super(); + } + + /** + * Creates an XMLResourceImpl and returns it. + */ + public Resource createResource(URI uri) + { + return new SDOXMLResourceImpl(uri); + } +} diff --git a/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/SDOXMLResourceImpl.java b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/SDOXMLResourceImpl.java new file mode 100644 index 0000000000..eeb88ca5b5 --- /dev/null +++ b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/SDOXMLResourceImpl.java @@ -0,0 +1,885 @@ +/** + * + * 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.util.resource; + +import java.io.IOException; +import java.io.Writer; +import java.net.URL; +import java.security.AccessController; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.xml.XMLConstants; +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; + +import org.apache.tuscany.sdo.SDOExtendedMetaData; +import org.apache.tuscany.sdo.helper.HelperContextImpl; +import org.apache.tuscany.sdo.helper.SDOExtendedMetaDataImpl; +import org.apache.tuscany.sdo.helper.XMLStreamHelper; +import org.apache.tuscany.sdo.helper.XSDHelperImpl; +import org.apache.tuscany.sdo.util.SDOUtil; +import org.apache.tuscany.sdo.util.StAX2SAXAdapter; +import org.eclipse.emf.common.util.URI; +import org.eclipse.emf.ecore.EClassifier; +import org.eclipse.emf.ecore.EFactory; +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.InternalEObject; +import org.eclipse.emf.ecore.resource.Resource; +import org.eclipse.emf.ecore.util.ExtendedMetaData; +import org.eclipse.emf.ecore.util.FeatureMap; +import org.eclipse.emf.ecore.xmi.XMIException; +import org.eclipse.emf.ecore.xmi.XMLHelper; +import org.eclipse.emf.ecore.xmi.XMLLoad; +import org.eclipse.emf.ecore.xmi.XMLOptions; +import org.eclipse.emf.ecore.xmi.XMLResource; +import org.eclipse.emf.ecore.xmi.XMLSave; +import org.eclipse.emf.ecore.xmi.impl.SAXXMLHandler; +import org.eclipse.emf.ecore.xmi.impl.XMLHelperImpl; +import org.eclipse.emf.ecore.xmi.impl.XMLLoadImpl; +import org.eclipse.emf.ecore.xmi.impl.XMLOptionsImpl; +import org.eclipse.emf.ecore.xmi.impl.XMLResourceImpl; +import org.eclipse.emf.ecore.xmi.impl.XMLSaveImpl; +import org.eclipse.emf.ecore.xmi.impl.XMLString; +import org.eclipse.emf.ecore.xmi.util.DefaultEcoreBuilder; +import org.eclipse.emf.ecore.xml.type.XMLTypePackage; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; + +import commonj.sdo.ChangeSummary; +import commonj.sdo.DataObject; +import commonj.sdo.helper.XSDHelper; + +public class SDOXMLResourceImpl extends XMLResourceImpl { + private XMLStreamReader reader; + + /** + * [rfeng] Override the XMLHelperImpl to replace the NamespaceSupport so that it's aware of the NamespaceContext from the XMLStreamReader + */ + public static class SDOXMLHelperImpl extends XMLHelperImpl { + + /** + * EMF XMLResource (SAX) may be used to load from only a *portion* of a StAX stream + * which may reference (global) namespaces bound outside the (local) portion. + * This class extends EMF's NamespaceSupport to make {@link #getPrefix} and {@link #getURI} + * query these global binding(s) after first checking the local context(s). + */ + private static class StreamNamespaceSupport extends XMLHelperImpl.NamespaceSupport { + protected NamespaceContext nameSpaceContext; + + public String getPrefix(String uri) { + String prefix = super.getPrefix(uri); + if (prefix == null) + try { + prefix = nameSpaceContext.getPrefix(uri); + } catch (Exception e) { + // HACK: + // java.lang.UnsupportedOperationException + // at org.apache.axiom.om.impl.llom.OMStAXWrapper.getNamespaceContext(OMStAXWrapper.java:984) + } + return prefix; + } + + public String getURI(String prefix) { + String uri = super.getURI(prefix); + if (uri == null) + try { + uri = nameSpaceContext.getNamespaceURI(prefix); + } catch (Exception e) { + // HACK: + // java.lang.UnsupportedOperationException + // at org.apache.axiom.om.impl.llom.OMStAXWrapper.getNamespaceContext(OMStAXWrapper.java:984) + } + return uri; + } + + public StreamNamespaceSupport(XMLStreamReader reader) { + super(); + nameSpaceContext = reader.getNamespaceContext(); + } + + } + + public SDOXMLHelperImpl(XMLResource resource, XMLStreamReader reader) { + this(reader); + setResource(resource); + } + + public SDOXMLHelperImpl(XMLStreamReader reader) { + super(); + if (reader instanceof XMLDocumentStreamReader) // Only use StreamNamespaceSupport when loading from a *portion* of a StAX stream + namespaceSupport = new StreamNamespaceSupport(reader); + } + + private class NameSpaceContext implements NamespaceContext { // TODO Helper# pushContext() & popContext + public String getNamespaceURI(String prefix) { + return SDOXMLHelperImpl.this.getNamespaceURI(prefix); + } + + public String getPrefix(String namespaceURI) { + return SDOXMLHelperImpl.this.getPrefix(namespaceURI); + } + + public Iterator getPrefixes(String namespaceURI) { + return ((Collection) urisToPrefixes.get(namespaceURI)).iterator(); + } + } + + NameSpaceContext nameSpaceContext/* = null */; + + protected final NameSpaceContext nameSpaceContext() { + if (nameSpaceContext == null) + nameSpaceContext = new NameSpaceContext(); + return nameSpaceContext; + } + } + + public EObject root; + + /** + * An EMF XMLLoad that loads a model from a StAX stream + */ + public class SDOXMLLoadImpl extends XMLLoadImpl { + public SDOXMLLoadImpl(XMLHelper helper) { + super(helper); + } + + final class XmlHandler extends SAXXMLHandler { + XmlHandler() { + super(resource, SDOXMLLoadImpl.this.helper, options); + } + + protected void handleTopLocations(String prefix, String name) { + processSchemaLocations(prefix, name); + if (!processAnyXML) + return; + String nameSpace = helper.getURI(prefix); + if (extendedMetaData.getPackage(nameSpace) == null) + if (options.get(XMLStreamHelper.OPTION_DEFAULT_ROOT_TYPE) == null) + extendedMetaData.demandFeature(nameSpace, name, true); + else + extendedMetaData.demandPackage(nameSpace); + } + + EClassifier defaultRootType(String prefix, String name, boolean isElement, EObject peekObject, String value) { + Object type = options.get(XMLStreamHelper.OPTION_DEFAULT_ROOT_TYPE); + if (type != null) + return (EClassifier) type; + super.handleUnknownFeature(prefix, name, isElement, peekObject, value); + return null; + } + + protected void handleUnknownFeature(String prefix, String name, boolean isElement, EObject peekObject, String value) { + if (objects.size() == 1) { + EFactory eFactory; + EClassifier type; + String typeQName = getXSIType(); + if (typeQName == null) { + type = defaultRootType(prefix, name, isElement, peekObject, value); + if (type == null) + return; + eFactory = type.getEPackage().getEFactoryInstance(); + } else {// createObjectFromTypeName + String typeName = null; + String xsiPrefix = XMLConstants.DEFAULT_NS_PREFIX; + int index = typeQName.indexOf(":"); + if (index > 0) { + xsiPrefix = typeQName.substring(0, index); + typeName = typeQName.substring(index + 1); + } else + typeName = typeQName; + eFactory = getFactoryForPrefix(xsiPrefix); + if (eFactory != null) + type = helper.getType(eFactory, typeName); + else if (XMLConstants.DEFAULT_NS_PREFIX.equals(xsiPrefix) && helper.getURI(xsiPrefix) == null) { + EPackage ePackage = handleMissingPackage(null); + if (ePackage == null) { + type = defaultRootType(prefix, name, isElement, peekObject, value); + if (type == null) + return; + eFactory = type.getEPackage().getEFactoryInstance(); + } else + type = helper.getType(eFactory = ePackage.getEFactoryInstance(), typeName); + } else { + type = defaultRootType(prefix, name, isElement, peekObject, value); + if (type == null) + return; + eFactory = type.getEPackage().getEFactoryInstance(); + } + } + root = helper.createObject(eFactory, type); + if (root != null) { + if (disableNotify) + root.eSetDeliver(false); + handleObjectAttribs(root); + processObject(root); + return; + } + } + super.handleUnknownFeature(prefix, name, isElement, peekObject, value); + } + + protected RecordedEventXMLStreamReader.Tag tag/* =null */; + + protected List nameSpaces/* = null */; + + public void startPrefixMapping(String prefix, String uri) { + if (nameSpaces == null) + nameSpaces = new ArrayList(); + RecordedEventXMLStreamReader.Tag.bind(prefix, uri, nameSpaces); + if (tag == null) + super.startPrefixMapping(prefix, uri); + } + + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + if (tag != null) { + tag.start(uri, localName, qName, attributes, locator, nameSpaces); + nameSpaces = null; + return; + } + EObject peekObject = objects.peekEObject(); + if (peekObject != null) { + String prefix = helper.getPrefix(uri.length() == 0 ? null : uri); + EStructuralFeature feature = getFeature(peekObject, prefix == null ? XMLConstants.DEFAULT_NS_PREFIX : prefix, localName, true); + if (feature != null && feature.getEType() == ChangeSummaryStreamSerializer.ChangeSummary_TYPE) { + tag = new RecordedEventXMLStreamReader.Tag(uri, localName, prefix, attributes, locator, ((SDOXMLHelperImpl) helper).nameSpaceContext(), + nameSpaces); + nameSpaces = null; + return; + } + } + if (nameSpaces != null) + nameSpaces.clear(); + super.startElement(uri, localName, qName, attributes); + } + + public void characters(char[] ch, int start, int length) { + if (tag == null) + super.characters(ch, start, length); + else + tag.text(XMLStreamConstants.CHARACTERS, new String(ch, start, length), locator); + } + + protected Collection changeSummaryDeserializers/* = null */; + + public void endElement(String uri, String localName, String qName) { + if (tag == null) + super.endElement(uri, localName, qName); + else if (tag.end(uri, localName, qName, locator)) { + if (changeSummaryDeserializers == null) + changeSummaryDeserializers = new ArrayList(); + ChangeSummaryStreamDeserializer changeSummaryDeserializer = new ChangeSummaryStreamDeserializer(); + try { + changeSummaryDeserializer.begin( + (DataObject) objects.peekEObject(), + new HelperContextImpl(extendedMetaData, false), + tag.play(xmlResource)); + changeSummaryDeserializers.add(changeSummaryDeserializer); + } catch (XMLStreamException e) { + xmlResource.getErrors().add(new XMIException(e)); + } + tag = null; + } + } + + public void endDocument() { + super.endDocument(); + if (changeSummaryDeserializers != null) + for (Iterator iterator = changeSummaryDeserializers.iterator(); iterator.hasNext();) + try { + ((ChangeSummaryStreamDeserializer) iterator.next()).end(); + // iterator.remove(); + } catch (XMLStreamException e) { + xmlResource.getErrors().add(new XMIException(e)); + } + } + } + + protected DefaultHandler makeDefaultHandler() { + return new XmlHandler(); + } + + /** + * Start parsing an XMLReader with the default handler. + */ + public void load(XMLResource resource, final XMLStreamReader reader, Map options) throws IOException { + this.resource = resource; + Map mergedOptions = new HashMap(defaultLoadOptions); + if (options != null) + mergedOptions.putAll(options); + + this.options = mergedOptions; + + final ContentHandler handler = makeDefaultHandler(); + + if (errors != null) { + errors.clear(); + } + + final StAX2SAXAdapter adapter = new StAX2SAXAdapter(true); + // Parse the XMLReader and generate SAX events + try { + AccessController.doPrivileged(new PrivilegedExceptionAction() { + public Object run() throws XMLStreamException, SAXException { + adapter.parse(reader, handler); + return null; + } + }); + } catch (PrivilegedActionException e) { + throw new Resource.IOWrappedException(e.getException()); + } + + helper = null; + if (!resource.getErrors().isEmpty()) { + Exception error = (Exception) resource.getErrors().get(0); + if (error instanceof XMIException) { + XMIException exception = (XMIException) error; + if (exception.getWrappedException() != null) { + throw new Resource.IOWrappedException(exception.getWrappedException()); + } + } + throw new Resource.IOWrappedException(error); + } + } + } + + public SDOXMLResourceImpl(URI uri) { + super(uri); + } + + protected XMLHelper createXMLHelper() { + return new SDOXMLHelperImpl(this, reader); + } + + /** + * @see org.eclipse.emf.ecore.xmi.impl.XMLResourceImpl#createXMLLoad() + */ + protected XMLLoad createXMLLoad() { + return new SDOXMLLoadImpl(createXMLHelper()); + } + + static protected int loadLaxForm; + static { + int defaultLaxForm = 0x4242; + String property = System.getProperty("XML.load.form.lax"); + if (property == null) + loadLaxForm = defaultLaxForm; + else + try { + loadLaxForm = Integer.decode(property).intValue(); + } catch (NumberFormatException eNumberFormat) { + loadLaxForm = defaultLaxForm; + } + } + + public void doLoad(InputSource inputSource, Map options) throws IOException { + if (options != null) { + /* + * Tolerates element/attribute malform unless indicated not to + */ + Object option = options.get(SDOUtil.XML_LOAD_LaxForm); + int tolerance = option == null ? loadLaxForm : ((Number) option).intValue(); + option = options.get(OPTION_EXTENDED_META_DATA); + if (tolerance == 0) { + if (option instanceof SDOExtendedMetaData) + ((SDOExtendedMetaData) option).setFeatureNamespaceMatchingLax(false); + } else if (option instanceof SDOExtendedMetaData) + ((SDOExtendedMetaData) option).setFeatureNamespaceMatchingLax(true); + else + options.put(OPTION_EXTENDED_META_DATA, option = new SDOExtendedMetaDataImpl()); // TODO copy (BasicExtendedMetaData)option + /* + * Loads schema if necessary + */ + if (Boolean.TRUE.equals(options.get(SDOUtil.XML_LOAD_SCHEMA))) { + XMLOptions xmlOptions = (XMLOptions) options.get(OPTION_XML_OPTIONS); + if (xmlOptions == null) { + xmlOptions = new XMLOptionsImpl(); + options.put(OPTION_XML_OPTIONS, xmlOptions); + } + xmlOptions.setProcessSchemaLocations(true); + if (option == null) + option = getDefaultLoadOptions().get(OPTION_EXTENDED_META_DATA); + ExtendedMetaData extendedMetaData; + final XSDHelper xsdHelper; + if (option == null) { + extendedMetaData = ExtendedMetaData.INSTANCE; + xsdHelper = XSDHelper.INSTANCE; + } else { + extendedMetaData = (ExtendedMetaData) option; + xsdHelper = new XSDHelperImpl(extendedMetaData, null); + } + xmlOptions.setEcoreBuilder(new DefaultEcoreBuilder(extendedMetaData) { + public Collection generate(Map targetNamespaceToURI) throws IOException { + for (Iterator iterator = targetNamespaceToURI.values().iterator(); iterator.hasNext();) { + String uri = iterator.next().toString(); + xsdHelper.define(uri.indexOf(":/") == -1 ? Thread.currentThread().getContextClassLoader().getResourceAsStream(uri) + : new URL(uri).openStream(), uri); + } + return null; // XMLHandler#processSchemaLocations doesn't take the result + } + }); + } + } else if (loadLaxForm != 0) { + /* + * Tolerates element/attribute malform + */ + options = new HashMap(); + options.put(OPTION_EXTENDED_META_DATA, new SDOExtendedMetaDataImpl()); + } + super.doLoad(inputSource, options); + // TODO there is some thinking to be done about the restoration of options + } + + /** + * Loads the resource from a StAX XMLStreamReader. + */ + public void load(XMLStreamReader reader, Map options) throws IOException { + this.reader = reader; + SDOXMLLoadImpl xmlLoad = (SDOXMLLoadImpl) createXMLLoad(); + Map mergedOptions = new HashMap(defaultLoadOptions); + if (options != null) + mergedOptions.putAll(options); + xmlLoad.load(this, reader, mergedOptions); + } + + ChangeSummaryStreamSerializer changeSummarySerializer/* = null*/; + + static private final class LocalName extends QName { + private LocalName(String name) { + super(name); + } + + public String getNamespaceURI() { + return null; + } + } + + static final String INDENT = " ", LINE_SEPARATOR = System.getProperty("line.separator"); + + static final class XmlString extends XMLString { + XmlString(int lineWidth, String temporaryFileName) { + super(lineWidth, temporaryFileName); // setLineWidth & setTemporaryFileName + } + + XmlString(int lineWidth, String publicId, String systemId, String temporaryFileName) { + super(lineWidth, publicId, systemId, temporaryFileName); + } + + void setLineBreak(String lineBreak) { + lineSeparator = lineBreak; + } + + void margin(String margin) { + indents.set(0, margin); + } + + String indent = INDENT; + + protected String getElementIndent(int extra) { + int nesting = depth + extra - 1; + for (int i = indents.size() - 1; i < nesting; ++i) { + indents.add(indents.get(i) + indent); + } + return (String) indents.get(nesting); + } + + protected String getAttributeIndent() { + return getElementIndent(); + } + + public final boolean mixed() { + return isMixed; + } + + public void reset(String publicId, String systemId, int lineWidth, String temporaryFileName) { + super.reset(publicId, systemId, lineWidth, temporaryFileName); + setLineBreak(LINE_SEPARATOR); + indent = INDENT; + } + } + + static final char MARK = '\n'; + + static final String LINE_BREAK = new String(new char[] { MARK }); + + final class SDOXMLSaveImpl extends XMLSaveImpl { + SDOXMLSaveImpl(XMLHelper helper) { + super(helper); + } + + XmlString doc(XMLResource resource, Map options) { + if (doc instanceof XmlString) + return (XmlString) doc; + Object lineWidth = options.get(OPTION_LINE_WIDTH); + int width = lineWidth == null ? Integer.MAX_VALUE : ((Number) lineWidth).intValue(); + XmlString d = resource != null && Boolean.TRUE.equals(options.get(OPTION_SAVE_DOCTYPE)) ? new XmlString(width, resource.getPublicId(), + resource.getSystemId(), doc.getTemporaryFileName()) : new XmlString(width, doc.getTemporaryFileName()); + doc = d; + return d; + } + + Map changeSummaryOptions = new HashMap(); + String indent = INDENT, margin; + + protected void init(XMLResource resource, Map options) { + super.init(resource, options); + int unformat = 0; + String lineBreak = (String) options.get(SDOUtil.XML_SAVE_LineBreak); + if (lineBreak == null) + changeSummaryOptions.put(SDOUtil.XML_SAVE_LineBreak, LINE_BREAK); + else if (lineBreak.length() == 0) + ++unformat; + else { + changeSummaryOptions.put(SDOUtil.XML_SAVE_LineBreak, LINE_BREAK); + if (lineBreak.equals(LINE_SEPARATOR)) + lineBreak = null; + } + String indent = (String) options.get(SDOUtil.XML_SAVE_INDENT); + if (indent == null) + changeSummaryOptions.put(SDOUtil.XML_SAVE_INDENT, INDENT); + else if (indent.length() == 0) + ++unformat; + else { + changeSummaryOptions.put(SDOUtil.XML_SAVE_INDENT, this.indent = indent); + if (indent.equals(INDENT)) + indent = null; + } + String margin = (String) options.get(SDOUtil.XML_SAVE_MARGIN); + if (margin == null || margin.length() == 0) { + if (unformat == 2) + doc.setUnformatted(true); + else if (lineBreak != null) { + XmlString d = doc(resource, options); + d.setLineBreak(lineBreak); + if (indent != null) + d.indent = indent; + } else if (indent != null) + doc(resource, options).indent = indent; + this.margin = this.indent; + } else { + XmlString d = doc(resource, options); + d.margin(margin); + if (lineBreak != null) + d.setLineBreak(lineBreak); + if (indent != null) + d.indent = indent; + this.margin = margin + this.indent; + if (!toDOM && declareXML) + d.add(margin); + } + // changeSummaryOptions.put(ChangeSummaryStreamSerializer.OPTION_RootObject_PATH, "#"); + // changeSummaryOptions.put(ChangeSummaryStreamSerializer.OPTION_OPTIMIZE_LIST, Boolean.TRUE); + changeSummaryOptions.put(OPTION_EXTENDED_META_DATA, extendedMetaData); + } + + QName qName(EStructuralFeature f) { + if (extendedMetaData == null) + return new LocalName(f.getName()); + String nameSpace = extendedMetaData.getNamespace(f), name = extendedMetaData.getName(f); + return nameSpace == null ? new LocalName(name) : new QName(nameSpace, name); + } + + XMLStreamWriter xmlStreamWriter/* = null*/; + + void saveChangeSummary(EObject o, EStructuralFeature f, Object changeSummary) { + boolean notMixed; + if (doc instanceof XmlString) + notMixed = !((XmlString) doc).mixed(); + else if (extendedMetaData == null) + notMixed = true; + else + switch (extendedMetaData.getContentKind(o.eClass())) { + case ExtendedMetaData.MIXED_CONTENT: + case ExtendedMetaData.SIMPLE_CONTENT: + notMixed = false; + break; + default: + notMixed = true; + } + if (notMixed) { + StringBuffer margin = new StringBuffer(this.margin); + for (EObject container = o.eContainer(), grandContainer; (grandContainer = container.eContainer()) != null; container = grandContainer) + margin.append(indent); + changeSummaryOptions.put(SDOUtil.XML_SAVE_MARGIN, margin.toString()); + } + try { + if (xmlStreamWriter == null) { + xmlStreamWriter = XMLOutputFactory.newInstance().createXMLStreamWriter(new Writer() { + public void close() { + } + + public void flush() { + } + + protected final void add(char[] cbuf, int index, int off) { + doc.addText(new String(cbuf, index, off - index)); + } + + public void write(char[] cbuf, int off, int len) { + if (len != 0) + for (;;) { + while (cbuf[off] == MARK) { + doc.addLine(); + if (--len == 0) + return; + ++off; + } + for (int index = off;/* true */;) { + ++off; + if (--len == 0) + add(cbuf, index, off); + else { + if (cbuf[off] != MARK) + continue; + add(cbuf, index, off); + doc.addLine(); + if (--len != 0) + break; + } + return; + } + ++off; + } + } + }); + xmlStreamWriter.setNamespaceContext(((SDOXMLHelperImpl) helper).new NameSpaceContext() { + public String getNamespaceURI(String prefix) { + return declareXSI && ExtendedMetaData.XSI_PREFIX.equals(prefix) ? ExtendedMetaData.XSI_URI : super + .getNamespaceURI(prefix); + } + + public String getPrefix(String namespaceURI) { + return declareXSI && ExtendedMetaData.XSI_URI.equals(namespaceURI) ? ExtendedMetaData.XSI_PREFIX : super + .getPrefix(namespaceURI); + } + + public Iterator getPrefixes(String namespaceURI) { + final Iterator iterator = super.getPrefixes(namespaceURI); + return ExtendedMetaData.XSI_URI.equals(namespaceURI) ? new Iterator() { + boolean first = true; + + public boolean hasNext() { + if (first) + if (declareXSI) // never from true to false + return true; + else + first = false; + return iterator.hasNext(); + } + + public Object next() { + if (first) { + first = false; + if (declareXSI) + return ExtendedMetaData.XSI_PREFIX; + } + return iterator.next(); + } + + public void remove() { + if (first) + declareXSI = false; + else + iterator.remove(); + } + } : iterator; + } + }); + for (Iterator iterator = helper.getPrefixToNamespaceMap().iterator(); iterator.hasNext();) { + Map.Entry entry = (Map.Entry) iterator.next(); + xmlStreamWriter.setPrefix((String) entry.getKey(), (String) entry.getValue()); + } + if (declareXSI) + xmlStreamWriter.setPrefix(ExtendedMetaData.XSI_PREFIX, ExtendedMetaData.XSI_URI); + if (changeSummarySerializer == null) + changeSummarySerializer = new ChangeSummaryStreamSerializer(); + } + changeSummarySerializer.saveChangeSummary((ChangeSummary) changeSummary, qName(f), xmlStreamWriter, changeSummaryOptions); + if (notMixed) + doc.addLine(); + } catch (XMLStreamException e) { + xmlResource.getErrors().add(new XMIException(e)); + } + } + + protected void saveDataTypeElementSingle(EObject o, EStructuralFeature f) { + if (f.getEType() == ChangeSummaryStreamSerializer.ChangeSummary_TYPE) + saveChangeSummary(o, f, helper.getValue(o, f)); + else + super.saveDataTypeElementSingle(o, f); + } + + /* + * TEMPORARILY COPIED FROM BASE CLASS - DO NOT EDIT - WILL BE REMOVED WHEN WE MOVE TO EMF 2.3 + */ + protected boolean saveElementFeatureMap(EObject o, EStructuralFeature f) + { + List values = (List)helper.getValue(o, f); + int size = values.size(); + for (int i = 0; i < size; i++) + { + FeatureMap.Entry entry = (FeatureMap.Entry)values.get(i); + EStructuralFeature entryFeature = entry.getEStructuralFeature(); + Object value = entry.getValue(); + if (entryFeature instanceof EReference) + { + if (value == null) + { + saveNil(o, entryFeature); + } + else + { + EReference referenceEntryFeature = (EReference)entryFeature; + if (referenceEntryFeature.isContainment()) + { + saveElement((InternalEObject)value, entryFeature); + } + else if (referenceEntryFeature.isResolveProxies()) + { + saveFeatureMapElementReference((EObject)value, referenceEntryFeature); + } + else + { + saveElementIDRef(o, (EObject)value, entryFeature); + } + } + } + else + { + if (entryFeature == XMLTypePackage.eINSTANCE.getXMLTypeDocumentRoot_Text()) + { + String svalue = value.toString(); + if (escape != null) + { + svalue = escape.convertText(svalue); + } + if (!toDOM) + { + doc.addText(svalue); + } + else + { + Node text = document.createTextNode(svalue); + currentNode.appendChild(text); + handler.recordValues(text, o, f, entry); + } + } + else if (entryFeature == XMLTypePackage.eINSTANCE.getXMLTypeDocumentRoot_CDATA()) + { + String stringValue = value.toString(); + if (escape != null) + { + stringValue = escape.convertLines(stringValue); + } + if (!toDOM) + { + doc.addCDATA(stringValue); + } + else + { + Node cdata = document.createCDATASection(stringValue); + currentNode.appendChild(cdata); + handler.recordValues(cdata, o, f, entry); + } + } + else if (entryFeature == XMLTypePackage.eINSTANCE.getXMLTypeDocumentRoot_Comment()) + { + String stringValue = value.toString(); + if (escape != null) + { + stringValue = escape.convertLines(stringValue); + } + if (!toDOM) + { + doc.addComment(stringValue); + } + else + { + // TODO comments are not sent to recordValues + currentNode.appendChild(document.createComment(stringValue)); + } + } + else + { + saveElement(o, value, entryFeature); + } + } + } + return size > 0; + } + + protected final void saveElement(EObject o, Object value, EStructuralFeature f) + { + if (f.getEType() == ChangeSummaryStreamSerializer.ChangeSummary_TYPE) + { + saveChangeSummary(o, f, value); + return; + } + /* super.saveElement(o, value, f); + * TEMPORARILY COPIED FROM BASE CLASS - DO NOT EDIT - WILL BE REMOVED WHEN WE MOVE TO EMF 2.3 + */ + if (value == null) + { + saveNil(o, f); + } + else + { + String svalue = getDatatypeValue(value, f, false); + if (!toDOM) + { + doc.saveDataValueElement(helper.getQName(f), svalue); + } + else + { + helper.populateNameInfo(nameInfo, f); + Element elem = document.createElementNS(nameInfo.getNamespaceURI(), nameInfo.getQualifiedName()); + Node text = document.createTextNode(svalue); + elem.appendChild(text); + currentNode.appendChild(elem); + handler.recordValues(elem, o, f, value); + handler.recordValues(text, o, f, value); + } + } + } + } + + protected XMLSave createXMLSave() { + return new SDOXMLSaveImpl(createXMLHelper()); + } +} diff --git a/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/XMLDocumentStreamReader.java b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/XMLDocumentStreamReader.java new file mode 100644 index 0000000000..64088a0366 --- /dev/null +++ b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/XMLDocumentStreamReader.java @@ -0,0 +1,438 @@ +/** + * + * 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.util.resource; + +import java.util.NoSuchElementException; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +/** + * This class is derived from Apache Axis2 class <a + * href="http://svn.apache.org/repos/asf/webservices/axis2/trunk/java/modules/core/src/org/apache/axis2/util/StreamWrapper.java"> + * org.apache.axis2.util.StreamWrapper</a>. It's used wrap a XMLStreamReader to create a XMLStreamReader representing a document and it will produce + * START_DOCUMENT, END_DOCUMENT events. + * + */ +public class XMLDocumentStreamReader implements XMLStreamReader { + private static final int STATE_INIT = 0; // The wrapper will produce START_DOCUMENT + + private static final int STATE_SWITCHED = 1; // The real reader will produce events + + private static final int STATE_COMPLETE_AT_NEXT = 2; // The wrapper will produce END_DOCUMENT + + private static final int STATE_COMPLETED = 3; // Done + + private XMLStreamReader realReader = null; + + private int state = STATE_INIT; + + public XMLDocumentStreamReader(XMLStreamReader realReader) { + if (realReader == null) { + throw new UnsupportedOperationException("Reader cannot be null"); + } + + this.realReader = realReader; + + // If the real reader is positioned at START_DOCUMENT, always use the real reader + if (realReader.getEventType() == START_DOCUMENT) + state = STATE_SWITCHED; + } + + public void close() throws XMLStreamException { + realReader.close(); + } + + public int next() throws XMLStreamException { + int returnEvent = -1; + + switch (state) { + case STATE_SWITCHED: + returnEvent = realReader.next(); + if (returnEvent == END_DOCUMENT) { + state = STATE_COMPLETED; + } else if (!realReader.hasNext()) { + state = STATE_COMPLETE_AT_NEXT; + } + break; + case STATE_INIT: + state = STATE_SWITCHED; + returnEvent = realReader.getEventType(); + break; + case STATE_COMPLETE_AT_NEXT: + state = STATE_COMPLETED; + returnEvent = END_DOCUMENT; + break; + case STATE_COMPLETED: + // oops - no way we can go beyond this + throw new NoSuchElementException("End of stream has reached."); + default: + throw new UnsupportedOperationException(); + } + + return returnEvent; + } + + private boolean isDelegating() { + return state == STATE_SWITCHED || state == STATE_COMPLETE_AT_NEXT; + } + + public int nextTag() throws XMLStreamException { + if (isDelegating()) { + return realReader.nextTag(); + } else { + throw new XMLStreamException(); + } + } + + public void require(int i, String s, String s1) throws XMLStreamException { + if (isDelegating()) { + realReader.require(i, s, s1); + } + } + + public boolean standaloneSet() { + if (isDelegating()) { + return realReader.standaloneSet(); + } else { + return false; + } + } + + public int getAttributeCount() { + if (isDelegating()) { + return realReader.getAttributeCount(); + } else { + throw new IllegalStateException(); + } + } + + public String getAttributeLocalName(int i) { + if (isDelegating()) { + return realReader.getAttributeLocalName(i); + } else { + throw new IllegalStateException(); + } + } + + public QName getAttributeName(int i) { + if (isDelegating()) { + return realReader.getAttributeName(i); + } else { + throw new IllegalStateException(); + } + } + + public String getAttributeNamespace(int i) { + if (isDelegating()) { + return realReader.getAttributeNamespace(i); + } else { + throw new IllegalStateException(); + } + } + + public String getAttributePrefix(int i) { + if (isDelegating()) { + return realReader.getAttributePrefix(i); + } else { + throw new IllegalStateException(); + } + } + + public String getAttributeType(int i) { + if (isDelegating()) { + return realReader.getAttributeType(i); + } else { + throw new IllegalStateException(); + } + } + + public String getAttributeValue(int i) { + if (isDelegating()) { + return realReader.getAttributeValue(i); + } else { + throw new IllegalStateException(); + } + } + + public String getAttributeValue(String s, String s1) { + if (isDelegating()) { + return realReader.getAttributeValue(s, s1); + } else { + throw new IllegalStateException(); + } + } + + public String getCharacterEncodingScheme() { + return realReader.getCharacterEncodingScheme(); + } + + public String getElementText() throws XMLStreamException { + if (isDelegating()) { + return realReader.getElementText(); + } else { + throw new XMLStreamException(); + } + } + + public String getEncoding() { + return realReader.getEncoding(); + } + + public int getEventType() { + int event = -1; + switch (state) { + case STATE_SWITCHED: + case STATE_COMPLETE_AT_NEXT: + event = realReader.getEventType(); + break; + case STATE_INIT: + event = START_DOCUMENT; + break; + case STATE_COMPLETED: + event = END_DOCUMENT; + break; + } + return event; + } + + public Location getLocation() { + if (isDelegating()) { + return realReader.getLocation(); + } else { + return null; + } + } + + public QName getName() { + if (isDelegating()) { + return realReader.getName(); + } else { + throw new IllegalStateException(); + } + } + + public String getLocalName() { + if (isDelegating()) { + return realReader.getLocalName(); + } else { + throw new IllegalStateException(); + } + } + + public NamespaceContext getNamespaceContext() { + return realReader.getNamespaceContext(); + } + + public int getNamespaceCount() { + if (isDelegating()) { + return realReader.getNamespaceCount(); + } else { + throw new IllegalStateException(); + } + } + + public String getNamespacePrefix(int i) { + if (isDelegating()) { + return realReader.getNamespacePrefix(i); + } else { + throw new IllegalStateException(); + } + } + + public String getNamespaceURI() { + if (isDelegating()) { + return realReader.getNamespaceURI(); + } else { + throw new IllegalStateException(); + } + } + + public String getNamespaceURI(int i) { + if (isDelegating()) { + return realReader.getNamespaceURI(i); + } else { + throw new IllegalStateException(); + } + } + + public String getNamespaceURI(String s) { + if (isDelegating()) { + return realReader.getNamespaceURI(s); + } else { + throw new IllegalStateException(); + } + } + + public String getPIData() { + if (isDelegating()) { + return realReader.getPIData(); + } else { + throw new IllegalStateException(); + } + } + + public String getPITarget() { + if (isDelegating()) { + return realReader.getPITarget(); + } else { + throw new IllegalStateException(); + } + } + + public String getPrefix() { + if (isDelegating()) { + return realReader.getPrefix(); + } else { + throw new IllegalStateException(); + } + } + + public Object getProperty(String s) throws IllegalArgumentException { + return realReader.getProperty(s); + } + + public String getText() { + if (isDelegating()) { + return realReader.getText(); + } else { + throw new IllegalStateException(); + } + } + + public char[] getTextCharacters() { + if (isDelegating()) { + return realReader.getTextCharacters(); + } else { + throw new IllegalStateException(); + } + } + + public int getTextCharacters(int i, char[] chars, int i1, int i2) throws XMLStreamException { + if (isDelegating()) { + return realReader.getTextCharacters(i, chars, i1, i2); + } else { + throw new IllegalStateException(); + } + } + + public int getTextLength() { + if (isDelegating()) { + return realReader.getTextLength(); + } else { + throw new IllegalStateException(); + } + } + + public int getTextStart() { + if (isDelegating()) { + return realReader.getTextStart(); + } else { + throw new IllegalStateException(); + } + } + + public String getVersion() { + if (isDelegating()) { + return realReader.getVersion(); + } else { + return null; + } + } + + public boolean hasName() { + if (isDelegating()) { + return realReader.hasName(); + } else { + return false; + } + } + + public boolean hasNext() throws XMLStreamException { + if (state == STATE_COMPLETE_AT_NEXT) { + return true; + } else if (state == STATE_COMPLETED) { + return false; + } else if (state == STATE_SWITCHED) { + return realReader.hasNext(); + } else { + return true; + } + } + + public boolean hasText() { + if (isDelegating()) { + return realReader.hasText(); + } else { + return false; + } + } + + public boolean isAttributeSpecified(int i) { + if (isDelegating()) { + return realReader.isAttributeSpecified(i); + } else { + return false; + } + } + + public boolean isCharacters() { + if (isDelegating()) { + return realReader.isCharacters(); + } else { + return false; + } + } + + public boolean isEndElement() { + if (isDelegating()) { + return realReader.isEndElement(); + } else { + return false; + } + } + + public boolean isStandalone() { + if (isDelegating()) { + return realReader.isStandalone(); + } else { + return false; + } + } + + public boolean isStartElement() { + if (isDelegating()) { + return realReader.isStartElement(); + } else { + return false; + } + } + + public boolean isWhiteSpace() { + if (isDelegating()) { + return realReader.isWhiteSpace(); + } else { + return false; + } + } +}
\ No newline at end of file diff --git a/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/XMLFragmentStreamReader.java b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/XMLFragmentStreamReader.java new file mode 100644 index 0000000000..66d8fbdc6a --- /dev/null +++ b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/XMLFragmentStreamReader.java @@ -0,0 +1,44 @@ +/** + * + * 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.util.resource; + +import javax.xml.stream.XMLStreamReader; + +interface XMLFragmentStreamReader extends XMLStreamReader { + + // this will help to handle Text within the current element. + // user should pass the element text to the property list as this + // ELEMENT_TEXT as the key. This key deliberately has a space in it + // so that it is not a valid XML name + static final String ELEMENT_TEXT = "Element Text"; + + /** + * Extra method to query the state of the pullparser + * @return + */ + boolean isEndOfFragment(); + + /** + * Initiate the parser - this will do whatever the needed + * tasks to initiate the parser and must be called before + * attempting any specific parsing using this parser + */ + void init(); +} diff --git a/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/XMLStreamSerializer.java b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/XMLStreamSerializer.java new file mode 100644 index 0000000000..a0242905f6 --- /dev/null +++ b/sdo-java/tags/1.0-incubating-beta1/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/XMLStreamSerializer.java @@ -0,0 +1,272 @@ +/* + * Copyright 2004,2005 The Apache Software Foundation. + * + * Licensed 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.util.resource; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; + +/** + * The XMLStreamSerializer pulls events from the XMLStreamReader and dumps into the XMLStreamWriter + */ +public class XMLStreamSerializer implements XMLStreamConstants { + + private static int namespaceSuffix = 0; + + public static final String NAMESPACE_PREFIX = "ns"; + + /* + * The behavior of the serializer is such that it returns when it encounters the starting element for the second time. The depth variable tracks + * the depth of the serilizer and tells it when to return. Note that it is assumed that this serialization starts on an Element. + */ + + /** + * Field depth + */ + private int depth = 0; + + /** + * Method serialize. + * + * @param node + * @param writer + * @throws XMLStreamException + */ + public void serialize(XMLStreamReader node, XMLStreamWriter writer) throws XMLStreamException { + serializeNode(node, writer); + } + + /** + * Method serializeNode. + * + * @param reader + * @param writer + * @throws XMLStreamException + */ + protected void serializeNode(XMLStreamReader reader, XMLStreamWriter writer) throws XMLStreamException { + // TODO We get the StAXWriter at this point and uses it hereafter assuming that this is the only entry point to this class. + // If there can be other classes calling methodes of this we might need to change methode signatures to OMOutputer + while (reader.hasNext()) { + int event = reader.next(); + if (event == START_ELEMENT) { + serializeElement(reader, writer); + depth++; + } else if (event == ATTRIBUTE) { + serializeAttributes(reader, writer); + } else if (event == CHARACTERS) { + serializeText(reader, writer); + } else if (event == COMMENT) { + serializeComment(reader, writer); + } else if (event == CDATA) { + serializeCData(reader, writer); + } else if (event == END_ELEMENT) { + serializeEndElement(writer); + depth--; + } else if (event == START_DOCUMENT) { + depth++; // if a start document is found then increment the depth + } else if (event == END_DOCUMENT) { + if (depth != 0) + depth--; // for the end document - reduce the depth + try { + serializeEndElement(writer); + } catch (Exception e) { + // TODO: log exceptions + } + } + if (depth == 0) { + break; + } + } + } + + /** + * @param reader + * @param writer + * @throws XMLStreamException + */ + protected void serializeElement(XMLStreamReader reader, XMLStreamWriter writer) throws XMLStreamException { + String prefix = reader.getPrefix(); + String nameSpaceName = reader.getNamespaceURI(); + if (nameSpaceName != null) { + String writer_prefix = writer.getPrefix(nameSpaceName); + if (writer_prefix != null) { + writer.writeStartElement(nameSpaceName, reader.getLocalName()); + } else { + if (prefix != null) { + writer.writeStartElement(prefix, reader.getLocalName(), nameSpaceName); + writer.writeNamespace(prefix, nameSpaceName); + writer.setPrefix(prefix, nameSpaceName); + } else { + writer.writeStartElement(nameSpaceName, reader.getLocalName()); + writer.writeDefaultNamespace(nameSpaceName); + writer.setDefaultNamespace(nameSpaceName); + } + } + } else { + writer.writeStartElement(reader.getLocalName()); + } + + // add the namespaces + int count = reader.getNamespaceCount(); + String namespacePrefix; + for (int i = 0; i < count; i++) { + namespacePrefix = reader.getNamespacePrefix(i); + if (namespacePrefix != null && namespacePrefix.length() == 0) + continue; + + serializeNamespace(namespacePrefix, reader.getNamespaceURI(i), writer); + } + + // add attributes + serializeAttributes(reader, writer); + + } + + /** + * Method serializeEndElement. + * + * @param writer + * @throws XMLStreamException + */ + protected void serializeEndElement(XMLStreamWriter writer) throws XMLStreamException { + writer.writeEndElement(); + } + + /** + * @param reader + * @param writer + * @throws XMLStreamException + */ + protected void serializeText(XMLStreamReader reader, XMLStreamWriter writer) throws XMLStreamException { + writer.writeCharacters(reader.getText()); + } + + /** + * Method serializeCData. + * + * @param reader + * @param writer + * @throws XMLStreamException + */ + protected void serializeCData(XMLStreamReader reader, XMLStreamWriter writer) throws XMLStreamException { + writer.writeCData(reader.getText()); + } + + /** + * Method serializeComment. + * + * @param reader + * @param writer + * @throws XMLStreamException + */ + protected void serializeComment(XMLStreamReader reader, XMLStreamWriter writer) throws XMLStreamException { + writer.writeComment(reader.getText()); + } + + /** + * @param reader + * @param writer + * @throws XMLStreamException + */ + protected void serializeAttributes(XMLStreamReader reader, XMLStreamWriter writer) + throws XMLStreamException { + int count = reader.getAttributeCount(); + String prefix = null; + String namespaceName = null; + String writerPrefix = null; + for (int i = 0; i < count; i++) { + prefix = reader.getAttributePrefix(i); + namespaceName = reader.getAttributeNamespace(i); + if (namespaceName != null) { + writerPrefix = writer.getNamespaceContext().getPrefix(namespaceName); + } + + if (!"".equals(namespaceName)) { + // prefix has already being declared but this particular attrib + // has a + // no prefix attached. So use the prefix provided by the writer + if (writerPrefix != null && (prefix == null || prefix.equals(""))) { + writer.writeAttribute(writerPrefix, + namespaceName, + reader.getAttributeLocalName(i), + reader.getAttributeValue(i)); + + // writer prefix is available but different from the current + // prefix of the attrib. We should be decalring the new + // prefix + // as a namespace declaration + } else if (prefix != null && !"".equals(prefix) && !prefix.equals(writerPrefix)) { + writer.writeNamespace(prefix, namespaceName); + writer.writeAttribute(prefix, namespaceName, reader.getAttributeLocalName(i), reader + .getAttributeValue(i)); + + // prefix is null (or empty), but the namespace name is + // valid! it has not + // being written previously also. So we need to generate a + // prefix + // here + } else if (prefix == null || prefix.equals("")) { + prefix = generateUniquePrefix(writer.getNamespaceContext()); + writer.writeNamespace(prefix, namespaceName); + writer.writeAttribute(prefix, namespaceName, reader.getAttributeLocalName(i), reader + .getAttributeValue(i)); + } else { + writer.writeAttribute(prefix, namespaceName, reader.getAttributeLocalName(i), reader + .getAttributeValue(i)); + } + } else { + // empty namespace is equal to no namespace! + writer.writeAttribute(reader.getAttributeLocalName(i), reader.getAttributeValue(i)); + } + + } + } + + /** + * Generates a unique namespace prefix that is not in the scope of the NamespaceContext + * + * @param nsCtxt + * @return string + */ + private String generateUniquePrefix(NamespaceContext nsCtxt) { + String prefix = NAMESPACE_PREFIX + namespaceSuffix++; + // null should be returned if the prefix is not bound! + while (nsCtxt.getNamespaceURI(prefix) != null) { + prefix = NAMESPACE_PREFIX + namespaceSuffix++; + } + + return prefix; + } + + /** + * Method serializeNamespace. + * + * @param prefix + * @param URI + * @param writer + * @throws XMLStreamException + */ + private void serializeNamespace(String prefix, String URI, XMLStreamWriter writer) throws XMLStreamException { + String prefix1 = writer.getPrefix(URI); + if (prefix1 == null) { + writer.writeNamespace(prefix, URI); + writer.setPrefix(prefix, URI); + } + } +} |