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.io.Serializable;
021import java.util.Locale;
022import java.util.Objects;
023import java.util.Optional;
024
025/**
026 * An <a href= "https://www.w3.org/TR/rdf11-concepts/#dfn-literal"
027 * >RDF-1.1 Literal</a>, as defined by
028 * <a href= "http://www.w3.org/TR/rdf11-concepts/#section-Graph-Literal"
029 * >RDF-1.1 Concepts and Abstract Syntax</a>, a W3C Recommendation published on
030 * 25 February 2014.
031 *
032 * @see RDF#createLiteral(String)
033 * @see RDF#createLiteral(String, IRI)
034 * @see RDF#createLiteral(String, String)
035 */
036public interface Literal extends RDFTerm {
037
038    /**
039     * The lexical form of this literal, represented by a
040     * <a href="http://www.unicode.org/versions/latest/">Unicode string</a>.
041     *
042     * @return The lexical form of this literal.
043     * @see <a href=
044     *      "http://www.w3.org/TR/rdf11-concepts/#dfn-lexical-form">RDF-1.1
045     *      Literal lexical form</a>
046     */
047    String getLexicalForm();
048
049    /**
050     * The IRI identifying the datatype that determines how the lexical form
051     * maps to a literal value.
052     *
053     * If the datatype IRI is
054     * <a href="http://www.w3.org/1999/02/22-rdf-syntax-ns#langString"
055     * >http://www.w3.org/1999/02/22-rdf-syntax-ns#langString</a>,
056     * {@link #getLanguageTag()} must not return {@link Optional#empty()}, and
057     * it must return a valid
058     * <a href="http://tools.ietf.org/html/bcp47">BCP47</a> language tag.
059     *
060     * @return The datatype IRI for this literal.
061     * @see <a href=
062     *      "http://www.w3.org/TR/rdf11-concepts/#dfn-datatype-iri">RDF-1.1
063     *      Literal datatype IRI</a>
064     */
065    IRI getDatatype();
066
067    /**
068     * If and only if the datatype IRI is
069     * <a href="http://www.w3.org/1999/02/22-rdf-syntax-ns#langString"
070     * >http://www.w3.org/1999/02/22-rdf-syntax-ns#langString</a>, the language
071     * tag for this Literal is a non-empty language tag as defined by
072     * <a href="http://tools.ietf.org/html/bcp47">BCP47</a>.<br>
073     * If the datatype IRI is not
074     * <a href="http://www.w3.org/1999/02/22-rdf-syntax-ns#langString"
075     * >http://www.w3.org/1999/02/22-rdf-syntax-ns#langString</a>, this method
076     * must return {@link Optional#empty()}.
077     * <p>
078     * The value space of language tags is always in lower case; although
079     * RDF implementations MAY convert all language tags to lower case,
080     * safe comparisons of language tags should be done using
081     * {@link String#toLowerCase(Locale)} with the locale
082     * {@link Locale#ROOT}.
083     * <p>
084     * Implementation note: If your application requires {@link Serializable}
085     * objects, it is best not to store an {@link Optional} in a field. It is
086     * recommended to use {@link Optional#ofNullable(Object)} to create the
087     * return value for this method.
088     *
089     * @return The {@link Optional} language tag for this literal. If
090     *         {@link Optional#isPresent()} returns true, the value returned by
091     *         {@link Optional#get()} must be a non-empty language tag string
092     *         conforming to BCP47.
093     * @see <a href=
094     *      "http://www.w3.org/TR/rdf11-concepts/#dfn-language-tag">RDF-1.1
095     *      Literal language tag</a>
096     */
097    Optional<String> getLanguageTag();
098
099    /**
100     * Check it this Literal is equal to another Literal.
101     * <blockquote>
102     * <a href="http://www.w3.org/TR/rdf11-concepts/#dfn-literal-term">Literal
103     * term equality</a>:
104     * Two literals are term-equal (the same RDF literal) if
105     * and only if the two lexical forms, the two datatype IRIs, and the two
106     * language tags (if any) compare equal, character by character. Thus, two
107     * literals can have the same value without being the same RDF term.
108     * </blockquote>
109     * As the value space for language tags is lower-space, if they are present,
110     * they MUST be compared character by character
111     * using the equivalent of {@link String#toLowerCase(java.util.Locale)} with
112     * the locale {@link Locale#ROOT}.
113     * <p>
114     * Implementations MUST also override {@link #hashCode()} so that two equal
115     * Literals produce the same hash code.
116     *
117     * @param other
118     *            Another object
119     * @return true if other is a Literal and is equal to this
120     * @see Object#equals(Object)
121     */
122    @Override
123    boolean equals(Object other);
124
125    /**
126     * Calculate a hash code for this Literal.
127     * <p>
128     * The returned hash code MUST be equal to the result of
129     * {@link Objects#hash(Object...)} with the arguments
130     * {@link #getLexicalForm()}, {@link #getDatatype()},
131     * {@link #getLanguageTag()}<code>.map(s-&gt;s.toLowerString(Locale.ROOT))</code>.
132     * <p>
133     * This method MUST be implemented in conjunction with
134     * {@link #equals(Object)} so that two equal Literals produce the same hash
135     * code.
136     *
137     * @return a hash code value for this Literal.
138     * @see Object#hashCode()
139     * @see Objects#hash(Object...)
140     */
141    @Override
142    int hashCode();
143
144}