KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > emf > ecore > xmi > impl > XMLSaveImpl


1 /**
2  * <copyright>
3  *
4  * Copyright (c) 2002-2005 IBM Corporation and others.
5  * All rights reserved. This program and the accompanying materials
6  * are made available under the terms of the Eclipse Public License v1.0
7  * which accompanies this distribution, and is available at
8  * http://www.eclipse.org/legal/epl-v10.html
9  *
10  * Contributors:
11  * IBM - Initial API and implementation
12  *
13  * </copyright>
14  *
15  * $Id: XMLSaveImpl.java,v 1.42 2005/06/16 04:06:26 marcelop Exp $
16  */

17 package org.eclipse.emf.ecore.xmi.impl;
18
19
20 import java.io.File JavaDoc;
21 import java.io.IOException JavaDoc;
22 import java.io.OutputStream JavaDoc;
23 import java.io.OutputStreamWriter JavaDoc;
24 import java.lang.reflect.Field JavaDoc;
25 import java.util.ArrayList JavaDoc;
26 import java.util.Collections JavaDoc;
27 import java.util.HashSet JavaDoc;
28 import java.util.Iterator JavaDoc;
29 import java.util.List JavaDoc;
30 import java.util.Map JavaDoc;
31 import java.util.Set JavaDoc;
32
33 import org.eclipse.emf.common.util.EMap;
34 import org.eclipse.emf.common.util.URI;
35 import org.eclipse.emf.ecore.EClass;
36 import org.eclipse.emf.ecore.EClassifier;
37 import org.eclipse.emf.ecore.EDataType;
38 import org.eclipse.emf.ecore.EFactory;
39 import org.eclipse.emf.ecore.EObject;
40 import org.eclipse.emf.ecore.EPackage;
41 import org.eclipse.emf.ecore.EReference;
42 import org.eclipse.emf.ecore.EStructuralFeature;
43 import org.eclipse.emf.ecore.InternalEObject;
44 import org.eclipse.emf.ecore.resource.Resource;
45 import org.eclipse.emf.ecore.util.BasicExtendedMetaData;
46 import org.eclipse.emf.ecore.util.ExtendedMetaData;
47 import org.eclipse.emf.ecore.util.FeatureMap;
48 import org.eclipse.emf.ecore.util.InternalEList;
49 import org.eclipse.emf.ecore.xmi.DOMHandler;
50 import org.eclipse.emf.ecore.xmi.DanglingHREFException;
51 import org.eclipse.emf.ecore.xmi.NameInfo;
52 import org.eclipse.emf.ecore.xmi.XMLHelper;
53 import org.eclipse.emf.ecore.xmi.XMLResource;
54 import org.eclipse.emf.ecore.xmi.XMLSave;
55 import org.eclipse.emf.ecore.xml.namespace.XMLNamespacePackage;
56 import org.eclipse.emf.ecore.xml.type.AnyType;
57 import org.eclipse.emf.ecore.xml.type.SimpleAnyType;
58 import org.eclipse.emf.ecore.xml.type.XMLTypePackage;
59 import org.eclipse.emf.ecore.xml.type.internal.DataValue.XMLChar;
60 import org.w3c.dom.Attr JavaDoc;
61 import org.w3c.dom.Document JavaDoc;
62 import org.w3c.dom.Element JavaDoc;
63 import org.w3c.dom.Node JavaDoc;
64
65
66 /**
67  * This implements the XML serializer, possibly using an XMLMap
68  * if one is provided as a save option.
69  */

