blob: c007aff34584ee99382ac27378a057f690820700 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.rdf.api;
import java.util.Objects;
import java.util.Optional;
/**
* A Quad is a statement in a
* <a href= "http://www.w3.org/TR/rdf11-concepts/#section-dataset" >RDF-1.1
* Dataset</a>, as defined by <a href=
* "https://www.w3.org/TR/2014/NOTE-rdf11-datasets-20140225/#quad-semantics"
* >RDF-1.1 Concepts and Abstract Syntax</a>, a W3C Working Group Note published
* on 25 February 2014.
* <p>
* A <code>Quad</code> object in Commons RDF is considered
* <strong>immutable</strong>, that is, over its life time it will have
* consistent behaviour for its {@link #equals(Object)}, and the instances
* returned from {@link #getGraphName()}, {@link #getSubject()},
* {@link #getPredicate()}, {@link #getObject()} and {@link #asTriple()} will
* have consistent {@link Object#equals(Object)} behaviour.
* <p>
* Note that <code>Quad</code> methods are not required to return object
* identical (<code>==</code>) instances as long as they are equivalent
* according to {@link Object#equals(Object)}. Specialisations of
* <code>Quad</code> may provide additional methods that are documented to be
* mutable.
* <p>
* <code>Quad</code> methods are <strong>thread-safe</strong>, however
* specialisations may provide additional methods that are documented to not be
* thread-safe.
* <p>
* <code>Quad</code>s can be safely used in hashing collections like
* {@link java.util.HashSet} and {@link java.util.HashMap}.
* <p>
* Any <code>Quad</code> can be used interchangeably across Commons RDF
* implementations.
*
* @since 0.3.0-incubating
* @see Dataset
* @see RDF#createQuad(BlankNodeOrIRI,BlankNodeOrIRI,IRI,RDFTerm)
* @see <a href="http://www.w3.org/TR/2014/NOTE-rdf11-datasets-20140225/">RDF
* 1.1: On Semantics of RDF Datasets</a>
* @see <a href="http://www.w3.org/TR/rdf11-concepts/#section-dataset"> </a>
*/
public interface Quad extends QuadLike<BlankNodeOrIRI> {
/**
* The graph name (graph label) of this quad, if present.
*
* If {@link Optional#isPresent()}, then the {@link Optional#get()} is
* either a {@link BlankNode} or an {@link IRI}, indicating the
* <a href="https://www.w3.org/TR/rdf11-concepts/#dfn-named-graph">graph
* name</a> of this Quad. If the graph name is not present, e.g. the value
* is {@link Optional#empty()}, it indicates that this Quad is in the
* <a href="https://www.w3.org/TR/rdf11-concepts/#dfn-default-graph">default
* graph</a>.
*
* @return If {@link Optional#isPresent()}, the graph name
* {@link BlankNodeOrIRI} of this quad, otherwise
* {@link Optional#empty()}, indicating the default graph.
*
* @see <a href="https://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset">RDF-
* 1.1 Dataset</a>
*/
@Override
Optional<BlankNodeOrIRI> getGraphName();
/**
* The subject of this quad, which may be either a {@link BlankNode} or an
* {@link IRI}, which are represented in Commons RDF by the interface
* {@link BlankNodeOrIRI}.
*
* @return The subject {@link BlankNodeOrIRI} of this quad.
* @see <a href="http://www.w3.org/TR/rdf11-concepts/#dfn-subject">RDF-1.1
* Triple subject</a>
*/
@Override
BlankNodeOrIRI getSubject();
/**
* The predicate {@link IRI} of this quad.
*
* @return The predicate {@link IRI} of this quad.
* @see <a href="http://www.w3.org/TR/rdf11-concepts/#dfn-predicate">RDF-1.1
* Triple predicate</a>
*/
@Override
IRI getPredicate();
/**
* The object of this quad, which may be either a {@link BlankNode}, an
* {@link IRI}, or a {@link Literal}, which are represented in Commons RDF
* by the interface {@link RDFTerm}.
*
* @return The object {@link RDFTerm} of this quad.
* @see <a href="http://www.w3.org/TR/rdf11-concepts/#dfn-object">RDF-1.1
* Triple object</a>
*/
@Override
RDFTerm getObject();
/**
* Adapt this Quad to a Triple.
* <p>
* The returned {@link Triple} will have equivalent values returned from the
* methods {@link TripleLike#getSubject()},
* {@link TripleLike#getPredicate()} and {@link TripleLike#getObject()}.
* <p>
* The returned {@link Triple} MUST NOT be {@link #equals(Object)} to this
* {@link Quad}, even if this quad has a default graph
* {@link #getGraphName()} value of {@link Optional#empty()}, but MUST
* follow the {@link Triple#equals(Object)} semantics. This means that the
* following MUST be true:
*
* <pre>
* Quad q1, q2;
* if (q1.equals(q2)) {
* assert (q1.asTriple().equals(q2.asTriple()));
* } else if (q1.asTriple().equals(q2.asTriple())) {
* assert (q1.getSubject().equals(q2.getSubject()));
* assert (q1.getPredicate().equals(q2.getPredicate()));
* assert (q1.getObject().equals(q2.getObject()));
* assert (!q1.getGraphName().equals(q2.getGraphName()));
* }
* </pre>
*
* The <code>default</code> implementation of this method return a proxy
* {@link Triple} instance that keeps a reference to this {@link Quad} to
* call the underlying {@link TripleLike} methods, but supplies a
* {@link Triple} compatible implementation of {@link Triple#equals(Object)}
* and {@link Triple#hashCode()}. Implementations may override this method,
* e.g. for a more efficient solution.
*
* @return A {@link Triple} that contains the same {@link TripleLike}
* properties as this Quad.
*/
default Triple asTriple() {
return new Triple() {
@Override
public BlankNodeOrIRI getSubject() {
return Quad.this.getSubject();
}
@Override
public IRI getPredicate() {
return Quad.this.getPredicate();
}
@Override
public RDFTerm getObject() {
return Quad.this.getObject();
}
@Override
public boolean equals(final Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof Triple)) {
return false;
}
final Triple other = (Triple) obj;
return Objects.equals(getSubject(), other.getSubject())
&& Objects.equals(getPredicate(), other.getPredicate())
&& Objects.equals(getObject(), other.getObject());
}
@Override
public int hashCode() {
return Objects.hash(getSubject(), getPredicate(), getObject());
}
};
}
/**
* Check it this Quad is equal to another Quad.
* <p>
* Two Quads are equal if and only if their {@link #getGraphName()},
* {@link #getSubject()}, {@link #getPredicate()} and {@link #getObject()}
* are equal.
* </p>
* <p>
* Implementations MUST also override {@link #hashCode()} so that two equal
* Quads produce the same hash code.
* </p>
* <p>
* Note that a {@link Quad} MUST NOT be equal to a {@link Triple}, even if
* this Quad's {@link #getGraphName()} is {@link Optional#empty()}. To test
* triple-like equivalence, callers can use:
* </p>
*
* <pre>
* Quad q1;
* Triple t2;
* q1.asTriple().equals(t2));
* </pre>
*
* @param other
* Another object
* @return true if other is a Quad and is equal to this
* @see Object#equals(Object)
*/
@Override
public boolean equals(Object other);
/**
* Calculate a hash code for this Quad.
* <p>
* The returned hash code MUST be equal to the result of
* {@link Objects#hash(Object...)} with the arguments {@link #getSubject()},
* {@link #getPredicate()}, {@link #getObject()}, {@link #getGraphName()}.
* <p>
* This method MUST be implemented in conjunction with
* {@link #equals(Object)} so that two equal {@link Quad}s produce the same
* hash code.
*
* @return a hash code value for this Quad.
* @see Object#hashCode()
* @see Objects#hash(Object...)
*/
@Override
public int hashCode();
}