Annotation of java/classes/org/w3c/rdf/SiRPAC.java, revision 1.4
1.1 jsaarela 1: /**
2: * SiRPAC - Simple RDF Parser & Compiler
3: * Copyright © World Wide Web Consortium, (Massachusetts Institute of Technology,
4: * Institut National de Recherche en Informatique et en Automatique, Keio University).
5: * All Rights Reserved.
6: * Please see the full Copyright clause at <http://www.w3.org/COPYRIGHT.html>
7: *
8: * This program translates RDF descriptions into triple representation
9: * This version is suitable for embedded use as well as command line use
10: *
11: * This version uses SAX V1.0 available at <http://www.microstar.com/XML/SAX/>
12: *
1.4 ! jsaarela 13: * $Log: SiRPAC.java,v $
! 14: * Revision 1.3 1998/07/28 09:40:41 jsaarela
! 15: * 1st distribution release.
! 16: *
1.1 jsaarela 17: *
18: * @author Janne Saarela <jsaarela@w3.org>
19: */
20: package org.w3c.rdf;
21:
22: import org.xml.sax.HandlerBase;
23: import org.xml.sax.InputSource;
24: import org.xml.sax.Locator;
25: import org.xml.sax.AttributeList;
26: import org.xml.sax.EntityResolver;
27: import org.xml.sax.DTDHandler;
28: import org.xml.sax.DocumentHandler;
29: import org.xml.sax.ErrorHandler;
30: import org.xml.sax.SAXParseException;
31: import org.xml.sax.Parser;
32: import org.xml.sax.InputSource;
33: import org.xml.sax.SAXException;
34:
35: import org.xml.sax.helpers.*;
36:
37: import java.net.URL;
38: import java.util.*;
39: import java.io.*;
40:
41: public class SiRPAC implements EntityResolver, DTDHandler, DocumentHandler,
42: ErrorHandler {
1.4 ! jsaarela 43: final static public String revision = "$Id: SiRPAC.java,v 1.3 1998/07/28 09:40:41 jsaarela Exp $";
1.1 jsaarela 44:
45: private Stack m_elementStack = new Stack ();
46: private Element m_root = null;
47: private Vector m_triples = new Vector ();
48: private String m_sErrorMsg = new String ();
49:
50: /**
51: * Namespace management
52: */
53: static private Hashtable s_namespaces = new Hashtable();
54: public static void addNamespace (String sAs, String sHref) {
55: s_namespaces.put (sAs.toLowerCase(), sHref);
56: }
57:
58: public static String namespace (String sAs) {
59: return (String)s_namespaces.get (sAs.toLowerCase());
60: }
61:
62: public static void main (String args[]) throws Exception
63: {
64: if (args.length != 1) {
1.2 jsaarela 65: System.err.println("Usage: java -Dsax.parser=<classname> SiRPAC <document>");
1.1 jsaarela 66: System.exit(1);
67: }
68:
1.2 jsaarela 69: SiRPAC compiler = null;
70: try {
71: // Create a new parser.
72: Parser p = ParserFactory.makeParser();
73:
74: // Create a new handler.
75: compiler = new SiRPAC();
76:
77: // Register the handlers
78: p.setEntityResolver(compiler);
79: p.setDTDHandler (compiler);
80: p.setDocumentHandler(compiler);
81: p.setErrorHandler (compiler);
82:
83: FileInputStream input = new FileInputStream(args[0]);
84: InputSource source = new InputSource(input);
85: source.setSystemId(args[0]);
86:
87: p.parse(source);
88: } catch (SAXException e) {
1.3 jsaarela 89: if (compiler != null)
90: compiler.addError (e.getMessage());
91: else
92: e.printStackTrace ();
1.2 jsaarela 93: } catch (Exception e) {
1.3 jsaarela 94: if (compiler != null)
95: compiler.addError ("Internal error "+e);
96: else
97: e.printStackTrace ();
1.2 jsaarela 98: }
99:
100: String sErrors = compiler.errors ();
1.4 ! jsaarela 101: if (sErrors != null && sErrors.length() > 0) {
1.2 jsaarela 102: System.out.println ("Errors during parsing:\n"+sErrors);
103: }
1.1 jsaarela 104: }
105:
106: public InputSource resolveEntity (String publicId, String systemId)
107: {
108: return null;
109: }
110:
111: public void notationDecl (String name, String publicId, String systemId)
112: {
113: }
114:
115: /**
116: * Display unparsed entity declarations as they are reported.
117: *
118: * @see org.xml.sax.DTDHandler#unparsedEntityDecl
119: */
120: public void unparsedEntityDecl (String name,
121: String publicId,
122: String systemId,
123: String notationName)
124: {
125: }
126:
127: public void setDocumentLocator (Locator locator)
128: {
129: }
130:
131: public void startDocument () {
132: m_sErrorMsg = "";
133: }
134:
1.2 jsaarela 135: public void endDocument () throws SAXException {
1.1 jsaarela 136: processRDF (m_root);
137: // m_root.linearize (0, System.out);
138: printTriples (System.out);
139: }
140:
141: public void doctype (String name, String publicID, String systemID) {
142: }
143:
1.2 jsaarela 144: public void startElement (String name, AttributeList al) throws SAXException {
1.1 jsaarela 145: int iLength = al.getLength ();
146: if (iLength == 0) {
147: // TODO: error reporting: no attributes
148: } else for (int x = 0; x < iLength; x++) {
149: String aname = al.getName (x);
150: String special = "";
151: }
152:
153: /**
154: * Create a new element and update the containment hierarchy
155: * with the stack.
156: */
157: Element newElement = new Element (name, al);
158:
159: if (!m_elementStack.empty()) {
160: Element e = (Element)m_elementStack.peek ();
161: e.addChild (newElement);
162: }
163:
164: /**
165: * Place the new element into the stack
166: */
167: m_elementStack.push (newElement);
168: }
169:
170: public void endElement (String name)
171: {
172: m_root = (Element)m_elementStack.pop ();
173: }
174:
175: public void characters (char ch[], int start, int length)
176: {
177: /**
178: * Place all characters as Data instance to the containment
179: * hierarchy with the help of the stack.
180: */
181: Element e = (Element)m_elementStack.peek ();
182: String s = new String (ch, start, length+start);
183:
184: /**
185: * Warning: this is not correct procedure according to XML spec.
186: * All whitespace matters!
187: */
188: String sTrimmed = s.trim();
189: if (sTrimmed.length() > 0)
190: e.addChild (new Data (s));
191: }
192:
193: public void ignorableWhitespace (char ch[], int start, int length)
194: {
195: }
196:
197: public void processingInstruction (String target, String data)
198: {
199: if (target.equalsIgnoreCase ("xml:namespace")) {
200: /**
201: * Figure out the href and as attributes from the namespace
202: * declaration
203: */
204: StringReader sr = new StringReader (data);
205: StreamTokenizer st = new StreamTokenizer (sr);
206:
207: int token1, token2, token3, token4, token5, token6;
208: try {
209: while ((token1 = st.nextToken()) != StreamTokenizer.TT_EOF) {
210: String sHref = st.sval;
211: token2 = st.nextToken();
212: token3 = st.nextToken();
213: String sHrefValue = st.sval;
214: token4 = st.nextToken();
215: String sAs = st.sval;
216: token5 = st.nextToken();
217: token6 = st.nextToken();
218: String sAsValue = st.sval;
219: if (token1 == StreamTokenizer.TT_WORD &&
220: token2 == '=' &&
221: token3 == 34 &&
222: token4 == StreamTokenizer.TT_WORD &&
223: token5 == '=' &&
224: token6 == 34 &&
225: sHref.equals ("ns") &&
226: sAs.equals ("prefix")) {
227: SiRPAC.addNamespace (sAsValue, sHrefValue);
228: }
229: }
230: } catch (Exception e) {
231: m_sErrorMsg = "# Malformed namespace declaration "+data;
232: e.printStackTrace();
233: }
234: }
235: }
236:
237: /**
238: * Report all warnings, and continue parsing.
239: *
240: * @see org.xml.sax.ErrorHandler#warning
241: */
242: public void warning (SAXParseException exception)
243: {
244: m_sErrorMsg = "Warning: " +
245: exception.getMessage() +
246: " (" +
247: // exception.getSystemId() +
248:
249: "line <a href=\"#" +
250: exception.getLineNumber() +
251: "\">" +
252: exception.getLineNumber() +
253: "</a>, column " +
254: exception.getColumnNumber() +
255: ")<br>";
256: }
257:
258:
259: /**
260: * Report all recoverable errors, and try to continue parsing.
261: *
262: * @see org.xml.sax.ErrorHandler#error
263: */
264: public void error (SAXParseException exception)
265: {
266: m_sErrorMsg = "Recoverable Error: " +
267: exception.getMessage() +
268: " (" +
269: // exception.getSystemId() +
270:
271: "line <a href=\"#" +
272: exception.getLineNumber() +
273: "\">" +
274: exception.getLineNumber() +
275: "</a>, column " +
276: exception.getColumnNumber() +
277: ")<br>";
278: }
279:
280:
281: /**
282: * Report all fatal errors, and try to continue parsing.
283: *
284: * <p>Note: results are no longer reliable once a fatal error has
285: * been reported.</p>
286: *
287: * @see org.xml.sax.ErrorHandler#fatalError
288: */
289: public void fatalError (SAXParseException exception)
290: {
291: m_sErrorMsg = "Fatal Error: " +
292: exception.getMessage() +
293: " (" +
294: // exception.getSystemId() +
295: "line <a href=\"#" +
296: exception.getLineNumber() +
297: "\">" +
298: exception.getLineNumber() +
299: "</a>, column " +
300: exception.getColumnNumber() +
301: ")<br>";
302: }
303:
304: public String errors () {
305: return m_sErrorMsg;
306: }
307:
1.2 jsaarela 308: public void addError (String sMsg) {
309: m_sErrorMsg += sMsg;
310: }
311:
1.1 jsaarela 312: public static Parser createParser (String className) {
313: Element.init ();
314: Parser parser = null;
315:
316: try {
317: // Get the named class.
318: Class c = Class.forName(className);
319: // Instantiate the parser.
320: parser = (Parser)(c.newInstance());
321: } catch (ClassNotFoundException e) {
322: System.err.println("SAX parser class " + className +
323: "cannot be loaded.");
324: System.exit(1);
325: } catch (IllegalAccessException e) {
326: System.err.println("SAX parser class " + className +
327: " does not have a zero-argument constructor.");
328: System.exit(1);
329: } catch (InstantiationException e) {
330: System.err.println("SAX parser class " + className +
331: " cannot be instantiated.");
332: System.exit(1);
333: }
334:
335: // Check the the parser object
336: // actually implements the Parser interface.
337: if (!(parser instanceof org.xml.sax.Parser)) {
338: System.err.println("Class " + className +
339: " does not implement org.xml.sax.Parser.");
340: System.exit(1);
341: }
342:
343: return parser;
344: }
345:
346: /**
347: * If a URL is relative, make it absolute against the current directory.
348: */
349: private static String makeAbsoluteURL (String url)
350: throws java.net.MalformedURLException {
351: URL baseURL;
352:
353: String currentDirectory = System.getProperty("user.dir");
354: String fileSep = System.getProperty("file.separator");
355: String file = currentDirectory.replace(fileSep.charAt(0), '/') + '/';
356:
357: if (file.charAt(0) != '/') {
358: file = "/" + file;
359: }
360: baseURL = new URL("file", null, file);
361:
362: return new URL(baseURL, url).toString();
363: }
364:
365:
366: /**
367: * Escape special characters for display.
368: */
369: private static String escapeCharacters(char ch[], int start, int length) {
370: StringBuffer out = new StringBuffer();
371:
372: for (int i = start; i < start+length; i++) {
373: if (ch[i] >= 0x20 && ch[i] < 0x7f) {
374: out.append(ch[i]);
375: } else {
376: out.append("&#" + (int)ch[i] + ';');
377: }
378: }
379:
380: return out.toString();
381: }
382:
383: /**
384: * Start processing an RDF/XML document instance
385: */
1.2 jsaarela 386: void processRDF (Element rdf) throws SAXException {
1.1 jsaarela 387: Element.resolve ();
388:
389: Enumeration e = rdf.children();
390: while (e.hasMoreElements()) {
391: Element ele = (Element)e.nextElement();
392:
393: if (isDescription (ele)) {
394: processDescription (ele, false, false, true);
395: } else if (isCollection (ele)) {
396: processCollection (ele);
397: } else if (isTypedProperty (ele)) {
398: processTypedNode (ele);
399: }
400: }
401: }
402:
403: /**
404: * Manage the production 6.12 in the spec
405: */
1.2 jsaarela 406: public String processTypedNode (Element typedNode) throws SAXException {
1.1 jsaarela 407: String sID = typedNode.getAttribute ("ID");
408: String sBagID = typedNode.getAttribute ("bagID");
409: String sResource = typedNode.getAttribute ("resource");
410: String sAbout = typedNode.getAttribute ("about");
411: String sAboutEach = typedNode.getAttribute ("aboutEach");
412:
413: // create a new node for this typedNode
414: Enumeration e = typedNode.attributes ();
415: while (e.hasMoreElements()) {
416: String sAttribute = (String)e.nextElement();
417: String sValue = typedNode.getAttribute (sAttribute);
418: sValue = sValue.trim ();
419: if (!sAttribute.equals ("ID") &&
420: !sAttribute.equals ("bagID") &&
421: !sAttribute.equals ("resource") &&
422: !sAttribute.equals ("aboutEach") &&
423: !sAttribute.equals ("about")) {
424: if (sValue.length() > 0) {
425: Element newProperty = new Element (sAttribute,
426: new AttributeListImpl());
427: newProperty.addAttribute ("ID", sID);
428: newProperty.addAttribute ("bagID", sBagID);
429: // make the resource property the about property
430: // of the new Description block
431: newProperty.addAttribute ("about", sResource);
432: Data newData = new Data (sValue);
433: newProperty.addChild (newData);
434: typedNode.addChild (newProperty);
435: typedNode.removeAttribute (sAttribute);
436: }
437: }
438: }
439:
440: String sObject = new String ();
441: if (sResource != null)
442: sObject = sResource;
443: else if (sID != null)
444: sObject = sID;
445: else
446: sObject = Element.newReificationID();
447:
448: typedNode.ID (sObject);
449:
450: // special case: should the typedNode have aboutEach attribute,
451: // the instanceOf property should distribute to pointed
452: // collection also -> create a child node to the typedNode
453: if (sAboutEach != null &&
454: typedNode.target() != null) {
455: Element newProperty = new Element ("rdf:instanceOf",
456: new AttributeListImpl());
457: Data newData = new Data (typedNode.expandName());
458: newProperty.addChild (newData);
459: typedNode.addChild (newProperty);
460: } else {
461: addTriple (Element.RDFSCHEMA + "#instanceOf",
462: sObject,
463: typedNode.expandName());
464: }
1.3 jsaarela 465:
1.1 jsaarela 466: String sDesc = processDescription (typedNode, false, false, true);
467:
468: return sObject;
469: }
470:
471: /**
472: * processDescription takes the following parameters
473: *
474: * @param description The Description element itself
475: * @param inProperty A flag to tell whether this is a nested description
476: inside a property.
477: * @param reificate Do we need to reificate
478: * @param createBag Do we create a bag collection out of nested properties
479: *
480: * @return An ID for the description
481: */
482: private String processDescription (Element description,
483: boolean inProperty,
484: boolean reificate,
1.2 jsaarela 485: boolean createBag) throws SAXException {
1.1 jsaarela 486: /**
487: * Return immediately if the description has already been managed
488: */
489: if (description.done())
490: return description.ID();
491:
492: int iChildCount = 1;
493: boolean bOnce = true;
494:
495: /**
496: * Determine first all relevant values
497: */
498: String sAbout = description.getAttribute ("about");
499: String sAboutEach = description.getAttribute ("aboutEach");
500: String sBagid = description.getAttribute ("bagID");
501: String sID = description.getAttribute ("ID");
502: Element target = description.target();
503:
504: boolean hasTarget = ( target != null );
505: boolean targetIsBag = false;
506: String sTargetAbout = null;
507: String sTargetBagid = null;
508: String sTargetID = null;
509:
510: if (hasTarget) {
511: sTargetAbout = target.getAttribute ("about");
512: sTargetBagid = target.getAttribute ("bagID");
513: sTargetID = target.getAttribute ("ID");
514:
515: if (sAbout != null && sTargetBagid != null) {
516: targetIsBag = (sAbout.substring(1).equals (sTargetBagid));
517: } else {
518: if (sAbout != null &&
519: sTargetID != null &&
520: sAbout.substring(1).equals (sTargetID) &&
521: (target.name().equals ("rdf:Bag") ||
522: target.name().equals ("rdf:Seq") ||
523: target.name().equals ("rdf:Alt"))) {
524: targetIsBag = true;
525: }
526: }
527: }
528:
529: /**
530: * Manage the properties encoded as attributes by creating
531: * a new child node for each one of them. In this way
532: * the code for non-abbreviated properties will also work.
533: */
534:
535: Enumeration e = description.attributes ();
536: while (e.hasMoreElements()) {
537: String sAttribute = (String)e.nextElement ();
538: String sValue = description.getAttribute(sAttribute);
539: sValue = sValue.trim ();
540:
541: /**
542: * Create child nodes for non-RDF specific attributes
543: */
544: if (!sAttribute.equals ("about") &&
545: !sAttribute.equals ("aboutEach") &&
546: !sAttribute.equals ("ID") &&
547: !sAttribute.equals ("bagID")) {
548: if (sValue.length() > 0) {
549: Element ele = new Element (sAttribute,
550: new AttributeListImpl());
551: ele.addChild (new Data (sValue));
552: description.addChild (ele);
553: }
554: }
555: }
556:
557: /**
558: * Resolve distributive referents here
559: *
560: * Use straight-forward replication of properties
561: * to newly created description nodes
562: */
563:
564: if (hasTarget && sAboutEach != null) {
565:
566: e = target.children ();
567: while (e.hasMoreElements()) {
568: Element ele = (Element)e.nextElement ();
569:
570: String sResource = ele.getAttribute ("resource");
571: Element newDescription = null;
572: if (sResource != null) {
573: newDescription = new Element ("rdf:Description",
574: new AttributeListImpl());
575: newDescription.addAttribute ("about", sResource);
576: }
577: Enumeration e2 = description.children();
578: while (e2.hasMoreElements()) {
579: Element ele2 = (Element)e2.nextElement ();
580: if (newDescription != null) {
581: newDescription.addChild (ele2);
582: }
583: }
584: if (newDescription != null)
585: processDescription (newDescription, false, false, false);
586: }
587:
588: // should not return anything I think nor should it
589: // go and generate bags
590: return null;
591: }
592:
593: /**
594: * Enumerate through the children
595: */
596: e = description.children();
597:
598: while (e.hasMoreElements()) {
599: Element n = (Element)e.nextElement();
600:
601: if (isCollection (n)) {
602: processCollection (n);
603:
604: } else if (n instanceof Element) {
605:
606: /**
607: * Quote from the spec:
608: *
609: * The Description element itself creates an instance of a Bag
610: * node. The members of this Bag are the nodes corresponding
611: * to the reification of each of the properties in the
612: * Description. If the BAGID attribute is specified its value
613: * is the identifier of this Bag, else the Bag is anonymous.
614: */
615: String sChildID = null;
616:
617: if (hasTarget && targetIsBag) {
618: sChildID = processProperty (n, description,
619: target.ID(), false);
620: description.ID (sChildID);
621: createBag = false;
622: } else if (hasTarget) {
623: sChildID = processProperty (n, description,
624: sTargetAbout, reificate);
625: // description.ID (sChildID);
626: } else if (!hasTarget && !inProperty) {
627: if (sAbout == null)
628: if (sID != null)
629: sAbout = sID;
630: else
631: sAbout = description.ID();
632: sChildID = processProperty (n, description,
633: ( sAbout != null ? sAbout : sID),
634: createBag);
635: // description.ID (sChildID);
636: } else if (!hasTarget && inProperty) {
637: if (sAbout == null) {
638: if (sID != null) {
639: description.ID (sID);
640: sAbout = sID;
641: } else {
642: if (description.ID() == null)
643: description.ID (Element.newReificationID());
644: sAbout = description.ID();
645: }
646: } else {
647: description.ID (sAbout);
648: }
649: sChildID = processProperty (n, description,
650: sAbout,
651: false);
652: }
653:
654: if (createBag) {
655: String sNamespace = Element.RDFSCHEMA;
656: if (bOnce) {
657: bOnce = false;
1.3 jsaarela 658: if (description.bagID() == null)
659: description.bagID (Element.newReificationID());
1.4 ! jsaarela 660: if (description.ID() == null)
! 661: description.ID (description.bagID());
1.1 jsaarela 662:
663: addTriple (sNamespace + "#instanceOf",
1.3 jsaarela 664: description.bagID(),
1.1 jsaarela 665: sNamespace + "#Bag");
666: }
667: addTriple (sNamespace + "#"+iChildCount,
1.3 jsaarela 668: description.bagID(),
1.1 jsaarela 669: sChildID);
670: iChildCount++;
671: }
672: }
673: }
674:
675: description.done (true);
676:
677: return description.ID();
678: }
679:
680: /**
681: * processProperty handles all elements not defined as special
682: * RDF elements.
683: *
684: * @param property The Property element itself
685: * @param description The Description element in which this property appears
686: * @param sTarget The target resource
687: * @param reificate Should this property be reificated
688: *
689: * @return the new ID which can be used to identify the property
690: */
691: private String processProperty (Element property,
692: Element description,
693: String sTarget,
1.2 jsaarela 694: boolean reificate) throws SAXException {
1.1 jsaarela 695: String sPropertyID = null;
696:
697: /**
698: * Do the same trick as with Description blocks:
699: * if the Property uses abbreviated syntax, transform
700: * the structure into corresponding full tree representation
701: * which is handled correctly by the code for the non-abbreviated
702: * syntax.
703: */
704:
705: String sID = property.getAttribute ("ID");
706: String sResource = property.getAttribute ("resource");
707: String sAbout = property.getAttribute ("about");
708:
709: boolean bAbbreviated = false;
710: Element d = new Element ("RDF:Description",
711: new AttributeListImpl());
712: /*
713: * Tricky part: use the resource attribute to name
714: * the intermediate Description block
715: */
716: if (sResource != null) {
717: d.addAttribute ("about", sResource);
718: }
719:
720: Enumeration e = property.attributes ();
721: while (e.hasMoreElements()) {
722: String sAttribute = (String)e.nextElement();
723: String sValue = property.getAttribute (sAttribute);
724: sValue = sValue.trim ();
725: if (!sAttribute.equals ("resource") &&
726: !sAttribute.equals ("about") &&
727: !sAttribute.equals ("ID") &&
728: !sAttribute.equals ("bagID")) {
729: if (sValue.length() > 0) {
730: bAbbreviated = true;
731: Element newProperty = new Element (sAttribute,
732: new AttributeListImpl());
733: Data newData = new Data (sValue);
734: newProperty.addChild (newData);
735: d.addChild (newProperty);
736: }
737: }
738: }
739: /**
740: * If we found properties and attributes and generated the subtree,
741: * attach it to the property itself and let the code below take
742: * care of the rest.
743: */
744: if (bAbbreviated) {
745: property.addChild (d);
746: }
747:
748: /**
749: * Does this property make a reference somewhere using the
750: * <i>resource</i> attribute
751: */
752: if (sResource != null && property.target() != null) {
753: sPropertyID = processDescription (property.target(),
1.2 jsaarela 754: true, false, false);
1.1 jsaarela 755: if (reificate) {
756: sPropertyID = reificate (property.expandName(),
757: sTarget, sPropertyID);
758: property.ID (sPropertyID);
759: } else {
760: addTriple (property.expandName(),
761: sTarget,
762: sPropertyID);
763: }
764:
765: return sPropertyID;
766: }
767:
768: /**
769: * Is the value of the attribute given as a URI in the
770: * about attribute?
771: */
772: if (sAbout != null) {
773: if (reificate) {
774: sPropertyID = reificate (property.expandName(),
775: sTarget,
776: sAbout);
777: property.ID (sPropertyID);
778: } else {
779: addTriple (property.expandName(),
780: sTarget,
781: sAbout);
782: }
783: }
784:
785: Enumeration e2 = property.children();
786: while (e2.hasMoreElements()) {
787: Element n2 = (Element)e2.nextElement();
788:
789: if (isDescription (n2)) {
790: Element d2 = n2;
791:
792: sPropertyID = processDescription (d2, true, false, false);
793:
794: d2.ID (sPropertyID);
795:
796: if (reificate) {
797: sPropertyID = reificate (property.expandName(),
798: sTarget, sPropertyID);
799: } else {
800: addTriple (property.expandName(),
801: sTarget, sPropertyID);
802: }
803:
804: } else if (n2 instanceof Data) {
805: /**
806: * We've got real data
807: */
808: String sValue = ((Data)n2).data();
809:
810: /**
811: * Only if the content is not empty PCDATA (whitespace that is),
812: * print the triple
813: */
814: sValue = sValue.trim();
815: if (sValue.length() > 0) {
816: if (reificate) {
817: sPropertyID = reificate (property.expandName(),
818: sTarget,
819: sValue);
820: property.ID (sPropertyID);
821: } else {
822: addTriple (property.expandName(),
823: sTarget,
824: sValue);
825: }
826: }
827: } else if (isCollection (n2)) {
828:
829: String sCollectionID = processCollection (n2);
830: sPropertyID = sCollectionID;
831:
832: /**
833: * Attach the collection to the current Property
834: */
835: if (description.target() != null) {
836: if (reificate) {
837: sPropertyID = reificate (property.expandName(),
838: description.target().getAttribute ("about"),
839: sCollectionID);
840: property.ID (sPropertyID);
841: } else {
842: addTriple (property.expandName(),
843: description.target().getAttribute ("about"),
844: sCollectionID);
845: }
846: } else {
847: if (reificate) {
848: sPropertyID = reificate (property.expandName(),
1.4 ! jsaarela 849: sTarget,
1.1 jsaarela 850: sCollectionID);
851: property.ID (sPropertyID);
852: } else {
853: addTriple (property.expandName(),
854: description.getAttribute ("about"),
855: sCollectionID);
856: }
857: }
858: } else if (isTypedProperty (n2)) {
859: sPropertyID = processTypedNode (n2);
860: addTriple (property.expandName(),
861: description.ID(),
862: sPropertyID);
863: }
864: }
865:
866: return sPropertyID;
867: }
868:
1.2 jsaarela 869: private String processCollection (Element n) throws SAXException {
1.1 jsaarela 870: String sID = n.getAttribute ("ID");
871: if (sID == null)
872: sID = Element.newReificationID();
873:
874: /**
875: * Do the instantiation only once
876: */
877: if (!n.done()) {
878: String sNamespace = Element.RDFSCHEMA;
879: if (isSequence (n)) {
880: addTriple (sNamespace+"#instanceOf",
881: sID,
882: sNamespace+"#Sequence");
883: } else if (isAlternative (n)) {
884: addTriple (sNamespace+"#instanceOf",
885: sID,
886: sNamespace+"#Alt");
887: } else if (isBag (n)) {
888: addTriple (sNamespace+"#instanceOf",
889: sID,
890: sNamespace+"#Bag");
891: }
892: n.done (true);
893: }
894:
895: Enumeration e = ((Element)n).children();
896: int iCounter = 1;
897: while (e.hasMoreElements()) {
898: Element n2 = (Element)e.nextElement();
899: if (n2.name().equalsIgnoreCase ("rdf:li")) {
900: processListItem (sID, n2, iCounter);
901: iCounter++;
902: }
903: }
904:
905: return sID;
906: }
907:
1.2 jsaarela 908: private void processListItem (String sID, Element listitem, int iCounter)
909: throws SAXException {
1.1 jsaarela 910: /**
911: * Two different cases for
912: * 1. LI element without content (href available)
913: * 2. LI element with content (href unavailable)
914: */
915: String sNamespace = SiRPAC.namespace (listitem.prefix());
916: String sResource = listitem.getAttribute ("resource");
917: if (sResource != null) {
918: addTriple (sNamespace+"#"+iCounter,
919: sID,
920: sResource);
921: } else {
922: Enumeration e = listitem.children();
923: while (e.hasMoreElements()) {
924: Element n = (Element)e.nextElement();
925: if (n instanceof Data) {
926: addTriple (sNamespace+"#"+iCounter,
927: sID,
928: ((Data)n).data());
929: } else if (isDescription (n)) {
930: processDescription (n, false, false, true);
931: }
932: }
933: }
934: }
935:
936: /**
937: * reificate creates one new node and four new triples
938: * and returns the ID of the new node
939: */
940: private String reificate (String sProperty,
941: String sPropertyObject,
942: String sPropertyValue) {
943: /**
944: * Reificate by creating 4 new triples
945: */
946: String sNamespace = Element.RDFSCHEMA;
947: String sNodeID = Element.newReificationID();
948:
949: addTriple (sNamespace + "#PropName",
950: sNodeID,
951: sProperty);
952:
953: addTriple (sNamespace + "#PropObj",
954: sNodeID,
955: sPropertyObject);
956:
957: addTriple (sNamespace + "#PropValue",
958: sNodeID,
959: sPropertyValue);
960:
961: addTriple (sNamespace + "#instanceOf",
962: sNodeID,
963: sNamespace + "#Property");
964:
965: return sNodeID;
966: }
967:
968: private void addTriple (String sProperty, String sPropertyObj, String sPropertyValue) {
969: Triple t = new Triple (sProperty, sPropertyObj, sPropertyValue);
970: m_triples.addElement (t);
971: }
972:
973: public void printTriples (PrintStream ps) {
974: for (int x = 0; x < m_triples.size(); x++) {
975: Triple t = (Triple)m_triples.elementAt (x);
976: ps.println ("triple(\""+t.property()+"\",\""+t.object()+"\",\""+t.value()+"\").");
977: }
978: }
979:
980: public Enumeration triples () {
981: return m_triples.elements ();
982: }
983:
984: /**
985: * Helper functions to identify different elements
986: */
987: public boolean isDescription (Element e) {
988: return e.name().equalsIgnoreCase ("rdf:description");
989: }
990:
991: public boolean isCollection (Element e) {
992: return (e.name().equalsIgnoreCase ("rdf:seq") ||
993: e.name().equalsIgnoreCase ("rdf:alt") ||
994: e.name().equalsIgnoreCase ("rdf:bag"));
995: }
996:
997: public boolean isSequence (Element e) {
998: return e.name().equalsIgnoreCase ("rdf:seq");
999: }
1000:
1001: public boolean isAlternative (Element e) {
1002: return e.name().equalsIgnoreCase ("rdf:alt");
1003: }
1004:
1005: public boolean isBag (Element e) {
1006: return e.name().equalsIgnoreCase ("rdf:bag");
1007: }
1008:
1009: public boolean isTypedProperty (Element e) {
1010: if (e.name().length() > 0)
1011: return true;
1012: else
1013: return false;
1014: /* int i = e.name().indexOf (":"); can be without prefix
1015: return i > -1; */
1016: }
1017: }
Webmaster