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.bio.search; 023 024import java.util.Collections; 025import java.util.List; 026import java.util.Map; 027 028import org.biojava.bio.Annotatable; 029import org.biojava.bio.Annotation; 030import org.biojava.bio.seq.Sequence; 031import org.biojava.bio.seq.db.SequenceDB; 032import org.biojava.utils.AbstractChangeable; 033import org.biojava.utils.ChangeForwarder; 034import org.biojava.utils.ChangeListener; 035import org.biojava.utils.ChangeSupport; 036import org.biojava.utils.ChangeType; 037import org.biojava.utils.ObjectUtil; 038 039/** 040 * <code>SequenceDBSearchResult</code> objects represent a result of a 041 * search of a <code>SymbolList</code> against the sequences within a 042 * <code>SequenceDB</code> object. The core data (query sequence, 043 * database, search parameters, hits) have accessors, while 044 * supplementary data are stored in the <code>Annotation</code> 045 * object. Supplementary data are typically the more loosely formatted 046 * details which vary from one search program to another (and between 047 * versions of those programs). 048 * 049 * @author Keith James 050 * @author Matthew Pocock 051 * @since 1.1 052 * @deprecated SimpleSeqSimilaritySearchResult has been made 053 * Annotatable and is now functionally identical. 054 * @see AbstractChangeable 055 * @see SeqSimilaritySearchResult 056 * @see Annotatable 057 */ 058public class SequenceDBSearchResult extends AbstractChangeable 059 implements SeqSimilaritySearchResult, Annotatable 060{ 061 protected transient ChangeForwarder annotationForwarder; 062 063 private Sequence querySequence; 064 private SequenceDB sequenceDB; 065 private Map searchParameters; 066 private Annotation annotation; 067 private List hits; 068 069 // Hashcode is cached after first calculation because the data on 070 // which is is based do not change 071 private int hc; 072 private boolean hcCalc; 073 074 /** 075 * Creates a new <code>SequenceDBSearchResult</code>. 076 * 077 * @param querySequence a <code>Sequence</code>. 078 * @param sequenceDB a <code>SequenceDB</code>. 079 * @param searchParameters a <code>Map</code>. 080 * @param annotation an <code>Annotation</code>. 081 * @param hits a <code>List</code>. 082 */ 083 public SequenceDBSearchResult(Sequence querySequence, 084 SequenceDB sequenceDB, 085 Map searchParameters, 086 List hits, 087 Annotation annotation) 088 { 089 if (querySequence == null) 090 { 091 throw new IllegalArgumentException("querySequence was null"); 092 } 093 094 if (sequenceDB == null) 095 { 096 throw new IllegalArgumentException("sequenceDB was null"); 097 } 098 099 if (searchParameters != null) 100 { 101 this.searchParameters = 102 Collections.unmodifiableMap(searchParameters); 103 } 104 105 if (annotation == null) 106 { 107 throw new IllegalArgumentException("annotation was null"); 108 } 109 110 if (hits == null) 111 { 112 throw new IllegalArgumentException("hits was null"); 113 } 114 115 // Lock the sequenceDB by vetoing all changes 116 sequenceDB.addChangeListener(ChangeListener.ALWAYS_VETO); 117 118 // Lock the querySeq by vetoing all changes 119 querySequence.addChangeListener(ChangeListener.ALWAYS_VETO); 120 121 // Lock the annotation by vetoing all changes to properties 122 annotation.addChangeListener(ChangeListener.ALWAYS_VETO); 123 124 this.querySequence = querySequence; 125 this.sequenceDB = sequenceDB; 126 this.annotation = annotation; 127 this.hits = Collections.unmodifiableList(hits); 128 129 hcCalc = false; 130 } 131 132 public Sequence getQuerySequence() 133 { 134 return querySequence; 135 } 136 137 public SequenceDB getSequenceDB() 138 { 139 return sequenceDB; 140 } 141 142 public Map getSearchParameters() 143 { 144 return searchParameters; 145 } 146 147 public List getHits() 148 { 149 return hits; 150 } 151 152 /** 153 * <code>getAnnotation</code> returns the Annotation associated 154 * with this hit. 155 * 156 * @return an <code>Annotation</code>. 157 */ 158 public Annotation getAnnotation() 159 { 160 return annotation; 161 } 162 163 public boolean equals(Object other) 164 { 165 if (other == this) return true; 166 if (other == null) return false; 167 168 if (! other.getClass().equals(this.getClass())) return false; 169 170 SequenceDBSearchResult that = (SequenceDBSearchResult) other; 171 172 if (! ObjectUtil.equals(this.querySequence, that.querySequence)) 173 return false; 174 if (! ObjectUtil.equals(this.sequenceDB, that.sequenceDB)) 175 return false; 176 if (! ObjectUtil.equals(this.searchParameters, that.searchParameters)) 177 return false; 178 if (! ObjectUtil.equals(this.annotation, that.annotation)) 179 return false; 180 if (! ObjectUtil.equals(this.hits, that.hits)) 181 return false; 182 183 return true; 184 } 185 186 public int hashCode() 187 { 188 if (! hcCalc) 189 { 190 hc = ObjectUtil.hashCode(hc, querySequence); 191 hc = ObjectUtil.hashCode(hc, sequenceDB); 192 hc = ObjectUtil.hashCode(hc, searchParameters); 193 hc = ObjectUtil.hashCode(hc, hits); 194 hc = ObjectUtil.hashCode(hc, annotation); 195 hcCalc = true; 196 } 197 198 return hc; 199 } 200 201 public String toString() 202 { 203 return "SequenceDBSearchResult of " + getQuerySequence() 204 + " against " + getSequenceDB().getName(); 205 } 206 207 protected ChangeSupport getChangeSupport(ChangeType ct) 208 { 209 ChangeSupport cs = super.getChangeSupport(ct); 210 211 if (annotationForwarder == null && 212 (ct.isMatchingType(Annotatable.ANNOTATION) || Annotatable.ANNOTATION.isMatchingType(ct))) 213 { 214 annotationForwarder = 215 new ChangeForwarder.Retyper(this, cs, Annotation.PROPERTY); 216 getAnnotation().addChangeListener(annotationForwarder, 217 Annotatable.ANNOTATION); 218 } 219 220 return cs; 221 } 222}