Skip to content

Instantly share code, notes, and snippets.

@betehess
Last active August 29, 2015 14:20
Show Gist options
  • Save betehess/8983dbff2c3e89f9dadb to your computer and use it in GitHub Desktop.
Save betehess/8983dbff2c3e89f9dadb to your computer and use it in GitHub Desktop.
import java.util.stream.*;
import java.util.function.*;
import java.util.*;
// this contract is mainly for library implementors, not that much for
// users. Well, this can be argued :-). Another side-effect of this
// approach is that code using the RDF interface would create and see
// the actual types/classes being manipulated, not the common
// interfaces.
interface RDF<Graph, Triple, RDFTerm, BlankNodeOrIRI, IRI, BlankNode, Literal> {
/* RDFTermFactory */
BlankNode createBlankNode();
BlankNode createBlankNode(String name);
Graph createGraph();
IRI createIRI(String iri) throws IllegalArgumentException;
Literal createLiteral(String lexicalForm) throws IllegalArgumentException;
Literal createLiteral(String lexicalForm, IRI dataType) throws IllegalArgumentException;
Literal createLiteral(String lexicalForm, String languageTag) throws IllegalArgumentException;
Triple createTriple(BlankNodeOrIRI subject, IRI predicate, RDFTerm object) throws IllegalArgumentException;
/* Graph */
// note that Graph is abstract, so that means that this handles
// both the mutable and immutable cases, as the implementer will
// be able to choose what Graph actually is.
Graph add(Graph graph, BlankNodeOrIRI subject, IRI predicate, RDFTerm object);
Graph add(Graph graph, Triple triple);
Graph remove(Graph graph, BlankNodeOrIRI subject, IRI predicate, RDFTerm object);
// no clear() or close(), as this is specific to a type, so it doesn't belong here
boolean contains(Graph graph, BlankNodeOrIRI subject, IRI predicate, RDFTerm object);
Stream<Triple> getTriplesAsStream(Graph graph);
Iterable<Triple> getTriplesAsIterable(Graph graph, BlankNodeOrIRI subject, IRI predicate, RDFTerm object);
long size(Graph graph);
/* RDFTerm */
// this is very much like a Visitor. Note that this would work
// even for RDFTerm =:= String and would still be type-safe. I beg that we do not rely on
// instanceof and/or isURI/isBNode/isLiteral.
<T> T visit(RDFTerm t, Function<IRI, T> fIRI, Function<BlankNode, T> fBNode, Function<Literal, T> fLiteral);
/* IRI */
String getIRIString(IRI iri);
/* BlankNode */
String uniqueReference(BlankNode bnode);
/* Literal */
IRI getDatatype(Literal literal);
Optional<String> getLanguageTag(Literal literal);
String getLexicalForm(Literal literal);
}
// I am arguing for a separation of concerns: ntriples stuff *should*
// be decoupled from the RDF model. It is actually easy to provide a
// default NTriples implementation when you already have a RDF
// implementation. Please do not mix the two.
interface NTriples<Graph, Triple, RDFTerm, BlankNodeOrIRI, IRI, BlankNode, Literal> {
String fromRDFTerm(RDFTerm t);
String fromIRI(IRI iri);
// etc.
}
import org.apache.commons.rdf.api.*;
// this is how you would pin the abstract types to existing Java
// interfaces/classes. This *might* be useful -- or not -- but still
// possible. What's important is that library users in Java-land could
// still rely on the class-based approach, while library authors
// wouldn't be tied to any classes.
class CommonsRDF extends RDF<Graph, Triple, RDFTerm, BlankNodeOrIRI, IRI, BlankNode, Literal> { }
class StringRDF extends RDF<Set<Tuple3<String, String, String>>, Tuple3<String, String, String>, String, String, String, String, String> { }
// from banana-rdf
object PlantainRDF extends RDF[plantain.Graph, plantain.Triple, Any, Any, URI, plantain.BNode, Any] { }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment