You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by an...@apache.org on 2013/01/18 18:42:53 UTC
svn commit: r1435266 - in /jena/Experimental/riot-output: ./ src/ src/main/
src/main/java/ src/main/java/dev/ src/main/java/out/ src/main/resources/
src/test/ src/test/java/ src/test/resources/
Author: andy
Date: Fri Jan 18 17:42:53 2013
New Revision: 1435266
URL: http://svn.apache.org/viewvc?rev=1435266&view=rev
Log:
Experimentation for better output routines.
Part 1 : a streaming writer that is eaier to read than the usual N-triples/N-quads.
Added:
jena/Experimental/riot-output/.classpath
jena/Experimental/riot-output/.project
jena/Experimental/riot-output/D.ttl
jena/Experimental/riot-output/src/
jena/Experimental/riot-output/src/main/
jena/Experimental/riot-output/src/main/java/
jena/Experimental/riot-output/src/main/java/dev/
jena/Experimental/riot-output/src/main/java/dev/OutputMain.java
jena/Experimental/riot-output/src/main/java/dev/PrintTurtleStreamRDF.java
jena/Experimental/riot-output/src/main/java/out/
jena/Experimental/riot-output/src/main/java/out/EscapeStr.java
jena/Experimental/riot-output/src/main/java/out/NodeFmtLib.java
jena/Experimental/riot-output/src/main/java/out/NodeFormatter.java
jena/Experimental/riot-output/src/main/java/out/NodeFormatterBase.java
jena/Experimental/riot-output/src/main/java/out/NodeFormatterNT.java
jena/Experimental/riot-output/src/main/java/out/NodeFormatterTTL.java
jena/Experimental/riot-output/src/main/java/out/OutputUtils.java
jena/Experimental/riot-output/src/main/resources/
jena/Experimental/riot-output/src/test/
jena/Experimental/riot-output/src/test/java/
jena/Experimental/riot-output/src/test/resources/
Added: jena/Experimental/riot-output/.classpath
URL: http://svn.apache.org/viewvc/jena/Experimental/riot-output/.classpath?rev=1435266&view=auto
==============================================================================
--- jena/Experimental/riot-output/.classpath (added)
+++ jena/Experimental/riot-output/.classpath Fri Jan 18 17:42:53 2013
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry including="**/*.java" kind="src" path="src/main/java"/>
+ <classpathentry including="**/*.java" kind="src" path="src/test/java"/>
+ <classpathentry excluding="**/*.java" kind="src" path="src/main/resources"/>
+ <classpathentry excluding="**/*.java" kind="src" path="src/test/resources"/>
+
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
+
+ <classpathentry kind="output" path="classes"/>
+
+ <classpathentry combineaccessrules="false" kind="src" path="/jena-arq"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/jena-core"/>
+
+ <classpathentry kind="lib" path="/home/afs/.m2/repo/org/apache/jena/jena-iri/0.9.5-SNAPSHOT/jena-iri-0.9.5-SNAPSHOT.jar"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/jena-tdb"/>
+ <classpathentry kind="var" path="M2_REPO/org/slf4j/slf4j-api/1.6.4/slf4j-api-1.6.4.jar" sourcepath="M2_REPO/org/slf4j/slf4j-api/1.6.4/slf4j-api-1.6.4-sources.jar"/>
+ <classpathentry kind="var" path="M2_REPO/org/slf4j/slf4j-log4j12/1.6.4/slf4j-log4j12-1.6.4.jar" sourcepath="M2_REPO/org/slf4j/slf4j-log4j12/1.6.4/slf4j-log4j12-1.6.4-sources.jar"/>
+ <classpathentry kind="var" path="M2_REPO/log4j/log4j/1.2.16/log4j-1.2.16.jar" sourcepath="M2_REPO/log4j/log4j/1.2.16/log4j-1.2.16-sources.jar"/>
+ <classpathentry kind="var" path="M2_REPO/org/slf4j/jcl-over-slf4j/1.6.4/jcl-over-slf4j-1.6.4.jar" sourcepath="M2_REPO/org/slf4j/jcl-over-slf4j/1.6.4/jcl-over-slf4j-1.6.4-sources.jar"/>
+</classpath>
Added: jena/Experimental/riot-output/.project
URL: http://svn.apache.org/viewvc/jena/Experimental/riot-output/.project?rev=1435266&view=auto
==============================================================================
--- jena/Experimental/riot-output/.project (added)
+++ jena/Experimental/riot-output/.project Fri Jan 18 17:42:53 2013
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>riot-output</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
Added: jena/Experimental/riot-output/D.ttl
URL: http://svn.apache.org/viewvc/jena/Experimental/riot-output/D.ttl?rev=1435266&view=auto
==============================================================================
--- jena/Experimental/riot-output/D.ttl (added)
+++ jena/Experimental/riot-output/D.ttl Fri Jan 18 17:42:53 2013
@@ -0,0 +1,6 @@
+@prefix : <http://example/> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+
+:s :p :o .
+:s :p (1 2) .
Added: jena/Experimental/riot-output/src/main/java/dev/OutputMain.java
URL: http://svn.apache.org/viewvc/jena/Experimental/riot-output/src/main/java/dev/OutputMain.java?rev=1435266&view=auto
==============================================================================
--- jena/Experimental/riot-output/src/main/java/dev/OutputMain.java (added)
+++ jena/Experimental/riot-output/src/main/java/dev/OutputMain.java Fri Jan 18 17:42:53 2013
@@ -0,0 +1,38 @@
+/*
+ * 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
+ *
+ * http://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.
+ */
+
+package dev;
+
+
+import org.apache.jena.riot.RDFDataMgr ;
+import org.apache.jena.riot.system.StreamRDF ;
+
+public class OutputMain
+{
+ public static void main(String[] args)
+ {
+ StreamRDF dst = new PrintTurtleStreamRDF(System.out);
+ RDFDataMgr.parse(dst, "D.ttl") ;
+ System.out.println("--------") ;
+ dst = new PrintTurtleStreamRDF(System.out);
+ RDFDataMgr.parse(dst, "D.trig") ;
+
+ System.out.println("DONE") ;
+ System.exit(0) ;
+ }
+}
Added: jena/Experimental/riot-output/src/main/java/dev/PrintTurtleStreamRDF.java
URL: http://svn.apache.org/viewvc/jena/Experimental/riot-output/src/main/java/dev/PrintTurtleStreamRDF.java?rev=1435266&view=auto
==============================================================================
--- jena/Experimental/riot-output/src/main/java/dev/PrintTurtleStreamRDF.java (added)
+++ jena/Experimental/riot-output/src/main/java/dev/PrintTurtleStreamRDF.java Fri Jan 18 17:42:53 2013
@@ -0,0 +1,236 @@
+/**
+ * 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
+ *
+ * http://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.
+ */
+
+package dev;
+
+import java.io.OutputStream ;
+
+import org.apache.jena.atlas.io.IndentedWriter ;
+import static org.apache.jena.atlas.lib.Lib.equal ;
+import org.apache.jena.atlas.lib.Tuple ;
+import org.apache.jena.riot.out.NodeToLabel ;
+import org.apache.jena.riot.system.PrefixMap ;
+import org.apache.jena.riot.system.StreamRDF ;
+import out.NodeFormatterTTL ;
+
+import com.hp.hpl.jena.graph.Node ;
+import com.hp.hpl.jena.graph.Triple ;
+import com.hp.hpl.jena.sparql.core.Quad ;
+
+class PrintTurtleStreamRDF implements StreamRDF
+{
+ private final PrefixMap pMap ;
+ private final NodeFormatterTTL fmt ;
+ private final IndentedWriter out ;
+
+ private static final int INDENT_G = 2 ;
+ private static final int INDENT_S = 4 ;
+
+ public PrintTurtleStreamRDF(OutputStream output)
+ {
+ this.out = new IndentedWriter(output) ;
+ out.setFlushOnNewline(true) ; // Debugging
+ this.pMap = new PrefixMap() ;
+ this.fmt = new NodeFormatterTTL(null, pMap, NodeToLabel.createScopeByDocument()) ;
+ }
+
+
+ @Override
+ public void start()
+ {}
+
+ private boolean lastWasTripleData = false ;
+ private boolean lastWasQuadData = false ;
+ private boolean lastWasDirective = false ;
+
+ private Node lastSubject = null ;
+ private Node lastGraph = null ;
+
+ private void out(Node n)
+ {
+ fmt.format(out, n) ;
+ }
+
+ private void reset()
+ {
+ lastWasTripleData = false ;
+ lastWasQuadData = false ;
+ lastWasDirective = false ;
+ lastSubject = null ;
+ lastGraph = null ;
+ }
+
+ private void printPre()
+ {
+ // Directive -> data transition.
+ if ( lastWasDirective )
+ {
+ reset() ;
+ out.print('\n') ;
+ }
+ }
+
+ private void print(Node g, Node s, Node p, Node o)
+ {
+ printPre() ;
+
+ // End of graph
+ if ( lastSubject != null && ! equal(lastGraph, g) )
+ {
+ //out.println() ;
+ out.print(" ") ;
+ out.decIndent(INDENT_G) ;
+ out.decIndent(INDENT_S) ;
+ out.println("}") ;
+ lastSubject = null ;
+ lastGraph = null ;
+
+ }
+ // Start graph
+ if ( lastGraph == null )
+ {
+ if ( lastSubject != null )
+ {
+ out.decIndent(INDENT_S) ;
+ out.println(" .") ;
+ }
+ lastSubject = null ;
+ if ( g != null )
+ {
+ fmt.format(out, g) ;
+ out.print(" ") ;
+ }
+ out.println("{") ;
+ out.incIndent(INDENT_G) ;
+ }
+ print$(s,p,o) ;
+ lastGraph = g ;
+ lastWasQuadData = true ;
+ }
+
+ private void print(Node s, Node p, Node o)
+ {
+ printPre() ;
+ print$(s, p, o) ;
+ lastWasTripleData = true ;
+ }
+
+ private void print$(Node s, Node p, Node o)
+ {
+ if ( equal(lastSubject, s) )
+ {
+ out.println(" ;") ;
+ fmt.format(out, p) ;
+ out.print(' ') ;
+ fmt.format(out, o) ;
+ } else {
+ // Change subject, same graph.
+ if ( lastSubject != null )
+ {
+ // DRY
+ out.print(" .") ;
+ out.decIndent(INDENT_S) ;
+ out.println() ;
+ }
+
+ fmt.format(out, s) ;
+ out.print(' ') ;
+ fmt.format(out, p) ;
+ out.print(' ') ;
+ fmt.format(out, o) ;
+ out.incIndent(INDENT_S) ;
+
+ }
+ lastSubject = s ;
+ }
+
+ @Override
+ public void triple(Triple triple)
+ {
+ Node s = triple.getSubject() ;
+ Node p = triple.getPredicate() ;
+ Node o = triple.getObject() ;
+ print(s,p,o) ;
+ }
+
+ @Override
+ public void quad(Quad quad)
+ {
+ Node g = quad.getGraph() ;
+ Node s = quad.getSubject() ;
+ Node p = quad.getPredicate() ;
+ Node o = quad.getObject() ;
+ print(g, s, p, o) ;
+ }
+
+ @Override
+ public void tuple(Tuple<Node> tuple)
+ {}
+
+ @Override
+ public void base(String base)
+ {
+
+ }
+
+ private void endData()
+ {
+ if ( lastWasTripleData )
+ {
+ out.println(" .") ;
+ out.decIndent(INDENT_S) ;
+ }
+
+ if ( lastWasQuadData )
+ {
+ // DRY
+ out.print(" ") ;
+ out.decIndent(INDENT_G) ;
+ out.decIndent(INDENT_S) ;
+ out.println("}") ;
+ }
+
+ reset() ;
+ }
+
+ @Override
+ public void prefix(String prefix, String iri)
+ {
+ boolean b = lastWasTripleData || lastWasQuadData ;
+ endData() ;
+ if ( b )
+ out.println() ;
+
+ lastWasDirective = true ;
+
+ out.print("@prefix ") ;
+ out.print(prefix) ;
+ out.print(": <") ;
+ out.print(iri) ; // Don't let it be abbreviated!
+ out.println("> .") ;
+ pMap.add(prefix, iri) ;
+ }
+
+ @Override
+ public void finish()
+ {
+ endData() ;
+ out.flush() ;
+ }
+
+}
Added: jena/Experimental/riot-output/src/main/java/out/EscapeStr.java
URL: http://svn.apache.org/viewvc/jena/Experimental/riot-output/src/main/java/out/EscapeStr.java?rev=1435266&view=auto
==============================================================================
--- jena/Experimental/riot-output/src/main/java/out/EscapeStr.java (added)
+++ jena/Experimental/riot-output/src/main/java/out/EscapeStr.java Fri Jan 18 17:42:53 2013
@@ -0,0 +1,117 @@
+/*
+ * 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
+ *
+ * http://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.
+ */
+
+package out;
+
+import org.apache.jena.atlas.io.IndentedLineBuffer ;
+import org.apache.jena.atlas.io.IndentedWriter ;
+
+import com.hp.hpl.jena.sparql.lang.ParserBase ;
+
+public class EscapeStr
+{
+ // Tests: TestOutput
+ // See also OutputLangUtils.outputEsc.
+ private final boolean ascii ;
+
+ public EscapeStr(boolean asciiOnly) { this.ascii = asciiOnly ; }
+
+ public void writeURI(IndentedWriter w, String s)
+ {
+ if ( ascii )
+ stringEsc(w, s, true, ascii) ;
+ else
+ // It's a URI - assume legal.
+ w.print(s) ;
+ }
+
+ public void writeStr(IndentedWriter w, String s)
+ {
+ stringEsc(w, s, true, ascii) ;
+ }
+
+ public void writeStrMultiLine(IndentedWriter w, String s)
+ {
+ // N-Triples does not have """
+ stringEsc(w, s, false, ascii) ;
+ }
+
+ // Utility
+ /*
+ * Escape characters in a string according to Turtle rules.
+ */
+ public static String stringEsc(String s)
+ { return stringEsc(s, true, false) ; }
+
+ private static String stringEsc(String s, boolean singleLineString, boolean asciiOnly)
+ {
+ IndentedLineBuffer sb = new IndentedLineBuffer() ;
+ stringEsc(sb, s, singleLineString, asciiOnly) ;
+ return sb.toString() ;
+ }
+
+ public static void stringEsc(IndentedWriter out, String s, boolean singleLineString, boolean asciiOnly)
+ {
+ int len = s.length() ;
+ for (int i = 0; i < len; i++) {
+ char c = s.charAt(i);
+
+ // \\ Escape always possible.
+ if (c == '\\')
+ {
+ out.print('\\') ;
+ out.print(c) ;
+ continue ;
+ }
+ if ( singleLineString )
+ {
+ if ( c == '"' ) { out.print("\\\""); continue ; }
+ else if (c == '\n') { out.print("\\n"); continue ; }
+ else if (c == '\t') { out.print("\\t"); continue ; }
+ else if (c == '\r') { out.print("\\r"); continue ; }
+ else if (c == '\f') { out.print("\\f"); continue ; }
+ }
+ // Not \-style esacpe.
+ if ( c >= 32 && c < 127 )
+ out.print(c);
+ else if ( !asciiOnly )
+ out.print(c);
+ else
+ {
+ // Outside the charset range.
+ // Does not cover beyond 16 bits codepoints directly
+ // (i.e. \U escapes) but Java keeps these as surrogate
+ // pairs and will print as characters
+ out.print( "\\u") ;
+ OutputUtils.printHex(out, c, 4) ;
+ }
+ }
+ }
+
+ // Utilities to remove escapes
+
+ public static String unescapeStr(String s)
+ { return unescape(s, '\\') ; }
+
+ // Worker function
+ public static String unescape(String s, char escape)
+ {
+ return ParserBase.unescape(s, escape, false, -1, -1) ;
+
+ }
+}
Added: jena/Experimental/riot-output/src/main/java/out/NodeFmtLib.java
URL: http://svn.apache.org/viewvc/jena/Experimental/riot-output/src/main/java/out/NodeFmtLib.java?rev=1435266&view=auto
==============================================================================
--- jena/Experimental/riot-output/src/main/java/out/NodeFmtLib.java (added)
+++ jena/Experimental/riot-output/src/main/java/out/NodeFmtLib.java Fri Jan 18 17:42:53 2013
@@ -0,0 +1,205 @@
+/*
+ * 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
+ *
+ * http://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.
+ */
+
+package out;
+
+import java.net.MalformedURLException ;
+import java.util.Map ;
+
+
+import com.hp.hpl.jena.graph.Node ;
+import com.hp.hpl.jena.graph.Triple ;
+
+import org.apache.jena.atlas.io.IndentedLineBuffer ;
+import org.apache.jena.atlas.io.IndentedWriter ;
+import org.apache.jena.atlas.lib.Bytes ;
+import org.apache.jena.atlas.lib.Chars ;
+import org.apache.jena.iri.IRI ;
+import org.apache.jena.iri.IRIFactory ;
+import org.apache.jena.iri.IRIRelativize ;
+import org.apache.jena.riot.system.PrefixMap ;
+import org.apache.jena.riot.system.Prologue ;
+import org.apache.jena.riot.system.RiotChars ;
+
+import com.hp.hpl.jena.shared.PrefixMapping ;
+import com.hp.hpl.jena.sparql.ARQConstants ;
+import com.hp.hpl.jena.sparql.core.Quad ;
+
+/** Presentation utilitiles for Nodes, Triples, Quads and more */
+public class NodeFmtLib
+{
+ // See OutputLangUtils.
+ // See and use EscapeStr
+
+ static PrefixMap dftPrefixMap = new PrefixMap() ;
+ static {
+ PrefixMapping pm = ARQConstants.getGlobalPrefixMap() ;
+ Map<String, String> map = pm.getNsPrefixMap() ;
+ for ( Map.Entry<String, String> e : map.entrySet() )
+ dftPrefixMap.add(e.getKey(), e.getValue() ) ;
+ }
+
+ public static String str(Triple t)
+ {
+ return strNodes(t.getSubject(), t.getPredicate(),t.getObject()) ;
+ }
+
+ public static String str(Quad q)
+ {
+ return strNodes(q.getGraph(), q.getSubject(), q.getPredicate(), q.getObject()) ;
+ }
+
+
+ // Worker
+ public static String strNodes(Node ... nodes)
+ {
+ IndentedLineBuffer sw = new IndentedLineBuffer() ;
+ boolean first = true ;
+ for ( Node n : nodes )
+ {
+ if ( ! first )
+ {
+ sw.append(" ") ;
+ first = false ;
+ }
+ str(sw, n) ;
+ }
+ return sw.toString() ;
+ }
+
+ public static String str(Node n)
+ {
+ IndentedLineBuffer sw = new IndentedLineBuffer() ;
+ str(sw, n) ;
+ return sw.toString() ;
+ }
+
+ private static final boolean onlySafeBNodeLabels = true ;
+
+ //public static String displayStr(Node n) { return serialize(n) ; }
+
+ public static void str(IndentedWriter w, Node n)
+ { serialize(w, n, null, null) ; }
+
+ public static void serialize(IndentedWriter w, Node n, Prologue prologue)
+ { serialize(w, n, prologue.getBaseURI(), prologue.getPrefixMap()) ; }
+
+
+ public static void serialize(IndentedWriter w, Node n, String base, PrefixMap prefixMap)
+ {
+ if ( prefixMap == null )
+ prefixMap = dftPrefixMap ;
+ NodeFormatter formatter = new NodeFormatterTTL(base, prefixMap) ;
+ formatter.format(w, n) ;
+ }
+
+ // ---- Blank node labels.
+
+ // Strict N-triples only allows [A-Za-z][A-Za-z0-9]
+ static char encodeMarkerChar = 'X' ;
+
+ // These two form a pair to convert bNode labels to a safe (i.e. legal N-triples form) and back agains.
+
+ // Encoding is:
+ // 1 - Add a Letter
+ // 2 - Hexify, as Xnn, anything outside ASCII A-Za-z0-9
+ // 3 - X is encoded as XX
+
+ private static char LabelLeadingLetter = 'B' ;
+
+ public static String encodeBNodeLabel(String label)
+ {
+ StringBuilder buff = new StringBuilder() ;
+ // Must be at least one char and not a digit.
+ buff.append(LabelLeadingLetter) ;
+
+ for ( int i = 0 ; i < label.length() ; i++ )
+ {
+ char ch = label.charAt(i) ;
+ if ( ch == encodeMarkerChar )
+ {
+ buff.append(ch) ;
+ buff.append(ch) ;
+ }
+ else if ( RiotChars.isA2ZN(ch) )
+ buff.append(ch) ;
+ else
+ Chars.encodeAsHex(buff, encodeMarkerChar, ch) ;
+ }
+ return buff.toString() ;
+ }
+
+ // Assumes that blank nodes only have characters in the range of 0-255
+ public static String decodeBNodeLabel(String label)
+ {
+ StringBuilder buffer = new StringBuilder() ;
+
+ if ( label.charAt(0) != LabelLeadingLetter )
+ return label ;
+
+ // Skip first.
+ for ( int i = 1; i < label.length(); i++ )
+ {
+ char ch = label.charAt(i) ;
+
+ if ( ch != encodeMarkerChar )
+ {
+ buffer.append(ch) ;
+ }
+ else
+ {
+ // Maybe XX or Xnn.
+ char ch2 = label.charAt(i+1) ;
+ if ( ch2 == encodeMarkerChar )
+ {
+ i++ ;
+ buffer.append(ch) ;
+ continue ;
+ }
+
+ // Xnn
+ i++ ;
+ char hiC = label.charAt(i) ;
+ int hi = Bytes.hexCharToInt(hiC) ;
+ i++ ;
+ char loC = label.charAt(i) ;
+ int lo = Bytes.hexCharToInt(loC) ;
+
+ int combined = ((hi << 4) | lo) ;
+ buffer.append((char) combined) ;
+ }
+ }
+
+ return buffer.toString() ;
+ }
+
+ // ---- Relative URIs.
+
+ static private int relFlags = IRIRelativize.SAMEDOCUMENT | IRIRelativize.CHILD ;
+ static public String abbrevByBase(String uri, String base)
+ {
+ if ( base == null )
+ return null ;
+ IRI baseIRI = IRIFactory.jenaImplementation().construct(base) ;
+ IRI rel = baseIRI.relativize(uri, relFlags) ;
+ String r = null ;
+ try { r = rel.toASCIIString() ; }
+ catch (MalformedURLException ex) { r = rel.toString() ; }
+ return r ;
+ }
+}
Added: jena/Experimental/riot-output/src/main/java/out/NodeFormatter.java
URL: http://svn.apache.org/viewvc/jena/Experimental/riot-output/src/main/java/out/NodeFormatter.java?rev=1435266&view=auto
==============================================================================
--- jena/Experimental/riot-output/src/main/java/out/NodeFormatter.java (added)
+++ jena/Experimental/riot-output/src/main/java/out/NodeFormatter.java Fri Jan 18 17:42:53 2013
@@ -0,0 +1,53 @@
+/*
+ * 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
+ *
+ * http://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.
+ */
+
+package out;
+
+
+import org.apache.jena.atlas.io.IndentedWriter ;
+
+import com.hp.hpl.jena.graph.Node ;
+
+public interface NodeFormatter
+{
+ public void format(IndentedWriter w, Node n) ;
+
+ /** Node is guaranteed to be a URI node */
+ public void formatURI(IndentedWriter w, Node n) ;
+ public void formatURI(IndentedWriter w, String uriStr) ;
+
+ public void formatVar(IndentedWriter w, Node n) ;
+ public void formatVar(IndentedWriter w, String name) ;
+
+ /** Node is guaranteed to be a blank node */
+ public void formatBNode(IndentedWriter w, Node n) ;
+ public void formatBNode(IndentedWriter w, String label) ;
+
+ /** Node is guaranteed to be a literal */
+ public void formatLiteral(IndentedWriter w, Node n) ;
+
+ /** Plain string / xsd:string (RDF 1.1) */
+ public void formatLitString(IndentedWriter w, String lex) ;
+
+ /** String with language tag */
+ public void formatLitLang(IndentedWriter w, String lex, String langTag) ;
+
+ /** Literal with datatype, not a simple literal, not an xsd:string (RDF 1.1), no language tag. */
+ public void formatLitDT(IndentedWriter w, String lex, String datatypeURI) ;
+
+}
Added: jena/Experimental/riot-output/src/main/java/out/NodeFormatterBase.java
URL: http://svn.apache.org/viewvc/jena/Experimental/riot-output/src/main/java/out/NodeFormatterBase.java?rev=1435266&view=auto
==============================================================================
--- jena/Experimental/riot-output/src/main/java/out/NodeFormatterBase.java (added)
+++ jena/Experimental/riot-output/src/main/java/out/NodeFormatterBase.java Fri Jan 18 17:42:53 2013
@@ -0,0 +1,74 @@
+/*
+ * 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
+ *
+ * http://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.
+ */
+
+package out;
+
+import org.apache.jena.atlas.io.IndentedWriter ;
+
+import com.hp.hpl.jena.graph.Node ;
+import com.hp.hpl.jena.sparql.ARQInternalErrorException ;
+
+/** Provide implementations of the operations of NodeFormatter in terms
+ * of core operations for each node type.
+ */
+public abstract class NodeFormatterBase implements NodeFormatter
+{
+ @Override
+ public void format(IndentedWriter w, Node n)
+ {
+ if ( n.isBlank() )
+ formatBNode(w, n) ;
+ else if ( n.isURI() )
+ formatURI(w, n) ;
+ else if ( n.isLiteral() )
+ formatLiteral(w, n) ;
+ else if ( n.isVariable() )
+ formatVar(w, n) ;
+ else if ( Node.ANY.equals(n) )
+ w.print("ANY") ;
+ else
+ throw new ARQInternalErrorException("Unknow node type: "+n) ;
+ }
+
+ @Override
+ public void formatURI(IndentedWriter w, Node n) { formatURI(w, n.getURI()) ; }
+
+ @Override
+ public void formatBNode(IndentedWriter w, Node n) { formatBNode(w, n.getBlankNodeLabel()) ; }
+
+ @Override
+ public void formatLiteral(IndentedWriter w, Node n)
+ {
+ String dt = n.getLiteralDatatypeURI() ;
+ String lang = n.getLiteralLanguage() ;
+ String lex = n.getLiteralLexicalForm() ;
+
+ if ( dt == null )
+ {
+ if ( lang == null || lang.equals("") )
+ formatLitString(w, lex) ;
+ else
+ formatLitLang(w, lex,lang) ;
+ }
+ else
+ formatLitDT(w, lex, dt) ;
+ }
+
+ @Override
+ public void formatVar(IndentedWriter w, Node n) { formatVar(w, n.getName()) ; }
+}
Added: jena/Experimental/riot-output/src/main/java/out/NodeFormatterNT.java
URL: http://svn.apache.org/viewvc/jena/Experimental/riot-output/src/main/java/out/NodeFormatterNT.java?rev=1435266&view=auto
==============================================================================
--- jena/Experimental/riot-output/src/main/java/out/NodeFormatterNT.java (added)
+++ jena/Experimental/riot-output/src/main/java/out/NodeFormatterNT.java Fri Jan 18 17:42:53 2013
@@ -0,0 +1,86 @@
+/*
+ * 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
+ *
+ * http://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.
+ */
+
+package out;
+
+
+import org.apache.jena.atlas.io.IndentedWriter ;
+
+public class NodeFormatterNT extends NodeFormatterBase
+{
+ // Formatting for NTriples
+ // Turtles extends this class to intercept forms it can do better.
+
+ private final EscapeStr escapeProc ;
+
+ public NodeFormatterNT() { this(true) ; }
+
+ protected NodeFormatterNT(boolean asciiOnly) { escapeProc = new EscapeStr(asciiOnly) ;}
+
+ @Override
+ public void formatURI(IndentedWriter w, String uriStr)
+ {
+ w.print('<') ;
+ w.print(uriStr) ;
+ w.print('>') ;
+ }
+
+ @Override
+ public void formatVar(IndentedWriter w, String name)
+ {
+ w.print('?') ;
+ w.print(name) ;
+ }
+
+ @Override
+ public void formatBNode(IndentedWriter w, String label)
+ {
+ w.print("_:") ;
+ String lab = NodeFmtLib.encodeBNodeLabel(label) ;
+ w.print(lab) ;
+ }
+
+ @Override
+ public void formatLitString(IndentedWriter w, String lex)
+ {
+ writeEscaped(w, lex) ;
+ }
+
+ private void writeEscaped(IndentedWriter w, String lex)
+ {
+ w.print('"') ;
+ escapeProc.writeStr(w, lex) ;
+ w.print('"') ;
+ }
+
+ @Override
+ public void formatLitLang(IndentedWriter w, String lex, String langTag)
+ {
+ writeEscaped(w, lex) ;
+ w.print('@') ;
+ w.print(langTag) ;
+ }
+
+ @Override
+ public void formatLitDT(IndentedWriter w, String lex, String datatypeURI)
+ {
+ writeEscaped(w, lex) ;
+ w.print("^^") ;
+ formatURI(w, datatypeURI) ;
+ }
+}
Added: jena/Experimental/riot-output/src/main/java/out/NodeFormatterTTL.java
URL: http://svn.apache.org/viewvc/jena/Experimental/riot-output/src/main/java/out/NodeFormatterTTL.java?rev=1435266&view=auto
==============================================================================
--- jena/Experimental/riot-output/src/main/java/out/NodeFormatterTTL.java (added)
+++ jena/Experimental/riot-output/src/main/java/out/NodeFormatterTTL.java Fri Jan 18 17:42:53 2013
@@ -0,0 +1,340 @@
+/*
+ * 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
+ *
+ * http://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.
+ */
+
+package out;
+
+import java.net.MalformedURLException ;
+
+import org.apache.jena.atlas.io.IndentedWriter ;
+import org.apache.jena.atlas.lib.Pair ;
+import org.apache.jena.iri.IRI ;
+import org.apache.jena.iri.IRIFactory ;
+import org.apache.jena.iri.IRIRelativize ;
+import org.apache.jena.riot.out.NodeToLabel ;
+import org.apache.jena.riot.system.PrefixMap ;
+import org.apache.jena.riot.system.RiotChars ;
+
+import com.hp.hpl.jena.datatypes.xsd.XSDDatatype ;
+import com.hp.hpl.jena.graph.Node ;
+
+public class NodeFormatterTTL extends NodeFormatterNT
+{
+ private final NodeToLabel nodeToLabel ;
+ private final PrefixMap prefixMap ;
+ private final String baseIRI ;
+
+ // Replace with a single "OutputPolicy"
+ public NodeFormatterTTL(String baseIRI , PrefixMap prefixMap) //OutputPolicy outputPolicy)
+ {
+ this(baseIRI, prefixMap, NodeToLabel.createBNodeByLabelEncoded()) ;
+ }
+
+ public NodeFormatterTTL(String baseIRI , PrefixMap prefixMap, NodeToLabel nodeToLabel)
+ {
+ super(false) ;
+ this.nodeToLabel = nodeToLabel ;
+ if ( prefixMap == null )
+ prefixMap = new PrefixMap() ;
+ this.prefixMap = prefixMap ;
+ this.baseIRI = baseIRI ;
+ }
+
+ @Override
+ public void formatURI(IndentedWriter w, String uriStr)
+ {
+ Pair<String, String> pName = prefixMap.abbrev(uriStr) ;
+ // Check if legal
+ if ( pName != null )
+ {
+ // Check legal - need to check legal, not for illegal.
+ String pref = pName.getLeft() ;
+ String ln = pName.getRight() ;
+ if ( safeForPrefix(pref) && safeForPrefixLocalname(ln) )
+ {
+ w.print(pName.getLeft()) ;
+ w.print(':') ;
+ w.print(pName.getRight()) ;
+ return ;
+ }
+ }
+
+ // Attempt base abbreviation.
+ if ( baseIRI != null )
+ {
+ String x = abbrevByBase(uriStr, baseIRI) ;
+ if ( x != null )
+ {
+ w.print('<') ;
+ w.print(x) ;
+ w.print('>') ;
+ return ;
+ }
+ }
+
+ // else
+ super.formatURI(w, uriStr) ;
+ }
+
+ static private int relFlags = IRIRelativize.SAMEDOCUMENT | IRIRelativize.CHILD ;
+ static private String abbrevByBase(String uri, String base)
+ {
+ if ( base == null )
+ return null ;
+ IRI baseIRI = IRIFactory.jenaImplementation().construct(base) ;
+ IRI rel = baseIRI.relativize(uri, relFlags) ;
+ String r = null ;
+ try { r = rel.toASCIIString() ; }
+ catch (MalformedURLException ex) { r = rel.toString() ; }
+ return r ;
+ }
+
+ /*private-testing*/
+ static boolean safeForPrefix(String str)
+ {
+ int N = str.length() ;
+ if ( N == 0 ) return true ;
+ int idx = 0 ;
+ idx = skip1_PN_CHARS_BASE(str, idx) ;
+ if ( idx == -1 ) return false ;
+ idx = skipAny_PN_CHARS_or_DOT(str, idx) ;
+ if ( idx == -1 ) return false ;
+ if ( idx == N ) return true ;
+ idx = skip1_PN_CHARS(str, idx) ;
+ if ( idx == -1 ) return false ;
+ return ( idx == N ) ;
+ }
+
+// @Override
+// public void formatVar(IndentedWriter w, String name)
+
+// @Override
+// public void formatBNode(IndentedWriter w, String label)
+
+ @Override
+ public void formatBNode(IndentedWriter w, Node n)
+ {
+ String x = nodeToLabel.get(null, n) ;
+ w.print(x) ;
+ }
+
+// @Override
+// public void formatLitString(IndentedWriter w, String lex)
+
+// @Override
+// public void formatLitLang(IndentedWriter w, String lex, String langTag)
+
+ /*private-testing*/ static boolean safeForPrefixLocalname(String str)
+ {
+ int N = str.length() ;
+ if ( N == 0 ) return true ;
+ int idx = 0 ;
+ idx = skip1_PN_CHARS_U_or_029(str, idx) ;
+ if ( idx == -1 ) return false ;
+ idx = skipAny_PN_CHARS_or_DOT(str, idx) ;
+ if ( idx == -1 ) return false ;
+ if ( idx == N ) return true ;
+ idx = skip1_PN_CHARS(str, idx) ;
+ return ( idx == N ) ;
+ }
+
+ private static boolean is_PN_CHARS_BASE(int ch) { return RiotChars.isAlpha(ch) ; }
+ private static boolean is_PN_CHARS_U(int ch) { return is_PN_CHARS_BASE(ch) || ch == '_' ; }
+ private static boolean is_PN_CHARS(int ch) { return is_PN_CHARS_U(ch) || ch == '-' || RiotChars.isDigit(ch) || isCharsExtra(ch) ; }
+
+ public static boolean isCharsExtra(int ch)
+ {
+ return ch == '\u00B7' || RiotChars.range(ch, '\u0300', '\u036F') || RiotChars.range(ch, '\u203F', '\u2040') ;
+ }
+
+ private static int skip1_PN_CHARS_U_or_029(String str, int idx)
+ {
+ char ch = str.charAt(idx) ;
+ if ( is_PN_CHARS_U(ch) ) return idx+1 ;
+ if ( RiotChars.isDigit(ch) ) return idx+1 ;
+ return -1 ;
+ }
+
+ private static int skip1_PN_CHARS_BASE(String str, int idx)
+ {
+ char ch = str.charAt(idx) ;
+ if ( is_PN_CHARS_BASE(ch) ) return idx+1 ;
+ return -1 ;
+ }
+
+ private static int skipAny_PN_CHARS_or_DOT(String str, int idx)
+ {
+ int N = str.length() ;
+ for ( int i = idx ; i < N ; i++ )
+ {
+ char ch = str.charAt(i) ;
+ if ( ! is_PN_CHARS(ch) && ch != '.' ) return i ;
+ }
+ return N ;
+ }
+
+ private static int skip1_PN_CHARS(String str, int idx)
+ {
+ char ch = str.charAt(idx) ;
+ if ( is_PN_CHARS(ch) ) return idx+1 ;
+ return -1 ;
+ }
+
+ private static final String dtDecimal = XSDDatatype.XSDdecimal.getURI() ;
+ private static final String dtInteger = XSDDatatype.XSDinteger.getURI() ;
+ private static final String dtDouble = XSDDatatype.XSDdouble.getURI() ;
+ private static final String dtBoolean = XSDDatatype.XSDboolean.getURI() ;
+
+ @Override
+ public void formatLitDT(IndentedWriter w, String lex, String datatypeURI)
+ {
+ if ( dtDecimal.equals(datatypeURI) )
+ {
+ if ( validDecimal(lex) )
+ {
+ w.print(lex) ;
+ return ;
+ }
+ }
+ else if ( dtInteger.equals(datatypeURI) )
+ {
+ if ( validInteger(lex) )
+ {
+ w.print(lex) ;
+ return ;
+ }
+ }
+ if ( dtDouble.equals(datatypeURI) )
+ {
+ if ( validDouble(lex) )
+ {
+ w.print(lex) ;
+ return ;
+ }
+ }
+ // Boolean
+ if ( dtBoolean.equals(datatypeURI) )
+ {
+ // We leave "0" and "1" as-is assumign that if written like that, there was a reason.
+ if ( lex.equals("true") || lex.equals("false") )
+ {
+ w.print(lex) ;
+ return ;
+ }
+ }
+
+ // else.
+ super.formatLitDT(w, lex, datatypeURI) ;
+ }
+
+
+ private static boolean validInteger(String lex)
+ {
+ int N = lex.length() ;
+ if ( N == 0 ) return false ;
+ int idx = 0 ;
+
+ idx = skipSign(lex, idx) ;
+ idx = skipDigits(lex, idx) ;
+ return ( idx == N ) ;
+ }
+
+ private static boolean validDecimal(String lex)
+ {
+ // case : In N3, "." illegal, as is "+." and -." but legal in Turtle.
+ int N = lex.length() ;
+ if ( N <= 1 ) return false ;
+ int idx = 0 ;
+
+ idx = skipSign(lex, idx) ;
+ idx = skipDigits(lex, idx) ; // Maybe none.
+
+ // DOT required.
+ if ( idx >= N ) return false ;
+
+ char ch = lex.charAt(idx) ;
+ if ( ch != '.' ) return false ;
+ idx++ ;
+ // Digit required.
+ if ( idx >= N ) return false ;
+ idx = skipDigits(lex, idx) ;
+ return ( idx == N ) ;
+ }
+
+ private static boolean validDouble(String lex)
+ {
+ int N = lex.length() ;
+ if ( N == 0 ) return false ;
+ int idx = 0 ;
+
+ // Decimal part (except 12. is legal)
+
+ idx = skipSign(lex, idx) ;
+
+ int idx2 = skipDigits(lex, idx) ;
+ boolean initialDigits = ( idx != idx2) ;
+ idx = idx2 ;
+ // Exponent required.
+ if ( idx >= N ) return false ;
+ char ch = lex.charAt(idx) ;
+ if ( ch == '.' )
+ {
+ idx++ ;
+ if ( idx >= N ) return false ;
+ idx2 = skipDigits(lex, idx) ;
+ boolean trailingDigits = ( idx != idx2 ) ;
+ idx = idx2 ;
+ if ( idx >= N ) return false ;
+ if ( !initialDigits && !trailingDigits ) return false ;
+ }
+ // "e" or "E"
+ ch = lex.charAt(idx) ;
+ if ( ch != 'e' && ch != 'E' ) return false ;
+ idx++ ;
+ if ( idx >= N ) return false ;
+ idx = skipSign(lex, idx) ;
+ if ( idx >= N ) return false ; // At least one digit.
+ idx = skipDigits(lex, idx) ;
+ return ( idx == N ) ;
+ }
+
+ /** Skip digits [0-9] and return the index just after the digits,
+ * which may be beyond the length of the string.
+ * May skip zero.
+ */
+ private static int skipDigits(String str, int start)
+ {
+ int N = str.length() ;
+ for ( int i = start ; i < N ; i++ )
+ {
+ char ch = str.charAt(i) ;
+ if ( ! RiotChars.isDigit(ch) )
+ return i ;
+ }
+ return N ;
+ }
+
+ /** Skip any plus or minus */
+ private static int skipSign(String str, int idx)
+ {
+ int N = str.length() ;
+ char ch = str.charAt(idx) ;
+ if ( ch == '+' || ch == '-' )
+ return idx + 1 ;
+ return idx ;
+ }
+}
Added: jena/Experimental/riot-output/src/main/java/out/OutputUtils.java
URL: http://svn.apache.org/viewvc/jena/Experimental/riot-output/src/main/java/out/OutputUtils.java?rev=1435266&view=auto
==============================================================================
--- jena/Experimental/riot-output/src/main/java/out/OutputUtils.java (added)
+++ jena/Experimental/riot-output/src/main/java/out/OutputUtils.java Fri Jan 18 17:42:53 2013
@@ -0,0 +1,78 @@
+/*
+ * 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
+ *
+ * http://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.
+ */
+
+package out;
+
+import java.io.IOException ;
+import java.io.Writer ;
+
+import org.apache.jena.atlas.io.IndentedWriter ;
+import org.apache.jena.atlas.lib.BitsInt ;
+import org.apache.jena.atlas.lib.Chars ;
+
+public class OutputUtils
+{
+ /** Print the number x in width hex chars. x must fit */
+ public static void printHex(StringBuilder out, int x, int width)
+ {
+ for ( int i = width-1 ; i >= 0 ; i-- )
+ x = oneHex(out, x, i) ;
+ }
+
+ /** Print one hex digit of the number */
+ public static int oneHex(StringBuilder out, int x, int i)
+ {
+ int y = BitsInt.unpack(x, 4*i, 4*i+4) ;
+ char charHex = Chars.hexDigitsUC[y] ;
+ out.append(charHex) ;
+ return BitsInt.clear(x, 4*i, 4*i+4) ;
+ }
+
+ /** Print the number x in width hex chars. x must fit */
+ public static void printHex(Writer out, int x, int width)
+ {
+ for ( int i = width-1 ; i >= 0 ; i-- )
+ x = oneHex(out, x, i) ;
+ }
+
+ /** Print one hex digit of the numer */
+ public static int oneHex(Writer out, int x, int i)
+ {
+ int y = BitsInt.unpack(x, 4*i, 4*i+4) ;
+ char charHex = Chars.hexDigitsUC[y] ;
+ try { out.write(charHex) ; } catch (IOException ex) {}
+ return BitsInt.clear(x, 4*i, 4*i+4) ;
+ }
+
+ /** Print the number x in width hex chars. x must fit */
+ public static void printHex(IndentedWriter out, int x, int width)
+ {
+ for ( int i = width-1 ; i >= 0 ; i-- )
+ x = oneHex(out, x, i) ;
+ }
+
+ /** Print one hex digit of the number */
+ public static int oneHex(IndentedWriter out, int x, int i)
+ {
+ int y = BitsInt.unpack(x, 4*i, 4*i+4) ;
+ char charHex = Chars.hexDigitsUC[y] ;
+ out.print(charHex) ;
+ return BitsInt.clear(x, 4*i, 4*i+4) ;
+ }
+
+}