/** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.tuscany.sdo.util.resource; import java.io.IOException; import java.io.Writer; import java.net.URL; import java.security.AccessController; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.xml.XMLConstants; import javax.xml.namespace.NamespaceContext; import javax.xml.namespace.QName; import javax.xml.stream.XMLOutputFactory; import javax.xml.stream.XMLStreamConstants; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; import javax.xml.stream.XMLStreamWriter; import org.apache.tuscany.sdo.SDOExtendedMetaData; import org.apache.tuscany.sdo.helper.HelperContextImpl; import org.apache.tuscany.sdo.helper.SDOExtendedMetaDataImpl; import org.apache.tuscany.sdo.helper.XMLStreamHelper; import org.apache.tuscany.sdo.helper.XSDHelperImpl; import org.apache.tuscany.sdo.util.SDOUtil; import org.apache.tuscany.sdo.util.StAX2SAXAdapter; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EClassifier; import org.eclipse.emf.ecore.EFactory; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EPackage; import org.eclipse.emf.ecore.EReference; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.InternalEObject; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.util.ExtendedMetaData; import org.eclipse.emf.ecore.util.FeatureMap; import org.eclipse.emf.ecore.xmi.XMIException; import org.eclipse.emf.ecore.xmi.XMLHelper; import org.eclipse.emf.ecore.xmi.XMLLoad; import org.eclipse.emf.ecore.xmi.XMLOptions; import org.eclipse.emf.ecore.xmi.XMLResource; import org.eclipse.emf.ecore.xmi.XMLSave; import org.eclipse.emf.ecore.xmi.impl.SAXXMLHandler; import org.eclipse.emf.ecore.xmi.impl.XMLHelperImpl; import org.eclipse.emf.ecore.xmi.impl.XMLLoadImpl; import org.eclipse.emf.ecore.xmi.impl.XMLOptionsImpl; import org.eclipse.emf.ecore.xmi.impl.XMLResourceImpl; import org.eclipse.emf.ecore.xmi.impl.XMLSaveImpl; import org.eclipse.emf.ecore.xmi.impl.XMLString; import org.eclipse.emf.ecore.xmi.util.DefaultEcoreBuilder; import org.eclipse.emf.ecore.xml.type.XMLTypePackage; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.xml.sax.Attributes; import org.xml.sax.ContentHandler; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; import commonj.sdo.ChangeSummary; import commonj.sdo.DataObject; import commonj.sdo.helper.XSDHelper; public class SDOXMLResourceImpl extends XMLResourceImpl { private XMLStreamReader reader; /** * [rfeng] Override the XMLHelperImpl to replace the NamespaceSupport so that it's aware of the NamespaceContext from the XMLStreamReader */ public static class SDOXMLHelperImpl extends XMLHelperImpl { /** * EMF XMLResource (SAX) may be used to load from only a *portion* of a StAX stream * which may reference (global) namespaces bound outside the (local) portion. * This class extends EMF's NamespaceSupport to make {@link #getPrefix} and {@link #getURI} * query these global binding(s) after first checking the local context(s). */ private static class StreamNamespaceSupport extends XMLHelperImpl.NamespaceSupport { protected NamespaceContext nameSpaceContext; public String getPrefix(String uri) { String prefix = super.getPrefix(uri); if (prefix == null) try { prefix = nameSpaceContext.getPrefix(uri); } catch (Exception e) { // HACK: // java.lang.UnsupportedOperationException // at org.apache.axiom.om.impl.llom.OMStAXWrapper.getNamespaceContext(OMStAXWrapper.java:984) } return prefix; } public String getURI(String prefix) { String uri = super.getURI(prefix); if (uri == null) try { uri = nameSpaceContext.getNamespaceURI(prefix); } catch (Exception e) { // HACK: // java.lang.UnsupportedOperationException // at org.apache.axiom.om.impl.llom.OMStAXWrapper.getNamespaceContext(OMStAXWrapper.java:984) } return uri; } public StreamNamespaceSupport(XMLStreamReader reader) { super(); nameSpaceContext = reader.getNamespaceContext(); } } public SDOXMLHelperImpl(XMLResource resource, XMLStreamReader reader) { this(reader); setResource(resource); } public SDOXMLHelperImpl(XMLStreamReader reader) { super(); if (reader instanceof XMLDocumentStreamReader) // Only use StreamNamespaceSupport when loading from a *portion* of a StAX stream namespaceSupport = new StreamNamespaceSupport(reader); } private class NameSpaceContext implements NamespaceContext { // TODO Helper# pushContext() & popContext public String getNamespaceURI(String prefix) { return SDOXMLHelperImpl.this.getNamespaceURI(prefix); } public String getPrefix(String namespaceURI) { return SDOXMLHelperImpl.this.getPrefix(namespaceURI); } public Iterator getPrefixes(String namespaceURI) { return ((Collection) urisToPrefixes.get(namespaceURI)).iterator(); } } NameSpaceContext nameSpaceContext/* = null */; protected final NameSpaceContext nameSpaceContext() { if (nameSpaceContext == null) nameSpaceContext = new NameSpaceContext(); return nameSpaceContext; } } public EObject root; /** * An EMF XMLLoad that loads a model from a StAX stream */ public class SDOXMLLoadImpl extends XMLLoadImpl { public SDOXMLLoadImpl(XMLHelper helper) { super(helper); } final class XmlHandler extends SAXXMLHandler { XmlHandler() { super(resource, SDOXMLLoadImpl.this.helper, options); } protected void handleTopLocations(String prefix, String name) { processSchemaLocations(prefix, name); if (!processAnyXML) return; String nameSpace = helper.getURI(prefix); if (extendedMetaData.getPackage(nameSpace) == null) if (options.get(XMLStreamHelper.OPTION_DEFAULT_ROOT_TYPE) == null) extendedMetaData.demandFeature(nameSpace, name, true); else extendedMetaData.demandPackage(nameSpace); } EClassifier defaultRootType(String prefix, String name, boolean isElement, EObject peekObject, String value) { Object type = options.get(XMLStreamHelper.OPTION_DEFAULT_ROOT_TYPE); if (type != null) return (EClassifier) type; super.handleUnknownFeature(prefix, name, isElement, peekObject, value); return null; } protected void handleUnknownFeature(String prefix, String name, boolean isElement, EObject peekObject, String value) { if (objects.size() == 1) { EFactory eFactory; EClassifier type; String typeQName = getXSIType(); if (typeQName == null) { type = defaultRootType(prefix, name, isElement, peekObject, value); if (type == null) return; eFactory = type.getEPackage().getEFactoryInstance(); } else {// createObjectFromTypeName String typeName = null; String xsiPrefix = XMLConstants.DEFAULT_NS_PREFIX; int index = typeQName.indexOf(":"); if (index > 0) { xsiPrefix = typeQName.substring(0, index); typeName = typeQName.substring(index + 1); } else typeName = typeQName; eFactory = getFactoryForPrefix(xsiPrefix); if (eFactory != null) type = helper.getType(eFactory, typeName); else if (XMLConstants.DEFAULT_NS_PREFIX.equals(xsiPrefix) && helper.getURI(xsiPrefix) == null) { EPackage ePackage = handleMissingPackage(null); if (ePackage == null) { type = defaultRootType(prefix, name, isElement, peekObject, value); if (type == null) return; eFactory = type.getEPackage().getEFactoryInstance(); } else type = helper.getType(eFactory = ePackage.getEFactoryInstance(), typeName); } else { type = defaultRootType(prefix, name, isElement, peekObject, value); if (type == null) return; eFactory = type.getEPackage().getEFactoryInstance(); } } root = helper.createObject(eFactory, type); if (root != null) { if (disableNotify) root.eSetDeliver(false); handleObjectAttribs(root); processObject(root); return; } } super.handleUnknownFeature(prefix, name, isElement, peekObject, value); } protected RecordedEventXMLStreamReader.Tag tag/* =null */; protected List nameSpaces/* = null */; public void startPrefixMapping(String prefix, String uri) { if (nameSpaces == null) nameSpaces = new ArrayList(); RecordedEventXMLStreamReader.Tag.bind(prefix, uri, nameSpaces); if (tag == null) super.startPrefixMapping(prefix, uri); } public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { if (tag != null) { tag.start(uri, localName, qName, attributes, locator, nameSpaces); nameSpaces = null; return; } EObject peekObject = objects.peekEObject(); if (peekObject != null) { String prefix = helper.getPrefix(uri.length() == 0 ? null : uri); EStructuralFeature feature = getFeature(peekObject, prefix == null ? XMLConstants.DEFAULT_NS_PREFIX : prefix, localName, true); if (feature != null && feature.getEType() == ChangeSummaryStreamSerializer.ChangeSummary_TYPE) { tag = new RecordedEventXMLStreamReader.Tag(uri, localName, prefix, attributes, locator, ((SDOXMLHelperImpl) helper).nameSpaceContext(), nameSpaces); nameSpaces = null; return; } } if (nameSpaces != null) nameSpaces.clear(); super.startElement(uri, localName, qName, attributes); } public void characters(char[] ch, int start, int length) { if (tag == null) super.characters(ch, start, length); else tag.text(XMLStreamConstants.CHARACTERS, new String(ch, start, length), locator); } protected Collection changeSummaryDeserializers/* = null */; public void endElement(String uri, String localName, String qName) { if (tag == null) super.endElement(uri, localName, qName); else if (tag.end(uri, localName, qName, locator)) { if (changeSummaryDeserializers == null) changeSummaryDeserializers = new ArrayList(); ChangeSummaryStreamDeserializer changeSummaryDeserializer = new ChangeSummaryStreamDeserializer(); try { changeSummaryDeserializer.begin( (DataObject) objects.peekEObject(), new HelperContextImpl(extendedMetaData, false), tag.play(xmlResource)); changeSummaryDeserializers.add(changeSummaryDeserializer); } catch (XMLStreamException e) { xmlResource.getErrors().add(new XMIException(e)); } tag = null; } } public void endDocument() { super.endDocument(); if (changeSummaryDeserializers != null) for (Iterator iterator = changeSummaryDeserializers.iterator(); iterator.hasNext();) try { ((ChangeSummaryStreamDeserializer) iterator.next()).end(); // iterator.remove(); } catch (XMLStreamException e) { xmlResource.getErrors().add(new XMIException(e)); } } } protected DefaultHandler makeDefaultHandler() { return new XmlHandler(); } /** * Start parsing an XMLReader with the default handler. */ public void load(XMLResource resource, final XMLStreamReader reader, Map options) throws IOException { this.resource = resource; Map mergedOptions = new HashMap(defaultLoadOptions); if (options != null) mergedOptions.putAll(options); this.options = mergedOptions; final ContentHandler handler = makeDefaultHandler(); if (errors != null) { errors.clear(); } final StAX2SAXAdapter adapter = new StAX2SAXAdapter(true); // Parse the XMLReader and generate SAX events try { AccessController.doPrivileged(new PrivilegedExceptionAction() { public Object run() throws XMLStreamException, SAXException { adapter.parse(reader, handler); return null; } }); } catch (PrivilegedActionException e) { throw new Resource.IOWrappedException(e.getException()); } helper = null; if (!resource.getErrors().isEmpty()) { Exception error = (Exception) resource.getErrors().get(0); if (error instanceof XMIException) { XMIException exception = (XMIException) error; if (exception.getWrappedException() != null) { throw new Resource.IOWrappedException(exception.getWrappedException()); } } throw new Resource.IOWrappedException(error); } } } public SDOXMLResourceImpl(URI uri) { super(uri); } protected XMLHelper createXMLHelper() { return new SDOXMLHelperImpl(this, reader); } /** * @see org.eclipse.emf.ecore.xmi.impl.XMLResourceImpl#createXMLLoad() */ protected XMLLoad createXMLLoad() { return new SDOXMLLoadImpl(createXMLHelper()); } static protected int loadLaxForm; static { int defaultLaxForm = 0x4242; String property = System.getProperty("XML.load.form.lax"); if (property == null) loadLaxForm = defaultLaxForm; else try { loadLaxForm = Integer.decode(property).intValue(); } catch (NumberFormatException eNumberFormat) { loadLaxForm = defaultLaxForm; } } public void doLoad(InputSource inputSource, Map options) throws IOException { if (options != null) { /* * Tolerates element/attribute malform unless indicated not to */ Object option = options.get(SDOUtil.XML_LOAD_LaxForm); int tolerance = option == null ? loadLaxForm : ((Number) option).intValue(); option = options.get(OPTION_EXTENDED_META_DATA); if (tolerance == 0) { if (option instanceof SDOExtendedMetaData) ((SDOExtendedMetaData) option).setFeatureNamespaceMatchingLax(false); } else if (option instanceof SDOExtendedMetaData) ((SDOExtendedMetaData) option).setFeatureNamespaceMatchingLax(true); else options.put(OPTION_EXTENDED_META_DATA, option = new SDOExtendedMetaDataImpl()); // TODO copy (BasicExtendedMetaData)option /* * Loads schema if necessary */ if (Boolean.TRUE.equals(options.get(SDOUtil.XML_LOAD_SCHEMA))) { XMLOptions xmlOptions = (XMLOptions) options.get(OPTION_XML_OPTIONS); if (xmlOptions == null) { xmlOptions = new XMLOptionsImpl(); options.put(OPTION_XML_OPTIONS, xmlOptions); } xmlOptions.setProcessSchemaLocations(true); if (option == null) option = getDefaultLoadOptions().get(OPTION_EXTENDED_META_DATA); ExtendedMetaData extendedMetaData; final XSDHelper xsdHelper; if (option == null) { extendedMetaData = ExtendedMetaData.INSTANCE; xsdHelper = XSDHelper.INSTANCE; } else { extendedMetaData = (ExtendedMetaData) option; xsdHelper = new XSDHelperImpl(extendedMetaData, null); } xmlOptions.setEcoreBuilder(new DefaultEcoreBuilder(extendedMetaData) { public Collection generate(Map targetNamespaceToURI) throws IOException { for (Iterator iterator = targetNamespaceToURI.values().iterator(); iterator.hasNext();) { String uri = iterator.next().toString(); xsdHelper.define(uri.indexOf(":/") == -1 ? Thread.currentThread().getContextClassLoader().getResourceAsStream(uri) : new URL(uri).openStream(), uri); } return null; // XMLHandler#processSchemaLocations doesn't take the result } }); } } else if (loadLaxForm != 0) { /* * Tolerates element/attribute malform */ options = new HashMap(); options.put(OPTION_EXTENDED_META_DATA, new SDOExtendedMetaDataImpl()); } super.doLoad(inputSource, options); // TODO there is some thinking to be done about the restoration of options } /** * Loads the resource from a StAX XMLStreamReader. */ public void load(XMLStreamReader reader, Map options) throws IOException { this.reader = reader; SDOXMLLoadImpl xmlLoad = (SDOXMLLoadImpl) createXMLLoad(); Map mergedOptions = new HashMap(defaultLoadOptions); if (options != null) mergedOptions.putAll(options); xmlLoad.load(this, reader, mergedOptions); } ChangeSummaryStreamSerializer changeSummarySerializer/* = null*/; static private final class LocalName extends QName { private LocalName(String name) { super(name); } public String getNamespaceURI() { return null; } } static final String INDENT = " ", LINE_SEPARATOR = System.getProperty("line.separator"); static final class XmlString extends XMLString { XmlString(int lineWidth, String temporaryFileName) { super(lineWidth, temporaryFileName); // setLineWidth & setTemporaryFileName } XmlString(int lineWidth, String publicId, String systemId, String temporaryFileName) { super(lineWidth, publicId, systemId, temporaryFileName); } void setLineBreak(String lineBreak) { lineSeparator = lineBreak; } void margin(String margin) { indents.set(0, margin); } String indent = INDENT; protected String getElementIndent(int extra) { int nesting = depth + extra - 1; for (int i = indents.size() - 1; i < nesting; ++i) { indents.add(indents.get(i) + indent); } return (String) indents.get(nesting); } protected String getAttributeIndent() { return getElementIndent(); } public final boolean mixed() { return isMixed; } public void reset(String publicId, String systemId, int lineWidth, String temporaryFileName) { super.reset(publicId, systemId, lineWidth, temporaryFileName); setLineBreak(LINE_SEPARATOR); indent = INDENT; } } static final char MARK = '\n'; static final String LINE_BREAK = new String(new char[] { MARK }); final class SDOXMLSaveImpl extends XMLSaveImpl { SDOXMLSaveImpl(XMLHelper helper) { super(helper); } XmlString doc(XMLResource resource, Map options) { if (doc instanceof XmlString) return (XmlString) doc; Object lineWidth = options.get(OPTION_LINE_WIDTH); int width = lineWidth == null ? Integer.MAX_VALUE : ((Number) lineWidth).intValue(); XmlString d = resource != null && Boolean.TRUE.equals(options.get(OPTION_SAVE_DOCTYPE)) ? new XmlString(width, resource.getPublicId(), resource.getSystemId(), doc.getTemporaryFileName()) : new XmlString(width, doc.getTemporaryFileName()); doc = d; return d; } Map changeSummaryOptions = new HashMap(); String indent = INDENT, margin; protected void init(XMLResource resource, Map options) { super.init(resource, options); int unformat = 0; String lineBreak = (String) options.get(SDOUtil.XML_SAVE_LineBreak); if (lineBreak == null) changeSummaryOptions.put(SDOUtil.XML_SAVE_LineBreak, LINE_BREAK); else if (lineBreak.length() == 0) ++unformat; else { changeSummaryOptions.put(SDOUtil.XML_SAVE_LineBreak, LINE_BREAK); if (lineBreak.equals(LINE_SEPARATOR)) lineBreak = null; } String indent = (String) options.get(SDOUtil.XML_SAVE_INDENT); if (indent == null) changeSummaryOptions.put(SDOUtil.XML_SAVE_INDENT, INDENT); else if (indent.length() == 0) ++unformat; else { changeSummaryOptions.put(SDOUtil.XML_SAVE_INDENT, this.indent = indent); if (indent.equals(INDENT)) indent = null; } String margin = (String) options.get(SDOUtil.XML_SAVE_MARGIN); if (margin == null || margin.length() == 0) { if (unformat == 2) doc.setUnformatted(true); else if (lineBreak != null) { XmlString d = doc(resource, options); d.setLineBreak(lineBreak); if (indent != null) d.indent = indent; } else if (indent != null) doc(resource, options).indent = indent; this.margin = this.indent; } else { XmlString d = doc(resource, options); d.margin(margin); if (lineBreak != null) d.setLineBreak(lineBreak); if (indent != null) d.indent = indent; this.margin = margin + this.indent; if (!toDOM && declareXML) d.add(margin); } // changeSummaryOptions.put(ChangeSummaryStreamSerializer.OPTION_RootObject_PATH, "#"); // changeSummaryOptions.put(ChangeSummaryStreamSerializer.OPTION_OPTIMIZE_LIST, Boolean.TRUE); changeSummaryOptions.put(OPTION_EXTENDED_META_DATA, extendedMetaData); } QName qName(EStructuralFeature f) { if (extendedMetaData == null) return new LocalName(f.getName()); String nameSpace = extendedMetaData.getNamespace(f), name = extendedMetaData.getName(f); return nameSpace == null ? new LocalName(name) : new QName(nameSpace, name); } XMLStreamWriter xmlStreamWriter/* = null*/; void saveChangeSummary(EObject o, EStructuralFeature f, Object changeSummary) { boolean notMixed; if (doc instanceof XmlString) notMixed = !((XmlString) doc).mixed(); else if (extendedMetaData == null) notMixed = true; else switch (extendedMetaData.getContentKind(o.eClass())) { case ExtendedMetaData.MIXED_CONTENT: case ExtendedMetaData.SIMPLE_CONTENT: notMixed = false; break; default: notMixed = true; } if (notMixed) { StringBuffer margin = new StringBuffer(this.margin); for (EObject container = o.eContainer(), grandContainer; (grandContainer = container.eContainer()) != null; container = grandContainer) margin.append(indent); changeSummaryOptions.put(SDOUtil.XML_SAVE_MARGIN, margin.toString()); } try { if (xmlStreamWriter == null) { xmlStreamWriter = XMLOutputFactory.newInstance().createXMLStreamWriter(new Writer() { public void close() { } public void flush() { } protected final void add(char[] cbuf, int index, int off) { doc.addText(new String(cbuf, index, off - index)); } public void write(char[] cbuf, int off, int len) { if (len != 0) for (;;) { while (cbuf[off] == MARK) { doc.addLine(); if (--len == 0) return; ++off; } for (int index = off;/* true */;) { ++off; if (--len == 0) add(cbuf, index, off); else { if (cbuf[off] != MARK) continue; add(cbuf, index, off); doc.addLine(); if (--len != 0) break; } return; } ++off; } } }); xmlStreamWriter.setNamespaceContext(((SDOXMLHelperImpl) helper).new NameSpaceContext() { public String getNamespaceURI(String prefix) { return declareXSI && ExtendedMetaData.XSI_PREFIX.equals(prefix) ? ExtendedMetaData.XSI_URI : super .getNamespaceURI(prefix); } public String getPrefix(String namespaceURI) { return declareXSI && ExtendedMetaData.XSI_URI.equals(namespaceURI) ? ExtendedMetaData.XSI_PREFIX : super .getPrefix(namespaceURI); } public Iterator getPrefixes(String namespaceURI) { final Iterator iterator = super.getPrefixes(namespaceURI); return ExtendedMetaData.XSI_URI.equals(namespaceURI) ? new Iterator() { boolean first = true; public boolean hasNext() { if (first) if (declareXSI) // never from true to false return true; else first = false; return iterator.hasNext(); } public Object next() { if (first) { first = false; if (declareXSI) return ExtendedMetaData.XSI_PREFIX; } return iterator.next(); } public void remove() { if (first) declareXSI = false; else iterator.remove(); } } : iterator; } }); for (Iterator iterator = helper.getPrefixToNamespaceMap().iterator(); iterator.hasNext();) { Map.Entry entry = (Map.Entry) iterator.next(); xmlStreamWriter.setPrefix((String) entry.getKey(), (String) entry.getValue()); } if (declareXSI) xmlStreamWriter.setPrefix(ExtendedMetaData.XSI_PREFIX, ExtendedMetaData.XSI_URI); if (changeSummarySerializer == null) changeSummarySerializer = new ChangeSummaryStreamSerializer(); } changeSummarySerializer.saveChangeSummary((ChangeSummary) changeSummary, qName(f), xmlStreamWriter, changeSummaryOptions); if (notMixed) doc.addLine(); } catch (XMLStreamException e) { xmlResource.getErrors().add(new XMIException(e)); } } protected void saveDataTypeElementSingle(EObject o, EStructuralFeature f) { if (f.getEType() == ChangeSummaryStreamSerializer.ChangeSummary_TYPE) saveChangeSummary(o, f, helper.getValue(o, f)); else super.saveDataTypeElementSingle(o, f); } /* * TEMPORARILY COPIED FROM BASE CLASS - DO NOT EDIT - WILL BE REMOVED WHEN WE MOVE TO EMF 2.3 */ protected boolean saveElementFeatureMap(EObject o, EStructuralFeature f) { List values = (List)helper.getValue(o, f); int size = values.size(); for (int i = 0; i < size; i++) { FeatureMap.Entry entry = (FeatureMap.Entry)values.get(i); EStructuralFeature entryFeature = entry.getEStructuralFeature(); Object value = entry.getValue(); if (entryFeature instanceof EReference) { if (value == null) { saveNil(o, entryFeature); } else { EReference referenceEntryFeature = (EReference)entryFeature; if (referenceEntryFeature.isContainment()) { saveElement((InternalEObject)value, entryFeature); } else if (referenceEntryFeature.isResolveProxies()) { saveFeatureMapElementReference((EObject)value, referenceEntryFeature); } else { saveElementIDRef(o, (EObject)value, entryFeature); } } } else { if (entryFeature == XMLTypePackage.eINSTANCE.getXMLTypeDocumentRoot_Text()) { String svalue = value.toString(); if (escape != null) { svalue = escape.convertText(svalue); } if (!toDOM) { doc.addText(svalue); } else { Node text = document.createTextNode(svalue); currentNode.appendChild(text); handler.recordValues(text, o, f, entry); } } else if (entryFeature == XMLTypePackage.eINSTANCE.getXMLTypeDocumentRoot_CDATA()) { String stringValue = value.toString(); if (escape != null) { stringValue = escape.convertLines(stringValue); } if (!toDOM) { doc.addCDATA(stringValue); } else { Node cdata = document.createCDATASection(stringValue); currentNode.appendChild(cdata); handler.recordValues(cdata, o, f, entry); } } else if (entryFeature == XMLTypePackage.eINSTANCE.getXMLTypeDocumentRoot_Comment()) { String stringValue = value.toString(); if (escape != null) { stringValue = escape.convertLines(stringValue); } if (!toDOM) { doc.addComment(stringValue); } else { // TODO comments are not sent to recordValues currentNode.appendChild(document.createComment(stringValue)); } } else { saveElement(o, value, entryFeature); } } } return size > 0; } protected final void saveElement(EObject o, Object value, EStructuralFeature f) { if (f.getEType() == ChangeSummaryStreamSerializer.ChangeSummary_TYPE) { saveChangeSummary(o, f, value); return; } /* super.saveElement(o, value, f); * TEMPORARILY COPIED FROM BASE CLASS - DO NOT EDIT - WILL BE REMOVED WHEN WE MOVE TO EMF 2.3 */ if (value == null) { saveNil(o, f); } else { String svalue = getDatatypeValue(value, f, false); if (!toDOM) { doc.saveDataValueElement(helper.getQName(f), svalue); } else { helper.populateNameInfo(nameInfo, f); Element elem = document.createElementNS(nameInfo.getNamespaceURI(), nameInfo.getQualifiedName()); Node text = document.createTextNode(svalue); elem.appendChild(text); currentNode.appendChild(elem); handler.recordValues(elem, o, f, value); handler.recordValues(text, o, f, value); } } } } protected XMLSave createXMLSave() { return new SDOXMLSaveImpl(createXMLHelper()); } }