|
What this is
Other links
The source code
/*
* Sun Public License Notice
*
* The contents of this file are subject to the Sun Public License
* Version 1.0 (the "License"). You may not use this file except in
* compliance with the License. A copy of the License is available at
* http://www.sun.com/
*
* The Original Code is NetBeans. The Initial Developer of the Original
* Code is Sun Microsystems, Inc. Portions Copyright 1997-2001 Sun
* Microsystems, Inc. All Rights Reserved.
*/
package org.netbeans.lib.jmi.xmi;
import java.io.*;
import java.util.*;
import java.net.*;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import org.netbeans.api.xmi.*;
import javax.jmi.reflect.*;
import javax.jmi.model.*;
import org.netbeans.lib.jmi.util.Logger;
import org.netbeans.lib.jmi.util.DebugException;
public class XmiSAXReader extends DefaultHandler {
private URL docURL = null;
// currently processed element
private XmiElement currentElement;
// context
private XmiContext context;
// differences that have to be applayed on the content of read XMI
private HashMap diffs = null;
// indicates if elements of Content section are being currently read
private boolean contentIsRead = false;
// indicates if a predecessor of a read sub-element has been deleted by a diference
private boolean elementIsDeleted = false;
// timestamp of a difference that has been or is being applyed
private int lastTimeStamp = 0;
// stack used to to track information needed to applay differences
private Stack stack = new Stack ();
// document locator
private Locator locator = null;
// root element name ("XMI" in case of XMI 1.1, "ns:XMI" or "ns:ClassName" in case of XMI 2.0)
private String rootElementName = null;
// possible elemnet of the stack, represents a deleted XMI element
private final Object DELETED = new Integer (0);
// an empty element, pushed to the stack if no information is needed to store in a given step
private final Object EMPTY = new Integer (1);
private XMIInputConfig config;
// init .....................................................................
public XmiSAXReader () {
this (null, null);
}
public XmiSAXReader (XMIInputConfig config) {
this (null, config);
}
public XmiSAXReader (XmiContext context, XMIInputConfig config) {
this.context = context;
if (config == null)
this.config = new InputConfig ();
else
this.config = config;
}
// methods ..................................................................
public Collection read (InputStream input, String uri, RefPackage[] extents, String encoding)
throws IOException, SAXException, ParserConfigurationException {
InputSource is = new InputSource (input);
if (encoding != null) {
is.setEncoding(encoding);
}
if (uri != null) {
is.setSystemId(uri);
try {
docURL = new URI (uri).toURL ();
} catch (URISyntaxException e) {
} catch (MalformedURLException e) {
} catch (IllegalArgumentException e) {
}
}
return read (is, extents);
}
public Collection read (URL url, RefPackage[] extents, String encoding)
throws IOException, SAXException, ParserConfigurationException {
docURL = url;
InputSource is = new InputSource (url.toString ());
if (encoding != null)
is.setEncoding(encoding);
return read (is, extents);
}
public Collection read (URL url, RefPackage[] extents, String encoding, HashMap diffs)
throws IOException, SAXException, ParserConfigurationException {
this.diffs = diffs;
return read (url, extents, encoding);
}
public Collection read (InputSource input, RefPackage[] extents)
throws IOException, SAXException, ParserConfigurationException {
if (diffs == null)
Logger.getDefault().log ("XMI reader started");
long time = System.currentTimeMillis ();
if (docURL == null) {
String systemId = input.getSystemId();
if (systemId != null) {
try {
docURL = new URL (systemId);
} catch (MalformedURLException e) {
} catch (IllegalArgumentException e) {
}
}
}
if (context == null)
context = new XmiContext (extents, docURL, config);
SAXParserFactory factory = SAXParserFactory.newInstance ();
factory.setValidating (false);
SAXParser saxParser = factory.newSAXParser ();
saxParser.parse (input, this);
time = System.currentTimeMillis () - time;
if (diffs == null)
Logger.getDefault().log ("finished, TIME: " + time/1000.0 + "[s]");
return context.getOutermostObjects ();
}
void initConsumer (RefPackage pkg) throws SAXException {
context = new XmiContext (new RefPackage [] {pkg}, null, config);
}
public void startDocument () throws SAXException {
rootElementName = null;
}
/*
public void endDocument () throws SAXException {
}
*/
public void startElement (String namespaceURI, String sName, String qName, Attributes attrs)
throws SAXException {
try {
// Logger.getDefault().log ("s: " + qName);
if (elementIsDeleted) {
stack.push (EMPTY);
return;
} else if (rootElementName == null) {
rootElementName = qName;
currentElement = new XmiElement.Document (null, context, qName, attrs);
return;
} else if (currentElement == null) {
throw new DebugException("Not an XMI document. Root element must be <"+XmiConstants.XMI_ROOT+">");
} else if (qName.equals (XmiConstants.XMI_CONTENT)) {
stack.push (EMPTY);
contentIsRead = true;
} else if ((contentIsRead && qName.equals(XmiConstants.XMI_EXTENSION)) ||
(!contentIsRead && qName.equals(XmiConstants.XMI_EXTENSIONS))) {
stack.push (DELETED);
elementIsDeleted = true;
return;
} else if ((contentIsRead) && (diffs != null)) {
// check if there are some differences to apply
String xmiId = attrs.getValue (XmiConstants.XMI_ID);
List list = null;
if (xmiId != null)
list = (List) diffs.get (xmiId);
if (list != null) {
String elementName = null;
Iterator iter = list.iterator ();
List modifs = new LinkedList ();
while (iter.hasNext ()) {
XmiElement.Difference.Diff diff = (XmiElement.Difference.Diff) iter.next ();
if (diff.timeStamp <= lastTimeStamp)
continue;
switch (diff.kind) {
case XmiElement.Difference.Diff.DELETE:
stack.push (DELETED);
elementIsDeleted = true;
return;
case XmiElement.Difference.Diff.ADD:
modifs.add (diff);
break;
case XmiElement.Difference.Diff.REPLACE:
XmiElement.Difference.Item item = (XmiElement.Difference.Item) diff.items.removeFirst ();
qName = item.qName;
attrs = item.attrs;
elementName = qName;
diff.items.removeLast ();
modifs.add (diff);
break;
} // switch
} // while
stack.push (new StackElement (modifs, elementName));
} else {
stack.push (EMPTY);
} // if
} // if
currentElement = currentElement.startSubElement (qName, attrs);
if (currentElement == null)
// should not occur
throw new DebugException ("XmiElement.startSubElement("+qName+", ..) returned null");
if (contentIsRead && (diffs != null))
applayDiffs ();
} catch (Exception e) {
e.printStackTrace ();
Logger.getDefault().annotate(e, "Error parsing XMI" + getLineNumberErrorString());
throw (SAXException) Logger.getDefault().annotate(new SAXException("XMI parsing error" + getLineNumberErrorString() + ": " + (e.getMessage() != null ? e.getMessage() : e.toString()), e), e);
}
}
public void endElement (String namespaceURI, String sName, String qName) throws SAXException {
// Logger.getDefault().log ("e: " + qName);
try {
if (elementIsDeleted) {
if (stack.pop () == DELETED)
elementIsDeleted = false;
return;
}
if (qName.equals (XmiConstants.XMI_CONTENT))
contentIsRead = false;
else {
if (contentIsRead && (diffs != null)) {
Object obj = stack.pop ();
if ((obj instanceof StackElement) && ((StackElement) obj).replacedName != null)
qName = ((StackElement) obj).replacedName;
}
} // if
currentElement = currentElement.endElement (qName);
if ((currentElement == null) && !qName.equals (rootElementName))
// should not occur
throw new DebugException ("XmiElement.endElement("+qName+") returned null");
if (contentIsRead && (diffs != null))
applayDiffs ();
} catch (Exception e) {
e.printStackTrace ();
String message = "XMI parsing error" + getLineNumberErrorString() + ": " + (e.getMessage() != null ? e.getMessage() : e.toString());
Logger.getDefault().log(Logger.WARNING, message);
SAXException ne = new SAXException(message, e);
throw (SAXException) Logger.getDefault().annotate(ne, e);
}
}
public void characters (char buf[], int offset, int len) throws SAXException {
String s = new String (buf, offset, len);
try {
if (!elementIsDeleted) {
if (currentElement != null)
currentElement.characters (buf, offset, len);
}
} catch (Exception e) {
e.printStackTrace ();
SAXException ne = new SAXException("XMI parsing error" + getLineNumberErrorString() + ": " + (e.getMessage() != null ? e.getMessage() : e.toString()), e);
Logger.getDefault().annotate(ne, e);
throw (SAXException) Logger.getDefault().annotate(ne, "XMI parsing error" + getLineNumberErrorString());
}
}
public void setDocumentLocator (Locator locator) {
this.locator = locator;
}
/**
* Produces text like "at line: #" useful for error messages. Produces
* the empty string, if no locator was set.
*/
private String getLineNumberErrorString() {
if ( locator != null ) {
return " at line: " + locator.getLineNumber();
} else {
return "";
}
}
public InputSource resolveEntity (String publicID, String systemID) {
Logger.getDefault().log ("resolving reference: " + publicID + ", " + systemID);
return new InputSource (new StringReader (""));
}
private void applayDiffs () throws SAXException {
Object elem = stack.peek ();
if (elem != EMPTY) {
((StackElement) elem).position++;
Iterator iter = ((StackElement) elem).diffs.iterator ();
while (iter.hasNext ()) {
XmiElement.Difference.Diff diff = (XmiElement.Difference.Diff) iter.next ();
if ((diff.position == ((StackElement) elem).position) && (diff.timeStamp > lastTimeStamp)) {
int temp = lastTimeStamp;
lastTimeStamp = diff.timeStamp;
addContent (diff);
lastTimeStamp = temp;
}
} // while
} // if (item != null)
}
private void addContent (XmiElement.Difference.Diff diff) throws SAXException {
Iterator iter = diff.items.iterator ();
while (iter.hasNext ()) {
Object obj = iter.next ();
if (obj instanceof XmiElement.Difference.Item) {
XmiElement.Difference.Item item = (XmiElement.Difference.Item) obj;
if (item.isStart) {
startElement (null, "", item.qName, item.attrs);
} else {
endElement (null, "", item.qName);
}
} else
characters (((String) obj).toCharArray (), 0, ((String) obj).length ());
} // while
}
private static class StackElement {
public int position = 0;
public List diffs;
public String replacedName;
public StackElement (List diffs, String replacedName) {
this.diffs = diffs;
this.replacedName = replacedName;
}
} // StackElement
}
|
| ... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.