001/**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.commons.rdf.api;
019
020import java.util.Arrays;
021import java.util.Locale;
022import java.util.Optional;
023
024/**
025 * Enumeration of the RDF 1.1 serialization syntaxes.
026 * <p>
027 * This enumeration lists the W3C standardized RDF 1.1 syntaxes like
028 * {@link #TURTLE} and {@link #JSONLD}. Note the existence of other RDF syntaxes
029 * that are not included here, e.g.
030 * <a href="http://www.w3.org/TeamSubmission/n3/">N3</a> and
031 * <a href="https://en.wikipedia.org/wiki/TriX_%28syntax%29">TriX</a>.
032 * 
033 * @see <a href="https://www.w3.org/TR/rdf11-primer/#section-graph-syntax">RDF
034 *      1.1 Primer</a>
035 * @see org.apache.commons.rdf.experimental.RDFParser
036 */
037public enum RDFSyntax {
038
039    /**
040     * JSON-LD 1.0
041     * 
042     * @see <a href=
043     *      "https://www.w3.org/TR/json-ld/">https://www.w3.org/TR/json-ld/</a>
044     * 
045     */
046    JSONLD("JSON-LD 1.0", "application/ld+json", ".jsonld", true),
047
048    /**
049     * RDF 1.1 Turtle
050     * 
051     * @see <a href=
052     *      "https://www.w3.org/TR/turtle/">https://www.w3.org/TR/turtle/</a>
053     *
054     */
055    TURTLE("RDF 1.1 Turtle", "text/turtle", ".ttl", false),
056
057    /**
058     * RDF 1.1 N-Quads
059     * 
060     * @see <a href=
061     *      "https://www.w3.org/TR/n-quads/">https://www.w3.org/TR/n-quads/</a>
062     */
063    NQUADS("RDF 1.1 N-Quads", "application/n-quads", ".nq", true),
064
065    /**
066     * RDF 1.1 N-Triples
067     * 
068     * @see <a href=
069     *      "https://www.w3.org/TR/n-triples/">https://www.w3.org/TR/n-triples/</a>
070     */
071    NTRIPLES("RDF 1.1 N-Triples", "application/n-triples", ".nt", false),
072
073    /**
074     * HTML+RDFa 1.1
075     * 
076     * @see <a href=
077     *      "https://www.w3.org/TR/html-rdfa/">https://www.w3.org/TR/html-rdfa/</a>
078     */
079    RDFA_HTML("HTML+RDFa 1.1", "text/html", ".html", false),
080
081    /**
082     * XHTML+RDFa 1.1
083     * 
084     * @see <a href=
085     *      "https://www.w3.org/TR/xhtml-rdfa/">https://www.w3.org/TR/xhtml-rdfa/</a>
086     */
087    RDFA_XHTML("XHTML+RDFa 1.1", "application/xhtml+xml", ".xhtml", false),
088
089    /**
090     * RDF 1.1 XML Syntax
091     * 
092     * @see <a href=
093     *      "https://www.w3.org/TR/rdf-syntax-grammar/">https://www.w3.org/TR/rdf-syntax-grammar/</a>
094     */
095    RDFXML("RDF 1.1 XML Syntax", "application/rdf+xml", ".rdf", false),
096
097    /**
098     * RDF 1.1 TriG
099     * 
100     * @see <a href=
101     *      "https://www.w3.org/TR/trig/">https://www.w3.org/TR/trig/</a>
102     */
103    TRIG("RDF 1.1 TriG", "application/trig", ".trig", true);
104
105    /**
106     * The <a href="https://tools.ietf.org/html/rfc2046">IANA media type</a> for
107     * the RDF syntax.
108     * <p>
109     * The media type can be used as part of <code>Content-Type</code> and
110     * <code>Accept</code> for <em>content negotiation</em> in the
111     * <a href="https://tools.ietf.org/html/rfc7231#section-3.1.1.1">HTTP
112     * protocol</a>.
113     */
114    public final String mediaType;
115
116    /**
117     * The <a href="https://tools.ietf.org/html/rfc2046">IANA-registered</a>
118     * file extension.
119     * <p>
120     * The file extension includes the leading period, e.g. <code>.jsonld</code>
121     */
122    public final String fileExtension;
123
124    /**
125     * Indicate if this RDF syntax supports
126     * <a href="https://www.w3.org/TR/rdf11-concepts/#section-dataset">RDF
127     * Datasets</a>.
128     */
129    public final boolean supportsDataset;
130
131    private final String name;
132
133    /**
134     * A human-readable name for the RDF syntax.
135     * <p>
136     * The name is equivalent to the the title of the corresponding W3C
137     * Specification.
138     */
139    @Override
140    public String toString() {
141        return name;
142    }
143
144    private RDFSyntax(final String name, final String mediaType, final String fileExtension, final boolean supportsDataset) {
145        this.name = name;
146        this.mediaType = mediaType;
147        this.fileExtension = fileExtension;
148        this.supportsDataset = supportsDataset;
149    }
150
151    /**
152     * Return the RDFSyntax with the specified media type.
153     * <p>
154     * The <code>mediaType</code> is compared in lower case, therefore it might
155     * not be equal to the {@link RDFSyntax#mediaType} of the returned
156     * RDFSyntax.
157     * <p>
158     * For convenience matching of media types used in a
159     * <code>Content-Type</code> header, if the <code>mediaType</code> contains
160     * the characters <code>;</code>, <code>,</code> or white space, only the
161     * part of the string to the left of those characters are considered.
162     * 
163     * @param mediaType
164     *            The media type to match
165     * @return If {@link Optional#isPresent()}, the {@link RDFSyntax} which has
166     *         a matching {@link RDFSyntax#mediaType}, otherwise
167     *         {@link Optional#empty()} indicating that no matching syntax was
168     *         found.
169     */
170    public static Optional<RDFSyntax> byMediaType(final String mediaType) {
171        final String type = mediaType.toLowerCase(Locale.ENGLISH).split("\\s*[;,]", 2)[0];
172        return Arrays.stream(RDFSyntax.values()).filter(t -> t.mediaType.equals(type)).findAny();
173    }
174
175    /**
176     * Return the RDFSyntax with the specified file extension.
177     * <p>
178     * The <code>fileExtension</code> is compared in lower case, therefore it
179     * might not be equal to the {@link RDFSyntax#fileExtension} of the returned
180     * RDFSyntax.
181     * 
182     * @param fileExtension
183     *            The fileExtension to match, starting with <code>.</code>
184     * @return If {@link Optional#isPresent()}, the {@link RDFSyntax} which has
185     *         a matching {@link RDFSyntax#fileExtension}, otherwise
186     *         {@link Optional#empty()} indicating that no matching file
187     *         extension was found.
188     */
189    public static Optional<RDFSyntax> byFileExtension(final String fileExtension) {
190        final String ext = fileExtension.toLowerCase(Locale.ENGLISH);
191        return Arrays.stream(RDFSyntax.values()).filter(t -> t.fileExtension.equals(ext)).findAny();
192    }
193
194}