KickJava   Java API By Example, From Geeks To Geeks.

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


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 import java.net.URL JavaDoc;
24
25 import org.xml.sax.ContentHandler JavaDoc;
26 import org.xml.sax.SAXException JavaDoc;
27 import org.xml.sax.helpers.AttributesImpl JavaDoc;
28
29 import org.netbeans.lib.jmi.util.DebugException;
30 import org.netbeans.api.xmi.*;
31
32 import javax.jmi.reflect.*;
33 import javax.jmi.model.*;
34 import org.netbeans.lib.jmi.util.Logger;
35
36 public class WriterBase extends XMIWriter {
37
38     private static final String JavaDoc XMI_VERSION = "1.2";
39     public static final String JavaDoc EXPORTER_NAME = "Netbeans XMI Writer";
40     public static final String JavaDoc EXPORTER_VERSION = "1.0";
41
42     public static final int ATTR_HREF = 0;
43     public static final int ATTR_XMI_ID = 1;
44     public static final int ATTR_XMI_IDREF = 2;
45     
46     public static final char HREF_DELIMITER = '#';
47
48     // variables ................................................................
49

50     // content handler used to produce XMI
51
protected ContentHandler JavaDoc contentHandler;
52     // output config
53
protected OutputConfig configuration;
54     // header provider
55
protected XMIHeaderProvider headerProvider = null;
56     // xmi reference provider
57
protected XMIReferenceProvider provider;
58     // default xmi reference provider
59
protected XMIReferenceProvider defaultProvider = new DefaultProvider ();
60     // encoding to be used
61
protected String JavaDoc encoding = null;
62     // attributes added for currently processed element
63
protected AttributesImpl JavaDoc attributes;
64     // system id of the document the writer writes in or null if it is not known
65
protected String JavaDoc thisSystemId = null;
66     // name of the currently processed element
67
protected String JavaDoc elementName;
68     // indicates if some element is being currently processed
69
protected boolean elementStarted;
70     
71     protected OutputStreamWriter stream;
72     // temp variable storing passed OutputStream parameter to be used by init () method
73
protected OutputStream outputStream = null;
74
75     // known namespaces
76
protected HashMap namespaces;
77
78     // stores objects to be written having immediate composite serialized in some external document
79
protected List lightOutermosts;
80     // stores all currently written components
81
protected Set writtenComponents;
82     // used to detect components that stay unwritten because of presence of composite associations with ends that are not visible via references
83
protected Set nonWrittenComponents;
84     // stores all instances having already generated xmi id (RefObject - key, String - value)
85
protected HashMap xmiIds;
86     // counts the number of all serialized instances
87
protected int instancesCounter = 0;
88
89     /* Serves to record already processed packages (when contents of packages are processed
90      * recursive - see writePackage, writeAssociations, writeStaticAttributes and findNamespaces
91      * methods) to avoid multiple searching trough a package.
92      */

93     protected HashSet processedPackages;
94
95     // caches storing instance-scoped and class-scoped attributes and references
96
protected HashMap instanceAttributes_cache;
97     protected HashMap classAttributes_cache;
98     protected HashMap references_cache;
99
100     // cache storing structures' fields
101
protected HashMap structureFields_cache;
102     // cache storing enum prefixes specified by a tag attached to EnumerationType
103
protected HashMap labelPrefix_cache;
104
105     // indicates if the method writing Collection of RefObjects is called or not
106
protected boolean collectionWriting = false;
107     // set and list of outermost composite objects to be write by write(Collection) method
108
protected Set objectsToWrite = null;
109     protected List objectsToWriteAsCollection = null;
110
111     // init .....................................................................
112

113     public WriterBase() {
114         configuration = new OutputConfig ();
115     }
116
117     public WriterBase(XMIOutputConfig config) {
118         configuration = new OutputConfig ();
119         configuration.setReferenceProvider (config.getReferenceProvider ());
120         if (config instanceof OutputConfig) {
121             configuration.setHeaderProvider (((OutputConfig) config).getHeaderProvider());
122             configuration.setEncoding (((OutputConfig) config).getEncoding());
123         }
124     }
125     
126     public void init () throws IOException {
127         collectionWriting = false;
128
129         attributes = new AttributesImpl JavaDoc ();
130
131         namespaces = new HashMap ();
132         xmiIds = new HashMap ();
133         nonWrittenComponents = new HashSet ();
134         writtenComponents = new HashSet ();
135         processedPackages = new HashSet ();
136         instancesCounter = 0;
137         instanceAttributes_cache = new HashMap ();
138         classAttributes_cache = new HashMap ();
139         references_cache = new HashMap ();
140         structureFields_cache = new HashMap ();
141         labelPrefix_cache = new HashMap ();
142     
143         lightOutermosts = new LinkedList ();
144         if (configuration == null) {
145             provider = defaultProvider;
146         } else {
147             provider = configuration.getReferenceProvider ();
148             if (provider == null)
149                 provider = defaultProvider;
150             if (configuration instanceof OutputConfig) {
151                 headerProvider = ((OutputConfig) configuration).getHeaderProvider ();
152                 encoding = ((OutputConfig) configuration).getEncoding ();
153             }
154         }
155         
156         if (outputStream != null) {
157             try {
158                 if (encoding == null) {
159                     stream = new OutputStreamWriter (outputStream);
160                 } else {
161                     stream = new OutputStreamWriter (outputStream, encoding);
162                 }
163                 contentHandler = new DefaultWriter (stream, encoding);
164                 // clear outputStream variable
165
outputStream = null;
166             } catch (UnsupportedEncodingException e) {
167                 throw new IOException ("Unsupported encoding: " + encoding);
168             }
169         } // if
170
}
171
172     // javax.jmi.xmi.XmiWriter interface implementation .........................
173

174     public void write (OutputStream os, RefPackage extent, String JavaDoc xmiVersion) throws IOException {
175         write (os, null, extent, xmiVersion);
176     }
177
178     public void write (OutputStream os, Collection objects, String JavaDoc xmiVersion) throws IOException {
179         write (os, null, objects, xmiVersion);
180     }
181
182     public void write(OutputStream stream, RefPackage extent) {
183         try {
184             write(stream, extent, null);
185         } catch (IOException e) {
186             DebugException ne = new DebugException(e.toString());
187             Logger.getDefault().annotate(ne, e);
188             throw ne;
189         }
190     }
191
192     // org.netbeans.api.xmi.XMIWriter implmentation .............................
193

194     public XMIOutputConfig getConfiguration() {
195         return configuration;
196     }
197         
198     public void write(OutputStream stream, String JavaDoc uri, RefPackage extent, String JavaDoc xmiVersion) throws IOException {
199         thisSystemId = uri;
200         outputStream = stream;
201         write (extent);
202     }
203         
204     public void write(OutputStream stream, String JavaDoc uri, Collection objects, String JavaDoc xmiVersion) throws IOException {
205         thisSystemId = uri;
206         outputStream = stream;
207         write (objects);
208     }
209     
210     // ..........................................................................
211

212     public void write(ContentHandler JavaDoc handler, String JavaDoc uri, RefPackage extent, String JavaDoc xmiVersion) throws IOException {
213         thisSystemId = uri;
214         contentHandler = handler;
215         write (extent);
216     }
217         
218     public void write(ContentHandler JavaDoc handler, String JavaDoc uri, Collection objects, String JavaDoc xmiVersion) throws IOException {
219         thisSystemId = uri;
220         contentHandler = handler;
221         write (objects);
222     }
223     
224     public void write (RefPackage extent) throws IOException {
225         Logger.getDefault().log("XMI writer started");
226         long time = System.currentTimeMillis ();
227         init ();
228         processedPackages.clear ();
229         findNamespaces (extent);
230         writeDocument (extent);
231         time = System.currentTimeMillis () - time;
232         Logger.getDefault().log("finished, TIME: " + time/1000.0 + "[s]");
233     }
234
235     public void write (Collection objects) throws IOException {
236         init ();
237         //
238
collectionWriting = true;
239         //
240
processedPackages.clear ();
241         RefPackage extent;
242         objectsToWrite = new HashSet ();
243         objectsToWriteAsCollection = new LinkedList ();
244         Set tempSet = new HashSet ();
245         if ((objects == null) || (objects.size () == 0)) {
246             extent = null;
247         } else {
248             Iterator iter = objects.iterator ();
249             while (iter.hasNext ()) {
250                 Object JavaDoc obj = iter.next ();
251                 if (!(obj instanceof RefObject))
252                     throw new DebugException ("Bad object (not instance of RefObject) in input collection: " + obj.getClass ().getName ());
253                 tempSet.add (obj);
254             } // while
255
iter = objects.iterator ();
256             RefFeatured featured;
257             RefObject container;
258             while (iter.hasNext ()) {
259                 RefObject obj = (RefObject) iter.next ();
260                 container = obj;
261                 boolean found = false;
262                 do {
263                     featured = container.refImmediateComposite ();
264                     container = (featured instanceof RefObject) ? (RefObject) featured : null;
265                     if ((container != null) && tempSet.contains (container)) {
266                         found = true;
267                         break;
268                     }
269                 } while (container != null);
270                 if (!found) {
271                     objectsToWrite.add (obj);
272                     objectsToWriteAsCollection.add (obj);
273                 }
274             } // while
275
extent = ((RefObject) objectsToWriteAsCollection.get (0)).refOutermostPackage ();
276             findNamespaces (extent);
277         }
278         writeDocument (extent);
279     }
280     
281     // methods ..................................................................
282

283     protected void findNamespaces (RefPackage pkg) {
284         String JavaDoc name;
285         Iterator iter;
286
287         if (processedPackages.contains (pkg))
288             return;
289
290         MofPackage metaPackage = (MofPackage) pkg.refMetaObject ();
291         name = getTagValue (metaPackage, XmiConstants.TAGID_XMI_NAMESPACE);
292         if (name != null) {
293             iter = metaPackage.getQualifiedName ().iterator ();
294             String JavaDoc fqName = (String JavaDoc) iter.next ();
295             while (iter.hasNext ())
296                 fqName = fqName.concat (XmiConstants.DOT_SEPARATOR).concat ((String JavaDoc) iter.next ());
297             namespaces.put (fqName, name);
298         }
299
300         processedPackages.add (pkg);
301         iter = pkg.refAllPackages ().iterator ();
302         while (iter.hasNext ()) {
303             findNamespaces ((RefPackage) iter.next ());
304         }
305     }
306
307     public static String JavaDoc getTagValue (ModelElement element, String JavaDoc tagId) {
308         Collection tags = ((ModelPackage) element.refImmediatePackage()).
309             getAttachesTo().getTag (element);
310         Tag tag = null;
311         for (Iterator it = tags.iterator(); it.hasNext();) {
312             Object JavaDoc obj = it.next ();
313             if (!(obj instanceof Tag))
314                 continue;
315             Tag temp = (Tag) obj;
316             if (tagId.equals (temp.getTagId ())) {
317                 tag = temp;
318                 break;
319             }
320         }
321         if (tag == null)
322             return null;
323         Collection values = tag.getValues ();
324         if (values.size () == 0)
325             return null;
326         return (String JavaDoc) values.iterator ().next ();
327     }
328
329     /**
330      * Finds all attributes and references belonging to a mof class and caches them.
331      */

332     protected void cacheContainedElements (MofClass mofClass) {
333         List temp = new LinkedList ();
334         List superClasses = mofClass.allSupertypes ();
335         Namespace namespace = null;
336         Iterator it = superClasses.iterator ();
337         while (it.hasNext ()) {
338             namespace = (Namespace) it.next ();
339             temp.addAll (namespace.getContents ());
340         }
341         temp.addAll (mofClass.getContents ());
342         List instanceAttributes = new LinkedList ();
343         List classAttributes = new LinkedList ();
344         List references = new LinkedList ();
345         Set referencedEnds = new HashSet ();
346         it = temp.iterator ();
347         while (it.hasNext ()) {
348             RefObject refObject = (RefObject) it.next ();
349             if (refObject instanceof Feature) {
350                 boolean instanceLevel = ((Feature) refObject).getScope ().equals (ScopeKindEnum.INSTANCE_LEVEL);
351                 if ((refObject instanceof Attribute) && (!((Attribute) refObject).isDerived ())) {
352                     if (instanceLevel) {
353                         instanceAttributes.add (refObject);
354                     } else {
355                         classAttributes.add (refObject);
356                     }
357                 } else if (refObject instanceof Reference) {
358                     AssociationEnd end = ((Reference) refObject).getReferencedEnd ();
359                     Association assoc = (Association) end.getContainer ();
360                     if (!assoc.isDerived () && !referencedEnds.contains (end)) {
361                         references.add (refObject);
362                         referencedEnds.add (end);
363                     }
364                 } // else
365
} // if (refObject instanceof Feature)
366
} // while
367
instanceAttributes_cache.put (mofClass, instanceAttributes);
368         classAttributes_cache.put (mofClass, classAttributes);
369         references_cache.put (mofClass, references);
370     }
371
372     /**
373      * For a given mof class, returns list of all instance-scoped attributes
374      * (references are not included).
375      *
376      * @param mofClass
377      * @return list of all non-derived instance-scoped attributes (including inherited ones)
378      */

379     protected List instanceAttributes (MofClass mofClass) {
380         List list = (List) instanceAttributes_cache.get (mofClass);
381         if (list == null) {
382             cacheContainedElements (mofClass);
383             list = (List) instanceAttributes_cache.get (mofClass);
384         }
385         return list;
386     }
387
388     /**
389      * For a given mof class, returns list of all class-scoped attributes.
390      *
391      * @param mofClass
392      * @return list of all non-derived class-scoped attributes (including inherited ones)
393      */

394     protected List classAttributes (MofClass mofClass) {
395         List list = (List) classAttributes_cache.get (mofClass);
396         if (list == null) {
397             cacheContainedElements (mofClass);
398             list = (List) classAttributes_cache.get (mofClass);
399         }
400         return list;
401     }
402
403     /**
404      * For a given mof class, returns list of all references.
405      *
406      * @param mofClass
407      * @return list of all non-derived references (including inherited ones)
408      */

409     protected List references (MofClass mofClass) {
410         List list = (List) references_cache.get (mofClass);
411         if (list == null) {
412             cacheContainedElements (mofClass);
413             list = (List) references_cache.get (mofClass);
414         }
415         return list;
416     }
417
418     /**
419      * Returns list of all fields belonging to the given StructureType.
420      */

421     public List structureFields (StructureType type) {
422         List fields = (List) structureFields_cache.get (type);
423         if (fields != null)
424             return fields;
425         // find fields and cache them
426
fields = new LinkedList ();
427         Iterator content = type.getContents ().iterator ();
428         while (content.hasNext ()) {
429             Object JavaDoc element = content.next ();
430             if (element instanceof StructureField)
431                 fields.add (element);
432         } // while
433
structureFields_cache.put (type, fields);
434         return fields;
435     }
436
437     /**
438      * Returns labels prefix given by "unprefix" tag attached to EnumerationType or
439      * the empty String if no such tag is present.
440      */

441     public String JavaDoc labelPrefix (EnumerationType type) {
442         String JavaDoc prefix = (String JavaDoc) labelPrefix_cache.get (type);
443         if (prefix != null)
444             return prefix;
445         prefix = getTagValue (type, XmiConstants.TAGID_XMI_ENUMERATION_UNPREFIX);
446         if (prefix == null)
447             prefix = "";
448         labelPrefix_cache.put (type, prefix);
449         return prefix;
450     }
451
452     // **************************************************************************
453
// Methods related to writing to content handler.
454
// **************************************************************************
455

456     protected void startElement (String JavaDoc name) {
457         if (elementStarted) {
458             writeStartElement ();
459         }
460         elementName = name;
461         elementStarted = true;
462     }
463
464     /**
465      * Writes end of an XML element to the output stream.
466      *
467      * @param name name of the XML element to be written
468      */

469     protected void endElement (String JavaDoc name) {
470         if (elementStarted) {
471             writeStartElement ();
472         }
473         try {
474             contentHandler.endElement (null, null, name);
475         } catch (SAXException JavaDoc e) {
476         }
477     }
478
479     /**
480      * Writes an attribute of the currenly written XML elemnt to the output stream.
481      *
482      * @param name attribute name
483      * @param value value of the attribute
484      */

485     protected void addAttribute (String JavaDoc name, String JavaDoc value) {
486         attributes.addAttribute(null, null, name, null, value); // uri, localName, qName, type, value
487
}
488
489     /**
490      * Writes characters into body of the currenly written XML elemnt.
491      * Before the string is written, @link #replaceSpecialChars is called
492      * on it to replace special XML characters.
493      *
494      * @param text string to be written
495      */

496     protected void characters (String JavaDoc text) {
497         if (elementStarted) {
498             writeStartElement ();
499         }
500         try {
501             contentHandler.characters (text.toCharArray(), 0, text.length ());
502         } catch (SAXException JavaDoc e) {
503         }
504     }
505
506     protected void writeStartElement () {
507         try {
508             contentHandler.startElement (null, null, elementName, attributes);
509         } catch (SAXException JavaDoc e) {
510         }
511         elementStarted = false;
512         attributes.clear ();
513     }
514
515     // **************************************************************************
516

517     /**
518      * Checks if a given instance is already cached. In not, generates an xmi.id for it,
519      * stores it in cache and returns the generated id, otherwise returns already stored id.
520      */

521     protected String JavaDoc getXmiId (RefObject obj) {
522         String JavaDoc xmiId = ((String JavaDoc) xmiIds.get (obj));
523         if (xmiId == null) {
524             instancesCounter++;
525             xmiId = "a" + instancesCounter;
526             xmiIds.put (obj, xmiId);
527         }
528         return xmiId;
529     }
530
531     /**
532      * Called when an istances has been written.
533      */

534     protected void markWritten (RefObject obj) {
535         // used to handle written status of components only
536
writtenComponents.add (obj);
537         nonWrittenComponents.remove (obj);
538     }
539
540     protected void writeDocument (RefPackage pkg) {
541         try {
542             contentHandler.startDocument();
543         } catch (SAXException JavaDoc e) {
544         }
545
546         startElement (XmiConstants.XMI_ROOT);
547         addAttribute ("xmi.version", XMI_VERSION);
548         writeNamespaces ();
549         addAttribute ("timestamp", new Date ().toString ());
550         
551         writeHeader ();
552         
553         // content
554
startElement (XmiConstants.XMI_CONTENT);
555         if (!collectionWriting) {
556             processedPackages.clear();
557             writePackage (pkg);
558          
559             RefObject obj;
560             while (nonWrittenComponents.size () > 0) {
561                 Iterator iter = nonWrittenComponents.iterator ();
562                 do {
563                     obj = (RefObject) iter.next ();
564                 } while (nonWrittenComponents.contains (obj.refImmediateComposite ()));
565                 writeInstance (obj, true);
566                 while (lightOutermosts.size() > 0) {
567                     obj = (RefObject) lightOutermosts.remove(0);
568                     writeInstance (obj, true);
569                 } // while
570
} // while
571

572             processedPackages.clear();
573             writeStaticAttributes (pkg);
574         } else {
575             writeObjects ();
576         }
577         processedPackages.clear();
578         writeAssociations (pkg);
579         endElement (XmiConstants.XMI_CONTENT);
580         // end of content
581
endElement (XmiConstants.XMI_ROOT);
582         try {
583             contentHandler.endDocument();
584         } catch (SAXException JavaDoc e) {
585         }
586     }
587
588     protected void writeHeader () {
589         // header
590
startElement (XmiConstants.XMI_HEADER);
591         if ((contentHandler instanceof DefaultWriter) && (headerProvider != null)) {
592             writeStartElement ();
593             characters ("");
594             Writer ps = ((DefaultWriter) contentHandler).getWriter ();
595             headerProvider.writeHeader (ps);
596         } else { // write default header
597
startElement (XmiConstants.XMI_DOCUMENTATION);
598             // exporter
599
startElement ("XMI.exporter");
600             characters (EXPORTER_NAME);
601             endElement ("XMI.exporter");
602             // exporter version
603
startElement ("XMI.exporterVersion");
604             characters (EXPORTER_VERSION);
605             endElement ("XMI.exporterVersion");
606             endElement (XmiConstants.XMI_DOCUMENTATION);
607         }
608         endElement (XmiConstants.XMI_HEADER);
609         // ... end of header
610
}
611     
612     protected void writeNamespaces () {
613         HashMap temp = new HashMap ();
614         Iterator iter = namespaces.entrySet ().iterator ();
615         while (iter.hasNext ()) {
616             String JavaDoc name = (String JavaDoc) ((Map.Entry) iter.next ()).getValue ();
617             if (temp.get (name) == null) {
618                 temp.put (name, name);
619                 addAttribute ("xmlns:" + name, XmiConstants.TAGID_XMI_NAMESPACE + "." + name);
620             } // if
621
} // while
622
}
623
624     /**
625      * Serializes instances contained in a package and in all its sub-packages.
626      */

627     protected void writePackage (RefPackage pkg) {
628
629         if (processedPackages.contains (pkg))
630             return;
631
632         Iterator classes = pkg.refAllClasses ().iterator ();
633         while (classes.hasNext ()) {
634             RefClass proxy = (RefClass) classes.next ();
635             Iterator instances = proxy.refAllOfClass ().iterator ();
636             while (instances.hasNext ()) {
637                 RefObject obj = (RefObject) instances.next ();
638                 if (obj == null) {
639                     continue;
640                 }
641                 if (obj.equals (obj.refOutermostComposite ())) {
642                     // non-outermost instance is serialized as a part of content
643
// of an outermost instance
644
writeInstance (obj, true);
645                     while (lightOutermosts.size() > 0) {
646                         obj = (RefObject) lightOutermosts.remove(0);
647                         writeInstance (obj, true);
648                     } // while
649
} else {
650                     if (!writtenComponents.contains (obj)) {
651                         nonWrittenComponents.add (obj);
652                     }
653                 }
654             } // while
655
} // while
656

657         processedPackages.add (pkg);
658         Iterator containedPackages = pkg.refAllPackages ().iterator ();
659         while (containedPackages.hasNext ())
660             writePackage ((RefPackage) containedPackages.next ());
661     }
662
663     protected void writeObjects () {
664         Iterator iter = objectsToWriteAsCollection.iterator ();
665         while (iter.hasNext ()) {
666             writeInstance ((RefObject) iter.next (), true);
667         }
668     }
669
670     /**
671      * Serializes an instance.
672      *
673      * @param obj object to be serialized
674      * @param isTop true if the instance is serialized as a top-element (i.e. direct sub-element of <content>)
675      */

676     protected void writeInstance (RefObject obj, boolean isTop) {
677         RefClass proxy = obj.refClass ();
678         ModelElement element = (ModelElement) obj.refMetaObject ();
679         String JavaDoc name = qualifiedName (element);
680         XMIReferenceProvider.XMIReference xmiRef = provider.getReference (obj);
681         String JavaDoc xmiId = xmiRef.getXmiId ();
682         String JavaDoc systemId = xmiRef.getSystemId ();
683         if ((systemId != null) && (thisSystemId != null) && (thisSystemId.equals (systemId)))
684             systemId = null;
685         
686         markWritten (obj);
687         if (systemId != null) { // object from an external document
688
if (!isTop) { // serialize href
689
startElement (name);
690                 addAttribute (XmiConstants.XMI_HREF, systemId + HREF_DELIMITER + xmiId);
691                 endElement (name);
692             }
693             collectLightOutermosts (obj, proxy);
694             return;
695         }
696                 
697         startElement (name);
698         addAttribute (XmiConstants.XMI_ID, xmiId);
699         Iterator attrs = instanceAttributes ((MofClass) proxy.refMetaObject ()).iterator ();
700         List attrsInContent = new LinkedList ();
701         while (attrs.hasNext ()) {
702             Attribute attr = (Attribute) attrs.next ();
703             if (!VisibilityKindEnum.PUBLIC_VIS.equals(attr.getVisibility()))
704                 continue;
705             boolean isMultivalued = isMultivalued (attr);
706             Object JavaDoc value;
707             try {
708             value = obj.refGetValue (attr);
709             } catch (Exception JavaDoc e) {
710                 Logger.getDefault().annotate(e, ((ModelElement) obj.refMetaObject ()).getName () + " " + attr.getName ());
711                 Logger.getDefault().notify(e);
712                 value = Boolean.FALSE; // [PENDING]
713
}
714             Object JavaDoc valueToWrite = value;
715             if (value == null)
716                 continue; // optional attribute of no value
717
if (isMultivalued) {
718                 Collection col = (Collection) value;
719                 if (col.size () > 0) {
720                     attrsInContent.add (attr);
721                 }
722                 continue;
723                 /*
724                 if (col.isEmpty ())
725                     continue;
726                 if (col.size () > 1) {
727                     // values have to be serialized in content
728                     attrsInContent.add (attr);
729                     continue;
730                 } else
731                     valueToWrite = col.iterator ().next ();
732                  */

733             } // if
734
Classifier type = getType (attr);
735             if (!(type instanceof PrimitiveType) && !(type instanceof EnumerationType)) {
736                 // values have to be serialized in content
737
attrsInContent.add (attr);
738             } else
739                 writeValueInAttr (attr, valueToWrite);
740         } // while
741
Iterator iter = attrsInContent.iterator ();
742         while (iter.hasNext ()) {
743             Attribute attr = (Attribute) iter.next ();
744             writeValueInContent (attr, obj.refGetValue (attr));
745         } // while
746
Iterator refs = references ((MofClass) proxy.refMetaObject ()).iterator ();
747         while (refs.hasNext ()) {
748             Reference ref = (Reference) refs.next ();
749             writeReference (obj, ref);
750         }
751         endElement (name);
752     }
753     
754     protected void collectLightOutermosts (RefObject obj, RefClass proxy) {
755         Iterator iter;
756         Iterator attrs = instanceAttributes ((MofClass) proxy.refMetaObject ()).iterator ();
757         while (attrs.hasNext ()) {
758             Attribute attr = (Attribute) attrs.next ();
759             Classifier type = getType (attr);
760             if ((type instanceof PrimitiveType) || (type instanceof EnumerationType))
761                 continue;
762             boolean isMultivalued = isMultivalued (attr);
763             Object JavaDoc value = obj.refGetValue (attr);
764             Collection values;
765             if (value == null)
766                 continue; // optional attribute of no value
767
if (isMultivalued) {
768                 values = (Collection) value;
769             } else {
770                 values = new LinkedList ();
771                 values.add (value);
772             }
773             iter = values.iterator ();
774             if (type instanceof MofClass) {
775                 while (iter.hasNext ()) {
776                     addLightOutermost ((RefObject) iter.next ());
777                 }
778             } else if (type instanceof StructureType) {
779                 while (iter.hasNext ()) {
780                     collectStructure ((StructureType) type, (RefStruct) iter.next ());
781                 }
782             } else if (type instanceof CollectionType) {
783                 while (iter.hasNext ()) {
784                     collectCollection ((CollectionType) type, (Collection) iter.next ());
785                 }
786             }
787         } // while
788

789         Iterator refs = references ((MofClass) proxy.refMetaObject ()).iterator ();
790         while (refs.hasNext ()) {
791             Reference ref = (Reference) refs.next ();
792             /*
793             AggregationKind kind = ref.getReferencedEnd ().getAggregation ();
794             if (AggregationKindEnum.COMPOSITE.equals (kind))
795                 return; // do not serialize reference to immediate composite object
796              */

797             AggregationKind kind = ref.getExposedEnd ().getAggregation ();
798             if (AggregationKindEnum.COMPOSITE.equals (kind)) {
799                 Object JavaDoc temp = obj.refGetValue (ref);
800                 if (temp == null)
801                     continue;
802                 Collection values;
803                 if (isMultivalued (ref))
804                     values = (Collection) temp;
805                 else {
806                     values = new LinkedList ();
807                     values.add (temp);
808                 }
809                 iter = values.iterator ();
810                 while (iter.hasNext ()) {
811                     addLightOutermost ((RefObject) iter.next ());
812                 } // while
813
} // if
814
} // while
815
}
816         
817     protected void collectStructure (StructureType type, RefStruct value) {
818         Iterator iter = structureFields (type).iterator ();
819         while (iter.hasNext ()) {
820             StructureField field = (StructureField) iter.next ();
821             Classifier fieldType = getType (field);
822             if (fieldType instanceof StructureType) {
823                 collectStructure ((StructureType) fieldType, (RefStruct) value.refGetValue (field.getName()));
824             } else if (fieldType instanceof MofClass) {
825                 addLightOutermost ((RefObject) value.refGetValue (field.getName()));
826             } else if (fieldType instanceof CollectionType) {
827                 collectCollection ((CollectionType) fieldType, (Collection) value.refGetValue (field.getName()));
828             }
829         } // while
830
}
831     
832     protected void collectCollection (CollectionType collType, Collection col) {
833         Classifier type = collType.getType ();
834         Iterator iter = col.iterator ();
835         if (type instanceof StructureType) {
836             while (iter.hasNext ())
837                 collectStructure ((StructureType) type, (RefStruct) iter.next ());
838         } else if (type instanceof CollectionType) {
839             while (iter.hasNext ())
840                 collectCollection ((CollectionType) type, (Collection) iter.next ());
841         } else if (type instanceof MofClass) {
842             while (iter.hasNext ())
843                 addLightOutermost ((RefObject) iter.next ());
844         }
845     }
846     
847     protected void addLightOutermost (RefObject obj) {
848         lightOutermosts.add (obj);
849     }
850     
851     /**
852      * Writes reference to an instance (e.g. <Model:Class xmi.idref = 'a1'/>).
853      *
854      * @param externalOnly parameter related to XMI 2.0
855      * @param hrefForced parameter related to XMI 2.0
856      */

857     protected void writeInstanceRef (RefObject obj, boolean externalOnly, boolean hrefForced) {
858         String JavaDoc name = qualifiedName ((ModelElement) obj.refMetaObject ());
859         XMIReferenceProvider.XMIReference xmiRef = provider.getReference (obj);
860         String JavaDoc xmiId = xmiRef.getXmiId ();
861         String JavaDoc systemId = xmiRef.getSystemId ();
862         if ((systemId != null) && (thisSystemId != null) && (thisSystemId.equals (systemId)))
863             systemId = null;
864         startElement (name);
865         if (systemId == null) {
866             addAttribute (XmiConstants.XMI_IDREF, xmiId);
867         } else {
868             addAttribute (XmiConstants.XMI_HREF, systemId + HREF_DELIMITER + xmiId);
869         }
870         endElement (name);
871     }
872
873     /**
874      * Serializes an attribute's value of Primitive or Enumeration type
875      * via XML attribute value.
876      */

877     protected void writeValueInAttr (TypedElement attr, Object JavaDoc value) {
878         String JavaDoc name = elementName (attr);
879         String JavaDoc asText;
880         Classifier type = attr.getType ();
881         if (type instanceof EnumerationType) {
882             String JavaDoc prefix = labelPrefix ((EnumerationType) type);
883             // (optional) enumeration label prefix have to be removed before label is serialized as a String
884
asText = value.toString ().substring (prefix.length ());
885         } else
886             asText = value.toString ();
887         addAttribute (name, asText);
888     }
889
890     /**
891      * Serializes an attribute's or field's (multi-)value into content of an owning element.
892      */

893     protected void writeValueInContent (TypedElement attr, Object JavaDoc value) {
894         if (value == null)
895             return;
896         String JavaDoc name = qualifiedName (attr);
897         Classifier type = getType (attr);
898         Collection values;
899         boolean isMultivalued = false;
900         if (attr instanceof StructuralFeature)
901             isMultivalued = isMultivalued ((StructuralFeature) attr);
902         if (isMultivalued)
903             values = (Collection) value;
904         else {
905             values = new LinkedList ();
906             values.add (value);
907         }
908         Iterator iter = values.iterator ();
909         if (type instanceof StructureType) {
910             startElement (name);
911             while (iter.hasNext ()) {
912                 writeStructure ((StructureType) type , (RefStruct) iter.next ());
913             }
914             endElement (name);
915         } else if (type instanceof MofClass) {
916             startElement (name);
917             while (iter.hasNext ()) {
918                 RefObject obj = (RefObject) iter.next ();
919                 writeInstance (obj, false);
920             }
921             endElement (name);
922         } else if (type instanceof PrimitiveType) {
923             while (iter.hasNext ()) {
924                 Object JavaDoc obj = iter.next ();
925                 startElement (name);
926                 characters (obj.toString ());
927                 endElement (name);
928             }
929         } else if (type instanceof EnumerationType) {
930             while (iter.hasNext ()) {
931                 Object JavaDoc obj = iter.next ();
932                 startElement (name);
933                 String JavaDoc prefix = labelPrefix ((EnumerationType) type);
934                 // (optional) enumeration label prefix have to be removed before label is serialized as a String
935
String JavaDoc label = obj.toString ().substring (prefix.length ());
936                 addAttribute (XmiConstants.XMI_VALUE, label);
937                 endElement (name);
938             }
939         } else if (type instanceof CollectionType) {
940             startElement (name);
941             while (iter.hasNext ()) {
942                 writeCollection ((CollectionType) type , (Collection) iter.next ());
943             }
944             endElement (name);
945         } else {
946             throw new DebugException ("Unsupported type: " + type.getName ());
947         } // if
948
}
949
950     /**
951      * Serializes structure.
952      */

953     /*
954     protected void writeStructure (StructureType type, RefStruct value) {
955         String name = qualifiedName (type);
956         startElement (name);
957         Iterator content = structureFields (type).iterator ();
958         List fields = new LinkedList ();
959         while (content.hasNext ()) {
960             Object field = content.next ();
961             Classifier fieldType = getType ((StructureField) field);
962             if ((fieldType instanceof PrimitiveType) ||
963                 (fieldType instanceof EnumerationType)) {
964                 writeValueInAttr (
965                     (StructureField) field,
966                     value.refGetValue (((ModelElement) field).getName ())
967                 );
968             } else
969                 fields.add (field);
970         } // while
971         Iterator iter = fields.iterator ();
972         while (iter.hasNext ()) {
973             StructureField field = (StructureField) iter.next ();
974             Classifier fieldType = getType (field);
975             String fieldName = qualifiedName (field);
976             Object fieldValue = value.refGetValue (((ModelElement) field).getName ());
977             startElement (fieldName);
978             if (fieldType instanceof MofClass)
979                 writeInstance ((RefObject) fieldValue);
980             else if (fieldType instanceof StructureType)
981                 writeStructure ((StructureType) fieldType, (RefStruct) fieldValue);
982             endElement (fieldName);
983         } // while
984         endElement (name);
985     }
986      */

987
988     // [PENDING] temporally changed, xmi.field tags are used to generate structure value
989
protected void writeStructure (StructureType type, RefStruct value) {
990         Iterator iter = structureFields (type).iterator ();
991         while (iter.hasNext ()) {
992             StructureField field = (StructureField) iter.next ();
993             Classifier fieldType = getType (field);
994             String JavaDoc fieldName = qualifiedName (field);
995             Object JavaDoc fieldValue = value.refGetValue (((ModelElement) field).getName ());
996             startElement (XmiConstants.XMI_FIELD);
997             if (fieldType instanceof MofClass)
998                 writeInstanceRef ((RefObject) fieldValue, false, false);
999             else if (fieldType instanceof StructureType)
1000                writeStructure ((StructureType) fieldType, (RefStruct) fieldValue);
1001            else if (fieldType instanceof CollectionType)
1002                writeCollection ((CollectionType) fieldType, (Collection) fieldValue);
1003            else if (fieldType instanceof PrimitiveType) {
1004                characters (fieldValue.toString ());
1005            }
1006            endElement (XmiConstants.XMI_FIELD);
1007        } // while
1008
}
1009
1010    protected void writeCollection (CollectionType collType, Collection value) {
1011        String JavaDoc collTypeName = qualifiedName (collType);
1012        startElement (collTypeName);
1013        Iterator iter = value.iterator ();
1014        Classifier type = collType.getType ();
1015        String JavaDoc typeName = qualifiedName (type);
1016        if (type instanceof MofClass) {
1017            while (iter.hasNext ()) {
1018                writeInstanceRef ((RefObject) iter.next (), false, false);
1019            }
1020        } else if (type instanceof StructureType) {
1021            while (iter.hasNext ()) {
1022                startElement (typeName);
1023                Object JavaDoc o = iter.next ();
1024                writeStructure ((StructureType) type, (RefStruct) o);
1025                endElement (typeName);
1026            }
1027        } else if (type instanceof CollectionType) {
1028            while (iter.hasNext ()) {
1029                // startElement (typeName);
1030
writeCollection ((CollectionType) type, (Collection) iter.next ());
1031                // endElement (typeName);
1032
}
1033        } else if (type instanceof PrimitiveType) {
1034            while (iter.hasNext ()) {
1035                startElement (typeName);
1036                characters (iter.next ().toString ());
1037                endElement (typeName);
1038            }
1039        } // if
1040
endElement (collTypeName);
1041    }
1042    
1043    /**
1044     * Serializes Reference.
1045     */

1046    protected void writeReference (RefObject obj, Reference ref) {
1047        AggregationKind kind = ref.getReferencedEnd ().getAggregation ();
1048        if (AggregationKindEnum.COMPOSITE.equals (kind))
1049            return; // do not serialize reference to immediate composite object
1050
kind = ref.getExposedEnd ().getAggregation ();
1051        boolean isComposite = AggregationKindEnum.COMPOSITE.equals (kind);
1052        Object JavaDoc temp = obj.refGetValue (ref);
1053        if (temp == null)
1054            return;
1055        Collection values;
1056        if (isMultivalued (ref))
1057            values = (Collection) temp;
1058        else {
1059            values = new LinkedList ();
1060            values.add (temp);
1061        }
1062        Iterator iter;
1063        
1064        if (collectionWriting) {
1065            // exclude all referenced instances that are not in the transitive closure generated by input collection
1066
Collection cValues = new LinkedList ();
1067            iter = values.iterator ();
1068            while (iter.hasNext ()) {
1069                RefObject referencedObject = (RefObject) iter.next ();
1070                if (isInClosure (referencedObject)) {
1071                    cValues.add (referencedObject);
1072                } // if
1073
} // while
1074
values = cValues;
1075        } // if
1076

1077        if (values.isEmpty ())
1078            return;
1079
1080        String JavaDoc name = qualifiedName (ref);
1081        startElement (name);
1082        iter = values.iterator ();
1083        while (iter.hasNext ()) {
1084            RefObject endValue = (RefObject) iter.next ();
1085            if (isComposite)
1086                writeInstance (endValue, false);
1087            else
1088                writeInstanceRef (endValue, false, false);
1089        } // while
1090
endElement (name);
1091    }
1092
1093    /**
1094     * Serializes values of class-scoped attributes of classes contained in a
1095     * given package and its sub-packages.
1096     */

1097    protected void writeStaticAttributes (RefPackage pkg) {
1098        if (processedPackages.contains (pkg))
1099            return;
1100        Iterator iter = pkg.refAllClasses ().iterator ();
1101        while (iter.hasNext ()) {
1102            RefClass proxy = (RefClass) iter.next ();
1103            Iterator attrs = classAttributes ((MofClass) proxy.refMetaObject ()).iterator ();
1104            while (attrs.hasNext ()) {
1105                Attribute attr = (Attribute) attrs.next ();
1106                writeValueInContent (attr, proxy.refGetValue (attr));
1107            } // while
1108
} // while
1109
processedPackages.add (pkg);
1110        // write values of class-scoped attributes of classes contained in sub-packages
1111
Iterator containedPackages = pkg.refAllPackages ().iterator ();
1112        while (containedPackages.hasNext ())
1113            writeStaticAttributes ((RefPackage) containedPackages.next ());
1114    }
1115
1116    /**
1117     * Serializes association links that are not serialized via References.
1118     * All associations contained in a given package and its sub-packages are checked.
1119     */

1120    protected void writeAssociations (RefPackage pkg) {
1121        if (processedPackages.contains (pkg))
1122            return;
1123        Iterator iter = pkg.refAllAssociations ().iterator ();
1124        while (iter.hasNext ()) {
1125            RefAssociation proxy = (RefAssociation) iter.next ();
1126            Association assoc = (Association) proxy.refMetaObject ();
1127            if (assoc.isDerived ())
1128                continue;
1129            // indicates if at least one link has been written
1130
boolean aLinkWritten = false;
1131            String JavaDoc name = qualifiedName (assoc);
1132            AssociationEnd end1 = null, end2 = null;
1133
1134            Iterator content = assoc.getContents ().iterator ();
1135            while (content.hasNext ()) {
1136                Object JavaDoc obj = content.next ();
1137                if (obj instanceof AssociationEnd) {
1138                    if (end1 == null)
1139                        end1 = (AssociationEnd) obj;
1140                    else {
1141                        end2 = (AssociationEnd) obj;
1142                        break;
1143                    }
1144                } // if
1145
} // while
1146
MofClass type1 = (MofClass) end1.getType ();
1147            MofClass type2 = (MofClass) end2.getType ();
1148            boolean isComposite1 = AggregationKindEnum.COMPOSITE.equals(end1.getAggregation ());
1149            boolean isComposite2 = AggregationKindEnum.COMPOSITE.equals(end2.getAggregation ());
1150            boolean ref_1_exists = referenceExists (type1, end2);
1151            boolean ref_2_exists = referenceExists (type2, end1);
1152
1153            if ((ref_1_exists && ref_2_exists) ||
1154                (ref_1_exists && !isComposite2) ||
1155                (ref_2_exists && !isComposite1))
1156                continue; // skip this Association, all its links have been already written via References
1157

1158            boolean isNavigable1 = end1.isNavigable ();
1159            boolean isNavigable2 = end2.isNavigable ();
1160
1161            // temporal caches storing MofClasses and information if they contain a reference
1162
// related to the association
1163
HashMap cache_1 = new HashMap ();
1164            HashMap cache_2 = new HashMap ();
1165            Iterator links = proxy.refAllLinks ().iterator ();
1166
1167            while (links.hasNext ()) {
1168                RefAssociationLink link = (RefAssociationLink) links.next ();
1169                RefObject value_1 = link.refFirstEnd ();
1170                RefObject value_2 = link.refSecondEnd ();
1171
1172                if (collectionWriting && !(isInClosure (value_1) && isInClosure (value_2)))
1173                    continue;
1174
1175                Boolean JavaDoc flag_1 = Boolean.FALSE, flag_2 = Boolean.FALSE;
1176                if (isNavigable1) {
1177                    type1 = (MofClass) value_1.refMetaObject ();
1178                    flag_1 = (Boolean JavaDoc) cache_1.get (type1);
1179                    if (flag_1 == null) {
1180                        if (referenceExists (type1, end2))
1181                            flag_1 = Boolean.TRUE;
1182                        else
1183                            flag_1 = Boolean.FALSE;
1184                        cache_1.put (type1, flag_1);
1185                    } // if
1186
} // if
1187
if (isNavigable2) {
1188                    type2 = (MofClass) value_2.refMetaObject ();
1189                    flag_2 = (Boolean JavaDoc) cache_2.get (type2);
1190                    if (flag_2 == null) {
1191                        if (referenceExists (type2, end1))
1192                            flag_2 = Boolean.TRUE;
1193                        else
1194                            flag_2 = Boolean.FALSE;
1195                        cache_2.put (type2, flag_2);
1196                    } // if
1197
} // if
1198

1199                ref_1_exists = flag_1.booleanValue();
1200                ref_2_exists = flag_2.booleanValue();
1201                
1202                if ((ref_1_exists && ref_2_exists) ||
1203                    (ref_1_exists && !isComposite2) ||
1204                    (ref_2_exists && !isComposite1))
1205                    continue;
1206                
1207                // serialize link
1208
if (!aLinkWritten) {
1209                    // write <AssociationStart>
1210
startElement (name);
1211                    aLinkWritten = true;
1212                }
1213                writeInstanceRef (value_1, false, false); // [PENDING] XMI 2.0 writer should override this
1214
writeInstanceRef (value_2, false, false); // [PENDING] XMI 2.0 writer should override this
1215
} // while (goes through all links of the association)
1216
if (aLinkWritten)
1217                endElement (name);
1218        } // while (goes through all associations in the package)
1219

1220        processedPackages.add (pkg);
1221        Iterator containedPackages = pkg.refAllPackages ().iterator ();
1222        while (containedPackages.hasNext ())
1223            writeAssociations ((RefPackage) containedPackages.next ());
1224    }
1225
1226
1227    /**
1228     * Tests if a mof class has a reference exposing given association end.
1229     */

1230    protected boolean referenceExists (MofClass mofClass, AssociationEnd assocEnd) {
1231        if (!assocEnd.isNavigable ()) {
1232            return false;
1233        }
1234        Iterator references = references (mofClass).iterator ();
1235        while (references.hasNext ()) {
1236            Reference ref = (Reference) references.next ();
1237            AssociationEnd end = ref.getReferencedEnd ();
1238            if (end.equals (assocEnd))
1239                return true;
1240        }
1241        return false;
1242    }
1243
1244    /**
1245     * True if the passed instance have to be written by write(Collection) method.
1246     */

1247    protected boolean isInClosure (RefObject obj) {
1248        RefObject container = obj;
1249        RefFeatured featured;
1250        while (container != null) {
1251            if (objectsToWrite.contains (container))
1252                return true;
1253            featured = container.refImmediateComposite ();
1254            container = ((featured instanceof RefObject) && (featured != obj))? (RefObject) featured : null;
1255        }
1256        return false;
1257    }
1258
1259    /**
1260     * Returns fully qualified name of an model element.
1261     */

1262    protected String JavaDoc qualifiedName (ModelElement element) {
1263        Iterator iter = element.getQualifiedName ().iterator ();
1264        String JavaDoc name = (String JavaDoc) iter.next ();
1265        while (iter.hasNext ())
1266            name = name.concat (XmiConstants.DOT_SEPARATOR).concat ((String JavaDoc) iter.next ());
1267
1268        int index = name.lastIndexOf ('.');
1269        String JavaDoc pName = name.substring (0, index);
1270        String JavaDoc sName = name.substring (index + 1, name.length ());
1271        if (!(element instanceof MofClass) && !(element instanceof Association)) {
1272            index = pName.lastIndexOf ('.');
1273            if (index > -1) {
1274                pName = pName.substring (0, index);
1275                sName = name.substring (index + 1, name.length ());
1276            }
1277        }
1278
1279        String JavaDoc namespace = (String JavaDoc) namespaces.get (pName);
1280
1281        if (namespace != null)
1282            return namespace + ":" + sName;
1283        return name;
1284    }
1285
1286    protected String JavaDoc elementName (ModelElement elem) {
1287        return elem.getName ();
1288    }
1289    
1290    /**
1291     * True iff given StructuralFeature is multivalued.
1292     */

1293    protected static boolean isMultivalued (StructuralFeature feature) {
1294        MultiplicityType multType = feature.getMultiplicity ();
1295        return multType.getUpper () != 1;
1296    }
1297
1298    protected static Classifier getType (TypedElement elem) {
1299        Classifier type = elem.getType ();
1300        while (type instanceof AliasType)
1301            type = ((AliasType) type).getType ();
1302        return type;
1303    }
1304
1305    // default XMIReferenceProvider ..............................................
1306

1307    class DefaultProvider implements XMIReferenceProvider {
1308        
1309        public XMIReferenceProvider.XMIReference getReference (RefObject obj) {
1310            return new XMIReferenceProvider.XMIReference (null, getXmiId(obj));
1311        }
1312        
1313    }
1314    
1315}
1316
Popular Tags