/** * Copyright 2005-2014 Restlet * * The contents of this file are subject to the terms of one of the following * open source licenses: Apache 2.0 or or EPL 1.0 (the "Licenses"). You can * select the license that you prefer but you may not use this file except in * compliance with one of these Licenses. * * You can obtain a copy of the Apache 2.0 license at * http://www.opensource.org/licenses/apache-2.0 * * You can obtain a copy of the EPL 1.0 license at * http://www.opensource.org/licenses/eclipse-1.0 * * See the Licenses for the specific language governing permissions and * limitations under the Licenses. * * Alternatively, you can obtain a royalty free commercial license with less * limitations, transferable or non-transferable, directly at * http://restlet.com/products/restlet-framework * * Restlet is a registered trademark of Restlet S.A.S. */ package org.restlet.ext.rdf; import java.io.IOException; import java.io.Writer; import java.util.logging.Level; import org.restlet.Context; import org.restlet.data.MediaType; import org.restlet.data.Reference; import org.restlet.ext.rdf.internal.n3.RdfN3Reader; import org.restlet.ext.rdf.internal.n3.RdfN3Writer; import org.restlet.ext.rdf.internal.ntriples.RdfNTriplesReader; import org.restlet.ext.rdf.internal.ntriples.RdfNTriplesWriter; import org.restlet.ext.rdf.internal.turtle.RdfTurtleReader; import org.restlet.ext.rdf.internal.turtle.RdfTurtleWriter; import org.restlet.ext.rdf.internal.xml.RdfXmlReader; import org.restlet.ext.rdf.internal.xml.RdfXmlWriter; import org.restlet.representation.Representation; import org.restlet.representation.WriterRepresentation; /** * Generic RDF representation. Provides support for the Resource Description * Framework (RDF) Semantic Web standard. It supports major RDF serialization * formats (n3, Turtle, N-Triples and RDF/XML) and is able to both serialize and * deserialize a {@link Graph}. * * @author Jerome Louvel */ public class RdfRepresentation extends WriterRepresentation { /** The inner graph of links. */ private Graph graph; /** The inner RDF representation. */ private Representation rdfRepresentation; /** * Constructor. */ public RdfRepresentation() { super(MediaType.TEXT_XML); } /** * Constructor with argument. * * @param linkSet * The graph of links. * @param mediaType * The representation's mediaType. */ public RdfRepresentation(Graph linkSet, MediaType mediaType) { super(mediaType); this.graph = linkSet; } /** * Constructor with argument. * * @param mediaType * The representation's mediaType. */ public RdfRepresentation(MediaType mediaType) { super(mediaType); } /** * Constructor that parsed a given RDF representation into a link set. * * @param rdfRepresentation * The RDF representation to parse. * @throws IOException */ public RdfRepresentation(Representation rdfRepresentation) throws IOException { super(rdfRepresentation.getMediaType()); this.rdfRepresentation = rdfRepresentation; } /** * Returns an instance of a graph handler used when parsing the inner RDF * representation. * * @param graph * The graph to build. * @return An instance of a graph handler used when parsing the inner RDF * representation. */ public GraphHandler createBuilder(Graph graph) { return new GraphBuilder(this.graph); } /** * Returns an instance of a graph handler used when writing the inner set of * links. * * @param mediaType * The given media type of the parsed RDF representation. * @param writer * The character writer to write to. * @return An instance of a graph handler used when writing the inner set of * links. * @throws IOException */ public GraphHandler createWriter(MediaType mediaType, Writer writer) throws IOException { if (MediaType.TEXT_RDF_N3.equals(getMediaType())) { return new RdfN3Writer(writer); } else if (MediaType.TEXT_XML.equals(getMediaType())) { return new RdfXmlWriter(writer); } else if (MediaType.APPLICATION_ALL_XML.includes(getMediaType())) { return new RdfXmlWriter(writer); } else if (MediaType.TEXT_PLAIN.equals(getMediaType())) { return new RdfNTriplesWriter(writer); } else if (MediaType.TEXT_RDF_NTRIPLES.equals(getMediaType())) { return new RdfNTriplesWriter(writer); } else if (MediaType.TEXT_TURTLE.equals(getMediaType())) { return new RdfTurtleWriter(writer); } // Writing for other media types goes here. return null; } /** * Updates the list of known namespaces for the given graph of links. * * @param linkset * The given graph of links. * @param GraphHandler * the graph handler. */ private void discoverNamespaces(Graph linkset, GraphHandler graphHandler) { for (Link link : linkset) { discoverNamespaces(link, graphHandler); } } /** * Updates the list of known namespaces of the XML writer for the given * link. * * @param link * The given link. * @param GraphHandler * the graph handler. */ private void discoverNamespaces(Link link, GraphHandler graphHandler) { // The subject of the link is not discovered, it is generated as the // value of an "about" attribute. if (link.hasLinkSource()) { discoverNamespaces(link.getSourceAsLink(), graphHandler); } else if (link.hasGraphSource()) { discoverNamespaces(link.getSourceAsGraph(), graphHandler); } discoverNamespaces(link.getTypeRef(), graphHandler); if (link.hasLinkTarget()) { discoverNamespaces(link.getTargetAsLink(), graphHandler); } else if (link.hasGraphSource()) { discoverNamespaces(link.getSourceAsGraph(), graphHandler); } } /** * Updates the list of known namespaces of the XML writer for the given * reference. * * @param reference * The given reference. * @param xmlWriter * the XML writer. */ private void discoverNamespaces(Reference reference, GraphHandler graphHandler) { if (!Link.isBlankRef(reference)) { graphHandler.startPrefixMapping(null, reference); } } /** * Returns the graph of links. * * @return The graph of links. * @throws IOException */ public Graph getGraph() throws IOException { if (this.graph == null) { this.graph = new Graph(); parse(createBuilder(this.graph)); } return this.graph; } /** * Parses the inner RDF representation. The given graph handler is invoked * each time a link is detected. * * @param graphHandler * The graph handler. * @throws IOException */ public void parse(GraphHandler graphHandler) throws IOException { if (rdfRepresentation != null) { if (MediaType.TEXT_RDF_N3.equals(rdfRepresentation.getMediaType())) { new RdfN3Reader(rdfRepresentation, graphHandler).parse(); } else if (MediaType.TEXT_XML.equals(rdfRepresentation .getMediaType())) { new RdfXmlReader(rdfRepresentation, graphHandler).parse(); } else if (MediaType.APPLICATION_ALL_XML.includes(rdfRepresentation .getMediaType())) { new RdfXmlReader(rdfRepresentation, graphHandler).parse(); } else if (MediaType.TEXT_PLAIN.equals(rdfRepresentation .getMediaType())) { new RdfNTriplesReader(rdfRepresentation, graphHandler).parse(); } else if (MediaType.TEXT_RDF_NTRIPLES.equals(rdfRepresentation .getMediaType())) { new RdfNTriplesReader(rdfRepresentation, graphHandler).parse(); } else if (MediaType.TEXT_TURTLE.equals(rdfRepresentation .getMediaType())) { new RdfTurtleReader(rdfRepresentation, graphHandler).parse(); } else if (MediaType.valueOf("text/rdf+n3").equals( rdfRepresentation.getMediaType())) { // Old media type still in usage new RdfN3Reader(rdfRepresentation, graphHandler).parse(); } // Parsing for other media types goes here. } } /** * Sets the graph of links. * * @param linkSet * The graph of links. */ public void setGraph(Graph linkSet) { this.graph = linkSet; } /** * Writes the * * @param graphHandler * @throws IOException */ public void write(GraphHandler graphHandler) throws IOException { try { if (graph != null) { discoverNamespaces(graph, graphHandler); graphHandler.startGraph(); for (Link link : graph) { if (link.hasReferenceSource()) { if (link.hasReferenceTarget()) { graphHandler.link(link.getSourceAsReference(), link.getTypeRef(), link.getTargetAsReference()); } else if (link.hasLiteralTarget()) { graphHandler.link(link.getSourceAsReference(), link.getTypeRef(), link.getTargetAsLiteral()); } else if (link.hasLinkTarget()) { Context.getCurrentLogger() .warning( "Cannot write the representation of a statement due to the fact that the object is neither a Reference nor a literal."); } else { Context.getCurrentLogger() .warning( "Cannot write the representation of a statement due to the fact that the object is neither a Reference nor a literal."); } } else if (link.hasGraphSource()) { if (link.hasReferenceTarget()) { graphHandler.link(link.getSourceAsGraph(), link.getTypeRef(), link.getTargetAsReference()); } else if (link.hasLiteralTarget()) { graphHandler.link(link.getSourceAsGraph(), link.getTypeRef(), link.getTargetAsLiteral()); } else if (link.hasLinkTarget()) { Context.getCurrentLogger() .warning( "Cannot write the representation of a statement due to the fact that the object is neither a Reference nor a literal."); } else { Context.getCurrentLogger() .warning( "Cannot write the representation of a statement due to the fact that the object is neither a Reference nor a literal."); } } } graphHandler.endGraph(); } } catch (Exception e) { Context.getCurrentLogger() .log(Level.WARNING, "Cannot write the RDF graph due to an unexpected exception", e); } } @Override public void write(Writer writer) throws IOException { write(createWriter(getMediaType(), writer)); } }