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 }