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.util.ArrayList; 025import java.util.Collection; 026import java.util.Collections; 027import java.util.Comparator; 028import java.util.Iterator; 029import java.util.List; 030import java.util.Map; 031 032import org.biojava.bio.Annotation; 033import org.biojava.bio.BioError; 034import org.biojava.bio.seq.Feature; 035import org.biojava.bio.seq.FeatureHolder; 036import org.biojava.bio.seq.Sequence; 037import org.biojava.bio.symbol.IllegalAlphabetException; 038import org.biojava.bio.symbol.Symbol; 039 040/** 041 * <code>SeqIOEventEmitter</code> is a utility class which scans a 042 * <code>Sequence</code> object and sends events describing its 043 * constituent data to a <code>SeqIOListener</code>. The listener 044 * should be able to reconstruct the <code>Sequence</code> from these 045 * events. 046 * 047 * @author Keith James 048 * @since 1.2 049 * @deprecated Use org.biojavax.bio.seq.io framework instead 050 */ 051public class SeqIOEventEmitter 052{ 053 private static Symbol [] symProto = new Symbol [0]; 054 055 private Comparator seqPropComparator; 056 private Comparator refPropComparator; 057 private Comparator featureComparator; 058 059 public SeqIOEventEmitter(Comparator seqPropComparator, 060 Comparator featureComparator) 061 { 062 this.seqPropComparator = seqPropComparator; 063 this.featureComparator = featureComparator; 064 } 065 066 067 /** 068 * <code>getSeqIOEvents</code> scans a <code>Sequence</code> 069 * object and sends events describing its data to the 070 * <code>SeqIOListener</code>. 071 * 072 * @param seq a <code>Sequence</code>. 073 * @param listener a <code>SeqIOListener</code>. 074 */ 075 public void getSeqIOEvents(Sequence seq, SeqIOListener listener) 076 { 077 try 078 { 079 // Inform listener of sequence start 080 listener.startSequence(); 081 082 // Pass name to listener 083 listener.setName(seq.getName()); 084 085 // Pass URN to listener 086 listener.setURI(seq.getURN()); 087 088 // Pass sequence properties to listener 089 Annotation a = seq.getAnnotation(); 090 List sKeys = new ArrayList(a.keys()); 091 Collections.sort(sKeys, seqPropComparator); 092 093 for (Iterator ki = sKeys.iterator(); ki.hasNext();) 094 { 095 Object key = ki.next(); 096 097 if ( key.equals(ReferenceAnnotation.class)) { 098 099 ArrayList references = null; 100 101 if (a.getProperty(key) instanceof ArrayList) { 102 references = ((ArrayList)a.getProperty(key)); 103 } 104 else if (a.getProperty(key) instanceof ReferenceAnnotation){ 105 //mark_s: if only one ReferenceAnnotation 106 references = new ArrayList(); 107 references.add(a.getProperty(key)); 108 } 109 110 111 if (references != null) { 112 113 for ( int i = 0; i < references.size(); i++ ) { 114 ReferenceAnnotation refAnnot = (ReferenceAnnotation)references.get(i); 115 116 Map referenceLines = refAnnot.getProperties(); 117 List refKeys = new ArrayList(referenceLines.keySet()); 118 refPropComparator = EmblReferenceComparator.INSTANCE; 119 Collections.sort(refKeys, refPropComparator); 120 121 for (Iterator kit = refKeys.iterator(); kit.hasNext();) 122 { 123 Object refKey = kit.next(); 124 //adds all the R* tags and final XX tag 125 listener.addSequenceProperty(refKey, refAnnot.getProperty(refKey)); 126 } 127 } 128 } 129 } 130 else { 131 132 if (!(key.equals(EmblLikeFormat.SEPARATOR_TAG))) { //lorna: ignore XX 133 134 listener.addSequenceProperty(key, a.getProperty(key)); 135 } 136 137 } 138 } 139 140 // Recurse through sub feature tree, flattening it for 141 // EMBL 142 List subs = getSubFeatures(seq); 143 Collections.sort(subs, featureComparator); 144 145 // Put the source features first for EMBL 146 for (Iterator fi = subs.iterator(); fi.hasNext();) 147 { 148 // The template is required to call startFeature 149 Feature.Template t = ((Feature) fi.next()).makeTemplate(); 150 151 // Inform listener of feature start 152 listener.startFeature(t); 153 154 // Pass feature properties (i.e. qualifiers to 155 // listener) 156 // FIXME: this will drop all non-comparable keys 157 List fKeys = comparableList(t.annotation.keys()); 158 Collections.sort(fKeys); 159 160 for (Iterator ki = fKeys.iterator(); ki.hasNext();) 161 { 162 Object key = ki.next(); 163 listener.addFeatureProperty(key, t.annotation.getProperty(key)); 164 } 165 166 // Inform listener of feature end 167 listener.endFeature(); 168 } 169 170 // Add symbols 171 listener.addSymbols(seq.getAlphabet(), 172 (Symbol []) seq.toList().toArray(symProto), 173 0, 174 seq.length()); 175 176 // Inform listener of sequence end 177 listener.endSequence(); 178 } 179 catch (IllegalAlphabetException iae) 180 { 181 // This should never happen as the alphabet is being used 182 // by this Sequence instance 183 throw new BioError("An internal error occurred processing symbols",iae); 184 } 185 catch (ParseException pe) 186 { 187 throw new BioError("An internal error occurred creating SeqIO events",pe); 188 } 189 } 190 191 192 /** 193 * <code>getSubFeatures</code> is a recursive method which returns 194 * a list of all <code>Feature</code>s within a 195 * <code>FeatureHolder</code>. 196 * 197 * @param fh a <code>FeatureHolder</code>. 198 * 199 * @return a <code>List</code>. 200 */ 201 private static List getSubFeatures(FeatureHolder fh) 202 { 203 List subfeat = new ArrayList(); 204 205 for (Iterator fi = fh.features(); fi.hasNext();) 206 { 207 FeatureHolder sfh = (FeatureHolder) fi.next(); 208 209 subfeat.addAll((Collection) getSubFeatures(sfh)); 210 subfeat.add(sfh); 211 } 212 return subfeat; 213 } 214 215 private List comparableList(Collection coll) { 216 ArrayList res = new ArrayList(); 217 for(Iterator i = coll.iterator(); i.hasNext(); ) { 218 Object o = i.next(); 219 if(o instanceof Comparable) { 220 res.add(o); 221 } 222 } 223 return res; 224 } 225}