You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tuscany.apache.org by fr...@apache.org on 2007/02/05 23:53:35 UTC

svn commit: r503913 [1/2] - in /incubator/tuscany/java/sdo/impl/src: main/java/org/apache/tuscany/sdo/helper/ main/java/org/apache/tuscany/sdo/impl/ main/java/org/apache/tuscany/sdo/util/ main/java/org/apache/tuscany/sdo/util/resource/ test/java/org/ap...

Author: frankb
Date: Mon Feb  5 14:53:34 2007
New Revision: 503913

URL: http://svn.apache.org/viewvc?view=rev&rev=503913
Log:
Fix for TUSCANY-1082

Added:
    incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/StreamDeserializer.java
    incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/ChangeSummaryStreamDeserializer.java
    incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/RecordedEventXMLStreamReader.java
    incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/SDODeserializer.java
Modified:
    incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/helper/HelperContextImpl.java
    incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/helper/XMLDocumentImpl.java
    incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/helper/XMLStreamHelper.java
    incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/helper/XMLStreamHelperImpl.java
    incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/impl/ChangeSummaryImpl.java
    incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/StAX2SAXAdapter.java
    incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/SDOXMLResourceImpl.java
    incubator/tuscany/java/sdo/impl/src/test/java/org/apache/tuscany/sdo/test/ChangeSummaryPropertyTestCase.java
    incubator/tuscany/java/sdo/impl/src/test/java/org/apache/tuscany/sdo/test/XMLStreamHelperTestCase.java

Modified: incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/helper/HelperContextImpl.java
URL: http://svn.apache.org/viewvc/incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/helper/HelperContextImpl.java?view=diff&rev=503913&r1=503912&r2=503913
==============================================================================
--- incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/helper/HelperContextImpl.java (original)
+++ incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/helper/HelperContextImpl.java Mon Feb  5 14:53:34 2007
@@ -40,17 +40,17 @@
 	private XMLHelper xmlHelper;
 	private XSDHelper xsdHelper;
 
-	
-	public HelperContextImpl() {
+	public HelperContextImpl(ExtendedMetaData extendedMetaData) {
+        typeHelper = new TypeHelperImpl(extendedMetaData);
 
-          EPackage.Registry registry = new EPackageRegistryImpl(EPackage.Registry.INSTANCE);
-          ExtendedMetaData extendedMetaData = new SDOExtendedMetaDataImpl(registry); //TODO create subclass that makes demand() methods synchronous
-          typeHelper = new TypeHelperImpl(extendedMetaData);
-          
-          dataFactory = new DataFactoryImpl(typeHelper);
-          xmlHelper = new XMLHelperImpl(typeHelper);
-          xsdHelper = new XSDHelperImpl(typeHelper);
-	}
+        dataFactory = new DataFactoryImpl(typeHelper);
+        xmlHelper = new XMLHelperImpl(typeHelper);
+        xsdHelper = new XSDHelperImpl(typeHelper);
+    }
+
+    public HelperContextImpl() {
+        this(new SDOExtendedMetaDataImpl(new EPackageRegistryImpl(EPackage.Registry.INSTANCE))); //TODO create subclass that makes demand() methods synchronous
+    }
 
 	public CopyHelper getCopyHelper() {
 		return CopyHelper.INSTANCE;

Modified: incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/helper/XMLDocumentImpl.java
URL: http://svn.apache.org/viewvc/incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/helper/XMLDocumentImpl.java?view=diff&rev=503913&r1=503912&r2=503913
==============================================================================
--- incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/helper/XMLDocumentImpl.java (original)
+++ incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/helper/XMLDocumentImpl.java Mon Feb  5 14:53:34 2007
@@ -222,9 +222,9 @@
     load(inputSource, locationURI, options);
   }
 
-  protected void load(XMLStreamReader reader) throws IOException
+  protected final void load(XMLStreamReader reader, Map options) throws IOException
   {
-    ((SDOXMLResourceImpl)resource).load(reader, null);
+    ((SDOXMLResourceImpl)resource).load(reader, options);
     initLoadedRoot();
   }
 
@@ -275,6 +275,8 @@
             break;
           }
         } //for
