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.Collections;
021import java.util.Locale;
022import java.util.Optional;
023import java.util.Set;
024
025/**
026 * An RDF syntax, e.g. as used for parsing and writing RDF.
027 * <p>
028 * An RDF syntax is uniquely identified by its {@link #mediaType()}, and has a
029 * suggested {@link #fileExtension()}.
030 * <p>
031 * Some of the RDF syntaxes may {@link #supportsDataset()}, meaning they can
032 * represent {@link Quad}s.
033 * <p>
034 * An enumeration of the official RDF 1.1 syntaxes is available in
035 * {@link W3CRDFSyntax} - for convenience they are also accessible
036 * as constants here, e.g. <code>RDFSyntax.JSONLD</code>.
037 *
038 */
039public interface RDFSyntax {
040
041    /**
042     * JSON-LD 1.0
043     *
044     * @see <a href=
045     *      "https://www.w3.org/TR/json-ld/">https://www.w3.org/TR/json-ld/</a>
046     *
047     */
048    static RDFSyntax JSONLD = W3CRDFSyntax.JSONLD;
049
050    /**
051     * RDF 1.1 Turtle
052     *
053     * @see <a href=
054     *      "https://www.w3.org/TR/turtle/">https://www.w3.org/TR/turtle/</a>
055     *
056     */
057    static RDFSyntax TURTLE = W3CRDFSyntax.TURTLE;
058
059    /**
060     * RDF 1.1 N-Quads
061     *
062     * @see <a href=
063     *      "https://www.w3.org/TR/n-quads/">https://www.w3.org/TR/n-quads/</a>
064     */
065    static RDFSyntax NQUADS = W3CRDFSyntax.NQUADS;
066
067    /**
068     * RDF 1.1 N-Triples
069     *
070     * @see <a href=
071     *      "https://www.w3.org/TR/n-triples/">https://www.w3.org/TR/n-triples/</a>
072     */
073    static RDFSyntax NTRIPLES = W3CRDFSyntax.NTRIPLES;
074
075    /**
076     * HTML+RDFa 1.1 and XHTML+RDFa 1.1
077     *
078     * @see <a href=
079     *      "https://www.w3.org/TR/html-rdfa/">https://www.w3.org/TR/html-rdfa/</a>
080     * @see <a href=
081     *      "https://www.w3.org/TR/xhtml-rdfa/">https://www.w3.org/TR/xhtml-rdfa/</a>
082     */
083    static RDFSyntax RDFA = W3CRDFSyntax.RDFA;
084
085    /**
086     * RDF 1.1 XML Syntax
087     *
088     * @see <a href=
089     *      "https://www.w3.org/TR/rdf-syntax-grammar/">https://www.w3.org/TR/rdf-syntax-grammar/</a>
090     */
091    static RDFSyntax RDFXML = W3CRDFSyntax.RDFXML;
092
093    /**
094     * RDF 1.1 TriG
095     *
096     * @see <a href=
097     *      "https://www.w3.org/TR/trig/">https://www.w3.org/TR/trig/</a>
098     */
099    static RDFSyntax TRIG = W3CRDFSyntax.TRIG;
100
101    /**
102     * A short name of the RDF Syntax e.g. <code>JSONLD</code>.
103     * <p>
104     * The name is specific to Commons RDF and carries no particular meaning.
105     *
106     * @return Short name for RDF syntax
107     */
108    String name();
109
110    /**
111     * The title of the RDF Syntax.
112     * <p>
113     * This is generally the title of the corresponding standard,
114     * e.g. <em>RDF 1.1 Turtle</em>.
115     *
116     * @return Title of RDF Syntax
117     */
118    String title();
119
120    /**
121     * The <a href="https://tools.ietf.org/html/rfc2046">IANA media type</a> for
122     * the RDF syntax.
123     * <p>
124     * The media type can be used as part of <code>Content-Type</code> and
125     * <code>Accept</code> for <em>content negotiation</em> in the
126     * <a href="https://tools.ietf.org/html/rfc7231#section-3.1.1.1">HTTP
127     * protocol</a>.
128     *
129     * @return The registered media type of the RDF Syntax
130     */
131    String mediaType();
132
133    /**
134     * Set of <a href="https://tools.ietf.org/html/rfc2046">IANA media types</a> that
135     * covers this RDF syntax, including any non-official media types.
136     * <p>
137     * The media type can be used as part of <code>Content-Type</code> and
138     * <code>Accept</code> for <em>content negotiation</em> in the
139     * <a href="https://tools.ietf.org/html/rfc7231#section-3.1.1.1">HTTP
140     * protocol</a>.
141     * <p>
142     * The returned Set MUST include the value {@link #mediaType()}; this is the
143     * behaviour of the default implementation.
144     *
145     * @return The media types corresponding to the RDF Syntax
146     */
147    default Set<String> mediaTypes() {
148        return Collections.singleton(mediaType());
149    }
150
151    /**
152     * The <a href="https://tools.ietf.org/html/rfc2046">IANA-registered</a>
153     * file extension.
154     * <p>
155     * The file extension includes the leading period, e.g. <code>.jsonld</code>
156     *
157     * @return The registered file extension of the RDF Syntax
158     */
159    String fileExtension();
160
161    /**
162     * Set of file extensions for this RDF syntax, including any non-official extensions.
163     * <p>
164     * The file extension includes the leading period, e.g. <code>.jsonld</code>
165     * <p>
166     * The returned Set MUST include the value from {@link #fileExtension()}; this is
167     * the behaviour of the default implementation.
168     *
169     * @return The file extensions corresponding to the RDF Syntax
170     */
171    default Set<String> fileExtensions() {
172        return Collections.singleton(fileExtension());
173    }
174
175    /**
176     * Indicate if this RDF syntax supports
177     * <a href="https://www.w3.org/TR/rdf11-concepts/#section-dataset">RDF
178     * Datasets</a>.
179     *
180     * @return true if this RDF Syntax supports datasets; false otherwise
181     */
182    boolean supportsDataset();
183
184    /**
185     * Return the {@link IRI} that <em>identifies</em> the RDF syntax.
186     * <p>
187     * Note that the identifying IRI is generally distinct from the IRI of the
188     * document that <em>specifies</em> the RDF syntax.
189     *
190     * @return Identifying IRI, e.g.
191     *         <code>http://www.w3.org/ns/formats/JSON-LD</code>
192     */
193    IRI iri();
194
195    /**
196     * Compare this RDFSyntax with another object.
197     * <p>
198     * Two {@link RDFSyntax}es are considered equal if their
199     * {@link #mediaType()}s are equal when compared as lower case strings
200     * according to {@link String#toLowerCase(Locale)} with the locale
201     * {@link Locale#ROOT}.
202     *
203     * @param obj the object with which to compare
204     * @return true if this object is the same as the obj argument; false otherwise
205     */
206    @Override
207    boolean equals(Object obj);
208
209    /**
210     * The hash code of an RDFSyntax is equivalent to the hash code
211     * of the {@link #mediaType()} in lower case according to
212     * {@link String#toLowerCase(Locale)} with the locale
213     * {@link Locale#ROOT}.
214     *
215     * @return Hash code of RDFSyntax
216     */
217    @Override
218    int hashCode();
219
220    /**
221     * Return the RDF 1.1 serialization syntaxes.
222     * <p>
223     * This lists the W3C standardized RDF 1.1 syntaxes like {@link #TURTLE} and
224     * {@link #JSONLD}. Note the existence of other RDF syntaxes that are not
225     * included here, e.g. <a href="http://www.w3.org/TeamSubmission/n3/">N3</a> and
226     * <a href="https://en.wikipedia.org/wiki/TriX_%28syntax%29">TriX</a>.
227     * <p>
228     * The syntaxes returned only support the {@link #mediaType()}
229     * and {@link #fileExtension()} as defined in the corresponding
230     * W3C specification.
231     *
232     * @return
233     *      A set of the official RDF 1.1 {@link RDFSyntax}es.
234     *
235     * @see <a href="https://www.w3.org/TR/rdf11-primer/#section-graph-syntax">RDF
236     *      1.1 Primer</a>
237     * @see org.apache.commons.rdf.experimental.RDFParser
238     */
239
240    static Set<RDFSyntax> w3cSyntaxes() {
241        return W3CRDFSyntax.syntaxes;
242    }
243
244    /**
245     * Return the RDFSyntax with the specified media type.
246     * <p>
247     * The <code>mediaType</code> is compared in lower case to all media types
248     * supported, therefore it might not be equal to the
249     * {@link RDFSyntax#mediaType} of the returned RDFSyntax.
250     * <p>
251     * If the media type specifies parameters, e.g.
252     * <code>text/turtle; charset=ascii</code>, only the part of the string to
253     * before <code>;</code> is considered.
254     * <p>
255     * This method support all syntaxes returned by {@link #w3cSyntaxes()}.
256     *
257     * @param mediaType
258     *            The media type to match
259     * @return If {@link Optional#isPresent()}, the {@link RDFSyntax} which has
260     *         a matching {@link RDFSyntax#mediaType()}, otherwise
261     *         {@link Optional#empty()} indicating that no matching syntax was
262     *         found.
263     */
264    static Optional<RDFSyntax> byMediaType(final String mediaType) {
265        final String type = mediaType.toLowerCase(Locale.ROOT).split("\\s*;", 2)[0];
266        return w3cSyntaxes().stream().filter(t -> t.mediaTypes().contains(type))
267                .findAny();
268    }
269
270    /**
271     * Return the RDFSyntax with the specified file extension.
272     * <p>
273     * The <code>fileExtension</code> is compared in lower case to all
274     * extensions supported, therefore it might not be equal to the
275     * {@link RDFSyntax#fileExtension} of the returned RDFSyntax.
276     * <p>
277     * This method support all syntaxes returned by {@link #w3cSyntaxes()}.
278     *
279     * @param fileExtension
280     *            The fileExtension to match, starting with <code>.</code>
281     * @return If {@link Optional#isPresent()}, the {@link RDFSyntax} which has
282     *         a matching {@link RDFSyntax#fileExtension()}, otherwise
283     *         {@link Optional#empty()} indicating that no matching file
284     *         extension was found.
285     */
286    static Optional<RDFSyntax> byFileExtension(final String fileExtension) {
287        final String ext = fileExtension.toLowerCase(Locale.ROOT);
288        return w3cSyntaxes().stream().filter(t -> t.fileExtensions().contains(ext))
289                .findAny();
290    }
291
292    /**
293     * Return the RDFSyntax with the specified {@link #name()}.
294     * <p>
295     * This method support all syntaxes returned by {@link #w3cSyntaxes()}.
296     *
297     * @param name
298     *            The name to match, , e.g. <code>"JSONLD"</code>
299     * @return If {@link Optional#isPresent()}, the {@link RDFSyntax} which has
300     *         a matching {@link RDFSyntax#name()}, otherwise
301     *         {@link Optional#empty()} indicating that no matching name was found.
302     */
303    static Optional<RDFSyntax> byName(final String name) {
304        return w3cSyntaxes().stream().filter(t -> t.name().equals(name)).findAny();
305    }
306
307
308}