001/**
002 *  BioJava development code This code may be freely distributed and modified
003 *  under the terms of the GNU Lesser General Public Licence. This should be
004 *  distributed with the code. If you do not have a copy, see:
005 *  http://www.gnu.org/copyleft/lesser.html Copyright for this code is held
006 *  jointly by the individual authors. These should be listed in
007 *
008 *@author    doc comments. For more information on the BioJava project and its
009 *      aims, or to join the biojava-l mailing list, visit the home page at:
010 *      http://www.biojava.org/
011 */
012
013package org.biojava.bio.seq.io.game12;
014
015import org.biojava.bio.SimpleAnnotation;
016import org.biojava.bio.seq.StrandedFeature;
017import org.biojava.bio.seq.io.ParseException;
018import org.biojava.bio.seq.io.game.ElementRecognizer;
019import org.biojava.bio.symbol.Location;
020import org.biojava.bio.symbol.LocationTools;
021import org.biojava.utils.ChangeVetoException;
022import org.biojava.utils.stax.StAXContentHandler;
023import org.biojava.utils.stax.StringElementHandlerBase;
024import org.xml.sax.Attributes;
025import org.xml.sax.SAXException;
026
027/**
028 *  Handles the GAME <feature_set> element
029 *
030 * this element is used to represent transcripts.
031 *
032 * @author     David Huen
033 * @since      1.2
034 */
035public class GAMEFeatureSetHandler
036         extends StAXFeatureHandler {
037    // this creates a bundle of data on a specific
038    // aspect of an annotation, e.g. a transcript.
039
040    // database columns
041//    private String id;
042//    private String produces_seq;
043    private String featureSetType;
044
045    StrandedFeature.Template template;
046
047    Location transcript;
048    Location translateOffset;
049    StrandedFeature.Strand transcriptStrand;
050
051    // subclass GAMEFeatureSpanHandler to retrieve data
052    private class FeatureSpanHandler extends GAMEFeatureSpanHandler
053    {
054        private FeatureSpanHandler(StAXFeatureHandler staxenv)
055        {
056            super(staxenv);
057//            System.out.println("entering FeatureSpanHandler");
058        }
059
060        public void endElementHandler(
061                String nsURI,
062                String localName,
063                String qName,
064                StAXContentHandler contentHandler)
065            throws SAXException
066        {
067            // validate
068            super.endElementHandler(nsURI, localName, qName, contentHandler);
069
070            // decide what to do on basis of type
071//            System.out.println("SpanHandler end seeing " + featureSpanType);
072            if (featureSpanType.equals("exon")) {
073                // got an exon
074                if (transcript == null) {
075                    // store transcript data
076                    transcript = featureSpanLoc;
077                    transcriptStrand = featureSpanStrand;
078                }
079                else {
080                    // validate this exon, is it on same strand?
081                    if (transcriptStrand != featureSpanStrand) {
082                        System.err.println("exons on differing strands!");
083                    }
084
085                    // update the transcript
086//                    System.out.println("setting exon in transcript " + featureSpanLoc);
087                    transcript = LocationTools.union(transcript, featureSpanLoc);
088                }
089            }
090            else if (featureSpanType.equals("translate offset")) {
091                // stash the location away
092                if (translateOffset != null)
093                    System.err.println("translate offset multiply defined.");
094                else {
095                    if (transcriptStrand == null) 
096                        transcriptStrand = featureSpanStrand;
097                    else if (transcriptStrand != featureSpanStrand)
098                        System.err.println("exons on differing strands!");
099
100                    translateOffset = featureSpanLoc;
101                }
102            }
103        }
104    }
105
106    // set up factory method
107    /**
108     *  Description of the Field
109     */
110    public final static StAXHandlerFactory GAME_FEATURE_SET_HANDLER_FACTORY
111             =
112        new StAXHandlerFactory() {
113            public StAXContentHandler getHandler(StAXFeatureHandler staxenv) {
114                return new GAMEFeatureSetHandler(staxenv);
115            }
116        };
117
118
119    GAMEFeatureSetHandler(StAXFeatureHandler staxenv) {
120        // setup environment
121        super(staxenv);
122
123        // setup handlers
124        // <name>
125        super.addHandler(new ElementRecognizer.ByLocalName("name"),
126            new StAXHandlerFactory() {
127                public StAXContentHandler getHandler(StAXFeatureHandler staxenv) {
128                    return new NameHandler();
129                }
130            }
131                );
132        // <type> local handler type
133        super.addHandler(new ElementRecognizer.ByLocalName("type"),
134            new StAXHandlerFactory() {
135                public StAXContentHandler getHandler(StAXFeatureHandler staxenv) {
136                    return new TypeHandler();
137                }
138            }
139                );
140        // <author> local handler type
141        super.addHandler(new ElementRecognizer.ByLocalName("author"),
142            new StAXHandlerFactory() {
143                public StAXContentHandler getHandler(StAXFeatureHandler staxenv) {
144                    return new AuthorHandler();
145                }
146            }
147                );
148
149        // <feature_span>
150//        super.addHandler(new ElementRecognizer.ByLocalName("feature_span"),
151//                GAMEFeatureSpanHandler.GAME_FEATURE_SPAN_HANDLER_FACTORY);
152        super.addHandler(new ElementRecognizer.ByLocalName("feature_span"),
153            new StAXHandlerFactory() {
154                public StAXContentHandler getHandler(StAXFeatureHandler staxenv) {
155                    return new FeatureSpanHandler(staxenv);
156                }
157            }
158        );
159        // <seq>
160//        super.addHandler(new ElementRecognizer.ByLocalName("seq"),
161//                GAMESeqHandler.GAME_SEQ_HANDLER_FACTORY);
162        // <property>
163        super.addHandler(new ElementRecognizer.ByLocalName("property"),
164                GAMEPropertyHandler.GAME_PROPERTY_HANDLER_FACTORY);
165    }
166
167    private class NameHandler extends StringElementHandlerBase {
168        /**
169         *  Sets the stringValue attribute of the NameHandler object
170         *
171         *@param  s  The new stringValue value
172         */
173        protected void setStringValue(String s) {
174        }
175    }
176
177    private class TypeHandler extends StringElementHandlerBase {
178        /**
179         *  Sets the stringValue attribute of the TypeHandler object
180         *
181         *@param  s  The new stringValue value
182         */
183        protected void setStringValue(String s) {
184            featureSetType = s.trim();
185        }
186    }
187
188    private class AuthorHandler extends StringElementHandlerBase {
189        /**
190         *  Sets the stringValue attribute of the TypeHandler object
191         *
192         *@param  s  The new stringValue value
193         */
194        protected void setStringValue(String s) {
195        }
196    }
197
198    public void startElementHandler(
199            String nsURI,
200            String localName,
201            String qName,
202            Attributes attrs) 
203        throws SAXException
204    {
205        // acquire attributes here
206        String id = attrs.getValue("id");
207        String produces_seq = attrs.getValue("produces_seq");
208
209        // create template
210        // this element is expected to encode a transcript
211        template = new StrandedFeature.Template();
212        template.annotation = new SimpleAnnotation();
213
214        // fill in annotation bundle
215        try {
216            try {
217                if (id != null) template.annotation.setProperty("id", id);
218                if (produces_seq != null) template.annotation.setProperty("produces_seq", produces_seq);
219            }
220            catch (ChangeVetoException cve) {
221                cve.printStackTrace();
222                throw new SAXException("unexpected ChangeVetoException when setting id!");
223            }
224
225            listener.startFeature(template);
226        }
227        catch (ParseException pe) {
228            pe.printStackTrace();
229            throw new SAXException("error in GAMEFeatureSetHandler.");
230        }
231    }
232
233
234    public void endElementHandler(
235            String nsURI,
236            String localName,
237            String qName,
238            StAXContentHandler contentHandler) 
239        throws SAXException
240    {
241        // issue warning if it is not a transcript
242        if (!featureSetType.equals("transcript")) {
243             System.err.println("<feature_set> of type " + featureSetType + " encountered when transcript expected");
244        }
245
246        // fill in template as best can
247        template.type = featureSetType;
248        template.source = "";
249        template.location = transcript;
250        template.strand = transcriptStrand;
251
252        // indicate end of sequence
253        try {
254
255            // set the translate offset if available
256            try {
257                if (translateOffset != null) template.annotation.setProperty("translate_offset", translateOffset);
258            }
259            catch (ChangeVetoException cve) {
260                cve.printStackTrace();
261                throw new SAXException("unexpected ChangeVetoException when setting id!");
262            }
263
264            listener.endFeature();
265        }
266        catch (ParseException pe) {
267            pe.printStackTrace();
268            throw new SAXException("error in GAMEFeatureSetHandler.");
269        }
270    }
271}
272