001/* 002 * BioJava development code 003 * 004 * This code may be freely distributed and modified under the 005 * terms of the GNU Lesser General Public Licence. This should 006 * be distributed with the code. If you do not have a copy, 007 * see: 008 * 009 * http://www.gnu.org/copyleft/lesser.html 010 * 011 * Copyright for this code is held jointly by the individual 012 * authors. These should be listed in @author doc comments. 013 * 014 * For more information on the BioJava project and its aims, 015 * or to join the biojava-l mailing list, visit the home page 016 * at: 017 * 018 * http://www.biojava.org/ 019 * 020 */ 021 022package org.biojava.ontology; 023 024import java.util.Arrays; 025import java.util.Set; 026import java.util.TreeSet; 027 028import org.biojava.bio.Annotation; 029import org.biojava.utils.Unchangeable; 030 031/** 032 * A triple in an ontology. This is two terms and a relationship between 033 * them, similar to RDF and other similar logic systems. 034 * 035 * <p> 036 * For documentation purposes, a Triple may provide a name. However, a Triple 037 * may also be named as "(subject, object, predicate)" if no specific name is 038 * provided. 039 * </p> 040 * 041 * @author Thomas Down 042 * @author Matthew Pocock 043 * @since 1.4 044 * @see org.biojavax.ontology.ComparableTriple 045 */ 046 047public interface Triple 048extends Term { 049 /** 050 * Return the subject term of this triple 051 * @return the subject term 052 */ 053 054 public Term getSubject(); 055 056 /** 057 * Return the object term of this triple. 058 * @return the object term 059 */ 060 061 public Term getObject(); 062 063 /** 064 * Return a Term which defines the type of relationship between the subject and object terms. 065 * @return the predicate 066 */ 067 068 public Term getPredicate(); 069 070 /** 071 * The hashcode for a Triple. 072 * 073 * <p>This <em>must</em> be implemented as: 074 * <pre> 075 * return getSubject().hashCode() + 076 31 * getObject().hashCode() + 077 31 * 31 * getPredicate().hashCode(); 078 * </pre> 079 * If you do not implement hashcode in this way then you have no guarantee 080 * that your Triple objects will be found in an ontology and that they will 081 * not be duplicated. 082 * </p> 083 */ 084 public int hashCode(); 085 086 /** 087 * Check to see if an object is an equivalent Triple. 088 * 089 * <p> 090 * Two triples are equivalent if they have the same subject, object and 091 * predicate fields. 092 * <pre> 093 * if (! (o instanceof Triple)) { 094 * return false; 095 * } 096 * Triple to = (Triple) o; 097 * return to.getSubject() == getSubject() && 098 * to.getObject() == getObject() && 099 * to.getPredicate() == getPredicate(); 100 * </pre> 101 * If you do not implement equals in this way then you have no guarantee 102 * that your Triple objects will be found in an ontology and that they will 103 * not be duplicated. 104 * </p> 105 */ 106 public boolean equals(Object obj); 107 108 /** 109 * Basic in-memory implementation of a Triple in an ontology 110 * 111 * This can be used to implement Ontology.createTriple 112 * @see org.biojavax.ontology.SimpleComparableTriple 113 */ 114 115 public static final class Impl 116 extends Unchangeable 117 implements Triple, java.io.Serializable { 118 /** 119 * 120 */ 121 private static final long serialVersionUID = 3807331980372839221L; 122 private final Term subject; 123 private final Term object; 124 private final Term predicate; 125 private /*final*/ String name; 126 private /*final*/ String description; 127 private Set<Object> synonyms; 128 129 public Impl(Term subject, Term object, Term predicate) { 130 this(subject, object, predicate, null, null, null); 131 } 132 133 public Impl(Term subject, Term object, Term predicate, Object[] synonyms) { 134 this(subject, object, predicate, null, null, synonyms); 135 } 136 137 public Impl(Term subject, 138 Term object, 139 Term predicate, 140 String name, 141 String description) { 142 this(subject,object,predicate,name,description,null); 143 } 144 145 public Impl(Term subject, 146 Term object, 147 Term predicate, 148 String name, 149 String description, 150 Object[] synonyms) 151 { 152 if (subject == null) { 153 throw new NullPointerException("Subject must not be null"); 154 } 155 if (object == null) { 156 throw new NullPointerException("Object must not be null"); 157 } 158 if (predicate == null) { 159 throw new NullPointerException("predicate must not be null"); 160 } 161 162 if( 163 subject.getOntology() != object.getOntology() || 164 subject.getOntology() != predicate.getOntology() 165 ) { 166 throw new IllegalArgumentException( 167 "All terms must be from the same ontology: " + 168 subject.getOntology().getName() + ", " + 169 object.getOntology().getName() + ", " + 170 predicate.getOntology().getName()); 171 } 172 173 if(description == null) { 174 description = ""; 175 } 176 177 this.subject = subject; 178 this.object = object; 179 this.predicate = predicate; 180 this.name = name; 181 this.description = description; 182 183 this.synonyms = new TreeSet<Object>(); 184 if (synonyms!=null) this.synonyms.addAll(Arrays.asList(synonyms)); 185 } 186 187 public void addSynonym(Object synonym) { 188 this.synonyms.add(synonym); 189 } 190 191 public void removeSynonym(Object synonym) { 192 this.synonyms.remove(synonym); 193 } 194 195 public Object[] getSynonyms() { 196 return this.synonyms.toArray(); 197 } 198 199 public String getName() { 200 if(name == null) { 201 name = predicate + "(" + subject + ", " + object + ")"; 202 } 203 return name; 204 } 205 206 public String getDescription() { 207 return description; 208 } 209 public void setDescription(String desc){ 210 this.description = desc; 211 } 212 213 public Ontology getOntology() { 214 return subject.getOntology(); 215 } 216 217 public Term getSubject() { 218 return subject; 219 } 220 221 public Term getObject() { 222 return object; 223 } 224 225 public Term getPredicate() { 226 return predicate; 227 } 228 229 public Annotation getAnnotation() { 230 return Annotation.EMPTY_ANNOTATION; 231 } 232 233 /** 234 * Two triples are equal if all their fields are identical. 235 */ 236 237 public boolean equals(Object o) { 238 if (! (o instanceof Triple)) { 239 return false; 240 } 241 Triple to = (Triple) o; 242 return to.getSubject().equals(getSubject()) && 243 to.getObject().equals(getObject()) && 244 to.getPredicate().equals(getPredicate()); 245 } 246 247 public int hashCode() { 248 return getSubject().hashCode() + 249 31 * getObject().hashCode() + 250 31 * 31 * getPredicate().hashCode(); 251 } 252 253 public String toString() { 254 if (getName().length() > 0) 255 return getName(); 256 return subject + " " + predicate + " " + object; 257 } 258 } 259}