KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > modfact > jmi > xmi > XmiParser


1 package org.objectweb.modfact.jmi.xmi;
2
3 import javax.xml.parsers.*;
4
5 import org.objectweb.modfact.jmi.reflect.ReflectHelper;
6 import org.w3c.dom.*;
7
8 import org.objectweb.modfact.jmi.xmi.PropertyTypeManager.TypeInfo;
9 import javax.jmi.reflect.*;
10 import java.util.*;
11 import java.io.*;
12
13
14
15 public class XmiParser {
16
17     static DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
18     static DocumentBuilder builder;
19     static {
20        try {
21          builder = documentBuilderFactory.newDocumentBuilder();
22        } catch(Exception JavaDoc e) {
23          System.err.println("Couldnot initialize DOM Parser");
24          throw new RuntimeException JavaDoc(e);
25        }
26     }
27     
28  
29     Document document;
30     Node rootNode;
31                
32     // xmi.id to RefObject
33
Hashtable id_object = new Hashtable();
34     List unresolvedProps = new Vector();
35     
36     RefPackage extent;
37     ObjectFactoryManager factManager;
38         
39     XmiReaderImpl caller;
40     
41     static Object JavaDoc lock = "";
42     XmiParser(XmiReaderImpl owner, RefPackage p, InputStream in) {
43       this.caller = owner;
44       this.extent = p;
45       try {
46         synchronized(lock) {
47           document = builder.parse(in);
48           rootNode = document.getDocumentElement().getElementsByTagName("XMI.content").item(0);
49         }
50       } catch(Exception JavaDoc e) {
51           throw new RuntimeException JavaDoc(e);
52       }
53     }
54     
55     private Set createdObjects = new HashSet() {
56       public boolean add(Object JavaDoc o) {
57         if(o==null) {
58             throw new RuntimeException JavaDoc("cannot add null");
59         }
60         return super.add(o);
61       }
62     };
63     
64     void run() {
65         extent = extent.refOutermostPackage();
66         factManager = new ObjectFactoryManager(extent);
67         
68         Node xmi_content = document.getElementsByTagName("XMI.content").item(0);
69         NodeList children = xmi_content.getChildNodes();
70         for (int i=0; i < children.getLength(); i++) {
71             Node node = children.item(i);
72             if(node instanceof Element) {
73               process1((Element) node);
74             }
75         }
76                        
77         Iterator it = elements.iterator();
78         while(it.hasNext()) {
79           process2((Element)it.next());
80         }
81     }
82     
83     Collection getOuterMostObjects() {
84       Collection r = new HashSet();
85       Iterator it = createdObjects.iterator();
86       while(it.hasNext()) {
87         RefObject o = (RefObject) it.next();
88         RefBaseObject outer = o.refOutermostComposite();
89
90         if(outer instanceof RefObject) r.add(outer);
91       }
92       return r;
93     }
94     
95     
96     
97
98      
99    
100     // list of empty element to assign properties' values to
101
List elements = new Vector();
102     
103     // create corresponding object
104
// and map xmi.id to it
105
void process1(Element elem) {
106
107         String JavaDoc xmi_id = elem.getAttribute("xmi.id");
108         String JavaDoc elemName = ReflectHelper.unqualifiedName(elem.getTagName());
109         RefObject o;
110                 
111         if(!"".equals(xmi_id)) {
112           // support for XMI 1.0, 1.1
113
o = doCorbaType(xmi_id, elemName, elem);
114           if(o==null) {
115             if(caller.verbose) System.err.println("creating object '" +elem.getTagName() +"' xmi.id=" +xmi_id );
116             o = createObject(elem);
117             if(o!=null) {
118               id_object.put(xmi_id, o);
119               elements.add(elem); // to be processed later;
120
}
121           }
122         }
123
124         NodeList children = elem.getChildNodes();
125         for (int i=0; i < children.getLength(); i++) {
126             Node child = children.item(i);
127             if(child instanceof Element) {
128               try {
129                   process1((Element) child);
130               } catch(RuntimeException JavaDoc e) {
131                  if(!caller.ignoreError) throw e;
132               }
133             }
134         }
135     }
136     
137     
138     RefObject createObject(Element elem) {
139         String JavaDoc xmi_id = elem.getAttribute("xmi.id");
140         
141         RefObject o = factManager.createObject(elem.getTagName());
142         if(o == null) {
143             System.out.println("warning: cannot create " +elem.getTagName() );
144         } else {
145             createdObjects.add(o);
146         }
147             
148         return o;
149     }
150     
151     // Set values of all properties
152
void process2(Element elem) {
153
154         String JavaDoc xmi_id = elem.getAttribute("xmi.id");
155         RefObject o = (RefObject) id_object.get(xmi_id);
156         
157         if(caller.verbose)
158             System.err.println("setting properties for object '"
159                 +elem.getNodeName() +"' xmi.id=" +xmi_id
160             );
161         try {
162           setProperties(elem ,o);
163         } catch(RuntimeException JavaDoc e) {
164           RuntimeException JavaDoc e2 = new RuntimeException JavaDoc("at xmi.id="+xmi_id, e);
165           throw e2;
166         }
167         
168     }
169     
170     void setProperties(Element elem, RefObject o) {
171
172           NamedNodeMap attrs = elem.getAttributes();
173            
174           NodeList children = elem.getChildNodes();
175           for (int i=0; i < children.getLength(); i++) {
176             Node child = children.item(i);
177             if(child instanceof Element)
178               setValue(o, child );
179           }
180         
181           for (int i=0; i < attrs.getLength(); i++) {
182             Attr attr = (Attr) attrs.item(i);
183             if(!attr.getName().equals("xmi.id"))
184               setValue(o, attr );
185           }
186             
187     }
188     
189     
190     PropertyTypeManager typeManager = new PropertyTypeManager();
191
192     
193     void setValue(RefObject owner, Node propNode) {
194         RefObject metaObject = owner.refMetaObject();
195         String JavaDoc propName = propNode.getNodeName();
196         
197         // ignore xmi extention tag
198
if( propName.toLowerCase().indexOf("xmi.")>=0) {
199           if(caller.verbose)
200               System.err.println("\t\t\t*** ignore node '" +propName +"'");
201           return;
202         }
203         
204         String JavaDoc unqPropName = ReflectHelper.unqualifiedName(propNode.getNodeName());
205         TypeInfo type;
206         try {
207           type = typeManager.findTypeFor(metaObject, unqPropName);
208         } catch(Exception JavaDoc e) {
209
210             String JavaDoc err = "property '" +propName +"' undefined in '" +metaObject.refGetValue("qualifiedName") +"'";
211             if(caller.ignoreError) {
212                 if(caller.verbose) System.err.println("***" +err);
213                 return;
214             } else {
215                 throw new RuntimeException JavaDoc( err ,e );
216             }
217         }
218         try {
219           if(type.isMultiValued) {
220             Collection values = (propNode instanceof Attr)?
221                   createValuesFrmAttr(type, (Attr) propNode)
222                 : createValuesFrmElement(type, (Element)propNode);
223             if(caller.verbose) System.err.println(" set property '"
224                 +propName +"' =" +values
225             );
226             ((Collection)owner.refGetValue(unqPropName)).addAll(values);
227           } else {
228             Object JavaDoc value = (propNode instanceof Attr)?
229                   createValueFrmAttr(type, (Attr)propNode)
230                 : createValueFrmElement(type, (Element)propNode);
231             if(caller.verbose)
232                 System.err.println(" set property '"
233                   +propName +"' =" +value
234                 );
235             if(value!=null) {
236               owner.refSetValue(unqPropName, value );
237             }
238           }
239         } catch(RuntimeException JavaDoc e) {
240             String JavaDoc err = "Could not set property '" +propName +"' from Node "+ propNode;
241             if(caller.ignoreError) {
242               if(caller.verbose) System.err.println("***" +err);
243             } else {
244               throw new RuntimeException JavaDoc(err, e);
245             }
246         }
247     }
248     
249
250     
251    Object JavaDoc createValueFrmAttr(TypeInfo type, Attr propNode) {
252        return createValue(type, propNode.getNodeValue());
253    }
254    
255    Object JavaDoc createValueFrmElement(TypeInfo type, Element propNode) {
256         if(type.isStruct) {
257           return createStruct(type, propNode);
258         }
259         
260         if(propNode.hasAttribute("xmi.value")) {
261           return createValue(type, propNode.getAttribute("xmi.value"));
262         }
263         
264         String JavaDoc xmi_idref = null;
265         NodeList children = ((Element)propNode).getChildNodes();
266         for(int i=0; i<children.getLength(); i++) {
267            Node child = children.item(i);
268            if(child instanceof Element) {
269               Element childElem = (Element)child;
270               if(childElem.hasAttribute("xmi.id")) {
271                 return createValue(type, childElem.getAttribute("xmi.id"));
272
273               } else if(childElem.hasAttribute("xmi.idref")) {
274                 return createValue(type, childElem.getAttribute("xmi.idref"));
275
276               } else if(childElem.getTagName().equalsIgnoreCase("XMI.any")) {
277                 return createValue(type, childElem.getFirstChild().getNodeValue());
278
279               } else if( !type.isEnum && !type.isPrimitive
280                          && factManager.canCreateObject( childElem.getTagName() )
281                      ) { // if type is object but the XML element has no xmi.id
282
// then create an object now
283
RefObject o = factManager.createObject(childElem.getTagName());
284                 setProperties(childElem, o);
285                 return o;
286               }
287               // otherwise ignore this element
288
System.err.println("\t\t\t*** ignore element '" +childElem +"'");
289            } else if(child instanceof Text) {
290               // avoid empty text nodes mixed with child elements
291
if(child.getNodeValue().trim().length() > 0)
292                 return createValue( type, child.getNodeValue() );
293            
294            } else if(child instanceof Comment) {
295            
296            } else {
297              // otherwise ignore
298
System.err.println("\t\t\t*** ignore node '" +child +"'");
299            }
300         }
301         return createValue(type ,"");
302     }
303     
304     Collection createValuesFrmAttr(TypeInfo type, Attr propNode) {
305           List r = new Vector();
306           // parse space-seperated string
307
StringTokenizer t = new StringTokenizer(propNode.getNodeValue());
308           while(t.hasMoreTokens()) {
309             String JavaDoc vs = t.nextToken();
310             Object JavaDoc vo = createValue(type,vs);
311             if(vo!=null) r.add(vo);
312           }
313           return r;
314     }
315     
316     Collection createValuesFrmElement(TypeInfo type, Element propNode) {
317         List r = new Vector();
318         if(type.isStruct) {
319           Object JavaDoc v = createStruct(type, propNode);
320           if(v!=null) r.add(v);
321           return r;
322         }
323         if(propNode.hasAttribute("xmi.value")) {
324           Object JavaDoc v = createValue(type, propNode.getAttribute("xmi.value"));
325           if(v!=null) r.add(v);
326           return r;
327         }
328         NodeList list = ((Element)propNode).getChildNodes();
329         for(int i=0; i<list.getLength(); i++) {
330           Node child = list.item(i);
331           if(child instanceof Element) {
332              Element childElem = (Element) child;
333              if(childElem.hasAttribute("xmi.id")) {
334                Object JavaDoc v = createValue(type, childElem.getAttribute("xmi.id"));
335                if(v!=null) r.add(v);
336                
337              } else if(childElem.hasAttribute("xmi.idref")) {
338                Object JavaDoc v = createValue(type, childElem.getAttribute("xmi.idref"));
339                if(v!=null) r.add(v);
340                
341              } else if(childElem.getTagName().equalsIgnoreCase("XMI.any")) {
342                Object JavaDoc v = createValue(type, childElem.getFirstChild().getNodeValue());
343                if(v!=null) r.add(v);
344             
345
346              } else if( !type.isEnum && !type.isPrimitive
347                         && factManager.canCreateObject( childElem.getTagName() )
348                     ) { // if type is object but the XML element has no xmi.id
349
// then create an object now
350
RefObject v = factManager.createObject(childElem.getTagName());
351                setProperties(childElem, v);
352                if(v!=null) r.add(v);
353              
354              } else {
355                // otherwise ignore this element
356
System.err.println("\t\t\t*** ignore element '" +childElem +"'");
357              }
358           
359           } else if(child instanceof Text) {
360              // avoid empty text nodes mixed with child elements
361
if(child.getNodeValue().trim().length() > 0) {
362                  Object JavaDoc v = createValue(type, child.getNodeValue());
363                  if(v!=null) r.add(v);
364              }
365           } else if(child instanceof Comment) {
366           
367           } else {
368             // otherwise ignore
369
System.err.println("\t\t\t*** ignore node '" +child +"'");
370           }
371         }
372         return r;
373     }
374
375     Object JavaDoc createValue(TypeInfo type, String JavaDoc value) {
376         if(type.isPrimitive) {
377           return parsePrimitiveValue(type.name, value);
378         }
379         if(type.isEnum) {
380           return getEnum(type, value);
381         }
382         if(type.isStruct) {
383           throw new RuntimeException JavaDoc("Struct value should not be encoded as attribute");
384         }
385         // type is RefObject
386
String JavaDoc xmi_idref = value; //the same action even if value comes from xmi.id
387
Object JavaDoc r = id_object.get(xmi_idref);
388         if(r==null) {
389            throw new RuntimeException JavaDoc("unresolved xmi.idref '" +xmi_idref +"'");
390         }
391         return r;
392     }
393     
394     Object JavaDoc parsePrimitiveValue(String JavaDoc type, String JavaDoc value) {
395       if(type.equalsIgnoreCase("string")) {
396         return value;
397       } else if(type.equalsIgnoreCase("long")
398         || type.equalsIgnoreCase("integer") ) {
399         return new Integer JavaDoc(Integer.parseInt(value));
400       } else if(type.equalsIgnoreCase("double")
401         || type.equalsIgnoreCase("float") ) {
402         return new Double JavaDoc(Double.parseDouble(value));
403       } else if(type.equalsIgnoreCase("boolean")) {
404         return Boolean.valueOf(value);
405       }
406       throw new RuntimeException JavaDoc("unknown primitive type '" + type +"'");
407     }
408     
409     
410     RefEnum getEnum(TypeInfo type, String JavaDoc label) {
411        String JavaDoc prefixLabel = label;
412        if(type.enumUnprefix!=null) {
413          if(!label.startsWith(type.enumUnprefix)) {
414             prefixLabel = type.enumUnprefix + label;
415          }
416        }
417        return factManager.getEnum(type.qname, prefixLabel);
418     }
419
420    /*
421     format 1:
422                  <Model.StructuralFeature.multiplicity>
423                     <XMI.field>1</XMI.field>
424                     <XMI.field>1</XMI.field>
425                     <XMI.field>false</XMI.field>
426                     <XMI.field>false</XMI.field>
427                  </Model.StructuralFeature.multiplicity>
428     format 2:
429        <Model:StructuralFeature.multiplicity>
430             <Model:MultiplicityType lower="1" upper="1" is_ordered="false" is_unique="false" />
431        </Model:StructuralFeature.multiplicity>
432       
433     todo: Test with nested Structures (Structure of Structures)
434     */

435     RefStruct createStruct(TypeInfo type, Element elem) {
436       if(isStructFormat1(elem)) {
437         return createStruct_Format1(type, elem);
438       }
439       return createStruct_Format2(type, elem);
440     }
441     
442     boolean isStructFormat1(Element elem) {
443       return getChildFromLocalName(elem, "XMI.field")!=null;
444     }
445     
446     Element getChildFromLocalName(Element elem, String JavaDoc name) {
447       NodeList list = elem.getChildNodes();
448       for(int i=0; i<list.getLength() ; i++) {
449         Node child = list.item(i);
450         if((child instanceof Element) && child.getNodeName().endsWith(name) )
451             return (Element)child;
452       }
453       return null;
454     }
455         
456     RefStruct createStruct_Format1(TypeInfo type, Element elem) {
457         List args = new Vector();
458         NodeList list = elem.getChildNodes();
459         int j = 0;
460         for(int i=0; i<list.getLength(); i++) {
461           Node child = list.item(i);
462           String JavaDoc nodeName = child.getNodeName();
463           if((child instanceof Element) && nodeName.endsWith("XMI.field")) {
464             args.add( createValueFrmElement(type.structFieldTypes[j], (Element)child) );
465             j++;
466           }
467         }
468         return factManager.createStruct(type.qname, args);
469     }
470     
471     RefStruct createStruct_Format2(TypeInfo type, Element elem) {
472         Element inner = getChildFromLocalName(elem, type.name);
473         List args = new Vector();
474         for(int i=0; i<type.structFieldTypes.length; i++) {
475           try {
476             String JavaDoc value = inner.getAttribute(type.structFieldNames[i]);
477             args.add(
478                 createValue(type.structFieldTypes[i], value )
479             );
480           } catch(RuntimeException JavaDoc e) {
481             System.err.println("CreateStruct: Error at att[" +i +"] "
482                 +type.structFieldNames[i]
483             );
484             throw e;
485           }
486         }
487         return factManager.createStruct(type.qname, args);
488     }
489     
490     
491     
492     Map sharedPrimitiveTypes = new Hashtable();
493     
494     // support for XMI 1.0 / 1.1
495
// translate corba typecode to PrimitiveType
496
// return false if this element does not have corba typecode
497
RefObject doCorbaType(String JavaDoc xmi_id, String JavaDoc elemName, Element elem) {
498         
499         if(!elemName.equals("DataType")) {
500             return null;
501         }
502         Element tc = findTypeCodeInDataType(elem);
503         if(tc==null) return null;
504                
505
506         //resolve alias type
507
while(tc.getNodeName().equalsIgnoreCase("XMI.CorbaTcAlias")) {
508           tc = findTypeCodeInDataType(tc);
509         }
510         
511         String JavaDoc name = null;
512         RefObject type; // object to be create
513

514         if(tc.getNodeName().equalsIgnoreCase("XMI.CorbaTcEnum")) {
515           if(caller.verbose) System.err.println(
516             "creating EnumerationType '" +name +"' xmi.id=" +xmi_id
517           );
518           type = extent.refClass("EnumerationType").refCreateInstance(null);
519           name = tc.getAttribute("xmi.tcName");
520           if(name.length()==0) {
521             throw new RuntimeException JavaDoc("Expecting xmi.tcName in " +tc.getNodeName());
522           }
523           type.refSetValue("name", name);
524           NodeList labels = tc.getElementsByTagName("XMI.CorbaTcEnumLabel");
525           List type_labels = (List)type.refGetValue("labels");
526           for(int i=0; i<labels.getLength() ; i++) {
527             Element label = (Element) labels.item(i);
528             type_labels.add(label.getAttribute("xmi.tcName"));
529           }
530           type.refSetValue("name", name);
531
532         } else {
533           //handle primitive type
534
// normalize the first letter of type name to upper case
535
// ex, 'integer' to 'Integer'
536
name = getTcName(tc);
537           char firstChar = name.charAt(0);
538           name = Character.toUpperCase(firstChar) + name.substring(1);
539           type = (RefObject) sharedPrimitiveTypes.get(name);
540           if(type==null) {
541             if(caller.verbose) System.err.println(
542               "creating PrimitiveType '" +name +"' xmi.id=" +xmi_id
543             );
544             type = extent.refClass("PrimitiveType").refCreateInstance(null);
545             type.refSetValue("name", name);
546           }
547         }
548         id_object.put(xmi_id, type);
549         createdObjects.add(type);
550         return type;
551     }
552     
553     
554     // find child element with tag XMI.CorbaTc...
555
// example : XMI.CorbaTcString XMI.CorbaTcBoolean
556
Element findTypeCodeInDataType(Element dataType) {
557         NodeList typeCode = dataType.getElementsByTagName("XMI.CorbaTypeCode");
558         if(typeCode.getLength()==0) {
559           return null;
560         }
561         Element tcElem = (Element) typeCode.item(0);
562         NodeList tcContentList = tcElem.getChildNodes();
563         for(int i = 0; i<tcContentList.getLength(); i++) {
564           Node n = tcContentList.item(i);
565           if(n instanceof Element) {
566             Element tcContent = (Element)n;
567             String JavaDoc s = tcContent.getNodeName().toLowerCase();
568             if(s.indexOf("xmi.corbatc")>=0) {
569               return tcContent;
570             }
571           }
572         }
573         throw new RuntimeException JavaDoc("Cannot handle CorbaTypeCode " + tcElem);
574     }
575     
576     String JavaDoc getTcName(Element tc) {
577       String JavaDoc n = tc.getNodeName().toLowerCase();
578       return n.replaceAll("xmi.corbatc","");
579     }
580     
581         
582
583
584
585
586
587     
588 }
589
Popular Tags