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.seq; 023 024import org.biojava.utils.AbstractChangeable; 025import org.biojava.utils.ChangeEvent; 026import org.biojava.utils.ChangeSupport; 027import org.biojava.utils.ChangeVetoException; 028import org.biojavax.RichObjectFactory; 029import org.biojavax.ontology.ComparableTerm; 030 031/** 032 * Represents a relationship between two features that is described by a term. 033 * @author Richard Holland 034 * @author Mark Schreiber 035 * @since 1.5 036 * 037 */ 038public class SimpleRichFeatureRelationship extends AbstractChangeable implements RichFeatureRelationship { 039 040 private RichFeature object; 041 private RichFeature subject; 042 private ComparableTerm term; 043 private int rank; 044 045 /** 046 * Gets the default CONTAINS term used for defining the relationship between features. 047 * @return the default CONTAINS term. 048 */ 049 public static ComparableTerm getContainsTerm() { 050 return RichObjectFactory.getDefaultOntology().getOrCreateTerm("contains"); 051 } 052 053 /** 054 * Creates a new instance of SimpleRichFeatureRelationship. 055 * @param subject The subject RichFeature. 056 * @param term The relationship term. 057 * @param rank the rank of the relationship. 058 */ 059 public SimpleRichFeatureRelationship(RichFeature object, RichFeature subject, ComparableTerm term, int rank) { 060 if (object==null) throw new IllegalArgumentException("Object cannot be null"); 061 if (subject==null) throw new IllegalArgumentException("Subject cannot be null"); 062 if (term==null) throw new IllegalArgumentException("Term cannot be null"); 063 this.object = object; 064 this.subject = subject; 065 this.term = term; 066 this.rank = rank; 067 } 068 069 // Hibernate requirement - not for public use. 070 protected SimpleRichFeatureRelationship() {} 071 072 /** 073 * {@inheritDoc} 074 */ 075 public void setRank(int rank) throws ChangeVetoException { 076 if(!this.hasListeners(RichFeatureRelationship.RANK)) { 077 this.rank = rank; 078 } else { 079 ChangeEvent ce = new ChangeEvent( 080 this, 081 RichFeatureRelationship.RANK, 082 new Integer(rank), 083 new Integer(this.rank) 084 ); 085 ChangeSupport cs = this.getChangeSupport(RichFeatureRelationship.RANK); 086 synchronized(cs) { 087 cs.firePreChangeEvent(ce); 088 this.rank = rank; 089 cs.firePostChangeEvent(ce); 090 } 091 } 092 } 093 094 /** 095 * {@inheritDoc} 096 */ 097 public int getRank() { return this.rank; } 098 099 /** 100 * {@inheritDoc} 101 */ 102 public RichFeature getObject() { return this.object; } 103 104 // Hibernate requirement - not for public use. 105 void setObject(RichFeature object) { this.object = object; } 106 107 /** 108 * {@inheritDoc} 109 */ 110 public RichFeature getSubject() { return this.subject; } 111 112 // Hibernate requirement - not for public use. 113 void setSubject(RichFeature subject) { this.subject = subject; } 114 115 /** 116 * {@inheritDoc} 117 */ 118 public ComparableTerm getTerm() { return this.term; } 119 120 // Hibernate requirement - not for public use. 121 void setTerm(ComparableTerm term) { this.term = term; } 122 123 /** 124 * {@inheritDoc} 125 * Relations are compared first by rank, then object, subject, then finally term. 126 */ 127 public int compareTo(Object o) { 128 if (o==this) return 0; 129 // Hibernate comparison - we haven't been populated yet 130 if (this.object==null) return -1; 131 // Normal comparison 132 RichFeatureRelationship them = (RichFeatureRelationship)o; 133 if (this.rank!=them.getRank()) return this.rank-them.getRank(); 134 if (!this.object.equals(them.getObject())) return this.object.compareTo(them.getObject()); 135 if (!this.subject.equals(them.getSubject())) return this.subject.compareTo(them.getSubject()); 136 else return this.getTerm().compareTo(them.getTerm()); 137 } 138 139 /** 140 * {@inheritDoc} 141 * Relations are equal if their objects, subjects and terms are equal. 142 */ 143 public boolean equals(Object obj) { 144 if (this == obj) return true; 145 if (obj==null || !(obj instanceof RichFeatureRelationship)) return false; 146 // Hibernate comparison - we haven't been populated yet 147 if (this.object==null) return false; 148 // Normal comparison 149 RichFeatureRelationship them = (RichFeatureRelationship)obj; 150 return (this.object.equals(them.getObject()) && 151 this.subject.equals(them.getSubject()) && 152 this.term.equals(them.getTerm())); 153 } 154 155 /** 156 * {@inheritDoc} 157 */ 158 public int hashCode() { 159 int code = 17; 160 // Hibernate comparison - we haven't been populated yet 161 if (this.subject==null) return code; 162 // Normal comparison 163 code = code*37 + this.object.hashCode(); 164 code = code*37 + this.subject.hashCode(); 165 code = code*37 + this.term.hashCode(); 166 return code; 167 } 168 169 /** 170 * {@inheritDoc} 171 * Form: "(#rank) term(object,subject)" 172 */ 173 public String toString() { 174 return "(#"+this.rank+") "+this.getTerm()+"("+this.getObject()+","+this.getSubject()+")"; 175 } 176 177 // Hibernate requirement - not for public use. 178 private Integer id; 179 180 /** 181 * Gets the Hibernate ID. Should be used with caution. 182 * @return the Hibernate ID, if using Hibernate. 183 */ 184 public Integer getId() { return this.id; } 185 186 /** 187 * Sets the Hibernate ID. Should be used with caution. 188 * @param id the Hibernate ID, if using Hibernate. 189 */ 190 public void setId(Integer id) { this.id = id;} 191} 192