KickJava   Java API By Example, From Geeks To Geeks.

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


1 /**
2  * <copyright>
3  *
4  * Copyright (c) 2002-2004 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: XMLHandler.java,v 1.34 2005/06/27 22:13:47 elena Exp $
16  */

17 package org.eclipse.emf.ecore.xmi.impl;
18
19
20 import java.io.IOException JavaDoc;
21 import java.io.InputStream JavaDoc;
22 import java.io.UnsupportedEncodingException JavaDoc;
23 import java.lang.reflect.Field JavaDoc;
24 import java.util.ArrayList JavaDoc;
25 import java.util.Collection JavaDoc;
26 import java.util.HashMap JavaDoc;
27 import java.util.HashSet JavaDoc;
28 import java.util.Iterator JavaDoc;
29 import java.util.LinkedList JavaDoc;
30 import java.util.List JavaDoc;
31 import java.util.Map JavaDoc;
32 import java.util.Set JavaDoc;
33 import java.util.StringTokenizer JavaDoc;
34
35 import org.eclipse.emf.common.util.EMap;
36 import org.eclipse.emf.common.util.URI;
37 import org.eclipse.emf.ecore.EClass;
38 import org.eclipse.emf.ecore.EClassifier;
39 import org.eclipse.emf.ecore.EFactory;
40 import org.eclipse.emf.ecore.EObject;
41 import org.eclipse.emf.ecore.EPackage;
42 import org.eclipse.emf.ecore.EReference;
43 import org.eclipse.emf.ecore.EStructuralFeature;
44 import org.eclipse.emf.ecore.EcorePackage;
45 import org.eclipse.emf.ecore.InternalEObject;
46 import org.eclipse.emf.ecore.resource.Resource;
47 import org.eclipse.emf.ecore.resource.ResourceSet;
48 import org.eclipse.emf.ecore.resource.URIConverter;
49 import org.eclipse.emf.ecore.util.BasicExtendedMetaData;
50 import org.eclipse.emf.ecore.util.EcoreUtil;
51 import org.eclipse.emf.ecore.util.ExtendedMetaData;
52 import org.eclipse.emf.ecore.util.FeatureMap;
53 import org.eclipse.emf.ecore.util.InternalEList;
54 import org.eclipse.emf.ecore.xmi.ClassNotFoundException;
55 import org.eclipse.emf.ecore.xmi.FeatureNotFoundException;
56 import org.eclipse.emf.ecore.xmi.IllegalValueException;
57 import org.eclipse.emf.ecore.xmi.PackageNotFoundException;
58 import org.eclipse.emf.ecore.xmi.UnresolvedReferenceException;
59 import org.eclipse.emf.ecore.xmi.XMIException;
60 import org.eclipse.emf.ecore.xmi.XMLHelper;
61 import org.eclipse.emf.ecore.xmi.XMLResource;
62 import org.eclipse.emf.ecore.xml.type.AnyType;
63 import org.eclipse.emf.ecore.xml.type.XMLTypeFactory;
64 import org.eclipse.emf.ecore.xml.type.XMLTypePackage;
65 import org.eclipse.emf.ecore.xml.type.util.XMLTypeUtil;
66
67
68 /**
69  * This class is a generic interface for loading XML files and
70  * creating EObjects from them. Its subclasses include the SAXXMLHandler
71  * class, which wraps this class in a SAX default handler.
72  */

