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.biojavax.ontology; 023 024import java.util.Collections; 025import java.util.Set; 026import java.util.TreeSet; 027 028import org.biojava.bio.Annotation; 029import org.biojava.ontology.Ontology; 030import org.biojava.ontology.Term; 031import org.biojava.ontology.Triple; 032import org.biojava.utils.AbstractChangeable; 033import org.biojava.utils.ChangeEvent; 034import org.biojava.utils.ChangeSupport; 035import org.biojava.utils.ChangeVetoException; 036import org.biojavax.RichAnnotation; 037 038/** 039 * Basic comparable triple, BioSQL style. 040 * @author Richard Holland 041 * @since 1.5 042 */ 043public class SimpleComparableTriple extends AbstractChangeable implements ComparableTriple { 044 045 private ComparableOntology ontology; 046 private ComparableTerm object; 047 private ComparableTerm subject; 048 private ComparableTerm predicate; 049 private Set descriptors = new TreeSet(); 050 051 /** 052 * Creates a new instance of SimpleComparableTriple. All parameters are 053 * required and immutable. 054 * @param ontology the ontology of the triple. 055 * @param subject the subject of the triple. 056 * @param object the object of the triple. 057 * @param predicate the predicate of the triple. 058 */ 059 SimpleComparableTriple(ComparableOntology ontology, ComparableTerm subject, ComparableTerm object, ComparableTerm predicate) { 060 if (ontology == null) throw new IllegalArgumentException("Ontology must not be null"); 061 if (subject == null) throw new IllegalArgumentException("Subject must not be null"); 062 if (object == null) throw new IllegalArgumentException("Object must not be null"); 063 if (predicate == null) throw new IllegalArgumentException("Predicate must not be null"); 064 this.ontology = ontology; 065 this.subject = subject; 066 this.object = object; 067 this.predicate = predicate; 068 } 069 070 // Hibernate requirement - not for public use. 071 protected SimpleComparableTriple() {} 072 073 /** 074 * {@inheritDoc} 075 * Triples are sorted in order of ontology, subject, object, and finally 076 * predicate. 077 */ 078 public int compareTo(Object o) { 079 if (o==this) return 0; 080 Triple them = (Triple)o; 081 // Hibernate comparison - we haven't been populated yet 082 if (this.ontology==null) return -1; 083 // Normal comparison 084 if (!this.ontology.equals(them.getOntology())) return this.ontology.compareTo((ComparableOntology)them.getOntology()); 085 if (!this.subject.equals(them.getSubject())) return this.subject.compareTo((ComparableTerm)them.getSubject()); 086 if (!this.object.equals(them.getObject())) return this.object.compareTo((ComparableTerm)them.getObject()); 087 return this.predicate.compareTo((ComparableTerm)them.getPredicate()); 088 } 089 090 /** 091 * {@inheritDoc} 092 * Triples are equal only if they are from the same ontology and share the 093 * same subject, object and predicate. 094 */ 095 public boolean equals(Object o) { 096 if(this == o) return true; 097 if (o==null || !(o instanceof Triple)) return false; 098 // Hibernate comparison - we haven't been populated yet 099 if (this.ontology==null) return false; 100 // Normal comparison 101 Triple them = (Triple)o; 102 return (this.ontology.equals(them.getOntology()) && 103 this.subject.equals(them.getSubject()) && 104 this.object.equals(them.getObject()) && 105 this.predicate.equals(them.getPredicate())); 106 } 107 108 /** 109 * {@inheritDoc} 110 */ 111 public int hashCode() { 112 int code = 17; 113 // Hibernate comparison - we haven't been populated yet 114 if (this.ontology==null) return code; 115 // Normal comparison 116 code = 37*code + this.ontology.hashCode(); 117 code = 37*code + this.subject.hashCode(); 118 code = 37*code + this.object.hashCode(); 119 code = 37*code + this.predicate.hashCode(); 120 return code; 121 } 122 123 /** 124 * {@inheritDoc} 125 * Returns the output of toSring() 126 */ 127 public String getName() { return this.toString(); } 128 129 /** 130 * {@inheritDoc} 131 */ 132 public Term getSubject() { return this.subject; } 133 134 // Hibernate requirement - not for public use. 135 void setSubject(ComparableTerm subject) { this.subject = subject; } 136 137 /** 138 * {@inheritDoc} 139 */ 140 public Term getObject() { return this.object; } 141 142 // Hibernate requirement - not for public use. 143 void setObject(ComparableTerm object) { this.object = object; } 144 145 /** 146 * {@inheritDoc} 147 */ 148 public Term getPredicate() { return this.predicate; } 149 150 // Hibernate requirement - not for public use. 151 void setPredicate(ComparableTerm predicate) { this.predicate = predicate; } 152 153 /** 154 * {@inheritDoc} 155 */ 156 public void addDescriptor(ComparableTerm desc) throws IllegalArgumentException,ChangeVetoException { 157 if (desc==null) throw new IllegalArgumentException("Cannot have null descriptor"); 158 if(!this.hasListeners(ComparableTriple.DESCRIPTOR)) { 159 this.descriptors.add(desc); 160 } else { 161 ChangeEvent ce = new ChangeEvent( 162 this, 163 ComparableTriple.DESCRIPTOR, 164 desc, 165 null 166 ); 167 ChangeSupport cs = this.getChangeSupport(ComparableTriple.DESCRIPTOR); 168 synchronized(cs) { 169 cs.firePreChangeEvent(ce); 170 this.descriptors.add(desc); 171 cs.firePostChangeEvent(ce); 172 } 173 } 174 } 175 176 /** 177 * {@inheritDoc} 178 */ 179 public boolean removeDescriptor(ComparableTerm desc) throws IllegalArgumentException,ChangeVetoException { 180 if (desc==null) throw new IllegalArgumentException("Cannot have null descriptor"); 181 boolean result; 182 if(!this.hasListeners(ComparableTriple.DESCRIPTOR)) { 183 result = this.descriptors.remove(desc); 184 } else { 185 ChangeEvent ce = new ChangeEvent( 186 this, 187 ComparableTriple.DESCRIPTOR, 188 null, 189 desc 190 ); 191 ChangeSupport cs = this.getChangeSupport(ComparableTriple.DESCRIPTOR); 192 synchronized(cs) { 193 cs.firePreChangeEvent(ce); 194 result = this.descriptors.remove(desc); 195 cs.firePostChangeEvent(ce); 196 } 197 } 198 return result; 199 } 200 201 /** 202 * {@inheritDoc} 203 * <b>Warning</b> this method gives access to the original 204 * Collection not a copy. This is required by Hibernate. If you 205 * modify the object directly the behaviour may be unpredictable. 206 */ 207 public Set getDescriptors() { return this.descriptors; } // originals for Hibernate 208 209 /** 210 * {@inheritDoc} 211 * <b>Warning</b> this method gives access to the original 212 * Collection not a copy. This is required by Hibernate. If you 213 * modify the object directly the behaviour may be unpredictable. 214 */ 215 public void setDescriptors(Set descriptors) throws ChangeVetoException { 216 this.descriptors = descriptors; // originals for Hibernate 217 } 218 219 /** 220 * {@inheritDoc} 221 * NOT IMPLEMENTED 222 */ 223 public void removeSynonym(Object synonym) { 224 throw new UnsupportedOperationException("BioJavaX does not know about triple synonyms."); 225 } 226 227 /** 228 * {@inheritDoc} 229 * NOT IMPLEMENTED 230 */ 231 public void addSynonym(Object synonym) { 232 throw new UnsupportedOperationException("BioJavaX does not know about triple synonyms."); 233 } 234 235 /** 236 * {@inheritDoc} 237 * ALWAYS RETURNS AN EMPTY LIST 238 */ 239 public Object[] getSynonyms() { return Collections.EMPTY_LIST.toArray(); } 240 241 /** 242 * {@inheritDoc} 243 */ 244 public Ontology getOntology() { return this.ontology; } 245 246 // Hibernate requirement - not for public use. 247 void setOntology(ComparableOntology ontology) { this.ontology = ontology; } 248 249 /** 250 * {@inheritDoc} 251 * ALWAYS RETURNS THE EMPTY STRING 252 */ 253 public String getDescription() { return ""; } 254 255 /** 256 * {@inheritDoc} 257 * does not do anything 258 */ 259 public void setDescription(String desc) { } 260 261 /** 262 * {@inheritDoc} 263 * ALWAYS RETURNS THE EMPTY ANNOTATION 264 */ 265 public Annotation getAnnotation() { return RichAnnotation.EMPTY_ANNOTATION; } 266 267 /** 268 * {@inheritDoc} 269 * Form: "ontology:predicate(subject,object)" 270 */ 271 public String toString() { 272 return this.ontology+":"+this.predicate+"("+this.subject+","+this.object+")"; 273 } 274 275 // Hibernate requirement - not for public use. 276 private Integer id; 277 278 /** 279 * Gets the Hibernate ID. Should be used with caution. 280 * @return the Hibernate ID, if using Hibernate. 281 */ 282 public Integer getId() { return this.id; } 283 284 /** 285 * Sets the Hibernate ID. Should be used with caution. 286 * @param id the Hibernate ID, if using Hibernate. 287 */ 288 public void setId(Integer id) { this.id = id;} 289}