+        if (rootObject == null)
+          rootObject = ((SDOXMLResourceImpl) resource).root;
       }
       else
       {

Modified: incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/helper/XMLStreamHelper.java
URL: http://svn.apache.org/viewvc/incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/helper/XMLStreamHelper.java?view=diff&rev=503913&r1=503912&r2=503913
==============================================================================
--- incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/helper/XMLStreamHelper.java (original)
+++ incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/helper/XMLStreamHelper.java Mon Feb  5 14:53:34 2007
@@ -19,6 +19,7 @@
  */
 package org.apache.tuscany.sdo.helper;
 
+import java.util.Map;
 import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.XMLStreamReader;
 import javax.xml.stream.XMLStreamWriter;
@@ -71,6 +72,25 @@
      * @throws IllegalStateException if the reader is not positioned on a START_ELEMENT event
      */
     DataObject loadObject(XMLStreamReader reader) throws XMLStreamException, IllegalStateException;
+
+    /**
+     * Default Type to load DataObject if the element is unqualified/local without xsi:type
+     * or the qualified/global element or xsi:type fail to resolve.
+     * Can be null.
+     */
+    String OPTION_DEFAULT_ROOT_TYPE = "default root type";
+    
+    /**
+     * Create a DataObject from an element in a XML stream.
+     * The reader must be positioned on a START_ELEMENT event.
+     *
+     * @param reader the stream to read
+     * @param options {@link OPTION_DEFAULT_ROOT_TYPE}; can be null or empty
+     * @return a DataObject created from the element in the stream
+     * @throws XMLStreamException    if there was a problem reading the stream
+     * @throws IllegalStateException if the reader is not positioned on a START_ELEMENT event
+     */
+    DataObject loadObject(XMLStreamReader reader, Map options) throws XMLStreamException, IllegalStateException;
 
     /**
      * Save a DataObject to an XML stream.

Modified: incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/helper/XMLStreamHelperImpl.java
URL: http://svn.apache.org/viewvc/incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/helper/XMLStreamHelperImpl.java?view=diff&rev=503913&r1=503912&r2=503913
==============================================================================
--- incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/helper/XMLStreamHelperImpl.java (original)
+++ incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/helper/XMLStreamHelperImpl.java Mon Feb  5 14:53:34 2007
@@ -19,6 +19,7 @@
  */
 package org.apache.tuscany.sdo.helper;
 
+import java.util.Map;
 import javax.xml.stream.XMLStreamConstants;
 import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.XMLStreamReader;
@@ -51,7 +52,7 @@
     if (reader.getEventType() != XMLStreamConstants.START_DOCUMENT)
       throw new IllegalStateException();
     
-    return loadDocument(reader);
+    return loadDocument(reader, null);
   }
   
   public void save(XMLDocument document, XMLStreamWriter writer) throws XMLStreamException
@@ -68,7 +69,7 @@
       
   }
 
-  public DataObject loadObject(XMLStreamReader reader) throws XMLStreamException, IllegalStateException
+  public final DataObject loadObject(XMLStreamReader reader, Map options) throws XMLStreamException, IllegalStateException
   {
     if (reader.getEventType() != XMLStreamConstants.START_ELEMENT)
       throw new IllegalStateException();
@@ -77,7 +78,12 @@
     // Wrap the reader so it represents a document
     reader = new XMLDocumentStreamReader(reader);
     
-    return loadDocument(reader).getRootObject();
+    return loadDocument(reader, options).getRootObject();
+  }
+
+  public DataObject loadObject(XMLStreamReader reader) throws XMLStreamException, IllegalStateException
+  {
+    return loadObject(reader, null);
   }
 
   public void saveObject(DataObject sdo, XMLStreamWriter writer) throws XMLStreamException
@@ -106,11 +112,11 @@
     return new DataObjectXMLStreamReader(dataObject, rootElementURI, rootElementName, typeHelper);
   }
   
