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>SimpleSeqSimilaritySearchResult</code> objects represent a 041 * result of a search of a <code>SymbolList</code> against the 042 * sequences within a <code>SequenceDB</code> object. The core data 043 * (query sequence, database, search parameters, hits) have accessors, 044 * while 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 Gerald Loeffler 051 * @since 1.1 052 * 053 * @see AbstractChangeable 054 * @see SeqSimilaritySearchResult 055 * @see Annotatable 056 */ 057public class SimpleSeqSimilaritySearchResult extends AbstractChangeable 058 implements SeqSimilaritySearchResult 059{ 060 protected transient ChangeForwarder annotationForwarder; 061 062 private Sequence querySequence; 063 private SequenceDB sequenceDB; 064 private Map searchParameters; 065 private Annotation annotation; 066 private List hits; 067 068 // Hashcode is cached after first calculation because the data on 069 // which is is based do not change 070 private int hc; 071 private boolean hcCalc; 072 073 /** 074 * Creates a new <code>SimpleSeqSimilaritySearchResult</code>. 075 * 076 * @param querySequence a <code>Sequence</code>. 077 * @param sequenceDB a <code>SequenceDB</code>. 078 * @param searchParameters a <code>Map</code>. 079 * @param annotation an <code>Annotation</code>. 080 * @param hits a <code>List</code>. 081 */ 082 public SimpleSeqSimilaritySearchResult(Sequence querySequence, 083 SequenceDB sequenceDB, 084 Map searchParameters, 085 List hits, 086 Annotation annotation) 087 { 088 if (querySequence == null) 089 { 090 throw new IllegalArgumentException("querySequence was null"); 091 } 092 093 if (sequenceDB == null) 094 { 095 throw new IllegalArgumentException("sequenceDB was null"); 096 } 097 098 if (searchParameters != null) 099 { 100 this.searchParameters = 101 Collections.unmodifiableMap(searchParameters); 102 } 103 104 if (annotation == null) 105 { 106 throw new IllegalArgumentException("annotation was null"); 107 } 108 109 if (hits == null) 110 { 111 throw new IllegalArgumentException("hits was null"); 112 } 113 114 // Lock the sequenceDB by vetoing all changes 115 sequenceDB.addChangeListener(ChangeListener.ALWAYS_VETO); 116 117 // Lock the querySeq by vetoing all changes 118 querySequence.addChangeListener(ChangeListener.ALWAYS_VETO); 119 120 // Lock the annotation by vetoing all changes to properties 121 annotation.addChangeListener(ChangeListener.ALWAYS_VETO); 122 123 this.querySequence = querySequence; 124 this.sequenceDB = sequenceDB; 125 this.annotation = annotation; 126 this.hits = Collections.unmodifiableList(hits); 127 128 hcCalc = false; 129 } 130 131 public Sequence getQuerySequence() 132 { 133 return querySequence; 134 } 135 136 public SequenceDB getSequenceDB() 137 { 138 return sequenceDB; 139 } 140 141 public Map getSearchParameters() 142 { 143 return searchParameters; 144 } 145 146 public List getHits() 147 { 148 return hits; 149 } 150 151 /** 152 * <code>getAnnotation</code> returns the Annotation associated 153 * with this hit. 154 * 155 * @return an <code>Annotation</code>. 156 */ 157 public Annotation getAnnotation() 158 { 159 return annotation; 160 } 161 162 public boolean equals(Object other) 163 { 164 if (other == this) return true; 165 if (other == null) return false; 166 167 if (! other.getClass().equals(this.getClass())) return false; 168 169 SimpleSeqSimilaritySearchResult that = 170 (SimpleSeqSimilaritySearchResult) 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 "SimpleSeqSimilaritySearchResult 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}