[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Local copy of SiRPAC
Hi Sergey and Dan
Please find attached my local copy of SiRPAC.java. By running
a diff -c against your own copy you will probably find quickest
the modifications I have made w.r.t your changes.
I'm sorry but I've been too busy to follow this up with Sergey
Hopefully this puts me off the critical path..
Cheers,
Janne
--
Janne Saarela <js@pro-solutions.com> Pro Solutions Ltd.
Phone/Finland: +358 (0)40 508 4767 P.O.Box 34
Phone/France : +33 (0)6.07.45.36.67 FIN-00131 Helsinki
Fax : +358 (0)42 508 4767 Finland
/**
* SiRPAC - Simple RDF Parser & Compiler
*
* Copyright ) World Wide Web Consortium, (Massachusetts Institute of
* Technology, Institut National de Recherche en Informatique et en
* Automatique, Keio University).
*
* All Rights Reserved.
*
* Please see the full Copyright clause at
* <http://www.w3.org/Consortium/Legal/copyright-software.html>
*
* This program translates RDF descriptions into corresponding
* triple representation.
* This version uses SAX V1.0 available at <http://www.microstar.com/XML/SAX/>
*
* $Log: SiRPAC.java,v $
* Revision 1.16 1999/05/21 13:02:32 jsaarela
* Distribution release V1.14 on 21-May-99.
*
* Revision 1.21 1999/05/06 12:20:18 jsaarela
* Fixed bug related to resource="#id" management.
*
* Revision 1.20 1999/05/04 14:52:43 jsaarela
* Literal value now tells if it is well-formed XML.
* Improved entity management in Data nodes.
*
* Revision 1.19 1999/04/26 14:51:27 jsaarela
* URI resolution improved.
*
* Revision 1.18 1999/04/01 09:32:48 jsaarela
* SiRPAC distribution release V1.11 on 1-Apr-99
*
* Revision 1.17 1999/03/10 08:54:40 jsaarela
* Management of parseType="Literal" and "Resource" now equally
* tested.
*
* Revision 1.16 1999/01/13 15:00:30 jsaarela
* Finished conformance testing with PR-rdf-syntax-19990105 version
* of the RDF M&S spec.
*
*
* @author Janne Saarela <jsaarela@w3.org>
*/
package org.w3c.rdf;
import org.xml.sax.HandlerBase;
import org.xml.sax.InputSource;
import org.xml.sax.Locator;
import org.xml.sax.AttributeList;
import org.xml.sax.EntityResolver;
import org.xml.sax.DTDHandler;
import org.xml.sax.DocumentHandler;
import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXParseException;
import org.xml.sax.Parser;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.*;
import java.net.URL;
import java.util.*;
import java.io.*;
public class SiRPAC implements EntityResolver, DTDHandler, DocumentHandler,
ErrorHandler, DataSource {
final static public String REVISION = "$Id: SiRPAC.java,v 1.16 1999/05/21 13:02:32 jsaarela Exp $";
public final static String RDFMS = new String ("http://www.w3.org/1999/02/22-rdf-syntax-ns#");
public final static String RDFSCHEMA = new String ("http://www.w3.org/TR/1999/PR-rdf-schema-19990303#");
public final static String XMLSCHEMA = new String ("xml");
private Stack m_namespaceStack = new Stack ();
private Stack m_elementStack = new Stack ();
private Element m_root = null;
private Vector m_triples = new Vector ();
private String m_sErrorMsg = new String ();
private String m_sWarningMsg = new String ();
private String m_sSource = null;
/**
* The walk-through of RDF schemas requires two lists
* shared by all SiRPAC instances
* 1. s_vNStodo - list of all namespaces SiRPAC should still vist
* 2. s_vNSdone - list of all namespaces SiRPAC has gone through
*/
static private Vector s_vNStodo = new Vector ();
static private Vector s_vNSdone = new Vector ();
/**
* The following two variables may be changed on the fly
* to change the behaviour of the parser
*/
private boolean m_bCreateBags = false;
private boolean m_bFetchSchemas = false;
/**
* The following flag indicates whether the XML markup
* should be stored into a string as a literal value
* for RDF
*/
private Stack m_parseTypeStack = new Stack ();
private Stack m_parseElementStack = new Stack ();
private String m_sLiteral = new String ();
/**
* Support for multiple RDFConsumer objects that can
* receive notifications about new triples
*/
private Vector m_consumers = new Vector ();
/**
* The current source of data
*/
private RDFSource m_RDFsource = null;
/**
* Which XML parser to use
*/
private String m_sXMLParser = null;
public SiRPAC () {
// You may wish to un-comment the following line
// in case you don't have the facility to set
// sax.parser property in your execution environment
// m_sXMLParser = "com.ibm.xml.parser.SAXDriver";
}
public SiRPAC (String sXMLParser) {
m_sXMLParser = sXMLParser;
}
/**
* Methods to determine whether we are parsing
* parseType="Literal" or parseType="Resource"
*/
public boolean parseLiteral() {
if (!m_elementStack.empty()) {
for (int x = m_elementStack.size()-1; x >= 0; x--) {
Element e = (Element)m_elementStack.elementAt(x);
String sParseType = e.getAttribute(RDFMS+"parseType");
if (sParseType != null) {
if (!sParseType.equals ("Resource")) {
return true;
}
}
}
}
return false;
}
public boolean parseResource() {
if (!m_elementStack.empty()) {
for (int x = m_elementStack.size()-1; x >= 0; x--) {
Element e = (Element)m_elementStack.elementAt(x);
String sParseType = e.getAttribute(RDFMS+"parseType");
if (sParseType != null) {
if (sParseType.equals ("Resource"))
return true;
}
}
}
return false;
}
/**
* createBags method allows one to determine whether SiRPAC
* produces Bag instances for each Description block.
* The default setting is to generate them.
*/
public void createBags (boolean b) {
m_bCreateBags = b;
}
/**
* Set whether parser recursively fetches and parses
* every RDF schema it finds in the namespace declarations
*/
public void fetchSchemas (boolean b) {
m_bFetchSchemas = b;
}
/**
* setSource methods saves the name of the source document for
* later inspection if needed
*/
public void setSource (String sSource) {
m_sSource = sSource;
}
public String source () {
return m_sSource;
}
/**
* Return all non-RDF namespace URIs recognized by the parser
*/
public Enumeration listNamespaces () {
return SiRPAC.s_vNSdone.elements();
}
/**
* Return the full namespace URI for a given prefix <i>sPrefix</i>.
* The default namespace is identified with <i>xmlns</i> prefix.
* The namespace of <i>xmlns</i> attribute is an empty string.
*/
public String namespace (String sPrefix) {
if (sPrefix == null) {
sPrefix = new String ("xmlns");
}
for (int x = m_namespaceStack.size()-1; x >=0; x--) {
Hashtable ht = (Hashtable)m_namespaceStack.elementAt (x);
String sURI = (String)ht.get (sPrefix);
if (sURI != null)
return sURI;
}
/**
* Give error only if
* 1. the prefix is not from the reserved xml namespace
* 2. the prefix is not xmlns which is to look for the default
* namespace
*/
if (sPrefix.equals (XMLSCHEMA)) {
return XMLSCHEMA;
} else if (sPrefix.equals ("xmlns")) {
return "";
} else {
addError ("Unresolved namespace prefix "+sPrefix);
}
return "";
}
/**
* One can register multiple RDFConsumer objects which will
* receive notifications about new triples
*/
public void register (RDFConsumer c) {
m_consumers.addElement (c);
}
/**
* Remove an RDFConsumer object from SiRPAC
*/
public void unregister (RDFConsumer c) {
m_consumers.removeElement(c);
}
/**
* Notify all registered consumers that were
* are about to start parsing
*/
public void startConsumers () {
for (int x = 0; x < m_consumers.size(); x++) {
RDFConsumer consumer = (RDFConsumer)m_consumers.elementAt(x);
consumer.start (this);
}
}
/**
* Notify all registered consumers that were
* are at the end of the parsing process
*/
public void endConsumers () {
for (int x = 0; x < m_consumers.size(); x++) {
RDFConsumer consumer = (RDFConsumer)m_consumers.elementAt(x);
consumer.end (this);
}
}
public void setRDFSource (RDFSource source) {
m_RDFsource = source;
}
public RDFSource getRDFSource () {
return m_RDFsource;
}
public void fetchRDF () throws Exception {
startConsumers ();
try {
// Create a new parser.
Parser p = null;
if (m_sXMLParser == null)
p = ParserFactory.makeParser();
else
p = ParserFactory.makeParser(m_sXMLParser);
// Register the handlers
p.setEntityResolver(this);
p.setDTDHandler (this);
p.setDocumentHandler(this);
p.setErrorHandler (this);
StringReader sr = new StringReader (m_RDFsource.content());
InputSource source = new InputSource (sr);
source.setSystemId(m_RDFsource.url());
setSource (m_RDFsource.url());
p.parse (source);
resolve ();
// createBags (true);
processXML (root());
// root().linearize (0, System.out);
} catch (SAXException e) {
addError ("\n<br>Internal error "+e.getMessage());
} catch (Exception e) {
addError ("\n<br>Internal error "+e);
}
endConsumers ();
}
public InputSource resolveEntity (String publicId, String systemId) {
return null;
}
public void notationDecl (String name, String publicId, String systemId) {
}
/**
* Display unparsed entity declarations as they are reported.
*
* @see org.xml.sax.DTDHandler#unparsedEntityDecl
*/
public void unparsedEntityDecl (String name,
String publicId,
String systemId,
String notationName) {
}
public void setDocumentLocator (Locator locator) {
}
public void startDocument () {
m_sErrorMsg = "";
}
public void endDocument () throws SAXException {
}
public void doctype (String name, String publicID, String systemID) {
}
/**
* Called for each new element.
* Build up the document tree using an element stack
*
* @exception SAXException Passed on since we don't handle it.
*/
public void startElement (String name, AttributeList al) throws SAXException {
Hashtable namespaces = new Hashtable ();
/**
* The following loop tries to identify special xmlns prefix
* attributes and update the namespace stack accordingly.
* While doing all this, it builds another AttributeList instance
* which will hold the expanded names of the attributes
* (I think this approach is only useful for RDF which uses
* attributes as an abbreviated syntax for element names)
*/
AttributeListImpl newAL = new AttributeListImpl ();
int iLength = al.getLength ();
if (iLength == 0) {
// ohwell, no attributes
} else for (int x = 0; x < iLength; x++) {
String aName = al.getName (x);
if (aName.equals ("xmlns")) {
String aValue = al.getValue (aName);
if (aValue != null && aValue.length() == 0 && source() != null)
aValue = source();
namespaces.put (aName, aValue);
// save all non-RDF schema addresses
if (!hasString (SiRPAC.s_vNStodo, aValue) &&
!hasString (SiRPAC.s_vNSdone, aValue) &&
!aValue.startsWith (RDFMS) &&
!aValue.startsWith (RDFSCHEMA)) {
SiRPAC.s_vNStodo.addElement (aValue);
}
} else if (aName.startsWith ("xmlns:")) {
String aValue = al.getValue (aName);
if (aValue != null && aValue.length() == 0 && source() != null)
aValue = source();
aName = aName.substring (6);
namespaces.put (aName, aValue);
// save all non-RDF schema addresses
if (!hasString (SiRPAC.s_vNStodo, aValue) &&
!hasString (SiRPAC.s_vNSdone, aValue) &&
!aValue.startsWith (RDFMS) &&
!aValue.startsWith (RDFSCHEMA)) {
SiRPAC.s_vNStodo.addElement (aValue);
}
}
}
/**
* Place new namespace declarations into the stack
* (Yes, I could optimize this a bit, not it wastes space
* if there are no xmlns definitions)
*/
m_namespaceStack.push (namespaces);
/**
* Figure out the prefix part if it exists and
* determine the namespace of the element accordingly
*/
String sNamespace = null;
String sElementName = null;
Element newElement = null;
int i = name.indexOf (':');
String sPrefix2 = null;
if (i > 0) {
sPrefix2 = name.substring (0, i);
sNamespace = namespace (sPrefix2);
sElementName = name.substring (i+1);
} else {
sNamespace = namespace ("xmlns");
sElementName = name;
}
/**
* Finally look for attributes other than the special xmlns,
* expand them, and place to the new AttributeListImpl
*/
for (int x = 0; x < iLength; x++) {
String sAttributeNamespace = null;
String aName = al.getName (x);
if (!aName.startsWith ("xmlns")) {
String aValue = al.getValue (aName);
String aType = al.getType (aName);
int iIndex = aName.indexOf (':');
String sPrefix = null;
if (iIndex > 0) {
sPrefix = aName.substring (0, iIndex);
sAttributeNamespace = namespace (sPrefix);
aName = aName.substring (iIndex+1);
} else {
if (sNamespace == null)
sAttributeNamespace = namespace ("xmlns");
else
sAttributeNamespace = sNamespace;
}
if (parseLiteral()) {
if (sPrefix == null) {
sPrefix = "gen" + x; // x is a handy counter
}
newAL.addAttribute (sPrefix + ":" + aName,
aType,
aValue);
newAL.addAttribute ("xmlns:"+sPrefix,
aType,
sAttributeNamespace);
} else {
newAL.addAttribute (sAttributeNamespace+aName,
aType,
aValue);
}
/**
* This call will try to see if the user is using
* RDF look-alike elements from another namespace
*
* Note: you can remove the call if you wish
*/
likeRDF (sAttributeNamespace, aName);
}
}
/**
* If we have parseType="Literal" set earlier, this element
* needs some additional attributes to make it stand-alone
* piece of XML
*/
if (parseLiteral()) {
if (sPrefix2 == null) {
// default namespace coming in
if (sNamespace != null) {
newAL.addAttribute ("xmlns:gen",
"CDATA",
sNamespace);
}
newElement = new Element ("gen:" + sElementName,
newAL);
newElement.prefix ("gen");
} else {
String sAttributeNamespace = namespace (sPrefix2);
if (sAttributeNamespace != null)
newAL.addAttribute ("xmlns:"+sPrefix2,
"CDATA",
sAttributeNamespace);
newElement = new Element (sPrefix2 + ":" + sElementName,
newAL);
}
} else {
newElement = new Element (sNamespace + sElementName,
newAL);
likeRDF (sNamespace, sElementName);
}
checkAttributes (newElement);
/**
* Check parseType
*/
String sLiteralValue = newElement.getAttribute(RDFMS+"parseType");
if (sLiteralValue != null && !sLiteralValue.equals ("Resource")) {
/**
* This is the management of the element where
* parseType="Literal" appears
*
* You should notice RDF V1.0 conforming implementations
* must treat other values than Literal and Resource as
* Literal. This is why the condition is !equals("Resource")
*/
m_parseTypeStack.push (sLiteralValue);
if (!m_elementStack.empty()) {
Element e = (Element)m_elementStack.peek ();
e.addChild (newElement);
}
m_elementStack.push (newElement);
m_parseElementStack.push (newElement);
m_sLiteral = "";
return;
}
if (parseLiteral()) {
/**
* This is the management of any element nested within
* a parseType="Literal" declaration
*/
makeMarkupST (newElement);
m_elementStack.push (newElement);
return;
}
/**
* Update the containment hierarchy
* with the stack.
*/
if (!m_elementStack.empty()) {
Element e = (Element)m_elementStack.peek ();
e.addChild (newElement);
}
/**
* Place the new element into the stack
*/
m_elementStack.push (newElement);
if (sLiteralValue != null && sLiteralValue.equals ("Resource")) {
m_parseTypeStack.push (sLiteralValue);
m_parseElementStack.push (newElement);
m_sLiteral = "";
/**
* Since parseType="Resource" implies the following
* production must match Description, let's create
* an additional Description node here in the document tree.
*/
Element desc = new Element (RDFMS+"Description", new AttributeListImpl());
if (!m_elementStack.empty()) {
Element e = (Element)m_elementStack.peek ();
e.addChild (desc);
}
m_elementStack.push (desc);
}
}
/**
* Helper function to determine if a String is already within a
* Vector
*
* @param v Vector to be inspected
* @param s String to be searched
*/
private boolean hasString (Vector v, String s) {
for (int x = 0; x < v.size(); x++) {
String s2 = (String)v.elementAt(x);
if (s.equals (s2)) {
return true;
}
}
return false;
}
/**
* For each end of an element scope step back in the
* element and namespace stack
*
* @exception SAXException Passed on since we don't handle it.
*/
public void endElement (String name) throws SAXException {
boolean bParseLiteral = parseLiteral();
m_root = (Element)m_elementStack.pop ();
m_namespaceStack.pop ();
if (bParseLiteral) {
Element pe = (Element)m_parseElementStack.peek ();
if (pe != m_root) {
makeMarkupET (m_root.prefix()+name);
} else {
m_root.addChild (new Data (m_sLiteral, true));
m_sLiteral = "";
m_parseElementStack.pop();
m_parseTypeStack.pop ();
}
} else if (parseResource()) {
/**
* If we are doing parseType="Resource"
* we need to explore whether the next element in
* the stack is the closing element in which case
* we remove it as well (remember, there's an
* extra Description element to be removed)
*/
if (!m_elementStack.empty()) {
Element pe = (Element)m_parseElementStack.peek ();
if (m_elementStack.peek() == pe) {
Element e = (Element)m_elementStack.pop ();
m_parseElementStack.pop();
m_parseTypeStack.pop ();
}
}
}
}
/**
* Return the root element pointer. This requires the parsing
* has been already done.
*/
public Element root () {
return m_root;
}
public void characters (char ch[], int start, int length)
throws SAXException {
/**
* Place all characters as Data instance to the containment
* hierarchy with the help of the stack.
*/
Element e = (Element)m_elementStack.peek ();
String s = new String (ch, start, length);
if (parseLiteral()) {
makeMarkupChar (s);
return;
}
/**
* Determine whether the previous event was for
* characters. If so, update the Data node contents.
* A&B would otherwise result in three
* separate Data nodes in the parse tree
*/
boolean bHasData = false;
Data dataNode = null;
Enumeration enum = e.children();
while (enum.hasMoreElements()) {
Element e2 = (Element)enum.nextElement();
if (e2 instanceof Data) {
bHasData = true;
dataNode = (Data)e2;
break;
}
}
/**
* Warning: this is not correct procedure according to XML spec.
* All whitespace matters!
*/
String sTrimmed = s.trim();
if (sTrimmed.length() > 0) {
if (!bHasData) {
e.addChild (new Data (s));
} else {
dataNode.set (dataNode.data() + s);
}
}
}
public void ignorableWhitespace (char ch[], int start, int length) {
}
public void processingInstruction (String target, String data) {
}
/**
* Report all warnings, and continue parsing.
*
* @see org.xml.sax.ErrorHandler#warning
*/
public void warning (SAXParseException exception)
{
m_sWarningMsg += exception.getMessage() +
" (" +
exception.getSystemId() +
"line <a href=\"#" +
exception.getLineNumber() +
"\">" +
exception.getLineNumber() +
"</a>, column " +
exception.getColumnNumber() +
")";
}
/**
* Report all recoverable errors, and try to continue parsing.
*
* @see org.xml.sax.ErrorHandler#error
*/
public void error (SAXParseException exception)
{
m_sErrorMsg += "Recoverable Error: " +
exception.getMessage() +
" (" +
// exception.getSystemId() +
"line <a href=\"#" +
exception.getLineNumber() +
"\">" +
exception.getLineNumber() +
"</a>, column " +
exception.getColumnNumber() +
")";
}
/**
* Report all fatal errors, and try to continue parsing.
*
* <p>Note: results are no longer reliable once a fatal error has
* been reported.</p>
*
* @see org.xml.sax.ErrorHandler#fatalError
*/
public void fatalError (SAXParseException exception)
{
m_sErrorMsg = "Fatal Error: " +
exception.getMessage() +
" (" +
// exception.getSystemId() +
"line <a href=\"#" +
exception.getLineNumber() +
"\">" +
exception.getLineNumber() +
"</a>, column " +
exception.getColumnNumber() +
")";
}
/**
* Generate an error message as a string
*/
public void addError (String sMsg) {
m_sErrorMsg += sMsg + "\n";
}
public String errors () {
return m_sErrorMsg;
}
/**
* Generate a warning message as a string
*/
public void addWarning (String sMsg) {
m_sWarningMsg += sMsg + "\n";
}
public String warnings () {
return m_sWarningMsg;
}
public static Parser createParser (String className) {
Parser parser = null;
try {
// Get the named class.
Class c = Class.forName(className);
// Instantiate the parser.
parser = (Parser)(c.newInstance());
} catch (ClassNotFoundException e) {
System.err.println("SAX parser class " + className +
"cannot be loaded.");
System.exit(1);
} catch (IllegalAccessException e) {
System.err.println("SAX parser class " + className +
" does not have a zero-argument constructor.");
System.exit(1);
} catch (InstantiationException e) {
System.err.println("SAX parser class " + className +
" cannot be instantiated.");
System.exit(1);
}
// Check the the parser object
// actually implements the Parser interface.
if (!(parser instanceof org.xml.sax.Parser)) {
System.err.println("Class " + className +
" does not implement org.xml.sax.Parser.");
System.exit(1);
}
return parser;
}
/**
* If a URL is relative, make it absolute against the current directory.
*
* @exception java.net.MalformedURLException
*/
private static String makeAbsoluteURL (String url)
throws java.net.MalformedURLException {
URL baseURL;
String currentDirectory = System.getProperty("user.dir");
String fileSep = System.getProperty("file.separator");
String file = currentDirectory.replace(fileSep.charAt(0), '/') + '/';
if (file.charAt(0) != '/') {
file = "/" + file;
}
baseURL = new URL("file", null, file);
return new URL(baseURL, url).toString();
}
/**
* Escape special characters for display.
*/
private static String escapeCharacters(char ch[], int start, int length) {
StringBuffer out = new StringBuffer();
for (int i = start; i < start+length; i++) {
if (ch[i] >= 0x20 && ch[i] < 0x7f) {
out.append(ch[i]);
} else {
out.append("&#" + (int)ch[i] + ';');
}
}
return out.toString();
}
/**
* Given an XML document (well-formed HTML, for example),
* look for a suitable element to start parsing from
*
* @exception SAXException Passed on since we don't handle it.
*/
public void processXML (Element ele) throws SAXException {
if (isRDF(ele)) {
if (isRDFroot (ele)) {
processRDF(ele);
} else if (isDescription (ele)) {
processDescription (ele, false, m_bCreateBags, m_bCreateBags);
}
} else {
Enumeration e = ele.children();
while (e.hasMoreElements()) {
Element child = (Element)e.nextElement();
processXML (child);
}
}
/**
* Call fetchSchema for all namespaces met during parsing
*/
if (m_bFetchSchemas) {
while (SiRPAC.s_vNStodo.size() > 0) {
String sURI = (String)SiRPAC.s_vNStodo.elementAt(0);
SiRPAC.s_vNStodo.removeElementAt(0);
SiRPAC.s_vNSdone.addElement (sURI);
fetchSchema (sURI);
}
}
}
/**
* fetchSchema fetches an RDF schema from the given <i>sURI</i>
*
*/
public void fetchSchema (String sURI) {
setSource (sURI);
try {
URL url = new URL (sURI);
String sContentType = url.openConnection().getContentType();
// DEBUG -> remove false later on
if (false &&
!sContentType.startsWith ("text/xml") &&
!sContentType.startsWith ("text/html")) {
addError ("The RDF schema at "+sURI+" is of wrong content type '"+sContentType+"'\n(should have been 'text/xml' or 'text/html')");
} else {
InputStream is = url.openStream ();
InputSource source = new InputSource (is);
// Create a new parser.
Parser p = null;
if (m_sXMLParser == null)
p = ParserFactory.makeParser();
else
p = ParserFactory.makeParser(m_sXMLParser);
// Register the handlers
p.setEntityResolver(this);
p.setDTDHandler (this);
p.setDocumentHandler(this);
p.setErrorHandler (this);
p.parse(source);
resolve ();
processXML (root());
}
} catch (Exception ex) {
addError ("Could not load RDF schema from "+sURI+". Problem: "+ex);
}
}
/**
* Start processing an RDF/XML document instance from the
* root element <i>rdf</i>.
*
* @exception SAXException Passed on since we don't handle it.
*/
public void processRDF (Element rdf) throws SAXException {
Enumeration e = rdf.children();
if (!e.hasMoreElements()) {
addError ("Empty RDF element");
return;
}
while (e.hasMoreElements()) {
Element ele = (Element)e.nextElement();
if (isDescription (ele)) {
processDescription (ele, false, m_bCreateBags, m_bCreateBags);
} else if (isContainer (ele)) {
processContainer (ele);
} else if (isTypedPredicate (ele)) {
processTypedNode (ele);
}
}
}
/**
* Manage the typedNode production in the RDF grammar.
*
* @exception SAXException Passed on since we don't handle it.
*/
public String processTypedNode (Element typedNode) throws SAXException {
String sID = typedNode.ID();
String sBagID = typedNode.bagID();
String sAbout = typedNode.about();
String sAboutEach = typedNode.aboutEach();
String sAboutEachPrefix = typedNode.aboutEachPrefix();
if (typedNode.resource() != null) {
addError ("'resource' attribute not allowed for a typedNode "+typedNode.name()+" - see <a href=\"http://www.w3.org/TR/REC-rdf-syntax/#typedNode\">[6.13]</a>");
}
/**
* We are going to manage this typedNode using the processDescription
* routine later on. Before that, place all properties encoded as
* attributes to separate child nodes.
*/
Enumeration e = typedNode.attributes ();
while (e.hasMoreElements()) {
String sAttribute = (String)e.nextElement();
String sValue = typedNode.getAttribute (sAttribute);
sValue = sValue.trim ();
if (!sAttribute.startsWith (RDFMS) &&
!sAttribute.startsWith (XMLSCHEMA)) {
if (sValue.length() > 0) {
Element newPredicate = new Element (sAttribute,
new AttributeListImpl ());
newPredicate.addAttribute (RDFMS + "ID", (sAbout != null ? sAbout : sID));
newPredicate.addAttribute (RDFMS + "bagID", sBagID);
Data newData = new Data (sValue);
newPredicate.addChild (newData);
typedNode.addChild (newPredicate);
typedNode.removeAttribute (sAttribute);
}
}
}
String sObject = new String ();
if (sAbout != null)
sObject = sAbout;
else if (sID != null)
sObject = sID;
else
sObject = newReificationID(source());
typedNode.ID (sObject, source());
// special case: should the typedNode have aboutEach attribute,
// the type predicate should distribute to pointed
// collection also -> create a child node to the typedNode
Enumeration eTargets = typedNode.targets ();
if (sAboutEach != null &&
eTargets.hasMoreElements()) {
Element newPredicate = new Element (RDFMS + "type",
new AttributeListImpl());
newPredicate.resource (typedNode.name());
typedNode.addChild (newPredicate);
} else {
addTriple (new Property(RDFMS + "type"),
new Resource(sObject),
new Resource(typedNode.name()));
}
String sDesc = processDescription (typedNode, false, false, false);
return sObject;
}
/**
* processDescription manages Description elements
*
* @param description The Description element itself
* @param inPredicate Is this is a nested description
* @param reificate Do we need to reificate
* @param createBag Do we create a bag container
*
* @return An ID for the description
*
* @exception SAXException Passed on since we don't handle it.
*/
public String processDescription (Element description,
boolean inPredicate,
boolean reificate,
boolean createBag) throws SAXException {
/**
* Return immediately if the description has already been managed
*/
if (description.done())
return description.ID();
int iChildCount = 1;
boolean bOnce = true;
/**
* Determine first all relevant values
*/
String sID = description.ID();
String sBagid = description.bagID();
String sAbout = description.about();
String sAboutEach = description.aboutEach();
String sAboutEachPrefix = description.aboutEachPrefix();
Element target = description.target();
boolean hasTarget = description.targets().hasMoreElements();
boolean targetIsContainer = false;
String sTargetAbout = null;
String sTargetBagid = null;
String sTargetID = null;
/**
* Determine what the target of the Description reference is
*/
if (hasTarget) {
sTargetAbout = target.about();
sTargetID = target.ID();
sTargetBagid = target.bagID();
/**
* Target is collection if
* 1. it is identified with bagID attribute
* 2. it is identified with ID attribute and is a collection
*/
if (sTargetBagid != null && sAbout != null) {
targetIsContainer = (sAbout.substring(1).equals (sTargetBagid));
} else {
if (sTargetID != null &&
sAbout != null &&
sAbout.substring(1).equals (sTargetID) &&
isContainer (target)) {
targetIsContainer = true;
}
}
}
/**
* Check if there are properties encoded using the abbreviated
* syntax
*/
expandAttributes (description, description);
/**
* Manage the aboutEach attribute here
*/
if (sAboutEach != null && hasTarget) {
if (isContainer(target)) {
Enumeration e = target.children ();
while (e.hasMoreElements()) {
Element ele = (Element)e.nextElement ();
if (isListItem (ele)) {
String sResource = ele.resource();
/**
* Manage <li resource="..." /> case
*/
if (sResource != null) {
Element newDescription = null;
newDescription = new Element (RDFMS + "Description",
new AttributeListImpl ());
newDescription.about (sResource);
Enumeration e2 = description.children();
while (e2.hasMoreElements()) {
Element ele2 = (Element)e2.nextElement ();
if (newDescription != null) {
newDescription.addChild (ele2);
}
}
if (newDescription != null)
processDescription (newDescription,
false, false, false);
} else {
/**
* Otherwise we have a structured value inside <li>
*/
// loop through the children of <li>
// (can be only one)
Enumeration e2 = ele.children ();
while (e2.hasMoreElements()) {
Element ele2 = (Element)e2.nextElement ();
// loop through the items in the
// description with aboutEach
// and add them to the target
Element newNode = new Element (RDFMS + "Description",
new AttributeListImpl());
Enumeration e3 = description.children();
while (e3.hasMoreElements()) {
Element ele3 = (Element)e3.nextElement ();
newNode.addChild (ele3);
}
newNode.addTarget (ele2);
processDescription (newNode,
true, false, false);
}
}
} else if (isTypedPredicate (ele)) {
Element newNode = new Element (RDFMS + "Description",
new AttributeListImpl());
Enumeration e2 = description.children();
while (e2.hasMoreElements()) {
Element ele2 = (Element)e2.nextElement ();
newNode.addChild (ele2);
}
newNode.addTarget (ele);
processDescription (newNode,
true, false, false);
}
}
} else if (isDescription(target)) {
processDescription (target,
false, reificate, createBag);
Enumeration e = target.children ();
while (e.hasMoreElements()) {
Element ele = (Element)e.nextElement ();
Element newNode = new Element (RDFMS + "Description",
new AttributeListImpl());
Enumeration e2 = description.children();
while (e2.hasMoreElements()) {
Element ele2 = (Element)e2.nextElement ();
newNode.addChild (ele2);
}
newNode.addTarget (ele);
processDescription (newNode,
true, false, false);
}
}
return null;
}
/**
* Manage the aboutEachPrefix attribute
*/
if (sAboutEachPrefix != null) {
if (hasTarget) {
Enumeration e = description.targets();
while (e.hasMoreElements()) {
target = (Element)e.nextElement ();
sTargetAbout = target.about();
Element newDescription = new Element (RDFMS + "Description",
new AttributeListImpl ());
newDescription.about (sTargetAbout);
Enumeration e2 = description.children();
while (e2.hasMoreElements()) {
Element ele2 = (Element)e2.nextElement ();
newDescription.addChild (ele2);
}
processDescription (newDescription,
false, false, false);
}
}
return null;
}
/**
* Enumerate through the children
*/
Enumeration e = description.children();
while (e.hasMoreElements()) {
Element n = (Element)e.nextElement();
if (isDescription (n)) {
addError ("Cannot nest a Description inside another Description");
} else if (isContainer (n)) {
addError ("Cannot nest a container (Bag/Alt/Seq) inside a Description");
} else if (isTypedPredicate(n)) {
String sChildID = null;
if (hasTarget && targetIsContainer) {
sChildID = processPredicate (n, description,
(target.bagID() != null ? target.bagID() : target.ID()),
false);
description.ID (sChildID, source());
createBag = false;
} else if (hasTarget) {
sChildID = processPredicate (n, description,
(target.bagID() != null ? target.bagID() : target.ID()),
reificate);
description.ID (sChildID, source());
} else if (!hasTarget && !inPredicate) {
// if (description.ID() == null)
//description.ID (newReificationID(source()));
if (sAbout == null)
if (sID != null)
sAbout = sID;
else
sAbout = description.ID();
sChildID = processPredicate (n, description,
sAbout,
( sBagid != null ? true : reificate));
//description.ID (sChildID, source());
} else if (!hasTarget && inPredicate) {
if (sAbout == null) {
if (sID != null) {
description.ID (sID, source());
sAbout = sID;
} else {
if (description.ID() == null)
description.ID (newReificationID(source()));
sAbout = description.ID();
}
} else {
description.ID (sAbout);
}
sChildID = processPredicate (n, description,
sAbout,
false);
}
/**
* Each Description block creates also a Bag node which
* has links to all properties within the block IF
* the m_bCreateBags variable is true
*/
if (sBagid != null || (m_bCreateBags && createBag)) {
String sNamespace = RDFMS;
// do only once and only if there is a child
if (bOnce && sChildID != null) {
bOnce = false;
if (description.bagID() == null)
description.bagID (newReificationID(source()));
if (description.ID() == null)
description.ID (description.bagID());
addTriple (new Property(sNamespace + "type"),
new Resource(description.bagID()),
new Resource(sNamespace + "Bag"));
}
if (sChildID != null) {
addTriple (new Property(sNamespace + "_" + iChildCount),
new Resource(description.bagID()),
new Resource(sChildID));
iChildCount++;
}
}
}
}
description.done (true);
return description.ID();
}
/**
* processPredicate handles all elements not defined as special
* RDF elements.
*
* @param predicate The predicate element itself
* @param description Context for the predicate
* @param sTarget The target resource
* @param reificate Should this predicate be reificated
*
* @return the new ID which can be used to identify the predicate
*
* @exception SAXException Passed on since we don't handle it.
*/
private String processPredicate (Element predicate,
Element description,
String sTarget,
boolean reificate) throws SAXException {
String sStatementID = predicate.ID();
String sBagID = predicate.bagID();
String sResource = predicate.resource();
/**
* If a predicate has other attributes than rdf:ID, rdf:bagID,
* or xmlns... -> generate new triples according to the spec.
* (See end of Section 6)
*/
// this new element may not be needed
Element d = new Element (RDFMS + "Description",
new AttributeListImpl());
if (expandAttributes (d, predicate)) {
// error checking
// determine the 'about' part for the new statements
if (sStatementID != null) {
d.about (sStatementID);
// make rdf:ID the value of the predicate
predicate.addChild (new Data (sStatementID));
} else if (sResource != null) {
d.about (sResource);
} else {
sStatementID = newReificationID(source());
d.ID (sStatementID);
}
if (sBagID != null) {
d.addAttribute (RDFMS + "bagID", sBagID);
d.bagID (sBagID);
}
processDescription (d, true, false, m_bCreateBags);
predicate.addChild (d);
}
/**
* Tricky part: if the resource attribute is present for a predicate
* AND there are no children, the value of the predicate is either
* 1. the URI in the resource attribute OR
* 2. the node ID of the resolved #resource attribute
*/
if (sResource != null && !predicate.children().hasMoreElements()) {
if (predicate.target() == null) {
if (reificate) {
sStatementID = reificate (new Property(predicate.name()),
new Resource(sTarget),
new Resource(sResource),
predicate.ID());
predicate.ID (sStatementID, source());
} else {
addTriple (new Property(predicate.name()),
new Resource(sTarget),
new Resource(sResource));
}
} else {
if (reificate) {
sStatementID = reificate (new Property(predicate.name()),
new Resource(sTarget),
new Resource(predicate.target().ID()),
predicate.ID());
predicate.ID (sStatementID, source());
} else {
addTriple (new Property(predicate.name()),
new Resource(sTarget),
new Resource(predicate.target().ID()));
}
}
return predicate.ID();
}
/**
* Does this predicate make a reference somewhere using the
* <i>sResource</i> attribute
*/
if (sResource != null && predicate.target() != null) {
sStatementID = processDescription (predicate.target(),
true, false, false);
if (reificate) {
sStatementID = reificate (new Property(predicate.name()),
new Resource(sTarget),
new Resource(sStatementID),
predicate.ID());
predicate.ID (sStatementID, source());
} else {
addTriple (new Property(predicate.name()),
new Resource(sTarget),
new Resource(sStatementID));
}
return sStatementID;
}
/**
* Before looping through the children, let's check
* if there are any. If not, the value of the predicate is
* an anonymous node
*/
Enumeration e2 = predicate.children();
if (!(e2.hasMoreElements())) {
if (reificate) {
sStatementID = reificate (new Property(predicate.name()),
new Resource(sTarget),
new Resource(newReificationID(source())),
predicate.ID());
} else {
addTriple (new Property(predicate.name()),
new Resource(sTarget),
new Resource(newReificationID(source())));
}
}
boolean bUsedTypedNodeProduction = false;
while (e2.hasMoreElements()) {
Element n2 = (Element)e2.nextElement();
if (isDescription (n2)) {
Element d2 = n2;
sStatementID = processDescription (d2, true, false, false);
d2.ID (sStatementID, source());
if (reificate) {
sStatementID = reificate (new Property(predicate.name()),
new Resource(sTarget),
new Resource(sStatementID),
predicate.ID());
} else {
addTriple (new Property(predicate.name()),
new Resource(sTarget),
new Resource(sStatementID));
}
} else if (n2 instanceof Data) {
/**
* We've got real data
*/
String sValue = ((Data)n2).data();
boolean isXML = ((Data)n2).isXML();
/**
* Only if the content is not empty PCDATA (whitespace that is),
* print the triple
*/
sValue = sValue.trim();
if (sValue.length() > 0) {
if (reificate) {
sStatementID = reificate (new Property(predicate.name()),
new Resource(sTarget),
new Literal(sValue, isXML),
predicate.ID());
predicate.ID (sStatementID, source());
} else {
addTriple (new Property(predicate.name()),
new Resource(sTarget),
new Literal(sValue, isXML));
}
}
} else if (isContainer (n2)) {
String sCollectionID = processContainer (n2);
sStatementID = sCollectionID;
/**
* Attach the collection to the current predicate
*/
if (description.target() != null) {
if (reificate) {
sStatementID = reificate (new Property(predicate.name()),
new Resource(description.target().about()),
new Resource(sCollectionID),
predicate.ID());
predicate.ID (sStatementID, source());
} else {
addTriple (new Property(predicate.name()),
new Resource(description.target().about()),
new Resource(sCollectionID));
}
} else {
if (reificate) {
sStatementID = reificate (new Property(predicate.name()),
new Resource(sTarget),
new Resource(sCollectionID),
predicate.ID());
predicate.ID (sStatementID, source());
} else {
addTriple (new Property(predicate.name()),
new Resource(sTarget),
new Resource(sCollectionID));
}
}
} else if (isTypedPredicate (n2)) {
if (bUsedTypedNodeProduction) {
addError ("Only one typedNode allowed inside a predicate (Extra typedNode is "+n2.name()+") - see <a href=\"http://www.w3.org/TR/REC-rdf-syntax/#propertyElt\">[6.12]</a>");
} else {
bUsedTypedNodeProduction = true;
}
sStatementID = processTypedNode (n2);
addTriple (new Property(predicate.name()),
new Resource(sTarget),
new Resource(sStatementID));
}
}
return sStatementID;
}
private String processContainer (Element n) throws SAXException {
String sID = n.ID();
if (sID == null)
sID = newReificationID(source());
/**
* Do the instantiation only once
*/
if (!n.done()) {
String sNamespace = RDFMS;
if (isSequence (n)) {
addTriple (new Property(sNamespace+"type"),
new Resource(sID),
new Resource(sNamespace+"Seq"));
} else if (isAlternative (n)) {
addTriple (new Property(sNamespace+"type"),
new Resource(sID),
new Resource(sNamespace+"Alt"));
} else if (isBag (n)) {
addTriple (new Property(sNamespace+"type"),
new Resource(sID),
new Resource(sNamespace+"Bag"));
}
n.done (true);
}
expandAttributes (n, n);
Enumeration e = ((Element)n).children();
if (!e.hasMoreElements() &&
isAlternative (n)) {
addError ("An RDF:Alt container must have at least one nested listitem");
}
int iCounter = 1;
while (e.hasMoreElements()) {
Element n2 = (Element)e.nextElement();
if (isListItem (n2)) {
processListItem (sID, n2, iCounter);
iCounter++;
} else {
addError ("Cannot nest "+n2.name()+" inside a container (Bag/Alt/Seq)");
}
}
return sID;
}
private void processListItem (String sID, Element listitem, int iCounter)
throws SAXException {
/**
* Two different cases for
* 1. LI element without content (resource available)
* 2. LI element with content (resource unavailable)
*/
String sResource = listitem.resource();
if (listitem.target() != null) {
sResource = listitem.target().ID();
}
if (sResource != null) {
addTriple (new Property(RDFMS+"_"+iCounter),
new Resource(sID),
new Resource(sResource));
// validity checking
if (listitem.children().hasMoreElements()) {
addError ("Listitem with 'resource' attribute cannot have child nodes - see <a href=\"http://www.w3.org/TR/REC-rdf-syntax/#referencedItem\">[6.29]</a>");
}
listitem.ID (sResource, source());
} else {
Enumeration e = listitem.children();
while (e.hasMoreElements()) {
Element n = (Element)e.nextElement();
if (n instanceof Data) {
addTriple (new Property(RDFMS+"_"+iCounter),
new Resource(sID),
new Literal(((Data)n).data()));
} else if (isDescription (n)) {
String sNodeID = processDescription (n, false, true, false);
addTriple (new Property(RDFMS+"_"+iCounter),
new Resource(sID),
new Resource(sNodeID));
listitem.ID (sNodeID, source());
} else if (isListItem (n)) {
addError ("Cannot nest a listitem inside another listitem");
} else if (isContainer (n)) {
processContainer (n);
addTriple (new Property(RDFMS+"_"+iCounter),
new Resource(sID),
new Resource(n.ID()));
} else if (isTypedPredicate (n)) {
String sNodeID = processTypedNode (n); //
addTriple (new Property(RDFMS+"_"+iCounter),
new Resource(sID),
new Resource(sNodeID));
}
}
}
}
/**
* checkAttributes goes through the attributes of element <i>e</i>
* to see
* 1. if there are symbolic references to other nodes in the data model.
* in which case they must be stored for later resolving with
* <i>resolveLater</i> method.
* 2. if there is an identity attribute, it is registered using
* <i>registerResource</i> or <i>registerID</i> method.
*
* @see resolveLater
* @see registerResource
* @see registerID
*/
private void checkAttributes (Element e) {
String sResource = e.getAttribute (RDFMS, "resource");
if (sResource != null) {
if (sResource.startsWith("#")) {
resolveLater (e);
e.resource (sResource);
} else {
e.resource (sResource, source());
}
}
String sAboutEach = e.getAttribute (RDFMS, "aboutEach");
if (sAboutEach != null &&
sAboutEach.startsWith("#")) {
resolveLater (e);
e.aboutEach (sAboutEach);
}
String sAboutEachPrefix = e.getAttribute (RDFMS, "aboutEachPrefix");
if (sAboutEachPrefix != null) {
resolveLater (e);
e.aboutEachPrefix (sAboutEachPrefix);
}
String sAbout = e.getAttribute (RDFMS, "about");
if (sAbout != null) {
if (sAbout.startsWith("#")) {
resolveLater (e);
} else {
registerID (sAbout, e);
registerResource (e);
e.about (sAbout, source());
}
}
String sBagID = e.getAttribute (RDFMS, "bagID");
if (sBagID != null) {
e.bagID (sBagID, source());
sBagID = e.bagID();
registerID (sBagID, e);
}
String sID = e.getAttribute (RDFMS, "ID");
if (sID != null) {
e.ID (sID, source());
sID = e.ID();
registerID (sID, e);
}
if (sID != null && sAbout != null) {
addError ("A description block cannot use both 'ID' and 'about' attributes - see <a href=\"http://www.w3.org/TR/REC-rdf-syntax/#idAboutAttr\">[6.5]</a>");
}
}
/**
* Take an element <i>ele</i> with its parent element <i>parent</i>
* and evaluate all its attributes to see if they are non-RDF specific
* and non-XML specific in which case they must become children of
* the <i>ele</i> node.
*
* @exception SAXException Passed on since we don't handle it.
*/
private boolean expandAttributes (Element parent, Element ele)
throws SAXException {
boolean foundAbbreviation = false;
Enumeration e = ele.attributes ();
while (e.hasMoreElements()) {
String sAttribute = (String)e.nextElement();
String sValue = ele.getAttribute (sAttribute).trim();
if (sAttribute.startsWith (XMLSCHEMA))
continue;
// exception: expand rdf:value
if (sAttribute.startsWith (RDFMS) &&
!sAttribute.startsWith (RDFMS+"_") &&
!sAttribute.endsWith ("value") &&
!sAttribute.endsWith ("type"))
continue;
if (sValue.length() > 0) {
foundAbbreviation = true;
Element newElement = new Element (sAttribute,
new AttributeListImpl());
Data newData = new Data (sValue);
newElement.addChild (newData);
parent.addChild (newElement);
}
}
return foundAbbreviation;
}
/**
* reificate creates one new node and four new triples
* and returns the ID of the new node
*/
private String reificate (Property predicate,
Resource subject,
RDFnode object,
String sNodeID) {
String sNamespace = RDFMS;
if (sNodeID == null)
sNodeID = newReificationID(source());
/**
* The original statement must remain in the data model
*/
addTriple (predicate, subject, object);
/**
* Do not reificate reificated properties
*/
if (predicate.equals (sNamespace+"subject") ||
predicate.equals (sNamespace+"predicate") ||
predicate.equals (sNamespace+"object") ||
predicate.equals (sNamespace+"type")) {
return null;
}
/**
* Reificate by creating 4 new triples
*/
addTriple (new Property(sNamespace + "predicate"),
new Resource(sNodeID),
predicate);
addTriple (new Property(sNamespace + "subject"),
new Resource(sNodeID),
new Resource(( subject.toString().length() == 0 ? source() : subject.toString())));
addTriple (new Property(sNamespace + "object"),
new Resource(sNodeID),
object);
addTriple (new Property(sNamespace + "type"),
new Resource(sNodeID),
new Resource(sNamespace + "Statement"));
return sNodeID;
}
/**
* Create a new triple and add it to the <i>m_triples</i> Vector
*/
public void addTriple (Property predicate,
Resource subject,
RDFnode object) {
/**
* If there is no subject (about=""), then use the URI/filename where
* the RDF description came from
*/
if (predicate == null) {
addWarning ("Predicate null when subject="+subject+" and object="+object);
return;
}
if (subject == null) {
addWarning ("Subject null when predicate="+predicate+" and object="+object);
return;
}
if (object == null) {
addWarning ("Object null when predicate="+predicate+" and subject="+subject);
return;
}
if (subject.toString() == null ||
subject.toString().length() == 0) {
subject = new Resource(source());
}
Triple t = new Triple (predicate, subject, object);
m_triples.addElement (t);
/**
* Notify RDFConsumer objects if any
*/
for (int x = 0; x < m_consumers.size(); x++) {
RDFConsumer consumer = (RDFConsumer)m_consumers.elementAt(x);
consumer.assert (this, predicate, subject, object);
}
}
/**
* Print all triples to the <i>ps</i> PrintStream
*/
public void printTriples (PrintStream ps) {
for (int x = 0; x < m_triples.size(); x++) {
Triple t = (Triple)m_triples.elementAt (x);
ps.println ("triple(\""+t.predicate()+"\",\""+t.subject()+"\",\""+t.object()+"\").");
}
}
/**
* Return all created triples in an Enumeration instance
*/
public Enumeration triples () {
return m_triples.elements ();
}
/**
* Is the element a Description
*/
public boolean isDescription (Element e) {
return isRDF(e) &&
e.name().endsWith ("Description");
}
/**
* Is the element a ListItem
*/
public boolean isListItem (Element e) {
return isRDF(e) &&
( e.name().endsWith ("li") ||
e.name().indexOf ("_") > -1);
}
/**
* Is the element a Container
*
* @see isSequence
* @see isAlternative
* @see isBag
*/
public boolean isContainer (Element e) {
return (isSequence (e) ||
isAlternative (e) ||
isBag (e));
}
/**
* Is the element a Sequence
*/
public boolean isSequence (Element e) {
return isRDF(e) &&
e.name().endsWith ("Seq");
}
/**
* Is the element an Alternative
*/
public boolean isAlternative (Element e) {
return isRDF(e) &&
e.name().endsWith ("Alt");
}
/**
* Is the element a Bag
*/
public boolean isBag (Element e) {
return isRDF(e) &&
e.name().endsWith ("Bag");
}
/**
* This method matches all properties but those from RDF namespace
*/
public boolean isTypedPredicate (Element e) {
if (isRDF(e)) {
// list all RDF predicates known by the RDF specification
if (e.name().endsWith ("predicate") ||
e.name().endsWith ("subject") ||
e.name().endsWith ("object") ||
e.name().endsWith ("type") ||
e.name().endsWith ("value") ||
e.name().indexOf("_") >= 0 ||
e.name().endsWith ("Property") ||
e.name().endsWith ("Statement")) {
return true;
}
return false;
}
if (e.name().length() > 0)
return true;
else
return false;
}
public boolean isRDFroot (Element e) {
return isRDF(e) &&
e.name().endsWith ("RDF");
}
/**
* Check if the element <i>e</i> is from the namespace
* of the RDF schema by comparing only the beginning of
* the expanded element name with the canonical RDFMS
* URI
*/
public boolean isRDF (Element e) {
if (e != null && e.name() != null)
return e.name().startsWith (RDFMS);
else
return false;
}
/**
* Methods for node reference management
*/
private Vector m_vResources = new Vector ();
private Vector m_vResolveQueue = new Vector ();
private Hashtable m_hIDtable = new Hashtable ();
private int m_iReificationCounter = 0;
/**
* Add the element <i>e</i> to the <i>m_vResolveQueue</i>
* to be resolved later.
*/
public void resolveLater (Element e) {
m_vResolveQueue.addElement (e);
}
/**
* Go through the <i>m_vResolveQueue</i> and assign
* direct object reference for each symbolic reference
*/
public void resolve () {
for (int x = 0; x < m_vResolveQueue.size(); x++) {
Element e = (Element)m_vResolveQueue.elementAt(x);
String sAbout = e.about();
if (sAbout != null) {
if (sAbout.startsWith ("#"))
sAbout = sAbout.substring(1);
Element e2 = (Element)lookforNode(sAbout);
if (e2 != null) {
e.addTarget (e2);
} else {
addError ("Unresolved internal reference to "+sAbout);
}
}
String sResource = e.getAttribute (RDFMS, "resource");
if (sResource != null) {
if (sResource.startsWith ("#"))
sResource = sResource.substring(1);
Element e2 = (Element)lookforNode(sResource);
if (e2 != null) {
e.resource (e2.ID());
e.addTarget (e2);
} else {
addError ("Unresolved internal reference to "+sResource);
}
}
String sAboutEach = e.getAttribute (RDFMS, "aboutEach");
if (sAboutEach != null) {
sAboutEach = sAboutEach.substring(1);
Element e2 = (Element)lookforNode(sAboutEach);
if (e2 != null) {
e.addTarget (e2);
}
}
String sAboutEachPrefix = e.getAttribute (RDFMS, "aboutEachPrefix");
if (sAboutEachPrefix != null) {
for (int y = 0; y < m_vResources.size(); y++) {
Element ele = (Element)m_vResources.elementAt(y);
String sA = ele.about();
if (sA.startsWith (sAboutEachPrefix)) {
e.addTarget (ele);
}
}
}
}
m_vResolveQueue.removeAllElements();
}
/**
* Look for a node by name <i>sID</i> from the Hashtable
* <i>m_hIDtable</i> of all registered IDs.
*/
public Element lookforNode (String sID) {
if (sID == null) {
return null;
} else {
return (Element)m_hIDtable.get (source()+"#"+sID);
}
}
/**
* Add an element <i>e</i> to the Hashtable <i>m_hIDtable</i>
* which stores all nodes with an ID
*/
public void registerID (String sID, Element e) {
if (m_hIDtable.get (sID) != null)
addError("Node ID '"+sID+"' redefined.");
m_hIDtable.put (sID, e);
}
/**
* Create a new reification ID by using a name part and an
* incremental counter <i>m_iReificationCounter</i>.
*/
public String newReificationID (String sSource) {
m_iReificationCounter++;
return Element.makeAbsolute(new String ("genid" + m_iReificationCounter),
sSource);
}
/**
* Add an element <i>e</i> to the Vector <i>m_vResources</i>
* which stores all nodes with an URI
*/
public void registerResource (Element e) {
m_vResources.addElement (e);
}
public void makeMarkupST (Element ele) {
m_sLiteral += "<" + ele.name();
Enumeration e = ele.attributes();
while (e.hasMoreElements()) {
String sAttribute = (String)e.nextElement();
String sAttributeValue = (String)ele.getAttribute (sAttribute);
m_sLiteral += " " + sAttribute + "='" + sAttributeValue + "'";
}
m_sLiteral += ">";
}
public void makeMarkupET (String name) {
m_sLiteral += "</" + name + ">";
}
public void makeMarkupChar (String s) {
m_sLiteral += s;
}
/**
* This method adds a warning for each name (element & attribute)
* which looks like it is from RDF but it is not.
*
* Note: this method is useful for interactive use but can be
* omitted from embedded applications.
*/
public void likeRDF (String sNamespace, String sElement) {
if (!sNamespace.equals (RDFMS)) {
if (sElement.equals ("RDF") ||
sElement.equals ("Description") ||
sElement.equals ("Bag") ||
sElement.equals ("Alt") ||
sElement.equals ("Seq") ||
sElement.equals ("li") ||
sElement.equals ("_1") ||
sElement.equals ("ID") ||
sElement.equals ("parseType") ||
sElement.equals ("resource") ||
sElement.equals ("about") ||
sElement.equals ("value") ||
sElement.equals ("subject") ||
sElement.equals ("predicate") ||
sElement.equals ("object") ||
sElement.equals ("type")) {
addWarning ("Name '"+sElement+"' looks like it is from RDF but it has namespace "+sNamespace+"\n");
}
}
}
/**
* main method for running SiRPAC as an application
*/
public static void main (String args[]) throws Exception {
if (args.length == 0) {
System.err.println("Usage: java -Dorg.xml.sax.parser=<classname> org.w3c.rdf.SiRPAC [ URI or filename ] [-fetch_schemas | -f]");
System.err.println ("This is revision "+REVISION);
System.exit(1);
}
SiRPAC compiler = new SiRPAC ();
if (args.length == 2 &&
args[1].startsWith ("-f")) {
compiler.fetchSchemas (true);
}
URL url = null;
try {
url = new URL (args[0]);
} catch (Exception e) {
url = new URL ("file", null, args[0]);
}
compiler.setRDFSource (new RDFSource(url));
compiler.fetchRDF ();
String sErrors = compiler.errors ();
if (sErrors != null && sErrors.length() > 0) {
System.out.println ("Errors during parsing:\n"+sErrors);
} else {
compiler.printTriples (System.out);
}
/*
String sWarnings = compiler.warnings ();
if (sWarnings != null && sWarnings.length() > 0) {
System.out.println ("Warnings during parsing:\n"+sWarnings);
}
*/
}
}