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; 023 024 025import org.biojava.bio.seq.io.ParseException; 026import org.biojava.utils.AbstractChangeable; 027import org.biojava.utils.ChangeEvent; 028import org.biojava.utils.ChangeSupport; 029import org.biojava.utils.ChangeVetoException; 030import org.biojavax.bio.seq.RichLocation; 031import org.biojavax.bio.seq.SimplePosition; 032import org.biojavax.bio.seq.SimpleRichLocation; 033import org.biojavax.bio.seq.io.GenbankLocationParser; 034 035/** 036 * Represents a documentary reference. 037 * @author Richard Holland 038 * @author gwaldon 039 * @since 1.5 040 */ 041public class SimpleRankedDocRef extends AbstractChangeable implements RankedDocRef { 042 043 private DocRef docref; 044 private Integer start; 045 private Integer end; 046 private RichLocation location; 047 private int rank; 048 049 /** 050 * Constructs a new docref for a given location. If one or the other 051 * of start and end are null, only the non-null value is used. If both 052 * are null, no value is used for the location. 053 * @param docref the document reference. Must not be null. 054 * @param start the start position of the location. 055 * @param end the end position of the location. 056 */ 057 public SimpleRankedDocRef(DocRef docref, Integer start, Integer end, int rank) { 058 if (docref==null) throw new IllegalArgumentException("Document reference cannot be null"); 059 this.docref = docref; 060 this.setStart(start); 061 this.setEnd(end); 062 this.rank = rank; 063 } 064 065 /** 066 * Constructs a new docref for a given location. 067 * @param docref the document reference. Must not be null. 068 * @param location the position of the document reference. Must not be null. 069 */ 070 public SimpleRankedDocRef(DocRef docref, RichLocation location, int rank) { 071 if (docref==null) throw new IllegalArgumentException("Document reference cannot be null"); 072 this.docref = docref; 073 this.makeLocation(location); 074 this.rank = rank; 075 } 076 077 // Hibernate requirement - not for public use. 078 protected SimpleRankedDocRef() {} 079 080 /** 081 * {@inheritDoc} 082 */ 083 public void setRank(int rank) throws ChangeVetoException { 084 if(rank==this.rank) 085 return; 086 if(!this.hasListeners(RankedDocRef.RANK)) { 087 this.rank = rank; 088 } else { 089 ChangeEvent ce = new ChangeEvent( 090 this, 091 RankedDocRef.RANK, 092 new Integer(rank), 093 new Integer(this.rank) 094 ); 095 ChangeSupport cs = this.getChangeSupport(RankedDocRef.RANK); 096 synchronized(cs) { 097 cs.firePreChangeEvent(ce); 098 this.rank = rank; 099 cs.firePostChangeEvent(ce); 100 } 101 } 102 } 103 104 /** 105 * {@inheritDoc} 106 */ 107 public int getRank() { return this.rank; } 108 109 /** 110 * {@inheritDoc} 111 */ 112 public DocRef getDocumentReference() { return this.docref; } 113 114 /** 115 * {@inheritDoc} 116 */ 117 public Integer getStart() { return this.start; } 118 119 /** 120 * {@inheritDoc} 121 */ 122 public Integer getEnd() { return this.end; } 123 124 // Hibernate requirement - not for public use. 125 void setDocumentReference(DocRef docref) { this.docref = docref; } 126 127 // Hibernate requirement - not for public use. 128 private void setStart(Integer start) { 129 this.start = start; 130 this.createLocation(); 131 } 132 133 // Hibernate requirement - not for public use. 134 private void setEnd(Integer end) { 135 this.end = end; 136 this.createLocation(); 137 } 138 139 // Internal use only. 140 private void createLocation() { 141 if (this.start==null && this.end==null) location = RichLocation.EMPTY_LOCATION; 142 else if (this.start==null) location = new SimpleRichLocation(null, new SimplePosition(this.end.intValue()), 0); 143 else if (this.end==null) location = new SimpleRichLocation(new SimplePosition(this.start.intValue()), null, 0); 144 else location = new SimpleRichLocation(new SimplePosition(this.start.intValue()), new SimplePosition(this.end.intValue()), 0); 145 } 146 147 // Internal use only. 148 private void makeLocation(RichLocation location) { 149 if (location==null) 150 throw new IllegalArgumentException("Document location cannot be null"); 151 this.location = location; 152 this.start = new Integer(location.getMin()); 153 this.end = new Integer(location.getMax()); 154 } 155 156 /** 157 * {@inheritDoc} 158 */ 159 public void setLocation(RichLocation location) throws ChangeVetoException { 160 if(!this.hasListeners(RankedDocRef.LOCATION)) { 161 makeLocation(location); 162 } else { 163 ChangeEvent ce = new ChangeEvent( 164 this, 165 RankedDocRef.LOCATION, 166 location, 167 this.location 168 ); 169 ChangeSupport cs = this.getChangeSupport(RankedDocRef.LOCATION); 170 synchronized(cs) { 171 cs.firePreChangeEvent(ce); 172 makeLocation(location); 173 cs.firePostChangeEvent(ce); 174 } 175 } 176 } 177 178 public RichLocation getLocation() { 179 return this.location; 180 } 181 182 // Internal use only. 183 final void setLocationText(final String theLocation) throws ParseException { 184 if (theLocation == null) { 185 makeLocation(RichLocation.EMPTY_LOCATION); 186 } else { 187 final RichLocation location = GenbankLocationParser.parseLocation(RichObjectFactory.getDefaultNamespace(), null, theLocation); 188 makeLocation(location); 189 } 190 } 191 192 // Internal use only. 193 final String getLocationText() { 194 return getLocation() == RichLocation.EMPTY_LOCATION?null:GenbankLocationParser.writeLocation(getLocation()); 195 } 196 197 /** 198 * {@inheritDoc} 199 * Two ranked document references are equal if they have the same rank 200 * and refer to the same location and same document reference. 201 */ 202 public boolean equals(Object obj) { 203 if (this == obj) return true; 204 if (obj==null || !(obj instanceof RankedDocRef)) return false; 205 // Hibernate comparison - we haven't been populated yet 206 if (this.docref==null) return false; 207 // Normal comparison 208 RankedDocRef them = (RankedDocRef)obj; 209 return (this.rank==them.getRank() && 210 this.location.equals(them.getLocation()) && 211 this.docref.equals(them.getDocumentReference())); 212 } 213 214 /** 215 * {@inheritDoc} 216 * Ranked document references are sorted first by rank then location 217 * then by actual document reference. 218 */ 219 public int compareTo(Object o) { 220 if (o==this) return 0; 221 // Hibernate comparison - we haven't been populated yet 222 if (this.docref==null) return -1; 223 // Normal comparison 224 RankedDocRef them = (RankedDocRef)o; 225 if (this.rank!=them.getRank()) return this.rank - them.getRank(); 226 if (!this.location.equals(them.getLocation())) return this.location.compareTo(them.getLocation()); 227 return this.docref.compareTo(them.getDocumentReference()); 228 } 229 230 /** 231 * {@inheritDoc} 232 */ 233 public int hashCode() { 234 int code = 17; 235 // Hibernate comparison - we haven't been populated yet 236 if (this.docref==null) return code; 237 // Normal comparison 238 code = 37*code + this.docref.hashCode(); 239 code = 37*code + this.location.hashCode(); 240 code = 37*code + this.rank; 241 return code; 242 } 243 244 /** 245 * {@inheritDoc} 246 * Form: "(#rank) docref" 247 */ 248 public String toString() { 249 return "(#"+this.rank+") "+this.docref; 250 } 251} 252 253 254