View Javadoc
1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements. See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership. The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.commons.rdf.api;
19  
20  import java.util.Objects;
21  import java.util.Optional;
22  
23  /**
24   * A Quad is a statement in a
25   * <a href= "http://www.w3.org/TR/rdf11-concepts/#section-dataset" >RDF-1.1
26   * Dataset</a>, as defined by <a href=
27   * "https://www.w3.org/TR/2014/NOTE-rdf11-datasets-20140225/#quad-semantics"
28   * >RDF-1.1 Concepts and Abstract Syntax</a>, a W3C Working Group Note published
29   * on 25 February 2014.
30   * <p>
31   * A <code>Quad</code> object in Commons RDF is considered
32   * <strong>immutable</strong>, that is, over its life time it will have
33   * consistent behaviour for its {@link #equals(Object)}, and the instances
34   * returned from {@link #getGraphName()}, {@link #getSubject()},
35   * {@link #getPredicate()}, {@link #getObject()} and {@link #asTriple()} will
36   * have consistent {@link Object#equals(Object)} behaviour.
37   * <p>
38   * Note that <code>Quad</code> methods are not required to return object
39   * identical (<code>==</code>) instances as long as they are equivalent
40   * according to {@link Object#equals(Object)}. Specialisations of
41   * <code>Quad</code> may provide additional methods that are documented to be
42   * mutable.
43   * <p>
44   * <code>Quad</code> methods are <strong>thread-safe</strong>, however
45   * specialisations may provide additional methods that are documented to not be
46   * thread-safe.
47   * <p>
48   * <code>Quad</code>s can be safely used in hashing collections like
49   * {@link java.util.HashSet} and {@link java.util.HashMap}.
50   * <p>
51   * Any <code>Quad</code> can be used interchangeably across Commons RDF
52   * implementations.
53   *
54   * @since 0.3.0-incubating
55   * @see Dataset
56   * @see RDF#createQuad(BlankNodeOrIRI,BlankNodeOrIRI,IRI,RDFTerm)
57   * @see <a href="http://www.w3.org/TR/2014/NOTE-rdf11-datasets-20140225/">RDF
58   *      1.1: On Semantics of RDF Datasets</a>
59   * @see <a href="http://www.w3.org/TR/rdf11-concepts/#section-dataset"> </a>
60   */
61  public interface Quad extends QuadLike<BlankNodeOrIRI> {
62  
63      /**
64       * The graph name (graph label) of this quad, if present.
65       *
66       * If {@link Optional#isPresent()}, then the {@link Optional#get()} is
67       * either a {@link BlankNode} or an {@link IRI}, indicating the
68       * <a href="https://www.w3.org/TR/rdf11-concepts/#dfn-named-graph">graph
69       * name</a> of this Quad. If the graph name is not present, e.g. the value
70       * is {@link Optional#empty()}, it indicates that this Quad is in the
71       * <a href="https://www.w3.org/TR/rdf11-concepts/#dfn-default-graph">default
72       * graph</a>.
73       *
74       * @return If {@link Optional#isPresent()}, the graph name
75       *         {@link BlankNodeOrIRI} of this quad, otherwise
76       *         {@link Optional#empty()}, indicating the default graph.
77       *
78       * @see <a href="https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset">RDF-
79       *      1.1 Dataset</a>
80       */
81      @Override
82      Optional<BlankNodeOrIRI> getGraphName();
83  
84      /**
85       * The subject of this quad, which may be either a {@link BlankNode} or an
86       * {@link IRI}, which are represented in Commons RDF by the interface
87       * {@link BlankNodeOrIRI}.
88       *
89       * @return The subject {@link BlankNodeOrIRI} of this quad.
90       * @see <a href="http://www.w3.org/TR/rdf11-concepts/#dfn-subject">RDF-1.1
91       *      Triple subject</a>
92       */
93      @Override
94      BlankNodeOrIRI getSubject();
95  
96      /**
97       * The predicate {@link IRI} of this quad.
98       *
99       * @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 }