Source Code Cross Referenced for Unparser.java in  » RSS-RDF » Jena-2.5.5 » com » hp » hpl » jena » xmloutput » impl » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » RSS RDF » Jena 2.5.5 » com.hp.hpl.jena.xmloutput.impl 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         *  (c)     Copyright 2000, 2001, 2002, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
0003:         *   All rights reserved.
0004:         * [See end of file]
0005:         *  $Id: Unparser.java,v 1.45 2008/02/11 11:10:13 jeremy_carroll Exp $
0006:         */
0007:
0008:        package com.hp.hpl.jena.xmloutput.impl;
0009:
0010:        /*
0011:         * @author Jeremy Carroll
0012:         * 
0013:         * Want todo List - easy efficiency gains in listSubjects() and
0014:         * modelListSubjects() by removing those subjects that we have already
0015:         * considered.
0016:         *  - Set Default language during first pass.
0017:         * 
0018:         * 
0019:         * Notes on ID and BagID: Our preferences are follows: for a Stating with an
0020:         * explicit local ID we avoid explicitly constructing the reification, and try
0021:         * and use rule 6.12 with an idAttr. If the Stating is anonymous or non-local
0022:         * then we construct the reification explicitly.
0023:         * 
0024:         * 
0025:         * Notes: The following rules are not supported by the current Jena RDF parser:
0026:         * 6.8
0027:         * 
0028:         * 
0029:         * [6.1] RDF ::= ['<rdf:RDF>'] obj* ['</rdf:RDF>'] [6.2] obj ::= description |
0030:         * container [6.3] description ::= '<rdf:Description' idAboutAttr? bagIdAttr?
0031:         * propAttr* '/>' | '<rdf:Description' idAboutAttr? bagIdAttr? propAttr* '>'
0032:         * propertyElt* '</rdf:Description>' | typedNode [6.4] container ::= sequence |
0033:         * bag | alternative [6.5] idAboutAttr ::= idAttr | aboutAttr | aboutEachAttr
0034:         * [6.6] idAttr ::= ' ID="' IDsymbol '"' [6.7] aboutAttr ::= ' about="'
0035:         * URI-reference '"' [6.8] aboutEachAttr ::= ' aboutEach="' URI-reference '"' | '
0036:         * aboutEachPrefix="' string '"' [6.9] bagIdAttr ::= ' bagID="' IDsymbol '"'
0037:         * [6.10] propAttr ::= typeAttr | propName '="' string '"' (with embedded quotes
0038:         * escaped) [6.11] typeAttr ::= ' type="' URI-reference '"' [6.12] propertyElt
0039:         * ::= '<' propName idAttr? '>' value '</' propName '>' | '<' propName
0040:         * idAttr? parseLiteral '>' literal '</' propName '>' | '<' propName idAttr?
0041:         * parseResource '>' propertyElt* '</' propName '>' | '<' propName idRefAttr?
0042:         * bagIdAttr? propAttr* '/>'
0043:         * 
0044:         * [daml.1 - 6.12 cont.] | '<' propName idAttr? parseDamlCollection '>' obj* '</'
0045:         * propName '>' [daml.2] parseDamlCollection ::= ' parseType="daml:collection"'
0046:         * 
0047:         * [6.13] typedNode ::= '<' typeName idAboutAttr? bagIdAttr? propAttr* '/>' | '<'
0048:         * typeName idAboutAttr? bagIdAttr? propAttr* '>' propertyElt* '</' typeName
0049:         * '>' [6.14] propName ::= Qname [6.15] typeName ::= Qname [6.16] idRefAttr ::=
0050:         * idAttr | resourceAttr [6.17] value ::= obj | string [6.18] resourceAttr ::= '
0051:         * resource="' URI-reference '"' [6.19] Qname ::= [ NSprefix ':' ] name [6.20]
0052:         * URI-reference ::= string, interpreted per [URI] [6.21] IDsymbol ::= (any
0053:         * legal XML name symbol) [6.22] name ::= (any legal XML name symbol) [6.23]
0054:         * NSprefix ::= (any legal XML namespace prefix) [6.24] string ::= (any XML
0055:         * text, with "<", ">", and "&" escaped) [6.25] sequence ::= '<rdf:Seq'
0056:         * idAttr? '>' member* '</rdf:Seq>' | '<rdf:Seq' idAttr? memberAttr* '/>'
0057:         * [6.26] bag ::= '<rdf:Bag' idAttr? '>' member* '</rdf:Bag>' | '<rdf:Bag'
0058:         * idAttr? memberAttr* '/>' [6.27] alternative ::= '<rdf:Alt' idAttr? '>'
0059:         * member+ '</rdf:Alt>' | '<rdf:Alt' idAttr? memberAttr? '/>' [6.28] member
0060:         * ::= referencedItem | inlineItem [6.29] referencedItem ::= '<rdf:li'
0061:         * resourceAttr '/>' [6.30] inlineItem ::= '<rdf:li' '>' value </rdf:li>' | '<rdf:li'
0062:         * parseLiteral '>' literal </rdf:li>' | '<rdf:li' parseResource '>'
0063:         * propertyElt* </rdf:li>' [6.31] memberAttr ::= ' rdf:_n="' string '"' (where n
0064:         * is an integer) [6.32] parseLiteral ::= ' parseType="Literal"' [6.33]
0065:         * parseResource ::= ' parseType="Resource"' [6.34] literal ::= (any well-formed
0066:         * XML)
0067:         * 
0068:         */
0069:        import java.io.PrintWriter;
0070:        import java.util.*;
0071:
0072:        import org.apache.commons.logging.*;
0073:        import org.apache.xerces.util.XMLChar;
0074:
0075:        import com.hp.hpl.jena.iri.IRI;
0076:        import com.hp.hpl.jena.rdf.model.*;
0077:        import com.hp.hpl.jena.rdf.model.impl.*;
0078:        import com.hp.hpl.jena.shared.*;
0079:        import com.hp.hpl.jena.util.iterator.*;
0080:        import com.hp.hpl.jena.vocabulary.*;
0081:
0082:        /**
0083:         * An Unparser will output a model in the abbreviated syntax. *
0084:         * 
0085:         * @version Release='$Name:  $' Revision='$Revision: 1.45 $' Date='$Date:
0086:         *          2005/07/13 15:33:51 $'
0087:         * 
0088:         */
0089:        class Unparser {
0090:            static private Property LI = new PropertyImpl(RDF.getURI(), "li");
0091:
0092:            static private Property DESCRIPTION = new PropertyImpl(
0093:                    RDF.getURI(), "Description");
0094:
0095:            static protected Log logger = LogFactory.getLog(Unparser.class);
0096:
0097:            /**
0098:             * Creates an Unparser for the specified model. The localName is the URI
0099:             * (typical URL) intended for the output file. No trailing "#" should be
0100:             * used. This will control the use of <I>ID</I> or <I>about</I> or
0101:             * <I>resource</I> on various rules.
0102:             * 
0103:             * @param localName
0104:             *            The intended URI of the output file. No trailing "#".
0105:             * @param m
0106:             *            The model.
0107:             * @param w
0108:             *            The output.
0109:             */
0110:            Unparser(Abbreviated parent, String localName, Model m,
0111:                    PrintWriter w) {
0112:                setLocalName(localName);
0113:                prettyWriter = parent;
0114:                out = w;
0115:                model = m;
0116:                addTypeNameSpaces();
0117:                objectTable = new HashMap();
0118:                StmtIterator ss = m.listStatements();
0119:                try {
0120:                    while (ss.hasNext()) {
0121:                        Statement s = ss.nextStatement();
0122:                        RDFNode rn = s.getObject();
0123:                        if (rn instanceof  Resource) {
0124:                            increaseObjectCount((Resource) rn);
0125:                        }
0126:                    }
0127:                } finally {
0128:                    ss.close();
0129:                }
0130:                try {
0131:                    res2statement = new HashMap();
0132:                    statement2res = new HashMap();
0133:                    ClosableIterator reified = new MapFilterIterator(
0134:                            new MapFilter() {
0135:                                public Object accept(Object o) {
0136:                                    Resource r = (Resource) o;
0137:                                    return (r.hasProperty(RDF.subject)
0138:                                            && r.hasProperty(RDF.object) && r
0139:                                            .hasProperty(RDF.predicate)) ? r
0140:                                            : null;
0141:
0142:                                }
0143:                            }, model.listResourcesWithProperty(RDF.type,
0144:                                    RDF.Statement));
0145:                    while (reified.hasNext()) {
0146:                        Resource r = (Resource) reified.next();
0147:                        try {
0148:                            /**
0149:                             * This block of code assumes that really we are dealing
0150:                             * with a reification. We may, on the contrary, be dealing
0151:                             * with a random collection of triples that do not make
0152:                             * sense.
0153:                             */
0154:                            Statement subj = r.getRequiredProperty(RDF.subject);
0155:                            Statement pred = r
0156:                                    .getRequiredProperty(RDF.predicate);
0157:                            Statement obj = r.getRequiredProperty(RDF.object);
0158:                            RDFNode nobj = obj.getObject();
0159:                            Resource rsubj = (Resource) subj.getObject();
0160:                            Resource rpred = (Resource) pred.getObject();
0161:
0162:                            Property ppred = model.createProperty(rpred
0163:                                    .getURI());
0164:
0165:                            Statement statement = model.createStatement(rsubj,
0166:                                    ppred, nobj);
0167:                            res2statement.put(r, statement);
0168:                            statement2res.put(statement, r);
0169:                        } catch (Exception ignored) {
0170:                        }
0171:                    }
0172:                } finally {
0173:                    ss.close();
0174:                }
0175:            }
0176:
0177:            /**
0178:             * Note: must work with uri being null.
0179:             */
0180:            private void setLocalName(String uri) {
0181:                if (uri == null || uri.equals(""))
0182:                    localName = "";
0183:                else
0184:                //            try 
0185:                {
0186:                    IRI u = BaseXMLWriter.factory.create(uri);
0187:                    u = u.create("");
0188:                    localName = u.toString();
0189:                }
0190:                //        catch (MalformedURIException e) {
0191:                //                throw new BadURIException(uri, e);
0192:                //            }
0193:            }
0194:
0195:            /**
0196:             * Should be called exactly once for each Unparser. Calling it a second time
0197:             * will have undesired results.
0198:             */
0199:            void write() {
0200:                prettyWriter.workOutNamespaces();
0201:                wRDF();
0202:                /*
0203:                 * System.out.print("Coverage = "); for (int i=0;i<codeCoverage.length;i++)
0204:                 * System.out.print(" c[" + i + "] = " + codeCoverage[i]+ ";");
0205:                 * System.out.println();
0206:                 */
0207:            }
0208:
0209:            /**
0210:             * Set a list of types of objects that will be expanded at the top-level of
0211:             * the file.
0212:             * 
0213:             * @param types
0214:             *            An array of rdf:Class'es.
0215:             * 
0216:             */
0217:            void setTopLevelTypes(Resource types[]) {
0218:                pleasingTypes = types;
0219:                pleasingTypeSet = new HashSet(Arrays.asList(types));
0220:            }
0221:
0222:            private String xmlBase;
0223:
0224:            void setXMLBase(String b) {
0225:                xmlBase = b;
0226:            }
0227:
0228:            /*
0229:             * THE MORE INTERESTING MEMBER VARIABLES. Note there are others scattered
0230:             * throughout the file, but those are only used by one or two methods.
0231:             */
0232:
0233:            final private static String rdfns = RDF.type.getNameSpace();
0234:
0235:            final private static Integer one = new Integer(1);
0236:
0237:            private String localName;
0238:
0239:            private Map objectTable; // This is a map from Resource to Integer
0240:
0241:            // which indicates how many times each resource
0242:            // occurs as an object of a triple.
0243:            private Model model;
0244:
0245:            private PrintWriter out;
0246:
0247:            private Set doing = new HashSet(); // Some of the resources that
0248:
0249:            // are currently being written.
0250:            private Set doneSet = new HashSet(); // The triples that have been
0251:            // output.
0252:
0253:            private Set haveReified = new HashSet(); // Those local resources that
0254:            // are
0255:
0256:            // the id's of a reification, used to ensure that anonymous
0257:            // resources are made non-anonymous when reified in certain ways.
0258:
0259:            private Resource pleasingTypes[] = null;
0260:
0261:            private Set pleasingTypeSet = new HashSet();
0262:
0263:            final private Abbreviated prettyWriter;
0264:
0265:            private boolean avoidExplicitReification = true;
0266:
0267:            // We set this to false as we start giving up on elegance.
0268:
0269:            // Reification stuff.
0270:
0271:            Map res2statement;
0272:
0273:            Map statement2res;
0274:
0275:            /*
0276:             * The top-down recursive descent unparser. The methods starting in w all
0277:             * refer to one of the rules of the grammar, which they implement. boolean
0278:             * valued rules first check whether they are applicable and return false if
0279:             * not. Otherwise they create appropriate output (using recursive descent)
0280:             * and return true. Note all necessary checks are made before any output or
0281:             * any recursive descent. The void w- methods just implement the rule, which
0282:             * typically does not involve any choice.
0283:             */
0284:            /*
0285:             * [6.1] RDF ::= ['<rdf:RDF>'] obj* ['</rdf:RDF>']
0286:             */
0287:            private void wRDF() {
0288:                tab();
0289:                print("<");
0290:                print(prettyWriter.rdfEl("RDF"));
0291:                indentPlus();
0292:                printNameSpaceDefn();
0293:                if (xmlBase != null) {
0294:                    setLocalName(xmlBase);
0295:                    tab();
0296:                    print("xml:base=" + quote(xmlBase));
0297:                }
0298:                print(">");
0299:                wObjStar();
0300:                indentMinus();
0301:                tab();
0302:                print("</");
0303:                print(prettyWriter.rdfEl("RDF"));
0304:                print(">");
0305:                tab();
0306:            }
0307:
0308:            /**
0309:             * All subjects get listed, for top level use only.
0310:             */
0311:            private void wObjStar() {
0312:                Iterator rs = listSubjects();
0313:                while (rs.hasNext()) {
0314:                    Resource r = (Resource) rs.next();
0315:                    increaseObjectCount(r);
0316:                    // This forces us to not be anonymous unless
0317:                    // we are never an object. See isGenuineAnon().
0318:                    wObj(r, true);
0319:                }
0320:                closeAllResIterators();
0321:            }
0322:
0323:            /*
0324:             * [6.12] propertyElt ::= '<' propName idAttr? '>' value '</' propName '>' | '<'
0325:             * propName idAttr? parseLiteral '>' literal '</' propName '>' | '<'
0326:             * propName idAttr? parseResource '>' propertyElt* '</' propName '>' | '<'
0327:             * propName idRefAttr? bagIdAttr? propAttr* '/>' [daml.1 - 6.12 cont.] | '<'
0328:             * propName idAttr? parseDamlCollection '>' obj* '</' propName '>' [daml.2]
0329:             * parseDamlCollection ::= ' parseType="daml:collection"'
0330:             * 
0331:             * For daml collections we prefer the special syntax otherwise: We prefer
0332:             * choice 4 where possible, except in the case where the statement is
0333:             * reified and the object is not anonymous in which case we use one of the
0334:             * others (e.g. choice 1). For embedded XML choice 2 is obligatory. For
0335:             * untyped, anonymous resource valued items choice 3 is used. Choice 1 is
0336:             * the fall back.
0337:             */
0338:            private boolean wPropertyElt(WType wt, Property prop, Statement s,
0339:                    RDFNode val) {
0340:                return wPropertyEltCompact(wt, prop, s, val)
0341:                        || // choice 4
0342:                        wPropertyEltDamlCollection(wt, prop, s, val)
0343:                        || // choice daml.1
0344:                        wPropertyEltLiteral(wt, prop, s, val)
0345:                        || // choice 2
0346:                        wPropertyEltResource(wt, prop, s, val)
0347:                        || // choice 3
0348:                        wPropertyEltDatatype(wt, prop, s, val)
0349:                        || wPropertyEltValue(wt, prop, s, val);
0350:                // choice 1.
0351:            }
0352:
0353:            /*
0354:             * [6.12.4] propertyElt ::= '<' propName idRefAttr? bagIdAttr? propAttr*
0355:             * '/>'
0356:             */
0357:            private boolean wPropertyEltCompact(WType wt, Property prop,
0358:                    Statement s, RDFNode val) {
0359:                // Conditions
0360:                if (!(val instanceof  Resource))
0361:                    return false;
0362:                Resource r = (Resource) val;
0363:                if (!(allPropsAreAttr(r) || doing.contains(r)))
0364:                    return false;
0365:                // '<' propName '/>' is 6.12.1 rather than 6.12.4
0366:                // and it becomes an empty string value.
0367:                // Whether this is a mistake or not is debatable.
0368:                // We avoid the construction.
0369:                if ((!hasProperties(r)) && isGenuineAnon(r))
0370:                    return false;
0371:                // Write out
0372:                done(s);
0373:                tab();
0374:                print("<");
0375:                wt.wTypeStart(prop);
0376:                indentPlus();
0377:                wIdRefAttrOpt(s, r);
0378:                if (!doing.contains(r)) {
0379:                    wPropAttrAll(r);
0380:                } else if (isGenuineAnon(r)) {
0381:                    // ???
0382:                    error("Genuine anon resource in cycle?");
0383:                }
0384:                indentMinus();
0385:                print("/>");
0386:                return true;
0387:            }
0388:
0389:            /*
0390:             * [6.12.2] propertyElt ::= '<' propName idAttr? parseLiteral '>' literal '</'
0391:             * propName '>'
0392:             */
0393:            private boolean wPropertyEltLiteral(WType wt, Property prop,
0394:                    Statement s, RDFNode r) {
0395:                if (prettyWriter.sParseTypeLiteralPropertyElt)
0396:                    return false;
0397:                if (!((r instanceof  Literal) && ((Literal) r).isWellFormedXML())) {
0398:                    return false;
0399:                }
0400:                // print out.
0401:                done(s);
0402:                tab();
0403:                print("<");
0404:                wt.wTypeStart(prop);
0405:                wIdAttrReified(s);
0406:                maybeNewline();
0407:                wParseLiteral();
0408:                maybeNewline();
0409:                print(">");
0410:                print(((Literal) r).getLexicalForm());
0411:                print("</");
0412:                wt.wTypeEnd(prop);
0413:                print(">");
0414:                return true;
0415:            }
0416:
0417:            private boolean wPropertyEltDatatype(WType wt, Property prop,
0418:                    Statement s, RDFNode r) {
0419:                if (!((r instanceof  Literal) && ((Literal) r).getDatatypeURI() != null)) {
0420:                    return false;
0421:                }
0422:                // print out.
0423:                done(s);
0424:                tab();
0425:                print("<");
0426:                wt.wTypeStart(prop);
0427:                wIdAttrReified(s);
0428:                maybeNewline();
0429:                wDatatype(((Literal) r).getDatatypeURI());
0430:                maybeNewline();
0431:                print(">");
0432:                print(Util.substituteEntitiesInElementContent(((Literal) r)
0433:                        .getLexicalForm()));
0434:                print("</");
0435:                wt.wTypeEnd(prop);
0436:                print(">");
0437:                return true;
0438:            }
0439:
0440:            /*
0441:             * [6.12.3] propertyElt ::= '<' propName idAttr? parseResource '>'
0442:             * propertyElt* '</' propName '>'
0443:             */
0444:            private boolean wPropertyEltResource(WType wt, Property prop,
0445:                    Statement s, RDFNode r) {
0446:                if (prettyWriter.sParseTypeResourcePropertyElt)
0447:                    return false;
0448:                if (r instanceof  Literal)
0449:                    return false;
0450:                Resource res = (Resource) r;
0451:                if (!isGenuineAnon(res))
0452:                    return false;
0453:                if (getType(res) != null)
0454:                    return false; // preferred typed node construction.
0455:                // print out.
0456:                done(s);
0457:                tab();
0458:                print("<");
0459:                wt.wTypeStart(prop);
0460:                indentPlus();
0461:                wIdAttrReified(s);
0462:                wParseResource();
0463:                print(">");
0464:                wPropertyEltStar(res);
0465:                indentMinus();
0466:                tab();
0467:                print("</");
0468:                wt.wTypeEnd(prop);
0469:                print(">");
0470:                return true;
0471:            }
0472:
0473:            /*
0474:             * [6.12] propertyElt ::= '<' propName idAttr? '>' value '</' propName '>'
0475:             */
0476:            private boolean wPropertyEltValue(WType wt, Property prop,
0477:                    Statement s, RDFNode r) {
0478:                return wPropertyEltValueString(wt, prop, s, r)
0479:                        || wPropertyEltValueObj(wt, prop, s, r);
0480:            }
0481:
0482:            /*
0483:             * [6.12] propertyElt ::= '<' propName idAttr? '>' value '</' propName '>'
0484:             */
0485:            private boolean wPropertyEltValueString(WType wt, Property prop,
0486:                    Statement s, RDFNode r) {
0487:                if (r instanceof  Literal) {
0488:                    done(s);
0489:                    Literal lt = (Literal) r;
0490:                    String lang = lt.getLanguage();
0491:                    tab();
0492:                    print("<");
0493:                    wt.wTypeStart(prop);
0494:                    wIdAttrReified(s);
0495:                    maybeNewline();
0496:                    if (lang != null && lang.length() > 0)
0497:                        print(" xml:lang=" + q(lang));
0498:                    maybeNewline();
0499:                    print(">");
0500:                    wValueString(lt);
0501:                    print("</");
0502:                    wt.wTypeEnd(prop);
0503:                    print(">");
0504:                    return true;
0505:                }
0506:                return false;
0507:
0508:            }
0509:
0510:            /*
0511:             * [6.17.2] value ::= string
0512:             */
0513:            private void wValueString(Literal lt) {
0514:                String val = lt.getString();
0515:                print(Util.substituteEntitiesInElementContent(val));
0516:            }
0517:
0518:            /*
0519:             * [6.12] propertyElt ::= '<' propName idAttr? '>' value '</' propName '>'
0520:             * [6.17.1] value ::= obj
0521:             */
0522:            private boolean wPropertyEltValueObj(WType wt, Property prop,
0523:                    Statement s, RDFNode r) {
0524:                if (r instanceof  Resource && !prettyWriter.sResourcePropertyElt) {
0525:                    Resource res = (Resource) r;
0526:                    done(s);
0527:                    tab();
0528:                    print("<");
0529:                    wt.wTypeStart(prop);
0530:                    wIdAttrReified(s);
0531:                    print(">");
0532:                    tab();
0533:                    indentPlus();
0534:                    wObj(res, false);
0535:                    indentMinus();
0536:                    tab();
0537:                    print("</");
0538:                    wt.wTypeEnd(prop);
0539:                    print(">");
0540:                    return true;
0541:                }
0542:
0543:                return false;
0544:
0545:            }
0546:
0547:            /*
0548:             * [daml.1 - 6.12 cont.] | '<' propName idAttr? parseDamlCollection '>'
0549:             * obj* '</' propName '>'
0550:             */
0551:            private boolean wPropertyEltDamlCollection(WType wt, Property prop,
0552:                    Statement s, RDFNode r) {
0553:                boolean daml = true;
0554:                Statement list[][] = getDamlList(r);
0555:                if (list == null) {
0556:                    daml = false;
0557:                    list = getRDFList(r);
0558:                }
0559:                if (list == null)
0560:                    return false;
0561:                // print out.
0562:                done(s);
0563:                // record all done's first - they may impact the
0564:                // way we print the values.
0565:                for (int i = 0; i < list.length; i++) {
0566:                    done(list[i][0]);
0567:                    done(list[i][1]);
0568:                    if (daml)
0569:                        done(list[i][2]);
0570:                }
0571:                tab();
0572:                print("<");
0573:                wt.wTypeStart(prop);
0574:                indentPlus();
0575:                wIdAttrReified(s);
0576:                if (daml)
0577:                    wParseDamlCollection();
0578:                else
0579:                    wParseCollection();
0580:
0581:                print(">");
0582:                for (int i = 0; i < list.length; i++) {
0583:                    wObj((Resource) list[i][0].getObject(), false);
0584:                }
0585:                indentMinus();
0586:                tab();
0587:                print("</");
0588:                wt.wTypeEnd(prop);
0589:                print(">");
0590:                return true;
0591:            }
0592:
0593:            // propAttr* with no left over statements.
0594:            private void wPropAttrAll(Resource r) {
0595:                wPropAttrSome(r);
0596:                if (hasProperties(r))
0597:                    error("Bad call to wPropAttrAll");
0598:            }
0599:
0600:            // propAttr* possibly with left over statements.
0601:            private void wPropAttrSome(Resource r) {
0602:                ClosableIterator ss = listProperties(r);
0603:                try {
0604:                    Set seen = new HashSet();
0605:                    while (ss.hasNext()) {
0606:                        Statement s = (Statement) ss.next();
0607:                        if (canBeAttribute(s, seen)) {
0608:                            done(s);
0609:                            wPropAttr(s.getPredicate(), s.getObject());
0610:                        }
0611:                    }
0612:                } finally {
0613:                    ss.close();
0614:                }
0615:            }
0616:
0617:            /*
0618:             * [6.2] obj ::= description | container [6.3] description ::= '<rdf:Description'
0619:             * idAboutAttr? bagIdAttr? propAttr* '/>' | '<rdf:Description' idAboutAttr?
0620:             * bagIdAttr? propAttr* '>' propertyElt* '</rdf:Description>' | typedNode
0621:             * [6.4] container ::= sequence | bag | alternative We use: [6.2a] obj ::=
0622:             * description | container | typedNode [6.3a] description ::= '<rdf:Description'
0623:             * idAboutAttr? bagIdAttr? propAttr* '/>' | '<rdf:Description' idAboutAttr?
0624:             * bagIdAttr? propAttr* '>' propertyElt* '</rdf:Description>'
0625:             * 
0626:             * This method has got somewhat messy. If we are not at the topLevel we may
0627:             * choose to not expand a node but just use a typedNode ::= '<' typeName
0628:             * idAboutAttr '/>' rule. This rules also applies to Bags that we feel
0629:             * unconfortable with, such as a Bag arising from a BagId rule that we don't
0630:             * handle properly.
0631:             * 
0632:             * 
0633:             */
0634:            private boolean wObj(Resource r, boolean topLevel) {
0635:                try {
0636:                    doing.add(r);
0637:                    Statement typeStatement = getType(r);
0638:                    if (typeStatement != null) {
0639:                        Resource t = typeStatement.getResource();
0640:                        if (!topLevel) {
0641:                            if (pleasingTypeSet.contains(t)
0642:                                    && (!isGenuineAnon(r))) {
0643:                                return wTypedNodeNoProperties(r);
0644:                            }
0645:                        }
0646:                        return wTypedNode(r) || wDescription(r);
0647:                    }
0648:                    return wDescription(r);
0649:                } finally {
0650:                    doing.remove(r);
0651:                }
0652:            }
0653:
0654:            abstract private class WType {
0655:                abstract void wTypeStart(Resource uri);
0656:
0657:                abstract void wTypeEnd(Resource uri);
0658:            }
0659:
0660:            static private int RDF_HASH = RDF.getURI().length();
0661:
0662:            private WType wdesc = new WType() {
0663:                void wTypeStart(Resource u) {
0664:                    print(prettyWriter.rdfEl(u.getURI().substring(RDF_HASH)));
0665:                }
0666:
0667:                void wTypeEnd(Resource u) {
0668:                    print(prettyWriter.rdfEl(u.getURI().substring(RDF_HASH)));
0669:                }
0670:            };
0671:
0672:            private WType wtype = new WType() {
0673:                void wTypeStart(Resource u) {
0674:                    print(prettyWriter.startElementTag(u.getURI()));
0675:                }
0676:
0677:                void wTypeEnd(Resource u) {
0678:                    print(prettyWriter.endElementTag(u.getURI()));
0679:                }
0680:            };
0681:
0682:            /*
0683:             * [6.3a] description ::= '<rdf:Description' idAboutAttr? bagIdAttr?
0684:             * propAttr* '/>' | '<rdf:Description' idAboutAttr? bagIdAttr? propAttr*
0685:             * '>' propertyElt* '</rdf:Description>'
0686:             */
0687:            private boolean wDescription(Resource r) {
0688:                return wTypedNodeOrDescription(wdesc, DESCRIPTION, r);
0689:            }
0690:
0691:            /*
0692:             * [6.13] typedNode ::= '<' typeName idAboutAttr? bagIdAttr? propAttr* '/>' | '<'
0693:             * typeName idAboutAttr? bagIdAttr? propAttr* '>' propertyElt* '</'
0694:             * typeName '>'
0695:             */
0696:            private boolean wTypedNode(Resource r) {
0697:                Statement st = getType(r);
0698:                if (st == null)
0699:                    return false;
0700:                Resource type = st.getResource();
0701:                done(st);
0702:                return wTypedNodeOrDescription(wtype, type, r);
0703:            }
0704:
0705:            private boolean wTypedNodeOrDescription(WType wt, Resource ty,
0706:                    Resource r) {
0707:                // preparation - look for the li's.
0708:                Vector found = new Vector();
0709:                ClosableIterator ss = listProperties(r);
0710:                try {
0711:                    int greatest = 0;
0712:                    if (!prettyWriter.sListExpand)
0713:                        while (ss.hasNext()) {
0714:                            Statement s = (Statement) ss.next();
0715:                            int ix = s.getPredicate().getOrdinal();
0716:                            if (ix != 0) {
0717:                                if (ix > greatest) {
0718:                                    found.setSize(ix);
0719:                                    greatest = ix;
0720:                                }
0721:                                found.set(ix - 1, s);
0722:                            }
0723:                        }
0724:                } finally {
0725:                    ss.close();
0726:                }
0727:                int last = found.indexOf(null);
0728:                List li = last == -1 ? found : found.subList(0, last);
0729:
0730:                return wTypedNodeOrDescriptionCompact(wt, ty, r, li)
0731:                        || wTypedNodeOrDescriptionLong(wt, ty, r, li);
0732:            }
0733:
0734:            /*
0735:             * [6.13.1] typedNode ::= '<' typeName idAboutAttr? bagIdAttr? propAttr*
0736:             * '/>'
0737:             */
0738:            private boolean wTypedNodeOrDescriptionCompact(WType wt,
0739:                    Resource ty, Resource r, List li) {
0740:                // Conditions
0741:                if ((!li.isEmpty()) || !allPropsAreAttr(r))
0742:                    return false;
0743:                // Write out
0744:                tab();
0745:                print("<");
0746:                wt.wTypeStart(ty);
0747:                indentPlus();
0748:                wIdAboutAttrOpt(r);
0749:                wPropAttrAll(r);
0750:                print("/>");
0751:                indentMinus();
0752:                return true;
0753:            }
0754:
0755:            /*
0756:             * [6.13.1] typedNode ::= '<' typeName idAboutAttr '/>'
0757:             */
0758:            private boolean wTypedNodeNoProperties(Resource r) {
0759:                // Conditions
0760:                if (isGenuineAnon(r))
0761:                    return false;
0762:                Statement st = getType(r);
0763:                if (st == null)
0764:                    return false;
0765:                Resource type = st.getResource();
0766:                done(st);
0767:                // Write out
0768:                tab();
0769:                print("<");
0770:                wtype.wTypeStart(type);
0771:                indentPlus();
0772:                // if (hasProperties(r))
0773:                // wAboutAttr(r);
0774:                // else
0775:                wIdAboutAttrOpt(r);
0776:                print("/>");
0777:                indentMinus();
0778:                return true;
0779:            }
0780:
0781:            /*
0782:             * [6.13.2] typedNode ::= '<' typeName idAboutAttr? bagIdAttr? propAttr*
0783:             * '>' propertyElt* '</' typeName '>'
0784:             */
0785:            private boolean wTypedNodeOrDescriptionLong(WType wt, Resource ty,
0786:                    Resource r, List li) {
0787:                Iterator it = li.iterator();
0788:                while (it.hasNext()) {
0789:                    done((Statement) it.next());
0790:                }
0791:
0792:                tab();
0793:                print("<");
0794:                wt.wTypeStart(ty);
0795:                indentPlus();
0796:                wIdAboutAttrOpt(r);
0797:                wPropAttrSome(r);
0798:                print(">");
0799:                wLiEltStar(li.iterator());
0800:                wPropertyEltStar(r);
0801:                indentMinus();
0802:                tab();
0803:                print("</");
0804:                wt.wTypeEnd(ty);
0805:                print(">");
0806:                return true;
0807:            }
0808:
0809:            private void wPropertyEltStar(Resource r) {
0810:                ClosableIterator ss = this .listProperties(r);
0811:                try {
0812:                    while (ss.hasNext()) {
0813:                        Statement s = (Statement) ss.next();
0814:                        wPropertyElt(wtype, s.getPredicate(), s, s.getObject());
0815:                    }
0816:                } finally {
0817:                    ss.close();
0818:                }
0819:            }
0820:
0821:            private void wLiEltStar(Iterator ss) {
0822:                while (ss.hasNext()) {
0823:                    Statement s = (Statement) ss.next();
0824:                    wPropertyElt(wdesc, LI, s, s.getObject());
0825:                }
0826:            }
0827:
0828:            /*
0829:             * [6.5] idAboutAttr ::= idAttr | aboutAttr | aboutEachAttr we use [6.5a]
0830:             * idAboutAttr ::= idAttr | aboutAttr
0831:             */
0832:            private Set idDone = new HashSet();
0833:
0834:            private boolean wIdAboutAttrOpt(Resource r) {
0835:                return wIdAttrOpt(r) || wNodeIDAttr(r) || wAboutAttr(r);
0836:            }
0837:
0838:            /**
0839:             * Returns false if the resource is not genuinely anonymous and cannot be
0840:             * referred to using an ID. [6.6] idAttr ::= ' ID="' IDsymbol '"'
0841:             */
0842:            private boolean wIdAttrOpt(Resource r) {
0843:
0844:                if (isGenuineAnon(r))
0845:                    return true; // We have output resource (with nothing).
0846:                if (prettyWriter.sIdAttr)
0847:                    return false;
0848:                if (r.isAnon())
0849:                    return false;
0850:                if (isLocalReference(r)) {
0851:                    // Try and use the reification rules if they apply.
0852:                    // Issue: aren't we just about to list those statements explicitly.
0853:                    if (wantReification(r))
0854:                        return false;
0855:                    // Can be an ID if not already output.
0856:                    if (idDone.contains(r)) {
0857:                        return false; // We have already output this one.
0858:                    }
0859:
0860:                    idDone.add(r);
0861:                    print(" ");
0862:                    printRdfAt("ID");
0863:                    print("=");
0864:                    print(quote(getLocalName(r)));
0865:                    return true;
0866:
0867:                }
0868:                return false;
0869:
0870:            }
0871:
0872:            /*
0873:             * [6.7] aboutAttr ::= ' about="' URI-reference '"'
0874:             */
0875:            private boolean wAboutAttr(Resource r) {
0876:                print(" ");
0877:                printRdfAt("about");
0878:                print("=");
0879:                wURIreference(r);
0880:                return true;
0881:            }
0882:
0883:            private void wURIreference(String s) {
0884:                print(quote(prettyWriter.relativize(s)));
0885:            }
0886:
0887:            private void wURIreference(Resource r) {
0888:                wURIreference(r.getURI());
0889:            }
0890:
0891:            /*
0892:             * [6.16] idRefAttr ::= idAttr | resourceAttr
0893:             */
0894:            private void wIdRefAttrOpt(Statement s, Resource r) {
0895:                wIdAttrReified(s);
0896:                if (!isGenuineAnon(r)) {
0897:                    wResourceNodeIDAttr(r);
0898:                }
0899:            }
0900:
0901:            /*
0902:             * [6.6] idAttr ::= ' ID="' IDsymbol '"'
0903:             */
0904:            private void wIdAttrReified(Statement s) {
0905:                if (wantReification(s)) {
0906:                    /*
0907:                     * if ( prettyWriter.sReification ) System.err.println("???"); else
0908:                     * System.err.println("!!!");
0909:                     */
0910:                    Statement reify[] = reification(s);
0911:                    Resource res = (Resource) statement2res.get(s);
0912:                    idDone.add(res);
0913:                    int i;
0914:                    for (i = 0; i < reify.length; i++)
0915:                        done(reify[i]);
0916:                    print(" ");
0917:                    printRdfAt("ID");
0918:                    print("=");
0919:                    print(quote(getLocalName(res)));
0920:                    haveReified.add(res);
0921:                }
0922:            }
0923:
0924:            /*
0925:             * [6.18] resourceAttr ::= ' resource="' URI-reference '"'
0926:             */
0927:            private boolean wResourceNodeIDAttr(Resource r) {
0928:                return wNodeIDAttr(r) || wResourceAttr(r);
0929:            }
0930:
0931:            /*
0932:             * nodeIDAttr ::= ' rdf:nodeID="' URI-reference '"'
0933:             */
0934:            private boolean wNodeIDAttr(Resource r) {
0935:                if (!r.isAnon())
0936:                    return false;
0937:                print(" ");
0938:                printRdfAt("nodeID");
0939:                print("=");
0940:                print(q(prettyWriter.anonId(r)));
0941:
0942:                return true;
0943:            }
0944:
0945:            /*
0946:             * [6.18] resourceAttr ::= ' resource="' URI-reference '"'
0947:             */
0948:            private boolean wResourceAttr(Resource r) {
0949:                if (r.isAnon())
0950:                    return false;
0951:                print(" ");
0952:                printRdfAt("resource");
0953:                print("=");
0954:                wURIreference(r);
0955:                return true;
0956:            }
0957:
0958:            int codeCoverage[] = new int[8];
0959:
0960:            /*
0961:             * [6.19] Qname ::= [ NSprefix ':' ] name
0962:             * 
0963:             * private void wQnameStart(String ns, String local) {
0964:             * print(prettyWriter.startElementTag(ns, local)); }
0965:             * 
0966:             * private void wQnameEnd(String ns, String local) {
0967:             * print(prettyWriter.endElementTag(ns, local)); }
0968:             */
0969:            private void wQNameAttr(Property p) {
0970:                print(prettyWriter.attributeTag(p.getURI()));
0971:            }
0972:
0973:            private void printRdfAt(String s) {
0974:                print(prettyWriter.rdfAt(s));
0975:            }
0976:
0977:            /*
0978:             * [6.10] propAttr ::= typeAttr | propName '="' string '"' (with embedded
0979:             * quotes escaped) [6.11] typeAttr ::= ' type="' URI-reference '"'
0980:             */
0981:            private void wPropAttr(Property p, RDFNode n) {
0982:                tab();
0983:                if (p.equals(RDF.type))
0984:                    wTypeAttr((Resource) n);
0985:                else
0986:                    wPropAttrString(p, (Literal) n);
0987:            }
0988:
0989:            private void wTypeAttr(Resource r) {
0990:                print(" ");
0991:                printRdfAt("type");
0992:                print("=");
0993:                wURIreference(r);
0994:                // print(quote(r.getURI()));
0995:            }
0996:
0997:            private void wPropAttrString(Property p, Literal l) {
0998:                print(" ");
0999:                wQNameAttr(p);
1000:                print("=" + quote(l.getString()));
1001:            }
1002:
1003:            /*
1004:             * [daml.2] parseDamlCollection ::= ' parseType="daml:collection"'
1005:             */
1006:            private void wParseDamlCollection() {
1007:                print(" ");
1008:                printRdfAt("parseType");
1009:                print("=" + q("daml:collection"));
1010:            }
1011:
1012:            /*
1013:             * [List.2] parseCollection ::= ' parseType="Collection"'
1014:             */
1015:            private void wParseCollection() {
1016:                print(" ");
1017:                printRdfAt("parseType");
1018:                print("=" + q("Collection"));
1019:            }
1020:
1021:            /*
1022:             * [6.32] parseLiteral ::= ' parseType="Literal"'
1023:             */
1024:            private void wParseLiteral() {
1025:                print(" ");
1026:                printRdfAt("parseType");
1027:                print("=" + q("Literal"));
1028:            }
1029:
1030:            private void wDatatype(String dtURI) {
1031:                print(" ");
1032:                printRdfAt("datatype");
1033:                print("=");
1034:                maybeNewline();
1035:                wURIreference(dtURI);
1036:            }
1037:
1038:            /*
1039:             * [6.33] parseResource ::= ' parseType="Resource"'
1040:             */
1041:            private void wParseResource() {
1042:                print(" ");
1043:                printRdfAt("parseType");
1044:                print("=" + q("Resource"));
1045:            }
1046:
1047:            private void printNameSpaceDefn() {
1048:                print(prettyWriter.xmlnsDecl());
1049:            }
1050:
1051:            /***************************************************************************
1052:             * Utility routines ...
1053:             * 
1054:             **************************************************************************/
1055:
1056:            /***************************************************************************
1057:             * Output and indentation.
1058:             **************************************************************************/
1059:            private int indentLevel = 0;
1060:
1061:            private int currentColumn = 0;
1062:
1063:            static private String filler(int lgth) {
1064:                char rslt[] = new char[lgth];
1065:                Arrays.fill(rslt, ' ');
1066:                return new String(rslt);
1067:            }
1068:
1069:            private void tab() {
1070:                int desiredColumn = prettyWriter.tabSize * indentLevel;
1071:                if (desiredColumn > prettyWriter.width) {
1072:                    desiredColumn = 4 + (desiredColumn - 4)
1073:                            % prettyWriter.width;
1074:                }
1075:                if ((desiredColumn == 0 && currentColumn == 0)
1076:                        || desiredColumn > currentColumn) {
1077:                    String spaces = filler(desiredColumn - currentColumn);
1078:                    out.print(spaces);
1079:                } else {
1080:                    out.println();
1081:                    out.print(filler(desiredColumn));
1082:                }
1083:                currentColumn = desiredColumn;
1084:            }
1085:
1086:            private void maybeNewline() {
1087:                if (currentColumn > prettyWriter.width) {
1088:                    tab();
1089:                }
1090:            }
1091:
1092:            /**
1093:             * Quote str with either ' or " quotes to be in attribute position in XML.
1094:             * The real rules are found at http://www.w3.org/TR/REC-xml#AVNormalize
1095:             */
1096:            private String quote(String str) {
1097:                return prettyWriter.substitutedAttribute(str);
1098:            }
1099:
1100:            private String q(String str) {
1101:                return prettyWriter.attributeQuoted(str);
1102:            }
1103:
1104:            /**
1105:             * Indentation screws up if there is a tab character in s. We do not check
1106:             * this.
1107:             */
1108:            private void print(String s) {
1109:                out.print(s);
1110:                int ix = s.lastIndexOf('\n');
1111:                if (ix == -1)
1112:                    currentColumn += s.length();
1113:                else
1114:                    currentColumn = s.length() - ix - 1;
1115:            }
1116:
1117:            private void indentPlus() {
1118:                indentLevel++;
1119:            }
1120:
1121:            private void indentMinus() {
1122:                indentLevel--;
1123:            }
1124:
1125:            /*
1126:             * Unexpected error.
1127:             */
1128:            private void error(String msg) {
1129:                JenaException e = new BrokenException(
1130:                        "Internal error in Unparser: " + msg);
1131:                this .prettyWriter.fatalError(e);
1132:                throw e; // Just in case.
1133:            }
1134:
1135:            /**
1136:             * Name space stuff.
1137:             */
1138:            private void addTypeNameSpaces() {
1139:                NodeIterator nn = model.listObjectsOfProperty(RDF.type);
1140:                try {
1141:                    while (nn.hasNext()) {
1142:                        RDFNode obj = nn.nextNode();
1143:                        int split = isOKType(obj);
1144:                        if (split != -1)
1145:                            prettyWriter.addNameSpace(((Resource) obj).getURI()
1146:                                    .substring(0, split));
1147:                    }
1148:                } finally {
1149:                    nn.close();
1150:                }
1151:            }
1152:
1153:            private String getNameSpace(Resource r) {
1154:                if (r.isAnon()) {
1155:                    logger
1156:                            .error("Internal error - Unparser.getNameSpace; giving up");
1157:                    throw new BrokenException(
1158:                            "Internal error: getNameSpace(bNode)");
1159:                }
1160:                String uri = r.getURI();
1161:                int split = Util.splitNamespace(uri);
1162:                return uri.substring(0, split);
1163:
1164:            }
1165:
1166:            /**
1167:             * Local and/or anonymous resources.
1168:             */
1169:            private boolean isGenuineAnon(Resource r) {
1170:                if (!r.isAnon())
1171:                    return false;
1172:                Integer v = (Integer) objectTable.get(r);
1173:                return v == null
1174:                        || ((!prettyWriter.sResourcePropertyElt)
1175:                                && v.intValue() <= 1 && (!haveReified
1176:                                .contains(r)));
1177:            }
1178:
1179:            private boolean isLocalReference(Resource r) {
1180:                return (!r.isAnon()) && getNameSpace(r).equals(localName + "#")
1181:                        && XMLChar.isValidNCName(getLocalName(r));
1182:            }
1183:
1184:            /*
1185:             * Utility for turning an integer into an alphabetic string.
1186:             * 
1187:             * private static String getSuffix(int suffixId) { if (suffixId == 0) return
1188:             * ""; else { suffixId--; int more = (suffixId / 26);
1189:             * 
1190:             * return getSuffix(more) + new Character((char) ('a' + suffixId % 26)); } }
1191:             */
1192:
1193:            private String getLocalName(Resource r) {
1194:                if (r.isAnon()) {
1195:                    logger
1196:                            .error("Internal error - giving up - Unparser.getLocalName");
1197:                    throw new BrokenException(
1198:                            "Internal error: getLocalName(bNode)");
1199:                }
1200:                String uri = r.getURI();
1201:                int split = Util.splitNamespace(uri);
1202:                return uri.substring(split);
1203:
1204:            }
1205:
1206:            /**
1207:             * objectTable initialization.
1208:             */
1209:
1210:            private void increaseObjectCount(Resource r) {
1211:                //        if (!r.isAnon())
1212:                //            return;
1213:                Integer cnt = (Integer) objectTable.get(r);
1214:                if (cnt == null) {
1215:                    cnt = one;
1216:                } else {
1217:                    cnt = new Integer(cnt.intValue() + 1);
1218:                }
1219:                objectTable.put(r, cnt);
1220:            }
1221:
1222:            /***************************************************************************
1223:             * Reification support.
1224:             **************************************************************************/
1225:            /*
1226:             * Is the use of ID in rule [6.12] to create a reification helpful or not?
1227:             */
1228:            private boolean wantReification(Statement s) {
1229:                return wantReification(s, (Resource) statement2res.get(s));
1230:            }
1231:
1232:            private boolean wantReification(Resource res) {
1233:                return wantReification((Statement) res2statement.get(res), res);
1234:            }
1235:
1236:            private boolean wantReification(Statement s, Resource ref) {
1237:                if (s == null || ref == null || ref.isAnon()
1238:                        || prettyWriter.sReification)
1239:                    return false;
1240:                if (!(isLocalReference(ref)))
1241:                    return false;
1242:                Statement reify[] = reification(s);
1243:                int i;
1244:                for (i = 0; i < reify.length; i++)
1245:                    if (doneSet.contains(reify[i])
1246:                            || (!model.contains(reify[i])))
1247:                        return false; // Some of reification already done.
1248:                return true; // Reification rule helps.
1249:            }
1250:
1251:            private Statement[] reification(Statement s) {
1252:                Model m = s.getModel();
1253:                Resource r = (Resource) statement2res.get(s);
1254:                return new Statement[] {
1255:                        m.createStatement(r, RDF.type, RDF.Statement),
1256:                        m.createStatement(r, RDF.subject, s.getSubject()),
1257:                        m.createStatement(r, RDF.predicate, s.getPredicate()),
1258:                        m.createStatement(r, RDF.object, s.getObject()) };
1259:            }
1260:
1261:            private boolean hasProperties(Resource r) {
1262:                ExtendedIterator ss = listProperties(r);
1263:                if (avoidExplicitReification
1264:                        && // ( r instanceof Statement ) &&
1265:                        (!r.isAnon()) && isLocalReference(r)
1266:                        && res2statement.containsKey(r)) {
1267:                    ss = new MapFilterIterator(new MapFilter() {
1268:                        public Object accept(Object o) {
1269:                            Statement s = (Statement) o;
1270:                            Property p = s.getPredicate();
1271:                            return ((!p.getNameSpace().equals(rdfns)) || !((RDF.type
1272:                                    .equals(p) && s.getObject().equals(
1273:                                    RDF.Statement))
1274:                                    || RDF.object.equals(p)
1275:                                    || RDF.predicate.equals(p) || RDF.subject
1276:                                    .equals(p))) ? o : null;
1277:                        }
1278:                    }, ss);
1279:                }
1280:                try {
1281:                    return ss.hasNext();
1282:                } finally {
1283:                    ss.close();
1284:                }
1285:            }
1286:
1287:            private ExtendedIterator listProperties(Resource r) {
1288:                return new MapFilterIterator(new MapFilter() {
1289:                    public Object accept(Object o) {
1290:                        return doneSet.contains(o) ? null : o;
1291:                    }
1292:                }, r.listProperties());
1293:            }
1294:
1295:            // Good type statement, or simple string valued statement with no langID
1296:            // See http://www.w3.org/TR/REC-xml#AVNormalize
1297:            private boolean canBeAttribute(Statement s, Set seen) {
1298:                Property p = s.getPredicate();
1299:                // Check seen first.
1300:                if (prettyWriter.sPropertyAttr || seen.contains(p)) // We can't use the
1301:                    // same attribute
1302:                    // twice in one rule.
1303:                    return false;
1304:                seen.add(p);
1305:
1306:                if (p.equals(RDF.type)) {
1307:                    // If we have a model in which a type is given
1308:                    // as a string, then we avoid the attribute rule 6.10 which is
1309:                    // ambiguous with 6.11.
1310:                    RDFNode n = s.getObject();
1311:                    // return (n instanceof Resource) && !((Resource) n).isAnon();
1312:                    return n.isURIResource();
1313:                }
1314:
1315:                if (s.getObject() instanceof  Literal) {
1316:                    Literal l = s.getLiteral();
1317:                    if (l.getDatatypeURI() != null)
1318:                        return false;
1319:
1320:                    if (l.getLanguage().equals("")) {
1321:                        // j.cook.up bug fix
1322:                        if (prettyWriter.isDefaultNamespace(getNameSpace(p)))
1323:                            return false;
1324:
1325:                        String str = l.getString();
1326:                        if (str.length() < 40) {
1327:                            char buf[] = str.toCharArray();
1328:                            for (int i = 0; i < buf.length; i++) {
1329:                                // See http://www.w3.org/TR/REC-xml#AVNormalize
1330:                                if (buf[i] <= ' ' || buf[i] == 0xFFFF
1331:                                        || buf[i] == 0xFFFE)
1332:                                    return false;
1333:                            }
1334:                            return !wantReification(s);
1335:                        }
1336:                    }
1337:                }
1338:                return false;
1339:            }
1340:
1341:            private boolean allPropsAreAttr(Resource r) {
1342:                ClosableIterator ss = listProperties(r);
1343:                Set seen = new HashSet();
1344:                try {
1345:                    while (ss.hasNext()) {
1346:                        Statement s = (Statement) ss.next();
1347:                        if (!canBeAttribute(s, seen))
1348:                            return false;
1349:                    }
1350:                } finally {
1351:                    ss.close();
1352:                }
1353:                return true;
1354:            }
1355:
1356:            private void done(Statement s) {
1357:                doneSet.add(s);
1358:                // return false;
1359:            }
1360:
1361:            /**
1362:             * If r represent a daml:collection return a 2D array of its statements. For
1363:             * each member there are three statements the first gives the DAML.first
1364:             * statement, the second the DAML.rest statement and the third the RDF.type
1365:             * statement.
1366:             * 
1367:             * @return null on failure or the elements of the collection.
1368:             * 
1369:             */
1370:            private Statement[][] getDamlList(RDFNode r) {
1371:                return prettyWriter.sDamlCollection ? null : getList(r,
1372:                        DAML_OIL.List, DAML_OIL.first, DAML_OIL.rest,
1373:                        DAML_OIL.nil);
1374:            }
1375:
1376:            private Statement[][] getRDFList(RDFNode r) {
1377:                return prettyWriter.sParseTypeCollectionPropertyElt ? null
1378:                        : getList(r, null, RDF.first, RDF.rest, RDF.nil);
1379:            }
1380:
1381:            private Statement[][] getList(RDFNode r, Resource list,
1382:                    Property first, Property rest, Resource nil) {
1383:
1384:                Vector rslt = new Vector();
1385:                Set seen = new HashSet();
1386:                RDFNode next = r;
1387:                // We walk down the list and check each member.
1388:                try {
1389:
1390:                    while (!next.equals(nil)) {
1391:                        Statement elt[] = new Statement[list == null ? 2 : 3];
1392:                        if (next instanceof  Literal)
1393:                            return null;
1394:                        Resource res = (Resource) next;
1395:                        // We cannot label the nodes in the daml:collection
1396:                        // construction.
1397:                        if (!isGenuineAnon(res))
1398:                            return null;
1399:                        // The occurs check - cyclic loop rather than a list.
1400:                        if (seen.contains(next))
1401:                            return null;
1402:                        seen.add(next);
1403:
1404:                        // We must have exactly three properties.
1405:                        StmtIterator ss = res.listProperties();
1406:                        try {
1407:                            while (ss.hasNext()) {
1408:                                Statement s = ss.nextStatement();
1409:                                Property p = s.getPredicate();
1410:                                int ix;
1411:                                RDFNode obj = s.getObject();
1412:                                if (doneSet.contains(s))
1413:                                    return null;
1414:                                if (!(obj instanceof  Resource)) {
1415:                                    return null;
1416:                                }
1417:                                if (p.equals(RDF.type)) {
1418:                                    ix = 2;
1419:                                    if (!obj.equals(list))
1420:                                        return null;
1421:                                } else if (p.equals(first)) {
1422:                                    ix = 0;
1423:                                } else if (p.equals(rest)) {
1424:                                    ix = 1;
1425:                                    next = obj;
1426:                                } else {
1427:                                    return null;
1428:                                }
1429:                                if (elt[ix] != null)
1430:                                    return null;
1431:                                elt[ix] = s;
1432:                            }
1433:                        } finally {
1434:                            ss.close();
1435:                        }
1436:                        for (int i = 0; i < elt.length; i++)
1437:                            if (elt[i] == null)
1438:                                // didn't have the three required elements.
1439:                                return null;
1440:                        rslt.add(elt);
1441:                    }
1442:                    if (rslt.size() == 0)
1443:                        return null;
1444:                } finally {
1445:
1446:                }
1447:                Statement array[][] = new Statement[rslt.size()][];
1448:                rslt.copyInto(array);
1449:                return array;
1450:
1451:            }
1452:
1453:            /**
1454:             * @return A statement that is suitable for a typed node construction or
1455:             *         null.
1456:             */
1457:            private Statement getType(Resource r) {
1458:                Statement rslt;
1459:                try {
1460:                    if (r instanceof  Statement) {
1461:                        rslt = ((Statement) r).getStatementProperty(RDF.type);
1462:                        if (rslt == null
1463:                                || (!rslt.getObject().equals(RDF.Statement)))
1464:                            error("Statement type problem");
1465:                    } else {
1466:                        rslt = r.getRequiredProperty(RDF.type);
1467:                    }
1468:                } catch (PropertyNotFoundException rdfe) {
1469:                    if (r instanceof  Statement)
1470:                        error("Statement type problem");
1471:                    rslt = null;
1472:                }
1473:                if (rslt == null || isOKType(rslt.getObject()) == -1)
1474:                    return null;
1475:
1476:                return rslt;
1477:            }
1478:
1479:            /**
1480:             * @param n
1481:             *            The value of some rdf:type (precondition).
1482:             * @return The split point or -1.
1483:             */
1484:
1485:            private int isOKType(RDFNode n) {
1486:
1487:                if (!(n instanceof  Resource))
1488:                    return -1;
1489:                if (((Resource) n).isAnon())
1490:                    return -1;
1491:                // Only allow resources with namespace and fragment ID
1492:                String uri = ((Resource) n).getURI();
1493:
1494:                int split = Util.splitNamespace(uri);
1495:                if (split == 0 || split == uri.length())
1496:                    return -1;
1497:
1498:                return split;
1499:            }
1500:
1501:            /**
1502:             * The order of outputting the resources. This all supports wObjStar.
1503:             */
1504:            private Set infinite;
1505:
1506:            private void findInfiniteCycles() {
1507:                // find all statements that haven't been done.
1508:                StmtIterator ss = model.listStatements();
1509:                Relation relation = new Relation();
1510:                try {
1511:                    while (ss.hasNext()) {
1512:                        Statement s = ss.nextStatement();
1513:                        if (!doneSet.contains(s)) {
1514:                            RDFNode rn = s.getObject();
1515:                            if (rn instanceof  Resource) {
1516:                                relation.set(s.getSubject(), rn);
1517:                            }
1518:                        }
1519:                    }
1520:                } finally {
1521:                    ss.close();
1522:                }
1523:                relation.transitiveClosure();
1524:                infinite = relation.getDiagonal();
1525:            }
1526:
1527:            /**
1528:             * This class is an iterator over the set infinite, but we wait until it is
1529:             * used before instantiating the underlying iterator.
1530:             */
1531:            private Iterator allInfiniteLeft() {
1532:                return new LateBindingIterator() {
1533:                    public Iterator create() {
1534:                        return infinite.iterator();
1535:                    }
1536:                };
1537:            }
1538:
1539:            private Iterator pleasingTypeIterator() {
1540:                if (pleasingTypes == null)
1541:                    return new NullIterator();
1542:                Map buckets = new HashMap();
1543:                Set bucketArray[] = new Set[pleasingTypes.length];
1544:                // Set up buckets and bucketArray. Each is a collection
1545:                // of the same buckets, one ordered, the other hashed.
1546:                for (int i = 0; i < pleasingTypes.length; i++) {
1547:                    bucketArray[i] = new HashSet();
1548:                    buckets.put(pleasingTypes[i], bucketArray[i]);
1549:                }
1550:
1551:                ResIterator rs = model.listSubjects();
1552:                try {
1553:                    while (rs.hasNext()) {
1554:                        Resource r = rs.nextResource();
1555:                        Statement s = getType(r);
1556:                        if (s != null) {
1557:                            Set bucket = (Set) buckets.get(s.getObject());
1558:                            if (bucket != null) {
1559:                                if (isGenuineAnon(r)) {
1560:                                    Integer v = (Integer) objectTable.get(r);
1561:                                    if (v != null && v.intValue() == 1)
1562:                                        continue;
1563:                                }
1564:                                bucket.add(r);
1565:                            }
1566:                        }
1567:                    }
1568:                } finally {
1569:                    rs.close();
1570:                }
1571:
1572:                // Now all the pleasing resources are in the buckets.
1573:                // Add all their iterators togethor:
1574:
1575:                return new IteratorIterator(new Map1Iterator(new Map1() {
1576:                    public Object map1(Object bkt) {
1577:                        return ((Set) bkt).iterator();
1578:                    }
1579:                }, new ArrayIterator(bucketArray)));
1580:
1581:            }
1582:
1583:            /**
1584:             * listSubjects - generates a list of subjects for the wObjStar rule. We
1585:             * wish to order these elegantly. The current implementation goes for:
1586:             * <ul>
1587:             * <li> The current file - mainly intended for good DAML.
1588:             * <li> Subjects that are not objects of anything, excluding reifications
1589:             * <li> At these stage we evaluate a dependency graph of the remaining
1590:             * resources.
1591:             * <li>non-anonymous resources that are the object of more than one rule
1592:             * that are in infinite cycles.
1593:             * <li> any non genuinely anonymous resources that are in infinite cycles
1594:             * <li>any other resource in an infinite cyle
1595:             * <li>any other resource.
1596:             * <li>reifications
1597:             * </ul>
1598:             * 
1599:             * 
1600:             * At the end, we need to close any underlying ResIterators from the model,
1601:             * however to avoid complications in much of this code we use general
1602:             * java.util.Iterator-s. We hence use a wrapper around a ResIterator to
1603:             * allow us to manage the closing issue.
1604:             */
1605:            private Iterator listSubjects() {
1606:                // The current file - mainly intended for good DAML.
1607:                Iterator currentFile =
1608:                // new ArrayIterator(
1609:                // new Resource[] { model.createResource(this.localName)});
1610:                new SingletonIterator(model.createResource(this .localName));
1611:                // The pleasing types
1612:                Iterator pleasing = pleasingTypeIterator();
1613:
1614:                Iterator fakeStopPleasing = new NullIterator() {
1615:                    public boolean hasNext() {
1616:                        pleasingTypeSet = new HashSet();
1617:                        return false;
1618:                    }
1619:                };
1620:
1621:                // Subjects that are not objects of anything.
1622:                Iterator nonObjects = new FilterIterator(new Filter() {
1623:                    public boolean accept(Object o) {
1624:                        return (!objectTable.containsKey(o))
1625:                                && (!wantReification((Resource) o));
1626:                    }
1627:                }, modelListSubjects());
1628:                // At these stage we evaluate a dependency graph of the remaining
1629:                // resources.
1630:                // This is stuck in the master iterator so that it's hasNext is called
1631:                // at an appropriate time (after the earlier stages, before the later
1632:                // stages).
1633:                // We use this to trigger the dependency graph evalaution.
1634:                Iterator fakeLazyEvaluator = new NullIterator() {
1635:                    public boolean hasNext() {
1636:                        // Evalaute dependency graph.
1637:                        findInfiniteCycles();
1638:                        return false;
1639:                    }
1640:                };
1641:                // non-anonymous resources that are the object of more than one
1642:                // triple that are in infinite cycles.
1643:                Iterator firstChoiceCyclic = new FilterIterator(new Filter() {
1644:                    public boolean accept(Object o) {
1645:                        Resource r = (Resource) o;
1646:                        codeCoverage[4]++;
1647:                        if (r.isAnon())
1648:                            return false;
1649:                        Integer cnt = (Integer) objectTable.get(r);
1650:                        if (cnt == null || cnt.intValue() <= 1)
1651:                            return false;
1652:                        return true;
1653:                    }
1654:                }, this .allInfiniteLeft());
1655:                // any non genuinely anonymous resources that are in infinite cycles
1656:                Iterator nonAnonInfinite = new FilterIterator(new Filter() {
1657:                    public boolean accept(Object o) {
1658:                        codeCoverage[5]++;
1659:                        Resource r = (Resource) o;
1660:                        return !isGenuineAnon(r);
1661:                    }
1662:                }, allInfiniteLeft());
1663:                // any other resource in an infinite cyle
1664:                Iterator inf = allInfiniteLeft();
1665:                Iterator anotherFake = new NullIterator() {
1666:                    public boolean hasNext() {
1667:                        avoidExplicitReification = false;
1668:                        return false;
1669:                    }
1670:                };
1671:                Iterator reifications = new FilterIterator(new Filter() {
1672:                    public boolean accept(Object o) {
1673:                        codeCoverage[6]++;
1674:                        return res2statement.containsKey(o);
1675:                    }
1676:                }, allInfiniteLeft());
1677:                // any other resource.
1678:                Iterator backStop = modelListSubjects();
1679:
1680:                Iterator all[] = new Iterator[] { currentFile, pleasing,
1681:                        fakeStopPleasing, nonObjects, fakeLazyEvaluator,
1682:                        firstChoiceCyclic, nonAnonInfinite, inf, anotherFake,
1683:                        reifications, new NullIterator() {
1684:                            public boolean hasNext() {
1685:                                if (modelListSubjects().hasNext())
1686:                                    codeCoverage[7]++;
1687:                                return false;
1688:                            }
1689:                        }, backStop };
1690:                Iterator allAsOne = new IteratorIterator(new ArrayIterator(all));
1691:
1692:                // Filter for those that still have something to list.
1693:                return new FilterIterator(new Filter() {
1694:                    public boolean accept(Object o) {
1695:                        return hasProperties((Resource) o);
1696:                    }
1697:                }, allAsOne);
1698:            }
1699:
1700:            private Set openResIterators = new HashSet();
1701:
1702:            private synchronized void closeAllResIterators() {
1703:                Iterator members = openResIterators.iterator();
1704:                while (members.hasNext()) {
1705:                    ((ResIterator) members.next()).close();
1706:                }
1707:                openResIterators = new HashSet();
1708:            }
1709:
1710:            private Iterator modelListSubjects() {
1711:                ResIterator resIt = model.listSubjects();
1712:                openResIterators.add(resIt);
1713:                return resIt;
1714:
1715:            }
1716:
1717:        }
1718:
1719:        /*
1720:         * (c) Copyright 2000, 2001, 2002, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard
1721:         * Development Company, LP All rights reserved.
1722:         * 
1723:         * Redistribution and use in source and binary forms, with or without
1724:         * modification, are permitted provided that the following conditions are met:
1725:         * 
1726:         * 1. Redistributions of source code must retain the above copyright notice,
1727:         * this list of conditions and the following disclaimer.
1728:         * 
1729:         * 2. Redistributions in binary form must reproduce the above copyright notice,
1730:         * this list of conditions and the following disclaimer in the documentation
1731:         * and/or other materials provided with the distribution.
1732:         * 
1733:         * 3. The name of the author may not be used to endorse or promote products
1734:         * derived from this software without specific prior written permission.
1735:         * 
1736:         * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
1737:         * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
1738:         * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
1739:         * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
1740:         * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
1741:         * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
1742:         * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
1743:         * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
1744:         * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
1745:         * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1746:         */
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.