diff options
author | lresende <lresende@13f79535-47bb-0310-9956-ffa450edef68> | 2009-11-10 19:19:55 +0000 |
---|---|---|
committer | lresende <lresende@13f79535-47bb-0310-9956-ffa450edef68> | 2009-11-10 19:19:55 +0000 |
commit | 2a444004802173fa97afbc389fc4a6600b6d3f88 (patch) | |
tree | b175a25dd02206218987ab4bc730ad8e77b7756a /sdo-java/branches/sdo-1.1-incubating/impl/src/main/java/org/apache/tuscany/sdo/util/resource/ChangeSummaryStreamSerializer.java | |
parent | c993ba575bdd1530b7bbc0c6a19c32e66fce4b89 (diff) |
moving SDO branches
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@834614 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'sdo-java/branches/sdo-1.1-incubating/impl/src/main/java/org/apache/tuscany/sdo/util/resource/ChangeSummaryStreamSerializer.java')
-rw-r--r-- | sdo-java/branches/sdo-1.1-incubating/impl/src/main/java/org/apache/tuscany/sdo/util/resource/ChangeSummaryStreamSerializer.java | 690 |
1 files changed, 690 insertions, 0 deletions
diff --git a/sdo-java/branches/sdo-1.1-incubating/impl/src/main/java/org/apache/tuscany/sdo/util/resource/ChangeSummaryStreamSerializer.java b/sdo-java/branches/sdo-1.1-incubating/impl/src/main/java/org/apache/tuscany/sdo/util/resource/ChangeSummaryStreamSerializer.java new file mode 100644 index 0000000000..ef5af8ab57 --- /dev/null +++ b/sdo-java/branches/sdo-1.1-incubating/impl/src/main/java/org/apache/tuscany/sdo/util/resource/ChangeSummaryStreamSerializer.java @@ -0,0 +1,690 @@ +/** + * + * 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.HelperContextImpl; +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 HelperContextImpl(extendedMetaData, false)).getXSDHelper(); + } + 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(); + } +} |