KickJava   Java API By Example, From Geeks To Geeks.

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


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: XMLHelperImpl.java,v 1.29 2005/06/10 13:57:51 elena Exp $
16  */

17 package org.eclipse.emf.ecore.xmi.impl;
18
19
20 import java.util.ArrayList JavaDoc;
21 import java.util.HashMap JavaDoc;
22 import java.util.Iterator JavaDoc;
23 import java.util.List JavaDoc;
24 import java.util.Map JavaDoc;
25 import java.util.StringTokenizer JavaDoc;
26 import java.util.TreeMap JavaDoc;
27
28 import org.eclipse.emf.common.util.BasicEList;
29 import org.eclipse.emf.common.util.BasicEMap;
30 import org.eclipse.emf.common.util.EMap;
31 import org.eclipse.emf.common.util.URI;
32 import org.eclipse.emf.common.util.UniqueEList;
33 import org.eclipse.emf.ecore.EClass;
34 import org.eclipse.emf.ecore.EClassifier;
35 import org.eclipse.emf.ecore.EDataType;
36 import org.eclipse.emf.ecore.EFactory;
37 import org.eclipse.emf.ecore.ENamedElement;
38 import org.eclipse.emf.ecore.EObject;
39 import org.eclipse.emf.ecore.EPackage;
40 import org.eclipse.emf.ecore.EReference;
41 import org.eclipse.emf.ecore.EStructuralFeature;
42 import org.eclipse.emf.ecore.EcorePackage;
43 import org.eclipse.emf.ecore.InternalEObject;
44 import org.eclipse.emf.ecore.resource.Resource;
45 import org.eclipse.emf.ecore.util.EcoreUtil;
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.DanglingHREFException;
50 import org.eclipse.emf.ecore.xmi.IllegalValueException;
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.xml.type.SimpleAnyType;
55 import org.eclipse.emf.ecore.xml.type.XMLTypePackage;
56 import org.eclipse.emf.ecore.xml.type.internal.QName;
57
58
59 /**
60  * This class handles the package to use when there is no XML
61  * namespace in an XML file.
62  */

