Annotation of java/classes/org/w3c/rdf/SiRPAC.java, revision 1.10

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 $
1.10    ! jsaarela   14:  * Revision 1.9  1998/08/28 10:03:25  jsaarela
        !            15:  * Distribution release 1.3 on 28-Aug-98.
        !            16:  *
1.9       jsaarela   17:  * Revision 1.8  1998/08/19 13:18:13  jsaarela
                     18:  * Compatibility with RDF M&S -19980819 and Namespaces in XML -19980820
                     19:  *
1.8       jsaarela   20:  * Revision 1.7  1998/08/12 15:12:48  jsaarela
                     21:  * Updated namespace management to correspond with the
                     22:  * Namespaces in XML specification dated 2-Aug-98.
                     23:  *
1.7       jsaarela   24:  * Revision 1.6  1998/07/31 09:42:27  jsaarela
                     25:  * Error reporting improved.
                     26:  * This is distribution V1.1
                     27:  *
1.6       jsaarela   28:  * Revision 1.5  1998/07/30 13:39:45  jsaarela
                     29:  * multiple internal references fixed,
                     30:  * properties without children fixed.
                     31:  *
1.5       jsaarela   32:  * Revision 1.4  1998/07/29 08:27:53  jsaarela
                     33:  * Bug fix: processProperty can now correctly determine the target
                     34:  * of the propertyValue. Didn't work with typedNodes.
                     35:  *
1.4       jsaarela   36:  * Revision 1.3  1998/07/28 09:40:41  jsaarela
                     37:  * 1st distribution release.
                     38:  *
1.1       jsaarela   39:  *
                     40:  * @author Janne Saarela <jsaarela@w3.org>
                     41:  */
                     42: package org.w3c.rdf;
                     43: 
                     44: import org.xml.sax.HandlerBase;
                     45: import org.xml.sax.InputSource;
                     46: import org.xml.sax.Locator;
                     47: import org.xml.sax.AttributeList;
                     48: import org.xml.sax.EntityResolver;
                     49: import org.xml.sax.DTDHandler;
                     50: import org.xml.sax.DocumentHandler;
                     51: import org.xml.sax.ErrorHandler;
                     52: import org.xml.sax.SAXParseException;
                     53: import org.xml.sax.Parser;
                     54: import org.xml.sax.InputSource;
                     55: import org.xml.sax.SAXException;
                     56: 
                     57: import org.xml.sax.helpers.*;
                     58: 
                     59: import java.net.URL;
                     60: import java.util.*;
                     61: import java.io.*;
                     62: 
                     63: public class SiRPAC implements EntityResolver, DTDHandler, DocumentHandler,
