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.bio; 023import java.util.Set; 024import java.util.TreeSet; 025 026import org.biojava.bio.Annotation; 027import org.biojava.utils.AbstractChangeable; 028import org.biojava.utils.ChangeEvent; 029import org.biojava.utils.ChangeSupport; 030import org.biojava.utils.ChangeVetoException; 031import org.biojavax.Comment; 032import org.biojavax.Namespace; 033import org.biojavax.Note; 034import org.biojavax.RankedCrossRef; 035import org.biojavax.RankedDocRef; 036import org.biojavax.RichAnnotation; 037import org.biojavax.SimpleRichAnnotation; 038import org.biojavax.bio.taxa.NCBITaxon; 039 040/** 041 * Reference implementation of a BioEntry object which has no features or sequence. 042 * Equality is the combination of namespace, name, accession and version. 043 * @author Richard Holland 044 * @author Mark Schreiber 045 * @author George Waldon 046 * @since 1.5 047 */ 048public class SimpleBioEntry extends AbstractChangeable implements BioEntry { 049 050 private Set<Comment> comments = new TreeSet<Comment>(); 051 private Set<RankedCrossRef> rankedcrossrefs = new TreeSet<RankedCrossRef>(); 052 private Set<RankedDocRef> rankeddocrefs = new TreeSet<RankedDocRef>(); 053 private Set<BioEntryRelationship> relationships = new TreeSet<BioEntryRelationship>(); 054 private String description; 055 private String division; 056 private String identifier; 057 private String name; 058 private String accession; 059 private int version; 060 private NCBITaxon taxon; 061 private Namespace ns; 062 private RichAnnotation notes = new SimpleRichAnnotation(); 063 064 /** 065 * Creates a new bioentry representing the sequence in the given namespace 066 * with the given name, accession and version. These properties are all 067 * immutable and non-nullable. 068 * @param ns The namespace for this new bioentry (not null). 069 * @param name The name for this new bioentry (not null). 070 * @param accession The accession for this new bioentry (not null). 071 * @param version The version for this new bioentry. 072 */ 073 public SimpleBioEntry(Namespace ns, String name, String accession, int version) { 074 if (name==null) throw new IllegalArgumentException("Name cannot be null"); 075 if (accession==null) throw new IllegalArgumentException("Accession cannot be null"); 076 if (ns==null) throw new IllegalArgumentException("Namespace cannot be null"); 077 this.description = null; 078 this.division = null; 079 this.identifier = null; 080 this.name = name; 081 this.accession = accession; 082 this.version = version; 083 this.taxon = null; 084 this.ns = ns; 085 } 086 087 // Hibernate requirement - not for public use. 088 protected SimpleBioEntry() {} // protected so SimpleRichSequence can extend us 089 090 /** 091 * {@inheritDoc} 092 * <b>Warning</b> this method gives access to the original 093 * Collection not a copy. This is required by Hibernate. If you 094 * modify the object directly the behaviour may be unpredictable. 095 */ 096 public Set<RankedCrossRef> getRankedCrossRefs() { return this.rankedcrossrefs; } // original for Hibernate 097 098 /** 099 * {@inheritDoc} 100 */ 101 public void setTaxon(NCBITaxon taxon) throws ChangeVetoException { 102 if(!this.hasListeners(BioEntry.TAXON)) { 103 this.taxon = taxon; 104 } else { 105 ChangeEvent ce = new ChangeEvent( 106 this, 107 BioEntry.TAXON, 108 taxon, 109 this.taxon 110 ); 111 ChangeSupport cs = this.getChangeSupport(BioEntry.TAXON); 112 synchronized(cs) { 113 cs.firePreChangeEvent(ce); 114 this.taxon = taxon; 115 cs.firePostChangeEvent(ce); 116 } 117 } 118 } 119 120 /** 121 * {@inheritDoc} 122 */ 123 public Annotation getAnnotation() { return getRichAnnotation(); } 124 125 /** 126 * {@inheritDoc} 127 */ 128 public RichAnnotation getRichAnnotation() { return this.notes; } 129 130 /** 131 * {@inheritDoc} 132 * <b>Warning</b> this method gives access to the original 133 * Collection not a copy. This is required by Hibernate. If you 134 * modify the object directly the behaviour may be unpredictable. 135 */ 136 public Set<Note> getNoteSet() { return this.notes.getNoteSet(); } 137 138 /** 139 * {@inheritDoc} 140 * <b>Warning</b> this method gives access to the original 141 * Collection not a copy. This is required by Hibernate. If you 142 * modify the object directly the behaviour may be unpredictable. 143 */ 144 public void setNoteSet(Set<Note> notes) throws ChangeVetoException { this.notes.setNoteSet(notes); } 145 146 /** 147 * {@inheritDoc} 148 * <b>Warning</b> this method gives access to the original 149 * Collection not a copy. This is required by Hibernate. If you 150 * modify the object directly the behaviour may be unpredictable. 151 */ 152 public Set<Comment> getComments() { return this.comments; } // must be original for Hibernate 153 154 /** 155 * {@inheritDoc} 156 * <b>Warning</b> this method gives access to the original 157 * Collection not a copy. This is required by Hibernate. If you 158 * modify the object directly the behaviour may be unpredictable. 159 */ 160 public Set<RankedDocRef> getRankedDocRefs() { return this.rankeddocrefs; } // must be original for Hibernate 161 162 /** 163 * {@inheritDoc} 164 * <b>Warning</b> this method gives access to the original 165 * Collection not a copy. This is required by Hibernate. If you 166 * modify the object directly the behaviour may be unpredictable. 167 */ 168 public Set<BioEntryRelationship> getRelationships() { return this.relationships; } // must be original for Hibernate 169 170 /** 171 * {@inheritDoc} 172 */ 173 public void setIdentifier(String identifier) throws ChangeVetoException { 174 if(!this.hasListeners(BioEntry.IDENTIFIER)) { 175 this.identifier = identifier; 176 } else { 177 ChangeEvent ce = new ChangeEvent( 178 this, 179 BioEntry.IDENTIFIER, 180 identifier, 181 this.identifier 182 ); 183 ChangeSupport cs = this.getChangeSupport(BioEntry.IDENTIFIER); 184 synchronized(cs) { 185 cs.firePreChangeEvent(ce); 186 this.identifier = identifier; 187 cs.firePostChangeEvent(ce); 188 } 189 } 190 } 191 192 /** 193 * {@inheritDoc} 194 */ 195 public void setDivision(String division) throws ChangeVetoException { 196 if(!this.hasListeners(BioEntry.DIVISION)) { 197 this.division = division; 198 } else { 199 ChangeEvent ce = new ChangeEvent( 200 this, 201 BioEntry.DIVISION, 202 division, 203 this.division 204 ); 205 ChangeSupport cs = this.getChangeSupport(BioEntry.DIVISION); 206 synchronized(cs) { 207 cs.firePreChangeEvent(ce); 208 this.division = division; 209 cs.firePostChangeEvent(ce); 210 } 211 } 212 } 213 214 /** 215 * {@inheritDoc} 216 */ 217 public void setDescription(String description) throws ChangeVetoException { 218 if(!this.hasListeners(BioEntry.DESCRIPTION)) { 219 this.description = description; 220 } else { 221 ChangeEvent ce = new ChangeEvent( 222 this, 223 BioEntry.DESCRIPTION, 224 description, 225 this.description 226 ); 227 ChangeSupport cs = this.getChangeSupport(BioEntry.DESCRIPTION); 228 synchronized(cs) { 229 cs.firePreChangeEvent(ce); 230 this.description = description; 231 cs.firePostChangeEvent(ce); 232 } 233 } 234 } 235 236 /** 237 * {@inheritDoc} 238 */ 239 public String getAccession() { return this.accession; } 240 241 /** 242 * {@inheritDoc} 243 */ 244 public String getDescription() { return this.description; } 245 246 /** 247 * {@inheritDoc} 248 */ 249 public String getDivision() { return this.division; } 250 251 /** 252 * {@inheritDoc} 253 */ 254 public String getIdentifier() { return this.identifier; } 255 256 /** 257 * {@inheritDoc} 258 */ 259 public String getName() { return this.name; } 260 261 /** 262 * {@inheritDoc} 263 */ 264 public Namespace getNamespace() { return this.ns; } 265 266 /** 267 * {@inheritDoc} 268 */ 269 public NCBITaxon getTaxon() { return this.taxon; } 270 271 /** 272 * {@inheritDoc} 273 */ 274 public int getVersion() { return this.version; } 275 276 /** 277 * {@inheritDoc} 278 * Two bioentries are equal if they share the same namespace, name, 279 * accession and version. 280 */ 281 public boolean equals(Object obj) { 282 if (this == obj) return true; 283 if (obj==null || !(obj instanceof BioEntry)) return false; 284 // Hibernate comparison - we haven't been populated yet 285 if (this.ns==null) return false; 286 // Normal comparison 287 BioEntry them = (BioEntry)obj; 288 return (this.ns.equals(them.getNamespace()) && 289 this.name.equals(them.getName()) && 290 this.accession.equals(them.getAccession()) && 291 this.version==them.getVersion()); 292 } 293 294 /** 295 * {@inheritDoc} 296 * Bioentries are ordered first by namespace, then name, accession, and 297 * finally version. 298 */ 299 public int compareTo(Object o) { 300 if (o==this) return 0; 301 // Hibernate comparison - we haven't been populated yet 302 if (this.ns==null) return -1; 303 // Normal comparison 304 BioEntry them = (BioEntry)o; 305 if (!this.ns.equals(them.getNamespace())) return this.ns.compareTo(them.getNamespace()); 306 if (!this.name.equals(them.getName())) return this.name.compareTo(them.getName()); 307 if (!this.accession.equals(them.getAccession())) return this.accession.compareTo(them.getAccession()); 308 return this.version-them.getVersion(); 309 } 310 311 /** 312 * {@inheritDoc} 313 */ 314 public int hashCode() { 315 int code = 17; 316 // Hibernate comparison - we haven't been populated yet 317 if (this.ns==null) return code; 318 // Normal comparison 319 code = 37*code + this.ns.hashCode(); 320 code = 37*code + this.name.hashCode(); 321 code = 37*code + this.accession.hashCode(); 322 code = 37*code + this.version; 323 return code; 324 } 325 326 /** 327 * {@inheritDoc} 328 * Form: namespace:name/accession.version 329 */ 330 public String toString() { 331 return this.getNamespace()+":"+this.getName()+"/"+this.getAccession()+"."+this.getVersion(); 332 } 333 334 /** 335 * {@inheritDoc} 336 */ 337 public void addRankedCrossRef(RankedCrossRef crossref) throws ChangeVetoException { 338 if (crossref==null) throw new IllegalArgumentException("Crossref cannot be null"); 339 if(!this.hasListeners(BioEntry.RANKEDCROSSREF)) { 340 this.rankedcrossrefs.add(crossref); 341 } else { 342 ChangeEvent ce = new ChangeEvent( 343 this, 344 BioEntry.RANKEDCROSSREF, 345 crossref, 346 null 347 ); 348 ChangeSupport cs = this.getChangeSupport(BioEntry.RANKEDCROSSREF); 349 synchronized(cs) { 350 cs.firePreChangeEvent(ce); 351 this.rankedcrossrefs.add(crossref); 352 cs.firePostChangeEvent(ce); 353 } 354 } 355 } 356 357 /** 358 * {@inheritDoc} 359 */ 360 public void removeRankedCrossRef(RankedCrossRef crossref) throws ChangeVetoException { 361 if (crossref==null) throw new IllegalArgumentException("Crossref cannot be null"); 362 if(!this.hasListeners(BioEntry.RANKEDCROSSREF)) { 363 this.rankedcrossrefs.remove(crossref); 364 } else { 365 ChangeEvent ce = new ChangeEvent( 366 this, 367 BioEntry.RANKEDCROSSREF, 368 null, 369 crossref 370 ); 371 ChangeSupport cs = this.getChangeSupport(BioEntry.RANKEDCROSSREF); 372 synchronized(cs) { 373 cs.firePreChangeEvent(ce); 374 this.rankedcrossrefs.remove(crossref); 375 cs.firePostChangeEvent(ce); 376 } 377 } 378 } 379 380 /** 381 * {@inheritDoc} 382 */ 383 public void addRankedDocRef(RankedDocRef docref) throws ChangeVetoException { 384 if (docref==null) throw new IllegalArgumentException("Docref cannot be null"); 385 if(!this.hasListeners(BioEntry.RANKEDDOCREF)) { 386 this.rankeddocrefs.add(docref); 387 } else { 388 ChangeEvent ce = new ChangeEvent( 389 this, 390 BioEntry.RANKEDDOCREF, 391 docref, 392 null 393 ); 394 ChangeSupport cs = this.getChangeSupport(BioEntry.RANKEDDOCREF); 395 synchronized(cs) { 396 cs.firePreChangeEvent(ce); 397 this.rankeddocrefs.add(docref); 398 cs.firePostChangeEvent(ce); 399 } 400 } 401 } 402 403 /** 404 * {@inheritDoc} 405 */ 406 public void removeRankedDocRef(RankedDocRef docref) throws ChangeVetoException { 407 if (docref==null) throw new IllegalArgumentException("Docref cannot be null"); 408 if(!this.hasListeners(BioEntry.RANKEDDOCREF)) { 409 this.rankeddocrefs.remove(docref); 410 } else { 411 ChangeEvent ce = new ChangeEvent( 412 this, 413 BioEntry.RANKEDDOCREF, 414 null, 415 docref 416 ); 417 ChangeSupport cs = this.getChangeSupport(BioEntry.RANKEDDOCREF); 418 synchronized(cs) { 419 cs.firePreChangeEvent(ce); 420 this.rankeddocrefs.remove(docref); 421 cs.firePostChangeEvent(ce); 422 } 423 } 424 } 425 426 /** 427 * {@inheritDoc} 428 */ 429 public void addComment(Comment comment) throws ChangeVetoException { 430 if (comment==null) throw new IllegalArgumentException("Comment cannot be null"); 431 if(!this.hasListeners(BioEntry.COMMENT)) { 432 this.comments.add(comment); 433 } else { 434 ChangeEvent ce = new ChangeEvent( 435 this, 436 BioEntry.COMMENT, 437 comment, 438 null 439 ); 440 ChangeSupport cs = this.getChangeSupport(BioEntry.COMMENT); 441 synchronized(cs) { 442 cs.firePreChangeEvent(ce); 443 this.comments.add(comment); 444 cs.firePostChangeEvent(ce); 445 } 446 } 447 } 448 449 /** 450 * {@inheritDoc} 451 */ 452 public void removeComment(Comment comment) throws ChangeVetoException { 453 if (comment==null) throw new IllegalArgumentException("Comment cannot be null"); 454 if(!this.hasListeners(BioEntry.COMMENT)) { 455 this.comments.remove(comment); 456 } else { 457 ChangeEvent ce = new ChangeEvent( 458 this, 459 BioEntry.COMMENT, 460 null, 461 comment 462 ); 463 ChangeSupport cs = this.getChangeSupport(BioEntry.COMMENT); 464 synchronized(cs) { 465 cs.firePreChangeEvent(ce); 466 this.comments.remove(comment); 467 cs.firePostChangeEvent(ce); 468 } 469 } 470 } 471 472 /** 473 * {@inheritDoc} 474 */ 475 public void addRelationship(BioEntryRelationship relation) throws ChangeVetoException { 476 if (relation==null) throw new IllegalArgumentException("Relationship cannot be null"); 477 if(!this.hasListeners(BioEntry.RELATIONS)) { 478 this.relationships.add(relation); 479 } else { 480 ChangeEvent ce = new ChangeEvent( 481 this, 482 BioEntry.RELATIONS, 483 relation, 484 null 485 ); 486 ChangeSupport cs = this.getChangeSupport(BioEntry.RELATIONS); 487 synchronized(cs) { 488 cs.firePreChangeEvent(ce); 489 this.relationships.add(relation); 490 cs.firePostChangeEvent(ce); 491 } 492 } 493 } 494 495 /** 496 * {@inheritDoc} 497 */ 498 public void removeRelationship(BioEntryRelationship relation) throws ChangeVetoException { 499 if (relation==null) throw new IllegalArgumentException("Relationship cannot be null"); 500 if(!this.hasListeners(BioEntry.RELATIONS)) { 501 this.relationships.remove(relation); 502 } else { 503 ChangeEvent ce = new ChangeEvent( 504 this, 505 BioEntry.RELATIONS, 506 null, 507 relation 508 ); 509 ChangeSupport cs = this.getChangeSupport(BioEntry.RELATIONS); 510 synchronized(cs) { 511 cs.firePreChangeEvent(ce); 512 this.relationships.remove(relation); 513 cs.firePostChangeEvent(ce); 514 } 515 } 516 } 517 518 // Hibernate requirement - not for public use. 519 void setRelationships(Set<BioEntryRelationship> relationships) { this.relationships = relationships; } // must be original for Hibernate 520 521 // Hibernate requirement - not for public use. 522 void setNamespace(Namespace ns) { this.ns = ns; } 523 524 // Hibernate requirement - not for public use. 525 void setName(String name) { this.name = name; } 526 527 // Hibernate requirement - not for public use. 528 void setAccession(String acc) { this.accession = acc; } 529 530 // Hibernate requirement - not for public use. 531 void setVersion(int v) { this.version = v; } 532 533 // Hibernate requirement - not for public use. 534 void setRankedDocRefs(Set<RankedDocRef> docrefs) { this.rankeddocrefs = docrefs; } // must be original for Hibernate 535 536 // Hibernate requirement - not for public use. 537 void setComments(Set<Comment> comments) { this.comments = comments; } // must be original for Hibernate 538 539 // Hibernate requirement - not for public use. 540 public void setRankedCrossRefs(Set<RankedCrossRef> rankedcrossrefs) { this.rankedcrossrefs = rankedcrossrefs; } // original for Hibernate 541 542 // Hibernate requirement - not for public use. 543 private Integer id; 544 545 /** 546 * Gets the Hibernate ID. Should be used with caution. 547 * @return the Hibernate ID, if using Hibernate. 548 */ 549 public Integer getId() { return this.id; } 550 551 /** 552 * Sets the Hibernate ID. Should be used with caution. 553 * @param id the Hibernate ID, if using Hibernate. 554 */ 555 public void setId(Integer id) { this.id = id;} 556 557} 558