/* * BioJava development code * * This code may be freely distributed and modified under the * terms of the GNU Lesser General Public Licence. This should * be distributed with the code. If you do not have a copy, * see: * * http://www.gnu.org/copyleft/lesser.html * * Copyright for this code is held jointly by the individual * authors. These should be listed in @author doc comments. * * For more information on the BioJava project and its aims, * or to join the biojava-l mailing list, visit the home page * at: * * http://www.biojava.org/ * */ package org.biojava.nbio.ontology; import org.biojava.nbio.ontology.utils.Annotation; import java.util.Arrays; import java.util.Set; import java.util.TreeSet; /** * A triple in an ontology. This is two terms and a relationship between * them, similar to RDF and other similar logic systems. * * <p> * For documentation purposes, a Triple may provide a name. However, a Triple * may also be named as "(subject, object, predicate)" if no specific name is * provided. * </p> * * @author Thomas Down * @author Matthew Pocock * @since 1.4 * @see org.biojavax.ontology.ComparableTriple */ public interface Triple extends Term { /** * Return the subject term of this triple * @return the subject term */ public Term getSubject(); /** * Return the object term of this triple. * @return the object term */ public Term getObject(); /** * Return a Term which defines the type of relationship between the subject and object terms. * @return the predicate */ public Term getPredicate(); /** * The hashcode for a Triple. * * <p>This <em>must</em> be implemented as: * <pre> * return getSubject().hashCode() + * 31 * getObject().hashCode() + * 31 * 31 * getPredicate().hashCode(); * </pre> * If you do not implement hashcode in this way then you have no guarantee * that your Triple objects will be found in an ontology and that they will * not be duplicated. * </p> */ @Override public int hashCode(); /** * Check to see if an object is an equivalent Triple. * * <p> * Two triples are equivalent if they have the same subject, object and * predicate fields. * <pre> * if (! (o instanceof Triple)) { * return false; * } * Triple to = (Triple) o; * return to.getSubject() == getSubject() && * to.getObject() == getObject() && * to.getPredicate() == getPredicate(); * </pre> * If you do not implement equals in this way then you have no guarantee * that your Triple objects will be found in an ontology and that they will * not be duplicated. * </p> */ @Override public boolean equals(Object obj); /** * Basic in-memory implementation of a Triple in an ontology * * This can be used to implement Ontology.createTriple * @see org.biojavax.ontology.SimpleComparableTriple */ public static final class Impl implements Triple, java.io.Serializable { /** * */ private static final long serialVersionUID = 3807331980372839221L; private final Term subject; private final Term object; private final Term predicate; private /*final*/ String name; private /*final*/ String description; private Set<Object> synonyms; public Impl(Term subject, Term object, Term predicate) { this(subject, object, predicate, null, null, null); } public Impl(Term subject, Term object, Term predicate, Object[] synonyms) { this(subject, object, predicate, null, null, synonyms); } public Impl(Term subject, Term object, Term predicate, String name, String description) { this(subject,object,predicate,name,description,null); } public Impl(Term subject, Term object, Term predicate, String name, String description, Object[] synonyms) { if (subject == null) { throw new NullPointerException("Subject must not be null"); } if (object == null) { throw new NullPointerException("Object must not be null"); } if (predicate == null) { throw new NullPointerException("predicate must not be null"); } if( subject.getOntology() != object.getOntology() || subject.getOntology() != predicate.getOntology() ) { throw new IllegalArgumentException( "All terms must be from the same ontology: " + subject.getOntology().getName() + ", " + object.getOntology().getName() + ", " + predicate.getOntology().getName()); } if(description == null) { description = ""; } this.subject = subject; this.object = object; this.predicate = predicate; this.name = name; this.description = description; this.synonyms = new TreeSet<Object>(); if (synonyms!=null) this.synonyms.addAll(Arrays.asList(synonyms)); } @Override public void addSynonym(Object synonym) { this.synonyms.add(synonym); } @Override public void removeSynonym(Object synonym) { this.synonyms.remove(synonym); } @Override public Object[] getSynonyms() { return this.synonyms.toArray(); } @Override public String getName() { if(name == null) { name = predicate + "(" + subject + ", " + object + ")"; } return name; } @Override public String getDescription() { return description; } @Override public void setDescription(String desc){ this.description = desc; } @Override public Ontology getOntology() { return subject.getOntology(); } @Override public Term getSubject() { return subject; } @Override public Term getObject() { return object; } @Override public Term getPredicate() { return predicate; } @Override public Annotation getAnnotation() { return Annotation.EMPTY_ANNOTATION; } /** * Two triples are equal if all their fields are identical. */ @Override public boolean equals(Object o) { if (! (o instanceof Triple)) { return false; } Triple to = (Triple) o; return to.getSubject().equals(getSubject()) && to.getObject().equals(getObject()) && to.getPredicate().equals(getPredicate()); } @Override public int hashCode() { return getSubject().hashCode() + 31 * getObject().hashCode() + 31 * 31 * getPredicate().hashCode(); } @Override public String toString() { if (getName().length() > 0) return getName(); return subject + " " + predicate + " " + object; } } }