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.game;
023
024import java.util.ListIterator;
025
026import org.biojava.bio.SmallAnnotation;
027import org.biojava.bio.seq.Feature;
028import org.biojava.bio.seq.StrandedFeature;
029import org.biojava.bio.symbol.Location;
030import org.biojava.bio.symbol.RangeLocation;
031import org.biojava.utils.ChangeVetoException;
032import org.biojava.utils.stax.StAXContentHandler;
033import org.xml.sax.Attributes;
034import org.xml.sax.SAXException;
035
036/**
037 * Handles the <feature_set> element
038 *
039 * @author David Huen
040 * @since 1.2
041 */
042public class GAMEFeatureSetHandler
043               extends StAXFeatureHandler
044               implements GAMENameCallbackItf, GAMETranscriptCallbackItf  
045{
046  // <feature_span> is one of the worst elements in GAME.  The type of element
047  // is only known from reading the nested <type> element.  The bloody
048  // strand and coordinates are nested 4-deep within the element.
049  // this element is implemented as a transcript.
050
051  private Location transcriptRange;
052  private StAXFeatureHandler staxenv;
053
054  public static final StAXHandlerFactory GAME_FEATURESET_HANDLER_FACTORY
055    = new StAXHandlerFactory() {
056    public StAXContentHandler getHandler(StAXFeatureHandler staxenv) {
057      return new GAMEFeatureSetHandler(staxenv);
058    }
059  };
060
061  GAMEFeatureSetHandler(StAXFeatureHandler staxenv) {
062    // setup up environment stuff
063    this.staxenv = staxenv;
064    featureListener = staxenv.featureListener;
065    setHandlerCharacteristics("feature_set", true);
066
067    // setup handlers
068       // <name>
069       super.addHandler(new ElementRecognizer.ByLocalName("name"),
070         GAMENamePropHandler.GAME_NAME_PROP_HANDLER_FACTORY);
071       // <feature_span>
072       super.addHandler(new ElementRecognizer.ByLocalName("feature_span"),
073         GAMEFeatureSpanHandler.GAME_FEATURESPAN_HANDLER_FACTORY);
074  }
075
076
077  public void NameSetStringValue(String s) {
078    // the id overrides name element by default.
079    if (!featureTemplate.annotation.containsProperty("id")) {
080      try {
081       featureTemplate.annotation.setProperty("id", s);
082      }
083      catch (ChangeVetoException cve) {
084        // baulk and discard exception
085        System.out.println("GAMEFeatureSetHandler: change vetoed");
086      }
087    }
088  }
089
090  public void reportExon(RangeLocation range, StrandedFeature.Strand strand) {
091    // set strand of transcript
092    ((StrandedFeature.Template) featureTemplate).strand = strand;
093
094    // check extend current range with new exon
095    if (transcriptRange == null)
096      transcriptRange = range;
097    else
098      transcriptRange = transcriptRange.union(range);
099  }
100
101  protected Feature.Template createTemplate() {
102    // create Gene Template for this
103    StrandedFeature.Template st = new StrandedFeature.Template();
104
105    // assume feature set to describe a transcript
106    st.type = "transcript";
107    st.strand = StrandedFeature.UNKNOWN;
108
109    // set up annotation bundle
110    st.annotation = new SmallAnnotation();
111
112    return st;
113  }
114
115  public void startElementHandler(
116                String nsURI,
117                String localName,
118                String qName,
119                Attributes attrs)
120         throws SAXException
121  {
122    // handle the attributes
123    String s = (String) attrs.getValue("id");
124    if (s != null) {
125      try {
126        featureTemplate.annotation.setProperty("id", s);
127      }
128      catch (ChangeVetoException cve) {
129        // just ignore change
130        System.err.println("GAMEFeatureSetHandler: change vetoed");
131      }
132    }
133  }
134
135  public void endElementHandler(
136                String nsURI,
137                String localName,
138                String qName,
139                StAXContentHandler handler)
140  {
141    // set the extent of the transcript to its limits
142    if (transcriptRange != null) {
143//      featureTemplate.location = new RangeLocation(transcriptRange.getMin(), transcriptRange.getMax());
144      featureTemplate.location = transcriptRange;      
145    }
146    else
147      featureTemplate.location = Location.empty;
148
149    // tell nesting feature about my extent and strand.
150    int currLevel = staxenv.getLevel();
151//    System.out.println("GAMEFeatureSetHandler.endElement entered. currlevel: " + currLevel);
152 
153    if (currLevel >=1) {
154      // search down stack for callback handler
155      ListIterator li = staxenv.getHandlerStackIterator(currLevel);
156//    System.out.println("GAMEFeatureSetHandler.endElement entered. got ListIterator");
157      while (li.hasPrevious()) {
158        Object ob = li.previous();
159//    System.out.println("GAMEFeatureSetHandler.endElement entered. got stack object");
160        if (ob instanceof GAMEFeatureCallbackItf) {
161          // we have a nesting handler, use it
162//    System.out.println("GAMEFeatureSetHandler.endElement calling back");
163          ((GAMEFeatureCallbackItf) ob).reportFeature(featureTemplate.location);
164          ((GAMEFeatureCallbackItf) ob).reportStrand(((StrandedFeature.Template) featureTemplate).strand);
165          return;
166        }
167      }
168    }
169
170  }
171}
172