1.10    ! jsaarela   64:                               ErrorHandler {
        !            65:     final static public String REVISION = "$Id: SiRPAC.java,v 1.9 1998/08/28 10:03:25 jsaarela Exp $";
        !            66:     public final static String RDFSCHEMA = new String ("http://www.w3.org/TR/WD-rdf-syntax#");
        !            67:     public final static String XMLSCHEMA = new String ("xml");
        !            68: 
        !            69:     private Stack              m_namespaceStack = new Stack ();
        !            70:     private Stack              m_elementStack = new Stack ();
        !            71:     private Element            m_root = null;
        !            72:     private Vector             m_triples = new Vector ();
        !            73:     private String             m_sErrorMsg = new String ();
        !            74: 
        !            75:     /**
        !            76:      * Namespace management
        !            77:      */
        !            78:     public String namespace (String sPrefix) {
        !            79:        if (sPrefix == null) {
        !            80:            sPrefix = new String ("xmlns");
        !            81:        }
        !            82:        for (int x = m_namespaceStack.size()-1; x >=0; x--) {
        !            83:            Hashtable ht = (Hashtable)m_namespaceStack.elementAt (x);
        !            84:            String sURI = (String)ht.get (sPrefix);
        !            85:            if (sURI != null)
        !            86:                return sURI;
        !            87:        }
        !            88:        /**
        !            89:         * Give error only if
        !            90:         * 1. the prefix is not from the reserved xml namespace
        !            91:         * 2. the prefix is not xmlns which is to look for the default
        !            92:         *    namespace
        !            93:         */
        !            94:        if (sPrefix.equals (XMLSCHEMA)) {
        !            95:            return XMLSCHEMA;
        !            96:        } else if (sPrefix.equals ("xmlns")) {
        !            97:            return "";
        !            98:        } else {
        !            99:            addError ("Unresolved namespace prefix "+sPrefix);
        !           100:        }
        !           101:        return "";
        !           102:     }
        !           103: 
        !           104:     public static void main (String args[]) throws Exception {
        !           105:        if (args.length != 1) {
        !           106:            System.err.println("Usage: java -Dsax.parser=<classname> org.w3c.rdf.SiRPAC <rdf_document>");
        !           107:            System.err.println ("This is revision "+REVISION);
        !           108:            System.exit(1);
        !           109:        }
        !           110: 
        !           111:        SiRPAC compiler = null;
        !           112:        try {
        !           113:            // Create a new parser.
        !           114:            Parser p = ParserFactory.makeParser();
        !           115:        
        !           116:            // Create a new handler.
        !           117:            compiler = new SiRPAC();
1.2       jsaarela  118:        
1.10    ! jsaarela  119:            // Register the handlers
        !           120:            p.setEntityResolver(compiler);
        !           121:            p.setDTDHandler (compiler);
        !           122:            p.setDocumentHandler(compiler);
        !           123:            p.setErrorHandler (compiler);
1.2       jsaarela  124:        
1.10    ! jsaarela  125:            FileInputStream input = new FileInputStream(args[0]);
        !           126:            InputSource source = new InputSource(input);
        !           127:            source.setSystemId(args[0]);
1.2       jsaarela  128:        
1.10    ! jsaarela  129:            p.parse(source);
        !           130:        } catch (SAXException e) {
        !           131:            if (compiler != null)
        !           132:                compiler.addError (e.getMessage());
        !           133:            else
        !           134:                e.printStackTrace ();
        !           135:        } catch (Exception e) {
        !           136:            if (compiler != null)
        !           137:                compiler.addError ("Internal error "+e);
        !           138:            else
        !           139:                e.printStackTrace ();
        !           140:        }
1.5       jsaarela  141: 
1.10    ! jsaarela  142:        String sErrors = compiler.errors ();
        !           143:        if (sErrors != null && sErrors.length() > 0) {
        !           144:            System.out.println ("Errors during parsing:\n"+sErrors);
        !           145:        } else {
        !           146:            compiler.printTriples (System.out);
        !           147:        }
1.2       jsaarela  148:     }
                    149: 
1.10    ! jsaarela  150:     public InputSource resolveEntity (String publicId, String systemId) {
        !           151:        return null;
        !           152:     }
1.1       jsaarela  153: 
1.10    ! jsaarela  154:     public void notationDecl (String name, String publicId, String systemId) {
        !           155:     }
1.7       jsaarela  156: 
                    157:     /**
1.10    ! jsaarela  158:      * Display unparsed entity declarations as they are reported.
        !           159:      *
        !           160:      * @see org.xml.sax.DTDHandler#unparsedEntityDecl
1.7       jsaarela  161:      */
1.10    ! jsaarela  162:     public void unparsedEntityDecl (String name,
        !           163:                                    String publicId,
        !           164:                                    String systemId,
        !           165:                                    String notationName) {
        !           166:     }
        !           167: 
        !           168:     public void setDocumentLocator (Locator locator) {
        !           169:     }
1.7       jsaarela  170: 
1.10    ! jsaarela  171:     public void startDocument () {
        !           172:        m_sErrorMsg = "";
        !           173:     }
        !           174: 
        !           175:     public void endDocument () throws SAXException {
        !           176:        processRDF (m_root);
1.1       jsaarela  177:     }
                    178: 
1.10    ! jsaarela  179:     public void doctype (String name, String publicID, String systemID) {
1.7       jsaarela  180:     }
                    181: 
1.10    ! jsaarela  182:     public void startElement (String name, AttributeList al) throws SAXException {
        !           183:        Hashtable namespaces = new Hashtable ();
        !           184: 
        !           185:        /**
        !           186:         * The following loop tries to identify special xmlns prefix
        !           187:         * attributes and update the namespace stack accordingly.
        !           188:         * While doing all this, it builds another AttributeList instance
        !           189:         * which will hold the expanded names of the attributes
        !           190:         * (I think this approach is only useful for RDF which uses
        !           191:         * attributes as an abbreviated syntax for element names)
        !           192:         */
        !           193:        AttributeListImpl newAL = new AttributeListImpl ();
        !           194: 
        !           195:        int iLength = al.getLength ();
        !           196:        if (iLength == 0) {
        !           197:            // ohwell, no attributes
        !           198:        } else for (int x = 0; x < iLength; x++) {
        !           199:            String aName = al.getName (x);
        !           200:            if (aName.equals ("xmlns")) {
        !           201:                String aValue = al.getValue (aName);
        !           202:                namespaces.put (aName, aValue);
        !           203:            } else if (aName.startsWith ("xmlns:")) {
        !           204:                String aValue = al.getValue (aName);
        !           205:                aName = aName.substring (6);
        !           206:                namespaces.put (aName, aValue);
        !           207:            }
        !           208:        }
        !           209:        /**
        !           210:         * Place new namespace declarations into the stack
        !           211:         * (Yes, I could optimize this a bit, not it wastes space
        !           212:         * if there are no xmlns definitions)
        !           213:         */
        !           214:        m_namespaceStack.push (namespaces);
        !           215: 
        !           216:        /**
        !           217:         * Figure out the prefix part if it exists and
        !           218:         * determine the namespace of the element accordingly
        !           219:         */
        !           220:        String sNamespace = null;
        !           221:        String sElementName = null;
        !           222:        Element newElement = null;
        !           223:        int i = name.indexOf (':');
        !           224:        if (i > 0) {
        !           225:            String sPrefix = name.substring (0, i);
        !           226:            sNamespace = namespace (sPrefix);
        !           227:            sElementName = name.substring (i+1);
        !           228:        } else {
        !           229:            sNamespace = namespace ("xmlns");
        !           230:            sElementName = name;
        !           231:        }
        !           232: 
        !           233:        /**
        !           234:         * Finally look for attributes other than the special xmlns,
        !           235:         * expand them, and place to the new AttributeListImpl
        !           236:         */
        !           237:        for (int x = 0; x < iLength; x++) {
        !           238:            String sAttributeNamespace = null;
        !           239:            String aName = al.getName (x);
        !           240:            if (!aName.startsWith ("xmlns")) {
        !           241:                String aValue = al.getValue (aName);
        !           242:                String aType = al.getType (aName);
        !           243: 
        !           244:                int iIndex = aName.indexOf (':');
        !           245:                if (iIndex > 0) {
        !           246:                    String sPrefix = aName.substring (0, iIndex);
        !           247:                    sAttributeNamespace = namespace (sPrefix);
        !           248:                    aName = aName.substring (iIndex+1);
        !           249:                } else {
        !           250:                    if (sNamespace == null)
        !           251:                        sAttributeNamespace = namespace ("xmlns");
        !           252:                    else 
        !           253:                        sAttributeNamespace = sNamespace;
        !           254:                }
        !           255:                newAL.addAttribute (sAttributeNamespace+aName,
        !           256:                                    aType,
        !           257:                                    aValue);
        !           258:            }
        !           259:        }
        !           260: 
        !           261:        newElement = new Element (sNamespace + sElementName,
        !           262:                                  newAL);
        !           263:        checkAttributes (newElement);
        !           264: 
        !           265:        /**
        !           266:         * Update the containment hierarchy
        !           267:         * with the stack.
        !           268:         */
        !           269:        if (!m_elementStack.empty()) {
        !           270:            Element e = (Element)m_elementStack.peek ();
        !           271:            e.addChild (newElement);
1.7       jsaarela  272:        }
1.10    ! jsaarela  273: 
        !           274:        /**
        !           275:         * Place the new element into the stack
        !           276:         */
        !           277:        m_elementStack.push (newElement);
        !           278:     }
        !           279: 
        !           280:     public void endElement (String name) {
        !           281:        m_root = (Element)m_elementStack.pop ();
        !           282:        m_namespaceStack.pop ();
1.7       jsaarela  283:     }
                    284: 
1.10    ! jsaarela  285:     public void characters (char ch[], int start, int length)
        !           286:        throws SAXException {
        !           287:        /**
        !           288:         * Place all characters as Data instance to the containment
        !           289:         * hierarchy with the help of the stack.
        !           290:         */
        !           291:        Element e = (Element)m_elementStack.peek ();
        !           292:        String s = new String (ch, start, length+start);
        !           293: 
        !           294:        /**
        !           295:         * Warning: this is not correct procedure according to XML spec.
        !           296:         * All whitespace matters!
        !           297:         */
        !           298:        String sTrimmed = s.trim();
        !           299:        if (sTrimmed.length() > 0)
        !           300:            e.addChild (new Data (s));
        !           301:     }
        !           302: 
        !           303:     public void ignorableWhitespace (char ch[], int start, int length) {
        !           304:     }
        !           305: 
        !           306:     public void processingInstruction (String target, String data) {
1.1       jsaarela  307:     }
                    308: 
                    309:     /**
1.10    ! jsaarela  310:      * Report all warnings, and continue parsing.
        !           311:      *
        !           312:      * @see org.xml.sax.ErrorHandler#warning
1.1       jsaarela  313:      */
1.10    ! jsaarela  314:     public void warning (SAXParseException exception)
        !           315:     {
        !           316:        m_sErrorMsg = "Warning: " +
        !           317:            exception.getMessage() +
        !           318:            " (" +
        !           319:            //    exception.getSystemId() +
        !           320: 
        !           321:            "line <a href=\"#" +
        !           322:            exception.getLineNumber() +
        !           323:            "\">" +
        !           324:            exception.getLineNumber() +
        !           325:            "</a>, column " +
        !           326:            exception.getColumnNumber() +
        !           327:            ")<br>";
        !           328:     }
1.1       jsaarela  329: 
                    330: 
                    331:     /**
1.10    ! jsaarela  332:      * Report all recoverable errors, and try to continue parsing.
        !           333:      *
        !           334:      * @see org.xml.sax.ErrorHandler#error
1.1       jsaarela  335:      */
1.10    ! jsaarela  336:     public void error (SAXParseException exception)
        !           337:     {
        !           338:        m_sErrorMsg = "Recoverable Error: " +
        !           339:            exception.getMessage() +
        !           340:            " (" +
        !           341:            //    exception.getSystemId() +
        !           342:          
        !           343:            "line <a href=\"#" +
        !           344:            exception.getLineNumber() +
        !           345:            "\">" +
        !           346:            exception.getLineNumber() +
        !           347:            "</a>, column " +
        !           348:            exception.getColumnNumber() +
        !           349:            ")<br>";
        !           350:     }
        !           351: 
1.1       jsaarela  352: 
                    353:     /**
1.10    ! jsaarela  354:      * Report all fatal errors, and try to continue parsing.
        !           355:      *
        !           356:      * <p>Note: results are no longer reliable once a fatal error has
        !           357:      * been reported.</p>
        !           358:      *
        !           359:      * @see org.xml.sax.ErrorHandler#fatalError
1.1       jsaarela  360:      */
1.10    ! jsaarela  361:     public void fatalError (SAXParseException exception)
        !           362:     {
        !           363:        m_sErrorMsg = "Fatal Error: " +
        !           364:            exception.getMessage() +
        !           365:            " (" +
        !           366:            //    exception.getSystemId() +
        !           367:            "line <a href=\"#" +
        !           368:            exception.getLineNumber() +
        !           369:            "\">" +
        !           370:            exception.getLineNumber() +
        !           371:            "</a>, column " +
        !           372:            exception.getColumnNumber() +
        !           373:            ")<br>";
        !           374:     }
1.1       jsaarela  375: 
1.10    ! jsaarela  376:     public String errors () {
1.1       jsaarela  377:        return m_sErrorMsg;
1.10    ! jsaarela  378:     }
1.1       jsaarela  379: 
1.10    ! jsaarela  380:     public void addError (String sMsg) {
1.2       jsaarela  381:        m_sErrorMsg += sMsg;
1.6       jsaarela  382:        m_sErrorMsg += "<br>\n";
1.10    ! jsaarela  383:     }
1.2       jsaarela  384: 
1.10    ! jsaarela  385:     public static Parser createParser (String className) {
        !           386:        Parser parser = null;
        !           387: 
        !           388:        try {
        !           389:            // Get the named class.
        !           390:            Class c = Class.forName(className);
        !           391:            // Instantiate the parser.
        !           392:            parser = (Parser)(c.newInstance());
        !           393:        } catch (ClassNotFoundException e) {
        !           394:            System.err.println("SAX parser class " + className +
        !           395:                               "cannot be loaded.");
        !           396:            System.exit(1);
        !           397:        } catch (IllegalAccessException e) {
        !           398:            System.err.println("SAX parser class " + className +
        !           399:                               " does not have a zero-argument constructor.");
        !           400:            System.exit(1);
        !           401:        } catch (InstantiationException e) {
        !           402:            System.err.println("SAX parser class " + className +
        !           403:                               " cannot be instantiated.");
        !           404:            System.exit(1);
        !           405:        }
        !           406: 
        !           407:        // Check the the parser object
        !           408:        // actually implements the Parser interface.
        !           409:        if (!(parser instanceof org.xml.sax.Parser)) {
        !           410:            System.err.println("Class " + className +
        !           411:                               " does not implement org.xml.sax.Parser.");
        !           412:            System.exit(1);
        !           413:        }
        !           414: 
        !           415:        return parser;
        !           416:     }
1.1       jsaarela  417: 
                    418:     /**
1.10    ! jsaarela  419:      * If a URL is relative, make it absolute against the current directory.
1.1       jsaarela  420:      */
1.10    ! jsaarela  421:     private static String makeAbsoluteURL (String url)
        !           422:        throws java.net.MalformedURLException {
        !           423:        URL baseURL;
        !           424: 
        !           425:        String currentDirectory = System.getProperty("user.dir");
        !           426:        String fileSep = System.getProperty("file.separator");
        !           427:        String file = currentDirectory.replace(fileSep.charAt(0), '/') + '/';
        !           428: 
        !           429:        if (file.charAt(0) != '/') {
        !           430:            file = "/" + file;
        !           431:        }
        !           432:        baseURL = new URL("file", null, file);
        !           433: 
        !           434:        return new URL(baseURL, url).toString();
        !           435:     }
1.1       jsaarela  436: 
                    437: 
                    438:     /**
1.10    ! jsaarela  439:      * Escape special characters for display.
1.1       jsaarela  440:      */
1.10    ! jsaarela  441:     private static String escapeCharacters(char ch[], int start, int length) {
        !           442:        StringBuffer out = new StringBuffer();
1.1       jsaarela  443: 
1.10    ! jsaarela  444:        for (int i = start; i < start+length; i++) {
        !           445:            if (ch[i] >= 0x20 && ch[i] < 0x7f) {
        !           446:                out.append(ch[i]);
        !           447:            } else {
        !           448:                out.append("&#" + (int)ch[i] + ';');
1.1       jsaarela  449:            }
                    450:        }
1.10    ! jsaarela  451: 
        !           452:        return out.toString();
1.1       jsaarela  453:     }
                    454: 
                    455:     /**
1.10    ! jsaarela  456:      * Start processing an RDF/XML document instance
1.1       jsaarela  457:      */
1.10    ! jsaarela  458:     void processRDF (Element rdf) throws SAXException {
        !           459:        resolve ();
1.1       jsaarela  460: 
1.10    ! jsaarela  461:        /**
        !           462:         * RDF leaves it optional to use the RDF root element
        !           463:         * -> process only one description block
        !           464:         */
        !           465:        if (isDescription (rdf)) {
        !           466:            processDescription (rdf, false, false, true);
        !           467:            return;
        !           468:        }
1.1       jsaarela  469: 
1.10    ! jsaarela  470:        Enumeration e = rdf.children();
1.1       jsaarela  471:        while (e.hasMoreElements()) {
1.10    ! jsaarela  472:            Element ele = (Element)e.nextElement();
1.1       jsaarela  473: 
1.10    ! jsaarela  474:            if (isDescription (ele)) {
        !           475:                processDescription (ele, false, false, true);
        !           476:            } else if (isContainer (ele)) {
        !           477:                processContainer (ele);
        !           478:            } else if (isTypedProperty (ele)) {
        !           479:                processTypedNode (ele);
1.1       jsaarela  480:            }
                    481:        }
                    482:     }
                    483: 
                    484:     /**
1.10    ! jsaarela  485:      * Manage the production 6.12 in the spec
1.1       jsaarela  486:      */
1.10    ! jsaarela  487:     public String processTypedNode (Element typedNode) throws SAXException {
        !           488:        String sID = typedNode.getAttribute (RDFSCHEMA, "ID");
        !           489:        String sBagID = typedNode.getAttribute (RDFSCHEMA, "bagID");
        !           490:        String sAbout = typedNode.getAttribute (RDFSCHEMA, "about");
        !           491:        String sAboutEach = typedNode.getAttribute (RDFSCHEMA, "aboutEach");
        !           492:        String sAboutEachPrefix = typedNode.getAttribute (RDFSCHEMA, "aboutEachPrefix");
1.1       jsaarela  493: 
1.10    ! jsaarela  494:        if (typedNode.getAttribute (RDFSCHEMA, "resource") != null) {
        !           495:            addError ("'resource' attribute not allowed for a typedNode "+typedNode.name());
        !           496:        }
        !           497:        /**
        !           498:         * We are going to manage this typedNode using the processDescription
        !           499:         * routine later on. Before that, place all properties encoded as
        !           500:         * attributes to separate child nodes.
        !           501:         */
        !           502:        Enumeration e = typedNode.attributes ();
        !           503:        while (e.hasMoreElements()) {
        !           504:            String sAttribute = (String)e.nextElement();
        !           505:            String sValue = typedNode.getAttribute (sAttribute);
        !           506:            sValue = sValue.trim ();
        !           507: 
        !           508:            if (!sAttribute.startsWith (RDFSCHEMA) &&
        !           509:                !sAttribute.startsWith (XMLSCHEMA)) {
        !           510:                if (sValue.length() > 0) {
        !           511:                    Element newProperty = new Element (sAttribute,
        !           512:                                                       new AttributeListImpl ());
        !           513:                    newProperty.addAttribute (RDFSCHEMA + "ID", sID);
        !           514:                    newProperty.addAttribute (RDFSCHEMA + "bagID", sBagID);
        !           515:                    Data newData = new Data (sValue);
        !           516:                    newProperty.addChild (newData);
        !           517:                    typedNode.addChild (newProperty);
        !           518:                    typedNode.removeAttribute (sAttribute);
1.1       jsaarela  519:                }
                    520:            }
                    521:        }
                    522: 
1.10    ! jsaarela  523:        String sObject = new String ();
        !           524:        if (sID != null)
        !           525:            sObject = sID;
        !           526:        else
        !           527:            sObject = newReificationID();
        !           528: 
        !           529:        typedNode.ID (sObject);
1.1       jsaarela  530: 
1.10    ! jsaarela  531:        // special case: should the typedNode have aboutEach attribute,
        !           532:        // the instanceOf property should distribute to pointed
        !           533:        // collection also -> create a child node to the typedNode
        !           534:        Enumeration eTargets = typedNode.targets ();
        !           535:        if (sAboutEach != null &&
        !           536:            eTargets.hasMoreElements()) {
        !           537:            Element newProperty = new Element (RDFSCHEMA + "type",
        !           538:                                               new AttributeListImpl());
        !           539:            Data newData = new Data (typedNode.name());
        !           540:            newProperty.addChild (newData);
        !           541:            typedNode.addChild (newProperty);
        !           542:        } else {
        !           543:            addTriple (RDFSCHEMA + "type",
        !           544:                       sObject,
        !           545:                       typedNode.name());
        !           546:        }
1.1       jsaarela  547: 
1.10    ! jsaarela  548:        String sDesc = processDescription (typedNode, false, false, true);
1.1       jsaarela  549: 
1.10    ! jsaarela  550:        return sObject;
1.1       jsaarela  551:     }
                    552: 
1.7       jsaarela  553:     /**
1.10    ! jsaarela  554:      * processDescription takes the following parameters
        !           555:      *
        !           556:      * @param description      The Description element itself
        !           557:      * @param inProperty       A flag to tell whether this is a nested description
        !           558:      inside a property.
        !           559:      * @param reificate        Do we need to reificate
        !           560:      * @param createBag   Do we create a bag collection out of nested properties
        !           561:      *
        !           562:      * @return         An ID for the description
1.7       jsaarela  563:      */
1.10    ! jsaarela  564:     private String processDescription (Element description,
        !           565:                                       boolean inProperty,
        !           566:                                       boolean reificate,
        !           567:                                       boolean createBag) throws SAXException {
        !           568:        /**
        !           569:         * Return immediately if the description has already been managed
        !           570:         */
        !           571:        if (description.done())
        !           572:            return description.ID();
        !           573: 
        !           574:        int     iChildCount = 1;
        !           575:        boolean bOnce = true;
        !           576: 
        !           577:        /**
        !           578:         * Determine first all relevant values
        !           579:         */
        !           580:        String sAbout = description.getAttribute (RDFSCHEMA, "about");
        !           581:        String sAboutEach = description.getAttribute (RDFSCHEMA, "aboutEach");
        !           582:        String sAboutEachPrefix = description.getAttribute (RDFSCHEMA, "aboutEachPrefix");
        !           583:        String sBagid = description.getAttribute (RDFSCHEMA, "bagID");
        !           584:        String sID = description.getAttribute (RDFSCHEMA, "ID");
        !           585:        Element target = description.target();
        !           586: 
        !           587:        boolean hasTarget = description.targets().hasMoreElements();
        !           588:        boolean targetIsContainer = false;
        !           589:        String sTargetAbout = null;
        !           590:        String sTargetBagid = null;
        !           591:        String sTargetID = null;
1.7       jsaarela  592: 
1.10    ! jsaarela  593:        /**
        !           594:         * Determine what the target of the Description reference is
        !           595:         */
        !           596:        if (hasTarget) {
        !           597:            sTargetAbout = target.getAttribute (RDFSCHEMA, "about");
        !           598:            sTargetBagid = target.getAttribute (RDFSCHEMA, "bagID");
        !           599:            sTargetID = target.getAttribute (RDFSCHEMA, "ID");
        !           600: 
        !           601:            /**
        !           602:             * Target is collection if
        !           603:             * 1. it is identified with bagID attribute
        !           604:             * 2. it is identified with ID attribute and is a collection
        !           605:             */
        !           606:            if (sTargetBagid != null) {
        !           607:                targetIsContainer = (sAbout.substring(1).equals (sTargetBagid));
1.5       jsaarela  608:            } else {
1.10    ! jsaarela  609:                if (sTargetID != null &&
        !           610:                    sAbout.substring(1).equals (sTargetID) &&
        !           611:                    isContainer (target)) {
        !           612:                    targetIsContainer = true;
        !           613:                }
1.5       jsaarela  614:            }
1.10    ! jsaarela  615:        }
        !           616: 
        !           617: 
        !           618:        /**
        !           619:         * Check if there are properties encoded using the abbreviated
        !           620:         * syntax
        !           621:         */
        !           622:        expandAttributes (description, description);
        !           623: 
        !           624:        /**
        !           625:         * Manage the aboutEach attribute here
        !           626:         */
        !           627:        if (sAboutEach != null) {
        !           628:            if (hasTarget) {
        !           629:                Enumeration e = target.children ();
        !           630:                while (e.hasMoreElements()) {
        !           631:                    Element ele = (Element)e.nextElement ();
        !           632:                
        !           633:                    String sResource = ele.getAttribute (RDFSCHEMA, "resource");
        !           634:                    Element newDescription = null;
        !           635:                    if (sResource != null) {
        !           636:                        newDescription = new Element (RDFSCHEMA + "Description",
        !           637:                                                      new AttributeListImpl ());
        !           638:                        newDescription.addAttribute (RDFSCHEMA + "about", sResource);
        !           639:                    }
        !           640:                    Enumeration e2 = description.children();
        !           641:                    while (e2.hasMoreElements()) {
        !           642:                        Element ele2 = (Element)e2.nextElement ();
        !           643:                        if (newDescription != null) {
        !           644:                            newDescription.addChild (ele2);
        !           645:                        }
        !           646:                    }
        !           647:                    if (newDescription != null)
        !           648:                        processDescription (newDescription, false, false, false);
        !           649:                }
1.5       jsaarela  650:            }
1.10    ! jsaarela  651:            return null;
1.5       jsaarela  652:        }
                    653: 
1.10    ! jsaarela  654:        /**
        !           655:         * Manage the aboutEachPrefix attribute here
        !           656:         */
        !           657:        if (sAboutEachPrefix != null) {
        !           658:            if (hasTarget) {
        !           659:                Enumeration e = description.targets();
        !           660:                while (e.hasMoreElements()) {
        !           661:                    target = (Element)e.nextElement ();
        !           662:                    sTargetAbout = target.getAttribute (RDFSCHEMA, "about");
        !           663:                    Element newDescription = new Element (RDFSCHEMA + "Description",
        !           664:                                                          new AttributeListImpl ());
        !           665:                    newDescription.addAttribute (RDFSCHEMA + "about", sTargetAbout);
        !           666:                
        !           667:                    Enumeration e2 = description.children();
        !           668:                    while (e2.hasMoreElements()) {
        !           669:                        Element ele2 = (Element)e2.nextElement ();
        !           670:                        newDescription.addChild (ele2);
        !           671:                    }
        !           672:                    processDescription (newDescription, false, false, false);
        !           673:                }
        !           674:            }
        !           675:            return null;
1.1       jsaarela  676:        }
                    677: 
1.10    ! jsaarela  678:        /**
        !           679:         * Enumerate through the children
        !           680:         */
        !           681:        Enumeration e = description.children();
        !           682: 
        !           683:        while (e.hasMoreElements()) {
        !           684:            Element n = (Element)e.nextElement();
        !           685: 
        !           686:            if (isDescription (n)) {
        !           687:                addError ("Cannot nest Description inside Description");
        !           688:            } else if (isListItem (n)) {
        !           689:                addError ("Cannot nest Listitem inside Description");
        !           690:            } else if (isContainer (n)) {
        !           691:                addError ("Cannot nest container inside Description");
        !           692:            } else if (n instanceof Element) {
        !           693: 
        !           694:                String sChildID = null;
        !           695: 
        !           696:                if (hasTarget && targetIsContainer) {
        !           697:                    sChildID = processProperty (n, description,
        !           698:                                                (target.bagID() != null ? target.bagID() : target.ID()),
        !           699:                                                false);
        !           700:                    description.ID (sChildID);
        !           701:                    createBag = false;
        !           702:                } else if (hasTarget) {
        !           703:                    sChildID = processProperty (n, description,
        !           704:                                                sTargetAbout, reificate);
        !           705:                } else if (!hasTarget && !inProperty) {
        !           706:                    if (description.ID() == null) {
        !           707:                        description.ID (newReificationID());
        !           708:                    }
        !           709:                    if (sAbout == null)
        !           710:                        if (sID != null)
        !           711:                            sAbout = sID;
        !           712:                        else
        !           713:                            sAbout = description.ID();
        !           714:                    sChildID = processProperty (n, description,
        !           715:                                                ( sAbout != null ? sAbout : sID),
        !           716:                                                createBag);
        !           717:                } else if (!hasTarget && inProperty) {
        !           718:                    if (sAbout == null) {
        !           719:                        if (sID != null) {
        !           720:                            description.ID (sID);
        !           721:                            sAbout = sID;
        !           722:                        } else {
        !           723:                            if (description.ID() == null)
        !           724:                                description.ID (newReificationID());
        !           725:                            sAbout = description.ID();
        !           726:                        }
        !           727:                    } else {
        !           728:                        description.ID (sAbout);
        !           729:                    }
        !           730:                    sChildID = processProperty (n, description,
        !           731:                                                sAbout,
        !           732:                                                false);
        !           733:                }
1.1       jsaarela  734: 
1.10    ! jsaarela  735:                /**
        !           736:                 * Each Description block creates also a Bag node which
        !           737:                 * has links to all properties within the block.
        !           738:                 */
        !           739:                if (createBag) {
        !           740:                    String sNamespace = RDFSCHEMA;
        !           741:                    if (bOnce) {
        !           742:                        bOnce = false;
        !           743:                        if (description.bagID() == null)
        !           744:                            description.bagID (newReificationID());
        !           745:                        if (description.ID() == null)
        !           746:                            description.ID (description.bagID());
        !           747: 
        !           748:                        addTriple (sNamespace + "type",
        !           749:                                   description.bagID(),
        !           750:                                   sNamespace + "Bag");
        !           751:                    }
        !           752:                    if (sChildID != null) {
        !           753:                        addTriple (sNamespace + "_" + iChildCount,
        !           754:                                   description.bagID(),
        !           755:                                   sChildID);
        !           756:                        iChildCount++;
        !           757:                    }
        !           758:                }
        !           759:            }
1.1       jsaarela  760:        }
1.10    ! jsaarela  761: 
        !           762:        description.done (true);
        !           763: 
        !           764:        return description.ID();
1.1       jsaarela  765:     }
                    766: 
1.6       jsaarela  767:     /**
1.10    ! jsaarela  768:      * processProperty handles all elements not defined as special
        !           769:      * RDF elements.
        !           770:      *
        !           771:      * @param property The Property element itself
        !           772:      * @param description      The Description element in which this property appears
        !           773:      * @param sTarget  The target resource
        !           774:      * @param reificate        Should this property be reificated
        !           775:      *
        !           776:      * @return the new ID which can be used to identify the property
1.6       jsaarela  777:      */
1.10    ! jsaarela  778:     private String processProperty (Element property,
        !           779:                                    Element description,
        !           780:                                    String sTarget,
        !           781:                                    boolean reificate) throws SAXException {
        !           782:        String sPropertyID = null;
1.1       jsaarela  783: 
1.10    ! jsaarela  784:        /**
        !           785:         * Do the same trick as with Description blocks:
        !           786:         * if the Property uses abbreviated syntax, transform
        !           787:         * the structure into corresponding full tree representation
        !           788:         * which is handled correctly by the code for the non-abbreviated
        !           789:         * syntax.
        !           790:         */
1.1       jsaarela  791: 
1.10    ! jsaarela  792:        String sResource = property.getAttribute (RDFSCHEMA, "resource");
        !           793:        String sAbout = property.getAttribute (RDFSCHEMA, "about");
1.1       jsaarela  794: 
1.10    ! jsaarela  795:        Element d = new Element (RDFSCHEMA + "Description",
        !           796:                                 new AttributeListImpl());
1.1       jsaarela  797: 
1.10    ! jsaarela  798:        /**
        !           799:         * Tricky part: use the resource attribute to name
        !           800:         * the intermediate Description block
        !           801:         */
        !           802:        if (sResource != null) {
        !           803:            d.addAttribute (RDFSCHEMA + "about", sResource);
1.1       jsaarela  804:        }
                    805: 
                    806:        /**
1.10    ! jsaarela  807:         * If we found properties and attributes and generated the subtree,
        !           808:         * attach it to the property itself and let the code below take
        !           809:         * care of the rest.
1.1       jsaarela  810:         */
1.10    ! jsaarela  811:        if (expandAttributes (d, property)) {
        !           812:            property.addChild (d);
        !           813:        }
1.1       jsaarela  814: 
1.10    ! jsaarela  815:        /**
        !           816:         * Tricky part 2: if the resource attribute is present for a property
        !           817:         * AND there are no children, the value of the property is either
        !           818:         * 1. the URI in the resource attribute OR
        !           819:         * 2. the node ID of the resolved #resource attribute
        !           820:         */
        !           821:        if (sResource != null && !property.children().hasMoreElements()) {
        !           822:            if (property.target() == null) {
        !           823:                if (reificate) {
        !           824:                    sPropertyID = reificate (property.name(),
        !           825:                                             sTarget,
        !           826:                                             sResource,
        !           827:                                             property.ID());
        !           828:                    property.ID (sPropertyID);
        !           829:                } else {
        !           830:                    addTriple (property.name(),
        !           831:                               sTarget,
        !           832:                               sResource);
        !           833:                }
        !           834:            } else {
        !           835:                if (reificate) {
        !           836:                    sPropertyID = reificate (property.name(),
        !           837:                                             sTarget,
        !           838:                                             property.target().ID(),
        !           839:                                             property.ID());
        !           840:                    property.ID (sPropertyID);
        !           841:                } else {
        !           842:                    addTriple (property.name(),
        !           843:                               sTarget,
        !           844:                               property.target().ID());
        !           845:                }
        !           846:            }
        !           847:            return property.ID();
        !           848:        }
1.1       jsaarela  849: 
                    850:        /**
1.10    ! jsaarela  851:         * Does this property make a reference somewhere using the
        !           852:         * <i>resource</i> attribute
1.1       jsaarela  853:         */
1.10    ! jsaarela  854:        if (sResource != null && property.target() != null) {
        !           855:            sPropertyID = processDescription (property.target(),
        !           856:                                              true, false, false);
1.1       jsaarela  857:            if (reificate) {
1.10    ! jsaarela  858:                sPropertyID = reificate (property.name(),
        !           859:                                         sTarget,
        !           860:                                         sPropertyID,
        !           861:                                         property.ID());
1.1       jsaarela  862:                property.ID (sPropertyID);
                    863:            } else {
1.10    ! jsaarela  864:                addTriple (property.name(),
        !           865:                           sTarget,
        !           866:                           sPropertyID);
1.1       jsaarela  867:            }
1.10    ! jsaarela  868: 
        !           869:            return sPropertyID;
        !           870:        }
        !           871: 
        !           872:        /**
        !           873:         * Is the value of the attribute given as a URI in the
        !           874:         * about attribute?
        !           875:         */
        !           876:        if (sAbout != null) {
1.1       jsaarela  877:            if (reificate) {
1.10    ! jsaarela  878:                sPropertyID = reificate (property.name(),
1.4       jsaarela  879:                                         sTarget,
1.10    ! jsaarela  880:                                         sAbout,
        !           881:                                         property.ID());
1.1       jsaarela  882:                property.ID (sPropertyID);
                    883:            } else {
1.10    ! jsaarela  884:                addTriple (property.name(),
        !           885:                           sTarget,
        !           886:                           sAbout);
        !           887:            }
        !           888:        }
        !           889: 
        !           890:        /**
        !           891:         * Before looping through the children, let's check
        !           892:         * is there are any. If not, the value of the property is an anonymous node
        !           893:         */
        !           894:        Enumeration e2 = property.children();
        !           895:        if (!(e2.hasMoreElements())) {
        !           896:            if (reificate) {
        !           897:                sPropertyID = reificate (property.name(),
        !           898:                                         sTarget,
        !           899:                                         newReificationID(),
        !           900:                                         property.ID());
        !           901:            } else {
        !           902:                addTriple (property.name(),
        !           903:                           sTarget,
        !           904:                           newReificationID());
        !           905:            }
        !           906:        }
        !           907:        while (e2.hasMoreElements()) {
        !           908:            Element n2 = (Element)e2.nextElement();
        !           909: 
        !           910:            if (isDescription (n2)) {
        !           911:                Element d2 = n2;
        !           912: 
        !           913:                sPropertyID = processDescription (d2, true, false, false);
        !           914: 
        !           915:                d2.ID (sPropertyID);
        !           916: 
        !           917:                if (reificate) {
        !           918:                    sPropertyID = reificate (property.name(),
        !           919:                                             sTarget,
        !           920:                                             sPropertyID,
        !           921:                                             property.ID());
        !           922:                } else {
        !           923:                    addTriple (property.name(),
        !           924:                               sTarget, sPropertyID);
        !           925:                }
        !           926: 
        !           927:            } else if (n2 instanceof Data) {
        !           928:                /**
        !           929:                 * We've got real data
        !           930:                 */
        !           931:                String sValue = ((Data)n2).data();
        !           932: 
        !           933:                /**
        !           934:                 * Only if the content is not empty PCDATA (whitespace that is),
        !           935:                 * print the triple
        !           936:                 */
        !           937:                sValue = sValue.trim();
        !           938:                if (sValue.length() > 0) {
        !           939:                    if (reificate) {
        !           940:                        sPropertyID = reificate (property.name(),
        !           941:                                                 sTarget,
        !           942:                                                 sValue,
        !           943:                                                 property.ID());
        !           944:                        property.ID (sPropertyID);
        !           945:                    } else {
        !           946:                        addTriple (property.name(),
        !           947:                                   sTarget,
        !           948:                                   sValue);
        !           949:                    }
        !           950:                }
        !           951:            } else if (isContainer (n2)) {
        !           952: 
        !           953:                String sCollectionID = processContainer (n2);
        !           954:                sPropertyID = sCollectionID;
        !           955: 
        !           956:                /**
        !           957:                 * Attach the collection to the current Property
        !           958:                 */
        !           959:                if (description.target() != null) {
        !           960:                    if (reificate) {
        !           961:                        sPropertyID = reificate (property.name(),
        !           962:                                                 description.target().getAttribute (RDFSCHEMA, "about"),
        !           963:                                                 sCollectionID,
        !           964:                                                 property.ID());
        !           965:                        property.ID (sPropertyID);
        !           966:                    } else {
        !           967:                        addTriple (property.name(),
        !           968:                                   description.target().getAttribute (RDFSCHEMA, "about"),
        !           969:                                   sCollectionID);
        !           970:                    }
        !           971:                } else {
        !           972:                    if (reificate) {
        !           973:                        sPropertyID = reificate (property.name(),
        !           974:                                                 sTarget,
        !           975:                                                 sCollectionID,
        !           976:                                                 property.ID());
        !           977:                        property.ID (sPropertyID);
        !           978:                    } else {
        !           979:                        addTriple (property.name(),
        !           980:                                   sTarget,
        !           981:                                   sCollectionID);
        !           982:                    }
        !           983:                }
        !           984:            } else if (isTypedProperty (n2)) {
        !           985:                sPropertyID = processTypedNode (n2);
        !           986:                addTriple (property.name(),
1.5       jsaarela  987:                           sTarget,
1.10    ! jsaarela  988:                           sPropertyID);
1.1       jsaarela  989:            }
                    990:        }
1.10    ! jsaarela  991: 
        !           992:        return sPropertyID;
1.1       jsaarela  993:     }
                    994: 
1.10    ! jsaarela  995:     private String processContainer (Element n) throws SAXException {
        !           996:        String sID = n.ID();
        !           997:        if (sID == null)
        !           998:            sID = newReificationID();
1.1       jsaarela  999: 
1.10    ! jsaarela 1000:        /**
        !          1001:         * Do the instantiation only once
        !          1002:         */
        !          1003:        if (!n.done()) {
        !          1004:            String sNamespace = RDFSCHEMA;
        !          1005:            if (isSequence (n)) {
        !          1006:                addTriple (sNamespace+"type",
        !          1007:                           sID,
        !          1008:                           sNamespace+"Seq");
        !          1009:            } else if (isAlternative (n)) {
        !          1010:                addTriple (sNamespace+"type",
        !          1011:                           sID,
        !          1012:                           sNamespace+"Alt");
        !          1013:            } else if (isBag (n)) {
        !          1014:                addTriple (sNamespace+"type",
        !          1015:                           sID,
        !          1016:                           sNamespace+"Bag");
        !          1017:            }
        !          1018:            n.done (true);
        !          1019:        }
        !          1020: 
        !          1021:        expandAttributes (n, n);
1.1       jsaarela 1022: 
1.10    ! jsaarela 1023:        Enumeration e = ((Element)n).children();
        !          1024: 
        !          1025:        if (!e.hasMoreElements() &&
        !          1026:            isAlternative (n)) {
        !          1027:            addError ("An RDF:Alt container must have at least one listitem");
        !          1028:        }
        !          1029: 
        !          1030:        int iCounter = 1;
        !          1031:        while (e.hasMoreElements()) {
        !          1032:            Element n2 = (Element)e.nextElement();
        !          1033:            if (isListItem (n2)) {
        !          1034:                processListItem (sID, n2, iCounter);
        !          1035:                iCounter++;
        !          1036:            } else {
        !          1037:                addError ("Cannot nest "+n2.name()+" inside container");
        !          1038:            }
        !          1039:        }
        !          1040: 
        !          1041:        return sID;
        !          1042:     }
        !          1043: 
        !          1044:     private void processListItem (String sID, Element listitem, int iCounter)
        !          1045:        throws SAXException {
        !          1046:        /**
        !          1047:         * Two different cases for
        !          1048:         * 1. LI element without content (resource available)
        !          1049:         * 2. LI element with content (resource unavailable)
        !          1050:         */
        !          1051:        String sResource = listitem.getAttribute (RDFSCHEMA, "resource");
        !          1052:        if (sResource != null) {
        !          1053:            addTriple (RDFSCHEMA+"_"+iCounter,
1.1       jsaarela 1054:                       sID,
1.10    ! jsaarela 1055:                       sResource);
        !          1056:            // validity checking
        !          1057:            if (listitem.children().hasMoreElements()) {
        !          1058:                addError ("Listitem with 'resource' attribute cannot have child nodes");
        !          1059:            }
        !          1060:        } else {
        !          1061:            Enumeration e = listitem.children();
        !          1062:            while (e.hasMoreElements()) {
        !          1063:                Element n = (Element)e.nextElement();
        !          1064:                if (n instanceof Data) {
        !          1065:                    addTriple (RDFSCHEMA+"_"+iCounter,
        !          1066:                               sID,
        !          1067:                               ((Data)n).data());
        !          1068:                } else if (isDescription (n)) {
        !          1069:                    String sNodeID = processDescription (n, false, false, false);
        !          1070:                    addTriple (RDFSCHEMA+"_"+iCounter,
        !          1071:                               sID,
        !          1072:                               sNodeID);
        !          1073:                } else if (isListItem (n)) {
        !          1074:                    addError ("Cannot nest listitem inside listitem");
        !          1075:                } else if (isTypedProperty (n)) {
        !          1076:                    String sNodeID = processTypedNode (n);
        !          1077:                    addTriple (RDFSCHEMA+"_"+iCounter,
        !          1078:                               sID,
        !          1079:                               sNodeID);
        !          1080:                }
        !          1081:            }
1.1       jsaarela 1082:        }
                   1083:     }
                   1084: 
1.10    ! jsaarela 1085:     private void checkAttributes (Element e) {
        !          1086:        String sResource = e.getAttribute (RDFSCHEMA, "resource");
        !          1087:        if (sResource != null &&
        !          1088:            sResource.startsWith("#")) {
        !          1089:            resolveLater (e);
        !          1090:        }
        !          1091:        String sAboutEach = e.getAttribute (RDFSCHEMA, "aboutEach");
        !          1092:        if (sAboutEach != null &&
        !          1093:            sAboutEach.startsWith("#")) {
        !          1094:            resolveLater (e);
        !          1095:        }
        !          1096:        String sAboutEachPrefix = e.getAttribute (RDFSCHEMA, "aboutEachPrefix");
        !          1097:        if (sAboutEachPrefix != null) {
        !          1098:            resolveLater (e);
        !          1099:        }
1.8       jsaarela 1100: 
1.10    ! jsaarela 1101:        String sAbout = e.getAttribute (RDFSCHEMA, "about");
        !          1102:        if (sAbout != null) {
        !          1103:            if (sAbout.startsWith("#")) {
        !          1104:                resolveLater (e);
        !          1105:            } else {
        !          1106:                registerResource (e);
        !          1107:            }
        !          1108:        }
        !          1109: 
        !          1110:        String sBagID = e.getAttribute (RDFSCHEMA, "bagID");
        !          1111:        if (sBagID != null) {
        !          1112:            registerID (sBagID, e);
        !          1113:            e.bagID (sBagID);
        !          1114:        }
1.6       jsaarela 1115: 
1.10    ! jsaarela 1116:        String sID = e.getAttribute (RDFSCHEMA, "ID");
        !          1117:        if (sID != null) {
        !          1118:            registerID (sID, e);
        !          1119:            e.ID (sID); // default value
        !          1120:        }
1.1       jsaarela 1121: 
1.10    ! jsaarela 1122:        if (sID != null && sAbout != null) {
        !          1123:            addError ("'ID' and 'about' attribute may not appear within the same Description block");
1.1       jsaarela 1124:        }
                   1125:     }
                   1126: 
1.10    ! jsaarela 1127:     private boolean expandAttributes (Element parent, Element ele)
        !          1128:        throws SAXException {
        !          1129:        boolean foundAbbreviation = false;
        !          1130:        Enumeration e = ele.attributes ();
        !          1131:        while (e.hasMoreElements()) {
        !          1132:            String sAttribute = (String)e.nextElement();
        !          1133:            String sValue = ele.getAttribute (sAttribute).trim();
        !          1134: 
        !          1135:            if (sAttribute.startsWith (XMLSCHEMA))
        !          1136:                continue;
        !          1137:            if (sAttribute.startsWith (RDFSCHEMA) && 
        !          1138:                !sAttribute.endsWith ("value"))
        !          1139:                continue;
1.8       jsaarela 1140:            if (sValue.length() > 0) {
                   1141:                foundAbbreviation = true;
1.10    ! jsaarela 1142:                Element newElement = new Element (sAttribute,
        !          1143:                                                  new AttributeListImpl());
1.8       jsaarela 1144:                Data newData = new Data (sValue);
                   1145:                newElement.addChild (newData);
                   1146:                parent.addChild (newElement);
                   1147:            }
                   1148:        }
1.10    ! jsaarela 1149:        return foundAbbreviation;
        !          1150:     }
        !          1151: 
        !          1152:     /**
        !          1153:      * reificate creates one new node and four new triples
        !          1154:      * and returns the ID of the new node
        !          1155:      */
        !          1156:     private String reificate (String sProperty,
        !          1157:                              String sPropertyObject,
        !          1158:                              String sPropertyValue,
        !          1159:                              String sNodeID) {
        !          1160:        String sNamespace = RDFSCHEMA;
        !          1161:        if (sNodeID == null)
        !          1162:            sNodeID = newReificationID();
        !          1163: 
        !          1164:        /**
        !          1165:         * The original property must remain in the data model
        !          1166:         */
        !          1167:        addTriple (sProperty, sPropertyObject, sPropertyValue);
        !          1168: 
        !          1169:        /**
        !          1170:         * Do not reificate reificated properties
        !          1171:         */
        !          1172: 
        !          1173:        if (sProperty.equals (sNamespace+"propObj") ||
        !          1174:            sProperty.equals (sNamespace+"propName") ||
        !          1175:            sProperty.equals (sNamespace+"value") ||
        !          1176:            sProperty.equals (sNamespace+"type")) {
        !          1177:            return null;
        !          1178:        }
        !          1179: 
        !          1180:        /**
        !          1181:         * Reificate by creating 4 new triples
        !          1182:         */
        !          1183: 
        !          1184:        addTriple (sNamespace + "propName",
        !          1185:                   sNodeID,
        !          1186:                   sProperty);
        !          1187: 
        !          1188:        addTriple (sNamespace + "propObj",
        !          1189:                   sNodeID,
        !          1190:                   sPropertyObject);
        !          1191: 
        !          1192:        addTriple (sNamespace + "value",
        !          1193:                   sNodeID,
        !          1194:                   sPropertyValue);
        !          1195: 
        !          1196:        addTriple (sNamespace + "type",
        !          1197:                   sNodeID,
        !          1198:                   sNamespace + "Property");
        !          1199: 
        !          1200:        return sNodeID;
        !          1201:     }
        !          1202: 
        !          1203:     private void addTriple (String sProperty, String sPropertyObj, String sPropertyValue) {
        !          1204:        Triple t = new Triple (sProperty, sPropertyObj, sPropertyValue);
        !          1205:        m_triples.addElement (t);
        !          1206:     }
        !          1207: 
        !          1208:     public void printTriples (PrintStream ps) {
        !          1209:        for (int x = 0; x < m_triples.size(); x++) {
        !          1210:            Triple t = (Triple)m_triples.elementAt (x);
        !          1211:            ps.println ("triple(\""+t.property()+"\",\""+t.object()+"\",\""+t.value()+"\").");
        !          1212:        }
        !          1213:     }
        !          1214: 
        !          1215:     public Enumeration triples () {
        !          1216:        return m_triples.elements ();
        !          1217:     }
        !          1218: 
        !          1219:     /**
        !          1220:      * Helper functions to identify different elements
        !          1221:      */
        !          1222:     public boolean isDescription (Element e) {
        !          1223:        return isRDF(e) &&
        !          1224:            e.name().endsWith ("Description");
        !          1225:     }
        !          1226: 
        !          1227:     public boolean isListItem (Element e) {
        !          1228:        return isRDF(e) &&
        !          1229:            ( e.name().endsWith ("li") ||
        !          1230:              e.name().indexOf ("_") > -1);
1.8       jsaarela 1231:     }
                   1232: 
1.10    ! jsaarela 1233:     public boolean isContainer (Element e) {
        !          1234:        return (isSequence (e) ||
        !          1235:                isAlternative (e) ||
        !          1236:                isBag (e));
        !          1237:     }
        !          1238: 
        !          1239:     public boolean isSequence (Element e) {
        !          1240:        return isRDF(e) &&
        !          1241:            e.name().endsWith ("Seq");
        !          1242:     }
        !          1243: 
        !          1244:     public boolean isAlternative (Element e) {
        !          1245:        return isRDF(e) &&
        !          1246:            e.name().endsWith ("Alt");
        !          1247:     }
        !          1248: 
        !          1249:     public boolean isBag (Element e) {
        !          1250:        return isRDF(e) &&
        !          1251:            e.name().endsWith ("Bag");
        !          1252:     }
        !          1253: 
        !          1254:     /**
        !          1255:      * This method matches all elements in practice
        !          1256:      */
        !          1257:     public boolean isTypedProperty (Element e) {
        !          1258:        if (e.name().length() > 0)
        !          1259:            return true;
        !          1260:        else
        !          1261:            return false;
        !          1262:     }
        !          1263: 
        !          1264:     public boolean isRDF (Element e) {
        !          1265:        return e.name().startsWith (RDFSCHEMA);
        !          1266:     }
        !          1267: 
        !          1268:     /**
        !          1269:      * Methods for node reference management
        !          1270:      */
        !          1271: 
        !          1272:     private Vector     m_vResources = new Vector ();
        !          1273:     private Vector     m_vResolveQueue = new Vector ();
        !          1274:     private Hashtable  m_hIDtable = new Hashtable ();
        !          1275:     private int                m_iReificationCounter = 0;
        !          1276: 
        !          1277:     public void resolveLater (Element e) {
        !          1278:        m_vResolveQueue.addElement (e);
        !          1279:     }
        !          1280: 
        !          1281:     public void resolve () {
        !          1282:        for (int x = 0; x < m_vResolveQueue.size(); x++) {
        !          1283:            Element e = (Element)m_vResolveQueue.elementAt(x);
        !          1284: 
        !          1285:            String sAbout = e.getAttribute (RDFSCHEMA, "about");
        !          1286:            if (sAbout != null) {
        !          1287:                if (sAbout.startsWith ("#"))
        !          1288:                    sAbout = sAbout.substring (1);
        !          1289:                Element e2 = (Element)lookforNode(sAbout);
        !          1290:                if (e2 != null) {
        !          1291:                    e.addTarget (e2);
        !          1292:                } else {
        !          1293:                    addError ("Unresolved internal reference to "+sAbout);
        !          1294:                }
        !          1295:            }
        !          1296: 
        !          1297:            String sResource = e.getAttribute (RDFSCHEMA, "resource");
        !          1298:            if (sResource != null) {
        !          1299:                if (sResource.startsWith ("#"))
        !          1300:                    sResource = sResource.substring (1);
        !          1301:                Element e2 = (Element)lookforNode(sResource);
        !          1302:                if (e2 != null) {
        !          1303:                    e.addTarget (e2);
        !          1304:                }       
        !          1305:            }
        !          1306: 
        !          1307:            String sAboutEach = e.getAttribute (RDFSCHEMA, "aboutEach");
        !          1308:            if (sAboutEach != null) {
        !          1309:                sAboutEach = sAboutEach.substring (1);
        !          1310:                Element e2 = (Element)lookforNode(sAboutEach);
        !          1311:                if (e2 != null) {
        !          1312:                    e.addTarget (e2);
        !          1313:                }       
        !          1314:            }
        !          1315: 
        !          1316:            String sAboutEachPrefix = e.getAttribute (RDFSCHEMA, "aboutEachPrefix");
        !          1317:            if (sAboutEachPrefix != null) {
        !          1318:                for (int y = 0; y < m_vResources.size(); y++) {
        !          1319:                    Element ele = (Element)m_vResources.elementAt(y);
        !          1320:                    String sA = ele.getAttribute (RDFSCHEMA, "about");
        !          1321:                    if (sA.startsWith (sAboutEachPrefix)) {
        !          1322:                        e.addTarget (ele);
        !          1323:                    }
        !          1324:                }
        !          1325:            }
        !          1326:        }
        !          1327:        m_vResolveQueue.removeAllElements();
        !          1328:     }
        !          1329: 
        !          1330:     public Element lookforNode (String sID) {
        !          1331:        if (sID == null)
        !          1332:            return null;
        !          1333:        else
        !          1334:            return (Element)m_hIDtable.get (sID);
        !          1335:     }
        !          1336: 
        !          1337:     public void registerID (String sID, Element e) {
        !          1338:        if (m_hIDtable.get (sID) != null)
        !          1339:            addError(sID+" ID already defined.");
        !          1340:        m_hIDtable.put (sID, e);
        !          1341:     }
        !          1342: 
        !          1343:     public String newReificationID () {
        !          1344:        m_iReificationCounter++;
        !          1345:        return  new String ("genid" + m_iReificationCounter);
        !          1346:     }
        !          1347: 
        !          1348:     public void registerResource (Element e) {
        !          1349:        m_vResources.addElement (e);
        !          1350:     }
1.1       jsaarela 1351: }

Webmaster