Index: lib/Makefile.am
===================================================================
RCS file: /cvsroot/cashew-s-editor/cashews/lib/Makefile.am,v
retrieving revision 1.3
diff -u -3 -p -u -r1.3 Makefile.am
--- lib/Makefile.am 28 Mar 2005 19:29:21 -0000 1.3
+++ lib/Makefile.am 9 Apr 2005 01:13:44 -0000
@@ -52,13 +52,13 @@ JAVAH = $(USER_JAVAH) -jni -classpath .:
if INSTALL_GLIBJ_ZIP
if FOUND_ECLIPSE
-pkgdata_DATA = rdf.jar owls.jar eclipse.jar
+pkgdata_DATA = xml.jar rdf.jar owls.jar eclipse.jar
install-data-local: genclasses compile-classes eclipse.jar
mkdir $(INSTALLDIR)
cp eclipse.jar $(INSTALLDIR)
cp $(top_srcdir)/resource/plugin.xml $(INSTALLDIR)
else
-pkgdata_DATA = rdf.jar owls.jar
+pkgdata_DATA = xml.jar rdf.jar owls.jar
endif
endif # INSTALL_GLIBJ_ZIP
@@ -79,6 +79,12 @@ endif # INSTALL_CLASS_FILES
.PHONY: genclasses
+xml.jar: classes compile-classes # resources
+ if test "$(JAR)" != ""; then rm xml.jar; $(JAR) cf xml.jar `find nongnu -path '*xml\/*' -name '*class'` > /dev/null; fi
+if FOUND_GCJ
+$(GCJ) -shared -fjni -findirect-dispatch -o xml.jar.so xml.jar
+endif
+
rdf.jar: classes compile-classes # resources
if test "$(JAR)" != ""; then rm rdf.jar; $(JAR) cf rdf.jar `find nongnu -path '*rdf*' -name '*class'` > /dev/null; fi
if FOUND_GCJ
Index: src/nongnu/cashews/commons/Pair.java
===================================================================
RCS file: src/nongnu/cashews/commons/Pair.java
diff -N src/nongnu/cashews/commons/Pair.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/nongnu/cashews/commons/Pair.java 9 Apr 2005 01:13:44 -0000
@@ -0,0 +1,95 @@
+/* Pair.java -- A heterogenous pair type.
+ Copyright (C) 2005 The University of Sheffield.
+
+ This file is part of the CASheW-s editor.
+
+ The CASheW-s editor is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ The CASheW-s editor is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with The CASheW-s editor; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA.
+*/
+
+package nongnu.cashews.commons;
+
+/**
+ * A small helper class to pair up two arbitrary heterogenously-typed
+ * values. This is where we wish we had a tuple data type.
+ *
+ * @author Andrew John Hughes (address@hidden)
+ */
+public class Pair
+{
+
+ /**
+ * The left-hand value.
+ */
+ private A left;
+
+ /**
+ * The right-hand value.
+ */
+ private B right;
+
+ /**
+ * Constructs a new pair using the values specified.
+ *
+ * @param a the left-hand value.
+ * @param b the right-hand value.
+ */
+ public Pair(A left, B right)
+ {
+ setLeft(left);
+ setRight(right);
+ }
+
+ /**
+ * Retrieve a reference to the left-hand value.
+ *
+ * @return the left-hand value.
+ */
+ public A getLeft()
+ {
+ return left;
+ }
+
+ /**
+ * Retrieve a reference to the right-hand value.
+ *
+ * @return the right-hand value.
+ */
+ public B getRight()
+ {
+ return right;
+ }
+
+ /**
+ * Set the left-hand value.
+ *
+ * @param left the new left-hand value.
+ */
+ public void setLeft(A left)
+ {
+ this.left = left;
+ }
+
+ /**
+ * Set the right-hand value.
+ *
+ * @param right the new right-hand value.
+ */
+ public void setRight(B right)
+ {
+ this.right = right;
+ }
+
+}
Index: src/nongnu/cashews/rdf/XMLParser.java
===================================================================
RCS file: /cvsroot/cashew-s-editor/cashews/src/nongnu/cashews/rdf/XMLParser.java,v
retrieving revision 1.6
diff -u -3 -p -u -r1.6 XMLParser.java
--- src/nongnu/cashews/rdf/XMLParser.java 5 Apr 2005 16:48:53 -0000 1.6
+++ src/nongnu/cashews/rdf/XMLParser.java 9 Apr 2005 01:13:44 -0000
@@ -32,11 +32,12 @@ import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;
+import nongnu.cashews.xml.XmlBaseHandler;
+
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
-import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;
/**
@@ -70,7 +71,14 @@ public class XMLParser
* @serial the graph of RDF triples.
*/
private Graph graph;
-
+
+ /**
+ * The handler for the XML.
+ *
+ * @serial the XML handler.
+ */
+ private RDFHandler rdfHandler;
+
/**
* Constructs a new XML-based RDF parser, using the specified handler
* for messages.
@@ -82,8 +90,9 @@ public class XMLParser
public XMLParser(Handler handler)
throws SAXException
{
- reader = XMLReaderFactory.createXMLReader();
- reader.setContentHandler(new RDFHandler(handler));
+ reader = XMLReaderFactory.createXMLReader();
+ rdfHandler = new RDFHandler(handler);
+ reader.setContentHandler(rdfHandler);
}
/**
@@ -97,9 +106,7 @@ public class XMLParser
public Graph parse(String systemId)
throws IOException, SAXException
{
- graph = new Graph();
- reader.parse(systemId);
- return graph;
+ return parse(new InputSource(systemId));
}
/**
@@ -114,6 +121,7 @@ public class XMLParser
throws IOException, SAXException
{
graph = new Graph();
+ rdfHandler.setBaseURI(source.getSystemId());
reader.parse(source);
return graph;
}
@@ -160,14 +168,14 @@ public class XMLParser
* @author Andrew John Hughes (address@hidden)
*/
private class RDFHandler
- extends DefaultHandler
+ extends XmlBaseHandler
{
/**
* A Logger
instance to log events generated by the
* parsing process.
*/
- private Logger logger;
+ private Logger rdfLogger;
/**
* Flag to indicate whether we are inside an RDF document
@@ -230,9 +238,10 @@ public class XMLParser
*/
public RDFHandler(Handler handler)
{
- logger = Logger.getLogger("nongnu.cashews.rdf.XMLParser");
- logger.addHandler(handler);
- logger.setLevel(handler.getLevel());
+ super(handler);
+ rdfLogger = Logger.getLogger("nongnu.cashews.rdf.XMLParser");
+ rdfLogger.addHandler(handler);
+ rdfLogger.setLevel(handler.getLevel());
}
/**
@@ -241,6 +250,7 @@ public class XMLParser
*/
public void startDocument()
{
+ super.startDocument();
inSubject = false;
inRDF = false;
inPredicate = false;
@@ -263,18 +273,19 @@ public class XMLParser
String qName, Attributes attributes)
throws SAXException
{
+ super.startElement(uri, localName, qName, attributes);
if (uri.equals(RDF_NAMESPACE))
{
if (localName.equals("RDF"))
{
/* rdf:RDF */
inRDF = true;
- logger.finer("Start of RDF block");
+ rdfLogger.finer("Start of RDF block");
}
else if (localName.equals("Description"))
{
/* rdf:Description */
- logger.finer("Start of RDF description block");
+ rdfLogger.finer("Start of RDF description block");
inRDF = true;
if (!inSubject)
{
@@ -289,13 +300,14 @@ public class XMLParser
if (value != null)
subject = new Blank(value);
else
- logger.warning("No subject found in RDF description.");
+ rdfLogger.warning("No subject found in RDF " +
+ "description.");
}
inSubject = true;
- logger.fine("Created subject: " + subject);
+ rdfLogger.fine("Created subject: " + subject);
}
else
- logger.warning("Invalid use of RDF namespace: " + uri +
+ rdfLogger.warning("Invalid use of RDF namespace: " + uri +
localName);
}
}
@@ -307,9 +319,9 @@ public class XMLParser
{
/* Predicate element */
predicateURI = uri + localName;
- logger.finer("Start of predicate: " + predicateURI);
+ rdfLogger.finer("Start of predicate: " + predicateURI);
predicate = parseRDFURI(predicateURI);
- logger.fine("Created predicate: " + predicate);
+ rdfLogger.fine("Created predicate: " + predicate);
inSubject = false;
inPredicate = true;
/* Check for RDF URI object */
@@ -318,7 +330,7 @@ public class XMLParser
if (value != null)
{
object = parseRDFURI(value);
- logger.fine("Created object: " + object);
+ rdfLogger.fine("Created object: " + object);
}
else
{
@@ -327,7 +339,7 @@ public class XMLParser
if (value != null)
{
object = new Blank(value);
- logger.fine("Created object: " + object);
+ rdfLogger.fine("Created object: " + object);
}
}
/* Check for a type */
@@ -371,17 +383,18 @@ public class XMLParser
public void characters(char[] ch, int start, int length)
throws SAXException
{
+ super.characters(ch, start, length);
String value = new String(ch, start, length).trim();
if (value.length() == 0)
return;
- logger.finer("Characters: " + value);
+ rdfLogger.finer("Characters: " + value);
if (inPredicate)
{
if (type == null)
object = new Literal(value);
else
object = new Literal(value, type);
- logger.fine("Created object: " + object);
+ rdfLogger.fine("Created object: " + object);
}
}
@@ -399,16 +412,17 @@ public class XMLParser
String qName)
throws SAXException
{
+ super.endElement(uri, localName, qName);
if (uri.equals(RDF_NAMESPACE))
{
if (localName.equals("RDF"))
{
inRDF = false;
- logger.finer("End of RDF block");
+ rdfLogger.finer("End of RDF block");
}
else if (localName.equals("Description"))
{
- logger.finer("End of description block");
+ rdfLogger.finer("End of description block");
inSubject = false;
}
}
@@ -419,9 +433,9 @@ public class XMLParser
predicateURI = null;
type = null;
triple = new Triple(subject, predicate, object);
- logger.fine("Created triple: " + triple);
+ rdfLogger.fine("Created triple: " + triple);
graph.addTriple(triple);
- logger.finer("End of predicate block");
+ rdfLogger.finer("End of predicate block");
}
}
Index: src/nongnu/cashews/xml/XmlBaseHandler.java
===================================================================
RCS file: src/nongnu/cashews/xml/XmlBaseHandler.java
diff -N src/nongnu/cashews/xml/XmlBaseHandler.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/nongnu/cashews/xml/XmlBaseHandler.java 9 Apr 2005 01:13:44 -0000
@@ -0,0 +1,262 @@
+/* XMLBaseHandler.java -- Handler for the XML Base standard.
+ Copyright (C) 2005 The University of Sheffield.
+
+ This file is part of the CASheW-s editor.
+
+ The CASheW-s editor is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ The CASheW-s editor is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with The CASheW-s editor; see the file COPYING. If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA.
+*/
+
+package nongnu.cashews.xml;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Stack;
+import java.util.logging.Handler;
+import java.util.logging.Logger;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * This class deals with the parsing of XML using the
+ * XML Base standard.
+ * The current base URI is monitored using a stack, with the default
+ * URI at the bottom.
+ *
+ * @author Andrew John Hughes (address@hidden)
+ */
+public class XmlBaseHandler
+ extends DefaultHandler
+{
+
+ /**
+ * The XML namespace.
+ */
+ public static final String
+ XML_NAMESPACE = "http://www.w3.org/XML/1998/namespace";
+
+ /**
+ * The stack of base URIs.
+ *
+ * @serial the base URI stack.
+ */
+ private Stack uris;
+
+ /**
+ * A Logger
instance to log events generated by the
+ * parsing process.
+ */
+ private Logger xmlBaseLogger;
+
+ /**
+ * The current hierarchical level.
+ */
+ private long level;
+
+ /**
+ * The last element at which a base URI was specified.
+ */
+ private String lastElement;
+
+ /**
+ * The last level at which a base URI was specified.
+ */
+ private long lastLevel;
+
+ /**
+ * Constructs a new XmlBaseHandler
, using the specified
+ * handler for log messages, and default base URI.
+ *
+ * @param handler the handler to use for log messages.
+ */
+ public XmlBaseHandler(Handler handler)
+ {
+ xmlBaseLogger = Logger.getLogger("nongnu.cashews.xml.XmlBaseHandler");
+ xmlBaseLogger.addHandler(handler);
+ xmlBaseLogger.setLevel(handler.getLevel());
+ uris = new Stack();
+ level = -1;
+ lastLevel = -1;
+ lastElement = "";
+ }
+
+ /**
+ * Sets the default base URI. This must be done before parsing begins.
+ * Any existing URIs are discarded. This method should not be used once
+ * parsing has begun. If this occurs, the behaviour of the parser is
+ * undefined (and is likely to lead to errors).
+ *
+ * @param baseURI the default base URI.
+ * @throws IllegalArgumentException if the URI is invalid.
+ */
+ public void setBaseURI(String baseURI)
+ {
+ if (!uris.empty())
+ uris = new Stack();
+ try
+ {
+ pushURI(baseURI);
+ }
+ catch (SAXException e)
+ {
+ throw new IllegalArgumentException("The default base URI couldn't " +
+ "be parsed: " + e, e);
+ }
+ }
+
+ /**
+ * Captures the start of the document and checks that the initial
+ * state is correct (i.e. we have some default base URI).
+ *
+ * @throws IllegalStateException if the default base URI is not set.
+ */
+ public void startDocument()
+ {
+ if (uris.empty())
+ {
+ xmlBaseLogger.severe("No default base URI specified.");
+ throw new IllegalStateException("No default base URI specified.");
+ }
+ }
+
+ /**
+ * Captures the start of an XML element.
+ *
+ * @param uri the namespace URI.
+ * @param localName the local name of the element inside the namespace.
+ * @param qName the local name qualified with the namespace URI. This
+ * may or may not be provided, as we don't ask for namespace
+ * prefixes.
+ * @param attributes the attributes of this element.
+ * @throws SAXException if some error occurs in parsing.
+ */
+ public void startElement(String uri, String localName,
+ String qName, Attributes attributes)
+ throws SAXException
+ {
+ xmlBaseLogger.finest("uri: " + uri + ", localName: " + localName);
+ logAttributes(attributes);
+ String value = attributes.getValue(XML_NAMESPACE, "base");
+ if (value != null)
+ {
+ pushURI(value);
+ lastElement = uri + localName;
+ lastLevel = level;
+ }
+ ++level;
+ xmlBaseLogger.finest("startElement - level: " + level);
+ }
+
+ /**
+ * Captures the end of an XML element.
+ *
+ * @param uri the namespace URI.
+ * @param localName the local name of the element inside the namespace.
+ * @param qName the local name qualified with the namespace URI. This
+ * may or may not be provided, as we don't ask for namespace
+ * prefixes.
+ * @throws SAXException if some error occurs in parsing.
+ */
+ public void endElement(String uri, String localName,
+ String qName)
+ throws SAXException
+ {
+ xmlBaseLogger.finest("uri: " + uri + ", localName: " + localName);
+ xmlBaseLogger.finest("endElement - level: " + level);
+ if (lastElement.equals(uri + localName) && lastLevel == level)
+ popURI();
+ --level;
+ }
+
+ /**
+ * Push a new base URI on to the stack and notify the logger of this
+ * event.
+ *
+ * @param baseURI the new URI to add.
+ * @throws SAXException if the URI can't be parsed.
+ */
+ private void pushURI(String baseURI)
+ throws SAXException
+ {
+ URI newURI;
+ if (baseURI == null)
+ baseURI = "";
+ if (uris.empty())
+ {
+ try
+ {
+ newURI = new URI(baseURI);
+ }
+ catch (URISyntaxException e)
+ {
+ throw new SAXException("Failed to parse URI: " + e, e);
+ }
+ }
+ else
+ {
+ URI currentBase = getBaseURI();
+ newURI = currentBase.resolve(baseURI);
+ }
+ uris.push(newURI);
+ xmlBaseLogger.fine("New base URI found: " + newURI);
+ }
+
+ /**
+ * Remove the most recent base URI from scope.
+ */
+ private void popURI()
+ {
+ URI baseURI = uris.pop();
+ xmlBaseLogger.fine("Leaving scope of base URI: " + baseURI);
+ }
+
+ /**
+ * Retrieve the most recent base URI.
+ *
+ * @return the most recent base URI.
+ */
+ protected URI getBaseURI()
+ {
+ return uris.peek();
+ }
+
+ /**
+ * Retrieve the current level in the hierarchy.
+ *
+ * @return the current hierarchical level.
+ */
+ protected long getHierarchicalLevel()
+ {
+ return level;
+ }
+
+ /**
+ * Logs a set of XML attributes received by the parser.
+ *
+ * @param attributes the attributes to log.
+ */
+ private void logAttributes(Attributes attributes)
+ {
+ int length = attributes.getLength();
+ for (int a = 0; a < length; ++a)
+ {
+ xmlBaseLogger.finest("Attribute " + a + ": " + attributes.getURI(a) +
+ attributes.getLocalName(a));
+ }
+ }
+
+}