73 public abstract class XMLHandler
74 {
75   protected static final String JavaDoc ERROR_TYPE = "error";
76   protected static final String JavaDoc OBJECT_TYPE = "object";
77   protected static final String JavaDoc UNKNOWN_FEATURE_TYPE = "unknownFeature";
78   protected static final String JavaDoc DOCUMENT_ROOT_TYPE = "documentRoot";
79
80   protected final static String JavaDoc TYPE_ATTRIB = XMLResource.XSI_NS + ":" + XMLResource.TYPE;
81   protected final static String JavaDoc NIL_ATTRIB = XMLResource.XSI_NS + ":" + XMLResource.NIL;
82   protected final static String JavaDoc SCHEMA_LOCATION_ATTRIB = XMLResource.XSI_NS + ":" + XMLResource.SCHEMA_LOCATION;
83   protected final static String JavaDoc NO_NAMESPACE_SCHEMA_LOCATION_ATTRIB = XMLResource.XSI_NS + ":" + XMLResource.NO_NAMESPACE_SCHEMA_LOCATION;
84
85   protected final static boolean DEBUG_DEMANDED_PACKAGES = false;
86   
87   protected static class MyStack extends ArrayList JavaDoc
88   {
89     public MyStack()
90     {
91     }
92
93     public Object JavaDoc peek()
94     {
95       int size = size();
96       return size == 0 ? null : get(size - 1);
97     }
98
99     public void push(Object JavaDoc o)
100     {
101       add(o);
102     }
103
104     public Object JavaDoc pop()
105     {
106       int size = size();
107       return size == 0 ? null : remove(size - 1);
108     }
109   }
110
111   /**
112    * For unresolved forward references, the line number where the incorrect id
113    * appeared in an XML resource is needed, so the Value for the forward reference
114    * and the line number where the forward reference occurred must be saved until
115    * the end of the XML resource is encountered.
116    */

117   protected static class SingleReference
118   {
119     private EObject object;
120     private EStructuralFeature feature;
121     private Object JavaDoc value;
122     private int position;
123     private int lineNumber;
124     private int columnNumber;
125
126     public SingleReference(EObject object,
127                     EStructuralFeature feature,
128                     Object JavaDoc value,
129                     int position,
130                     int lineNumber,
131                     int columnNumber)
132     {
133       this.object = object;
134       this.feature = feature;
135       this.value = value;
136       this.position = position;
137       this.lineNumber = lineNumber;
138       this.columnNumber = columnNumber;
139     }
140
141     public EObject getObject()
142     {
143       return object;
144     }
145
146     public EStructuralFeature getFeature()
147     {
148       return feature;
149     }
150
151     public Object JavaDoc getValue()
152     {
153       return value;
154     }
155
156     public int getPosition()
157     {
158       return position;
159     }
160
161     public int getLineNumber()
162     {
163       return lineNumber;
164     }
165
166     public int getColumnNumber()
167     {
168       return columnNumber;
169     }
170   }
171
172   protected static class ManyReference implements XMLHelper.ManyReference
173   {
174     private EObject object;
175     private EStructuralFeature feature;
176     private Object JavaDoc[] values;
177     private int[] positions;
178     private int lineNumber;
179     private int columnNumber;
180
181     ManyReference(EObject object,
182                   EStructuralFeature feature,
183                   Object JavaDoc[] values,
184                   int[] positions,
185                   int lineNumber,
186                   int columnNumber)
187     {
188       this.object = object;
189       this.feature = feature;
190       this.values = values;
191       this.positions = positions;
192       this.lineNumber = lineNumber;
193       this.columnNumber = columnNumber;
194     }
195
196     public EObject getObject()
197     {
198       return object;
199     }
200
201     public EStructuralFeature getFeature()
202     {
203       return feature;
204     }
205
206     public Object JavaDoc[] getValues()
207     {
208       return values;
209     }
210
211     public int[] getPositions()
212     {
213       return positions;
214     }
215
216     public int getLineNumber()
217     {
218       return lineNumber;
219     }
220
221     public int getColumnNumber()
222     {
223       return columnNumber;
224     }
225   }
226
227   protected XMLResource xmlResource;
228   protected XMLHelper helper;
229   protected MyStack elements;
230   protected MyStack objects;
231   protected MyStack types;
232   protected MyStack mixedTargets;
233   protected Map JavaDoc prefixesToFactories;
234   protected Map JavaDoc urisToLocations;
235   protected InternalEList extent;
236   protected ResourceSet resourceSet;
237   protected EPackage.Registry packageRegistry;
238   protected URI resourceURI;
239   protected boolean resolve;
240   protected boolean oldStyleProxyURIs;
241   protected boolean disableNotify;
242   protected StringBuffer JavaDoc text;
243   protected boolean isIDREF;
244   protected boolean isSimpleFeature;
245   protected List JavaDoc sameDocumentProxies;
246   protected List JavaDoc forwardSingleReferences;
247   protected List JavaDoc forwardManyReferences;
248   protected Object JavaDoc[] identifiers;
249   protected int[] positions;
250   protected static final int ARRAY_SIZE = 64;
251   protected static final int REFERENCE_THRESHOLD = 5;
252   protected int capacity;
253   protected Set JavaDoc notFeatures;
254   protected String JavaDoc idAttribute;
255   protected String JavaDoc hrefAttribute;
256   protected XMLResource.XMLMap xmlMap;
257   protected ExtendedMetaData extendedMetaData;
258   protected EClass anyType;
259   protected EClass anySimpleType;
260   protected boolean recordUnknownFeature;
261   protected boolean recordAnyTypeNSDecls;
262   protected Map JavaDoc eObjectToExtensionMap;
263   protected EStructuralFeature contextFeature;
264   protected EPackage xmlSchemaTypePackage = XMLTypePackage.eINSTANCE;
265   protected boolean deferIDREFResolution;
266
267   /**
268    */

269   public XMLHandler(XMLResource xmlResource, XMLHelper helper, Map JavaDoc options)
270   {
271     this.xmlResource = xmlResource;
272     this.helper = helper;
273     elements = new MyStack();
274     objects = new MyStack();
275     mixedTargets = new MyStack();
276
277     types = new MyStack();
278     prefixesToFactories = new HashMap JavaDoc();
279     forwardSingleReferences = new LinkedList JavaDoc();
280     forwardManyReferences = new LinkedList JavaDoc();
281     sameDocumentProxies = new LinkedList JavaDoc();
282     identifiers = new Object JavaDoc[ARRAY_SIZE];
283     positions = new int[ARRAY_SIZE];
284     capacity = ARRAY_SIZE;
285     resourceSet = xmlResource.getResourceSet();
286     packageRegistry = resourceSet == null ? EPackage.Registry.INSTANCE : resourceSet.getPackageRegistry();
287     resourceURI = xmlResource.getURI();
288     extent = (InternalEList) xmlResource.getContents();
289     resolve = resourceURI != null && resourceURI.isHierarchical() && !resourceURI.isRelative();
290
291     eObjectToExtensionMap = xmlResource.getEObjectToExtensionMap();
292     eObjectToExtensionMap.clear();
293     
294     helper.setOptions(options);
295
296     if (Boolean.TRUE.equals(options.get(XMLResource.OPTION_DISABLE_NOTIFY)))
297       disableNotify = true;
298
299     notFeatures = new HashSet JavaDoc();
300     notFeatures.add(TYPE_ATTRIB);
301     notFeatures.add(SCHEMA_LOCATION_ATTRIB);
302     notFeatures.add(NO_NAMESPACE_SCHEMA_LOCATION_ATTRIB);
303
304     xmlMap = (XMLResource.XMLMap) options.get(XMLResource.OPTION_XML_MAP);
305     helper.setXMLMap(xmlMap);
306     if (xmlMap != null)
307     {
308       idAttribute = xmlMap.getIDAttributeName();
309     }
310
311     Object JavaDoc extendedMetaDataOption = options.get(XMLResource.OPTION_EXTENDED_META_DATA);
312     setExtendedMetaDataOption(extendedMetaDataOption);
313
314     recordUnknownFeature = Boolean.TRUE.equals(options.get(XMLResource.OPTION_RECORD_UNKNOWN_FEATURE));
315     if (recordUnknownFeature && extendedMetaData == null)
316     {
317       setExtendedMetaDataOption(Boolean.TRUE);
318     }
319
320     if (extendedMetaData != null)
321     {
322       AnyType anyType = XMLTypeFactory.eINSTANCE.createAnyType();
323       mixedTargets.push(anyType.getMixed());
324       text = new StringBuffer JavaDoc();
325     }
326     
327     anyType = (EClass)options.get(XMLResource.OPTION_ANY_TYPE);
328     anySimpleType = (EClass)options.get(XMLResource.OPTION_ANY_SIMPLE_TYPE);
329
330     if (anyType == null)
331     {
332       anyType = XMLTypePackage.eINSTANCE.getAnyType();
333       anySimpleType = XMLTypePackage.eINSTANCE.getSimpleAnyType();
334     }
335     
336     helper.setAnySimpleType(anySimpleType);
337     
338     eClassFeatureNamePairToEStructuralFeatureMap = (Map JavaDoc)options.get(XMLResource.OPTION_USE_XML_NAME_TO_FEATURE_MAP);
339     if (eClassFeatureNamePairToEStructuralFeatureMap == null)
340     {
341       eClassFeatureNamePairToEStructuralFeatureMap = new HashMap JavaDoc();
342     }
343     
344     recordAnyTypeNSDecls = Boolean.TRUE.equals(options.get(XMLResource.OPTION_RECORD_ANY_TYPE_NAMESPACE_DECLARATIONS));
345     
346     hrefAttribute = XMLResource.HREF;
347     
348     if (Boolean.FALSE.equals(options.get(XMLResource.OPTION_USE_ENCODED_ATTRIBUTE_STYLE)))
349     {
350       hrefAttribute = null;
351     }
352     
353     if (Boolean.TRUE.equals(options.get(XMLResource.OPTION_DEFER_IDREF_RESOLUTION)))
354     {
355       helper.setCheckForDuplicates(deferIDREFResolution = true);
356     }
357   }
358
359   protected void setExtendedMetaDataOption(Object JavaDoc extendedMetaDataOption)
360   {
361     if (extendedMetaDataOption instanceof Boolean JavaDoc)
362     {
363       if (extendedMetaDataOption.equals(Boolean.TRUE))
364       {
365         extendedMetaData =
366           resourceSet == null ?
367             ExtendedMetaData.INSTANCE :
368             new BasicExtendedMetaData(resourceSet.getPackageRegistry());
369         if (xmlResource != null)
370         {
371           xmlResource.getDefaultSaveOptions().put(XMLResource.OPTION_EXTENDED_META_DATA, extendedMetaData);
372         }
373       }
374       else
375       {
376         extendedMetaData = null;
377       }
378     }
379     else
380     {
381       extendedMetaData = (ExtendedMetaData)extendedMetaDataOption;
382     }
383
384     helper.setExtendedMetaData(extendedMetaData);
385   }
386
387   /**
388    * Process the XML attributes for the newly created object.
389    */

390   protected abstract void handleObjectAttribs(EObject obj);
391
392   /**
393    * Process the XML namespace declarations.
394    */

395   protected abstract void handleNamespaceAttribs();
396
397   /**
398    * Returns true if the xsi:nil attribute is in the list of attributes.
399    */

400   protected abstract boolean isNull();
401
402   /**
403    * Sets the current attributes and returns the old ones.
404    */

405   protected abstract Object JavaDoc setAttributes(Object JavaDoc attributes);
406
407   /**
408    * Sets the object that might be used for determining the line and
409    * column number.
410    */

411   protected abstract void setLocator(Object JavaDoc locator);
412
413   /**
414    * Returns the xsi type attribute's value.
415    */

416   protected abstract String JavaDoc getXSIType();
417
418   public void startDocument()
419   {
420   }
421
422   /**
423    * This method determines whether to make an object or not, then makes an
424    * object based on the XML attributes and the metamodel.
425    */

426   public void startElement(String JavaDoc uri, String JavaDoc localName, String JavaDoc name)
427   {
428     helper.pushContext();
429     if (text != null && mixedTargets.peek() != null)
430     {
431       handleMixedText();
432     }
433
434     elements.push(name);
435
436     handleNamespaceAttribs();
437
438     // Turning on namespace awareness is very expensive so this simulates the effect.
439
//
440
int index = name.indexOf(":");
441     String JavaDoc prefix = "";
442     localName = name;
443     if (index != -1)
444     {
445       prefix = name.substring(0, index);
446       localName = name.substring(index + 1);
447     }
448
449     processElement(name, prefix, localName);
450   }
451
452   protected void processElement(String JavaDoc name, String JavaDoc prefix, String JavaDoc localName)
453   {
454     if (isError())
455     {
456       types.push(ERROR_TYPE);
457     }
458     else
459     {
460       if (objects.isEmpty())
461       {
462         createTopObject(prefix, localName);
463       }
464       else
465       {
466         handleFeature(prefix, localName);
467       }
468     }
469   }
470
471   protected void handleForwardReferences()
472   {
473     handleForwardReferences(false);
474   }
475
476   /**
477    * Check if the values of the forward references have been set (they may
478    * have been set due to a bi-directional reference being set). If not,
479    * set them.
480    * If this is called during end document processing, errors should be diagnosed.
481    * If it is called in the middle of a document,
482    * we need to clean up the forward reference lists to avoid reprocessing resolved references again later.
483    */

484   protected void handleForwardReferences(boolean isEndDocument)
485   {
486     // Handle the same document proxies, which may have problems resulting from the
487
// other end of a bidirectional reference being handled as an IDREF rather than as a proxy.
488
// When we are done with these, we know that funny proxies are now resolved as if they were handled as IDREFs.
489
//
490
for (Iterator JavaDoc i = sameDocumentProxies.iterator(); i.hasNext(); )
491     {
492       InternalEObject proxy = (InternalEObject)i.next();
493
494       // Look through all the references...
495
//
496
LOOP:
497       for (Iterator JavaDoc j = proxy.eClass().getEAllReferences().iterator(); j.hasNext(); )
498       {
499         // And find the one that holds this proxy.
500
//
501
EReference eReference = (EReference)j.next();
502         EReference oppositeEReference = eReference.getEOpposite();
503         if (oppositeEReference != null && proxy.eIsSet(eReference))
504         {
505           // Try to resolve the proxy locally.
506
//
507
EObject resolvedEObject = xmlResource.getEObject(proxy.eProxyURI().fragment());
508           if (resolvedEObject != null)
509           {
510             // We won't need to process this again later.
511
//
512
if (!isEndDocument)
513             {
514               i.remove();
515             }
516
517             // Compute the holder of the proxy
518
//
519
EObject proxyHolder = (EObject)(eReference.isMany() ? ((List JavaDoc)proxy.eGet(eReference)).get(0) : proxy.eGet(eReference));
520
521             // If the proxy holder can hold many values,
522
// it may contain a duplicate that resulted when the other end was processed as an IDREF
523
// and hence did both sides of the bidirectional relation.
524
//
525
if (oppositeEReference.isMany())
526             {
527               // So if the resolved object is also present...
528
//
529
InternalEList holderContents = (InternalEList)proxyHolder.eGet(oppositeEReference);
530               List JavaDoc basicHolderContents = holderContents.basicList();
531               int resolvedEObjectIndex = basicHolderContents.indexOf(resolvedEObject);
532               if (resolvedEObjectIndex != -1)
533               {
534                 // Move the resolved object to the right place, remove the proxy, and we're done.
535
//
536
int proxyIndex = basicHolderContents.indexOf(proxy);
537                 holderContents.move(proxyIndex, resolvedEObjectIndex);
538                 holderContents.remove(proxyIndex > resolvedEObjectIndex ? proxyIndex - 1 : proxyIndex + 1);
539                 break LOOP;
540               }
541             }
542
543             // If the resolved object doesn't contain a reference to the proxy holder as it should.
544
//
545
if (eReference.isMany() ?
546                   !((InternalEList)resolvedEObject.eGet(eReference)).basicList().contains(proxyHolder) :
547                   resolvedEObject.eGet(eReference) != proxyHolder)
548             {
549               // The proxy needs to be replaced in a way that updates both ends of the reference.
550
//
551
if (oppositeEReference.isMany())
552               {
553                 InternalEList proxyHolderList = (InternalEList)proxyHolder.eGet(oppositeEReference);
554                 proxyHolderList.setUnique(proxyHolderList.indexOf(proxy), resolvedEObject);
555               }
556               else
557               {
558                 proxyHolder.eSet(oppositeEReference, resolvedEObject);
559               }
560             }
561           }
562
563           break;
564         }
565       }
566     }
567
568     for (Iterator JavaDoc i = forwardSingleReferences.iterator(); i.hasNext(); )
569     {
570       SingleReference ref = (SingleReference) i.next();
571       EObject obj = xmlResource.getEObject((String JavaDoc) ref.getValue());
572
573       if (obj != null)
574       {
575         // We won't need to process this again later.
576
if (!isEndDocument)
577         {
578           i.remove();
579         }
580         EStructuralFeature feature = ref.getFeature();
581         setFeatureValue(ref.getObject(), feature, obj, ref.getPosition());
582       }
583       else if (isEndDocument)
584       {
585         error
586           (new UnresolvedReferenceException
587             ((String JavaDoc) ref.getValue(),
588              getLocation(),
589              ref.getLineNumber(),
590              ref.getColumnNumber()));
591       }
592     }
593
594     for (Iterator JavaDoc i = forwardManyReferences.iterator(); i.hasNext(); )
595     {
596       ManyReference ref = (ManyReference) i.next();
597       Object JavaDoc[] values = ref.getValues();
598
599       boolean failure = false;
600       for (int j = 0, l = values.length; j < l; j++)
601       {
602         String JavaDoc id = (String JavaDoc) values[j];
603         EObject obj = xmlResource.getEObject(id);
604         values[j] = obj;
605
606         if (obj == null)
607         {
608           failure = true;
609           if (isEndDocument)
610           {
611             error
612               (new UnresolvedReferenceException
613                 (id,
614                  getLocation(),
615                  ref.getLineNumber(),
616                  ref.getColumnNumber()));
617           }
618         }
619       }
620
621       if (!failure)
622       {
623         if (!isEndDocument)
624         {
625           i.remove();
626         }
627         setFeatureValues(ref);
628       }
629       else if (isEndDocument)
630       {
631         // At least set the references that we were able to resolve, if any.
632
//
633
setFeatureValues(ref);
634       }
635     }
636   }
637
638   /**
639    * Check if the values of the forward references have been set (they may
640    * have been set due to a bi-directional reference being set). If not,
641    * set them.
642    */

643   public void endDocument()
644   {
645     helper.recordPrefixToURIMapping();
646     handleForwardReferences(true);
647
648     if (disableNotify)
649     {
650       for (Iterator JavaDoc i = xmlResource.getAllContents(); i.hasNext(); )
651       {
652         EObject eObject = (EObject)i.next();
653         eObject.eSetDeliver(true);
654       }
655     }
656
657     if (extendedMetaData != null)
658     {
659       if (extent.size() == 1)
660       {
661         EObject root = (EObject)extent.get(0);
662         recordNamespacesSchemaLocations(root);
663       }
664
665       if (DEBUG_DEMANDED_PACKAGES)
666       {
667         // EATM temporary for debug purposes only.
668
//
669
Collection JavaDoc demandedPackages = EcoreUtil.copyAll(extendedMetaData.demandedPackages());
670         for (Iterator JavaDoc i = demandedPackages.iterator(); i.hasNext();)
671         {
672           EPackage ePackage = (EPackage)i.next();
673           ePackage.setName(ePackage.getNsURI());
674         }
675         extent.addAll(demandedPackages);
676       }
677     }
678   }
679   
680   protected EMap recordNamespacesSchemaLocations(EObject root)
681   {
682     EClass eClass = root.eClass();
683     EReference xmlnsPrefixMapFeature = extendedMetaData.getXMLNSPrefixMapFeature(eClass);
684     EMap xmlnsPrefixMap = null;
685     if (xmlnsPrefixMapFeature != null)
686     {
687       xmlnsPrefixMap = (EMap)root.eGet(xmlnsPrefixMapFeature);
688       xmlnsPrefixMap.putAll(helper.getPrefixToNamespaceMap());
689     }
690
691     if (urisToLocations != null)
692     {
693       EReference xsiSchemaLocationMapFeature = extendedMetaData.getXSISchemaLocationMapFeature(eClass);
694       if (xsiSchemaLocationMapFeature != null)
695       {
696         EMap xsiSchemaLocationMap = (EMap)root.eGet(xsiSchemaLocationMapFeature);
697         for (Iterator JavaDoc i = urisToLocations.entrySet().iterator(); i.hasNext(); )
698         {
699           Map.Entry JavaDoc entry = (Map.Entry JavaDoc)i.next();
700           xsiSchemaLocationMap.put(entry.getKey(), entry.getValue().toString());
701         }
702       }
703     }
704     return xmlnsPrefixMap;
705   }
706
707   /**
708    * Create an object based on the prefix and type name.
709    */

710   protected EObject createObjectByType(String JavaDoc prefix, String JavaDoc name, boolean top)
711   {
712     if (top)
713     {
714       handleTopLocations(prefix, name);
715     }
716
717     EFactory eFactory = getFactoryForPrefix(prefix);
718     if (eFactory == null && prefix.equals("") && helper.getURI(prefix) == null)
719     {
720       EPackage ePackage = handleMissingPackage(null);
721       if (ePackage == null)
722       {
723         error
724           (new PackageNotFoundException
725              (null,
726               getLocation(),
727               getLineNumber(),
728               getColumnNumber()));
729       }
730       else
731       {
732         eFactory = ePackage.getEFactoryInstance();
733       }
734     }
735
736     if (extendedMetaData != null && eFactory != null)
737     {
738       EClass eClass = extendedMetaData.getDocumentRoot(eFactory.getEPackage());
739       if (eClass != null)
740       {
741         // EATM Kind of hacky.
742
String JavaDoc typeName = extendedMetaData.getName(eClass);
743         EObject newObject = helper.createObject(eFactory, typeName);
744         validateCreateObjectFromFactory(eFactory, typeName, newObject);
745         if (top)
746         {
747           processTopObject(newObject);
748           handleFeature(prefix, name);
749         }
750         return newObject;
751       }
752     }
753
754     EObject newObject = createObjectFromFactory(eFactory, name);
755     validateCreateObjectFromFactory(eFactory, name, newObject);
756     if (top)
757     {
758       processTopObject(newObject);
759     }
760     return newObject;
761   }
762
763   protected void createTopObject(String JavaDoc prefix, String JavaDoc name)
764   {
765     createObjectByType(prefix, name, true);
766   }
767
768   /**
769    * Add object to extent and call processObject.
770    */

771   protected void processTopObject(EObject object)
772   {
773     if (object != null)
774     {
775       extent.addUnique(object);
776
777       if (extendedMetaData != null)
778       {
779         FeatureMap featureMap = (FeatureMap)mixedTargets.pop();
780         EStructuralFeature target = extendedMetaData.getMixedFeature(object.eClass());
781         if (target != null)
782         {
783           FeatureMap otherFeatureMap = (FeatureMap)object.eGet(target);
784           for (Iterator JavaDoc i = featureMap.iterator(); i.hasNext(); )
785           {
786             FeatureMap.Entry entry = (FeatureMap.Entry)i.next();
787
788             // Ignore a whitespace only text entry at the beginning.
789
//
790
if (entry.getEStructuralFeature() != XMLTypePackage.eINSTANCE.getXMLTypeDocumentRoot_Text() ||
791                   !"".equals(XMLTypeUtil.normalize(entry.getValue().toString(), true)))
792             {
793               otherFeatureMap.add(entry.getEStructuralFeature(), entry.getValue());
794             }
795           }
796         }
797         text = null;
798       }
799     }
800
801     processObject(object);
802   }
803
804   /**
805    * Pop the appropriate stacks and set features whose values are in
806    * the content of XML elements.
807    */

808   public void endElement(String JavaDoc uri, String JavaDoc localName, String JavaDoc name)
809   {
810     elements.pop();
811     Object JavaDoc type = types.pop();
812     if (type == OBJECT_TYPE)
813     {
814       if (text == null)
815       {
816         objects.pop();
817         mixedTargets.pop();
818       }
819       else
820       {
821         Object JavaDoc object = objects.pop();
822         if (mixedTargets.peek() != null &&
823               (((EObject)object).eContainer() != null || recordUnknownFeature && eObjectToExtensionMap.containsValue(object)))
824         {
825           handleMixedText();
826           mixedTargets.pop();
827         }
828         else
829         {
830           if (text.length() != 0)
831           {
832             handleProxy((InternalEObject)object, text.toString().trim());
833           }
834           mixedTargets.pop();
835           text = null;
836         }
837       }
838     }
839     else if (isIDREF)
840     {
841       objects.pop();
842       mixedTargets.pop();
843       if (text != null)
844       {
845         setValueFromId((EObject)objects.peek(), (EReference)type, text.toString());
846         text = null;
847       }
848       isIDREF= false;
849     }
850     else if (isTextFeatureValue(type))
851     {
852       EObject eObject = (EObject)objects.pop();
853       mixedTargets.pop();
854       if (eObject == null)
855       {
856         eObject = (EObject)objects.peek();
857       }
858       setFeatureValue(eObject, (EStructuralFeature) type, text == null ? null : text.toString());
859       text = null;
860     }
861
862     if (isSimpleFeature)
863     {
864       types.pop();
865       objects.pop();
866       mixedTargets.pop();
867       isSimpleFeature = false;
868     }
869     helper.popContext();
870   }
871
872   protected boolean isTextFeatureValue(Object JavaDoc type)
873   {
874     return type != ERROR_TYPE;
875   }
876
877   public void startPrefixMapping(String JavaDoc prefix, String JavaDoc uri)
878   {
879     helper.addPrefix(prefix, uri);
880   }
881
882   public void endPrefixMapping(String JavaDoc prefix)
883   {
884   }
885
886   public void characters(char [] ch, int start, int length)
887   {
888     if (text == null && mixedTargets.peek() != null)
889     {
890       text = new StringBuffer JavaDoc();
891     }
892
893     if (text != null)
894     {
895       text.append(ch, start, length);
896     }
897   }
898
899   public void processingInstruction(String JavaDoc target, String JavaDoc data)
900   {
901     // do nothing
902
}
903
904   public void comment(char [] ch, int start, int length) // throws SAXException
905
{
906     if (mixedTargets.peek() != null)
907     {
908       if (text != null)
909       {
910         handleMixedText();
911       }
912
913       handleComment(new String JavaDoc(ch, start, length));
914     }
915   }
916
917   public void startCDATA()
918   {
919     if (mixedTargets.peek() != null)
920     {
921       if (text != null)
922       {
923         handleMixedText();
924       }
925       text = new StringBuffer JavaDoc();
926     }
927   }
928
929   public void endCDATA()
930   {
931     if (mixedTargets.peek() != null && text != null)
932     {
933       handleCDATA();
934     }
935   }
936   
937   public void startDTD(String JavaDoc name, String JavaDoc publicId, String JavaDoc systemId)
938   {
939     xmlResource.setDoctypeInfo(publicId, systemId);
940   }
941
942   protected void handleXMLNSAttribute(String JavaDoc attrib, String JavaDoc value)
943   {
944     // Handle namespaces
945
int index = attrib.indexOf(":");
946     String JavaDoc prefix = index == -1 ? "" : attrib.substring(index + 1);
947     helper.addPrefix(prefix, value);
948   }
949
950   protected void handleXSISchemaLocation(String JavaDoc schemaLocations)
951   {
952     if (urisToLocations == null)
953     {
954       urisToLocations = new HashMap JavaDoc();
955       xmlResource.getDefaultSaveOptions().put(XMLResource.OPTION_SCHEMA_LOCATION, Boolean.TRUE);
956     }
957
958     for (StringTokenizer JavaDoc stringTokenizer = new StringTokenizer JavaDoc(schemaLocations, " "); stringTokenizer.hasMoreTokens(); )
959     {
960       String JavaDoc key = stringTokenizer.nextToken();
961       if (stringTokenizer.hasMoreTokens())
962       {
963         String JavaDoc value = stringTokenizer.nextToken();
964         URI uri = URI.createURI(value);
965         if (resolve && uri.isRelative() && uri.hasRelativePath())
966         {
967           uri = helper.resolve(uri, resourceURI);
968         }
969         urisToLocations.put(key, uri);
970       }
971     }
972   }
973
974   protected void handleXSINoNamespaceSchemaLocation(String JavaDoc noNamespaceSchemaLocation)
975   {
976     if (urisToLocations == null)
977     {
978       urisToLocations = new HashMap JavaDoc();
979       xmlResource.getDefaultSaveOptions().put(XMLResource.OPTION_SCHEMA_LOCATION, Boolean.TRUE);
980     }
981
982     URI uri = URI.createURI(noNamespaceSchemaLocation);
983     if (resolve && uri.isRelative() && uri.hasRelativePath())
984     {
985       uri = helper.resolve(uri, resourceURI);
986     }
987     urisToLocations.put(null, uri);
988   }
989
990   protected void handleTopLocations(String JavaDoc prefix, String JavaDoc name)
991   {
992     if (urisToLocations != null)
993     {
994       URI locationForNull = (URI)urisToLocations.get(null);
995       if (locationForNull != null && helper.getNoNamespacePackage() == null)
996       {
997         helper.setNoNamespacePackage(getPackageForURI(locationForNull.toString()));
998       }
999     }
1000  }
1001
1002  /**
1003   * The XML element represents a feature. There are two
1004   * cases to handle:
1005   * 1. The feature has a type that is a datatype.
1006   * 2. The feature has a type that is a class.
1007   */

1008  protected void handleFeature(String JavaDoc prefix, String JavaDoc name)
1009  {
1010    EObject peekObject = (EObject) objects.peek();
1011
1012    // This happens when processing an element with simple content that has elements content even though it shouldn't.
1013
//
1014
if (peekObject == null)
1015    {
1016      types.push(ERROR_TYPE);
1017      error
1018        (new FeatureNotFoundException
1019          (name,
1020           null,
1021           getLocation(),
1022           getLineNumber(),
1023           getColumnNumber()));
1024      return;
1025    }
1026
1027    EStructuralFeature feature = getFeature(peekObject, prefix, name, true);
1028    if (feature != null)
1029    {
1030      int kind = helper.getFeatureKind(feature);
1031      if (kind == XMLHelper.DATATYPE_SINGLE || kind == XMLHelper.DATATYPE_IS_MANY)
1032      {
1033        objects.push(null);
1034        mixedTargets.push(null);
1035        types.push(feature);
1036        if (!isNull())
1037        {
1038          text = new StringBuffer JavaDoc();
1039        }
1040      }
1041      else if (extendedMetaData != null && extendedMetaData.getFeatureKind(feature) != ExtendedMetaData.UNSPECIFIED_FEATURE)
1042      {
1043        EReference eReference = (EReference)feature;
1044        boolean isContainment = eReference.isContainment();
1045        if (!isContainment && !eReference.isResolveProxies())
1046        {
1047          isIDREF = true;
1048          objects.push(null);
1049          mixedTargets.push(null);
1050          types.push(feature);
1051          text = new StringBuffer JavaDoc();
1052        }
1053        else
1054        {
1055          createObject(peekObject, feature);
1056          EObject childObject = (EObject) objects.peek();
1057          if (childObject != null)
1058          {
1059            if (isContainment)
1060            {
1061              EStructuralFeature simpleFeature = extendedMetaData.getSimpleFeature(childObject.eClass());
1062              if (simpleFeature != null)
1063              {
1064                isSimpleFeature = true;
1065                isIDREF = simpleFeature instanceof EReference;
1066                objects.push(null);
1067                mixedTargets.push(null);
1068                types.push(simpleFeature);
1069                text = new StringBuffer JavaDoc();
1070              }
1071            }
1072            else
1073            {
1074              text = new StringBuffer JavaDoc();
1075            }
1076          }
1077        }
1078      }
1079      else
1080      {
1081        createObject(peekObject, feature);
1082      }
1083    }
1084    else
1085    {
1086      // Try to get a general-content feature.
1087
// Use a pattern that's not possible any other way.
1088
//
1089
if (xmlMap != null && (feature = getFeature(peekObject, null, "", true)) != null)
1090      {
1091        EFactory eFactory = getFactoryForPrefix(prefix);
1092
1093        // This is for the case for a local unqualified element that has been bound.
1094
//
1095
if (eFactory == null)
1096        {
1097          eFactory = feature.getEContainingClass().getEPackage().getEFactoryInstance();
1098        }
1099
1100        EObject newObject = createObjectFromFactory(eFactory, name);
1101        newObject = validateCreateObjectFromFactory(eFactory, name, newObject, feature);
1102        if (newObject != null)
1103        {
1104          setFeatureValue(peekObject, feature, newObject);
1105        }
1106        processObject(newObject);
1107      }
1108      else
1109      {
1110        // This handles the case of a substitution group.
1111
//
1112
if (xmlMap != null)
1113        {
1114          EFactory eFactory = getFactoryForPrefix(prefix);
1115          EObject newObject = createObjectFromFactory(eFactory, name);
1116          validateCreateObjectFromFactory(eFactory, name, newObject);
1117          if (newObject != null)
1118          {
1119            for (Iterator JavaDoc i = peekObject.eClass().getEAllReferences().iterator(); i.hasNext(); )
1120            {
1121              EReference eReference = (EReference)i.next();
1122              if (eReference.getEType().isInstance(newObject))
1123              {
1124                setFeatureValue(peekObject, eReference, newObject);
1125                processObject(newObject);
1126                return;
1127              }
1128            }
1129          }
1130        }
1131       
1132        handleUnknownFeature(prefix, name, true, peekObject, null);
1133      }
1134    }
1135  }
1136
1137  protected int getLineNumber()
1138  {
1139    return -1;
1140  }
1141
1142  protected int getColumnNumber()
1143  {
1144    return -1;
1145  }
1146
1147  protected String JavaDoc getLocation()
1148  {
1149    return resourceURI == null ? "" : resourceURI.toString();
1150  }
1151  
1152  protected AnyType getExtension(EObject peekObject)
1153  {
1154    AnyType anyType = (AnyType)eObjectToExtensionMap.get(peekObject);
1155    if (anyType == null)
1156    {
1157      anyType = XMLTypeFactory.eINSTANCE.createAnyType();
1158      eObjectToExtensionMap.put(peekObject, anyType);
1159    }
1160    return anyType;
1161  }
1162
1163  protected void handleUnknownFeature(String JavaDoc prefix, String JavaDoc name, boolean isElement, EObject peekObject, String JavaDoc value)
1164  {
1165    if (recordUnknownFeature)
1166    {
1167      recordUnknownFeature(prefix, name, isElement, peekObject, value);
1168    }
1169    else
1170    {
1171      reportUnknownFeature(prefix, name, isElement, peekObject, value);
1172    }
1173  }
1174
1175  protected void recordUnknownFeature(String JavaDoc prefix, String JavaDoc name, boolean isElement, EObject peekObject, String JavaDoc value)
1176  {
1177    if (isElement)
1178    {
1179      AnyType anyType = getExtension(peekObject);
1180      objects.push(anyType);
1181      mixedTargets.push(anyType.getAny());
1182      types.push(UNKNOWN_FEATURE_TYPE);
1183
1184      handleFeature(prefix, name);
1185
1186      objects.remove(objects.size() - 2);
1187      mixedTargets.remove(mixedTargets.size() - 2);
1188      types.remove(types.size() - 2);
1189    }
1190    else
1191    {
1192      AnyType anyType = getExtension(peekObject);
1193      setAttribValue(anyType, prefix == null ? name : prefix + ":" + name, value);
1194    }
1195  }
1196
1197  protected void reportUnknownFeature(String JavaDoc prefix, String JavaDoc name, boolean isElement, EObject peekObject, String JavaDoc value)
1198  {
1199    types.push(ERROR_TYPE);
1200    error
1201      (new FeatureNotFoundException
1202        (name,
1203         peekObject,
1204         getLocation(),
1205         getLineNumber(),
1206         getColumnNumber()));
1207  }
1208  
1209  public void error(XMIException e)
1210  {
1211    xmlResource.getErrors().add(e);
1212  }
1213
1214  public void warning(XMIException e)
1215  {
1216    xmlResource.getWarnings().add(e);
1217  }
1218
1219  public void fatalError(XMIException e)
1220  {
1221    xmlResource.getErrors().add(e);
1222  }
1223
1224  /**
1225   * Create an object based on the given feature and attributes.
1226   */

1227  protected void createObject(EObject peekObject, EStructuralFeature feature)
1228  {
1229    if (isNull())
1230    {
1231      setFeatureValue(peekObject, feature, null);
1232      objects.push(null);
1233      mixedTargets.push(null);
1234      types.push(OBJECT_TYPE);
1235    }
1236    else
1237    {
1238      String JavaDoc xsiType = getXSIType();
1239      if (xsiType != null)
1240      {
1241        createObjectFromTypeName(peekObject, xsiType, feature);
1242      }
1243      else
1244      {
1245        createObjectFromFeatureType(peekObject, feature);
1246        if (extendedMetaData != null && !((EReference)feature).isContainment())
1247        {
1248          text = new StringBuffer JavaDoc();
1249        }
1250        if (xmlMap != null && !((EReference)feature).isContainment())
1251        {
1252          XMLResource.XMLInfo info = xmlMap.getInfo(feature);
1253          if (info != null && info.getXMLRepresentation() == XMLResource.XMLInfo.ELEMENT)
1254          {
1255            text = new StringBuffer JavaDoc();
1256          }
1257        }
1258      }
1259    }
1260  }
1261
1262  /**
1263   * Create an object from the given qualified type name.
1264   */

1265  protected EObject createObjectFromTypeName(EObject peekObject, String JavaDoc typeQName, EStructuralFeature feature)
1266  {
1267    String JavaDoc typeName = null;
1268    String JavaDoc prefix = "";
1269    int index = typeQName.indexOf(":");
1270    if (index > 0)
1271    {
1272      prefix = typeQName.substring(0, index);
1273      typeName = typeQName.substring(index + 1);
1274    }
1275    else
1276    {
1277      typeName = typeQName;
1278    }
1279
1280    contextFeature = feature;
1281    EFactory eFactory = getFactoryForPrefix(prefix);
1282    contextFeature = null;
1283
1284    if (eFactory == null && prefix.equals("") && helper.getURI(prefix) == null)
1285    {
1286      contextFeature = feature;
1287      EPackage ePackage = handleMissingPackage(null);
1288      contextFeature = null;
1289      if (ePackage == null)
1290      {
1291        error
1292          (new PackageNotFoundException
1293             (null,
1294              getLocation(),
1295              getLineNumber(),
1296              getColumnNumber()));
1297      }
1298      else
1299      {
1300        eFactory = ePackage.getEFactoryInstance();
1301      }
1302    }
1303
1304    EObject obj = createObjectFromFactory(eFactory, typeName);
1305    obj = validateCreateObjectFromFactory(eFactory, typeName, obj, feature);
1306
1307    if (obj != null)
1308    {
1309      if (contextFeature == null)
1310      {
1311        setFeatureValue(peekObject, feature, obj);
1312      }
1313      else
1314      {
1315        contextFeature = null;
1316      }
1317    }
1318
1319    processObject(obj);
1320
1321    return obj;
1322  }
1323
1324  /**
1325   * Create an object based on the type of the given feature.
1326   */

1327  protected EObject createObjectFromFeatureType(EObject peekObject, EStructuralFeature feature)
1328  {
1329    String JavaDoc typeName = null;
1330    EFactory factory = null;
1331    EClassifier eType = null;
1332
1333    if (feature != null && (eType = feature.getEType()) != null)
1334    {
1335      if (extendedMetaData != null &&
1336            eType == EcorePackage.eINSTANCE.getEObject() &&
1337            extendedMetaData.getFeatureKind(feature) != ExtendedMetaData.UNSPECIFIED_FEATURE)
1338      {
1339        typeName = extendedMetaData.getName(anyType);
1340        factory = anyType.getEPackage().getEFactoryInstance();
1341      }
1342      else
1343      {
1344        EClass eClass = (EClass) eType;
1345        typeName = extendedMetaData == null ? eClass.getName() : extendedMetaData.getName(eClass);
1346        factory = eClass.getEPackage().getEFactoryInstance();
1347      }
1348    }
1349
1350    EObject obj = createObjectFromFactory(factory, typeName);
1351    obj = validateCreateObjectFromFactory(factory, typeName, obj, feature);
1352    if (obj != null)
1353    {
1354      setFeatureValue(peekObject, feature, obj);
1355    }
1356
1357    processObject(obj);
1358    return obj;
1359  }
1360
1361  /**
1362   * Create an object given a content helper, a factory, and a type name,
1363   * and process the XML attributes.
1364   */

1365  protected EObject createObjectFromFactory(EFactory factory, String JavaDoc typeName)
1366  {
1367    EObject newObject = null;
1368
1369    if (factory != null)
1370    {
1371      newObject = helper.createObject(factory, typeName);
1372
1373      if (newObject != null)
1374      {
1375        if (disableNotify)
1376          newObject.eSetDeliver(false);
1377
1378        handleObjectAttribs(newObject);
1379      }
1380/*
1381      else
1382      {
1383        error
1384          (new ClassNotFoundException
1385            (typeName,
1386             factory,
1387             getLocation(),
1388             getLineNumber(),
1389             getColumnNumber()));
1390      }
1391*/

1392    }
1393
1394    return newObject;
1395  }
1396
1397  protected void validateCreateObjectFromFactory(EFactory factory, String JavaDoc typeName, EObject newObject)
1398  {
1399    if (newObject == null)
1400    {
1401      error
1402        (new ClassNotFoundException JavaDoc
1403          (typeName,
1404           factory,
1405           getLocation(),
1406           getLineNumber(),
1407           getColumnNumber()));
1408    }
1409  }
1410
1411  protected EObject validateCreateObjectFromFactory(EFactory factory, String JavaDoc typeName, EObject newObject, EStructuralFeature feature)
1412  {
1413    if (newObject != null)
1414    {
1415      if (extendedMetaData != null)
1416      {
1417        Collection JavaDoc demandedPackages = extendedMetaData.demandedPackages();
1418        if (!demandedPackages.isEmpty() && demandedPackages.contains(newObject.eClass().getEPackage()))
1419        {
1420          if (recordUnknownFeature)
1421          {
1422            EObject peekObject = (EObject)objects.peek();
1423            if (!(peekObject instanceof AnyType))
1424            {
1425              AnyType anyType = getExtension((EObject)objects.peek());
1426              EStructuralFeature entryFeature =
1427                extendedMetaData.demandFeature(extendedMetaData.getNamespace(feature), extendedMetaData.getName(feature), true);
1428              anyType.getAny().add(entryFeature, newObject);
1429              contextFeature = entryFeature;
1430            }
1431            return newObject;
1432          }
1433          else
1434          {
1435            String JavaDoc namespace = extendedMetaData.getNamespace(feature);
1436            String JavaDoc name = extendedMetaData.getName(feature);
1437            EStructuralFeature wildcardFeature =
1438              extendedMetaData.getElementWildcardAffiliation(((EObject)objects.peek()).eClass(), namespace, name);
1439            if (wildcardFeature != null)
1440            {
1441              switch (extendedMetaData.getProcessingKind(wildcardFeature))
1442              {
1443                case ExtendedMetaData.LAX_PROCESSING:
1444                case ExtendedMetaData.SKIP_PROCESSING:
1445                {
1446                  return newObject;
1447                }
1448              }
1449            }
1450          }
1451
1452          newObject = null;
1453        }
1454      }
1455    }
1456    else if (feature != null && factory != null && extendedMetaData != null)
1457    {
1458      if (recordUnknownFeature)
1459      {
1460        factory =
1461          extendedMetaData.demandType
1462            (extendedMetaData.getNamespace(factory.getEPackage()), typeName).getEPackage().getEFactoryInstance();
1463        EObject result = createObjectFromFactory(factory, typeName);
1464        EObject peekObject = (EObject)objects.peek();
1465        if (!(peekObject instanceof AnyType))
1466        {
1467          AnyType anyType = getExtension((EObject)objects.peek());
1468          EStructuralFeature entryFeature =
1469            extendedMetaData.demandFeature(extendedMetaData.getNamespace(feature), extendedMetaData.getName(feature), true);
1470          anyType.getAny().add(entryFeature, result);
1471          contextFeature = entryFeature;
1472        }
1473        return result;
1474      }
1475      else
1476      {
1477        String JavaDoc namespace = extendedMetaData.getNamespace(feature);
1478        String JavaDoc name = extendedMetaData.getName(feature);
1479        EStructuralFeature wildcardFeature =
1480          extendedMetaData.getElementWildcardAffiliation(((EObject)objects.peek()).eClass(), namespace, name);
1481        if (wildcardFeature != null)
1482        {
1483          switch (extendedMetaData.getProcessingKind(wildcardFeature))
1484          {
1485            case ExtendedMetaData.LAX_PROCESSING:
1486            case ExtendedMetaData.SKIP_PROCESSING:
1487            {
1488              // EATM Demand create metadata; needs to depend on processing mode...
1489
factory =
1490                extendedMetaData.demandType
1491                  (extendedMetaData.getNamespace(factory.getEPackage()), typeName).getEPackage().getEFactoryInstance();
1492              return createObjectFromFactory(factory, typeName);
1493            }
1494          }
1495        }
1496      }
1497    }
1498
1499    validateCreateObjectFromFactory(factory, typeName, newObject);
1500    return newObject;
1501  }
1502
1503  /**
1504   * Add object to appropriate stacks.
1505   */

1506  protected void processObject(EObject object)
1507  {
1508    if (recordAnyTypeNSDecls && object instanceof AnyType)
1509    {
1510      FeatureMap featureMap = ((AnyType)object).getAnyAttribute();
1511      for (Iterator JavaDoc i = helper.getAnyContentPrefixToURIMapping().entrySet().iterator(); i.hasNext();)
1512      {
1513        Map.Entry JavaDoc entry = (Map.Entry JavaDoc)i.next();
1514        Object JavaDoc uri = entry.getValue();
1515        featureMap.add(extendedMetaData.demandFeature(ExtendedMetaData.XMLNS_URI, (String JavaDoc)entry.getKey(), false), uri == null ? "" : uri);
1516      }
1517    }
1518
1519    if (object != null)
1520    {
1521      objects.push(object);
1522      types.push(OBJECT_TYPE);
1523
1524      if (extendedMetaData != null)
1525      {
1526        EStructuralFeature mixedFeature = extendedMetaData.getMixedFeature(object.eClass());
1527        if (mixedFeature != null)
1528        {
1529          mixedTargets.push(object.eGet(mixedFeature));
1530        }
1531        else
1532        {
1533          mixedTargets.push(null);
1534        }
1535      }
1536      else
1537      {
1538        mixedTargets.push(null);
1539      }
1540    }
1541    else
1542    {
1543      types.push(ERROR_TYPE);
1544    }
1545  }
1546
1547  protected EFactory getFactoryForPrefix(String JavaDoc prefix)
1548  {
1549    EFactory factory = (EFactory) prefixesToFactories.get(prefix);
1550    if (factory == null)
1551    {
1552      String JavaDoc uriString = helper.getURI(prefix);
1553      EPackage ePackage = getPackageForURI(uriString);
1554
1555      if (ePackage == null && uriString == null && prefix.equals(""))
1556      {
1557        ePackage = helper.getNoNamespacePackage();
1558      }
1559
1560
1561      if (ePackage != null)
1562      {
1563        factory = ePackage.getEFactoryInstance();
1564        prefixesToFactories.put(prefix, factory);
1565      }
1566    }
1567
1568    return factory;
1569  }
1570
1571  /**
1572   * Attempt to get the namespace for the given prefix, then return
1573   * ERegister.getPackage() or null.
1574   */

1575  protected EPackage getPackageForURI(String JavaDoc uriString)
1576  {
1577    if (uriString == null)
1578    {
1579      return null;
1580    }
1581
1582    EPackage ePackage =
1583      extendedMetaData == null ?
1584        packageRegistry.getEPackage(uriString) :
1585        extendedMetaData.getPackage(uriString);
1586
1587    if (ePackage != null && ePackage.eIsProxy())
1588    {
1589      ePackage = null;
1590    }
1591
1592    if (ePackage == null)
1593    {
1594      URI uri = URI.createURI(uriString);
1595      if (uri.scheme() == null)
1596      {
1597        // This only works for old globally registered things.
1598
for (Iterator JavaDoc entries = packageRegistry.entrySet().iterator(); entries.hasNext(); )
1599        {
1600          Map.Entry JavaDoc entry = (Map.Entry JavaDoc)entries.next();
1601          String JavaDoc nsURI = (String JavaDoc)entry.getKey();
1602          if (nsURI != null &&
1603                nsURI.endsWith(uriString) &&
1604                nsURI.charAt(nsURI.length() - uriString.length() - 1) == '/')
1605          {
1606            oldStyleProxyURIs = true;
1607            return (EPackage)entry.getValue();
1608          }
1609        }
1610      }
1611
1612      if (urisToLocations != null)
1613      {
1614        URI locationURI = (URI)urisToLocations.get(uriString);
1615        if (locationURI != null)
1616        {
1617          uri = locationURI;
1618        }
1619      }
1620
1621      String JavaDoc fragment = uri.fragment();
1622      Resource resource = null;
1623
1624      if ("java".equalsIgnoreCase(uri.scheme()) && uri.authority() != null)
1625      {
1626        try
1627        {
1628          String JavaDoc className = uri.authority();
1629          Class JavaDoc javaClass = Class.forName(className, true, Thread.currentThread().getContextClassLoader());
1630          Field JavaDoc field = javaClass.getField("eINSTANCE");
1631          resource = ((EPackage)field.get(null)).eResource();
1632        }
1633        catch (Exception JavaDoc exception)
1634        {
1635        }
1636      }
1637
1638      if (resource == null && resourceSet != null)
1639      {
1640        URI trimmedURI = uri.trimFragment();
1641        resource = resourceSet.getResource(trimmedURI, false);
1642        if (resource != null)
1643        {
1644          if (!resource.isLoaded())
1645          {
1646            try
1647            {
1648              resource.load(resourceSet.getLoadOptions());
1649            }
1650            catch (IOException JavaDoc exception)
1651            {
1652            }
1653          }
1654        }
1655        else if (!XMLResource.XML_SCHEMA_URI.equals(uriString))
1656        {
1657          try
1658          {
1659            InputStream JavaDoc inputStream = getURIConverter().createInputStream(trimmedURI);
1660            resource = resourceSet.createResource(trimmedURI);
1661            if (resource == null)
1662            {
1663              inputStream.close();
1664            }
1665            else
1666            {
1667              resource.load(inputStream, resourceSet.getLoadOptions());
1668            }
1669          }
1670          catch (IOException JavaDoc exception)
1671          {
1672          }
1673        }
1674      }
1675
1676      if (resource != null)
1677      {
1678        Object JavaDoc content = null;
1679        if (fragment != null)
1680        {
1681          content = resource.getEObject(fragment);
1682        }
1683        else
1684        {
1685          List JavaDoc contents = resource.getContents();
1686          if (!contents.isEmpty())
1687          {
1688            content = contents.get(0);
1689          }
1690        }
1691
1692        if (content instanceof EPackage)
1693        {
1694          ePackage = (EPackage)content;
1695          if (extendedMetaData != null)
1696          {
1697            extendedMetaData.putPackage(extendedMetaData.getNamespace(ePackage), ePackage);
1698          }
1699          else
1700          {
1701            resourceSet.getPackageRegistry().put(ePackage.getNsURI(), ePackage);
1702          }
1703        }
1704      }
1705    }
1706
1707    if (ePackage == null)
1708    {
1709      ePackage = handleMissingPackage(uriString);
1710    }
1711
1712    if (ePackage == null)
1713    {
1714      error
1715        (new PackageNotFoundException
1716           (uriString,
1717            getLocation(),
1718            getLineNumber(),
1719            getColumnNumber()));
1720    }
1721
1722    return ePackage;
1723  }
1724
1725  protected EPackage handleMissingPackage(String JavaDoc uriString)
1726  {
1727    if (XMLResource.XML_SCHEMA_URI.equals(uriString))
1728    {
1729      return xmlSchemaTypePackage;
1730    }
1731    else if (extendedMetaData != null)
1732    {
1733      if (recordUnknownFeature)
1734      {
1735        return extendedMetaData.demandPackage(uriString);
1736      }
1737      else if (contextFeature != null)
1738      {
1739        String JavaDoc namespace = extendedMetaData.getNamespace(contextFeature);
1740        String JavaDoc name = extendedMetaData.getName(contextFeature);
1741        EStructuralFeature wildcardFeature =
1742          extendedMetaData.getElementWildcardAffiliation(((EObject)objects.peek()).eClass(), namespace, name);
1743        if (wildcardFeature != null)
1744        {
1745          switch (extendedMetaData.getProcessingKind(wildcardFeature))
1746          {
1747            case ExtendedMetaData.LAX_PROCESSING:
1748            case ExtendedMetaData.SKIP_PROCESSING:
1749            {
1750              return extendedMetaData.demandPackage(uriString);
1751            }
1752          }
1753        }
1754      }
1755    }
1756
1757    return null;
1758  }
1759
1760  protected URIConverter getURIConverter()
1761  {
1762    return resourceSet.getURIConverter();
1763  }
1764
1765  protected void setFeatureValue(EObject object, EStructuralFeature feature, Object JavaDoc value)
1766  {
1767    setFeatureValue(object, feature, value, -1);
1768  }
1769
1770  /**
1771   * Set the given feature of the given object to the given value.
1772   */

1773  protected void setFeatureValue(EObject object, EStructuralFeature feature, Object JavaDoc value, int position)
1774  {
1775    try
1776    {
1777      helper.setValue(object, feature, value, position);
1778    }
1779    catch (RuntimeException JavaDoc e)
1780    {
1781      error
1782        (new IllegalValueException
1783           (object,
1784            feature,
1785            value,
1786            e,
1787            getLocation(),
1788            getLineNumber(),
1789            getColumnNumber()));
1790    }
1791  }
1792
1793  /**
1794   * Set the values for the given multi-valued forward reference.
1795   */

1796  protected void setFeatureValues(ManyReference reference)
1797  {
1798    List JavaDoc xmiExceptions = helper.setManyReference(reference, getLocation());
1799
1800    if (xmiExceptions != null)
1801      for (Iterator JavaDoc i = xmiExceptions.iterator(); i.hasNext(); )
1802      {
1803        XMIException exception = (XMIException) i.next();
1804        error(exception);
1805      }
1806  }
1807
1808  /**
1809   * Create a feature with the given name for the given object with the
1810   * given values.
1811   */

1812  protected void setAttribValue(EObject object, String JavaDoc name, String JavaDoc value)
1813  {
1814    int index = name.indexOf(":");
1815
1816    // We use null here instead of "" because an attribute without a prefix is considered to have the null target namespace...
1817
String JavaDoc prefix = null;
1818    String JavaDoc localName = name;
1819    if (index != -1)
1820    {
1821      prefix = name.substring(0, index);
1822      localName = name.substring(index + 1);
1823    }
1824
1825    EStructuralFeature feature = getFeature(object, prefix, localName, false);
1826    if (feature == null)
1827    {
1828      handleUnknownFeature(prefix, localName, false, object, value);
1829    }
1830    else
1831    {
1832      int kind = helper.getFeatureKind(feature);
1833
1834      if (kind == XMLHelper.DATATYPE_SINGLE || kind == XMLHelper.DATATYPE_IS_MANY)
1835      {
1836        setFeatureValue(object, feature, value, -2);
1837      }
1838      else
1839      {
1840        setValueFromId(object, (EReference)feature, value);
1841      }
1842    }
1843  }
1844
1845  /**
1846   * Create a ValueLine object and put it in the list
1847   * of references to resolve at the end of the document.
1848   */

1849  protected void setValueFromId(EObject object, EReference eReference, String JavaDoc ids)
1850  {
1851    StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(ids);
1852
1853    boolean isFirstID = true;
1854    boolean mustAdd = deferIDREFResolution;
1855    boolean mustAddOrNotOppositeIsMany = false;
1856
1857    int size = 0;
1858    String JavaDoc qName = null;
1859    int position = 0;
1860    while (st.hasMoreTokens())
1861    {
1862      String JavaDoc id = st.nextToken();
1863      int index = id.indexOf("#");
1864      if (index != -1)
1865      {
1866        if (index == 0)
1867        {
1868          id = id.substring(1);
1869        }
1870        else
1871        {
1872          Object JavaDoc oldAttributes = setAttributes(null);
1873          // Create a proxy in the correct way and pop it.
1874
//
1875
InternalEObject proxy =
1876            (InternalEObject)
1877              (qName == null ?
1878                 createObjectFromFeatureType(object, eReference) :
1879                 createObjectFromTypeName(object, qName, eReference));
1880          setAttributes(oldAttributes);
1881          handleProxy(proxy, id);
1882          objects.pop();
1883          types.pop();
1884          mixedTargets.pop();
1885
1886          qName = null;
1887          ++position;
1888          continue;
1889        }
1890      }
1891      else if (id.indexOf(":") != -1)
1892      {
1893        qName = id;
1894        continue;
1895      }
1896
1897      if (!deferIDREFResolution)
1898      {
1899        if (isFirstID)
1900        {
1901          EReference eOpposite = eReference.getEOpposite();
1902          mustAdd = eOpposite == null || eOpposite.isTransient() || eReference.isMany();
1903          mustAddOrNotOppositeIsMany = mustAdd || !eOpposite.isMany();
1904          isFirstID = false;
1905        }
1906  
1907        if (mustAddOrNotOppositeIsMany)
1908        {
1909          EObject resolvedEObject = xmlResource.getEObject(id);
1910          if (resolvedEObject != null)
1911          {
1912            setFeatureValue(object, eReference, resolvedEObject);
1913            qName = null;
1914            ++position;
1915            continue;
1916          }
1917        }
1918      }
1919
1920      if (mustAdd)
1921      {
1922        if (size == capacity)
1923          growArrays();
1924
1925        identifiers[size] = id;
1926        positions[size] = position;
1927        ++size;
1928      }
1929      qName = null;
1930      ++position;
1931    }
1932
1933    if (position == 0)
1934    {
1935      setFeatureValue(object, eReference, null, -2);
1936    }
1937    else if (size <= REFERENCE_THRESHOLD)
1938    {
1939      for (int i = 0; i < size; i++)
1940      {
1941        SingleReference ref = new SingleReference
1942                                   (object,
1943                                    eReference,
1944                                    identifiers[i],
1945                                    positions[i],
1946                                    getLineNumber(),
1947                                    getColumnNumber());
1948        forwardSingleReferences.add(ref);
1949      }
1950    }
1951    else
1952    {
1953      Object JavaDoc[] values = new Object JavaDoc[size];
1954      int[] currentPositions = new int[size];
1955      System.arraycopy(identifiers, 0, values, 0, size);
1956      System.arraycopy(positions, 0, currentPositions, 0, size);
1957
1958      ManyReference ref = new ManyReference
1959                                 (object,
1960                                  eReference,
1961                                  values,
1962                                  currentPositions,
1963                                  getLineNumber(),
1964                                  getColumnNumber());
1965      forwardManyReferences.add(ref);
1966    }
1967  }
1968
1969  protected void handleProxy(InternalEObject proxy, String JavaDoc uriLiteral)
1970  {
1971    URI proxyURI;
1972    if (oldStyleProxyURIs)
1973    {
1974      proxy.eSetProxyURI(proxyURI = URI.createURI(uriLiteral.startsWith("/") ? uriLiteral : "/" + uriLiteral));
1975    }
1976    else
1977    {
1978      URI uri = URI.createURI(uriLiteral);
1979      if (resolve &&
1980            uri.isRelative() &&
1981            uri.hasRelativePath() &&
1982            (extendedMetaData == null ?
1983              !packageRegistry.containsKey(uri.trimFragment().toString()) :
1984              extendedMetaData.getPackage(uri.trimFragment().toString()) == null))
1985      {
1986        uri = helper.resolve(uri, resourceURI);
1987      }
1988      proxy.eSetProxyURI(proxyURI = uri);
1989    }
1990
1991    // Test for a same document reference that would usually be handled as an IDREF.
1992
//
1993
if (proxyURI.trimFragment().equals(resourceURI))
1994    {
1995      sameDocumentProxies.add(proxy);
1996    }
1997  }
1998
1999  protected void growArrays() {
2000    int oldCapacity = capacity;
2001    capacity = capacity * 2;
2002    Object JavaDoc[] newIdentifiers = new Object JavaDoc[capacity];
2003    int[] newPositions = new int[capacity];
2004    System.arraycopy(identifiers, 0, newIdentifiers, 0, oldCapacity);
2005    System.arraycopy(positions, 0, newPositions, 0, oldCapacity);
2006    identifiers = newIdentifiers;
2007    positions = newPositions;
2008  }
2009
2010  /**
2011   * Returns true if there was an error in the last XML element; false otherwise.
2012   */

2013  protected boolean isError()
2014  {
2015    return types.peek() == ERROR_TYPE;
2016  }
2017
2018  static class EClassFeatureNamePair
2019  {
2020    public EClass eClass;
2021    public String JavaDoc featureName;
2022    public String JavaDoc namespaceURI;
2023    public boolean isElement;
2024
2025    public boolean equals(Object JavaDoc that)
2026    {
2027      EClassFeatureNamePair typedThat = (EClassFeatureNamePair)that;
2028      return
2029        typedThat.eClass == eClass &&
2030        typedThat.isElement == isElement &&
2031        typedThat.featureName.equals(featureName) &&
2032        (typedThat.namespaceURI != null ? typedThat.namespaceURI.equals(namespaceURI): namespaceURI == null);
2033    }
2034
2035    public int hashCode()
2036    {
2037      return eClass.hashCode() ^ featureName.hashCode() ^ (namespaceURI == null ? 0 : namespaceURI.hashCode()) + (isElement ? 0 : 1);
2038    }
2039  }
2040
2041  Map JavaDoc eClassFeatureNamePairToEStructuralFeatureMap = null;
2042  EClassFeatureNamePair eClassFeatureNamePair = new EClassFeatureNamePair();
2043
2044  /**
2045   * @deprecated
2046   */

2047  protected EStructuralFeature getFeature(EObject object, String JavaDoc prefix, String JavaDoc name)
2048  {
2049    EClass eClass = object.eClass();
2050    String JavaDoc namespace = helper.getURI(prefix);
2051    EStructuralFeature result = helper.getFeature(eClass, namespace, name, true);
2052    if (result == null)
2053    {
2054      helper.getFeature(eClass, namespace, name, false);
2055    }
2056    return result;
2057  }
2058
2059  /**
2060   * Get the EStructuralFeature from the metaObject for the given object
2061   * and feature name.
2062   */

2063  protected EStructuralFeature getFeature(EObject object, String JavaDoc prefix, String JavaDoc name, boolean isElement)
2064  {
2065    String JavaDoc namespace = helper.getURI(prefix);
2066    EClass eClass = object.eClass();
2067    eClassFeatureNamePair.eClass = eClass;
2068    eClassFeatureNamePair.featureName = name;
2069    eClassFeatureNamePair.namespaceURI = namespace;
2070    eClassFeatureNamePair.isElement = isElement;
2071    EStructuralFeature result = (EStructuralFeature)eClassFeatureNamePairToEStructuralFeatureMap.get(eClassFeatureNamePair);
2072    if (result == null)
2073    {
2074      result = helper.getFeature(eClass, namespace, name, isElement);
2075
2076      if (result == null)
2077      {
2078        if (extendedMetaData != null)
2079        {
2080          EStructuralFeature wildcardFeature =
2081            isElement ?
2082              extendedMetaData.getElementWildcardAffiliation(eClass, namespace, name) :
2083              extendedMetaData.getAttributeWildcardAffiliation(eClass, namespace, name);
2084          if (wildcardFeature != null)
2085          {
2086            switch (extendedMetaData.getProcessingKind(wildcardFeature))
2087            {
2088              case ExtendedMetaData.LAX_PROCESSING:
2089              case ExtendedMetaData.SKIP_PROCESSING:
2090              {
2091                // EATM Demand create metadata.
2092
result = extendedMetaData.demandFeature(namespace, name, isElement);
2093                break;
2094              }
2095            }
2096          }
2097        }
2098        else
2099        {
2100          // EATM Call the deprecated method which does the same thing
2101
// but might have an override in older code.
2102
result = getFeature(object, prefix, name);
2103        }
2104      }
2105
2106      EClassFeatureNamePair entry = new EClassFeatureNamePair();
2107      entry.eClass = eClass;
2108      entry.featureName = name;
2109      entry.namespaceURI = namespace;
2110      entry.isElement = isElement;
2111      eClassFeatureNamePairToEStructuralFeatureMap.put(entry, result);
2112    }
2113
2114    return result;
2115  }
2116
2117  /**
2118   * Searches the array of bytes to determine the XML
2119   * encoding.
2120   */

2121  public static String JavaDoc getXMLEncoding(byte[] bytes)
2122  {
2123    String JavaDoc javaEncoding = null;
2124
2125    if (bytes.length >= 4)
2126    {
2127      if (((bytes[0] == -2) && (bytes[1] == -1)) ||
2128          ((bytes[0] == 0) && (bytes[1] == 60)))
2129        javaEncoding = "UnicodeBig";
2130      else if (((bytes[0] == -1) && (bytes[1] == -2)) ||
2131                ((bytes[0] == 60) && (bytes[1] == 0)))
2132        javaEncoding = "UnicodeLittle";
2133      else if ((bytes[0] == -17) && (bytes[1] == -69) && (bytes[2] == -65))
2134        javaEncoding = "UTF8";
2135    }
2136
2137    String JavaDoc header = null;
2138
2139    try
2140    {
2141      if (javaEncoding != null)
2142        header = new String JavaDoc(bytes, 0, bytes.length, javaEncoding);
2143      else
2144        header = new String JavaDoc(bytes, 0, bytes.length);
2145    }
2146    catch (UnsupportedEncodingException JavaDoc e)
2147    {
2148      return null;
2149    }
2150
2151    if (!header.startsWith("<?xml"))
2152      return "UTF-8";
2153
2154    int endOfXMLPI = header.indexOf("?>");
2155    int encodingIndex = header.indexOf("encoding", 6);
2156
2157    if ((encodingIndex == -1) || (encodingIndex > endOfXMLPI))
2158      return "UTF-8";
2159
2160    int firstQuoteIndex = header.indexOf("\"", encodingIndex);
2161    int lastQuoteIndex;
2162
2163    if ((firstQuoteIndex == -1) || (firstQuoteIndex > endOfXMLPI))
2164    {
2165      firstQuoteIndex = header.indexOf("'", encodingIndex);
2166      lastQuoteIndex = header.indexOf("'", firstQuoteIndex + 1);
2167    }
2168    else
2169      lastQuoteIndex = header.indexOf("\"", firstQuoteIndex + 1);
2170
2171    return header.substring(firstQuoteIndex + 1, lastQuoteIndex);
2172  }
2173
2174  protected void handleComment(String JavaDoc comment)
2175  {
2176    FeatureMap featureMap = (FeatureMap)mixedTargets.peek();
2177    featureMap.add(XMLTypePackage.eINSTANCE.getXMLTypeDocumentRoot_Comment(), comment);
2178    text = null;
2179  }
2180  protected void handleMixedText()
2181  {
2182    FeatureMap featureMap = (FeatureMap)mixedTargets.peek();
2183    featureMap.add(XMLTypePackage.eINSTANCE.getXMLTypeDocumentRoot_Text(), text.toString());
2184    text = null;
2185  }
2186
2187  protected void handleCDATA()
2188  {
2189    FeatureMap featureMap = (FeatureMap)mixedTargets.peek();
2190    featureMap.add(XMLTypePackage.eINSTANCE.getXMLTypeDocumentRoot_CDATA(), text.toString());
2191    text = null;
2192  }
2193}
2194
Popular Tags