KickJava   Java API By Example, From Geeks To Geeks.

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


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.*;
24
25 import org.xml.sax.*;
26 import org.xml.sax.helpers.DefaultHandler JavaDoc;
27 import javax.xml.parsers.SAXParserFactory JavaDoc;
28 import javax.xml.parsers.ParserConfigurationException JavaDoc;
29 import javax.xml.parsers.SAXParser JavaDoc;
30
31 import org.netbeans.api.xmi.*;
32
33 import javax.jmi.reflect.*;
34 import javax.jmi.model.*;
35 import org.netbeans.lib.jmi.util.Logger;
36 import org.netbeans.lib.jmi.util.DebugException;
37
38 public class XmiSAXReader extends DefaultHandler JavaDoc {
39
40     private URL docURL = null;
41     
42     // currently processed element
43
private XmiElement currentElement;
44     // context
45
private XmiContext context;
46     
47     // differences that have to be applayed on the content of read XMI
48
private HashMap diffs = null;
49     // indicates if elements of Content section are being currently read
50
private boolean contentIsRead = false;
51     // indicates if a predecessor of a read sub-element has been deleted by a diference
52
private boolean elementIsDeleted = false;
53     // timestamp of a difference that has been or is being applyed
54
private int lastTimeStamp = 0;
55     // stack used to to track information needed to applay differences
56
private Stack stack = new Stack ();
57     // document locator
58
private Locator locator = null;
59     // root element name ("XMI" in case of XMI 1.1, "ns:XMI" or "ns:ClassName" in case of XMI 2.0)
60
private String JavaDoc rootElementName = null;
61
62     // possible elemnet of the stack, represents a deleted XMI element
63
private final Object JavaDoc DELETED = new Integer JavaDoc (0);
64     // an empty element, pushed to the stack if no information is needed to store in a given step
65
private final Object JavaDoc EMPTY = new Integer JavaDoc (1);
66     
67     private XMIInputConfig config;
68     
69     // init .....................................................................
70

71     public XmiSAXReader () {
72         this (null, null);
73     }
74     
75     public XmiSAXReader (XMIInputConfig config) {
76         this (null, config);
77     }
78     
79     public XmiSAXReader (XmiContext context, XMIInputConfig config) {
80         this.context = context;
81         if (config == null)
82             this.config = new InputConfig ();
83         else
84             this.config = config;
85     }
86     
87     // methods ..................................................................
88

89     public Collection read (InputStream input, String JavaDoc uri, RefPackage[] extents, String JavaDoc encoding)
90         throws IOException, SAXException, ParserConfigurationException JavaDoc {
91         InputSource is = new InputSource (input);
92         if (encoding != null) {
93             is.setEncoding(encoding);
94         }
95         if (uri != null) {
96             is.setSystemId(uri);
97             try {
98                 docURL = new URI (uri).toURL ();
99             } catch (URISyntaxException e) {
100             } catch (MalformedURLException e) {
101             } catch (IllegalArgumentException JavaDoc e) {
102             }
103         }
104         return read (is, extents);
105     }
106     
107     public Collection read (URL url, RefPackage[] extents, String JavaDoc encoding)
108         throws IOException, SAXException, ParserConfigurationException JavaDoc {
109         docURL = url;
110         InputSource is = new InputSource (url.toString ());
111         if (encoding != null)
112             is.setEncoding(encoding);
113         return read (is, extents);
114     }
115      
116     public Collection read (URL url, RefPackage[] extents, String JavaDoc encoding, HashMap diffs)
117         throws IOException, SAXException, ParserConfigurationException JavaDoc {
118         this.diffs = diffs;
119         return read (url, extents, encoding);
120     }
121     
122     public Collection read (InputSource input, RefPackage[] extents)
123         throws IOException, SAXException, ParserConfigurationException JavaDoc {
124         if (diffs == null)
125             Logger.getDefault().log ("XMI reader started");
126         long time = System.currentTimeMillis ();
127         if (docURL == null) {
128             String JavaDoc systemId = input.getSystemId();
129             if (systemId != null) {
130                 try {
131                     docURL = new URL (systemId);
132                 } catch (MalformedURLException e) {
133                 } catch (IllegalArgumentException JavaDoc e) {
134                 }
135             }
136         }
137         if (context == null)
138             context = new XmiContext (extents, docURL, config);
139         SAXParserFactory JavaDoc factory = SAXParserFactory.newInstance ();
140         factory.setValidating (false);
141         SAXParser JavaDoc saxParser = factory.newSAXParser ();
142         saxParser.parse (input, this);
143         time = System.currentTimeMillis () - time;
144         if (diffs == null)
145             Logger.getDefault().log ("finished, TIME: " + time/1000.0 + "[s]");
146         return context.getOutermostObjects ();
147     }
148     
149     void initConsumer (RefPackage pkg) throws SAXException {
150         context = new XmiContext (new RefPackage [] {pkg}, null, config);
151     }
152     
153     
154     public void startDocument () throws SAXException {
155         rootElementName = null;
156     }
157
158     /*
159     public void endDocument () throws SAXException {
160     }
161      */

162
163     public void startElement (String JavaDoc namespaceURI, String JavaDoc sName, String JavaDoc qName, Attributes attrs)
164     throws SAXException {
165         
166         try {
167         
168         // Logger.getDefault().log ("s: " + qName);
169

170         if (elementIsDeleted) {
171             stack.push (EMPTY);
172             return;
173         } else if (rootElementName == null) {
174             rootElementName = qName;
175             currentElement = new XmiElement.Document (null, context, qName, attrs);
176             return;
177         } else if (currentElement == null) {
178             throw new DebugException("Not an XMI document. Root element must be <"+XmiConstants.XMI_ROOT+">");
179         } else if (qName.equals (XmiConstants.XMI_CONTENT)) {
180             stack.push (EMPTY);
181             contentIsRead = true;
182         } else if ((contentIsRead && qName.equals(XmiConstants.XMI_EXTENSION)) ||
183                     (!contentIsRead && qName.equals(XmiConstants.XMI_EXTENSIONS))) {
184             stack.push (DELETED);
185             elementIsDeleted = true;
186             return;
187         } else if ((contentIsRead) && (diffs != null)) {
188             // check if there are some differences to apply
189
String JavaDoc xmiId = attrs.getValue (XmiConstants.XMI_ID);
190             List list = null;
191             if (xmiId != null)
192                 list = (List) diffs.get (xmiId);
193             if (list != null) {
194                 String JavaDoc elementName = null;
195                 Iterator iter = list.iterator ();
196                 List modifs = new LinkedList ();
197                 while (iter.hasNext ()) {
198                     XmiElement.Difference.Diff diff = (XmiElement.Difference.Diff) iter.next ();
199                     if (diff.timeStamp <= lastTimeStamp)
200                         continue;
201                     switch (diff.kind) {
202                         case XmiElement.Difference.Diff.DELETE:
203                             stack.push (DELETED);
204                             elementIsDeleted = true;
205                             return;
206                         case XmiElement.Difference.Diff.ADD:
207                             modifs.add (diff);
208                         break;
209                         case XmiElement.Difference.Diff.REPLACE:
210                             XmiElement.Difference.Item item = (XmiElement.Difference.Item) diff.items.removeFirst ();
211                             qName = item.qName;
212                             attrs = item.attrs;
213                             elementName = qName;
214                             diff.items.removeLast ();
215                             modifs.add (diff);
216                         break;
217                     } // switch
218
} // while
219
stack.push (new StackElement (modifs, elementName));
220             } else {
221                 stack.push (EMPTY);
222             } // if
223
} // if
224

225         currentElement = currentElement.startSubElement (qName, attrs);
226         if (currentElement == null)
227             // should not occur
228
throw new DebugException ("XmiElement.startSubElement("+qName+", ..) returned null");
229         
230         if (contentIsRead && (diffs != null))
231             applayDiffs ();
232         
233         } catch (Exception JavaDoc e) {
234             
235             e.printStackTrace ();
236             
237             Logger.getDefault().annotate(e, "Error parsing XMI" + getLineNumberErrorString());
238             throw (SAXException) Logger.getDefault().annotate(new SAXException("XMI parsing error" + getLineNumberErrorString() + ": " + (e.getMessage() != null ? e.getMessage() : e.toString()), e), e);
239         }
240         
241     }
242
243     public void endElement (String JavaDoc namespaceURI, String JavaDoc sName, String JavaDoc qName) throws SAXException {
244         // Logger.getDefault().log ("e: " + qName);
245

246         try {
247         
248         if (elementIsDeleted) {
249             if (stack.pop () == DELETED)
250                 elementIsDeleted = false;
251             return;
252         }
253
254         if (qName.equals (XmiConstants.XMI_CONTENT))
255             contentIsRead = false;
256         else {
257             if (contentIsRead && (diffs != null)) {
258                 Object JavaDoc obj = stack.pop ();
259                 if ((obj instanceof StackElement) && ((StackElement) obj).replacedName != null)
260                     qName = ((StackElement) obj).replacedName;
261             }
262         } // if
263

264         currentElement = currentElement.endElement (qName);
265         if ((currentElement == null) && !qName.equals (rootElementName))
266             // should not occur
267
throw new DebugException ("XmiElement.endElement("+qName+") returned null");
268         
269         if (contentIsRead && (diffs != null))
270             applayDiffs ();
271         
272         } catch (Exception JavaDoc e) {
273             
274             e.printStackTrace ();
275             String JavaDoc message = "XMI parsing error" + getLineNumberErrorString() + ": " + (e.getMessage() != null ? e.getMessage() : e.toString());
276             Logger.getDefault().log(Logger.WARNING, message);
277             SAXException ne = new SAXException(message, e);
278             throw (SAXException) Logger.getDefault().annotate(ne, e);
279         }
280         
281     }
282
283     public void characters (char buf[], int offset, int len) throws SAXException {
284         
285         String JavaDoc s = new String JavaDoc (buf, offset, len);
286         
287         try {
288         
289         if (!elementIsDeleted) {
290             if (currentElement != null)
291                 currentElement.characters (buf, offset, len);
292         }
293         
294         } catch (Exception JavaDoc e) {
295             
296             e.printStackTrace ();
297             
298             SAXException ne = new SAXException("XMI parsing error" + getLineNumberErrorString() + ": " + (e.getMessage() != null ? e.getMessage() : e.toString()), e);
299             Logger.getDefault().annotate(ne, e);
300             throw (SAXException) Logger.getDefault().annotate(ne, "XMI parsing error" + getLineNumberErrorString());
301         }
302     
303     }
304
305     public void setDocumentLocator (Locator locator) {
306         this.locator = locator;
307     }
308     
309     /**
310      * Produces text like "at line: #" useful for error messages. Produces
311      * the empty string, if no locator was set.
312      */

313     private String JavaDoc getLineNumberErrorString() {
314       if ( locator != null ) {
315         return " at line: " + locator.getLineNumber();
316       } else {
317         return "";
318       }
319     }
320     
321     public InputSource resolveEntity (String JavaDoc publicID, String JavaDoc systemID) {
322         Logger.getDefault().log ("resolving reference: " + publicID + ", " + systemID);
323         return new InputSource (new StringReader (""));
324     }
325
326     private void applayDiffs () throws SAXException {
327         Object JavaDoc elem = stack.peek ();
328         if (elem != EMPTY) {
329             ((StackElement) elem).position++;
330             Iterator iter = ((StackElement) elem).diffs.iterator ();
331             while (iter.hasNext ()) {
332                 XmiElement.Difference.Diff diff = (XmiElement.Difference.Diff) iter.next ();
333                 if ((diff.position == ((StackElement) elem).position) && (diff.timeStamp > lastTimeStamp)) {
334                     int temp = lastTimeStamp;
335                     lastTimeStamp = diff.timeStamp;
336                     addContent (diff);
337                     lastTimeStamp = temp;
338                 }
339             } // while
340
} // if (item != null)
341
}
342     
343     private void addContent (XmiElement.Difference.Diff diff) throws SAXException {
344         Iterator iter = diff.items.iterator ();
345         while (iter.hasNext ()) {
346             Object JavaDoc obj = iter.next ();
347             if (obj instanceof XmiElement.Difference.Item) {
348                 XmiElement.Difference.Item item = (XmiElement.Difference.Item) obj;
349                 if (item.isStart) {
350                     startElement (null, "", item.qName, item.attrs);
351                 } else {
352                     endElement (null, "", item.qName);
353                 }
354             } else
355                 characters (((String JavaDoc) obj).toCharArray (), 0, ((String JavaDoc) obj).length ());
356         } // while
357
}
358     
359     private static class StackElement {
360         public int position = 0;
361         public List diffs;
362         public String JavaDoc replacedName;
363         
364         public StackElement (List diffs, String JavaDoc replacedName) {
365             this.diffs = diffs;
366             this.replacedName = replacedName;
367         }
368     } // StackElement
369

370 }
Popular Tags