diff --git a/jena-arq/src/main/java/org/apache/jena/riot/system/InitRIOT.java b/jena-arq/src/main/java/org/apache/jena/riot/system/InitRIOT.java index 18b514b76a3..1f03826d51d 100644 --- a/jena-arq/src/main/java/org/apache/jena/riot/system/InitRIOT.java +++ b/jena-arq/src/main/java/org/apache/jena/riot/system/InitRIOT.java @@ -27,6 +27,7 @@ public class InitRIOT implements JenaSubsystemLifecycle { @Override public void start() { RIOT.init(); + SerializerRDF.init(); } @Override diff --git a/jena-arq/src/main/java/org/apache/jena/riot/system/SNode.java b/jena-arq/src/main/java/org/apache/jena/riot/system/SNode.java new file mode 100644 index 00000000000..193cf2cf628 --- /dev/null +++ b/jena-arq/src/main/java/org/apache/jena/riot/system/SNode.java @@ -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 org.apache.jena.riot.system; + +import java.io.IOException; +import java.io.ObjectStreamException; +import java.io.Serializable; + +import org.apache.jena.graph.Node; +import org.apache.jena.riot.thrift.TRDF; +import org.apache.jena.riot.thrift.wire.RDF_Term; +import org.apache.thrift.protocol.TProtocol; + +/** Serialization of a {@link Node} using Thrift for the serialization. */ +public final class SNode implements Serializable { + private static final long serialVersionUID = 0xb17aa042f299adb9L; + private transient Node node; + + public SNode(Node node) { this.node = node; } + public Node getNode() { return node; } + + private void writeObject(java.io.ObjectOutputStream out) throws IOException { + TProtocol protocol = TRDF.protocol(out); + RDF_Term tterm = new RDF_Term(); + SerializerRDF.write(protocol, tterm, node); + TRDF.flush(protocol); + } + + private void readObject(java.io.ObjectInputStream in) throws IOException { + TProtocol protocol = TRDF.protocol(in); + RDF_Term tterm = new RDF_Term(); + node = SerializerRDF.read(protocol, tterm); + } + + Object readResolve() throws ObjectStreamException + { return node; } +} diff --git a/jena-arq/src/main/java/org/apache/jena/riot/system/SQuad.java b/jena-arq/src/main/java/org/apache/jena/riot/system/SQuad.java new file mode 100644 index 00000000000..12abe3d982b --- /dev/null +++ b/jena-arq/src/main/java/org/apache/jena/riot/system/SQuad.java @@ -0,0 +1,62 @@ +/* + * 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 org.apache.jena.riot.system; + +import java.io.IOException; +import java.io.ObjectStreamException; +import java.io.Serializable; + +import org.apache.jena.graph.Node; +import org.apache.jena.riot.thrift.TRDF; +import org.apache.jena.riot.thrift.wire.RDF_Term; +import org.apache.jena.sparql.core.Quad; +import org.apache.thrift.protocol.TProtocol; + +/** Serialization of a {@link Quad} using Thrift for the serialization. */ +public final class SQuad implements Serializable { + private static final long serialVersionUID = 0x993530716d72ff06L; + private transient Quad quad; + + public SQuad(Quad quad) { this.quad = quad; } + public Quad getQuad() { return quad; } + + private void writeObject(java.io.ObjectOutputStream out) throws IOException { + TProtocol protocol = TRDF.protocol(out); + RDF_Term tterm = new RDF_Term(); + SerializerRDF.write(protocol, tterm, quad.getGraph()); + SerializerRDF.write(protocol, tterm, quad.getSubject()); + SerializerRDF.write(protocol, tterm, quad.getPredicate()); + SerializerRDF.write(protocol, tterm, quad.getObject()); + TRDF.flush(protocol); + } + + private void readObject(java.io.ObjectInputStream in) throws IOException { + TProtocol protocol = TRDF.protocol(in); + RDF_Term tterm = new RDF_Term(); + Node g = SerializerRDF.read(protocol, tterm); + Node s = SerializerRDF.read(protocol, tterm); + Node p = SerializerRDF.read(protocol, tterm); + Node o = SerializerRDF.read(protocol, tterm); + quad = Quad.create(g, s, p, o); + } + + Object readResolve() throws ObjectStreamException + { return quad; } + +} \ No newline at end of file diff --git a/jena-arq/src/main/java/org/apache/jena/riot/system/STriple.java b/jena-arq/src/main/java/org/apache/jena/riot/system/STriple.java new file mode 100644 index 00000000000..dc5ab2309a1 --- /dev/null +++ b/jena-arq/src/main/java/org/apache/jena/riot/system/STriple.java @@ -0,0 +1,59 @@ +/* + * 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 org.apache.jena.riot.system; + +import java.io.IOException; +import java.io.ObjectStreamException; +import java.io.Serializable; + +import org.apache.jena.graph.Node; +import org.apache.jena.graph.Triple; +import org.apache.jena.riot.thrift.TRDF; +import org.apache.jena.riot.thrift.wire.RDF_Term; +import org.apache.thrift.protocol.TProtocol; + +/** Serialization of a {@link Triple} using Thrift for the serialization. */ +public final class STriple implements Serializable { + private static final long serialVersionUID = 0xa08f3324dc69187dL; + private transient Triple triple; + + public STriple(Triple triple) { this.triple = triple; } + public Triple getTriple() { return triple; } + + private void writeObject(java.io.ObjectOutputStream out) throws IOException { + TProtocol protocol = TRDF.protocol(out); + RDF_Term tterm = new RDF_Term(); + SerializerRDF.write(protocol, tterm, triple.getSubject()); + SerializerRDF.write(protocol, tterm, triple.getPredicate()); + SerializerRDF.write(protocol, tterm, triple.getObject()); + TRDF.flush(protocol); + } + + private void readObject(java.io.ObjectInputStream in) throws IOException { + TProtocol protocol = TRDF.protocol(in); + RDF_Term tterm = new RDF_Term(); + Node s = SerializerRDF.read(protocol, tterm); + Node p = SerializerRDF.read(protocol, tterm); + Node o = SerializerRDF.read(protocol, tterm); + triple = Triple.create(s, p, o); + } + + Object readResolve() throws ObjectStreamException + { return triple; } +} \ No newline at end of file diff --git a/jena-arq/src/main/java/org/apache/jena/riot/system/Serializer.java b/jena-arq/src/main/java/org/apache/jena/riot/system/Serializer.java new file mode 100644 index 00000000000..1c2e090021f --- /dev/null +++ b/jena-arq/src/main/java/org/apache/jena/riot/system/Serializer.java @@ -0,0 +1,58 @@ +/* + * 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 org.apache.jena.riot.system; + +import java.io.Serializable; +import java.util.function.Function; + +import org.apache.jena.sparql.core.Quad; + +/** The injection point for the Quad {@link Serializable} process. + * This class is public to allow system initialization to inject + * handler functions for {@link Quad}. + * + * See also {@code Node} and {@ocde Triple}. + */ +public class Serializer { + /*package*/ static Function quadWriteReplaceFunction = null; + + /** Set the quad serializer replacement function. + * This is a function called by {@code Triple.writeReplace} during the {@link Serializable} process. + * The return is an object used in place of {@link Quad} for the serialization. + * + *
+     * ANY-ACCESS-MODIFIER Object writeReplace() throws ObjectStreamException;
+     * 

+ * The returned object must provide + *

+     * ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException;
+     * 

+ * where "Object" is a {@link Quad}. + * + * @see java.io.Serializable + */ + public static void setQuadSerializer(Function writeReplaceFunction) { + quadWriteReplaceFunction = writeReplaceFunction; + } + + /** Return the current triple serializer replacement function. */ + public static Function getQuadSerializer() { + return quadWriteReplaceFunction; + } +} diff --git a/jena-arq/src/main/java/org/apache/jena/riot/system/SerializerRDF.java b/jena-arq/src/main/java/org/apache/jena/riot/system/SerializerRDF.java new file mode 100644 index 00000000000..f5d7a734ced --- /dev/null +++ b/jena-arq/src/main/java/org/apache/jena/riot/system/SerializerRDF.java @@ -0,0 +1,73 @@ +/* + * 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 org.apache.jena.riot.system; + +import org.apache.jena.graph.Node; +import org.apache.jena.riot.thrift.TRDF; +import org.apache.jena.riot.thrift.ThriftConvert; +import org.apache.jena.riot.thrift.wire.RDF_Term; +import org.apache.thrift.TException; +import org.apache.thrift.protocol.TProtocol; + +public class SerializerRDF { + + public static void init() { + org.apache.jena.system.Serializer.setNodeSerializer(SNode::new); + org.apache.jena.system.Serializer.setTripleSerializer(STriple::new); + org.apache.jena.riot.system.Serializer.setQuadSerializer(SQuad::new); + } + + /*

+    * ANY-ACCESS-MODIFIER Object writeReplace() throws ObjectStreamException;
+    * 

+ * + * This writeReplace method is invoked by serialization if the method + * exists and it would be accessible from a method defined within the + * class of the object being serialized. Thus, the method can have private, + * protected and package-private access. Subclass access to this method + * follows java accessibility rules.

+ * + * Classes that need to designate a replacement when an instance of it + * is read from the stream should implement this special method with the + * exact signature. + * + *

+    * ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException;
+    * 

+ */ + + static Node read(TProtocol protocol, RDF_Term tterm) { + tterm.clear(); + try { tterm.read(protocol); } + catch (TException e) { TRDF.exception(e); } + return ThriftConvert.convert(tterm); + } + + // For now - no prefix map, no value encoding. + // The benefit unclear, sometimes even a bit slower (few percent). + private static final PrefixMap pmap = null; + private static final boolean encodeValues = false; + + static void write(TProtocol protocol, RDF_Term tterm, Node node) { + tterm.clear(); + ThriftConvert.toThrift(node, pmap, tterm, encodeValues); + try { tterm.write(protocol); } + catch (TException e) { TRDF.exception(e); } + } +} diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/core/Quad.java b/jena-arq/src/main/java/org/apache/jena/sparql/core/Quad.java index 143299c7ca2..d7b152b59d5 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/core/Quad.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/core/Quad.java @@ -18,14 +18,19 @@ package org.apache.jena.sparql.core; +import java.io.IOException; +import java.io.ObjectStreamException; +import java.io.Serializable; import java.util.Objects; +import java.util.function.Function; import org.apache.jena.graph.Node ; import org.apache.jena.graph.NodeFactory ; import org.apache.jena.graph.Triple ; +import org.apache.jena.riot.system.Serializer; -public class Quad -{ +public class Quad implements Serializable +{ // Create QuadNames? GraphNames? /** Name of the default for explict use in GRAPH */ @@ -163,6 +168,22 @@ public boolean isLegalAsData() return true ; } + // ---- Serializable + protected Object writeReplace() throws ObjectStreamException { + Function function = Serializer.getQuadSerializer() ; + if ( function == null ) + throw new IllegalStateException("Function for Quad.writeReplace not set") ; + return function.apply(this); + } + // Any attempt to serialize without replacement is an error. + private void writeObject(java.io.ObjectOutputStream out) throws IOException { + throw new IllegalStateException(); + } + private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { + throw new IllegalStateException(); + } + // ---- Serializable + @Override public int hashCode() { diff --git a/jena-arq/src/test/java/org/apache/jena/riot/system/TS_RiotSystem.java b/jena-arq/src/test/java/org/apache/jena/riot/system/TS_RiotSystem.java index 7b4f08d53a0..d3fa45ba790 100644 --- a/jena-arq/src/test/java/org/apache/jena/riot/system/TS_RiotSystem.java +++ b/jena-arq/src/test/java/org/apache/jena/riot/system/TS_RiotSystem.java @@ -45,7 +45,8 @@ , TestIO_JenaWriters.class , TestLangRegistration.class , TestFormatRegistration.class - , TestJsonLDReadWrite.class // Some simple testing of the jsonld-java engine. + , TestJsonLDReadWrite.class // Some simple testing of the jsonld-java engine. + , TestSerializable.class // May be subject to performance vagaries, with the improvements made // to the fast implementation this should be fairly safe diff --git a/jena-arq/src/test/java/org/apache/jena/riot/system/TestSerializable.java b/jena-arq/src/test/java/org/apache/jena/riot/system/TestSerializable.java new file mode 100644 index 00000000000..8f4c99ba3d2 --- /dev/null +++ b/jena-arq/src/test/java/org/apache/jena/riot/system/TestSerializable.java @@ -0,0 +1,168 @@ +/* + * 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 org.apache.jena.riot.system; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +import java.io.*; + +import org.apache.jena.graph.Node; +import org.apache.jena.graph.NodeFactory; +import org.apache.jena.graph.Triple; +import org.apache.jena.sparql.core.Quad; +import org.apache.jena.sparql.core.Var; +import org.apache.jena.sparql.sse.SSE; +import org.apache.jena.system.JenaSystem; +import org.junit.BeforeClass; +import org.junit.Test; + +public class TestSerializable { + @BeforeClass + public static void beforeClass() { + JenaSystem.init(); + } + + private static X roundTrip(X n) throws IOException, ClassNotFoundException { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(out); + // writeReplace. + oos.writeObject(n); + + byte b[] = out.toByteArray(); + ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(b)); + + // readResolve + @SuppressWarnings("unchecked") + X x = (X)ois.readObject(); + return x; + } + + @Test + public void serialize_node_01() throws Exception { + Node n = SSE.parseNode(""); + Node n1 = roundTrip(n); + assertTrue(n1.isURI()); + assertEquals(n, n1); + } + + @Test + public void serialize_node_02() throws Exception { + Node n = SSE.parseNode("123"); + Node n1 = roundTrip(n); + assertTrue(n1.isLiteral()); + assertEquals(n, n1); + } + + @Test + public void serialize_node_03() throws Exception { + Node n = SSE.parseNode("_:b"); + Node n1 = roundTrip(n); + assertTrue(n1.isBlank()); + assertEquals(n, n1); + } + + @Test + public void serialize_node_04() throws Exception { + Node n = Node.ANY; + Node n1 = roundTrip(n); + assertEquals(n, n1); + assertSame(n, n1); + } + + @Test + public void serialize_node_05() throws Exception { + Var v = Var.alloc("X"); + Var v1 = roundTrip(v); + assertEquals(v, v1); + } + + @Test + public void serialize_node_06() throws Exception { + Node v = NodeFactory.createVariable("Foo"); + Node v1 = roundTrip(v); // This will be a "Var". + assertEquals(v, v1); + } + + @Test + public void serialize_triple_01() throws Exception { + Triple t = SSE.parseTriple("(:s :p :o)"); + Triple t1 = roundTrip(t); + assertEquals(t, t1); + } + + @Test + public void serialize_triple_02() throws Exception { + Triple t = SSE.parseTriple("(:x :x :x)"); + Triple t1 = roundTrip(t); + assertEquals(t, t1); + assertEquals(t1.getSubject(), t1.getObject()); + } + + @Test + public void serialize_triple_03() throws Exception { + Triple t = SSE.parseTriple("(?a _:b 123)"); + Triple t1 = roundTrip(t); + assertEquals(t, t1); + } + + @Test + public void serialize_triple_04() throws Exception { + Triple t = SSE.parseTriple("(_:b _:b _:c)"); + Triple t1 = roundTrip(t); + assertEquals(t, t1); + assertEquals(t1.getSubject(), t1.getPredicate()); + assertNotEquals(t1.getSubject(), t1.getObject()); + assertTrue(t1.getSubject().isBlank()); + } + + @Test + public void serialize_quad_01() throws Exception { + Quad q = SSE.parseQuad("(:g :s :p :o)"); + Quad q1 = roundTrip(q); + assertEquals(q, q1); + } + + @Test + public void serialize_quad_02() throws Exception { + Quad q = SSE.parseQuad("(_ :s :p :o)"); + Quad q1 = roundTrip(q); + assertEquals(q, q1); + assertNotEquals(q.getSubject(), q1.getObject()); + } + + @Test + public void serialize_quad_03() throws Exception { + Quad q = SSE.parseQuad("(<_:abc> ?y ?x <_:abc>)"); + Quad q1 = roundTrip(q); + assertEquals(q, q1); + assertEquals(q.getGraph(), q1.getObject()); + } + + @Test + public void serialize_quad_04() throws Exception { + Quad q = SSE.parseQuad("(<_:abc> <_:abc> <_:def> <_:abc>)"); + Quad q1 = roundTrip(q); + assertEquals(q, q1); + assertEquals(q.getSubject(), q1.getObject()); + assertNotEquals(q.getSubject(), q1.getPredicate()); + } +} diff --git a/jena-core/src/main/java/org/apache/jena/graph/Node.java b/jena-core/src/main/java/org/apache/jena/graph/Node.java index 492e1fcfa9a..2ad3eab8607 100644 --- a/jena-core/src/main/java/org/apache/jena/graph/Node.java +++ b/jena-core/src/main/java/org/apache/jena/graph/Node.java @@ -18,11 +18,17 @@ package org.apache.jena.graph; +import java.io.IOException; +import java.io.ObjectStreamException; +import java.io.Serializable; +import java.util.function.Function; + import org.apache.jena.datatypes.RDFDatatype ; import org.apache.jena.graph.impl.LiteralLabel ; import org.apache.jena.shared.JenaException ; import org.apache.jena.shared.PrefixMapping ; import org.apache.jena.system.JenaSystem; +import org.apache.jena.system.Serializer; /** A Node has five subtypes: Node_Blank, Node_Anon, Node_URI, @@ -32,7 +38,7 @@ enough. */ -public abstract class Node { +public abstract class Node implements Serializable { static { JenaSystem.init(); } @@ -258,6 +264,23 @@ public int hashCode() public boolean matches( Node other ) { return equals( other ); } + // ---- Serializable + // Must be "protected", not "private". + protected Object writeReplace() throws ObjectStreamException { + Function function = Serializer.getNodeSerializer() ; + if ( function == null ) + throw new IllegalStateException("Function for Node.writeReplace not set") ; + return function.apply(this); + } + // Any attempt to serialize without replacement is an error. + private void writeObject(java.io.ObjectOutputStream out) throws IOException { + throw new IllegalStateException(); + } + private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { + throw new IllegalStateException(); + } + // ---- Serializable + /** Answer a human-readable representation of this Node. It will not compress URIs, nor quote literals (because at the moment too many places use toString() for diff --git a/jena-core/src/main/java/org/apache/jena/graph/Triple.java b/jena-core/src/main/java/org/apache/jena/graph/Triple.java index ee3f0e25141..f5eafeafed1 100644 --- a/jena-core/src/main/java/org/apache/jena/graph/Triple.java +++ b/jena-core/src/main/java/org/apache/jena/graph/Triple.java @@ -18,9 +18,14 @@ package org.apache.jena.graph; +import java.io.IOException; +import java.io.ObjectStreamException; +import java.io.Serializable; +import java.util.function.Function; import java.util.function.Predicate; import org.apache.jena.shared.PrefixMapping ; +import org.apache.jena.system.Serializer; import org.apache.jena.util.iterator.ExtendedIterator ; import org.apache.jena.util.iterator.NullIterator ; @@ -29,8 +34,9 @@ object field (all nodes) and express the notion that the relationship named by the predicate holds between the subject and the object. */ -public class Triple - { +public class Triple implements Serializable +{ + private final Node subj, pred, obj; public Triple( Node s, Node p, Node o ) @@ -135,7 +141,23 @@ public boolean predicateMatches( Node p ) public boolean objectMatches( Node o ) { return obj.matches( o ); } - + + // ---- Serializable + protected Object writeReplace() throws ObjectStreamException { + Function function = Serializer.getTripleSerializer() ; + if ( function == null ) + throw new IllegalStateException("Function for Triple.writeReplace not set") ; + return function.apply(this); + } + // Any attempt to serialize without replacement is an error. + private void writeObject(java.io.ObjectOutputStream out) throws IOException { + throw new IllegalStateException(); + } + private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { + throw new IllegalStateException(); + } + // ---- Serializable + /** The hash-code of a triple is the hash-codes of its components munged together: see hashCode(S, P, O). diff --git a/jena-core/src/main/java/org/apache/jena/system/Serializer.java b/jena-core/src/main/java/org/apache/jena/system/Serializer.java new file mode 100644 index 00000000000..3c2a8ad6bf6 --- /dev/null +++ b/jena-core/src/main/java/org/apache/jena/system/Serializer.java @@ -0,0 +1,84 @@ +/* + * 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 org.apache.jena.system; + +import java.io.Serializable; +import java.util.function.Function; + +import org.apache.jena.graph.Node; +import org.apache.jena.graph.Triple; + +/** The injection points for the Node and Triple {@link Serializable} process. + * This class is public to allow system initialization to inject + * handler functions for {@link Node} and {@link Triple}. + * See also {@code Quad}. + */ +public class Serializer { + + /*package*/ static Function nodeWriteReplaceFunction = null; + /*package*/ static Function tripleWriteReplaceFunction = null; + + /** Set the node serializer replacement function. + * This is a function called by {@code Node.writeReplace} during the {@link Serializable} process. + * The return is an object used in place of {@link Node} for the serialization. + * + *

+     * ANY-ACCESS-MODIFIER Object writeReplace() throws ObjectStreamException;
+     * 

+ * The returned object must provide + *

+     * ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException;
+     * 

+ * where "Object" is a {@link Node}. + * + * @see java.io.Serializable + */ + public static void setNodeSerializer(Function writeReplaceFunction) { + nodeWriteReplaceFunction = writeReplaceFunction; + } + + /** Return the current node serializer replacement function. */ + public static Function getNodeSerializer() { + return nodeWriteReplaceFunction; + } + + /** Set the triple serializer replacement function. + * This is a function called by {@code Triple.writeReplace} during the {@link Serializable} process. + * The return is an object used in place of {@link Triple} for the serialization. + * + *

+     * ANY-ACCESS-MODIFIER Object writeReplace() throws ObjectStreamException;
+     * 

+ * The returned object must provide + *

+     * ANY-ACCESS-MODIFIER Object readResolve() throws ObjectStreamException;
+     * 

+ * where "Object" is a {@link Triple}. + * + * @see java.io.Serializable + */ + public static void setTripleSerializer(Function writeReplaceFunction) { + tripleWriteReplaceFunction = writeReplaceFunction; + } + + /** Return the current triple serializer replacement function. */ + public static Function getTripleSerializer() { + return tripleWriteReplaceFunction; + } +}