This is an automated email from the ASF dual-hosted git repository. andy pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/jena.git
commit 66aafa89280d26fec0af51eda4a1275f9a6581a6 Author: Andy Seaborne <[email protected]> AuthorDate: Sun Mar 8 21:32:18 2026 +0000 GH-3790: Pretty RDF/XML output: write triple terms and text dir --- .../java/org/apache/jena/system/TS_System.java | 1 + .../org/apache/jena/system/TestFindNamespaces.java | 68 +++++ .../jena/rdfxml/xmloutput/impl/BaseXMLWriter.java | 37 +-- .../xmloutput/impl/FindNamespacesRDFXML.java | 75 +++++ .../jena/rdfxml/xmloutput/impl/Unparser.java | 311 ++++++++++++++++++--- .../main/java/org/apache/jena/vocabulary/ITS.java | 32 +-- .../jena/rdfxml/xmloutput/TestXMLAbbrev.java | 2 +- .../jena/rdfxml/xmloutput/TestXMLFeatures.java | 2 +- 8 files changed, 448 insertions(+), 80 deletions(-) diff --git a/jena-arq/src/test/java/org/apache/jena/system/TS_System.java b/jena-arq/src/test/java/org/apache/jena/system/TS_System.java index cb22b2c717..292ea12e20 100644 --- a/jena-arq/src/test/java/org/apache/jena/system/TS_System.java +++ b/jena-arq/src/test/java/org/apache/jena/system/TS_System.java @@ -36,6 +36,7 @@ import org.junit.platform.suite.api.Suite; , TestPrefixes.class , TestPrefixLib.class , TestRDFStarTranslation.class + , TestFindNamespaces.class }) public class TS_System {} diff --git a/jena-arq/src/test/java/org/apache/jena/system/TestFindNamespaces.java b/jena-arq/src/test/java/org/apache/jena/system/TestFindNamespaces.java new file mode 100644 index 0000000000..ac25f02d55 --- /dev/null +++ b/jena-arq/src/test/java/org/apache/jena/system/TestFindNamespaces.java @@ -0,0 +1,68 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.apache.jena.system; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.Set; + +import org.junit.jupiter.api.Test; + +import org.apache.jena.graph.Graph; +import org.apache.jena.rdfxml.xmloutput.impl.FindNamespacesRDFXML; +import org.apache.jena.riot.Lang; +import org.apache.jena.riot.RDFParser; + +/** Test FindNamespacesRDFXML - easier heer se we can use full turtle */ +public class TestFindNamespaces { + private static String testStr = """ + PREFIX : <http://example/> + + <http://x-subj/s> <http://x-pred/p1> 'abc'^^<http://ns-dt/dType> . + + :s <http://x-pred/p1> <<( :s1 <http://x-pred-tt/p1> 'abc'^^<http://ns-dt-tt/dType> )>> . + + :s <http://x-pred/p1> <<( + <http://x-subj/s1> + <http://x-pred-tt/p1> + <<( :s1 <http://x-pred-tt2/p1> 'abc'^^<http://ns-dt-tt2/dType> )>> + )>> . + """; + + @Test + public void findNamespace() { + Graph graph = RDFParser.fromString(testStr, Lang.TURTLE).toGraph(); + Set<String> ns = FindNamespacesRDFXML.namespacesForRDFXML(graph); + + // Not http://x-subj/s, not http://example/ + Set<String> expected = Set.of("http://x-pred/", "http://x-pred-tt/", "http://x-pred-tt2/" + // datatypes. + //, "http://ns-dt-tt2/", "http://ns-dt-tt/" + ); + if ( ! expected.equals(ns) ) { + System.err.println("== TestFindNamespaces"); + System.err.println("Expected: "+expected); + System.err.println("Actual: "+ns); + } + assertEquals(expected, ns); + } +} diff --git a/jena-core/src/main/java/org/apache/jena/rdfxml/xmloutput/impl/BaseXMLWriter.java b/jena-core/src/main/java/org/apache/jena/rdfxml/xmloutput/impl/BaseXMLWriter.java index 996a140ae5..94c745ff0c 100644 --- a/jena-core/src/main/java/org/apache/jena/rdfxml/xmloutput/impl/BaseXMLWriter.java +++ b/jena-core/src/main/java/org/apache/jena/rdfxml/xmloutput/impl/BaseXMLWriter.java @@ -119,12 +119,12 @@ abstract public class BaseXMLWriter implements RDFXMLWriterI { /** Counter used for allocating Jena transient namespace declarations. */ - private int jenaPrefixCount; + private int jenaPrefixCount = 0; static String RDFNS = RDF.getURI(); - static private final Pattern jenaNamespace = Pattern.compile("j\\.([1-9][0-9]*|cook\\.up)"); + static private final Pattern jenaNamespace = Pattern.compile("j\\.([1-9][0-9]*|cook\\.up|fixup)"); String xmlBase = null; @@ -213,8 +213,10 @@ abstract public class BaseXMLWriter implements RDFXMLWriterI { } private void addNameSpaces( Model model ) { - NsIterator nsIter = model.listNameSpaces(); - while (nsIter.hasNext()) this.addNameSpace( nsIter.nextNs() ); + Set<String> ns = FindNamespacesRDFXML.namespacesForRDFXML(model); + ns.forEach(u->addNameSpace(u)); +// NsIterator nsIter = model.listNameSpaces(); +// while (nsIter.hasNext()) this.addNameSpace( nsIter.nextNs() ); } private void primeNamespace(Model model) { @@ -300,9 +302,8 @@ abstract public class BaseXMLWriter implements RDFXMLWriterI { } if ( val == null ) { // just in case the prefix has already been used, look for a free - // one. - // (the usual source of such prefixes is reading in a model we wrote - // out earlier) + // one (the usual source of such prefixes is reading in a model we + // wrote out earlier) do { val = "j." + (jenaPrefixCount++); } while (prefixesUsed.contains(val)); @@ -312,7 +313,7 @@ abstract public class BaseXMLWriter implements RDFXMLWriterI { } } - final synchronized public void setNsPrefix(String prefix, String ns) { + final public void setNsPrefix(String prefix, String ns) { if (checkLegalPrefix(prefix)) { nameSpaces.set11(ns, prefix); } @@ -400,24 +401,26 @@ abstract public class BaseXMLWriter implements RDFXMLWriterI { } } String prefix = ns.get( namespace ); - boolean cookUp = false; + boolean synthNS = false; if (prefix == null) { checkURI( namespace ); - logger.warn("Internal error: unexpected QName URI: <" + namespace + ">. Fixing up.", - new BrokenException( "unexpected QName URI " + namespace )); - cookUp = true; + logger.warn("Internal error: QNamed needed but no namespace for URI: <" + namespace + ">. Fixing up." + //Development: , new BrokenException( "unexpected QName URI " + namespace ) + ); + synthNS = true; } else if (prefix.length() == 0) { if (type == ATTR || type == FASTATTR) - cookUp = true; + synthNS = true; else return local; } - if (cookUp) return cookUpAttribution( type, namespace, local ); + if (synthNS) return fixupQName( type, namespace, local ); return prefix + ":" + local; } - private String cookUpAttribution( int type, String namespace, String local ) { - String prefix = "j.cook.up"; + private String fixupQName( int type, String namespace, String local ) { + //String prefix = "j.cook.up"; // "Traditional" name. + String prefix = "j.fixup"; switch (type) { case FASTATTR : case ATTR : @@ -429,7 +432,7 @@ abstract public class BaseXMLWriter implements RDFXMLWriterI { return prefix + ":" + local; case FAST : // logger.error("Unreachable code - reached."); - throw new BrokenException( "cookup reached final FAST" ); + throw new BrokenException( "NS generation reached final FAST" ); } } diff --git a/jena-core/src/main/java/org/apache/jena/rdfxml/xmloutput/impl/FindNamespacesRDFXML.java b/jena-core/src/main/java/org/apache/jena/rdfxml/xmloutput/impl/FindNamespacesRDFXML.java new file mode 100644 index 0000000000..442ff4dd12 --- /dev/null +++ b/jena-core/src/main/java/org/apache/jena/rdfxml/xmloutput/impl/FindNamespacesRDFXML.java @@ -0,0 +1,75 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.apache.jena.rdfxml.xmloutput.impl; + +import java.util.Set; + +import org.apache.jena.graph.Graph; +import org.apache.jena.graph.Triple; +import org.apache.jena.rdf.model.Model; +import org.apache.jena.util.CollectionFactory; +import org.apache.jena.util.SplitIRI; +import org.apache.jena.util.iterator.ExtendedIterator; + +/** + * Find all the namespaces needed to print RDF/XML, including inside triple terms. + * Namespaces are needed for predicates. + */ +public class FindNamespacesRDFXML { + + public static Set<String> namespacesForRDFXML(Model model) { + return namespacesForRDFXML(model.getGraph()); + } + + public static Set<String> namespacesForRDFXML(Graph graph) { + Set<String> namespaces = CollectionFactory.createHashedSet(); + ExtendedIterator<Triple> iter = graph.find(); + try { + iter.forEachRemaining(triple->{ + processTriple(namespaces, triple); + }); + } finally { iter.close(); } + return namespaces; + } + + private static void processTriple(Set<String> namespaces, Triple triple) { + String predicateURI = triple.getPredicate().getURI(); + accNamespace(namespaces, predicateURI); + + // Nor necessary for RDF/XML but Jena used to include them. +// if ( triple.getObject().isLiteral() ) { +// String dtURI = triple.getObject().getLiteralDatatypeURI(); +// accNamepsace(namespaces, dtURI); +// return; +// } + + if ( triple.getObject().isTripleTerm() ) { + processTriple(namespaces, triple.getObject().getTriple()); + } + } + + private static void accNamespace(Set<String> namespaces, String uri) { + String ns = uri.substring(0, SplitIRI.splitXML(uri)); + namespaces.add(ns); + } + +} diff --git a/jena-core/src/main/java/org/apache/jena/rdfxml/xmloutput/impl/Unparser.java b/jena-core/src/main/java/org/apache/jena/rdfxml/xmloutput/impl/Unparser.java index 274ce91472..4d1bdb7404 100644 --- a/jena-core/src/main/java/org/apache/jena/rdfxml/xmloutput/impl/Unparser.java +++ b/jena-core/src/main/java/org/apache/jena/rdfxml/xmloutput/impl/Unparser.java @@ -21,6 +21,8 @@ package org.apache.jena.rdfxml.xmloutput.impl; +import static java.lang.String.format; + /* * Want todo List - easy efficiency gains in listSubjects() and * modelListSubjects() by removing those subjects that we have already @@ -137,6 +139,7 @@ import org.apache.jena.shared.JenaException ; import org.apache.jena.shared.PropertyNotFoundException ; import org.apache.jena.util.XML10Char; import org.apache.jena.util.iterator.* ; +import org.apache.jena.vocabulary.ITS; import org.apache.jena.vocabulary.RDF ; import org.slf4j.Logger ; import org.slf4j.LoggerFactory ; @@ -173,12 +176,12 @@ class Unparser { objectTable = new HashMap<>(); StmtIterator ss = m.listStatements(); try { + // Track number of time a (blank) node will be used + // Recurse into triple terms. while (ss.hasNext()) { Statement s = ss.nextStatement(); - RDFNode rn = s.getObject(); - if (rn instanceof Resource) { - increaseObjectCount((Resource) rn); - } + RDFNode obj = s.getObject(); + processRDFNode(obj, false); } } finally { ss.close(); @@ -214,8 +217,7 @@ class Unparser { Property ppred = model.createProperty(rpred.getURI()); - Statement statement = model.createStatement(rsubj, ppred, - nobj); + Statement statement = model.createStatement(rsubj, ppred, nobj); res2statement.put(r, statement); statement2res.put(statement, r); } catch (Exception ignored) { @@ -226,6 +228,56 @@ class Unparser { } } + private void processRDFNode(RDFNode obj, boolean inTripleTerm) { + if ( obj.isResource() ) { + Resource r = obj.asResource(); + increaseObjectCount(r); + if ( inTripleTerm && r.isAnon() ) + // Force it to be printed + increaseObjectCount(r); + } + if ( obj.isStatementTerm() ) { + processTripleTerm(obj.asStatementTerm()); + return; + } + if ( obj.isLiteral() ) { + if ( obj.asLiteral().getBaseDirection() != null ) { + hasTextDirectionLiterals = true; + // We will need a namespace prefix. + // Ideally, there is one in the model can be added to rdf:RDF as usual. + itsPrefix = model.getNsURIPrefix(ITS.uri); + if ( itsPrefix == null ) { + // Not in model. + // This is added to rdf:RDF, along with [its]:version + itsInsertNs = true; + itsPrefix = syntheticNamespaceForITS(); + } + } + } + } + + private void processTripleTerm(StatementTerm sTerm) { + Statement tripleTerm = sTerm.asStatementTerm().getStatement(); + processTripleTermsOneLevel(tripleTerm); + + if ( tripleTerm.getObject().isStatementTerm() ) { + StatementTerm sTerm2 = tripleTerm.getObject().asStatementTerm(); + processTripleTerm(sTerm2); + } + } + + private void processTripleTermsOneLevel(Statement stmt) { + RDFNode ttSubj = stmt.getSubject(); + if ( ttSubj.isAnon() ) { + Resource r = ttSubj.asResource(); + // XXX !!! twice to make sure it is printed and not compacted. + if ( r.isAnon() ) + increaseObjectCount(r); + increaseObjectCount(r); + } + processRDFNode(stmt.getObject(), true); + } + /** * Note: must work with uri being null. */ @@ -242,6 +294,25 @@ class Unparser { outputName = u.str(); } + // Determine a prefix for the ITS + private String syntheticNamespaceForITS() { + if ( itsPrefix != null ) + return itsPrefix; + int count = 0; + String nsPrefix = "its"; + // Find an unused prefix. + for(;;) { + if ( model.getNsPrefixURI(nsPrefix) == null) + break; + nsPrefix = "its." + (count++); + if ( count > 10_000 ) + // Safety + throw new JenaException("Can't determine an XML namepsace prefix for ITS"); + } + prettyWriter.setNsPrefix(nsPrefix, ITS.uri); + return nsPrefix; + } + /** * Should be called exactly once for each Unparser. Calling it a second time * will have undesired results. @@ -249,20 +320,13 @@ class Unparser { void write() { prettyWriter.workOutNamespaces(); wRDF(); - /* - * System.out.print("Coverage = "); for (int i=0;i<codeCoverage.length;i++) - * System.out.print(" c[" + i + "] = " + codeCoverage[i]+ ";"); - * System.out.println(); - */ } /** * Set a list of types of objects that will be expanded at the top-level of * the file. * - * @param types - * An array of rdf:Class'es. - * + * @param types An array of rdf:Class'es. */ void setTopLevelTypes(Resource types[]) { pleasingTypes = types; @@ -316,9 +380,17 @@ class Unparser { // Reification stuff. - Map<Resource, Statement> res2statement; + private Map<Resource, Statement> res2statement; + + private Map<Statement, Resource> statement2res; - Map<Statement, Resource> statement2res; + // ITS (text direction) + // The data has text direction literals. + private boolean hasTextDirectionLiterals = false; + // The model does not have an its: namespace so we need to add it. + private boolean itsInsertNs = false; + // The prefix decided on (its:: may be already used by the model) + private String itsPrefix = null; /* * The top-down recursive descent unparser. The methods starting in w all @@ -338,6 +410,20 @@ class Unparser { print(prettyWriter.rdfEl("RDF")); indentPlus(); printNameSpaceDefn(); + if ( hasTextDirectionLiterals ) { + indentPlus(); + if ( itsInsertNs ) { + tab(); + print("xmlns:" ); + print(itsPrefix); + print("="); + print(q(ITS.uri)); + } + // Put the version in. + tab(); + print(format("%s:%s=%s", itsPrefix, ITS.version, q("2.0"))); + indentMinus(); + } if (xmlBase != null) { setOutputName(xmlBase); tab(); @@ -384,16 +470,141 @@ class Unparser { * others (e.g. choice 1). For embedded XML choice 2 is obligatory. For * untyped, anonymous resource valued items choice 3 is used. Choice 1 is * the fall back. + * + * Do triple term first to protect the later (original) functions that may not expect triple terms */ - private boolean wPropertyElt(WType wt, Property prop, Statement s, - RDFNode val) { - return wPropertyEltCompact(wt, prop, s, val) || // choice 4 + private boolean wPropertyElt(WType wt, Property prop, Statement s, RDFNode val) { + return wPropertyEltTripleTerm(wt, prop, s, val) || // RDF Triple term + wPropertyEltCompact(wt, prop, s, val) || // choice 4 wPropertyEltCollection(wt, prop, s, val) || // choice RDF collections - wPropertyEltLiteral(wt, prop, s, val) || // choice 2 - wPropertyEltResource(wt, prop, s, val) || // choice 3 - wPropertyEltDatatype(wt, prop, s, val) || - wPropertyEltValue(wt, prop, s, val); - // choice 1. + wPropertyEltLiteral(wt, prop, s, val) || // choice 2 + wPropertyEltResource(wt, prop, s, val) || // choice 3 + wPropertyEltDatatype(wt, prop, s, val) || + wPropertyEltValue(wt, prop, s, val); // choice 1. + + } + + private boolean wPropertyEltTripleTerm(WType wt, Property prop, Statement statement, RDFNode val) { + if ( ! ( val instanceof StatementTerm sTerm ) ) + return false; + done(statement); + wPropertyTripleTerm(wt, prop, sTerm.getStatement(), statement); + return true; + } + + private void wPropertyTripleTerm(WType wt, Property prop, Statement triple, Statement containingStatement) { + // parseType="Triple" + tab(); + print("<"); + wt.wTypeStart(prop); + if ( containingStatement != null ) + wIdAttrReified(containingStatement); + maybeNewline(); + print(" "); + printRdfAt("parseType"); + print("=" + q("Triple")); + print(">"); + indentPlus(); + tab(); + // Print the triple term + wTripleTerm(wt, triple); + + // End property. + indentMinus(); + tab(); + + print("</"); + wt.wTypeEnd(prop); + print(">"); + } + + private void wTripleTerm(WType wt, Statement triple) { + // Don't use the asserted triple printing mechanism. + // - it tracks asserted triples that have been printed + // the triple of a triple term may also be asserted and need to be printed twice. + // - it looks in the (asserted) model for properties and objects + + Resource subject = triple.getSubject(); + + print("<"); + printRdfAt("Description"); + // rdf:NodeID= or rdf:about= , not wIdAttrOpt ID= (check) + boolean x = wNodeIDAttr(subject) || wAboutAttr(subject); + print(">"); + indentPlus(); + + Property property = triple.getPredicate(); + RDFNode object = triple.getObject(); + wTripleTermPropertyObject(property, object); + + indentMinus(); + tab(); + print("</"); + printRdfAt("Description"); + print(">"); + } + + private void wTripleTermPropertyObject(Property property, RDFNode object) { + tab(); + + if ( object.isStatementTerm() ) { + indentPlus(); + wPropertyTripleTerm(wtype, property, object.asStatementTerm().getStatement(), null); + //wTripleTerm(wtype, object.asStatementTerm().getStatement()); + indentMinus(); + return; + } + + print("<"); + wtype.wTypeStart(property); + + // Could split up! + + // "/>" forms. + if ( object.isURIResource() ) { + // parse type resource + //wResourceAttr + print(" "); + printRdfAt("resource"); + print("="); + String uri = object.asResource().getURI(); + wURIreference(uri); + print("/>"); + return; + } + if ( object.isAnon() ) { + print(" "); + printRdfAt("nodeID"); + print("="); + // Corner(?) case + // Could use <property rdf:parseType="Resource"></property> + print(q(prettyWriter.anonId(object.asResource()))); + print("/>"); + return; + } + // Forms that have text. + if ( object.isLiteral() ) { + Literal literal = object.asLiteral() ; + String lang = literal.getLanguage(); + if ( Util.isLangString(literal) || Util.isDirLangString(literal) ) { + // has language tag + // And don't print datatype; + wLangAndBaseDirection(literal); + } else if ( !Util.isSimpleString(literal) ) { + maybeNewline(); + wDatatype(literal.getDatatypeURI()); + } + print(">"); + String escLex = Util.substituteEntitiesInElementContent(literal.getLexicalForm()); + print(escLex); + } else { + throw new JenaException("Triple terms not supported in RDF/XML"); + } + + // End property. + print("</"); + wtype.wTypeEnd(property); + print(">"); } /* @@ -403,9 +614,10 @@ class Unparser { // Conditions if (!(val instanceof Resource)) return false; + Resource r = (Resource) val; if ( r.isStatementTerm() ) - throw new JenaException("Triple terms not supported in RDF/XML"); + return false; if (!(allPropsAreAttr(r) || doing.contains(r))) return false; @@ -497,8 +709,7 @@ class Unparser { /* * [6.12.3] propertyElt ::= '<' propName idAttr? parseResource '>' propertyElt* '</' propName '>' */ - private boolean wPropertyEltResource(WType wt, Property prop, Statement s, - RDFNode r) { + private boolean wPropertyEltResource(WType wt, Property prop, Statement s, RDFNode r) { if (prettyWriter.sParseTypeResourcePropertyElt) return false; if (r instanceof Literal) @@ -529,8 +740,7 @@ class Unparser { /* * [6.12] propertyElt ::= '<' propName idAttr? '>' value '</' propName '>' */ - private boolean wPropertyEltValue(WType wt, Property prop, Statement s, - RDFNode r) { + private boolean wPropertyEltValue(WType wt, Property prop, Statement s, RDFNode r) { return wPropertyEltValueString(wt, prop, s, r) || wPropertyEltValueObj(wt, prop, s, r); } @@ -538,19 +748,16 @@ class Unparser { /* * [6.12] propertyElt ::= '<' propName idAttr? '>' value '</' propName '>' */ - private boolean wPropertyEltValueString(WType wt, Property prop, - Statement s, RDFNode r) { + private boolean wPropertyEltValueString(WType wt, Property prop, Statement s, RDFNode r) { if (r instanceof Literal) { done(s); Literal lt = (Literal) r; - String lang = lt.getLanguage(); tab(); print("<"); wt.wTypeStart(prop); wIdAttrReified(s); maybeNewline(); - if (lang != null && lang.length() > 0) - print(" xml:lang=" + q(lang)); + wLangAndBaseDirection(lt); maybeNewline(); print(">"); wValueString(lt); @@ -563,6 +770,23 @@ class Unparser { } + private void wLangAndBaseDirection(Literal literal) { + String lang = literal.getLanguage(); + if ( lang == null || lang.isEmpty() ) + return; + String baseDir = literal.getBaseDirection(); +// if ( baseDir != null ) { +// if ( itsInsertNs ) +// print(format(" xmlns:%s=\"%s\"", itsPrefix, ITS.uri)); +// } + print(" xml:lang=" + q(lang)); + if ( baseDir != null ) { + // done in rdf:RDFs + //print(format(" %s:%s=%s", itsPrefix, ITS.version, q("2.0"))); + print(format(" %s:%s=%s", itsPrefix, ITS.dir, q(baseDir))); + } + } + /* * [6.17.2] value ::= string */ @@ -575,8 +799,7 @@ class Unparser { * [6.12] propertyElt ::= '<' propName idAttr? '>' value '</' propName '>' * [6.17.1] value ::= obj */ - private boolean wPropertyEltValueObj(WType wt, Property prop, Statement s, - RDFNode r) { + private boolean wPropertyEltValueObj(WType wt, Property prop, Statement s, RDFNode r) { if (r instanceof Resource && !prettyWriter.sResourcePropertyElt) { Resource res = (Resource) r; done(s); @@ -603,8 +826,7 @@ class Unparser { /* * '<' propName idAttr? parseCollection '>' obj* '</' propName '>' */ - private boolean wPropertyEltCollection(WType wt, Property prop, - Statement s, RDFNode r) { + private boolean wPropertyEltCollection(WType wt, Property prop, Statement s, RDFNode r) { Statement list[][] = getRDFList(r); if (list == null) return false; @@ -837,8 +1059,7 @@ class Unparser { * [6.13.2] typedNode ::= * '<' typeName idAboutAttr? bagIdAttr? propAttr*'>' propertyElt* '</' typeName '>' */ - private boolean wTypedNodeOrDescriptionLong(WType wt, Resource ty, - Resource r, List<Statement> li) { + private boolean wTypedNodeOrDescriptionLong(WType wt, Resource ty, Resource r, List<Statement> li) { Iterator<Statement> it = li.iterator(); while (it.hasNext()) { done(it.next()); @@ -924,7 +1145,6 @@ class Unparser { } return false; - } /* @@ -1211,6 +1431,11 @@ class Unparser { if (!r.isAnon()) return false; Integer v = objectTable.get(r); +// if ( v == null ) +// return true; +// return !prettyWriter.sResourcePropertyElt && +// v.intValue() <= 1 && +// !haveReified.contains(r); return v == null || ((!prettyWriter.sResourcePropertyElt) && v.intValue() <= 1 && (!haveReified .contains(r))); @@ -1501,11 +1726,9 @@ class Unparser { } /** - * @param n - * The value of some rdf:type (precondition). + * @param n The value of some rdf:type (precondition). * @return The split point or -1. */ - private int isOKType(RDFNode n) { if (!(n instanceof Resource)) diff --git a/jena-arq/src/test/java/org/apache/jena/system/TS_System.java b/jena-core/src/main/java/org/apache/jena/vocabulary/ITS.java similarity index 62% copy from jena-arq/src/test/java/org/apache/jena/system/TS_System.java copy to jena-core/src/main/java/org/apache/jena/vocabulary/ITS.java index cb22b2c717..72e7f5ffc3 100644 --- a/jena-arq/src/test/java/org/apache/jena/system/TS_System.java +++ b/jena-core/src/main/java/org/apache/jena/vocabulary/ITS.java @@ -19,23 +19,21 @@ * SPDX-License-Identifier: Apache-2.0 */ -package org.apache.jena.system; +package org.apache.jena.vocabulary; -import org.junit.platform.suite.api.SelectClasses; -import org.junit.platform.suite.api.Suite; +/** + * See <a href="https://www.w3.org/TR/its20/">Internationalization Tag Set (ITS) Version 2.0</a> + */ +public class ITS { + /** + * The namespace as a string + * NB the namespace does not end in '/' or '#'. + */ + public static final String uri = "http://www.w3.org/2005/11/its"; -@Suite -@SelectClasses({ - TestCounter.class - , TestThreadAction.class - , TestTxnLifecycle.class - , TestTxnOp.class - , TestTxn.class - , TestTxnThread.class - , TestReadXML.class - , TestPrefixes.class - , TestPrefixLib.class - , TestRDFStarTranslation.class -}) + // There are no resources in this vocabulary. + // ITS = Internationalization Tag Set -public class TS_System {} + public static final String version = "version"; + public static final String dir = "dir"; +} diff --git a/jena-core/src/test/java/org/apache/jena/rdfxml/xmloutput/TestXMLAbbrev.java b/jena-core/src/test/java/org/apache/jena/rdfxml/xmloutput/TestXMLAbbrev.java index f45b865896..ea96b64ca6 100644 --- a/jena-core/src/test/java/org/apache/jena/rdfxml/xmloutput/TestXMLAbbrev.java +++ b/jena-core/src/test/java/org/apache/jena/rdfxml/xmloutput/TestXMLAbbrev.java @@ -140,7 +140,7 @@ public class TestXMLAbbrev extends XMLOutputTestBase { check("testing/abbreviated/cookup.rdf", null, - "j.cook.up", + "(j\\.fixup|j\\.cook\\.up)", Change.blockRules( "" ) ); } diff --git a/jena-core/src/test/java/org/apache/jena/rdfxml/xmloutput/TestXMLFeatures.java b/jena-core/src/test/java/org/apache/jena/rdfxml/xmloutput/TestXMLFeatures.java index 02d749e2e1..f1c8a7450c 100644 --- a/jena-core/src/test/java/org/apache/jena/rdfxml/xmloutput/TestXMLFeatures.java +++ b/jena-core/src/test/java/org/apache/jena/rdfxml/xmloutput/TestXMLFeatures.java @@ -188,7 +188,7 @@ public class TestXMLFeatures extends XMLOutputTestBase { public void testRDFDefaultNamespace() throws IOException { check(file1, "xmlns=['\"]" + RDF.getURI() + "['\"].*" - + "xmlns:j.cook.up=['\"]" + RDF.getURI() + "['\"]", Change + + "xmlns:(j\\.cook.up|j\\.fixup)=['\"]" + RDF.getURI() + "['\"]", Change .setPrefix("", RDF.getURI())); }
