Skip to content

Commit

Permalink
COMMONSRDF-47: RDFSyntax as an interface, not emum
Browse files Browse the repository at this point in the history
Official media types are provided from W3CRDFSyntax

Added plural mediaTypes() and extensions()

Thanks to @ansell for reviewing.

This closes #27
  • Loading branch information
stain committed Feb 16, 2017
2 parents f6ea058 + fbd72a9 commit ef7f444
Show file tree
Hide file tree
Showing 6 changed files with 426 additions and 87 deletions.
218 changes: 161 additions & 57 deletions api/src/main/java/org/apache/commons/rdf/api/RDFSyntax.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,26 @@
*/
package org.apache.commons.rdf.api;

import java.util.Arrays;
import java.util.Collections;
import java.util.Locale;
import java.util.Optional;
import java.util.Set;

/**
* Enumeration of the RDF 1.1 serialization syntaxes.
* An RDF syntax, e.g. as used for parsing and writing RDF.
* <p>
* This enumeration lists the W3C standardized RDF 1.1 syntaxes like
* {@link #TURTLE} and {@link #JSONLD}. Note the existence of other RDF syntaxes
* that are not included here, e.g.
* <a href="http://www.w3.org/TeamSubmission/n3/">N3</a> and
* <a href="https://en.wikipedia.org/wiki/TriX_%28syntax%29">TriX</a>.
* An RDF syntax is uniquely identified by its {@link #mediaType()}, and has a
* suggested {@link #fileExtension()}.
* <p>
* Some of the RDF syntaxes may {@link #supportsDataset()}, meaning they can
* represent {@link Quad}s.
* <p>
* An enumeration of the official RDF 1.1 syntaxes is available in
* {@link W3CRDFSyntax} - for convenience they are also accessible
* as constants here, e.g. <code>RDFSyntax.JSONLD</code>.
*
* @see <a href="https://www.w3.org/TR/rdf11-primer/#section-graph-syntax">RDF
* 1.1 Primer</a>
* @see org.apache.commons.rdf.experimental.RDFParser
*/
public enum RDFSyntax {
public interface RDFSyntax {

/**
* JSON-LD 1.0
Expand All @@ -43,7 +45,7 @@ public enum RDFSyntax {
* "https://www.w3.org/TR/json-ld/">https://www.w3.org/TR/json-ld/</a>
*
*/
JSONLD("JSON-LD 1.0", "application/ld+json", ".jsonld", true),
public static RDFSyntax JSONLD = W3CRDFSyntax.JSONLD;

/**
* RDF 1.1 Turtle
Expand All @@ -52,56 +54,69 @@ public enum RDFSyntax {
* "https://www.w3.org/TR/turtle/">https://www.w3.org/TR/turtle/</a>
*
*/
TURTLE("RDF 1.1 Turtle", "text/turtle", ".ttl", false),
public static RDFSyntax TURTLE = W3CRDFSyntax.TURTLE;

/**
* RDF 1.1 N-Quads
*
* @see <a href=
* "https://www.w3.org/TR/n-quads/">https://www.w3.org/TR/n-quads/</a>
*/
NQUADS("RDF 1.1 N-Quads", "application/n-quads", ".nq", true),
public static RDFSyntax NQUADS = W3CRDFSyntax.NQUADS;

/**
* RDF 1.1 N-Triples
*
* @see <a href=
* "https://www.w3.org/TR/n-triples/">https://www.w3.org/TR/n-triples/</a>
*/
NTRIPLES("RDF 1.1 N-Triples", "application/n-triples", ".nt", false),
public static RDFSyntax NTRIPLES = W3CRDFSyntax.NTRIPLES;

/**
* HTML+RDFa 1.1
* HTML+RDFa 1.1 and XHTML+RDFa 1.1
*
* @see <a href=
* "https://www.w3.org/TR/html-rdfa/">https://www.w3.org/TR/html-rdfa/</a>
*/
RDFA_HTML("HTML+RDFa 1.1", "text/html", ".html", false),

/**
* XHTML+RDFa 1.1
*
* @see <a href=
* "https://www.w3.org/TR/xhtml-rdfa/">https://www.w3.org/TR/xhtml-rdfa/</a>
*/
RDFA_XHTML("XHTML+RDFa 1.1", "application/xhtml+xml", ".xhtml", false),
public static RDFSyntax RDFA = W3CRDFSyntax.RDFA;

/**
* RDF 1.1 XML Syntax
*
* @see <a href=
* "https://www.w3.org/TR/rdf-syntax-grammar/">https://www.w3.org/TR/rdf-syntax-grammar/</a>
*/
RDFXML("RDF 1.1 XML Syntax", "application/rdf+xml", ".rdf", false),
public static RDFSyntax RDFXML = W3CRDFSyntax.RDFXML;

/**
* RDF 1.1 TriG
*
* @see <a href=
* "https://www.w3.org/TR/trig/">https://www.w3.org/TR/trig/</a>
*/
TRIG("RDF 1.1 TriG", "application/trig", ".trig", true);
public static RDFSyntax TRIG = W3CRDFSyntax.TRIG;

/**
* A short name of the RDF Syntax e.g. <code>JSONLD</code>.
* <p>
* The name is specific to Commons RDF and carries no particular meaning.
*
* @return Short name for RDF syntax
*/
public String name();

/**
* The title of the RDF Syntax.
* <p>
* This is generally the title of the corresponding standard,
* e.g. <em>RDF 1.1 Turtle</em>.
*
* @return Title of RDF Syntax
*/
public String title();

/**
* The <a href="https://tools.ietf.org/html/rfc2046">IANA media type</a> for
* the RDF syntax.
Expand All @@ -111,84 +126,173 @@ public enum RDFSyntax {
* <a href="https://tools.ietf.org/html/rfc7231#section-3.1.1.1">HTTP
* protocol</a>.
*/
public final String mediaType;
public String mediaType();

/**
* Set of <a href="https://tools.ietf.org/html/rfc2046">IANA media types/a> that
* covers this RDF syntax, including any non-official media types.
* <p>
* The media type can be used as part of <code>Content-Type</code> and
* <code>Accept</code> for <em>content negotiation</em> in the
* <a href="https://tools.ietf.org/html/rfc7231#section-3.1.1.1">HTTP
* protocol</a>.
* <p>
* The returned Set MUST include the value {@link #mediaType()}; this is the
* behaviour of the default implementation.
*/
default public Set<String> mediaTypes() {
return Collections.singleton(mediaType());
}

/**
* The <a href="https://tools.ietf.org/html/rfc2046">IANA-registered</a>
* file extension.
* <p>
* The file extension includes the leading period, e.g. <code>.jsonld</code>
*/
public final String fileExtension;
public String fileExtension();

/**
* Set of file extensions for this RDF syntax, including any non-official extensions.
* <p>
* The file extension includes the leading period, e.g. <code>.jsonld</code>
* <p>
* The returned Set MUST include the value from {@link #fileExtension()}; this is
* the behaviour of the default implementation.
*/
default public Set<String> fileExtensions() {
return Collections.singleton(fileExtension());
}

/**
* Indicate if this RDF syntax supports
* <a href="https://www.w3.org/TR/rdf11-concepts/#section-dataset">RDF
* Datasets</a>.
*/
public final boolean supportsDataset;
public boolean supportsDataset();

private final String name;
/**
* Return the {@link IRI} that <em>identifies</em> the RDF syntax.
* <p>
* Note that the identifying IRI is generally distinct from the IRI of the
* document that <em>specifies</em> the RDF syntax.
*
* @return Identifying IRI, e.g.
* <code>http://www.w3.org/ns/formats/JSON-LD</code>
*/
public IRI iri();

/**
* A human-readable name for the RDF syntax.
* Compare this RDFSyntax with another object.
* <p>
* The name is equivalent to the the title of the corresponding W3C
* Specification.
* Two {@link RDFSyntax}es are considered equal if their
* {@link #mediaType()}s are equal when compared as lower case strings
* according to {@link String#toLowerCase(Locale)} with the locale
* {@link Locale#ROOT}.
*
* @param obj
* @return
*/
@Override
public String toString() {
return name;
}
boolean equals(Object obj);

/**
* The hash code of an RDFSyntax is equivalent to the hash code
* of the {@link #mediaType()} in lower case according to
* {@link String#toLowerCase(Locale)} with the locale
* {@link Locale#ROOT}.
*
* @return Hash code of RDFSyntax
*/
@Override
int hashCode();

/**
* Return the RDF 1.1 serialization syntaxes.
* <p>
* This lists the W3C standardized RDF 1.1 syntaxes like {@link #TURTLE} and
* {@link #JSONLD}. Note the existence of other RDF syntaxes that are not
* included here, e.g. <a href="http://www.w3.org/TeamSubmission/n3/">N3</a> and
* <a href="https://en.wikipedia.org/wiki/TriX_%28syntax%29">TriX</a>.
* <p>
* The syntaxes returned only support the {@link #mediaType()}
* and {@link #fileExtension()} as defined in the corresponding
* W3C specification.
*
* @return
* A set of the official RDF 1.1 {@link RDFSyntax}es.
*
* @see <a href="https://www.w3.org/TR/rdf11-primer/#section-graph-syntax">RDF
* 1.1 Primer</a>
* @see org.apache.commons.rdf.experimental.RDFParser
*/

private RDFSyntax(final String name, final String mediaType, final String fileExtension, final boolean supportsDataset) {
this.name = name;
this.mediaType = mediaType;
this.fileExtension = fileExtension;
this.supportsDataset = supportsDataset;
public static Set<RDFSyntax> w3cSyntaxes() {
return W3CRDFSyntax.syntaxes;
}

/**
* Return the RDFSyntax with the specified media type.
* <p>
* The <code>mediaType</code> is compared in lower case, therefore it might
* not be equal to the {@link RDFSyntax#mediaType} of the returned
* RDFSyntax.
* The <code>mediaType</code> is compared in lower case to all media types
* supported, therefore it might not be equal to the
* {@link RDFSyntax#mediaType} of the returned RDFSyntax.
* <p>
* If the media type specifies parameters, e.g.
* <code>text/turtle; charset=ascii</code>, only the part of the string to
* before <code>;</code> is considered.
* <p>
* For convenience matching of media types used in a
* <code>Content-Type</code> header, if the <code>mediaType</code> contains
* the characters <code>;</code>, <code>,</code> or white space, only the
* part of the string to the left of those characters are considered.
* This method support all syntaxes returned by {@link #w3cSyntaxes()}.
*
* @param mediaType
* The media type to match
* @return If {@link Optional#isPresent()}, the {@link RDFSyntax} which has
* a matching {@link RDFSyntax#mediaType}, otherwise
* a matching {@link RDFSyntax#mediaType()}, otherwise
* {@link Optional#empty()} indicating that no matching syntax was
* found.
*/
public static Optional<RDFSyntax> byMediaType(final String mediaType) {
final String type = mediaType.toLowerCase(Locale.ENGLISH).split("\\s*[;,]", 2)[0];
return Arrays.stream(RDFSyntax.values()).filter(t -> t.mediaType.equals(type)).findAny();
final String type = mediaType.toLowerCase(Locale.ROOT).split("\\s*;", 2)[0];
return w3cSyntaxes().stream().filter(t -> t.mediaTypes().contains(type))
.findAny();
}

/**
* Return the RDFSyntax with the specified file extension.
* <p>
* The <code>fileExtension</code> is compared in lower case, therefore it
* might not be equal to the {@link RDFSyntax#fileExtension} of the returned
* RDFSyntax.
* The <code>fileExtension</code> is compared in lower case to all
* extensions supported, therefore it might not be equal to the
* {@link RDFSyntax#fileExtension} of the returned RDFSyntax.
* <p>
* This method support all syntaxes returned by {@link #w3cSyntaxes()}.
*
* @param fileExtension
* The fileExtension to match, starting with <code>.</code>
* @return If {@link Optional#isPresent()}, the {@link RDFSyntax} which has
* a matching {@link RDFSyntax#fileExtension}, otherwise
* a matching {@link RDFSyntax#fileExtension()}, otherwise
* {@link Optional#empty()} indicating that no matching file
* extension was found.
*/
public static Optional<RDFSyntax> byFileExtension(final String fileExtension) {
final String ext = fileExtension.toLowerCase(Locale.ENGLISH);
return Arrays.stream(RDFSyntax.values()).filter(t -> t.fileExtension.equals(ext)).findAny();
final String ext = fileExtension.toLowerCase(Locale.ROOT);
return w3cSyntaxes().stream().filter(t -> t.fileExtensions().contains(ext))
.findAny();
}

/**
* Return the RDFSyntax with the specified {@link #name()}.
* <p>
* This method support all syntaxes returned by {@link #w3cSyntaxes()}.
*
* @param name
* The name to match, , e.g. <code>"JSONLD"</code>
* @return If {@link Optional#isPresent()}, the {@link RDFSyntax} which has
* a matching {@link RDFSyntax#name()}, otherwise
* {@link Optional#empty()} indicating that no matching name was found.
*/
public static Optional<RDFSyntax> byName(final String name) {
return w3cSyntaxes().stream().filter(t -> t.name().equals(name)).findAny();
}


}
}
Loading

0 comments on commit ef7f444

Please sign in to comment.