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}