-  protected XMLDocument loadDocument(XMLStreamReader reader) throws XMLStreamException
+  protected XMLDocument loadDocument(XMLStreamReader reader, Map options) throws XMLStreamException
   {
     try {
       XMLDocumentImpl document = new XMLDocumentImpl(typeHelper.extendedMetaData, null);
-      document.load(reader);
+      document.load(reader, options);
       return document;
     }
     catch (Exception e) {

Modified: incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/impl/ChangeSummaryImpl.java
URL: http://svn.apache.org/viewvc/incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/impl/ChangeSummaryImpl.java?view=diff&rev=503913&r1=503912&r2=503913
==============================================================================
--- incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/impl/ChangeSummaryImpl.java (original)
+++ incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/impl/ChangeSummaryImpl.java Mon Feb  5 14:53:34 2007
@@ -751,9 +751,11 @@
   {
     //TODO: Fix this method. Currently, it has the side effect of undoing the unset of contained children references
     //      of root deleted objects - i.e., when featureChange.apply(oldDataObject) is called.
+    //
+    List changes = (List) getObjectChanges().get(dataObject);
+    if (changes == null) 
+      return dataObject;
     EObject oldDataObject = EcoreUtil.copy((EObject)dataObject);
-
-    List changes = (List)getObjectChanges().get(dataObject);
     for (Iterator fIter = changes.iterator(); fIter.hasNext(); )
     {
       FeatureChange featureChange = (FeatureChange)fIter.next();

Modified: incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/StAX2SAXAdapter.java
URL: http://svn.apache.org/viewvc/incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/StAX2SAXAdapter.java?view=diff&rev=503913&r1=503912&r2=503913
==============================================================================
--- incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/StAX2SAXAdapter.java (original)
+++ incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/StAX2SAXAdapter.java Mon Feb  5 14:53:34 2007
@@ -119,7 +119,7 @@
             case XMLStreamConstants.END_ELEMENT:
                 handleEndElement(reader, handler);
                 level--;
-                if (level == 0) {
+                if (level == 1) {
                     return;
                 }
                 break;

Added: incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/StreamDeserializer.java
URL: http://svn.apache.org/viewvc/incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/StreamDeserializer.java?view=auto&rev=503913
==============================================================================
--- incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/StreamDeserializer.java (added)
+++ incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/StreamDeserializer.java Mon Feb  5 14:53:34 2007
@@ -0,0 +1,74 @@
+/**
+ *
+ *  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.XMLConstants;
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.stream.*;
+
+import org.apache.tuscany.sdo.util.resource.RecordedEventXMLStreamReader;
+import org.eclipse.emf.ecore.*;
+import org.eclipse.emf.ecore.util.*;
+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;
+    }
+}
\ No newline at end of file

Added: incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/ChangeSummaryStreamDeserializer.java
URL: http://svn.apache.org/viewvc/incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/ChangeSummaryStreamDeserializer.java?view=auto&rev=503913
==============================================================================
--- incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/ChangeSummaryStreamDeserializer.java (added)
+++ incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/ChangeSummaryStreamDeserializer.java Mon Feb  5 14:53:34 2007
@@ -0,0 +1,579 @@
+/**
+ *
+ *  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.*;
+
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.stream.*;
+
+import commonj.sdo.*;
+import commonj.sdo.helper.HelperContext;
+
+import org.eclipse.emf.ecore.*;
+import org.eclipse.emf.ecore.change.*;
+import org.apache.tuscany.sdo.SDOFactory;
+import org.apache.tuscany.sdo.helper.SDOAnnotations;
+import org.apache.tuscany.sdo.impl.*;
+
+/**
+ * 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 {
+        String ref, unset;
+
+        Collection attributes/* = null */, qualifiedAttributes/* = null */, tags/* = null */; // may be null, never empty
+
+        NamespaceContext nameSpaces;
+    }
+
+    protected Collection forwardReferences/* = null */;
+
+    static private final class ElementChange {
+        private Object property;
+
+        private String ref;
+    }
+
+    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, Object property, Object value, boolean set) {
+        EStructuralFeature feature = (EStructuralFeature) property;
+        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, 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 void logPropertyChange(Collection featureChanges, Object property, Object value) {
+        logPropertyChange(featureChanges, property, value, true);
+    }
+
+    void logAttributeChange(Collection featureChanges, Property property, String literal, NamespaceContext nameSpaces) {
+        if (property != null)
+            logPropertyChange(featureChanges, property, value(property.getType(), literal, nameSpaces));
+        // else report error?
+    }
+
+    protected final void logAttributeChange(Collection featureChanges, String property, Type type, String value, NamespaceContext nameSpaces) {
+        logAttributeChange(featureChanges, type.getProperty(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), 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 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);
+                if (referent == null) {
+                    /*
+                     * Forward-referenced(unresolved) modified DataObject
+                     */
+                    ForwardReference forwardReference = new ForwardReference();
+                    if (forwardReferences == null)
+                        forwardReferences = new ArrayList();
+                    forwardReferences.add(forwardReference);
+                    forwardReference.ref = ref;
+                    forwardReference.unset = unset;
+                    forwardReference.nameSpaces = nameSpaces;
+                    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) {
+                            nameSpace = tag.nameSpace;
+                            if (nameSpace != null)
+                                tag.value = value(globalElementType(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
+                             */
+                            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(property, reader);
+                                else {
+                                    xsi = globalElementType(name);
+                                    value = value(xsi == null ? property.getType() : xsi);
+                                }
+                            } else {
+                                /*
+                                 * Referenced child DataObject
+                                 */
+                                reader.nextTag()/* END_ELEMENT */;
+                                value = referent(ref);
+                                if (value == null) {
+                                    /*
+                                     * Forward-referenced(unresolved) child DataObject
+                                     */
+                                    if (!many) {
+                                        ElementChange elementChange = new ElementChange();
+                                        elementChange.property = property;
+                                        elementChange.ref = ref;
+                                        if (objectChanges == null) {
+                                            objectChanges = newObjectChanges(featureChanges);
+                                            objectChanges.newElementChanges();
+                                        } else if (objectChanges.elementChanges == null)
+                                            objectChanges.newElementChanges();
+                                        objectChanges.elementChanges.add(elementChange);
+                                        continue;
+                                    }
+                                    value = ref;
+                                }
+                            }
+                            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);
+                                list.add(value);
+                            } else
+                                logPropertyChange(featureChanges, property, value);
+                        } while (START_ELEMENT == reader.nextTag());
+                    }
+                }
+            } while (START_ELEMENT == reader.nextTag());
+        }
+    }
+
+    private Collection changeList(ChangeKind changeKind, int index, Collection listChanges) {
+        ListChange listChange = changeFactory.createListChange();
+        listChange.setKind(changeKind);
+        listChange.setIndex(index);
+        listChanges.add(listChange);
+        return listChange.getValues();
+    }
+
+    Collection add(Collection adds, int change, Collection listChanges, Object value) {
+        if (adds == null)
+            adds = changeList(ChangeKind.ADD_LITERAL, change, listChanges);
+        adds.add(value);
+        return adds;
+    }
+
+    private int remove(int change, Collection listChanges, List list, int begin, int end) {
+        Collection removes = changeList(ChangeKind.REMOVE_LITERAL, change, listChanges);
+        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, Object 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();
+            Property property = (Property) entry.getKey();
+            Iterator values = ((Collection) entry.getValue()).iterator(); // old list
+            List list = ((DataObject) referent).getList(property); // new
+            int change = 0;
+            FeatureChange featureChange = changeSettingFactory == null ? changeFactory.createFeatureChange() : (FeatureChange) changeSettingFactory
+                    .createChangeSummarySetting();
+            featureChange.setFeature((EStructuralFeature) property);
+            Collection listChanges = featureChange.getListChanges(), adds = null;
+            featureChanges.add(featureChange);
+            Type type = property.getType();
+            if (type.isDataType()) {
+                /*
+                 * Log simple value changes
+                 */
+                while (values.hasNext()) {
+                    Object 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);
+            } else {
+                /*
+                 * Log child DataObject changes
+                 */
+                int begin = 0, end = list.size();
+                while (values.hasNext()) {
+                    Object value = values.next();
+                    if (value.getClass() == String.class) // final
+                    {
+                        value = referent((String) 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);
+            }
+        }
+    }
+
+    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.ref);
+                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);
+                        // if (tag.value == null) report error?
+                        else if (tag.events != null)
+                            tag.value = value(property, play(tag));
+                        if (property.isMany()) {
+                            Collection list;
+                            if (propertyMapChanges == null) {
+                                propertyMapChanges = new PropertyMapChanges();
+                                list = propertyMapChanges.newList(property);
+                            } else
+                                list = propertyMapChanges.get(property);
+                            list.add(tag.value);
+                        } 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.ref);
+                        if (value == null)
+                            continue; // report error?
+                        // iterator.remove();
+                        logPropertyChange(objectChanges.featureChanges, elementChange.property, value);
+                    }
+                if (objectChanges.lists != null)
+                    logManyChanges(objectChanges, ((Map.Entry) ((EStructuralFeature.Setting) objectChanges.featureChanges).getEObject()).getKey(),
+                            objectChanges.featureChanges);
+            }
+        if (logging)
+            changeSummary.resumeLogging();
+        return changeSummary;
+    }
+}
\ No newline at end of file

