00001 package org.gel.mauve.format;
00002
00003 import java.io.File;
00004 import java.io.FileNotFoundException;
00005 import java.util.HashMap;
00006 import java.util.Iterator;
00007 import java.util.List;
00008 import java.util.Map;
00009
00010 import org.biojava.bio.Annotation;
00011 import org.biojava.bio.BioException;
00012 import org.biojava.bio.SimpleAnnotation;
00013 import org.biojava.bio.seq.Feature;
00014 import org.biojava.bio.seq.FeatureFilter;
00015 import org.biojava.bio.seq.FeatureHolder;
00016 import org.biojava.bio.seq.Sequence;
00017 import org.biojava.bio.seq.SimpleFeatureHolder;
00018 import org.biojava.bio.seq.StrandedFeature;
00019 import org.biojava.bio.seq.Feature.Template;
00020 import org.biojava.bio.seq.impl.SimpleStrandedFeature;
00021 import org.biojava.bio.symbol.Alphabet;
00022 import org.biojava.bio.symbol.Edit;
00023 import org.biojava.bio.symbol.IllegalAlphabetException;
00024 import org.biojava.bio.symbol.PackedSymbolListFactory;
00025 import org.biojava.bio.symbol.Symbol;
00026 import org.biojava.bio.symbol.SymbolList;
00027 import org.biojava.ontology.OntoTools;
00028 import org.biojava.utils.ChangeListener;
00029 import org.biojava.utils.ChangeType;
00030 import org.biojava.utils.ChangeVetoException;
00031 import org.biojava.utils.Changeable;
00032 import org.biojava.utils.Unchangeable;
00033 import org.biojavax.bio.seq.RichFeature;
00034 import org.gel.mauve.FilterCacheSpec;
00035 import org.gel.mauve.SupportedFormat;
00036
00037 class DelegatingSequence implements Sequence {
00038 protected File source;
00039
00040 protected int sequenceIndex;
00041
00042 protected Annotation annotation;
00043
00044 protected Alphabet alphabet;
00045
00046 protected int length;
00047
00048 protected String name;
00049
00050 protected String urn;
00051
00052 protected int featureCount;
00053
00054 protected Map filterCache = new HashMap ();
00055
00056 protected SupportedFormat format;
00057
00058 protected boolean circular;
00059
00060
00061 Changeable ch = new Unchangeable ();
00062
00063 SymbolList packedList = null;
00064
00065 public DelegatingSequence (Sequence s, SupportedFormat format, File source,
00066 int index) throws FileNotFoundException {
00067 format.validate (s, source, index);
00068
00069 this.format = format;
00070 this.source = source;
00071 this.sequenceIndex = index;
00072
00073 init (s);
00074 }
00075
00076 protected void init (Sequence s) {
00077 PackedSymbolListFactory pslFactory = new PackedSymbolListFactory ();
00078 Symbol [] symArray = new Symbol [s.length ()];
00079 int symI = 0;
00080 for (Iterator symIter = s.iterator (); symIter.hasNext ();) {
00081 symArray[symI++] = (Symbol) symIter.next ();
00082 }
00083 try {
00084 packedList = pslFactory.makeSymbolList(symArray, s.length(), s.getAlphabet());
00085 }catch(IllegalAlphabetException iae)
00086 {
00087 iae.printStackTrace ();
00088 }
00089
00090 annotation = new SimpleAnnotation (s.getAnnotation ());
00091 alphabet = s.getAlphabet ();
00092 length = s.length ();
00093 name = format.getChromosomeName (s);
00094
00095 urn = s.getURN ();
00096 featureCount = s.countFeatures ();
00097
00098 for (int i = 0; i < format.getFilterCacheSpecs ().length; i++) {
00099 addToCache (s, format.getFilterCacheSpecs ()[i]);
00100 }
00101
00102 completeInit (s);
00103 }
00104
00105 protected void completeInit (Sequence s) {
00106
00107 }
00108
00109
00110
00111 public String getName () {
00112 return name;
00113 }
00114
00115 public String getURN () {
00116 return urn;
00117 }
00118
00119
00120
00121
00122
00123
00127
00128 public void addChangeListener (ChangeListener cl) {
00129 ch.addChangeListener (cl);
00130 }
00131
00132 public void addChangeListener (ChangeListener cl, ChangeType ct) {
00133 ch.addChangeListener (cl, ct);
00134 }
00135
00139
00140 public void removeChangeListener (ChangeListener cl) {
00141 ch.removeChangeListener (cl);
00142 }
00143
00144 public void removeChangeListener (ChangeListener cl, ChangeType ct) {
00145 ch.removeChangeListener (cl, ct);
00146 }
00147
00148 public boolean isUnchanging (ChangeType ct) {
00149 return ch.isUnchanging (ct);
00150 }
00151
00152
00153
00154
00155
00156
00157 public Annotation getAnnotation () {
00158 return annotation;
00159 }
00160
00161
00162
00163
00164
00165
00166 public Alphabet getAlphabet () {
00167 return packedList.getAlphabet ();
00168 }
00169
00170 public int length () {
00171 return length;
00172 }
00173
00174 public Symbol symbolAt (int index) throws IndexOutOfBoundsException {
00175 return packedList.symbolAt (index);
00176 }
00177
00178 public List toList () {
00179 return packedList.toList ();
00180 }
00181
00182 public Iterator iterator () {
00183 return packedList.iterator ();
00184 }
00185
00186 public SymbolList subList (int start, int end)
00187 throws IndexOutOfBoundsException {
00188 return new DelegatingSublist (start, end);
00189 }
00190
00191 public String seqString () {
00192 return packedList.seqString ();
00193 }
00194
00195 public String subStr (int start, int end) throws IndexOutOfBoundsException {
00196 return packedList.subStr (start, end);
00197 }
00198
00199 public void edit (Edit edit) throws IllegalAlphabetException,
00200 ChangeVetoException {
00201 throw new ChangeVetoException ();
00202 }
00203
00204 public int countFeatures () {
00205 return featureCount;
00206 }
00207
00208 public Iterator features () {
00209 Sequence s = format.readInnerSequence (source, sequenceIndex);
00210 return s.features ();
00211 }
00212
00213 public FeatureHolder filter (FeatureFilter fc, boolean recurse) {
00214 FeatureHolder fh;
00215
00216
00217
00218 if (fc instanceof FeatureFilter.And
00219 && ((FeatureFilter.And) fc).getChild2 () instanceof FeatureFilter.OverlapsLocation) {
00220 fh = getCachedFilterResults (((FeatureFilter.And) fc).getChild1 ());
00221 } else {
00222 fh = format.readInnerSequence (source, sequenceIndex);
00223 }
00224 return fh.filter (fc, recurse);
00225 }
00226
00227 private FeatureHolder getCachedFilterResults (FeatureFilter ff) {
00228 if (!filterCache.containsKey (ff)) {
00229 Sequence s = format.readInnerSequence (source, sequenceIndex);
00230 addToCache (s, new FilterCacheSpec (ff));
00231 }
00232
00233 return (FeatureHolder) filterCache.get (ff);
00234 }
00235
00236 private void addToCache (Sequence s, FilterCacheSpec filterCacheSpec) {
00237 FeatureHolder results = s.filter (filterCacheSpec.filter, true);
00238
00239
00240 SimpleFeatureHolder sfh = new SimpleFeatureHolder ();
00241 Iterator i = results.features ();
00242 while (i.hasNext ()) {
00243 Feature f = (Feature) i.next ();
00244 Feature sf = null;
00245 if (f instanceof StrandedFeature)
00246 sf = makeThinFeature ((StrandedFeature) f, filterCacheSpec);
00247 else
00248 System.err.println ("found one that ain't stranded");
00249 try {
00250 sfh.addFeature (sf);
00251 } catch (ChangeVetoException e) {
00252 throw new Error (e);
00253 }
00254 }
00255 filterCache.put (filterCacheSpec.filter, sfh);
00256 }
00257
00258 protected SimpleStrandedFeature makeThinFeature (StrandedFeature f, FilterCacheSpec spec) {
00259 return makeThinFeature (this, f, spec);
00260 }
00261
00270 protected static SimpleStrandedFeature makeThinFeature (Sequence sequence,
00271 StrandedFeature f, FilterCacheSpec spec) {
00272 Feature.Template template = f.makeTemplate ();
00273 if (f.getAnnotation () != null && spec.getAnnotations () != null
00274 && spec.getAnnotations ().length > 0) {
00275 if (spec.getAnnotations ()[0]
00276 .equals (FilterCacheSpec.ALL_ANNOTATIONS)) {
00277
00278 } else {
00279 Annotation a = new SimpleAnnotation ();
00280 for (int i = 0; i < spec.getAnnotations ().length; i++) {
00281 String property = spec.getAnnotations ()[i];
00282
00283 if (f.getAnnotation ().containsProperty (property)) {
00284 try {
00285 a.setProperty (property, f.getAnnotation ()
00286 .getProperty (property));
00287 } catch (ChangeVetoException e) {
00288
00289 throw new RuntimeException (e);
00290 }
00291 }
00292 }
00293 template.annotation = a;
00294 }
00295 } else {
00296
00297 template.annotation = Annotation.EMPTY_ANNOTATION;
00298 }
00299 template.source = null;
00300 template.sourceTerm = OntoTools.ANY;
00301 if(template instanceof RichFeature.Template)
00302 {
00303 SimpleStrandedFeature sf = new SimpleStrandedFeature(sequence, sequence,
00304 new RichStrandedFeatureTemplate((RichFeature.Template)template));
00305 return sf;
00306 }else{
00307 SimpleStrandedFeature sf = new SimpleStrandedFeature(sequence, sequence,
00308 (StrandedFeature.Template)template);
00309 return sf;
00310 }
00311 }
00312
00313 public FeatureHolder filter (FeatureFilter fc) {
00314 FeatureHolder fh;
00315
00316
00317
00318 if (fc instanceof FeatureFilter.And
00319 && ((FeatureFilter.And) fc).getChild2 () instanceof FeatureFilter.OverlapsLocation) {
00320 fh = getCachedFilterResults (((FeatureFilter.And) fc).getChild1 ());
00321 } else if (fc instanceof FeatureFilter.ByType) {
00322 fh = getCachedFilterResults (fc);
00323 } else {
00324 fh = format.readInnerSequence (source, sequenceIndex);
00325 }
00326 return fh.filter (fc);
00327 }
00328
00329 public Feature createFeature (Template ft) throws BioException,
00330 ChangeVetoException {
00331 throw new ChangeVetoException ();
00332 }
00333
00334 public void removeFeature (Feature f) throws ChangeVetoException,
00335 BioException {
00336 throw new ChangeVetoException ();
00337 }
00338
00339 public boolean containsFeature (Feature f) {
00340 Sequence s = format.readInnerSequence (source, sequenceIndex);
00341 return s.containsFeature (f);
00342 }
00343
00344 public FeatureFilter getSchema () {
00345 Sequence s = format.readInnerSequence (source, sequenceIndex);
00346 return s.getSchema ();
00347 }
00348
00349 private class DelegatingSublist implements SymbolList {
00350 private int start;
00351
00352 private int end;
00353
00354 public DelegatingSublist (int start, int end) {
00355 this.start = start;
00356 this.end = end;
00357 }
00358
00359 public Alphabet getAlphabet () {
00360 return alphabet;
00361 }
00362
00363 public int length () {
00364 return end - start + 1;
00365 }
00366
00367 public Symbol symbolAt (int index) throws IndexOutOfBoundsException {
00368 return DelegatingSequence.this.symbolAt (index + start - 1);
00369 }
00370
00371 public List toList () {
00372 throw new Error ("Not implemented");
00373 }
00374
00375 public Iterator iterator () {
00376 throw new Error ("Not implemented");
00377 }
00378
00379 public SymbolList subList (int start, int end)
00380 throws IndexOutOfBoundsException {
00381 return new DelegatingSublist (this.start + start - 1, this.start
00382 + end - 1);
00383 }
00384
00385 public String seqString () {
00386 return packedList.subStr (start, end);
00387
00388 }
00389
00390 public String subStr (int start, int end)
00391 throws IndexOutOfBoundsException {
00392 throw new Error ("Not implemented");
00393 }
00394
00395 public void edit (Edit edit) throws IndexOutOfBoundsException,
00396 IllegalAlphabetException, ChangeVetoException {
00397 throw new ChangeVetoException ();
00398 }
00399
00403
00404 public void addChangeListener (ChangeListener cl) {
00405 ch.addChangeListener (cl);
00406 }
00407
00408 public void addChangeListener (ChangeListener cl, ChangeType ct) {
00409 ch.addChangeListener (cl, ct);
00410 }
00411
00415 public void removeChangeListener (ChangeListener cl) {
00416 ch.removeChangeListener (cl);
00417 }
00418
00419 public void removeChangeListener (ChangeListener cl, ChangeType ct) {
00420 ch.removeChangeListener (cl, ct);
00421 }
00422
00423 public boolean isUnchanging (ChangeType ct) {
00424 return true;
00425 }
00426
00427 }
00428
00429 }