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.Objects;
021import java.util.Optional;
022
023/**
024 * A Quad is a statement in a
025 * <a href= "http://www.w3.org/TR/rdf11-concepts/#section-dataset" >RDF-1.1
026 * Dataset</a>, as defined by <a href=
027 * "https://www.w3.org/TR/2014/NOTE-rdf11-datasets-20140225/#quad-semantics"
028 * >RDF-1.1 Concepts and Abstract Syntax</a>, a W3C Working Group Note published
029 * on 25 February 2014.
030 * <p>
031 * A <code>Quad</code> object in Commons RDF is considered
032 * <strong>immutable</strong>, that is, over its life time it will have
033 * consistent behaviour for its {@link #equals(Object)}, and the instances
034 * returned from {@link #getGraphName()}, {@link #getSubject()},
035 * {@link #getPredicate()}, {@link #getObject()} and {@link #asTriple()} will
036 * have consistent {@link Object#equals(Object)} behaviour.
037 * <p>
038 * Note that <code>Quad</code> methods are not required to return object
039 * identical (<code>==</code>) instances as long as they are equivalent
040 * according to {@link Object#equals(Object)}. Specialisations of
041 * <code>Quad</code> may provide additional methods that are documented to be
042 * mutable.
043 * <p>
044 * <code>Quad</code> methods are <strong>thread-safe</strong>, however
045 * specialisations may provide additional methods that are documented to not be
046 * thread-safe.
047 * <p>
048 * <code>Quad</code>s can be safely used in hashing collections like
049 * {@link java.util.HashSet} and {@link java.util.HashMap}.
050 * <p>
051 * Any <code>Quad</code> can be used interchangeably across Commons RDF
052 * implementations.
053 *
054 * @since 0.3.0-incubating
055 * @see Dataset
056 * @see RDF#createQuad(BlankNodeOrIRI,BlankNodeOrIRI,IRI,RDFTerm)
057 * @see <a href="http://www.w3.org/TR/2014/NOTE-rdf11-datasets-20140225/">RDF
058 *      1.1: On Semantics of RDF Datasets</a>
059 * @see <a href="http://www.w3.org/TR/rdf11-concepts/#section-dataset"> </a>
060 */
061public interface Quad extends QuadLike<BlankNodeOrIRI> {
062
063    /**
064     * The graph name (graph label) of this quad, if present.
065     *
066     * If {@link Optional#isPresent()}, then the {@link Optional#get()} is
067     * either a {@link BlankNode} or an {@link IRI}, indicating the
068     * <a href="https://www.w3.org/TR/rdf11-concepts/#dfn-named-graph">graph
069     * name</a> of this Quad. If the graph name is not present, e.g. the value
070     * is {@link Optional#empty()}, it indicates that this Quad is in the
071     * <a href="https://www.w3.org/TR/rdf11-concepts/#dfn-default-graph">default
072     * graph</a>.
073     *
074     * @return If {@link Optional#isPresent()}, the graph name
075     *         {@link BlankNodeOrIRI} of this quad, otherwise
076     *         {@link Optional#empty()}, indicating the default graph.
077     *
078     * @see <a href="https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset">RDF-
079     *      1.1 Dataset</a>
080     */
081    @Override
082    Optional<BlankNodeOrIRI> getGraphName();
083
084    /**
085     * The subject of this quad, which may be either a {@link BlankNode} or an
086     * {@link IRI}, which are represented in Commons RDF by the interface
087     * {@link BlankNodeOrIRI}.
088     *
089     * @return The subject {@link BlankNodeOrIRI} of this quad.
090     * @see <a href="http://www.w3.org/TR/rdf11-concepts/#dfn-subject">RDF-1.1
091     *      Triple subject</a>
092     */
093    @Override
094    BlankNodeOrIRI getSubject();
095
096    /**
097     * The predicate {@link IRI} of this quad.
098     *
099     * @return The predicate {@link IRI} of this quad.
100     * @see <a href="http://www.w3.org/TR/rdf11-concepts/#dfn-predicate">RDF-1.1
101     *      Triple predicate</a>
102     */
103    @Override
104    IRI getPredicate();
105
106    /**
107     * The object of this quad, which may be either a {@link BlankNode}, an
108     * {@link IRI}, or a {@link Literal}, which are represented in Commons RDF
109     * by the interface {@link RDFTerm}.
110     *
111     * @return The object {@link RDFTerm} of this quad.
112     * @see <a href="http://www.w3.org/TR/rdf11-concepts/#dfn-object">RDF-1.1
113     *      Triple object</a>
114     */
115    @Override
116    RDFTerm getObject();
117
118    /**
119     * Adapt this Quad to a Triple.
120     * <p>
121     * The returned {@link Triple} will have equivalent values returned from the
122     * methods {@link TripleLike#getSubject()},
123     * {@link TripleLike#getPredicate()} and {@link TripleLike#getObject()}.
124     * <p>
125     * The returned {@link Triple} MUST NOT be {@link #equals(Object)} to this
126     * {@link Quad}, even if this quad has a default graph
127     * {@link #getGraphName()} value of {@link Optional#empty()}, but MUST
128     * follow the {@link Triple#equals(Object)} semantics. This means that the
129     * following MUST be true:
130     *
131     * <pre>
132     * Quad q1, q2;
133     * if (q1.equals(q2)) {
134     *     assert (q1.asTriple().equals(q2.asTriple()));
135     * } else if (q1.asTriple().equals(q2.asTriple())) {
136     *     assert (q1.getSubject().equals(q2.getSubject()));
137     *     assert (q1.getPredicate().equals(q2.getPredicate()));
138     *     assert (q1.getObject().equals(q2.getObject()));
139     *     assert (!q1.getGraphName().equals(q2.getGraphName()));
140     * }
141     * </pre>
142     *
143     * The <code>default</code> implementation of this method return a proxy
144     * {@link Triple} instance that keeps a reference to this {@link Quad} to
145     * call the underlying {@link TripleLike} methods, but supplies a
146     * {@link Triple} compatible implementation of {@link Triple#equals(Object)}
147     * and {@link Triple#hashCode()}. Implementations may override this method,
148     * e.g. for a more efficient solution.
149     *
150     * @return A {@link Triple} that contains the same {@link TripleLike}
151     *         properties as this Quad.
152     */
153    default Triple asTriple() {
154        return new Triple() {
155            @Override
156            public BlankNodeOrIRI getSubject() {
157                return Quad.this.getSubject();
158            }
159
160            @Override
161            public IRI getPredicate() {
162                return Quad.this.getPredicate();
163            }
164
165            @Override
166            public RDFTerm getObject() {
167                return Quad.this.getObject();
168            }
169
170            @Override
171            public boolean equals(final Object obj) {
172                if (obj == this) {
173                    return true;
174                }
175                if (!(obj instanceof Triple)) {
176                    return false;
177                }
178                final Triple other = (Triple) obj;
179                return Objects.equals(getSubject(), other.getSubject())
180                        && Objects.equals(getPredicate(), other.getPredicate())
181                        && Objects.equals(getObject(), other.getObject());
182            }
183
184            @Override
185            public int hashCode() {
186                return Objects.hash(getSubject(), getPredicate(), getObject());
187            }
188        };
189    }
190
191    /**
192     * Check it this Quad is equal to another Quad.
193     * <p>
194     * Two Quads are equal if and only if their {@link #getGraphName()},
195     * {@link #getSubject()}, {@link #getPredicate()} and {@link #getObject()}
196     * are equal.
197     * </p>
198     * <p>
199     * Implementations MUST also override {@link #hashCode()} so that two equal
200     * Quads produce the same hash code.
201     * </p>
202     * <p>
203     * Note that a {@link Quad} MUST NOT be equal to a {@link Triple}, even if
204     * this Quad's {@link #getGraphName()} is {@link Optional#empty()}. To test
205     * triple-like equivalence, callers can use:
206     * </p>
207     *
208     * <pre>
209     * Quad q1;
210     * Triple t2;
211     * q1.asTriple().equals(t2));
212     * </pre>
213     *
214     * @param other
215     *            Another object
216     * @return true if other is a Quad and is equal to this
217     * @see Object#equals(Object)
218     */
219    @Override
220    boolean equals(Object other);
221
222    /**
223     * Calculate a hash code for this Quad.
224     * <p>
225     * The returned hash code MUST be equal to the result of
226     * {@link Objects#hash(Object...)} with the arguments {@link #getSubject()},
227     * {@link #getPredicate()}, {@link #getObject()}, {@link #getGraphName()}.
228     * <p>
229     * This method MUST be implemented in conjunction with
230     * {@link #equals(Object)} so that two equal {@link Quad}s produce the same
231     * hash code.
232     *
233     * @return a hash code value for this Quad.
234     * @see Object#hashCode()
235     * @see Objects#hash(Object...)
236     */
237    @Override
238    int hashCode();
239
240}