Added: incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/RecordedEventXMLStreamReader.java
URL: http://svn.apache.org/viewvc/incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/RecordedEventXMLStreamReader.java?view=auto&rev=503913
==============================================================================
--- incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/RecordedEventXMLStreamReader.java (added)
+++ incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/RecordedEventXMLStreamReader.java Mon Feb  5 14:53:34 2007
@@ -0,0 +1,854 @@
+/**
+ *
+ *  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.*;
+
+import javax.xml.XMLConstants;
+import javax.xml.namespace.*;
+import javax.xml.stream.*;
+
+import org.eclipse.emf.ecore.xmi.XMLResource;
+import org.xml.sax.*;
+
+/**
+ * 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;
+
+        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;
+        }
+
+        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();
+            event.nameSpaceContext = index == 0 ? nameSpaceContext : ((Event) events.get(--index)).nameSpaceContext;
+            events.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;
+            events.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");
+    }
+}
\ No newline at end of file

Added: incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/SDODeserializer.java
URL: http://svn.apache.org/viewvc/incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/SDODeserializer.java?view=auto&rev=503913
==============================================================================
--- incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/SDODeserializer.java (added)
+++ incubator/tuscany/java/sdo/impl/src/main/java/org/apache/tuscany/sdo/util/resource/SDODeserializer.java Mon Feb  5 14:53:34 2007
@@ -0,0 +1,193 @@
+/**
+ *
+ *  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.*;
+
+import javax.xml.stream.*;
+
+import commonj.sdo.*;
+import commonj.sdo.helper.*;
+
+import org.apache.tuscany.sdo.helper.*;
+import org.apache.tuscany.sdo.util.StreamDeserializer;
+import org.eclipse.emf.ecore.*;
+import org.eclipse.emf.ecore.util.*;
+import org.eclipse.emf.ecore.xmi.XMLResource;
+
+/**
+ * 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();
+        deserializer = null;
+        root = (EObject) rootObject;
+    }
+
+    XSDHelper xsdHelper;
+
+    protected final Property getProperty(Type type, String nameSpace, String name) {
+        for (Iterator iterator = type.getProperties().iterator(); iterator.hasNext();) {
+            Property property = (Property) iterator.next();
+            if (nameSpace.equals(xsdHelper.getNamespaceURI(property)) && name.equals(xsdHelper.getLocalName(property)))
+                return property;
+        }
+        return null; // TODO substitutionGroup & any
+    }
+
+    protected final Property getProperty(String nameSpace, String name, Type type) {
+        return nameSpace == null ? type.getProperty(name) : getProperty(type, nameSpace, name);
+        // if (property == null) report error?
+    }
+
+    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(Property property, XMLStreamReader reader) throws XMLStreamException {
+        Type propertyType = property.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);
+    }
+
+    EObject root;
+
+    static EObject step(String ref, int step, int index, EObject container, ExtendedMetaData extendedMetaData) {
+        String name = ref.substring(step, index);
+        for (Iterator iterator = container.eContents().iterator(); iterator.hasNext();) {
+            container = (EObject) iterator.next();
+            // if( container == null )continue;
+            if (name.equals(extendedMetaData.getName(container.eContainmentFeature())))
+                return container;
+        }
+        return null;
+    }
+
+    protected EObject referent(String ref) {
+        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;
+        }
+        ExtendedMetaData extendedMetaData = ((TypeHelperImpl) typeHelper).getExtendedMetaData();
+        for (int index = step; ++index != length;) {
+            switch (ref.charAt(index)) {
+            case '/':
+                container = step(ref, step, index, container, extendedMetaData);
+                if (container == null)
+                    return null;
+                break;
+            default:
+                continue;
+            case '[':
+                name = ref.substring(step, index);
+                step = ref.indexOf(']', index + 2);
+                if (step == -1)
+                    return null;
+                index = Integer.parseInt(ref.substring(++index, step));
+                EStructuralFeature feature;
+                for (Iterator iterator = container.eContents().iterator();/* true */;) {
+                    if (!iterator.hasNext())
+                        return null;
+                    EObject content = (EObject) iterator.next();
+                    // if( content == null )continue;
+                    feature = content.eContainmentFeature();
+                    if (name.equals(extendedMetaData.getName(feature)))
+                        break;
+                }
+                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;
+        }
+        return step(ref, step, length, container, extendedMetaData);
+    }
+
+    protected final Type typeXSI() {
+        return typedXSI() ? typeHelper.getType(nameSpace, name) : null;
+    }
+
+    protected final Type globalElementType(String name) {
+        return xsdHelper.getGlobalProperty(nameSpace, name, true).getType();
+    }
+}
\ No newline at end of file



---------------------------------------------------------------------
To unsubscribe, e-mail: tuscany-commits-unsubscribe@ws.apache.org
For additional commands, e-mail: tuscany-commits-help@ws.apache.org