001package org.biojava.bio.program.ssaha; 002 003import java.io.PrintStream; 004 005/** 006 * The interface used to inform interested parties that some sequence has 007 * been searched and something found. 008 * <p> 009 * The callbacks will always be called in the order startSearch, hit, 010 * endSearch, during which time there may be multiple hit calls. The seqID 011 * of startSearch and endSearch will match. After this, a new startSearch 012 * may begin. These events will usually originate from the search method of 013 * DataStore. 014 * 015 * @author Matthew Pocock 016 */ 017public interface SearchListener { 018 /** 019 * Indicates that a sequence is about to be searched against a DataStore. 020 * 021 * @param seqID the id of the sequence to be searched 022 */ 023 public void startSearch(String seqID); 024 025 /** 026 * Indicates that a sequence has been searched against a DataStore. 027 * 028 * @param seqID the id of the sequence to be searched 029 */ 030 public void endSearch(String seqID); 031 032 /** 033 * There has been a hit between the query sequence and a database 034 * sequence. 035 * 036 * @param hitID the number of the sequence hit; resolvable by 037 * String id = DataStore.seqNameForID(hitID) 038 * @param queryOffset the offset into the query sequence 039 * @param hitOffset the offset into the sequence hit in the database 040 * @param hitLength the number of symbols hit 041 */ 042 public void hit( 043 int hitID, 044 int queryOffset, 045 int hitOffset, 046 int hitLength 047 ); 048 049 /** 050 * A simple wrapper implementation. 051 * 052 * <p>Extend this and over-ride any of the interface methods to implement 053 * SearchListeners that filter hits before passing them on to an 054 * underlying listener.</p> 055 * You can modify the search events the delegate sees by over-riding any of 056 * the SearchListener methods, modify the arguments 057 * and then call the method on super with the new arguments. 058 * You can drop hits by just not passing them onto the delegate using 059 * super.hits(). 060 * <em>Note:</em> Be sure to maintain the nesting of start/stop search and 061 * hit, or you will confuse the delegate. 062 * 063 * @author Matthew Pocock 064 * @since 1.4 065 */ 066 public static abstract class Wrapper 067 implements SearchListener { 068 private final SearchListener delegate; 069 070 public Wrapper(SearchListener delegate) { 071 this.delegate = delegate; 072 } 073 074 public void startSearch(String seqID) { 075 delegate.startSearch(seqID); 076 } 077 078 public void endSearch(String seqID) { 079 delegate.endSearch(seqID); 080 } 081 082 public void hit( 083 int hitID, 084 int queryOffset, 085 int hitOffset, 086 int hitLength 087 ) { 088 delegate.hit(hitID, queryOffset, hitOffset, hitLength); 089 } 090 } 091 092 /** 093 * A SearchListener that passes events on to two delegate listeners. 094 * 095 * <p>This allows you to build trees of listeners. This is usefull, for 096 * example, when echoing output from different listeners.</p> 097 * 098 * @author Matthew Pocock 099 * @since 1.4 100 */ 101 public static final class Tee 102 implements SearchListener { 103 private final SearchListener d1; 104 private final SearchListener d2; 105 106 public Tee(SearchListener d1, SearchListener d2) { 107 if(d1 == null || d2 == null) { 108 throw new IllegalArgumentException( 109 "Delegates can not be null: " + d1 + " " + d2 ); 110 } 111 112 this.d1 = d1; 113 this.d2 = d2; 114 } 115 116 public void startSearch(String seqID) { 117 d1.startSearch(seqID); 118 d2.startSearch(seqID); 119 } 120 121 public void endSearch(String seqID) { 122 d1.endSearch(seqID); 123 d2.endSearch(seqID); 124 } 125 126 public void hit( 127 int hitID, 128 int queryOffset, 129 int hitOffset, 130 int hitLength 131 ) { 132 d1.hit(hitID, queryOffset, hitOffset, hitLength); 133 d2.hit(hitID, queryOffset, hitOffset, hitLength); 134 } 135 } 136 137 /** 138 * A simple listener that filters out all hits that are too short. 139 * 140 * @author Matthew Pocock 141 * @since 1.4 142 */ 143 public static final class FilterByLength 144 extends Wrapper { 145 private final int minLength; 146 147 public FilterByLength(SearchListener delegate, int minLength) { 148 super(delegate); 149 this.minLength = minLength; 150 } 151 152 public void hit( 153 int hitID, 154 int queryOffset, 155 int hitOffset, 156 int hitLength 157 ) { 158 if(hitLength >= minLength) { 159 super.hit(hitID, queryOffset, hitOffset, hitLength); 160 } 161 } 162 } 163 164 /** 165 * A SearchListener that prints events out to a PrintStream. 166 * 167 * <p>Use this for debugging purposes.</p> 168 * 169 * @author Matthew Pocock 170 * @since 1.4 171 */ 172 public static final class Echo 173 implements SearchListener { 174 private final PrintStream out; 175 176 public Echo(PrintStream out) { 177 this.out = out; 178 } 179 180 public void startSearch(String seqID) { 181 out.println("startSearch: " + seqID); 182 } 183 184 public void endSearch(String seqID) { 185 out.println("endSearch: " + seqID); 186 } 187 188 public void hit( 189 int hitID, 190 int queryOffset, 191 int hitOffset, 192 int hitLength 193 ) { 194 out.println( 195 "hit." + 196 "\thitID: " + hitID + 197 "\tqueryOffset: " + queryOffset + 198 "\thitOffset: " + hitOffset + 199 "\thitLength: " + hitLength ); 200 } 201 } 202}