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.seq.io; 023 024import java.io.Serializable; 025import java.util.ArrayList; 026import java.util.List; 027import java.util.StringTokenizer; 028import java.util.Vector; 029 030import org.biojava.bio.BioException; 031import org.biojava.utils.ParseErrorEvent; 032import org.biojava.utils.ParseErrorListener; 033import org.biojava.utils.ParseErrorSource; 034 035/** 036 * Simple filter which handles attribute lines from an Swissprot entry. 037 * Skeleton implementation, please add more functionality. 038 * 039 * <p> 040 * <strong>FIXME:</strong> Note that this is currently rather incomplete, 041 * and doesn't handle any of the header information sensibly except for 042 * ID and AC. 043 * </p> 044 * 045 * @author Thomas Down 046 * @author Matthew Pocock 047 * @author Greg Cox 048 * @since 1.1 049 * @deprecated Use org.biojavax.bio.seq.io framework instead 050 */ 051 052public class SwissprotProcessor 053 extends 054 SequenceBuilderFilter 055 implements 056 ParseErrorSource 057{ 058 public static final String PROPERTY_SWISSPROT_ACCESSIONS = "swissprot.accessions"; 059 public static final String PROPERTY_SWISSPROT_COMMENT = "swissprot.comment"; 060 public static final String PROPERTY_SWISSPROT_FEATUREATTRIBUTE = "swissprot.featureattribute"; 061 062 private boolean mBadFeature = false; 063 private Vector mListeners = new Vector(); 064 065 /** 066 * Factory which wraps SequenceBuilders in a SwissprotProcessor 067 * 068 * @author Thomas Down 069 */ 070 071 public static class Factory implements SequenceBuilderFactory, Serializable 072 { 073 private SequenceBuilderFactory delegateFactory; 074 075 public Factory(SequenceBuilderFactory delegateFactory) 076 { 077 this.delegateFactory = delegateFactory; 078 } 079 080 public SequenceBuilder makeSequenceBuilder() 081 { 082 return new SwissprotProcessor(delegateFactory.makeSequenceBuilder()); 083 } 084 085 public SequenceBuilder makeSequenceBuilder(String theSource) 086 { 087 return new SwissprotProcessor(delegateFactory.makeSequenceBuilder(), theSource); 088 } 089 } 090 091 private SwissprotFeatureTableParser features; 092 private List accessions; 093 { 094 accessions = new ArrayList(); 095 } 096 097 /** 098 * Constructor that sets the source of the feature to theSource. 099 * 100 * @param delegate The sequecence builder to be used in constructing the 101 * sequence 102 * @param theSource The source of the features. e.g. "SWISS-PROT", "TrEMBL" 103 */ 104 public SwissprotProcessor(SequenceBuilder delegate, String theSource) 105 { 106 super(delegate); 107 features = new SwissprotFeatureTableParser(this, theSource); 108 } 109 110 public SwissprotProcessor(SequenceBuilder delegate) 111 { 112 super(delegate); 113 features = new SwissprotFeatureTableParser(this, "SWISSPROT"); 114 } 115 116 public void endSequence() throws ParseException 117 { 118 if (accessions.size() > 0) 119 { 120 String id = (String) accessions.get(0); 121 getDelegate().setName(id); 122 getDelegate().setURI("urn:sequence/swissprot:" + id); 123 getDelegate().addSequenceProperty(PROPERTY_SWISSPROT_ACCESSIONS, accessions); 124 accessions = new ArrayList(); 125 } 126 127 getDelegate().endSequence(); 128 } 129 130 public void addSequenceProperty(Object key, Object value) throws ParseException 131 { 132 try 133 { 134 if(mBadFeature) 135 { 136 // If this feature is bad in some way, ignore it. 137 String featureLine = value.toString(); 138 if((key.equals("FT")) && (featureLine.charAt(0) != ' ')) 139 { 140 // If the offending feature is past, start reading data again 141 mBadFeature = false; 142 features.startFeature(featureLine.substring(0, 8).trim()); 143 features.featureData(featureLine.substring(9)); 144 } 145 } 146 else 147 { 148 // Tidy up any end-of-block jobbies 149 if (features.inFeature() && !key.equals("FT")) 150 { 151 features.endFeature(); 152 } 153 154 if (key.equals("FT")) 155 { 156 String featureLine = value.toString(); 157 if (featureLine.charAt(0) != ' ') 158 { 159 // This is a featuretype field 160 if (features.inFeature()) 161 { 162 features.endFeature(); 163 } 164 165 features.startFeature(featureLine.substring(0, 8).trim()); 166 } 167 features.featureData(featureLine.substring(9)); 168 } 169 else 170 { 171 getDelegate().addSequenceProperty(key, value); 172 173 if (key.equals("AC")) 174 { 175 String acc= value.toString(); 176 StringTokenizer toke = new StringTokenizer(acc, "; "); 177 while (toke.hasMoreTokens()) 178 { 179 accessions.add(toke.nextToken()); 180 } 181 } 182 } 183 } 184 } 185 catch (BioException ex) 186 { 187 // If an exception is thrown, read past the offending feature 188 mBadFeature = true; 189 ParseErrorEvent offendingLineEvent = new ParseErrorEvent(this, "This line could not be parsed: " + value.toString()); 190 this.notifyParseErrorEvent(offendingLineEvent); 191 } 192 catch (IndexOutOfBoundsException ex) 193 { 194 // This occurs when for some line min > max 195 mBadFeature = true; 196 ParseErrorEvent offendingLineEvent = new ParseErrorEvent(this, "From must be less than To: " + value.toString()); 197 this.notifyParseErrorEvent(offendingLineEvent); 198 } 199 } 200 201 /** 202 * Adds a parse error listener to the list of listeners if it isn't already 203 * included. 204 * 205 * @param theListener Listener to be added. 206 */ 207 public synchronized void addParseErrorListener( 208 ParseErrorListener theListener) 209 { 210 if(mListeners.contains(theListener) == false) 211 { 212 mListeners.addElement(theListener); 213 } 214 } 215 216 /** 217 * Removes a parse error listener from the list of listeners if it is 218 * included. 219 * 220 * @param theListener Listener to be removed. 221 */ 222 public synchronized void removeParseErrorListener( 223 ParseErrorListener theListener) 224 { 225 if(mListeners.contains(theListener) == true) 226 { 227 mListeners.removeElement(theListener); 228 } 229 } 230 231 // Protected methods 232 /** 233 * Passes the event on to all the listeners registered for ParseErrorEvents. 234 * 235 * @param theEvent The event to be handed to the listeners. 236 */ 237 protected void notifyParseErrorEvent(ParseErrorEvent theEvent) 238 { 239 Vector listeners; 240 synchronized(this) 241 { 242 listeners = (Vector)mListeners.clone(); 243 } 244 245 for (int index = 0; index < listeners.size(); index++) 246 { 247 ParseErrorListener client = (ParseErrorListener)listeners.elementAt(index); 248 client.BadLineParsed(theEvent); 249 } 250 } 251}