63 public class XMLHelperImpl implements XMLHelper
64 {
65   protected static final Integer JavaDoc INTEGER_DATATYPE_IS_MANY = new Integer JavaDoc(DATATYPE_IS_MANY);
66   protected static final Integer JavaDoc INTEGER_DATATYPE_SINGLE = new Integer JavaDoc(DATATYPE_SINGLE);
67   protected static final Integer JavaDoc INTEGER_IS_MANY_ADD = new Integer JavaDoc(IS_MANY_ADD);
68   protected static final Integer JavaDoc INTEGER_IS_MANY_MOVE = new Integer JavaDoc(IS_MANY_MOVE);
69
70   protected EPackage noNamespacePackage;
71   protected XMLResource.XMLMap xmlMap;
72   protected ExtendedMetaData extendedMetaData;
73   protected boolean laxFeatureProcessing;
74   protected EPackage.Registry packageRegistry;
75   protected XMLResource resource;
76   protected URI resourceURI;
77   protected boolean deresolve;
78   protected Map JavaDoc packages;
79   protected Map JavaDoc featuresToKinds;
80   protected String JavaDoc processDanglingHREF;
81   protected DanglingHREFException danglingHREFException;
82   protected EMap prefixesToURIs;
83   protected Map JavaDoc anyPrefixesToURIs;
84   protected NamespaceSupport namespaceSupport;
85   protected EClass anySimpleType;
86   // true if seen xmlns="" declaration
87
protected boolean seenEmptyStringMapping;
88   protected EPackage xmlSchemaTypePackage = XMLTypePackage.eINSTANCE;
89   protected List JavaDoc allPrefixToURI;
90   protected boolean checkForDuplicates;
91   protected boolean mustHavePrefix;
92   
93   private EPackage previousPackage;
94   private String JavaDoc previousNS;
95   
96   public static String JavaDoc saveString(Map JavaDoc options, List JavaDoc contents, String JavaDoc encoding, XMLHelper helper) throws Exception JavaDoc
97   {
98     if (helper == null)
99     {
100       helper = new XMIHelperImpl();
101     }
102     if (!options.containsKey(XMLResource.OPTION_DECLARE_XML))
103     {
104       options = new HashMap JavaDoc(options);
105       options.put(XMLResource.OPTION_DECLARE_XML, Boolean.FALSE);
106     }
107     XMLSaveImpl save = new XMISaveImpl(options, helper, encoding);
108     
109     if (Boolean.TRUE.equals(options.get(XMLResource.OPTION_DEFER_IDREF_RESOLUTION)))
110     {
111       ((XMLHelperImpl)helper).checkForDuplicates = true;
112     }
113     
114     ((XMLHelperImpl)helper).processDanglingHREF = (String JavaDoc)options.get(XMLResource.OPTION_PROCESS_DANGLING_HREF);
115     save.traverse(contents);
116     if (save.useCache)
117     {
118       ConfigurationCache.INSTANCE.releasePrinter(save.doc);
119       if (save.escape != null)
120       {
121         ConfigurationCache.INSTANCE.releaseEscape(save.escape);
122       }
123     }
124     char[] chars = save.toChar();
125     return new String JavaDoc(chars);
126   }
127
128   public XMLHelperImpl()
129   {
130     super();
131     packages = new HashMap JavaDoc();
132     featuresToKinds = new HashMap JavaDoc();
133     prefixesToURIs = new BasicEMap();
134     anyPrefixesToURIs = new HashMap JavaDoc();
135     allPrefixToURI = new ArrayList JavaDoc();
136     namespaceSupport = new NamespaceSupport();
137   }
138
139   public XMLHelperImpl(XMLResource resource)
140   {
141     this();
142     setResource(resource);
143   }
144   
145   public void setOptions (Map JavaDoc options)
146   {
147     laxFeatureProcessing = Boolean.TRUE.equals(options.get(XMLResource.OPTION_LAX_FEATURE_PROCESSING));
148   }
149
150   public void setNoNamespacePackage(EPackage pkg)
151   {
152     noNamespacePackage = pkg;
153   }
154
155   public EPackage getNoNamespacePackage()
156   {
157     return
158       noNamespacePackage != null ?
159         noNamespacePackage :
160         extendedMetaData != null ?
161           extendedMetaData.getPackage(null) :
162           null;
163   }
164
165   public void setXMLMap(XMLResource.XMLMap map)
166   {
167     xmlMap = map;
168     if (map != null && map.getNoNamespacePackage() != null)
169     {
170       setNoNamespacePackage(map.getNoNamespacePackage());
171     }
172   }
173
174   public XMLResource.XMLMap getXMLMap()
175   {
176     return xmlMap;
177   }
178
179   public void setExtendedMetaData(ExtendedMetaData extendedMetaData)
180   {
181     this.extendedMetaData = extendedMetaData;
182     if (extendedMetaData != null && extendedMetaData.getPackage(null) != null)
183     {
184       setNoNamespacePackage(extendedMetaData.getPackage(null));
185     }
186   }
187
188   public ExtendedMetaData getExtendedMetaData()
189   {
190     return extendedMetaData;
191   }
192
193   public XMLResource getResource()
194   {
195     return resource;
196   }
197
198   public void setResource(XMLResource resource)
199   {
200     this.resource = resource;
201     if (resource == null)
202     {
203       resourceURI = null;
204       deresolve = false;
205       packageRegistry = EPackage.Registry.INSTANCE;
206     }
207     else
208     {
209       resourceURI = resource.getURI();
210       deresolve = resourceURI != null && !resourceURI.isRelative() && resourceURI.isHierarchical();
211       packageRegistry = resource.getResourceSet() == null ? EPackage.Registry.INSTANCE : resource.getResourceSet().getPackageRegistry();
212     }
213   }
214
215   public Object JavaDoc getValue(EObject obj, EStructuralFeature f)
216   {
217     return obj.eGet(f, false);
218   }
219
220   public String JavaDoc getQName(EClass c)
221   {
222     String JavaDoc name = getName(c);
223     if (xmlMap != null)
224     {
225       XMLResource.XMLInfo clsInfo = xmlMap.getInfo(c);
226
227       if (clsInfo != null)
228       {
229         String JavaDoc targetNamespace = clsInfo.getTargetNamespace();
230         return getQName(targetNamespace, name);
231       }
232     }
233
234     return getQName(c.getEPackage(), name);
235   }
236
237   public void populateNameInfo(NameInfo nameInfo, EClass c)
238   {
239     String JavaDoc name = getName(c);
240     nameInfo.setLocalPart(name);
241     if (xmlMap != null)
242     {
243       XMLResource.XMLInfo clsInfo = xmlMap.getInfo(c);
244
245       if (clsInfo != null)
246       {
247         String JavaDoc targetNamespace = clsInfo.getTargetNamespace();
248         nameInfo.setNamespaceURI(targetNamespace);
249         nameInfo.setQualifiedName(getQName(targetNamespace, name));
250         return;
251       }
252     }
253     getQName(nameInfo, c.getEPackage(), name);
254   }
255
256   public String JavaDoc getQName(EDataType c)
257   {
258     String JavaDoc name = getName(c);
259     if (xmlMap != null)
260     {
261       XMLResource.XMLInfo clsInfo = xmlMap.getInfo(c);
262
263       if (clsInfo != null)
264       {
265         String JavaDoc targetNamespace = clsInfo.getTargetNamespace();
266         return getQName(targetNamespace, name);
267       }
268     }
269
270     return getQName(c.getEPackage(), name);
271   }
272
273   public void populateNameInfo(NameInfo nameInfo, EDataType eDataType)
274   {
275     String JavaDoc name = getName(eDataType);
276     nameInfo.setLocalPart(name);
277     if (xmlMap != null)
278     {
279       XMLResource.XMLInfo clsInfo = xmlMap.getInfo(eDataType);
280
281       if (clsInfo != null)
282       {
283         String JavaDoc targetNamespace = clsInfo.getTargetNamespace();
284         nameInfo.setNamespaceURI(targetNamespace);
285         nameInfo.setQualifiedName(getQName(targetNamespace, name));
286         return;
287       }
288     }
289     getQName(nameInfo, eDataType.getEPackage(), name);
290   }
291
292   public String JavaDoc getQName(EStructuralFeature feature)
293   {
294     if (extendedMetaData != null)
295     {
296       String JavaDoc namespace = extendedMetaData.getNamespace(feature);
297       String JavaDoc name = extendedMetaData.getName(feature);
298       String JavaDoc result = name;
299
300       // We need to be careful that we don't end up requiring the no namespace package
301
// just because the feature is unqualified.
302
//
303
if (namespace != null)
304       {
305         // There really must be a package.
306
//
307
EPackage ePackage;
308         if (namespace.equals(previousNS))
309         {
310           ePackage = previousPackage;
311         }
312         else
313         {
314           ePackage = extendedMetaData.getPackage(namespace);
315           if (ePackage == null)
316           {
317             ePackage = extendedMetaData.demandPackage(namespace);
318           }
319           previousPackage = ePackage;
320           previousNS = namespace;
321         }
322         
323         result = getQName(ePackage, name);
324
325         // We must have a qualifier for an attribute that needs qualified.
326
//
327
if (result.length() == name.length() && extendedMetaData.getFeatureKind(feature) == ExtendedMetaData.ATTRIBUTE_FEATURE)
328         {
329           result = getQName(ePackage, name, true);
330         }
331       }
332       return result;
333     }
334
335     String JavaDoc name = getName(feature);
336     if (xmlMap != null)
337     {
338       XMLResource.XMLInfo info = xmlMap.getInfo(feature);
339       if (info != null)
340       {
341         return getQName(info.getTargetNamespace(), name);
342       }
343     }
344
345     return name;
346   }
347
348   public void populateNameInfo(NameInfo nameInfo, EStructuralFeature feature)
349   {
350     if (extendedMetaData != null)
351     {
352       String JavaDoc namespace = extendedMetaData.getNamespace(feature);
353       String JavaDoc name = extendedMetaData.getName(feature);
354       nameInfo.setNamespaceURI(namespace);
355       nameInfo.setLocalPart(name);
356       nameInfo.setQualifiedName(name);
357
358       // We need to be careful that we don't end up requiring the no namespace package
359
// just because the feature is unqualified.
360
//
361
if (namespace != null)
362       {
363         // There really must be a package.
364
//
365
EPackage ePackage = extendedMetaData.getPackage(namespace);
366         if (ePackage == null)
367         {
368           ePackage = extendedMetaData.demandPackage(namespace);
369         }
370
371         String JavaDoc result = getQName(nameInfo, ePackage, name);
372
373         // We must have a qualifier for an attribute that needs qualified.
374
//
375
if (result.length() == name.length() && extendedMetaData.getFeatureKind(feature) == ExtendedMetaData.ATTRIBUTE_FEATURE)
376         {
377           getQName(nameInfo, ePackage, name, true);
378         }
379       }
380     }
381     else
382     {
383       String JavaDoc name = getName(feature);
384       nameInfo.setNamespaceURI(null);
385       nameInfo.setLocalPart(name);
386       if (xmlMap != null)
387       {
388         XMLResource.XMLInfo info = xmlMap.getInfo(feature);
389         if (info != null)
390         {
391           String JavaDoc targetNamespace = info.getTargetNamespace();
392           nameInfo.setNamespaceURI(targetNamespace);
393           nameInfo.setQualifiedName(getQName(targetNamespace, name));
394         }
395       }
396       nameInfo.setQualifiedName(name);
397     }
398   }
399   
400   protected String JavaDoc getQName(NameInfo nameInfo, EPackage ePackage, String JavaDoc name)
401   {
402     String JavaDoc qname = getQName(nameInfo, ePackage, name, mustHavePrefix);
403     nameInfo.setQualifiedName(qname);
404     return qname;
405   }
406
407   protected String JavaDoc getQName(NameInfo nameInfo, EPackage ePackage, String JavaDoc name, boolean mustHavePrefix)
408   {
409     String JavaDoc nsPrefix = getPrefix(ePackage, mustHavePrefix);
410     nameInfo.setNamespaceURI(getNamespaceURI(nsPrefix));
411     if ("".equals(nsPrefix))
412     {
413       return name;
414     }
415     else if (name.length() == 0)
416     {
417       return nsPrefix;
418     }
419     else
420     {
421       return nsPrefix + ":" + name;
422     }
423   }
424
425   protected String JavaDoc getQName(EPackage ePackage, String JavaDoc name)
426   {
427     return getQName(ePackage, name, mustHavePrefix);
428   }
429
430   protected String JavaDoc getQName(EPackage ePackage, String JavaDoc name, boolean mustHavePrefix)
431   {
432     String JavaDoc nsPrefix = getPrefix(ePackage, mustHavePrefix);
433     if ("".equals(nsPrefix))
434     {
435       return name;
436     }
437     else if (name.length() == 0)
438     {
439       return nsPrefix;
440     }
441     else
442     {
443       return nsPrefix + ":" + name;
444     }
445   }
446
447   public String JavaDoc getPrefix(EPackage ePackage)
448   {
449     return getPrefix(ePackage, mustHavePrefix);
450   }
451   
452   public String JavaDoc getNamespaceURI(String JavaDoc prefix)
453   {
454     String JavaDoc namespaceURI = namespaceSupport.getURI(prefix);
455     if (namespaceURI == null)
456     {
457       namespaceURI = (String JavaDoc)prefixesToURIs.get(prefix);
458     }
459     return namespaceURI;
460   }
461
462   protected String JavaDoc getPrefix(EPackage ePackage, boolean mustHavePrefix)
463   {
464     String JavaDoc nsPrefix = (String JavaDoc)packages.get(ePackage);
465     if (nsPrefix == null || mustHavePrefix && nsPrefix.length() == 0)
466     {
467       String JavaDoc nsURI =
468         xmlSchemaTypePackage == ePackage ?
469           XMLResource.XML_SCHEMA_URI :
470           extendedMetaData == null ?
471             ePackage.getNsURI() :
472             extendedMetaData.getNamespace(ePackage);
473
474       boolean found = false;
475       for (Iterator JavaDoc i = prefixesToURIs.entrySet().iterator(); i.hasNext(); )
476       {
477         Map.Entry JavaDoc entry = (Map.Entry JavaDoc)i.next();
478         if (nsURI == null ? entry.getValue() == null : nsURI.equals(entry.getValue()))
479         {
480           nsPrefix = (String JavaDoc)entry.getKey();
481           if (!mustHavePrefix || nsPrefix.length() > 0)
482           {
483             found = true;
484             break;
485           }
486         }
487       }
488
489       if (!found)
490       {
491         // for any content prefix to URI mapping could be in namespace context
492
nsPrefix = namespaceSupport.getPrefix(nsURI);
493         if (nsPrefix != null)
494         {
495           return nsPrefix;
496         }
497
498         if (nsURI != null)
499         {
500           nsPrefix = xmlSchemaTypePackage == ePackage ? "xsd" : ePackage.getNsPrefix();
501         }
502         if (nsPrefix == null)
503         {
504           nsPrefix = mustHavePrefix ? "_" : "";
505         }
506   
507         if (prefixesToURIs.containsKey(nsPrefix))
508         {
509           String JavaDoc currentValue = (String JavaDoc)prefixesToURIs.get(nsPrefix);
510           if (currentValue == null ? nsURI != null : !currentValue.equals(nsURI))
511           {
512             int index = 1;
513             while (prefixesToURIs.containsKey(nsPrefix + "_" + index))
514             {
515               ++index;
516             }
517             nsPrefix += "_" + index;
518           }
519         }
520
521         prefixesToURIs.put(nsPrefix, nsURI);
522       }
523
524       if (!packages.containsKey(ePackage))
525       {
526         packages.put(ePackage, nsPrefix);
527       }
528     }
529
530     return nsPrefix;
531   }
532
533   public List JavaDoc getPrefixes(EPackage ePackage)
534   {
535     List JavaDoc result = new UniqueEList();
536     result.add(getPrefix(ePackage));
537     String JavaDoc namespace = extendedMetaData == null ? ePackage.getNsURI() : extendedMetaData.getNamespace(ePackage);
538     for (Iterator JavaDoc i = prefixesToURIs.entrySet().iterator(); i.hasNext(); )
539     {
540       Map.Entry JavaDoc entry = (Map.Entry JavaDoc)i.next();
541       if (namespace == null ? entry.getValue() == null : namespace.equals(entry.getValue()))
542       {
543         result.add(entry.getKey());
544       }
545     }
546     return result;
547   }
548
549   protected String JavaDoc getQName(String JavaDoc uri, String JavaDoc name)
550   {
551     if (uri == null)
552     {
553       EPackage theNoNamespacePackage = getNoNamespacePackage();
554       if (theNoNamespacePackage != null)
555       {
556         packages.put(theNoNamespacePackage, "");
557       }
558
559       return name;
560     }
561
562     EPackage ePackage =
563       extendedMetaData == null ?
564         EPackage.Registry.INSTANCE.getEPackage(uri) :
565         extendedMetaData.getPackage(uri);
566     if (ePackage == null)
567     {
568       if (extendedMetaData != null)
569       {
570         return getQName(extendedMetaData.demandPackage(uri), name);
571       }
572       else
573       {
574         // EATM this would be wrong.
575
return name;
576       }
577     }
578     else
579     {
580       return getQName(ePackage, name);
581     }
582   }
583
584   public String JavaDoc getName(ENamedElement obj)
585   {
586     if (extendedMetaData != null)
587     {
588       return
589         obj instanceof EStructuralFeature ?
590             extendedMetaData.getName((EStructuralFeature)obj) :
591               extendedMetaData.getName((EClassifier)obj);
592     }
593     
594     if (xmlMap != null)
595     {
596       XMLResource.XMLInfo info = xmlMap.getInfo(obj);
597       if (info != null)
598       {
599          String JavaDoc result = info.getName();
600          if (result != null)
601          {
602            return result;
603          }
604       }
605     }
606
607     return obj.getName();
608   }
609
610
611   public String JavaDoc getID(EObject obj)
612   {
613     return resource == null ? null : resource.getID(obj);
614   }
615
616   protected String JavaDoc getURIFragmentQuery(Resource containingResource, EObject object)
617   {
618     return null;
619   }
620
621   protected String JavaDoc getURIFragment(Resource containingResource, EObject object)
622   {
623     String JavaDoc result = containingResource.getURIFragment(object);
624     if (result.charAt(0) != '/')
625     {
626       String JavaDoc query = getURIFragmentQuery(containingResource, object);
627       if (query != null)
628       {
629         result += "?" + query + "?";
630       }
631     }
632     return result;
633   }
634
635   public String JavaDoc getIDREF(EObject obj)
636   {
637     return resource == null ? null : getURIFragment(resource, obj);
638   }
639
640   protected URI handleDanglingHREF(EObject object)
641   {
642     if (!XMLResource.OPTION_PROCESS_DANGLING_HREF_DISCARD.equals(processDanglingHREF))
643     {
644       DanglingHREFException exception = new DanglingHREFException(
645         "The object '" + object + "' is not contained in a resource.",
646         resource.getURI() == null ? "unknown" : resource.getURI().toString(), 0, 0);
647  
648       if (danglingHREFException == null)
649       {
650         danglingHREFException = exception;
651       }
652    
653       resource.getErrors().add(exception);
654     }
655
656     return null;
657   }
658
659   public String JavaDoc getHREF(EObject obj)
660   {
661     InternalEObject o = (InternalEObject) obj;
662
663     URI objectURI = o.eProxyURI();
664     if (objectURI == null)
665     {
666       Resource otherResource = obj.eResource();
667       if (otherResource == null)
668       {
669         objectURI = handleDanglingHREF(obj);
670         if (objectURI == null)
671         {
672           return null;
673         }
674       }
675       else
676       {
677         objectURI = getHREF(otherResource, obj);
678       }
679     }
680
681     objectURI = deresolve(objectURI);
682
683     return objectURI.toString();
684   }
685
686   protected URI getHREF(Resource otherResource, EObject obj)
687   {
688     return otherResource.getURI().appendFragment(getURIFragment(otherResource, obj));
689   }
690
691   public URI deresolve(URI uri)
692   {
693     if (deresolve && !uri.isRelative())
694     {
695       URI deresolvedURI = uri.deresolve(resourceURI, true, true, false);
696       if (deresolvedURI.hasRelativePath())
697       {
698         uri = deresolvedURI;
699       }
700     }
701
702     return uri;
703   }
704
705   public int getFeatureKind(EStructuralFeature feature)
706   {
707     Integer JavaDoc kind = (Integer JavaDoc) featuresToKinds.get(feature);
708     if (kind != null)
709     {
710       return kind.intValue();
711     }
712     else
713     {
714       computeFeatureKind(feature);
715       kind = (Integer JavaDoc) featuresToKinds.get(feature);
716       if (kind != null)
717       {
718         return kind.intValue();
719       }
720       else
721       {
722         return OTHER;
723       }
724     }
725   }
726
727   public EObject createObject(EFactory eFactory, String JavaDoc classXMIName)
728   {
729     EPackage ePackage = eFactory.getEPackage();
730     if (extendedMetaData != null)
731     {
732       EClassifier eClassifier = extendedMetaData.getType(ePackage, classXMIName);
733       if (eClassifier == null)
734       {
735         return null;
736       }
737       else if (eClassifier instanceof EClass)
738       {
739         return eFactory.create((EClass)eClassifier);
740       }
741       else
742       {
743         SimpleAnyType result = (SimpleAnyType)EcoreUtil.create(anySimpleType);
744         result.setInstanceType((EDataType)eClassifier);
745         return result;
746       }
747     }
748     else
749     {
750       EClass eClass = (EClass)ePackage.getEClassifier(classXMIName);
751       if (eClass == null && xmlMap != null)
752       {
753         eClass = (EClass) xmlMap.getClassifier(ePackage.getNsURI(), classXMIName);
754       }
755   
756       if (eClass != null)
757       {
758         return eFactory.create(eClass);
759       }
760       else
761       {
762         return null;
763       }
764     }
765   }
766
767   public EStructuralFeature getFeature(EClass eClass, String JavaDoc namespaceURI, String JavaDoc name)
768   {
769     EStructuralFeature feature = getFeatureWithoutMap(eClass, name);
770     if (feature == null && xmlMap != null)
771     {
772       feature = xmlMap.getFeature(eClass, namespaceURI, name);
773       if (feature != null)
774       {
775         computeFeatureKind(feature);
776       }
777     }
778
779     return feature;
780   }
781
782   public EStructuralFeature getFeature(EClass eClass, String JavaDoc namespaceURI, String JavaDoc name, boolean isElement)
783   {
784     if (extendedMetaData != null)
785     {
786       EStructuralFeature eStructuralFeature =
787         isElement ?
788           extendedMetaData.getElement(eClass, namespaceURI, name) :
789           extendedMetaData.getAttribute(eClass, namespaceURI == "" ? null : namespaceURI, name);
790       if (eStructuralFeature != null)
791       {
792         computeFeatureKind(eStructuralFeature);
793       }
794       else
795       {
796         eStructuralFeature = getFeature(eClass, namespaceURI, name);
797
798         // Only if the feature kind is unspecified should we return a match.
799
// Otherwise, we might return an attribute feature when an element is required,
800
// or vice versa. This also can be controlled by XMLResource.OPTION_LAX_FEATURE_PROCESSING.
801
//
802
if (!laxFeatureProcessing && eStructuralFeature != null &&
803               extendedMetaData.getFeatureKind(eStructuralFeature) != ExtendedMetaData.UNSPECIFIED_FEATURE)
804         {
805           eStructuralFeature = null;
806         }
807       }
808
809       return eStructuralFeature;
810     }
811
812     return getFeature(eClass, namespaceURI, name);
813   }
814
815   protected EStructuralFeature getFeatureWithoutMap(EClass eClass, String JavaDoc name)
816   {
817     EStructuralFeature feature = eClass.getEStructuralFeature(name);
818
819     if (feature != null)
820       computeFeatureKind(feature);
821
822     return feature;
823   }
824
825   protected void computeFeatureKind(EStructuralFeature feature)
826   {
827     EClassifier eClassifier = feature.getEType();
828
829     if (eClassifier instanceof EDataType)
830     {
831       if (feature.isMany())
832       {
833         featuresToKinds.put(feature, INTEGER_DATATYPE_IS_MANY);
834       }
835       else
836       {
837         featuresToKinds.put(feature, INTEGER_DATATYPE_SINGLE);
838       }
839     }
840     else
841     {
842       if (feature.isMany())
843       {
844         EReference reference = (EReference) feature;
845         EReference opposite = reference.getEOpposite();
846
847         if (opposite == null || opposite.isTransient() || !opposite.isMany())
848           featuresToKinds.put(feature, INTEGER_IS_MANY_ADD);
849         else
850           featuresToKinds.put(feature, INTEGER_IS_MANY_MOVE);
851       }
852     }
853   }
854
855   public String JavaDoc getJavaEncoding(String JavaDoc xmlEncoding)
856   {
857     return xmlEncoding;
858   }
859
860   public String JavaDoc getXMLEncoding(String JavaDoc javaEncoding)
861   {
862     return javaEncoding;
863   }
864
865   public EPackage[] packages()
866   {
867     Map JavaDoc map = new TreeMap JavaDoc();
868
869     // Sort and eliminate duplicates caused by having both a regular package and a demanded package for the same nsURI.
870
//
871
for (Iterator JavaDoc i = packages.entrySet().iterator(); i.hasNext(); )
872     {
873       Map.Entry JavaDoc entry = (Map.Entry JavaDoc)i.next();
874       EPackage ePackage = (EPackage)entry.getKey();
875       String JavaDoc prefix= getPrefix(ePackage);
876       if (prefix == null)
877       {
878         prefix = "";
879       }
880       EPackage conflict = (EPackage)map.put(prefix, ePackage);
881       if (conflict != null && conflict.eResource() != null)
882       {
883         map.put(prefix, conflict);
884       }
885     }
886     EPackage[] result = new EPackage[map.size()];
887     map.values().toArray(result);
888     return result;
889   }
890
891   public void setValue(EObject object, EStructuralFeature feature, Object JavaDoc value, int position)
892   {
893     if (extendedMetaData != null)
894     {
895       EStructuralFeature targetFeature = extendedMetaData.getAffiliation(object.eClass(), feature);
896       if (targetFeature != null && targetFeature != feature)
897       {
898         EStructuralFeature group = extendedMetaData.getGroup(targetFeature);
899         if (group != null)
900         {
901           targetFeature = group;
902         }
903         if (targetFeature.getEType() == EcorePackage.eINSTANCE.getEFeatureMapEntry())
904         {
905           FeatureMap featureMap = (FeatureMap)object.eGet(targetFeature);
906           EClassifier eClassifier = feature.getEType();
907           if (eClassifier instanceof EDataType)
908           {
909             EDataType eDataType = (EDataType) eClassifier;
910             EFactory eFactory = eDataType.getEPackage().getEFactoryInstance();
911             value = createFromString(eFactory, eDataType, (String JavaDoc)value);
912           }
913           featureMap.add(feature, value);
914           return;
915         }
916         else
917         {
918           feature = targetFeature;
919         }
920       }
921     }
922
923     int kind = getFeatureKind(feature);
924     switch (kind)
925     {
926       case DATATYPE_SINGLE:
927       case DATATYPE_IS_MANY:
928       {
929         EClassifier eClassifier = feature.getEType();
930         EDataType eDataType = (EDataType) eClassifier;
931         EFactory eFactory = eDataType.getEPackage().getEFactoryInstance();
932
933         if (kind == DATATYPE_IS_MANY)
934         {
935           InternalEList list = (InternalEList) object.eGet(feature);
936           if (position == -2)
937           {
938             for (StringTokenizer JavaDoc stringTokenizer = new StringTokenizer JavaDoc((String JavaDoc)value, " "); stringTokenizer.hasMoreTokens(); )
939             {
940               String JavaDoc token = stringTokenizer.nextToken();
941               list.addUnique(createFromString(eFactory, eDataType, token));
942             }
943
944             // Make sure that the list will appear to be set to be empty.
945
//
946
if (list.isEmpty())
947             {
948               list.clear();
949             }
950           }
951           else if (value == null)
952           {
953             list.addUnique(null);
954           }
955           else
956           {
957             list.addUnique(createFromString(eFactory, eDataType, (String JavaDoc)value));
958           }
959         }
960         else if (value == null)
961         {
962           object.eSet(feature, null);
963         }
964         else
965         {
966           object.eSet(feature, createFromString(eFactory, eDataType, (String JavaDoc) value));
967         }
968         break;
969       }
970       case IS_MANY_ADD:
971       case IS_MANY_MOVE:
972       {
973         InternalEList list = (InternalEList) object.eGet(feature);
974
975         if (position == -1)
976         {
977           list.addUnique(value);
978         }
979         else if (position == -2)
980         {
981           list.clear();
982         }
983         else if (checkForDuplicates)
984         {
985           int index = list.indexOf(value);
986           if (index == -1)
987           {
988             list.addUnique(position, value);
989           }
990           else
991           {
992             list.move(position, index);
993           }
994         }
995         else if (kind == IS_MANY_ADD)
996         {
997           list.addUnique(position, value);
998         }
999         else
1000        {
1001          list.move(position, value);
1002        }
1003        break;
1004      }
1005      default:
1006      {
1007        object.eSet(feature, value);
1008        break;
1009      }
1010    }
1011  }
1012
1013  public List JavaDoc setManyReference(ManyReference reference, String JavaDoc location)
1014  {
1015    EStructuralFeature feature = reference.getFeature();
1016    int kind = getFeatureKind(feature);
1017    InternalEList list = (InternalEList) reference.getObject().eGet(feature);
1018    List JavaDoc xmiExceptions = new BasicEList();
1019    Object JavaDoc[] values = reference.getValues();
1020    int[] positions = reference.getPositions();
1021
1022    if (kind == IS_MANY_ADD)
1023    {
1024      for (int i = 0, l = values.length; i < l; i++)
1025      {
1026        if (values[i] != null)
1027        {
1028          try
1029          {
1030            list.addUnique(positions[i], values[i]);
1031          }
1032          catch (RuntimeException JavaDoc e)
1033          {
1034            xmiExceptions.add(new IllegalValueException
1035                                    (reference.getObject(),
1036                                     feature,
1037                                     values[i],
1038                                     e,
1039                                     location,
1040                                     reference.getLineNumber(),
1041                                     reference.getColumnNumber()
1042                                    ));
1043          }
1044        }
1045      }
1046    }
1047    else
1048    {
1049      for (int i = 0, l = values.length; i < l; i++)
1050      {
1051        if (values[i] != null)
1052        {
1053          try
1054          {
1055            list.move(positions[i], values[i]);
1056          }
1057          catch (RuntimeException JavaDoc e)
1058          {
1059            xmiExceptions.add(new IllegalValueException
1060                                    (reference.getObject(),
1061                                     feature,
1062                                     values[i],
1063                                     e,
1064                                     location,
1065                                     reference.getLineNumber(),
1066                                     reference.getColumnNumber()
1067                                    ));
1068          }
1069        }
1070      }
1071    }
1072
1073    if (xmiExceptions.isEmpty())
1074    {
1075      return null;
1076    }
1077    else
1078    {
1079      return xmiExceptions;
1080    }
1081  }
1082
1083  public void setCheckForDuplicates(boolean checkForDuplicates)
1084  {
1085    this.checkForDuplicates = checkForDuplicates;
1086  }
1087
1088  public void setProcessDanglingHREF(String JavaDoc value)
1089  {
1090    processDanglingHREF = value;
1091  }
1092
1093  public DanglingHREFException getDanglingHREFException()
1094  {
1095    return danglingHREFException;
1096  }
1097
1098  public URI resolve(URI relative, URI base)
1099  {
1100    return relative.resolve(base);
1101  }
1102  
1103  public void pushContext()
1104  {
1105    namespaceSupport.pushContext();
1106  }
1107
1108  public void popContext()
1109  {
1110    namespaceSupport.popContext();
1111  }
1112
1113  public void addPrefix(String JavaDoc prefix, String JavaDoc uri)
1114  {
1115    if (!"xml".equals(prefix) && !"xmlns".equals(prefix))
1116    {
1117      uri = (uri.length() == 0) ? null : uri;
1118      namespaceSupport.declarePrefix(prefix, uri);
1119      allPrefixToURI.add(prefix);
1120      allPrefixToURI.add(uri);
1121    }
1122  }
1123  
1124  public Map JavaDoc getAnyContentPrefixToURIMapping()
1125  {
1126    anyPrefixesToURIs.clear();
1127    int count = namespaceSupport.getDeclaredPrefixCount();
1128    int size = allPrefixToURI.size();
1129    Object JavaDoc uri, prefix = null;
1130    while (count-->0)
1131    {
1132      uri = allPrefixToURI.remove(--size);
1133      prefix = allPrefixToURI.remove(--size);
1134      anyPrefixesToURIs.put(prefix, uri);
1135     }
1136    return anyPrefixesToURIs;
1137  }
1138  
1139
1140  public String JavaDoc getURI(String JavaDoc prefix)
1141  {
1142    return
1143      "xml".equals(prefix) ?
1144        "http://www.w3.org/XML/1998/namespace" :
1145        "xmlns".equals(prefix) ?
1146          ExtendedMetaData.XMLNS_URI :
1147          namespaceSupport.getURI(prefix);
1148  }
1149
1150  public EMap getPrefixToNamespaceMap()
1151  {
1152    return prefixesToURIs;
1153  }
1154  
1155  public void recordPrefixToURIMapping()
1156  {
1157    for (int i = 0, size = allPrefixToURI.size(); i < size;)
1158    {
1159      String JavaDoc prefix = (String JavaDoc)allPrefixToURI.get(i++);
1160      String JavaDoc uri = (String JavaDoc)allPrefixToURI.get(i++);
1161      String JavaDoc originalURI = (String JavaDoc)prefixesToURIs.get(prefix);
1162      if (uri == null)
1163      {
1164        // xmlns="" declaration
1165
// Example #1: <a><qname>q</qname><b xmlns="abc"/></a>
1166
// Example #2: <a xmlns="abc"><b xmlns=""/><c xmlns="abc2"/></a>
1167
// Example #3: <a xmlns:a="abc"><b xmlns:a="abc2"/></a>
1168

1169        seenEmptyStringMapping = true;
1170        if (originalURI != null)
1171        {
1172          // since xmlns="" is default declaration, remove ""->empty_URI mapping
1173
prefixesToURIs.removeKey(prefix);
1174          addNSDeclaration(prefix, originalURI);
1175        }
1176        continue;
1177      }
1178      else if ((seenEmptyStringMapping && prefix.length() == 0))
1179      {
1180        // record default ns declaration as duplicate if seen QName (#1) or seen xmlns="" (#2)
1181
addNSDeclaration(prefix, uri);
1182      }
1183      else if (originalURI != null)
1184      {
1185        if (!uri.equals(originalURI))
1186        {
1187          // record duplicate declaration for a given prefix (#3)
1188
addNSDeclaration(prefix, uri);
1189        }
1190      }
1191      else
1192      {
1193        // recording a first declaration for a given prefix
1194
prefixesToURIs.put(prefix, uri);
1195      }
1196    }
1197  }
1198
1199  public void setPrefixToNamespaceMap(EMap prefixToNamespaceMap)
1200  {
1201    for (Iterator JavaDoc i = prefixToNamespaceMap.iterator(); i.hasNext(); )
1202    {
1203      Map.Entry JavaDoc entry = (Map.Entry JavaDoc)i.next();
1204      String JavaDoc prefix = (String JavaDoc)entry.getKey();
1205      String JavaDoc namespace = (String JavaDoc)entry.getValue();
1206      EPackage ePackage = null;
1207      if (extendedMetaData == null)
1208      {
1209        ePackage = packageRegistry.getEPackage(namespace);
1210      }
1211      else
1212      {
1213        ePackage = extendedMetaData.getPackage(namespace);
1214        if (ePackage == null && !XMLResource.XSI_URI.equals(namespace))
1215        {
1216          if (XMLResource.XML_SCHEMA_URI.equals(namespace))
1217          {
1218            ePackage = xmlSchemaTypePackage;
1219          }
1220          else
1221          {
1222            ePackage = extendedMetaData.demandPackage(namespace);
1223          }
1224        }
1225      }
1226      if (ePackage != null && !packages.containsKey(ePackage))
1227      {
1228        packages.put(ePackage, prefix);
1229      }
1230      prefixesToURIs.put(prefix, namespace);
1231    }
1232  }
1233  
1234  /**
1235   * A helper to encode namespace prefix mappings.
1236   */

1237  protected static class NamespaceSupport
1238  {
1239    protected String JavaDoc[] namespace = new String JavaDoc [16 * 2];
1240
1241    protected int namespaceSize = 0;
1242
1243    protected int[] context = new int [8];
1244
1245    protected int currentContext = -1;
1246
1247    protected String JavaDoc[] prefixes = new String JavaDoc [16];
1248
1249    public void pushContext()
1250    {
1251      // extend the array, if necessary
1252
if (currentContext + 1 == context.length)
1253      {
1254        int[] contextarray = new int [context.length * 2];
1255        System.arraycopy(context, 0, contextarray, 0, context.length);
1256        context = contextarray;
1257      }
1258
1259      // push context
1260
context[++currentContext] = namespaceSize;
1261    }
1262
1263    public void popContext()
1264    {
1265      namespaceSize = context[currentContext--];
1266    }
1267
1268    /**
1269     * @param prefix prefix to declare
1270     * @param uri uri that maps to the prefix
1271     * @return true if the prefix existed in the current context and
1272     * its uri has been remapped; false if prefix does not exist in the
1273     * current context
1274     */

1275    public boolean declarePrefix(String JavaDoc prefix, String JavaDoc uri)
1276    {
1277      // see if prefix already exists in current context
1278
for (int i = namespaceSize; i > context[currentContext]; i -= 2)
1279      {
1280        if (namespace[i - 2].equals(prefix))
1281        {
1282          namespace[i - 1] = uri;
1283          return true;
1284        }
1285      }
1286
1287      // resize array, if needed
1288
if (namespaceSize == namespace.length)
1289      {
1290        String JavaDoc[] namespacearray = new String JavaDoc [namespaceSize * 2];
1291        System.arraycopy(namespace, 0, namespacearray, 0, namespaceSize);
1292        namespace = namespacearray;
1293      }
1294
1295      // bind prefix to uri in current context
1296
namespace[namespaceSize++] = prefix;
1297      namespace[namespaceSize++] = uri;
1298      return false;
1299    }
1300
1301    public String JavaDoc getURI(String JavaDoc prefix)
1302    {
1303      // find prefix in current context
1304
for (int i = namespaceSize; i > 0; i -= 2)
1305      {
1306        if (namespace[i - 2].equals(prefix))
1307        {
1308          return namespace[i - 1];
1309        }
1310      }
1311
1312      // prefix not found
1313
return null;
1314    }
1315    
1316    public String JavaDoc getPrefix(String JavaDoc uri)
1317    {
1318      // find uri in current context
1319
for (int i = namespaceSize; i > 0; i -= 2)
1320      {
1321        if (namespace[i - 1].equals(uri))
1322        {
1323          if (getURI(namespace[i - 2]).equals(uri))
1324            return namespace[i - 2];
1325        }
1326      }
1327
1328      // uri not found
1329
return null;
1330    }
1331    
1332    public int getDeclaredPrefixCount()
1333    {
1334      return (namespaceSize - context[currentContext]) / 2;
1335    }
1336
1337    public String JavaDoc getDeclaredPrefixAt(int index)
1338    {
1339      return namespace[context[currentContext] + index * 2];
1340    } // getDeclaredPrefixAt(int):String
1341

1342  }// namespace context
1343

1344  public void setAnySimpleType(EClass type)
1345  {
1346    anySimpleType = type;
1347  }
1348  
1349  public String JavaDoc convertToString(EFactory factory, EDataType dataType, Object JavaDoc value)
1350  {
1351    if (extendedMetaData != null)
1352    {
1353      if (value instanceof List JavaDoc)
1354      {
1355        List JavaDoc list = (List JavaDoc)value;
1356        for (Iterator JavaDoc i = list.iterator(); i.hasNext(); )
1357        {
1358          updateQNamePrefix(factory, dataType, i.next(), true);
1359        }
1360        return factory.convertToString(dataType, value);
1361      }
1362      else
1363      {
1364        return updateQNamePrefix(factory, dataType, value, false);
1365      }
1366    }
1367    return factory.convertToString(dataType, value);
1368  }
1369  
1370  protected Object JavaDoc createFromString(EFactory eFactory, EDataType eDataType, String JavaDoc value)
1371  {
1372    Object JavaDoc obj = eFactory.createFromString(eDataType, value);
1373    if (extendedMetaData != null)
1374    {
1375      if (obj instanceof List JavaDoc)
1376      {
1377         List JavaDoc list = (List JavaDoc)obj;
1378         for (int i=0;i<list.size();i++)
1379         {
1380           updateQNameURI(list.get(i));
1381         }
1382      }
1383      else
1384      {
1385       updateQNameURI(obj);
1386      }
1387    }
1388    return obj;
1389  }
1390  
1391  protected void updateQNameURI(Object JavaDoc value)
1392  {
1393    if (value instanceof QName)
1394    {
1395       QName qname = (QName) value;
1396       String JavaDoc namespace = getURI(qname.getPrefix());
1397       qname.setNamespaceURI(namespace);
1398       if (qname.getPrefix().length() >0 && qname.getNamespaceURI().length() == 0)
1399       {
1400         throw new IllegalArgumentException JavaDoc("The prefix '" + qname.getPrefix() + "' is not declared for the QName '"+qname.toString()+"'");
1401       }
1402       if (namespace == null)
1403       {
1404         seenEmptyStringMapping = true;
1405         String JavaDoc uri = (String JavaDoc)prefixesToURIs.get("");
1406         if (uri != null)
1407         {
1408           prefixesToURIs.put("", namespace);
1409           addNSDeclaration("", uri);
1410         }
1411       }
1412    }
1413  }
1414  
1415  /**
1416   * @param factory
1417   * @param dataType
1418   * @param value a data value to be converted to string
1419   * @param list if the value is part of the list of values
1420   * @return if the value is not part of the list, return string corresponding to value,
1421   * otherwise return null
1422   */

1423  protected String JavaDoc updateQNamePrefix(EFactory factory, EDataType dataType, Object JavaDoc value, boolean list)
1424  {
1425    if (value instanceof QName)
1426    {
1427      QName qname = (QName)value;
1428      String JavaDoc namespace = qname.getNamespaceURI();
1429      if (namespace.length() == 0)
1430      {
1431        qname.setPrefix("");
1432        return qname.getLocalPart();
1433      }
1434      EPackage ePackage = extendedMetaData.getPackage(namespace);
1435      if (ePackage == null)
1436      {
1437        ePackage = extendedMetaData.demandPackage(namespace);
1438      }
1439
1440      String JavaDoc prefix = getPrefix(ePackage, true);
1441      if (!packages.containsKey(ePackage))
1442      {
1443        packages.put(ePackage, prefix);
1444      }
1445      qname.setPrefix(prefix);
1446      return (!list) ? qname.toString() : null;
1447    }
1448
1449    return (!list) ? factory.convertToString(dataType, value) : null;
1450  }
1451  
1452  protected void addNSDeclaration(String JavaDoc prefix, String JavaDoc uri)
1453  {
1454    if (uri != null)
1455    {
1456      int index = 1;
1457      while (prefixesToURIs.containsKey(prefix + "_" + index))
1458      {
1459        ++index;
1460      }
1461      prefixesToURIs.put(prefix + "_" + index, uri);
1462    }
1463  }
1464
1465  public void setMustHavePrefix(boolean mustHavePrefix)
1466  {
1467    this.mustHavePrefix = mustHavePrefix;
1468  }
1469  
1470}
1471
Popular Tags