KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > lib > jmi > xmi > XmiDtdProducer


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19 package org.netbeans.lib.jmi.xmi;
20
21 import java.io.*;
22 import java.util.*;
23
24 import javax.jmi.reflect.*;
25 import javax.jmi.model.*;
26
27 import org.netbeans.lib.jmi.util.DebugException;
28 import org.netbeans.lib.jmi.util.Logger;
29
30 public class XmiDtdProducer extends org.netbeans.api.mdr.DTDProducer {
31
32     public static String JavaDoc TAG_ELEMENT = "!ELEMENT";
33     public static String JavaDoc TAG_ATTLIST = "!ATTLIST";
34     public static String JavaDoc TAG_REQUIRED = "#REQUIRED";
35     public static String JavaDoc TAG_PCDATA = "#PCDATA";
36     public static String JavaDoc TAG_CDATA = "CDATA";
37     public static String JavaDoc TAG_IMPLIED = "#IMPLIED";
38     public static String JavaDoc TAG_IDREFS = "IDREFS";
39     public static String JavaDoc TAG_EMPTY = "EMPTY";
40     public static String JavaDoc TAG_XMI_REFERENCE = "XMI.reference";
41     public static String JavaDoc TAG_XMI_EXTENSION = "XMI.extension";
42     public static String JavaDoc TAG_XMI_VALUE = "xmi.value";
43     public static String JavaDoc TAG_XMI_FIXED_ATTRIBS = "%XMI.element.att; %XMI.link.att;";
44     
45     // String used in DTD fixed file to mark end of the licence part.
46
private static String JavaDoc END_OF_LICENCE_MARKER = "<!-- -->";
47     // Fixed DTD file name.
48
private static String JavaDoc FIXED_DTD_FILE = "resources/fixed.dtd";
49     // treshold (number of chars) for line breaking when writing !ELEMENT
50
private static int LINE_BOUND = 60;
51
52     // output stream to which the produced DTD is written
53
private PrintStream stream;
54     // main package extent
55
private RefPackage extent;
56     // elements cache used to obtain classes' attributes, references, etc.
57
private ElementsCache elementsCache;
58     // stored already processed packages
59
private Set trackedPackages;
60     // stores mapping class -> set of all direct subtypes
61
private Map classHierarchy;
62     // cache for mapping class -> all subtypes (direct and non-direct)
63
private Map allSubtypes_cache;
64     // mapping MofPackage -> namespace name
65
private Map namespaces;
66     // flag indicating, if first item in !ELEMENT is to be written
67
private boolean isFirstItem;
68     // counter of characters in currently writen line (used when writing !ELEMENT)
69
private int charsCounter;
70
71     // init .....................................................................
72

73     public void init () {
74         elementsCache = new ElementsCache (extent);
75         trackedPackages = new HashSet ();
76         classHierarchy = new HashMap ();
77         allSubtypes_cache = new HashMap ();
78         namespaces = new HashMap ();
79
80         elementsCache = new ElementsCache (extent);
81         findNamespaces (extent);
82         trackedPackages.clear ();
83     }
84
85     // methods ..................................................................
86

87     public void startElement (String JavaDoc name) {
88         stream.println ();
89         isFirstItem = true;
90         stream.print ("<" + TAG_ELEMENT + " ");
91         stream.print (name);
92         charsCounter = TAG_ELEMENT.length () + 2 + name.length ();
93     }
94
95     public void addEmptyElement () {
96         stream.println (" " + TAG_EMPTY + ">");
97     }
98     
99     public void addElementItem (String JavaDoc name) {
100         if (!isFirstItem) {
101             stream.print (" | ");
102             charsCounter += 3;
103         } else {
104             isFirstItem = false;
105             stream.print (" (");
106             charsCounter += 2;
107         }
108         charsCounter += name.length ();
109         if (charsCounter > LINE_BOUND) {
110             stream.println ();
111             stream.print (" ");
112             charsCounter = 4;
113         }
114         stream.print (name);
115     }
116
117     public void endElement () {
118         stream.println (")* >");
119     }
120     
121     public void startAttlist (String JavaDoc text) {
122         stream.print ("<" + TAG_ATTLIST + " ");
123         stream.print (text);
124     }
125     
126     public void addAttlistItem (String JavaDoc text) {
127         stream.println ();
128         stream.print (" " + text);
129     }
130         
131     public void endAttlist () {
132         stream.println (">");
133     }
134     
135     // ..........................................................................
136

137     /** Generates DTD based on outermost package.
138      *
139      * @param outermost package
140      */

141     public void generate (OutputStream stream, RefPackage extent) {
142         this.stream = new PrintStream (stream);
143         this.extent = extent;
144         init ();
145         writeFixedContent ();
146         writeNamespaces ();
147         writePackageDTD (extent);
148         
149         try {
150             stream.flush ();
151             stream.close ();
152         } catch (IOException e) {
153             e.printStackTrace ();
154         }
155     }
156
157     public void writePackageDTD (RefPackage pkg) {
158         if (trackedPackages.contains (pkg)) {
159             return;
160         } else {
161             trackedPackages.add (pkg);
162         }
163         Iterator iter = pkg.refAllPackages ().iterator ();
164         while (iter.hasNext ()) {
165             writePackageDTD ((RefPackage) iter.next ());
166         }
167         iter = pkg.refAllClasses ().iterator ();
168         while (iter.hasNext ()) {
169             writeClassDTD ((RefClass) iter.next ());
170         }
171         iter = pkg.refAllClasses ().iterator ();
172         while (iter.hasNext ()) {
173             writeStaticAttributesDTD ((RefClass) iter.next ());
174         }
175         iter = getFreeAssociations (pkg).iterator ();
176         while (iter.hasNext ()) {
177             writeAssociationDTD ((Association) iter.next ());
178         }
179         
180         writePackageElementDef (pkg);
181     }
182     
183     public void writeClassDTD (RefClass proxy) {
184         Iterator iter;
185         String JavaDoc text;
186         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc ();
187         MofClass meta = (MofClass) proxy.refMetaObject ();
188         String JavaDoc className = objectName (meta);
189         List instAttrs, references;
190         
191         instAttrs = elementsCache.instanceAttributes (meta);
192         references = elementsCache.references (meta);
193         
194         // attribute element definitions
195
iter = instAttrs.iterator ();
196         while (iter.hasNext ()) {
197             Attribute attr = (Attribute) iter.next ();
198             if (attr.getContainer () == meta) {
199                 writeAttributeElemDef (attr);
200             }
201         } // while
202

203         // reference element definitions
204
iter = references.iterator ();
205         while (iter.hasNext ()) {
206             Reference ref = (Reference) iter.next ();
207             if (ref.getContainer () != meta)
208                 continue;
209             startElement (elementName (ref));
210             MofClass type = (MofClass) ref.getType ();
211             Iterator it = elementsCache.getAllSubtypes ((MofClass) type).iterator ();
212             while (it.hasNext ()) {
213                 addElementItem (objectName ((MofClass) it.next ()));
214             } // while
215
endElement ();
216         } // while
217

218         // class element definition
219
startElement (className);
220         Iterator it;
221         for (it = instAttrs.iterator (); it.hasNext ();) {
222             addElementItem (elementName ((Attribute) it.next ()));
223         }
224         for (it = references.iterator (); it.hasNext ();) {
225             addElementItem (elementName ((Reference) it.next ()));
226         }
227         for (it = getComposites (meta).iterator (); it.hasNext ();) {
228             addElementItem (objectName ((MofClass) it.next ()));
229         }
230         addElementItem (TAG_XMI_EXTENSION);
231         endElement ();
232                 
233         buffer.delete(0, buffer.length ());
234         startAttlist (className);
235         for (it = references.iterator (); it.hasNext ();) { // ? [PENDING] non-composite reference, multiplicity 1 allowed ...
236
buffer.append (((Reference) it.next ()).getName ());
237             buffer.append (" " + TAG_IDREFS + " " + TAG_IMPLIED);
238             addAttlistItem (buffer.toString ());
239             buffer.delete(0, buffer.length ());
240         }
241         for (it = instAttrs.iterator (); it.hasNext ();) {
242             Attribute attr = (Attribute) it.next ();
243             buffer.append (attr.getName ());
244             Classifier type = getType (attr);
245             if (type instanceof EnumerationType) {
246                 int prefixLength = labelPrefix ((EnumerationType) type).length ();
247                 buffer.append (" (");
248                 for (Iterator it_2 = ((EnumerationType) type).getLabels ().iterator (); it_2.hasNext ();) {
249                     buffer.append (((String JavaDoc) it_2.next ()).substring (prefixLength));
250                     if (it_2.hasNext ())
251                         buffer.append ("|");
252                 }
253                 buffer.append (") " + TAG_IMPLIED);
254             } else if (type instanceof MofClass) {
255                 buffer.append (" " + TAG_IDREFS + " " + TAG_IMPLIED);
256             } else {
257                 buffer.append (" " + TAG_CDATA + " " + TAG_IMPLIED);
258             }
259             addAttlistItem (buffer.toString ());
260             buffer.delete(0, buffer.length ());
261         }
262         addAttlistItem (TAG_XMI_FIXED_ATTRIBS);
263         endAttlist ();
264     }
265
266     public void writeStaticAttributesDTD (RefClass proxy) {
267         MofClass meta = (MofClass) proxy.refMetaObject ();
268         for (Iterator iter = elementsCache.classAttributes (meta).iterator (); iter.hasNext ();) {
269             Attribute attr = (Attribute) iter.next ();
270             if (attr.getContainer () == meta)
271                 writeAttributeElemDef (attr);
272         }
273     }
274     
275     public void writeAssociationDTD (Association assoc) {
276         String JavaDoc name;
277         Set subtypes = new HashSet ();
278         for (Iterator iter = assoc.getContents ().iterator (); iter.hasNext ();) {
279             Object JavaDoc elem = iter.next ();
280             if (elem instanceof AssociationEnd) {
281                 subtypes.addAll (elementsCache.getAllSubtypes ((MofClass) ((AssociationEnd) elem).getType ()));
282             } // if
283
} // for
284
name = objectName (assoc);
285         startElement (name);
286         for (Iterator iter = subtypes.iterator (); iter.hasNext ();) {
287             addElementItem (objectName ((MofClass) iter.next ()));
288         }
289         addElementItem (TAG_XMI_EXTENSION);
290         endElement ();
291         
292         startAttlist (name);
293         addAttlistItem (TAG_XMI_FIXED_ATTRIBS);
294         endAttlist ();
295         /*
296         String name;
297         String end_name [] = new String [2];
298         int num = 0;
299         for (Iterator iter = assoc.getContents ().iterator (); iter.hasNext ();) {
300             Object elem = iter.next ();
301             if (elem instanceof AssociationEnd) {
302                 AssociationEnd end = (AssociationEnd) elem;
303                 name = elementName (end);
304                 end_name [num++] = name;
305                 startElement (name);
306                 addEmptyElement ();
307         
308                 startAttlist (name);
309                 addAttlistItem (TAG_XMI_FIXED_ATTRIBS);
310                 endAttlist ();
311             } // if
312         } // for
313         name = objectName (assoc);
314         startElement (name);
315         addElementItem (end_name [0]);
316         addElementItem (end_name [1]);
317         addElementItem (TAG_XMI_EXTENSION);
318         endElement ();
319         
320         startAttlist (name);
321         addAttlistItem (TAG_XMI_FIXED_ATTRIBS);
322         endAttlist ();
323          */

324     }
325     
326     public void writeAttributeElemDef (Attribute attr) {
327         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc ();
328         Classifier type = getType (attr);
329         boolean isEnum = type instanceof EnumerationType;
330         startElement (elementName (attr));
331
332         if (isEnum) { // AttribEnum
333
addEmptyElement ();
334         } else if (type instanceof MofClass) { // AttribMofClass
335
Iterator it = elementsCache.getAllSubtypes ((MofClass) type).iterator ();
336             addElementItem (objectName ((MofClass) it.next ()));
337             while (it.hasNext ()) {
338                 MofClass clazz = (MofClass) it.next ();
339                 addElementItem (objectName (clazz));
340             } // while
341
endElement ();
342         } else if (type instanceof StructureType) { // StructureType
343
addElementItem ("XMI.field");
344             endElement ();
345         } else { // AttribData
346
addElementItem (TAG_PCDATA);
347             addElementItem (TAG_XMI_REFERENCE);
348             endElement ();
349         }
350             
351         if (isEnum) {
352             int prefixLength = labelPrefix ((EnumerationType) type).length ();
353             buffer = new StringBuffer JavaDoc ();
354             startAttlist (elementName (attr));
355             buffer.append (TAG_XMI_VALUE + " (");
356             Iterator it = ((EnumerationType) type).getLabels ().iterator ();
357             while (it.hasNext ()) {
358                 buffer.append (((String JavaDoc) it.next ()).substring (prefixLength));
359                 if (it.hasNext ())
360                     buffer.append ("|");
361             }
362             buffer.append (") " + TAG_REQUIRED);
363             addAttlistItem (buffer.toString ());
364             endAttlist ();
365         }
366     }
367     
368     /**
369      * Writes fixed part of XMI DTD content.
370      */

371     public void writeFixedContent () {
372         java.net.URL JavaDoc fixedDTD = getClass().getResource(FIXED_DTD_FILE);
373         if (fixedDTD == null) {
374             throw new DebugException("Resource not found: " + FIXED_DTD_FILE);
375         }
376         try {
377             InputStream in = fixedDTD.openStream ();
378             BufferedReader reader = new BufferedReader (new InputStreamReader(in));
379             String JavaDoc line;
380             // skip licence
381
do {
382                 line = reader.readLine ();
383             } while (!line.equals (END_OF_LICENCE_MARKER));
384             // copy fixed DTD elements
385
line = reader.readLine ();
386             while (line != null) {
387                 stream.println (line);
388                 line = reader.readLine();
389             }
390         } catch (IOException e) {
391             Logger.getDefault().log("Unable to open " + FIXED_DTD_FILE + ": " + e.getMessage());
392             throw new DebugException (e.getMessage ());
393         }
394     }
395
396     public void writeNamespaces () {
397         Set names = new HashSet ();
398         if (namespaces.size () > 0) {
399             startAttlist ("XMI");
400             for (Iterator iter = namespaces.entrySet ().iterator (); iter.hasNext ();) {
401                 Object JavaDoc name = ((Map.Entry) iter.next ()).getValue ();
402                 if (!names.contains (name)) {
403                     addAttlistItem ("xmlns:" + name + " " + TAG_CDATA + " " + TAG_IMPLIED);
404                     names.add (name);
405                 }
406             } // for
407
endAttlist ();
408         } // if
409
}
410
411     public void writePackageElementDef (RefPackage pkg) {
412         MofPackage meta = (MofPackage) pkg.refMetaObject ();
413         String JavaDoc packageName = packageName (meta);
414         Set classes = new HashSet ();
415         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc ();
416         for (Iterator iter = pkg.refAllClasses ().iterator (); iter.hasNext ();) {
417             classes.addAll (elementsCache.getAllSubtypes ((MofClass) ((RefClass) iter.next ()).refMetaObject ()));
418         }
419         startElement (packageName);
420         // owned classes
421
for (Iterator iter = classes.iterator (); iter.hasNext ();) {
422             addElementItem (objectName ((MofClass) iter.next ()));
423         }
424         // owned associations that are not accessible via any reference
425
for (Iterator iter = getFreeAssociations (pkg).iterator (); iter.hasNext ();) {
426             addElementItem (objectName ((Association) iter.next ()));
427         }
428         // nested packages (imported are excluded, is it correct ? [PENDING])
429
for (Iterator iter = pkg.refAllPackages ().iterator (); iter.hasNext ();) {
430             RefPackage refPkg = (RefPackage) iter.next ();
431             MofPackage metaPkg = (MofPackage) refPkg.refMetaObject ();
432             if (metaPkg.getContainer () == meta) {
433                 addElementItem (packageName (metaPkg));
434             }
435         }
436         // XMI.extension
437
addElementItem (TAG_XMI_EXTENSION);
438         endElement ();
439         
440         // attributes
441
startAttlist (packageName);
442         addAttlistItem (TAG_XMI_FIXED_ATTRIBS);
443         endAttlist ();
444     }
445
446     // helper methods ...........................................................
447

448     /**
449      * Finds and caches namespace declarations.
450      */

451     private void findNamespaces (RefPackage pkg) {
452         String JavaDoc name;
453         Iterator iter;
454
455         if (trackedPackages.contains (pkg))
456             return;
457         else
458             trackedPackages.add (pkg);
459
460         MofPackage metaPackage = (MofPackage) pkg.refMetaObject ();
461         name = WriterBase.getTagValue (metaPackage, XmiConstants.TAGID_XMI_NAMESPACE);
462         if (name != null) {
463             namespaces.put (metaPackage, name);
464         }
465
466         iter = pkg.refAllPackages ().iterator ();
467         while (iter.hasNext ()) {
468             findNamespaces ((RefPackage) iter.next ());
469         }
470     }
471
472     public String JavaDoc elementName (ModelElement element) {
473         ModelElement container = element.getContainer ();
474         return objectName (container) + '.' + element.getName ();
475     }
476
477     public String JavaDoc objectName (ModelElement element) {
478         String JavaDoc namespace = (String JavaDoc) namespaces.get (element.getContainer ());
479         if (namespace != null) {
480             return namespace + ":" + element.getName ();
481         } else {
482             return qualifiedName (element);
483         }
484     }
485     
486     public String JavaDoc packageName (MofPackage pkg) {
487         String JavaDoc namespace = (String JavaDoc) namespaces.get (pkg);
488         if (namespace != null) {
489             return namespace + ":" + pkg.getName ();
490         } else {
491             return qualifiedName (pkg);
492         }
493     }
494     
495     public String JavaDoc qualifiedName (ModelElement element) {
496         Iterator iter = element.getQualifiedName ().iterator ();
497         String JavaDoc name = (String JavaDoc) iter.next ();
498         while (iter.hasNext ()) {
499             name = name.concat (XmiConstants.DOT_SEPARATOR).concat ((String JavaDoc) iter.next ());
500         }
501         return name;
502     }
503     
504     /**
505      * Returns labels prefix given by "unprefix" tag attached to EnumerationType or
506      * the empty String if no such tag is present.
507      */

508     public String JavaDoc labelPrefix (EnumerationType type) {
509         String JavaDoc prefix = WriterBase.getTagValue (type, XmiConstants.TAGID_XMI_ENUMERATION_UNPREFIX);
510         if (prefix == null)
511             prefix = "";
512         return prefix;
513     }
514     
515     /**
516      * Returns type of the typed element. Aliases are substituted by proper types.
517      */

518     public Classifier getType (TypedElement elem) {
519         Classifier type = elem.getType ();
520         while (type instanceof AliasType)
521             type = ((AliasType) type).getType ();
522         return type;
523     }
524     
525     public Set getComposites (MofClass meta) {
526         return new HashSet ();
527         /*
528         Set set = new HashSet ();
529         Iterator iter = elementsCache.instanceAttributes (meta).iterator ();
530         while (iter.hasNext ()) {
531             Attribute attr = (Attribute) iter.next ();
532             Classifier type = attr.getType ();
533             if (type instanceof MofClass)
534                 set.add (type);
535         }
536         iter = elementsCache.references (meta).iterator ();
537         while (iter.hasNext ()) {
538             Reference ref = (Reference) iter.next ();
539             if (AggregationKindEnum.COMPOSITE.equals (ref.getReferencedEnd ().getAggregation ()))
540                 set.add (ref.getType ());
541         }
542         Set result = new HashSet ();
543         iter = set.iterator ();
544         while (iter.hasNext ()) {
545             Set temp = elementsCache.getAllSubtypes ((MofClass) iter.next ());
546             result.addAll(temp);
547         }
548         return result;
549          */

550     }
551     
552     /**
553      * Returns associations in the package that are not accessible via any reference.
554      */

555     public Set getFreeAssociations (RefPackage pkg) {
556         ModelPackage model = (ModelPackage) pkg.refMetaObject ().refImmediatePackage ();
557         RefersTo refersTo = model.getRefersTo ();
558         Set set = new HashSet ();
559         for (Iterator iter = pkg.refAllAssociations ().iterator (); iter.hasNext ();) {
560             Association assoc = (Association) ((RefAssociation) iter.next ()).refMetaObject ();
561             boolean found = false;
562             for (Iterator it = assoc.getContents ().iterator (); it.hasNext ();) {
563                 Object JavaDoc elem = it.next ();
564                 if (elem instanceof AssociationEnd) {
565                     Collection col = refersTo.getReferent ((AssociationEnd) elem);
566                     if ((col != null) && (col.size () > 0)) {
567                         found = true;
568                         break;
569                     }
570                 }
571             } // for
572
if (!found) {
573                 set.add (assoc);
574             }
575         } // for
576
return set;
577     }
578     
579 }
580
Popular Tags