70 public class XMLSaveImpl implements XMLSave
71 {
72   protected static final int INDEX_LOOKUP = 0;
73  
74   final StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
75   
76   protected XMLHelper helper;
77   protected XMLString doc;
78   protected boolean declareXSI;
79   protected boolean useEncodedAttributeStyle;
80   protected boolean declareXML;
81   protected boolean saveTypeInfo;
82   protected XMLTypeInfo xmlTypeInfo;
83   protected boolean keepDefaults;
84   protected Escape escape;
85   protected Escape escapeURI;
86   protected Lookup featureTable;
87   protected String JavaDoc encoding;
88   protected String JavaDoc idAttributeName = "id";
89   protected String JavaDoc idAttributeNS = null;
90   protected String JavaDoc processDanglingHREF;
91   protected boolean declareSchemaLocation;
92   protected boolean declareSchemaLocationImplementation;
93   protected XMLResource.XMLMap map;
94   protected ExtendedMetaData extendedMetaData;
95   protected EClass anySimpleType;
96   protected EClass anyType;
97   protected Map JavaDoc eObjectToExtensionMap;
98   protected EPackage xmlSchemaTypePackage = XMLTypePackage.eINSTANCE;
99   protected int flushThreshold = Integer.MAX_VALUE;
100   protected boolean toDOM;
101   protected DOMHandler handler;
102   protected Document JavaDoc document;
103   protected Node JavaDoc currentNode;
104   protected NameInfo nameInfo;
105   protected boolean useCache;
106   
107   protected static final int SKIP = 0;
108   protected static final int SAME_DOC = 1;
109   protected static final int CROSS_DOC = 2;
110
111   protected static final int TRANSIENT = 0;
112   protected static final int DATATYPE_SINGLE = 1;
113   protected static final int DATATYPE_ELEMENT_SINGLE = 2;
114   protected static final int DATATYPE_CONTENT_SINGLE = 3;
115   protected static final int DATATYPE_SINGLE_NILLABLE = 4;
116   protected static final int DATATYPE_MANY = 5;
117   protected static final int OBJECT_CONTAIN_SINGLE = 6;
118   protected static final int OBJECT_CONTAIN_MANY = 7;
119   protected static final int OBJECT_HREF_SINGLE = 8;
120   protected static final int OBJECT_HREF_MANY = 9;
121   protected static final int OBJECT_CONTAIN_SINGLE_UNSETTABLE = 10;
122   protected static final int OBJECT_CONTAIN_MANY_UNSETTABLE = 11;
123   protected static final int OBJECT_HREF_SINGLE_UNSETTABLE = 12;
124   protected static final int OBJECT_HREF_MANY_UNSETTABLE = 13;
125   protected static final int OBJECT_ELEMENT_SINGLE = 14;
126   protected static final int OBJECT_ELEMENT_SINGLE_UNSETTABLE = 15;
127   protected static final int OBJECT_ELEMENT_MANY = 16;
128   protected static final int OBJECT_ELEMENT_IDREF_SINGLE = 17;
129   protected static final int OBJECT_ELEMENT_IDREF_SINGLE_UNSETTABLE = 18;
130   protected static final int OBJECT_ELEMENT_IDREF_MANY = 19;
131   protected static final int ATTRIBUTE_FEATURE_MAP = 20;
132   protected static final int ELEMENT_FEATURE_MAP = 21;
133   protected static final int OBJECT_ATTRIBUTE_SINGLE = 22;
134   protected static final int OBJECT_ATTRIBUTE_MANY = 23;
135   protected static final int OBJECT_ATTRIBUTE_IDREF_SINGLE = 24;
136   protected static final int OBJECT_ATTRIBUTE_IDREF_MANY = 25;
137   protected static final int DATATYPE_ATTRIBUTE_MANY = 26;
138
139   protected static final String JavaDoc XML_VERSION = "1.0";
140
141   protected static final String JavaDoc XSI_NIL = XMLResource.XSI_NS+":"+XMLResource.NIL; // xsi:nil
142
protected static final String JavaDoc XSI_TYPE_NS = XMLResource.XSI_NS+":"+XMLResource.TYPE; // xsi:type
143
protected static final String JavaDoc XSI_XMLNS = XMLResource.XML_NS+":"+XMLResource.XSI_NS; // xmlns:xsi
144
protected static final String JavaDoc XSI_SCHEMA_LOCATION = XMLResource.XSI_NS+":"+XMLResource.SCHEMA_LOCATION; // xsi:schemaLocation
145
protected static final String JavaDoc XSI_NO_NAMESPACE_SCHEMA_LOCATION = XMLResource.XSI_NS+":"+XMLResource.NO_NAMESPACE_SCHEMA_LOCATION; // xsi:noNamespaceSchemaLocation
146

147   protected static final int EMPTY_ELEMENT = 1;
148   protected static final int CONTENT_ELEMENT = 2;
149
150   public XMLSaveImpl(XMLHelper helper)
151   {
152     this.helper = helper;
153   }
154
155   /**
156    * Constructor for XMLSave.
157    * @param options
158    * @param helper
159    * @param encoding
160    */

161   public XMLSaveImpl(Map JavaDoc options, XMLHelper helper, String JavaDoc encoding)
162   {
163     this.helper = helper;
164     init(helper.getResource(), options);
165     this.encoding = encoding;
166   }
167   
168   public Document JavaDoc save(XMLResource resource, Document JavaDoc doc, Map JavaDoc options, DOMHandler handler)
169   {
170     toDOM = true;
171     document = doc;
172     this.handler = handler;
173     
174     init(resource, options);
175     List JavaDoc contents = resource.getContents();
176     traverse(contents);
177     if (extendedMetaData != null && contents.size() >= 1)
178     {
179       EObject root = (EObject)contents.get(0);
180       EClass eClass = root.eClass();
181
182       EReference xmlnsPrefixMapFeature = extendedMetaData.getXMLNSPrefixMapFeature(eClass);
183       if (xmlnsPrefixMapFeature != null)
184       {
185         EMap xmlnsPrefixMap = (EMap)root.eGet(xmlnsPrefixMapFeature);
186         for (Iterator JavaDoc i = helper.getPrefixToNamespaceMap().iterator(); i.hasNext(); )
187         {
188           Map.Entry JavaDoc entry = (Map.Entry JavaDoc)i.next();
189           Object JavaDoc key = entry.getKey();
190           Object JavaDoc value = entry.getValue();
191           Object JavaDoc currentValue = xmlnsPrefixMap.get(key);
192           if (currentValue == null ? value != null : !currentValue.equals(value))
193           {
194             xmlnsPrefixMap.put(key, value);
195           }
196         }
197       }
198     }
199     return document;
200   }
201
202   public void save(XMLResource resource, OutputStream JavaDoc outputStream, Map JavaDoc options) throws IOException JavaDoc
203   {
204     init(resource, options);
205     List JavaDoc contents = resource.getContents();
206     traverse(contents);
207
208     if (encoding.equals("US-ASCII") || encoding.equals("ASCII"))
209     {
210       writeAscii(outputStream);
211       outputStream.flush();
212     }
213     else
214     {
215       OutputStreamWriter JavaDoc outputStreamWriter = new OutputStreamWriter JavaDoc(outputStream, helper.getJavaEncoding(encoding));
216       write(outputStreamWriter);
217       outputStreamWriter.flush();
218     }
219
220     if (extendedMetaData != null && contents.size() >= 1)
221     {
222       EObject root = (EObject)contents.get(0);
223       EClass eClass = root.eClass();
224
225       EReference xmlnsPrefixMapFeature = extendedMetaData.getXMLNSPrefixMapFeature(eClass);
226       if (xmlnsPrefixMapFeature != null)
227       {
228         EMap xmlnsPrefixMap = (EMap)root.eGet(xmlnsPrefixMapFeature);
229         for (Iterator JavaDoc i = helper.getPrefixToNamespaceMap().iterator(); i.hasNext(); )
230         {
231           Map.Entry JavaDoc entry = (Map.Entry JavaDoc)i.next();
232           Object JavaDoc key = entry.getKey();
233           Object JavaDoc value = entry.getValue();
234           Object JavaDoc currentValue = xmlnsPrefixMap.get(key);
235           if (currentValue == null ? value != null : !currentValue.equals(value))
236           {
237             xmlnsPrefixMap.put(key, value);
238           }
239         }
240       }
241     }
242
243     if (processDanglingHREF == null ||
244         XMLResource.OPTION_PROCESS_DANGLING_HREF_THROW.equals(processDanglingHREF))
245     {
246       DanglingHREFException exception = helper.getDanglingHREFException();
247
248       if (exception != null)
249       {
250         helper = null;
251         throw new Resource.IOWrappedException(exception);
252       }
253     }
254
255     if (useCache)
256     {
257       ConfigurationCache.INSTANCE.releasePrinter(doc);
258       if (escape != null)
259       {
260         ConfigurationCache.INSTANCE.releaseEscape(escape);
261       }
262     }
263     featureTable = null;
264     doc = null;
265     helper = null;
266   }
267
268   
269   protected void init(XMLResource resource, Map JavaDoc options)
270   {
271     useCache = Boolean.TRUE.equals(options.get(XMLResource.OPTION_CONFIGURATION_CACHE));
272
273     nameInfo = new NameInfoImpl();
274     declareXSI = false;
275     keepDefaults = Boolean.TRUE.equals(options.get(XMLResource.OPTION_KEEP_DEFAULT_CONTENT));
276     useEncodedAttributeStyle = Boolean.TRUE.equals(options.get(XMLResource.OPTION_USE_ENCODED_ATTRIBUTE_STYLE));
277     declareSchemaLocationImplementation = Boolean.TRUE.equals(options.get(XMLResource.OPTION_SCHEMA_LOCATION_IMPLEMENTATION));
278     declareSchemaLocation = declareSchemaLocationImplementation || Boolean.TRUE.equals(options.get(XMLResource.OPTION_SCHEMA_LOCATION));
279
280     Object JavaDoc saveTypeInfoOption = options.get(XMLResource.OPTION_SAVE_TYPE_INFORMATION);
281     if (saveTypeInfoOption instanceof Boolean JavaDoc)
282     {
283       saveTypeInfo = saveTypeInfoOption.equals(Boolean.TRUE);
284       if (saveTypeInfo)
285       {
286         xmlTypeInfo = new XMLTypeInfoImpl();
287       }
288     }
289     else
290     {
291       saveTypeInfo = saveTypeInfoOption != null;
292       if (saveTypeInfo)
293       {
294         xmlTypeInfo = (XMLTypeInfo)saveTypeInfoOption;
295       }
296     }
297
298     anyType = (EClass)options.get(XMLResource.OPTION_ANY_TYPE);
299     anySimpleType = (EClass)options.get(XMLResource.OPTION_ANY_SIMPLE_TYPE);
300     if (anyType == null)
301     {
302       anyType = XMLTypePackage.eINSTANCE.getAnyType();
303       anySimpleType = XMLTypePackage.eINSTANCE.getSimpleAnyType();
304     }
305     
306     Object JavaDoc extendedMetaDataOption = options.get(XMLResource.OPTION_EXTENDED_META_DATA);
307     if (extendedMetaDataOption instanceof Boolean JavaDoc)
308     {
309       if (extendedMetaDataOption.equals(Boolean.TRUE))
310       {
311         extendedMetaData =
312           resource == null || resource.getResourceSet() == null ?
313             ExtendedMetaData.INSTANCE :
314             new BasicExtendedMetaData(resource.getResourceSet().getPackageRegistry());
315       }
316     }
317     else
318     {
319       extendedMetaData = (ExtendedMetaData)options.get(XMLResource.OPTION_EXTENDED_META_DATA);
320     }
321     
322     // set serialization options
323
if (!toDOM)
324     {
325       declareXML = !Boolean.FALSE.equals(options.get(XMLResource.OPTION_DECLARE_XML));
326
327       if (options.get(XMLResource.OPTION_FLUSH_THRESHOLD) instanceof Integer JavaDoc)
328       {
329         flushThreshold = ((Integer JavaDoc)options.get(XMLResource.OPTION_FLUSH_THRESHOLD)).intValue();
330       }
331
332       String JavaDoc temporaryFileName = null;
333       if (Boolean.TRUE.equals(options.get(XMLResource.OPTION_USE_FILE_BUFFER)))
334       {
335         try
336         {
337           temporaryFileName = File.createTempFile("XMLSave", null).getPath();
338         }
339         catch (IOException JavaDoc exception)
340         {
341           // If we can't create a temp file then we have to ignore the option.
342
}
343       }
344       
345       Integer JavaDoc lineWidth = (Integer JavaDoc)options.get(XMLResource.OPTION_LINE_WIDTH);
346       int effectiveLineWidth = lineWidth == null ? Integer.MAX_VALUE : lineWidth.intValue();
347       String JavaDoc publicId = null, systemId = null;
348       if (resource != null && Boolean.TRUE.equals(options.get(XMLResource.OPTION_SAVE_DOCTYPE)))
349       {
350         publicId = resource.getPublicId();
351         systemId = resource.getSystemId();
352       }
353       if (useCache)
354       {
355         doc = ConfigurationCache.INSTANCE.getPrinter();
356         doc.reset(publicId, systemId, effectiveLineWidth, temporaryFileName);
357         escape = Boolean.TRUE.equals(options.get(XMLResource.OPTION_SKIP_ESCAPE)) ? null : ConfigurationCache.INSTANCE.getEscape();
358       }
359       else
360       {
361         doc = new XMLString(effectiveLineWidth, publicId, systemId, temporaryFileName);
362         escape = Boolean.TRUE.equals(options.get(XMLResource.OPTION_SKIP_ESCAPE)) ? null : new Escape();
363       }
364
365       if (Boolean.FALSE.equals(options.get(XMLResource.OPTION_FORMATTED)))
366       {
367         doc.setUnformatted(true);
368       }
369       
370
371       escapeURI = Boolean.FALSE.equals(options.get(XMLResource.OPTION_SKIP_ESCAPE_URI)) ? escape : null;
372
373       if (options.containsKey(XMLResource.OPTION_ENCODING))
374       {
375         encoding = (String JavaDoc)options.get(XMLResource.OPTION_ENCODING);
376       }
377       else if (resource != null)
378       {
379         encoding = resource.getEncoding();
380       }
381     }
382     else
383     {
384       // DOM serialization
385
if (handler instanceof DefaultDOMHandlerImpl)
386       {
387         ((DefaultDOMHandlerImpl)handler).setExtendedMetaData(extendedMetaData);
388       }
389     }
390     processDanglingHREF = (String JavaDoc) options.get(XMLResource.OPTION_PROCESS_DANGLING_HREF);
391     helper.setProcessDanglingHREF(processDanglingHREF);
392
393     map = (XMLResource.XMLMap) options.get(XMLResource.OPTION_XML_MAP);
394     if (map != null)
395     {
396       helper.setXMLMap(map);
397
398       if (map.getIDAttributeName() != null)
399       {
400         idAttributeName = map.getIDAttributeName();
401       }
402     }
403
404     if (resource != null)
405     {
406       eObjectToExtensionMap = resource.getEObjectToExtensionMap();
407       if (eObjectToExtensionMap.isEmpty())
408       {
409         eObjectToExtensionMap = null;
410       }
411       else if (extendedMetaData == null)
412       {
413         extendedMetaData =
414           resource.getResourceSet() == null ?
415             ExtendedMetaData.INSTANCE :
416             new BasicExtendedMetaData(resource.getResourceSet().getPackageRegistry());
417       }
418     }
419
420     if (extendedMetaData != null)
421     {
422       helper.setExtendedMetaData(extendedMetaData);
423       if (resource != null && resource.getContents().size() >=1)
424       {
425         EObject root = (EObject)resource.getContents().get(0);
426         EClass eClass = root.eClass();
427
428         EReference xmlnsPrefixMapFeature = extendedMetaData.getXMLNSPrefixMapFeature(eClass);
429         if (xmlnsPrefixMapFeature != null)
430         {
431           EMap xmlnsPrefixMap = (EMap)root.eGet(xmlnsPrefixMapFeature);
432           helper.setPrefixToNamespaceMap(xmlnsPrefixMap);
433         }
434       }
435     }
436     
437     List JavaDoc lookup = (List JavaDoc)options.get(XMLResource.OPTION_USE_CACHED_LOOKUP_TABLE);
438     if (lookup != null)
439     {
440       // caching turned on by the user
441
if (lookup.isEmpty())
442       {
443         featureTable = new Lookup(map, extendedMetaData);
444         lookup.add(featureTable);
445       }
446       else
447       {
448         featureTable = (Lookup)lookup.get(INDEX_LOOKUP);
449       }
450     }
451     else
452     {
453       //no caching
454
featureTable = new Lookup(map, extendedMetaData);
455     }
456   }
457
458   public void traverse(List JavaDoc contents)
459   {
460     if (!toDOM && declareXML)
461     {
462       doc.add("<?xml version=\"" + XML_VERSION + "\" encoding=\"" + encoding + "\"?>");
463       doc.addLine();
464     }
465
466     int size = contents.size();
467
468     // Reserve a place to insert xmlns declarations after we know what they all are.
469
//
470
Object JavaDoc mark;
471
472     if (size == 1)
473     {
474       mark = writeTopObject((EObject) contents.get(0));
475     }
476     else
477     {
478       mark = writeTopObjects(contents);
479     }
480     if (!toDOM)
481     {
482       // Go back and add all the XMLNS stuff.
483
//
484
doc.resetToMark(mark);
485     }
486     else
487     {
488       currentNode = document.getDocumentElement();
489     }
490     addNamespaceDeclarations();
491   }
492   /*
493    * INTERNAL: this is a specialized method to add attributes for a top/root element
494    */

495   protected void writeTopAttributes(EObject top)
496   {
497   }
498
499   protected Object JavaDoc writeTopObject(EObject top)
500   {
501     EClass eClass = top.eClass();
502     if (!toDOM)
503     {
504       if (extendedMetaData == null || featureTable.getDocumentRoot(eClass.getEPackage()) != eClass)
505       {
506         String JavaDoc name = helper.getQName(eClass);
507         doc.startElement(name);
508         writeTopAttributes(top);
509         Object JavaDoc mark = doc.mark();
510         saveElementID(top);
511         return mark;
512       }
513       else
514       {
515         doc.startElement(null);
516         saveFeatures(top);
517         return null;
518       }
519     }
520     else
521     {
522       if (extendedMetaData == null || extendedMetaData.getDocumentRoot(eClass.getEPackage()) != eClass)
523       {
524         helper.populateNameInfo(nameInfo, eClass);
525         if (document.getLastChild() == null)
526         {
527           currentNode = document.createElementNS(nameInfo.getNamespaceURI(), nameInfo.getQualifiedName());
528           currentNode = document.appendChild(currentNode);
529         }
530         else
531         {
532           currentNode = currentNode.appendChild(document.createElementNS(nameInfo.getNamespaceURI(), nameInfo.getQualifiedName()));
533         }
534         handler.recordValues(currentNode, null, null, top);
535         writeTopAttributes(top);
536         saveElementID(top);
537         return null;
538       }
539       else
540       {
541         saveFeatures(top);
542         return null;
543       }
544     }
545   }
546
547   protected Object JavaDoc writeTopObjects(List JavaDoc contents)
548   {
549     return writeTopObject((EObject)contents.get(0));
550   }
551
552   protected void addNamespaceDeclarations()
553   {
554     EPackage noNamespacePackage = helper.getNoNamespacePackage();
555     EPackage[] packages = helper.packages();
556     buffer.setLength(0);
557     StringBuffer JavaDoc xsiSchemaLocation = buffer;
558     String JavaDoc xsiNoNamespaceSchemaLocation = null;
559     if (declareSchemaLocation)
560     {
561       Map JavaDoc handledBySchemaLocationMap = Collections.EMPTY_MAP;
562
563       if (extendedMetaData != null)
564       {
565         Resource resource = helper.getResource();
566         if (resource != null && resource.getContents().size() >= 1)
567         {
568           EObject root = (EObject)resource.getContents().get(0);
569           EClass eClass = root.eClass();
570
571           EReference xsiSchemaLocationMapFeature = extendedMetaData.getXSISchemaLocationMapFeature(eClass);
572           if (xsiSchemaLocationMapFeature != null)
573           {
574             EMap xsiSchemaLocationMap = (EMap)root.eGet(xsiSchemaLocationMapFeature);
575             if (!xsiSchemaLocationMap.isEmpty())
576             {
577               handledBySchemaLocationMap = xsiSchemaLocationMap.map();
578               declareXSI = true;
579               for (Iterator JavaDoc i = xsiSchemaLocationMap.entrySet().iterator(); i.hasNext(); )
580               {
581                 Map.Entry JavaDoc entry = (Map.Entry JavaDoc)i.next();
582                 String JavaDoc namespace = (String JavaDoc)entry.getKey();
583                 URI location = URI.createURI(entry.getValue().toString());
584                 if (namespace == null)
585                 {
586                   xsiNoNamespaceSchemaLocation = helper.deresolve(location).toString();
587                 }
588                 else
589                 {
590                   if (xsiSchemaLocation.length() > 0)
591                   {
592                     xsiSchemaLocation.append(' ');
593                   }
594                   xsiSchemaLocation.append(namespace);
595                   xsiSchemaLocation.append(' ');
596                   xsiSchemaLocation.append(helper.deresolve(location).toString());
597                 }
598               }
599             }
600           }
601         }
602       }
603
604       for (int i = 0; i < packages.length; i++)
605       {
606         EPackage ePackage = packages[i];
607
608         String JavaDoc javaImplementationLocation = null;
609         if (declareSchemaLocationImplementation)
610         {
611           // First try to see if this package's implementation class has an eInstance.
612
//
613
try
614           {
615             Field JavaDoc field = ePackage.getClass().getField("eINSTANCE");
616             javaImplementationLocation = "java://" + field.getDeclaringClass().getName();
617           }
618           catch (Exception JavaDoc exception)
619           {
620           }
621         }
622
623         if (noNamespacePackage == ePackage)
624         {
625           if (ePackage.eResource() != null && !handledBySchemaLocationMap.containsKey(null))
626           {
627             declareXSI = true;
628             if (javaImplementationLocation != null)
629             {
630               xsiNoNamespaceSchemaLocation = javaImplementationLocation;
631             }
632             else
633             {
634               xsiNoNamespaceSchemaLocation = helper.getHREF(ePackage);
635               if (xsiNoNamespaceSchemaLocation.endsWith("#/"))
636               {
637                 xsiNoNamespaceSchemaLocation = xsiNoNamespaceSchemaLocation.substring(0, xsiNoNamespaceSchemaLocation.length() - 2);
638               }
639             }
640           }
641         }
642         else
643         {
644           Resource resource = ePackage.eResource();
645           if (resource != null)
646           {
647             String JavaDoc nsURI = ePackage.getNsURI();
648             if (!handledBySchemaLocationMap.containsKey(nsURI))
649             {
650               URI uri = resource.getURI();
651               if (javaImplementationLocation != null || (uri == null ? nsURI != null : !uri.toString().equals(nsURI)))
652               {
653                 declareXSI = true;
654                 if (xsiSchemaLocation.length() > 0)
655                 {
656                   xsiSchemaLocation.append(' ');
657                 }
658                 xsiSchemaLocation.append(nsURI);
659                 xsiSchemaLocation.append(' ');
660                 String JavaDoc location = javaImplementationLocation == null ? helper.getHREF(ePackage) : javaImplementationLocation;
661                 if (location.endsWith("#/"))
662                 {
663                   location = location.substring(0, location.length() - 2);
664                 }
665                 xsiSchemaLocation.append(location);
666               }
667             }
668           }
669         }
670       }
671     }
672
673     if (declareXSI)
674     {
675       if (!toDOM)
676       {
677         doc.addAttribute(XSI_XMLNS, XMLResource.XSI_URI);
678       }
679       else
680       {
681         ((Element JavaDoc)currentNode).setAttributeNS(ExtendedMetaData.XMLNS_URI, XSI_XMLNS, XMLResource.XSI_URI);
682       }
683     }
684
685     for (int i = 0; i < packages.length; i++)
686     {
687       EPackage ePackage = packages[i];
688       if (ePackage != noNamespacePackage &&
689             ePackage != XMLNamespacePackage.eINSTANCE &&
690             !ExtendedMetaData.XMLNS_URI.equals(ePackage.getNsURI()))
691       {
692         String JavaDoc nsURI = extendedMetaData == null ? ePackage.getNsURI() : extendedMetaData.getNamespace(ePackage);
693         if (ePackage == xmlSchemaTypePackage)
694         {
695           nsURI = XMLResource.XML_SCHEMA_URI;
696         }
697         if (nsURI != null && !isDuplicateURI(nsURI))
698         {
699           List JavaDoc nsPrefixes = helper.getPrefixes(ePackage);
700           for (Iterator JavaDoc j = nsPrefixes.iterator(); j.hasNext(); )
701           {
702             String JavaDoc nsPrefix = (String JavaDoc)j.next();
703             if (!toDOM)
704             {
705               if (nsPrefix != null && nsPrefix.length() > 0)
706               {
707                 doc.addAttributeNS(XMLResource.XML_NS, nsPrefix, nsURI);
708               }
709               else
710               {
711                 doc.addAttribute(XMLResource.XML_NS, nsURI);
712               }
713             }
714             else
715             {
716               if (nsPrefix != null && nsPrefix.length() > 0)
717               {
718                 ((Element JavaDoc)currentNode).setAttributeNS(ExtendedMetaData.XMLNS_URI, XMLResource.XML_NS +":" + nsPrefix, nsURI);
719               }
720               else
721               {
722                 ((Element JavaDoc)currentNode).setAttributeNS(ExtendedMetaData.XMLNS_URI, XMLResource.XML_NS, nsURI);
723               }
724             }
725           }
726         }
727       }
728     }
729
730     if (xsiSchemaLocation.length() > 0)
731     {
732       if (!toDOM)
733       {
734         doc.addAttribute(XSI_SCHEMA_LOCATION, xsiSchemaLocation.toString());
735       }
736       else
737       {
738         ((Element JavaDoc)currentNode).setAttributeNS(XMLResource.XSI_URI, XSI_SCHEMA_LOCATION, xsiSchemaLocation.toString());
739       }
740     }
741
742     if (xsiNoNamespaceSchemaLocation != null)
743     {
744       if (!toDOM)
745       {
746         doc.addAttribute(XSI_NO_NAMESPACE_SCHEMA_LOCATION, xsiNoNamespaceSchemaLocation);
747       }
748       else
749       {
750         ((Element JavaDoc)currentNode).setAttributeNS(XMLResource.XSI_URI, XSI_NO_NAMESPACE_SCHEMA_LOCATION, xsiNoNamespaceSchemaLocation);
751       }
752     }
753   }
754   
755   public boolean isDuplicateURI(String JavaDoc nsURI)
756   {
757     return false;
758   }
759
760   public void write(OutputStreamWriter JavaDoc os) throws IOException JavaDoc
761   {
762     doc.write(os, flushThreshold);
763     os.flush();
764   }
765
766   public void writeAscii(OutputStream JavaDoc os) throws IOException JavaDoc
767   {
768     doc.writeAscii(os, flushThreshold);
769     os.flush();
770   }
771
772   public char[] toChar()
773   {
774     int size = doc.getLength();
775     char[] output = new char[size];
776     doc.getChars(output, 0);
777     return output;
778   }
779
780   protected void saveElement(EObject o, EStructuralFeature f)
781   {
782     EClass eClass = o.eClass();
783     EClassifier eType = f.getEType();
784
785     if (extendedMetaData != null && eClass != eType)
786     {
787       // Check if it's an anonymous type.
788
//
789
String JavaDoc name = extendedMetaData.getName(eClass);
790       if (name.endsWith("_._type"))
791       {
792         String JavaDoc elementName = name.substring(0, name.indexOf("_._"));
793         String JavaDoc prefix = helper.getPrefix(eClass.getEPackage());
794         if (!"".equals(prefix))
795         {
796           elementName = prefix + ":" + elementName;
797         }
798         if (!toDOM)
799         {
800           doc.startElement(elementName);
801         }
802         else
803         {
804           currentNode = currentNode.appendChild(document.createElementNS(helper.getNamespaceURI(prefix), elementName));
805           handler.recordValues(currentNode, o.eContainer(), f, o);
806         }
807         saveElementID(o);
808         return;
809       }
810     }
811
812     if (map != null)
813     {
814       XMLResource.XMLInfo info = map.getInfo(eClass);
815       if (info != null && info.getXMLRepresentation() == XMLResource.XMLInfo.ELEMENT)
816       {
817         if (!toDOM)
818         {
819           String JavaDoc elementName = helper.getQName(eClass);
820           doc.startElement(elementName);
821         }
822         else
823         {
824           helper.populateNameInfo(nameInfo, eClass);
825           if (currentNode == null)
826           {
827             currentNode = document.createElementNS(nameInfo.getNamespaceURI(), nameInfo.getQualifiedName());
828             document.appendChild(currentNode);
829             handler.recordValues(currentNode, o.eContainer(), f, o);
830           }
831           else
832           {
833             currentNode = currentNode.appendChild(document.createElementNS(nameInfo.getNamespaceURI(), nameInfo.getQualifiedName()));
834             handler.recordValues(currentNode, o.eContainer(), f, o);
835           }
836         }
837         saveElementID(o);
838         return;
839       }
840     }
841
842     if (o instanceof AnyType)
843     {
844       helper.pushContext();
845       for (Iterator JavaDoc i = ((AnyType)o).getAnyAttribute().iterator(); i.hasNext(); )
846       {
847         FeatureMap.Entry entry = (FeatureMap.Entry)i.next();
848         if (ExtendedMetaData.XMLNS_URI.equals(extendedMetaData.getNamespace(entry.getEStructuralFeature())))
849         {
850           String JavaDoc uri = (String JavaDoc)entry.getValue();
851           helper.addPrefix(extendedMetaData.getName(entry.getEStructuralFeature()), uri == null ? "" : uri);
852         }
853       }
854     }
855     if (!toDOM)
856     {
857       String JavaDoc featureName = helper.getQName(f);
858       doc.startElement(featureName);
859     }
860     else
861     {
862       helper.populateNameInfo(nameInfo, f);
863       if (currentNode == null)
864       {
865         // this is a root element
866
currentNode = document.createElementNS(nameInfo.getNamespaceURI(), nameInfo.getQualifiedName());
867         document.appendChild(currentNode);
868         handler.recordValues(currentNode, o.eContainer(), f, o);
869       }
870       else
871       {
872         currentNode = currentNode.appendChild(document.createElementNS(nameInfo.getNamespaceURI(), nameInfo.getQualifiedName()));
873         handler.recordValues(currentNode, o.eContainer(), f, o);
874       }
875     }
876     
877     if (saveTypeInfo ? xmlTypeInfo.shouldSaveType(eClass, eType, f) : eClass != eType && eClass != anyType)
878     {
879       if (eClass == anySimpleType)
880       {
881         saveTypeAttribute(((SimpleAnyType)o).getInstanceType());
882       }
883       else
884       {
885         saveTypeAttribute(eClass);
886       }
887     }
888
889     saveElementID(o);
890   }
891
892   protected void saveTypeAttribute(EClass eClass)
893   {
894     declareXSI = true;
895     if (!toDOM)
896     {
897       doc.addAttribute(XSI_TYPE_NS, helper.getQName(eClass));
898     }
899     else
900     {
901       helper.populateNameInfo(nameInfo, eClass);
902       ((Element JavaDoc)currentNode).setAttributeNS(ExtendedMetaData.XSI_URI, XSI_TYPE_NS, nameInfo.getQualifiedName());
903     }
904     
905   }
906
907   protected void saveTypeAttribute(EDataType eDataType)
908   {
909     declareXSI = true;
910     if (!toDOM)
911     {
912       doc.addAttribute(XSI_TYPE_NS, helper.getQName(eDataType));
913     }
914     else
915     {
916       helper.populateNameInfo(nameInfo, eDataType);
917       ((Element JavaDoc)currentNode).setAttributeNS(XMLResource.XSI_URI, XSI_TYPE_NS, nameInfo.getQualifiedName());
918     }
919   }
920
921   protected boolean saveFeatures(EObject o)
922   {
923     EClass eClass = o.eClass();
924     int contentKind = extendedMetaData == null ? ExtendedMetaData.UNSPECIFIED_CONTENT : extendedMetaData.getContentKind(eClass);
925     if (!toDOM)
926     {
927       switch (contentKind)
928       {
929         case ExtendedMetaData.MIXED_CONTENT:
930         case ExtendedMetaData.SIMPLE_CONTENT:
931         {
932           doc.setMixed(true);
933           break;
934         }
935       }
936     }
937
938     EStructuralFeature[] features = featureTable.getFeatures(eClass);
939     int[] featureKinds = featureTable.getKinds(eClass, features);
940     int[] elementFeatures = null;
941     int elementCount = 0;
942
943     String JavaDoc content = null;
944
945     // Process XML attributes
946
LOOP:
947     for (int i = 0; i < features.length; i++ )
948     {
949       int kind = featureKinds[i];
950       EStructuralFeature f = features[i];
951       if (kind != TRANSIENT && (o.eIsSet(f) || keepDefaults && f.getDefaultValueLiteral() != null))
952       {
953         switch (kind)
954         {
955           case DATATYPE_ELEMENT_SINGLE:
956           {
957             if (contentKind == ExtendedMetaData.SIMPLE_CONTENT)
958             {
959               content = getDataTypeElementSingleSimple(o, f);
960               continue LOOP;
961             }
962             break;
963           }
964           case DATATYPE_SINGLE:
965           {
966             saveDataTypeSingle(o, f);
967             continue LOOP;
968           }
969           case DATATYPE_SINGLE_NILLABLE:
970           {
971             if (!isNil(o, f))
972             {
973               saveDataTypeSingle(o, f);
974               continue LOOP;
975             }
976             break;
977           }
978           case OBJECT_ATTRIBUTE_SINGLE:
979           {
980             saveEObjectSingle(o, f);
981             continue LOOP;
982           }
983           case OBJECT_ATTRIBUTE_MANY:
984           {
985             saveEObjectMany(o, f);
986             continue LOOP;
987           }
988           case OBJECT_ATTRIBUTE_IDREF_SINGLE:
989           {
990             saveIDRefSingle(o, f);
991             continue LOOP;
992           }
993           case OBJECT_ATTRIBUTE_IDREF_MANY:
994           {
995             saveIDRefMany(o, f);
996             continue LOOP;
997           }
998           case OBJECT_HREF_SINGLE_UNSETTABLE:
999           {
1000            if (isNil(o, f))
1001            {
1002              break;
1003            }
1004            // it's intentional to keep going
1005
}
1006          case OBJECT_HREF_SINGLE:
1007          {
1008            if (useEncodedAttributeStyle)
1009            {
1010              saveEObjectSingle(o, f);
1011              continue LOOP;
1012            }
1013            else
1014            {
1015              switch (sameDocSingle(o, f))
1016              {
1017                case SAME_DOC:
1018                {
1019                  saveIDRefSingle(o, f);
1020                  continue LOOP;
1021                }
1022                case CROSS_DOC:
1023                {
1024                  break;
1025                }
1026                default:
1027                {
1028                  continue LOOP;
1029                }
1030              }
1031            }
1032            break;
1033          }
1034          case OBJECT_HREF_MANY_UNSETTABLE:
1035          {
1036            if (isEmpty(o, f))
1037            {
1038              saveManyEmpty(o, f);
1039              continue LOOP;
1040            }
1041            // It's intental to keep going.
1042
}
1043          case OBJECT_HREF_MANY:
1044          {
1045            if (useEncodedAttributeStyle)
1046            {
1047              saveEObjectMany(o, f);
1048              continue LOOP;
1049            }
1050            else
1051            {
1052              switch (sameDocMany(o, f))
1053              {
1054                case SAME_DOC:
1055                {
1056                  saveIDRefMany(o, f);
1057                  continue LOOP;
1058                }
1059                case CROSS_DOC:
1060                {
1061                  break;
1062                }
1063                default:
1064                {
1065                  continue LOOP;
1066                }
1067              }
1068            }
1069            break;
1070          }
1071          case OBJECT_ELEMENT_SINGLE_UNSETTABLE:
1072          case OBJECT_ELEMENT_SINGLE:
1073          {
1074            if (contentKind == ExtendedMetaData.SIMPLE_CONTENT)
1075            {
1076              content = getElementReferenceSingleSimple(o, f);
1077              continue LOOP;
1078            }
1079            break;
1080          }
1081          case OBJECT_ELEMENT_MANY:
1082          {
1083            if (contentKind == ExtendedMetaData.SIMPLE_CONTENT)
1084            {
1085              content = getElementReferenceManySimple(o, f);
1086              continue LOOP;
1087            }
1088            break;
1089          }
1090          case OBJECT_ELEMENT_IDREF_SINGLE_UNSETTABLE:
1091          case OBJECT_ELEMENT_IDREF_SINGLE:
1092          {
1093            if (contentKind == ExtendedMetaData.SIMPLE_CONTENT)
1094            {
1095              content = getElementIDRefSingleSimple(o, f);
1096              continue LOOP;
1097            }
1098            break;
1099          }
1100          case OBJECT_ELEMENT_IDREF_MANY:
1101          {
1102            if (contentKind == ExtendedMetaData.SIMPLE_CONTENT)
1103            {
1104              content = getElementIDRefManySimple(o, f);
1105              continue LOOP;
1106            }
1107            break;
1108          }
1109          case DATATYPE_ATTRIBUTE_MANY:
1110          {
1111            break;
1112          }
1113          case OBJECT_CONTAIN_MANY_UNSETTABLE:
1114          case DATATYPE_MANY:
1115          {
1116            if (isEmpty(o, f))
1117            {
1118              saveManyEmpty(o, f);
1119              continue LOOP;
1120            }
1121            break;
1122          }
1123          case OBJECT_CONTAIN_SINGLE_UNSETTABLE:
1124          case OBJECT_CONTAIN_SINGLE:
1125          case OBJECT_CONTAIN_MANY:
1126          case ELEMENT_FEATURE_MAP:
1127          {
1128            break;
1129          }
1130          case ATTRIBUTE_FEATURE_MAP:
1131          {
1132            saveAttributeFeatureMap(o, f);
1133            continue LOOP;
1134          }
1135          default:
1136          {
1137            continue LOOP;
1138          }
1139        }
1140
1141        // We only get here if we should do this.
1142
//
1143
if (elementFeatures == null)
1144        {
1145          elementFeatures = new int[features.length];
1146        }
1147        elementFeatures[elementCount++] = i;
1148      }
1149    }
1150
1151    processAttributeExtensions(o);
1152
1153    if (elementFeatures == null)
1154    {
1155      if (content == null)
1156      {
1157        content = getContent(o, features);
1158      }
1159
1160      if (content == null)
1161      {
1162        endSaveFeatures(o, EMPTY_ELEMENT, null);
1163        return false;
1164      }
1165      else
1166      {
1167        endSaveFeatures(o, CONTENT_ELEMENT, content);
1168        return true;
1169      }
1170    }
1171
1172    // Process XML elements
1173
for (int i = 0; i < elementCount; i++ )
1174    {
1175      int kind = featureKinds[elementFeatures[i]];
1176      EStructuralFeature f = features[elementFeatures[i]];
1177      switch (kind)
1178      {
1179        case DATATYPE_SINGLE_NILLABLE:
1180        {
1181          saveNil(o, f);
1182          break;
1183        }
1184        case ELEMENT_FEATURE_MAP:
1185        {
1186          saveElementFeatureMap(o, f);
1187          break;
1188        }
1189        case DATATYPE_MANY:
1190        {
1191          saveDataTypeMany(o, f);
1192          break;
1193        }
1194        case DATATYPE_ATTRIBUTE_MANY:
1195        {
1196          saveDataTypeAttributeMany(o, f);
1197          break;
1198        }
1199        case DATATYPE_ELEMENT_SINGLE:
1200        {
1201          saveDataTypeElementSingle(o, f);
1202          break;
1203        }
1204        case OBJECT_CONTAIN_SINGLE_UNSETTABLE:
1205        {
1206          if (isNil(o, f))
1207          {
1208            saveNil(o, f);
1209            break;
1210          }
1211          // it's intentional to keep going
1212
}
1213        case OBJECT_CONTAIN_SINGLE:
1214        {
1215          saveContainedSingle(o, f);
1216          break;
1217        }
1218        case OBJECT_CONTAIN_MANY_UNSETTABLE:
1219        case OBJECT_CONTAIN_MANY:
1220        {
1221          saveContainedMany(o, f);
1222          break;
1223        }
1224        case OBJECT_HREF_SINGLE_UNSETTABLE:
1225        {
1226          if (isNil(o, f))
1227          {
1228            saveNil(o, f);
1229            break;
1230          }
1231          // it's intentional to keep going
1232
}
1233        case OBJECT_HREF_SINGLE:
1234        {
1235          saveHRefSingle(o, f);
1236          break;
1237        }
1238        case OBJECT_HREF_MANY_UNSETTABLE:
1239        case OBJECT_HREF_MANY:
1240        {
1241          saveHRefMany(o, f);
1242          break;
1243        }
1244        case OBJECT_ELEMENT_SINGLE_UNSETTABLE:
1245        {
1246          if (isNil(o, f))
1247          {
1248            saveNil(o, f);
1249            break;
1250          }
1251          // it's intentional to keep going
1252
}
1253        case OBJECT_ELEMENT_SINGLE:
1254        {
1255          saveElementReferenceSingle(o, f);
1256          break;
1257        }
1258        case OBJECT_ELEMENT_MANY:
1259        {
1260          saveElementReferenceMany(o, f);
1261          break;
1262        }
1263        case OBJECT_ELEMENT_IDREF_SINGLE_UNSETTABLE:
1264        {
1265          if (isNil(o, f))
1266          {
1267            saveNil(o, f);
1268            break;
1269          }
1270          // it's intentional to keep going
1271
}
1272        case OBJECT_ELEMENT_IDREF_SINGLE:
1273        {
1274          saveElementIDRefSingle(o, f);
1275          break;
1276        }
1277        case OBJECT_ELEMENT_IDREF_MANY:
1278        {
1279          saveElementIDRefMany(o, f);
1280          break;
1281        }
1282      }
1283    }
1284    endSaveFeatures(o, 0, null);
1285    return true;
1286  }
1287
1288  protected void endSaveFeatures(EObject o, int elementType, String JavaDoc content)
1289  {
1290    if (processElementExtensions(o))
1291    {
1292      if (o instanceof AnyType)
1293      {
1294        helper.popContext();
1295      }
1296      if (!toDOM)
1297      {
1298        doc.endElement();
1299      }
1300    }
1301    else
1302    {
1303      switch (elementType)
1304      {
1305        case EMPTY_ELEMENT:
1306        {
1307          if (!toDOM)
1308          {
1309            doc.endEmptyElement();
1310          }
1311          break;
1312        }
1313        case CONTENT_ELEMENT:
1314        {
1315          if (!toDOM)
1316          {
1317            doc.endContentElement(content);
1318          }
1319          break;
1320        }
1321        default:
1322        {
1323          if (o instanceof AnyType)
1324          {
1325            helper.popContext();
1326          }
1327          if (!toDOM)
1328          {
1329            doc.endElement();
1330          }
1331          break;
1332        }
1333      }
1334    }
1335    if (toDOM)
1336    {
1337      currentNode = currentNode.getParentNode();
1338    }
1339  }
1340  
1341  /**
1342   * Returns true if there were extensions for the specified object.
1343   */

1344  protected boolean processElementExtensions(EObject object)
1345  {
1346    if (eObjectToExtensionMap != null)
1347    {
1348      AnyType anyType = (AnyType)eObjectToExtensionMap.get(object);
1349      return anyType != null && saveElementFeatureMap(anyType, XMLTypePackage.eINSTANCE.getAnyType_Mixed());
1350    }
1351    else
1352    {
1353      return false;
1354    }
1355  }
1356
1357  /**
1358   */

1359  protected void processAttributeExtensions(EObject object)
1360  {
1361    if (eObjectToExtensionMap != null)
1362    {
1363      AnyType anyType = (AnyType)eObjectToExtensionMap.get(object);
1364      if (anyType != null)
1365      {
1366        saveAttributeFeatureMap(anyType, XMLTypePackage.eINSTANCE.getAnyType_AnyAttribute());
1367      }
1368    }
1369  }
1370
1371  protected void saveDataTypeSingle(EObject o, EStructuralFeature f)
1372  {
1373    Object JavaDoc value = helper.getValue(o, f);
1374    String JavaDoc svalue = getDatatypeValue(value, f, true);
1375    if (svalue != null)
1376    {
1377      if (!toDOM)
1378      {
1379        doc.addAttribute(helper.getQName(f), svalue);
1380      }
1381      else
1382      {
1383        helper.populateNameInfo(nameInfo, f);
1384        Attr JavaDoc attr = document.createAttributeNS(nameInfo.getNamespaceURI(), nameInfo.getQualifiedName());
1385        attr.setNodeValue(svalue);
1386        ((Element JavaDoc)currentNode).setAttributeNodeNS(attr);
1387        handler.recordValues(attr, o, f, value);
1388      }
1389    }
1390  }
1391
1392  protected boolean isNil(EObject o, EStructuralFeature f)
1393  {
1394    return helper.getValue(o, f) == null;
1395  }
1396
1397  protected boolean isEmpty(EObject o, EStructuralFeature f)
1398  {
1399    return ((List JavaDoc)helper.getValue(o, f)).isEmpty();
1400  }
1401
1402  protected void saveNil(EObject o, EStructuralFeature f)
1403  {
1404    if (!toDOM)
1405    {
1406      saveNil(f);
1407    }
1408    else
1409    {
1410      declareXSI = true;
1411      helper.populateNameInfo(nameInfo, f);
1412      Element JavaDoc elem = document.createElementNS(nameInfo.getNamespaceURI(), nameInfo.getQualifiedName());
1413      elem.setAttributeNS(ExtendedMetaData.XSI_URI, XSI_NIL, "true");
1414      currentNode.appendChild(elem);
1415      handler.recordValues(currentNode.getLastChild(), o, f, null);
1416    }
1417  }
1418  
1419  protected void saveNil(EStructuralFeature f)
1420  {
1421    declareXSI = true;
1422    doc.saveNilElement(helper.getQName(f));
1423  }
1424  
1425  protected void saveManyEmpty(EObject o, EStructuralFeature f)
1426  {
1427    if (!toDOM)
1428    {
1429      saveManyEmpty(f);
1430    }
1431    else
1432    {
1433      helper.populateNameInfo(nameInfo, f);
1434      Attr JavaDoc attr = document.createAttributeNS(nameInfo.getNamespaceURI(), nameInfo.getQualifiedName());
1435      ((Element JavaDoc)currentNode).setAttributeNodeNS(attr);
1436      handler.recordValues(attr, o, f, null);
1437    }
1438  }
1439  
1440  protected void saveManyEmpty(EStructuralFeature f)
1441  {
1442      doc.addAttribute(helper.getQName(f), "");
1443  }
1444
1445  protected void saveDataTypeMany(EObject o, EStructuralFeature f)
1446  {
1447    List JavaDoc values = (List JavaDoc)helper.getValue(o, f);
1448    int size = values.size();
1449    if (size > 0)
1450    {
1451      // for performance reasons saveNil and saveElement are not used
1452
if (!toDOM)
1453      {
1454        EDataType d = (EDataType)f.getEType();
1455        EPackage ePackage = d.getEPackage();
1456        EFactory fac = ePackage.getEFactoryInstance();
1457        String JavaDoc name = helper.getQName(f);
1458        for (int i = 0; i < size; ++i)
1459        {
1460          Object JavaDoc value = values.get(i);
1461          if (value == null)
1462          {
1463            doc.startElement(name);
1464            doc.addAttribute(XSI_NIL, "true");
1465            doc.endEmptyElement();
1466            declareXSI = true;
1467          }
1468          else
1469          {
1470            String JavaDoc svalue = helper.convertToString(fac, d, value);
1471            if (escape != null)
1472            {
1473              svalue = escape.convert(svalue);
1474            }
1475            doc.saveDataValueElement(name, svalue);
1476          }
1477        }
1478      }
1479      else
1480      {
1481        EDataType d = (EDataType)f.getEType();
1482        EPackage ePackage = d.getEPackage();
1483        EFactory fac = ePackage.getEFactoryInstance();
1484        helper.populateNameInfo(nameInfo, f);
1485        for (int i = 0; i < size; ++i)
1486        {
1487          Object JavaDoc value = values.get(i);
1488          if (value == null)
1489          {
1490            Element JavaDoc elem = document.createElementNS(nameInfo.getNamespaceURI(), nameInfo.getQualifiedName());
1491            elem.setAttributeNS(XMLResource.XSI_URI, XSI_NIL, "true");
1492            currentNode.appendChild(elem);
1493            handler.recordValues(elem, o, f, null);
1494            declareXSI = true;
1495          }
1496          else
1497          {
1498            Element JavaDoc elem = document.createElementNS(nameInfo.getNamespaceURI(), nameInfo.getQualifiedName());
1499            Node JavaDoc text = document.createTextNode(helper.convertToString(fac, d, value));
1500            elem.appendChild(text);
1501            currentNode.appendChild(elem);
1502            handler.recordValues(elem, o, f, value);
1503            handler.recordValues(text, o, f, value);
1504          }
1505        }
1506      }
1507    }
1508  }
1509
1510  protected void saveDataTypeAttributeMany(EObject o, EStructuralFeature f)
1511  {
1512    List JavaDoc values = (List JavaDoc)helper.getValue(o, f);
1513    int size = values.size();
1514    if (size > 0)
1515    {
1516      EDataType d = (EDataType)f.getEType();
1517      EPackage ePackage = d.getEPackage();
1518      EFactory fac = ePackage.getEFactoryInstance();
1519      StringBuffer JavaDoc stringValues = new StringBuffer JavaDoc();
1520      for (int i = 0; i < size; ++i)
1521      {
1522        Object JavaDoc value = values.get(i);
1523        if (value != null)
1524        {
1525          String JavaDoc svalue = helper.convertToString(fac, d, value);
1526          if (escape != null)
1527          {
1528            svalue = escape.convert(svalue);
1529          }
1530          if (i > 0)
1531          {
1532            stringValues.append(' ');
1533          }
1534          stringValues.append(svalue);
1535        }
1536      }
1537      if (!toDOM)
1538      {
1539        String JavaDoc name = helper.getQName(f);
1540        doc.startAttribute(name);
1541        doc.addAttributeContent(stringValues.toString());
1542        doc.endAttribute();
1543      }
1544      else
1545      {
1546        helper.populateNameInfo(nameInfo, f);
1547        Attr JavaDoc attr = document.createAttributeNS(nameInfo.getNamespaceURI(), nameInfo.getQualifiedName());
1548        String JavaDoc value = stringValues.toString();
1549        attr.setNodeValue(value);
1550        ((Element JavaDoc)currentNode).setAttributeNodeNS(attr);
1551        handler.recordValues(attr, o, f, value);
1552      }
1553    }
1554  }
1555
1556  protected void saveEObjectSingle(EObject o, EStructuralFeature f)
1557  {
1558    EObject value = (EObject)helper.getValue(o, f);
1559    if (value != null)
1560    {
1561      String JavaDoc id = helper.getHREF(value);
1562      if (id != null)
1563      {
1564        if (escapeURI != null)
1565        {
1566          id = escapeURI.convert(id);
1567        }
1568        buffer.setLength(0);
1569        if (!id.startsWith("#"))
1570        {
1571          EClass eClass = value.eClass();
1572          EClass expectedType = (EClass)f.getEType();
1573          if (saveTypeInfo ? xmlTypeInfo.shouldSaveType(eClass, expectedType, f) : eClass != expectedType && expectedType.isAbstract())
1574          {
1575            buffer.append(helper.getQName(eClass));
1576            buffer.append(" ");
1577          }
1578        }
1579        buffer.append(id);
1580        if (!toDOM)
1581        {
1582          String JavaDoc name = helper.getQName(f);
1583          doc.startAttribute(name);
1584          doc.addAttributeContent(buffer.toString());
1585          doc.endAttribute();
1586        }
1587        else
1588        {
1589          helper.populateNameInfo(nameInfo, f);
1590          Attr JavaDoc attr = document.createAttributeNS(nameInfo.getNamespaceURI(), nameInfo.getQualifiedName());
1591          attr.setNodeValue(buffer.toString());
1592          ((Element JavaDoc)currentNode).setAttributeNodeNS(attr);
1593          handler.recordValues(attr, o, f, value);
1594        }
1595      }
1596    }
1597  }
1598
1599  protected void saveEObjectMany(EObject o, EStructuralFeature f)
1600  {
1601    InternalEList values = (InternalEList)helper.getValue(o, f);
1602
1603    if (!values.isEmpty())
1604    {
1605      buffer.setLength(0);
1606      for (Iterator JavaDoc i = values.basicIterator();;)
1607      {
1608        EObject value = (EObject)i.next();
1609        String JavaDoc id = helper.getHREF(value);
1610        if (id != null)
1611        {
1612          if (escapeURI != null)
1613          {
1614            id = escapeURI.convert(id);
1615          }
1616          if (!id.startsWith("#"))
1617          {
1618            EClass eClass = value.eClass();
1619            EClass expectedType = (EClass)f.getEType();
1620            if (saveTypeInfo ? xmlTypeInfo.shouldSaveType(eClass, expectedType, f) : eClass != expectedType && expectedType.isAbstract())
1621            {
1622              buffer.append(helper.getQName(eClass));
1623              buffer.append(" ");
1624            }
1625          }
1626          buffer.append(id);
1627        }
1628        if (i.hasNext())
1629        {
1630          buffer.append(" ");
1631        }
1632        else
1633        {
1634          break;
1635        }
1636      }
1637
1638      if (!toDOM)
1639      {
1640        String JavaDoc name = helper.getQName(f);
1641        doc.startAttribute(name);
1642        doc.addAttributeContent(buffer.toString());
1643        doc.endAttribute();
1644      }
1645      else
1646      {
1647        helper.populateNameInfo(nameInfo, f);
1648        Attr JavaDoc attr = document.createAttributeNS(nameInfo.getNamespaceURI(), nameInfo.getQualifiedName());
1649        attr.setNodeValue(buffer.toString());
1650        ((Element JavaDoc)currentNode).setAttributeNodeNS(attr);
1651        handler.recordValues(attr, o, f, values);
1652      }
1653    }
1654  }
1655
1656  protected void saveIDRefSingle(EObject o, EStructuralFeature f)
1657  {
1658    EObject value = (EObject)helper.getValue(o, f);
1659    if (value != null)
1660    {
1661      String JavaDoc id = helper.getIDREF(value);
1662      if (!toDOM)
1663      {
1664        String JavaDoc name = helper.getQName(f);
1665        doc.addAttribute(name, id);
1666      }
1667      else
1668      {
1669        helper.populateNameInfo(nameInfo, f);
1670        Attr JavaDoc attr = document.createAttributeNS(nameInfo.getNamespaceURI(), nameInfo.getQualifiedName());
1671        attr.setNodeValue(id);
1672        ((Element JavaDoc)currentNode).setAttributeNodeNS(attr);
1673        handler.recordValues(attr, o, f, value);
1674      }
1675    }
1676  }
1677
1678  protected void saveIDRefMany(EObject o, EStructuralFeature f)
1679  {
1680    InternalEList values = (InternalEList)helper.getValue(o, f);
1681    if (!values.isEmpty())
1682    {
1683      buffer.setLength(0);
1684      StringBuffer JavaDoc ids = buffer;
1685      for (Iterator JavaDoc i = values.basicIterator();;)
1686      {
1687        EObject value = (EObject)i.next();
1688        String JavaDoc id = helper.getIDREF(value);
1689        ids.append(id);
1690        if (i.hasNext())
1691        {
1692          ids.append(" ");
1693        }
1694        else
1695        {
1696          break;
1697        }
1698      }
1699      if (!toDOM)
1700      {
1701        String JavaDoc name = helper.getQName(f);
1702        doc.addAttribute(name, ids.toString());
1703      }
1704      else
1705      {
1706        helper.populateNameInfo(nameInfo, f);
1707        Attr JavaDoc attr = document.createAttributeNS(nameInfo.getNamespaceURI(), nameInfo.getQualifiedName());
1708        attr.setNodeValue(ids.toString());
1709        ((Element JavaDoc)currentNode).setAttributeNodeNS(attr);
1710        handler.recordValues(attr, o, f, values);
1711      }
1712    }
1713  }
1714
1715  protected void saveElementReference(EObject remote, EStructuralFeature f)
1716  {
1717    String JavaDoc href = helper.getHREF(remote);
1718    if (href != null)
1719    {
1720      if (escapeURI != null)
1721      {
1722        href = escapeURI.convert(href);
1723      }
1724      if (!toDOM)
1725      {
1726        doc.startElement(helper.getQName(f));
1727      }
1728      else
1729      {
1730        helper.populateNameInfo(nameInfo, f);
1731        Element JavaDoc elem = document.createElementNS(nameInfo.getNamespaceURI(), nameInfo.getQualifiedName());
1732        Node JavaDoc text = document.createTextNode(href);
1733        elem.appendChild(text);
1734        currentNode = currentNode.appendChild(elem);
1735        handler.recordValues(elem, remote.eContainer(), f, remote);
1736        handler.recordValues(text, remote.eContainer(), f, remote);
1737      }
1738      EClass eClass = remote.eClass();
1739      EClass expectedType = (EClass)f.getEType();
1740      if (saveTypeInfo ? xmlTypeInfo.shouldSaveType(eClass, expectedType, f) : eClass != expectedType && expectedType.isAbstract())
1741      {
1742        saveTypeAttribute(eClass);
1743      }
1744      if (!toDOM)
1745      {
1746        doc.endContentElement(href);
1747      }
1748      else
1749      {
1750        currentNode = currentNode.getParentNode();
1751      }
1752    }
1753  }
1754
1755  protected void saveElementReferenceSingle(EObject o, EStructuralFeature f)
1756  {
1757    EObject value = (EObject)helper.getValue(o, f);
1758    if (value != null)
1759    {
1760      saveElementReference(value, f);
1761    }
1762  }
1763
1764  protected void saveElementReferenceMany(EObject o, EStructuralFeature f)
1765  {
1766    InternalEList values = (InternalEList)helper.getValue(o, f);
1767    int size = values.size();
1768    for (int i = 0; i < size; i++)
1769    {
1770      saveElementReference((EObject)values.basicGet(i), f);
1771    }
1772  }
1773
1774  protected String JavaDoc getElementReferenceSingleSimple(EObject o, EStructuralFeature f)
1775  {
1776    EObject value = (EObject)helper.getValue(o, f);
1777    String JavaDoc svalue = helper.getHREF(value);
1778    if (escapeURI != null && svalue != null)
1779    {
1780      svalue = escapeURI.convert(svalue);
1781    }
1782    if (toDOM)
1783    {
1784      Node JavaDoc text = document.createTextNode(svalue);
1785      currentNode.appendChild(text);
1786      handler.recordValues(text, o, f, value);
1787    }
1788    return svalue;
1789  }
1790
1791  protected String JavaDoc getElementReferenceManySimple(EObject o, EStructuralFeature f)
1792  {
1793    InternalEList values = (InternalEList)helper.getValue(o, f);
1794    buffer.setLength(0);
1795    StringBuffer JavaDoc result = buffer;
1796    int size = values.size();
1797    String JavaDoc href = null;
1798    for (int i = 0; i < size; i++)
1799    {
1800      href = helper.getHREF(((EObject)values.basicGet(i)));
1801      if (escapeURI != null && href != null)
1802      {
1803        href = escapeURI.convert(href);
1804      }
1805      result.append(href);
1806      result.append(' ');
1807    }
1808    String JavaDoc svalue = result.substring(0, result.length() - 1);
1809    if (toDOM)
1810    {
1811      Node JavaDoc text = document.createTextNode(svalue);
1812      currentNode.appendChild(text);
1813      handler.recordValues(text, o, f, values);
1814    }
1815    return svalue;
1816  }
1817  
1818  protected void saveElementIDRef(EObject o, EObject target, EStructuralFeature f)
1819  {
1820    if (!toDOM)
1821    {
1822      saveElementIDRef(target, f);
1823    }
1824    else
1825    {
1826      String JavaDoc id = helper.getIDREF(target);
1827      helper.populateNameInfo(nameInfo, f);
1828      Element JavaDoc elem = document.createElementNS(nameInfo.getNamespaceURI(), nameInfo.getQualifiedName());
1829      Node JavaDoc text = document.createTextNode(id);
1830      elem.appendChild(text);
1831      currentNode.appendChild(elem);
1832      handler.recordValues(elem, o, f, target);
1833      handler.recordValues(text, o, f, target);
1834    }
1835  }
1836
1837  protected void saveElementIDRef(EObject target, EStructuralFeature f)
1838  {
1839    String JavaDoc name = helper.getQName(f);
1840    String JavaDoc id = helper.getIDREF(target);
1841    doc.saveDataValueElement(name, id);
1842  }
1843
1844  protected void saveElementIDRefSingle(EObject o, EStructuralFeature f)
1845  {
1846    EObject value = (EObject)helper.getValue(o, f);
1847    if (value != null)
1848    {
1849      saveElementIDRef(o, value, f);
1850    }
1851  }
1852
1853  protected void saveElementIDRefMany(EObject o, EStructuralFeature f)
1854  {
1855    InternalEList values = (InternalEList)helper.getValue(o, f);
1856    int size = values.size();
1857    for (int i = 0; i < size; i++)
1858    {
1859      saveElementIDRef(o, (EObject)values.basicGet(i), f);
1860    }
1861  }
1862
1863  protected String JavaDoc getElementIDRefSingleSimple(EObject o, EStructuralFeature f)
1864  {
1865    EObject value = (EObject)helper.getValue(o, f);
1866    String JavaDoc svalue = helper.getIDREF(value);
1867    if (toDOM)
1868    {
1869      Node JavaDoc text = document.createTextNode(svalue);
1870      currentNode.appendChild(text);
1871      handler.recordValues(text, o, f, value);
1872    }
1873    return svalue;
1874  }
1875
1876  protected String JavaDoc getElementIDRefManySimple(EObject o, EStructuralFeature f)
1877  {
1878    InternalEList values = (InternalEList)helper.getValue(o, f);
1879    buffer.setLength(0);
1880    StringBuffer JavaDoc result = buffer;
1881    for (int i = 0, size = values.size(); i < size; i++)
1882    {
1883      result.append(helper.getIDREF((EObject)values.basicGet(i)));
1884      result.append(' ');
1885    }
1886    String JavaDoc svalue = result.substring(0, result.length() - 1);
1887    if (toDOM)
1888    {
1889      Node JavaDoc text = document.createTextNode(svalue);
1890      currentNode.appendChild(text);
1891      handler.recordValues(text, o, f, values);
1892    }
1893    return svalue;
1894  }
1895
1896/*
1897  protected void saveElementIDRefMany(EObject o, EStructuralFeature f)
1898  {
1899    InternalEList values = (InternalEList)helper.getValue(o, f);
1900    if (!values.isEmpty())
1901    {
1902      String name = helper.getQName(f);
1903      StringBuffer ids = new StringBuffer(values.size() * 10);
1904      for (Iterator i = values.basicIterator();;)
1905      {
1906        EObject value = (EObject)i.next();
1907        String id = helper.getIDREF(value);
1908        ids.append(id);
1909        if (i.hasNext())
1910        {
1911          ids.append(" ");
1912        }
1913        else
1914        {
1915          break;
1916        }
1917      }
1918      doc.startElement(name);
1919      doc.endContentElement(ids.toString());
1920    }
1921  }
1922*/

1923
1924  protected void saveHref(EObject remote, EStructuralFeature f)
1925  {
1926    String JavaDoc href = helper.getHREF(remote);
1927    if (href != null)
1928    {
1929      if (escapeURI != null)
1930      {
1931        href = escapeURI.convert(href);
1932      }
1933      if (!toDOM)
1934      {
1935        String JavaDoc name = helper.getQName(f);
1936        doc.startElement(name);
1937      }
1938      else
1939      {
1940        helper.populateNameInfo(nameInfo, f);
1941        Element JavaDoc elem = document.createElementNS(nameInfo.getNamespaceURI(), nameInfo.getQualifiedName());
1942        currentNode = currentNode.appendChild(elem);
1943        handler.recordValues(elem, remote.eContainer(), f, remote);
1944      }
1945      EClass eClass = remote.eClass();
1946      EClass expectedType = (EClass) f.getEType();
1947      if (saveTypeInfo ? xmlTypeInfo.shouldSaveType(eClass, expectedType, f) : eClass != expectedType && expectedType.isAbstract())
1948      {
1949        saveTypeAttribute(eClass);
1950      }
1951      if (!toDOM)
1952      {
1953        doc.addAttribute(XMLResource.HREF, href);
1954        doc.endEmptyElement();
1955      }
1956      else
1957      {
1958        ((Element JavaDoc)currentNode).setAttributeNS(null, XMLResource.HREF, href);
1959        currentNode = currentNode.getParentNode();
1960      }
1961    }
1962  }
1963
1964  protected void saveHRefSingle(EObject o, EStructuralFeature f)
1965  {
1966    EObject value = (EObject)helper.getValue(o, f);
1967    if (value != null)
1968    {
1969      saveHref(value, f);
1970    }
1971  }
1972
1973  protected void saveHRefMany(EObject o, EStructuralFeature f)
1974  {
1975    InternalEList values = (InternalEList)helper.getValue(o, f);
1976    int size = values.size();
1977    for (int i = 0; i < size; i++)
1978    {
1979      saveHref((EObject)values.basicGet(i), f);
1980    }
1981  }
1982
1983  protected void saveContainedSingle(EObject o, EStructuralFeature f)
1984  {
1985    EObject value = (EObject)helper.getValue(o, f);
1986    if (value != null)
1987    {
1988      saveElement(value, f);
1989    }
1990  }
1991
1992  protected void saveContainedMany(EObject o, EStructuralFeature f)
1993  {
1994    List JavaDoc values = (List JavaDoc)helper.getValue(o, f);
1995    int size = values.size();
1996    for (int i = 0; i < size; i++)
1997    {
1998      EObject value = (EObject)values.get(i);
1999      if (value != null)
2000      {
2001        saveElement(value, f);
2002      }
2003    }
2004  }
2005
2006  protected void saveFeatureMapElementReference(EObject o, EReference f)
2007  {
2008    saveElementReference(o, f);
2009  }
2010  
2011  protected boolean saveElementFeatureMap(EObject o, EStructuralFeature f)
2012  {
2013    List JavaDoc values = (List JavaDoc)helper.getValue(o, f);
2014    int size = values.size();
2015    for (int i = 0; i < size; i++)
2016    {
2017      FeatureMap.Entry entry = (FeatureMap.Entry)values.get(i);
2018      EStructuralFeature entryFeature = entry.getEStructuralFeature();
2019      Object JavaDoc value = entry.getValue();
2020      if (entryFeature instanceof EReference)
2021      {
2022        if (value == null)
2023        {
2024          saveNil(o, entryFeature);
2025        }
2026        else
2027        {
2028          EReference referenceEntryFeature = (EReference)entryFeature;
2029          if (referenceEntryFeature.isContainment())
2030          {
2031            saveElement((EObject)value, entryFeature);
2032          }
2033          else if (referenceEntryFeature.isResolveProxies())
2034          {
2035            saveFeatureMapElementReference((EObject)value, referenceEntryFeature);
2036          }
2037          else
2038          {
2039            saveElementIDRef(o, (EObject)value, entryFeature);
2040          }
2041        }
2042      }
2043      else
2044      {
2045        if (entryFeature == XMLTypePackage.eINSTANCE.getXMLTypeDocumentRoot_Text())
2046        {
2047          String JavaDoc svalue = value.toString();
2048          if (escape != null)
2049          {
2050            svalue = escape.convertText(svalue);
2051          }
2052          if (!toDOM)
2053          {
2054            doc.addText(svalue);
2055          }
2056          else
2057          {
2058            Node JavaDoc text = document.createTextNode(svalue);
2059            currentNode.appendChild(text);
2060            handler.recordValues(text, o, f, entry);
2061          }
2062        }
2063        else if (entryFeature == XMLTypePackage.eINSTANCE.getXMLTypeDocumentRoot_CDATA())
2064        {
2065          String JavaDoc stringValue = value.toString();
2066          if (escape != null)
2067          {
2068            stringValue = escape.convertLines(stringValue);
2069          }
2070          if (!toDOM)
2071          {
2072            doc.addCDATA(stringValue);
2073          }
2074          else
2075          {
2076            Node JavaDoc cdata = document.createCDATASection(stringValue);
2077            currentNode.appendChild(cdata);
2078            handler.recordValues(cdata, o, f, entry);
2079          }
2080        }
2081        else if (entryFeature == XMLTypePackage.eINSTANCE.getXMLTypeDocumentRoot_Comment())
2082        {
2083          String JavaDoc stringValue = value.toString();
2084          if (escape != null)
2085          {
2086            stringValue = escape.convertLines(stringValue);
2087          }
2088          if (!toDOM)
2089          {
2090            doc.addComment(stringValue);
2091          }
2092          else
2093          {
2094            // TODO comments are not sent to recordValues
2095
currentNode.appendChild(document.createComment(stringValue));
2096          }
2097        }
2098        else
2099        {
2100          saveElement(o, value, entryFeature);
2101        }
2102      }
2103    }
2104    return size > 0;
2105  }
2106
2107  protected void saveAttributeFeatureMap(EObject o, EStructuralFeature f)
2108  {
2109    List JavaDoc values = (List JavaDoc)helper.getValue(o, f);
2110    int size = values.size();
2111    Set JavaDoc repeats = null;
2112    for (int i = 0; i < size; i++)
2113    {
2114      FeatureMap.Entry entry = (FeatureMap.Entry)values.get(i);
2115      EStructuralFeature entryFeature = entry.getEStructuralFeature();
2116      if (entryFeature instanceof EReference)
2117      {
2118        EReference referenceEntryFeature = (EReference)entryFeature;
2119        if (referenceEntryFeature.isMany())
2120        {
2121          if (repeats == null)
2122          {
2123            repeats = new HashSet JavaDoc();
2124          }
2125          else if (repeats.contains(referenceEntryFeature))
2126          {
2127            continue;
2128          }
2129          
2130          repeats.add(referenceEntryFeature);
2131          
2132          if (referenceEntryFeature.isResolveProxies())
2133          {
2134            saveEObjectMany(o, entryFeature);
2135          }
2136          else
2137          {
2138            saveIDRefMany(o, entryFeature);
2139          }
2140        }
2141        else
2142        {
2143          if (referenceEntryFeature.isResolveProxies())
2144          {
2145            saveEObjectSingle(o, entryFeature);
2146          }
2147          else
2148          {
2149            saveIDRefSingle(o, entryFeature);
2150          }
2151        }
2152      }
2153      else
2154      {
2155        Object JavaDoc value = entry.getValue();
2156        String JavaDoc svalue = getDatatypeValue(value, entryFeature, true);
2157        if (!toDOM)
2158        {
2159          doc.addAttribute(helper.getQName(entryFeature), svalue);
2160        }
2161        else
2162        {
2163          helper.populateNameInfo(nameInfo, entryFeature);
2164          Attr JavaDoc attr = document.createAttributeNS(nameInfo.getNamespaceURI(), nameInfo.getQualifiedName());
2165          attr.setNodeValue(svalue);
2166          ((Element JavaDoc)currentNode).setAttributeNodeNS(attr);
2167          handler.recordValues(attr, o, f, value);
2168        }
2169      }
2170    }
2171  }
2172
2173  protected int sameDocSingle(EObject o, EStructuralFeature f)
2174  {
2175    InternalEObject value = (InternalEObject)helper.getValue(o, f);
2176    if (value == null)
2177    {
2178      return SKIP;
2179    }
2180    else if (value.eIsProxy())
2181    {
2182      return CROSS_DOC;
2183    }
2184    else
2185    {
2186      Resource res = value.eResource();
2187      return res == helper.getResource() ? SAME_DOC : CROSS_DOC;
2188    }
2189  }
2190
2191  protected int sameDocMany(EObject o, EStructuralFeature f)
2192  {
2193    InternalEList values = (InternalEList)helper.getValue(o, f);
2194    if (values.isEmpty())
2195    {
2196      return SKIP;
2197    }
2198
2199    for (Iterator JavaDoc i = values.basicIterator(); i.hasNext(); )
2200    {
2201      InternalEObject value = (InternalEObject)i.next();
2202      if (value.eIsProxy() || value.eResource() != helper.getResource()) {
2203        return CROSS_DOC;
2204      }
2205    }
2206
2207    return SAME_DOC;
2208  }
2209
2210  protected String JavaDoc getContent(EObject o, EStructuralFeature[] features)
2211  {
2212    if (map == null)
2213    {
2214      return null;
2215    }
2216
2217    for (int i = 0; i < features.length; i++)
2218    {
2219      EStructuralFeature feature = features[i];
2220      XMLResource.XMLInfo info = map.getInfo(feature);
2221      if (info != null && info.getXMLRepresentation() == XMLResource.XMLInfo.CONTENT)
2222      {
2223        Object JavaDoc value = helper.getValue(o, feature);
2224        String JavaDoc svalue = getDatatypeValue(value, feature, false);
2225        if (toDOM)
2226        {
2227          Node JavaDoc text = document.createTextNode(svalue);
2228          currentNode.appendChild(text);
2229          handler.recordValues(text, o, feature, value);
2230        }
2231        return svalue;
2232      }
2233    }
2234    return null;
2235  }
2236
2237  protected void saveDataTypeElementSingle(EObject o, EStructuralFeature f)
2238  {
2239    saveElement(o, helper.getValue(o, f), f);
2240  }
2241
2242  protected String JavaDoc getDataTypeElementSingleSimple(EObject o, EStructuralFeature f)
2243  {
2244    Object JavaDoc value = helper.getValue(o, f);
2245    String JavaDoc svalue = getDatatypeValue(value, f, false);
2246    if (toDOM)
2247    {
2248      Node JavaDoc text = document.createTextNode(svalue);
2249      currentNode.appendChild(text);
2250      handler.recordValues(text, o, f, value);
2251    }
2252    return svalue;
2253  }
2254
2255  protected void saveElementID(EObject o)
2256  {
2257    String JavaDoc id = helper.getID(o);
2258    if (id != null)
2259    {
2260      if (!toDOM)
2261      {
2262        doc.addAttribute(idAttributeName, id);
2263      }
2264      else
2265      {
2266        Attr JavaDoc attr = document.createAttributeNS(idAttributeNS, idAttributeName);
2267        attr.setNodeValue(id);
2268        ((Element JavaDoc)currentNode).setAttributeNodeNS(attr);
2269        handler.recordValues(attr, o, null, o);
2270      }
2271    }
2272    saveFeatures(o);
2273  }
2274
2275  protected static class Lookup
2276  {
2277    protected static final int SHIFT = 10;
2278    protected static final int SIZE = 1 << SHIFT; // 2^N
2279
protected static final int MASK = SIZE - 1; // 2^N-1
2280

2281    protected EClass[] classes;
2282    protected EStructuralFeature[][] features;
2283    protected int[][] featureKinds;
2284    protected XMLResource.XMLMap map;
2285    protected ExtendedMetaData extendedMetaData;
2286    protected ArrayList JavaDoc docRoots = new ArrayList JavaDoc();
2287
2288    public Lookup(XMLResource.XMLMap map)
2289    {
2290      this(map, null);
2291    }
2292
2293    public Lookup(XMLResource.XMLMap map, ExtendedMetaData extendedMetaData)
2294    {
2295      this.map = map;
2296      this.extendedMetaData = extendedMetaData;
2297      classes = new EClass[SIZE];
2298      features = new EStructuralFeature[SIZE][];
2299      featureKinds = new int[SIZE][];
2300    }
2301    
2302    public EClass getDocumentRoot(EPackage epackage)
2303    {
2304      for (int i = 0; i < docRoots.size(); i += 2)
2305      {
2306        if (docRoots.get(i) == epackage)
2307        {
2308          return (EClass)docRoots.get(++i);
2309        }
2310      }
2311      docRoots.add(epackage);
2312      EClass docRoot = extendedMetaData.getDocumentRoot(epackage);
2313      docRoots.add(docRoot);
2314      return docRoot;
2315    }
2316    
2317    public EStructuralFeature[] getFeatures(EClass cls)
2318    {
2319      int index = getIndex(cls);
2320      EClass c = classes[index];
2321
2322      if (c == cls)
2323      {
2324        return features[index];
2325      }
2326
2327      EStructuralFeature[] featureList = listFeatures(cls);
2328      if (c == null)
2329      {
2330        classes[index] = cls;
2331        features[index] = featureList;
2332        featureKinds[index] = listKinds(featureList);
2333      }
2334      return featureList;
2335    }
2336
2337    public int[] getKinds(EClass cls, EStructuralFeature[] featureList)
2338    {
2339      int index = getIndex(cls);
2340      EClass c = classes[index];
2341
2342      if (c == cls)
2343      {
2344        return featureKinds[index];
2345      }
2346
2347      int[] kindsList = listKinds(featureList);
2348      if (c == null)
2349      {
2350        classes[index] = cls;
2351        features[index] = featureList;
2352        featureKinds[index] = kindsList;
2353      }
2354      return kindsList;
2355    }
2356    
2357    protected int getIndex(EClass cls)
2358    {
2359      String JavaDoc name = cls.getInstanceClassName();
2360      int index = 0;
2361      if (name != null)
2362      {
2363        index = name.hashCode() & MASK;
2364      }
2365      else
2366      {
2367        index = cls.hashCode() >> SHIFT & MASK;
2368      }
2369      return index;
2370    }
2371
2372    protected EStructuralFeature[] listFeatures(EClass cls)
2373    {
2374      if (extendedMetaData != null)
2375      {
2376        List JavaDoc f = new ArrayList JavaDoc();
2377        f.addAll(cls.getEAllStructuralFeatures());
2378        List JavaDoc orderedElements = extendedMetaData.getAllElements(cls);
2379        f.removeAll(orderedElements);
2380        f.addAll(orderedElements);
2381        return (EStructuralFeature[]) f.toArray(new EStructuralFeature[f.size()]);
2382      }
2383      else
2384      {
2385        List JavaDoc f = map == null ? cls.getEAllStructuralFeatures() : map.getFeatures(cls);
2386        return (EStructuralFeature[]) f.toArray(new EStructuralFeature[f.size()]);
2387      }
2388    }
2389
2390    protected int[] listKinds(EStructuralFeature[] featureList)
2391    {
2392      int[] kinds = new int[featureList.length];
2393      for (int i = featureList.length-1; i >= 0; i--)
2394      {
2395        kinds[i] = featureKind(featureList[i]);
2396      }
2397
2398      return kinds;
2399    }
2400
2401    protected int featureKind(EStructuralFeature f)
2402    {
2403      if (f.isTransient())
2404      {
2405        return TRANSIENT;
2406      }
2407
2408      boolean isMany = f.isMany();
2409      boolean isUnsettable = f.isUnsettable();
2410
2411      if (f instanceof EReference)
2412      {
2413        EReference r = (EReference)f;
2414        if (r.isContainment())
2415        {
2416          return
2417            isMany ?
2418              isUnsettable ? OBJECT_CONTAIN_MANY_UNSETTABLE : OBJECT_CONTAIN_MANY :
2419              isUnsettable ? OBJECT_CONTAIN_SINGLE_UNSETTABLE : OBJECT_CONTAIN_SINGLE;
2420        }
2421        EReference opposite = r.getEOpposite();
2422        if (opposite != null && opposite.isContainment())
2423        {
2424          return TRANSIENT;
2425        }
2426
2427        if (map != null)
2428        {
2429          XMLResource.XMLInfo info = map.getInfo(f);
2430          if (info != null && info.getXMLRepresentation() == XMLResource.XMLInfo.ELEMENT)
2431          {
2432            return
2433              isMany ?
2434                OBJECT_ELEMENT_MANY :
2435                r.isUnsettable() ?
2436                  OBJECT_ELEMENT_SINGLE_UNSETTABLE :
2437                  OBJECT_ELEMENT_SINGLE;
2438          }
2439        }
2440
2441        if (extendedMetaData != null)
2442        {
2443          switch (extendedMetaData.getFeatureKind(f))
2444          {
2445            case ExtendedMetaData.ATTRIBUTE_FEATURE:
2446            {
2447              return
2448                  r.isResolveProxies() ?
2449                    isMany ?
2450                      OBJECT_ATTRIBUTE_MANY :
2451                      OBJECT_ATTRIBUTE_SINGLE :
2452                    isMany ?
2453                      OBJECT_ATTRIBUTE_IDREF_MANY :
2454                      OBJECT_ATTRIBUTE_IDREF_SINGLE;
2455            }
2456            case ExtendedMetaData.SIMPLE_FEATURE:
2457            case ExtendedMetaData.ELEMENT_FEATURE:
2458            {
2459              return
2460                  r.isResolveProxies() ?
2461                    isMany ?
2462                      OBJECT_ELEMENT_MANY :
2463                      r.isUnsettable() ?
2464                        OBJECT_ELEMENT_SINGLE_UNSETTABLE :
2465                        OBJECT_ELEMENT_SINGLE :
2466                    isMany ?
2467                      OBJECT_ELEMENT_IDREF_MANY :
2468                      r.isUnsettable() ?
2469                        OBJECT_ELEMENT_IDREF_SINGLE_UNSETTABLE :
2470                        OBJECT_ELEMENT_IDREF_SINGLE;
2471            }
2472          }
2473        }
2474
2475        return
2476          isMany ?
2477            isUnsettable ? OBJECT_HREF_MANY_UNSETTABLE : OBJECT_HREF_MANY :
2478            isUnsettable ? OBJECT_HREF_SINGLE_UNSETTABLE : OBJECT_HREF_SINGLE;
2479      }
2480      else
2481      {
2482        // Attribute
2483
EDataType d = (EDataType) f.getEType();
2484        if (!d.isSerializable())
2485        {
2486          return TRANSIENT;
2487        }
2488
2489        if (d.getInstanceClass() == FeatureMap.Entry.class)
2490        {
2491          return
2492            extendedMetaData != null && extendedMetaData.getFeatureKind(f) == ExtendedMetaData.ATTRIBUTE_WILDCARD_FEATURE ?
2493              ATTRIBUTE_FEATURE_MAP :
2494              ELEMENT_FEATURE_MAP;
2495        }
2496
2497        if (extendedMetaData != null)
2498        {
2499          switch (extendedMetaData.getFeatureKind(f))
2500          {
2501            case ExtendedMetaData.SIMPLE_FEATURE:
2502            {
2503              return DATATYPE_ELEMENT_SINGLE;
2504            }
2505            case ExtendedMetaData.ELEMENT_FEATURE:
2506            {
2507              return f.isMany() ? DATATYPE_MANY : DATATYPE_ELEMENT_SINGLE;
2508            }
2509            case ExtendedMetaData.ATTRIBUTE_FEATURE:
2510            {
2511              return f.isMany() ? DATATYPE_ATTRIBUTE_MANY: DATATYPE_SINGLE;
2512            }
2513          }
2514        }
2515
2516        if (isMany)
2517        {
2518          return DATATYPE_MANY;
2519        }
2520
2521        if (isUnsettable && map == null)
2522        {
2523          return DATATYPE_SINGLE_NILLABLE;
2524        }
2525
2526        if (map == null)
2527        {
2528          return DATATYPE_SINGLE;
2529        }
2530        else
2531        {
2532          XMLResource.XMLInfo info = map.getInfo(f);
2533
2534          if (info != null && info.getXMLRepresentation() == XMLResource.XMLInfo.ELEMENT)
2535          {
2536            return DATATYPE_ELEMENT_SINGLE;
2537          }
2538          else if (info != null && info.getXMLRepresentation() == XMLResource.XMLInfo.CONTENT)
2539          {
2540            return DATATYPE_CONTENT_SINGLE;
2541          }
2542          else
2543          {
2544            if (isUnsettable)
2545              return DATATYPE_SINGLE_NILLABLE;
2546            else
2547              return DATATYPE_SINGLE;
2548          }
2549        }
2550      }
2551    }
2552  }
2553
2554  protected String JavaDoc getDatatypeValue(Object JavaDoc value, EStructuralFeature f, boolean isAttribute)
2555  {
2556    if (value == null)
2557    {
2558      return null;
2559    }
2560    EDataType d = (EDataType)f.getEType();
2561    EPackage ePackage = d.getEPackage();
2562    EFactory fac = ePackage.getEFactoryInstance();
2563    String JavaDoc svalue = helper.convertToString(fac, d, value);
2564    if (escape != null)
2565    {
2566      if (isAttribute)
2567      {
2568        svalue = escape.convert(svalue);
2569      }
2570      else
2571      {
2572        svalue = escape.convertText(svalue);
2573      }
2574    }
2575    return svalue;
2576  }
2577  
2578  private void saveElement(EObject o, Object JavaDoc value, EStructuralFeature f)
2579  {
2580    if (value == null)
2581    {
2582      saveNil(o, f);
2583    }
2584    else
2585    {
2586      String JavaDoc svalue = getDatatypeValue(value, f, false);
2587      if (!toDOM)
2588      {
2589        doc.saveDataValueElement(helper.getQName(f), svalue);
2590      }
2591      else
2592      {
2593        helper.populateNameInfo(nameInfo, f);
2594        Element JavaDoc elem = document.createElementNS(nameInfo.getNamespaceURI(), nameInfo.getQualifiedName());
2595        Node JavaDoc text = document.createTextNode(svalue);
2596        elem.appendChild(text);
2597        currentNode.appendChild(elem);
2598        handler.recordValues(elem, o, f, value);
2599        handler.recordValues(text, o, f, value);
2600      }
2601    }
2602  }
2603
2604  protected static class Escape
2605  {
2606    protected char[] value;
2607
2608    protected final char[] AMP = { '&', 'a', 'm', 'p', ';' };
2609    protected final char[] LESS = { '&', 'l', 't',';' };
2610    protected final char[] QUOTE = { '&', 'q', 'u', 'o', 't', ';' };
2611    protected final char[] LF = { '&', '#', 'x', 'A', ';' };
2612    protected final char[] CR = { '&', '#', 'x', 'D', ';' };
2613    protected final char[] TAB = { '&', '#', 'x', '9', ';' };
2614    protected final char[] LINE_FEED = System.getProperty("line.separator").toCharArray();
2615
2616    public Escape()
2617    {
2618      value = new char[100];
2619    }
2620
2621    /*
2622     * Convert:
2623     * & to &amp;
2624     * < to &lt;
2625     * " to &quot;
2626     * \t to &#x9;
2627     * \n to &#xA;
2628     * \r to &#xD;
2629     */

2630    public String JavaDoc convert(String JavaDoc input)
2631    {
2632      //TODO: performance could be improved (e.g. avoid copy characters on each string)
2633
boolean changed = false;
2634      int inputLength = input.length();
2635      grow(inputLength);
2636      input.getChars(0, inputLength, value, 0);
2637      int pos = 0;
2638      char ch = 0;
2639      while (inputLength-- > 0)
2640      {
2641        ch = value[pos];
2642        switch (ch)
2643        {
2644          case '&':
2645            pos = replace(pos, AMP, inputLength);
2646            changed = true;
2647            break;
2648          case '<':
2649            pos = replace(pos, LESS, inputLength);
2650            changed = true;
2651            break;
2652          case '"':
2653            pos = replace(pos, QUOTE, inputLength);
2654            changed = true;
2655            break;
2656          case '\n':
2657          {
2658            pos = replace(pos, LF, inputLength);
2659            changed = true;
2660            break;
2661          }
2662          case '\r':
2663          {
2664            pos = replace(pos, CR, inputLength);
2665            changed = true;
2666            break;
2667          }
2668          case '\t':
2669          {
2670            pos = replace(pos, TAB, inputLength);
2671            changed = true;
2672            break;
2673          }
2674          default:
2675            if (!XMLChar.isValid(ch))
2676            {
2677              throw new RuntimeException JavaDoc("An invalid XML character (Unicode: 0x" + Integer.toHexString(ch)+") was found in the element content:" +input);
2678            }
2679            pos++;
2680            break;
2681        }
2682      }
2683
2684      return changed ? new String JavaDoc(value, 0, pos) : input;
2685    }
2686
2687    /*
2688     * Convert:
2689     * & to &amp;
2690     * < to &lt;
2691     * " to &quot;
2692     * \n to line separator
2693     */

2694    public String JavaDoc convertText(String JavaDoc input)
2695    {
2696      //TODO: performance could be improved (e.g. avoid copy characters on each string)
2697
boolean changed = false;
2698      int inputLength = input.length();
2699      grow(inputLength);
2700      input.getChars(0, inputLength, value, 0);
2701      int pos = 0;
2702      char ch;
2703      while (inputLength-- > 0)
2704      {
2705        ch = value[pos];
2706        switch (ch)
2707        {
2708          case '&':
2709            pos = replace(pos, AMP, inputLength);
2710            changed = true;
2711            break;
2712          case '<':
2713            pos = replace(pos, LESS, inputLength);
2714            changed = true;
2715            break;
2716          case '"':
2717            pos = replace(pos, QUOTE, inputLength);
2718            changed = true;
2719            break;
2720          case '\n':
2721          {
2722            pos = replace(pos, LINE_FEED, inputLength);
2723            changed = true;
2724            break;
2725          }
2726          default:
2727            if (!XMLChar.isValid(ch))
2728            {
2729              throw new RuntimeException JavaDoc("An invalid XML character (Unicode: 0x" + Integer.toHexString(ch)+") was found in the element content:" +input);
2730            }
2731            pos++;
2732            break;
2733        }
2734      }
2735
2736      return changed ? new String JavaDoc(value, 0, pos) : input;
2737    }
2738
2739    /*
2740     * Convert:
2741     * \n to line separator
2742     */

2743    public String JavaDoc convertLines(String JavaDoc input)
2744    {
2745      boolean changed = false;
2746      int inputLength = input.length();
2747      grow(inputLength);
2748      input.getChars(0, inputLength, value, 0);
2749      int pos = 0;
2750      while (inputLength-- > 0)
2751      {
2752        switch (value[pos])
2753        {
2754          case '\n':
2755          {
2756            pos = replace(pos, LINE_FEED, inputLength);
2757            changed = true;
2758            break;
2759          }
2760          default:
2761            pos++;
2762            break;
2763        }
2764      }
2765
2766      return changed ? new String JavaDoc(value, 0, pos) : input;
2767    }
2768
2769    protected int replace(int pos, char[] replacement, int inputLength)
2770    {
2771      int rlen = replacement.length;
2772      int newPos = pos + rlen;
2773      grow(newPos + inputLength);
2774      System.arraycopy(value, pos+1, value, newPos, inputLength);
2775      System.arraycopy(replacement, 0, value, pos, rlen);
2776      return newPos;
2777    }
2778
2779    protected void grow(int newSize)
2780    {
2781      int vlen = value.length;
2782      if (vlen < newSize)
2783      {
2784        char[] newValue = new char[newSize + newSize/2];
2785        System.arraycopy(value, 0, newValue, 0, vlen);
2786        value = newValue;
2787      }
2788    }
2789  }
2790
2791  /**
2792   * Forces type information (xsi:type/xmi:type) to be serialized for references
2793   * in cases where the object's type is different from the feature's type.
2794   */

2795  protected class XMLTypeInfoImpl implements XMLTypeInfo
2796  {
2797
2798    public boolean shouldSaveType(EClass objectType, EClassifier featureType, EStructuralFeature feature)
2799    {
2800      return objectType != featureType && objectType != anyType;
2801    }
2802
2803    public boolean shouldSaveType(EClass objectType, EClass featureType, EStructuralFeature feature)
2804    {
2805      return objectType != featureType;
2806    }
2807  }
2808}
2809
Popular Tags