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 java.util.ArrayList;
016import java.util.List;
017
018import org.biojava.bio.seq.io.SeqIOListener;
019import org.biojava.bio.seq.io.game.ElementRecognizer;
020import org.biojava.utils.stax.DelegationManager;
021import org.biojava.utils.stax.StAXContentHandler;
022import org.biojava.utils.stax.StAXContentHandlerBase;
023import org.xml.sax.Attributes;
024import org.xml.sax.SAXException;
025
026/**
027 *  StAX handler shamelessly ripped off from Thomas Down's XFFFeatureSetHandler.
028 *  It was modified for greater generality. <strong>NOTE</strong> This class is
029 *  not thread-safe -- it must only be used for one parse at any time.
030 *
031 * @author     Thomas Down
032 * @author     David Huen
033 * @since      1.2
034 */
035
036public class StAXFeatureHandler extends StAXContentHandlerBase {
037    // class variables
038    /**
039     * the SeqIOListener for this object
040     */
041    SeqIOListener listener;
042
043    /**
044     *  Nesting class that provides callback interfaces to nested class
045     */
046    public StAXFeatureHandler staxenv;
047    /**
048     *  handler list for delegation
049     */
050    private List handlers;
051
052    /**
053     *  These switches control functionality *
054     */
055    /**
056     *  are we in delegation from current object or is this pass my own?
057     */
058    private int level = 0;
059
060    /**
061     *  This base class defines default behaviour for a StAX handler including
062     *  delegation.
063     */
064    /**
065     *  the version of constructor called depends on whether there is an
066     *  explicit super(...) in the constructor of the derived class. If there
067     *  is, that specific constructor will be called. If not, the parameterless
068     *  will is called.
069     */
070
071    StAXFeatureHandler() {
072//        System.out.println("entering anonymous constructor");
073        handlers = new ArrayList();
074    }
075
076
077    /**
078     *  Constructor for the StAXFeatureHandler object
079     *
080     *@param  staxenv   Description of the Parameter
081     */
082    StAXFeatureHandler(StAXFeatureHandler staxenv) {
083        handlers = new ArrayList();
084        this.staxenv = staxenv;
085        this.listener = staxenv.listener;
086    }
087
088    // Class to implement bindings
089    /**
090     *  Description of the Class
091     *
092     *@author     david
093     *@created    19 January 2002
094     */
095    class Binding {
096        final ElementRecognizer recognizer;
097        final StAXHandlerFactory handlerFactory;
098
099
100        /**
101         *  Constructor for the Binding object
102         *
103         *@param  er  Description of the Parameter
104         *@param  hf  Description of the Parameter
105         */
106        Binding(ElementRecognizer er, StAXHandlerFactory hf) {
107            recognizer = er;
108            handlerFactory = hf;
109        }
110    }
111
112    // method to add a handler
113    // we do not distinguish whither it is a feature or property
114    // handler.  The factory method creates the right type subclassed
115    // from the correct type of handler
116    /**
117     *  Adds a feature to the Handler attribute of the StAXFeatureHandler object
118     *
119     *@param  rec      The feature to be added to the Handler attribute
120     *@param  handler  The feature to be added to the Handler attribute
121     */
122    protected void addHandler(
123            ElementRecognizer rec,
124            StAXHandlerFactory handler) {
125        handlers.add(new Binding(rec, handler));
126    }
127
128    /** provides a standardised way of returning an
129     *  object that represents the result of parsing the
130     *  child element
131     */
132    public void returnData(Object o)
133    {
134    }
135
136    /**
137     * get the SeqIOListener for this parser
138     */
139//    public SeqIOListener getListener()
140//    {
141//        return staxenv.listener;
142//    }
143
144    /**
145     *  Element-specific handler. Subclass this to do something useful!
146     *
147     *@param  nsURI             Description of the Parameter
148     *@param  localName         Description of the Parameter
149     *@param  qName             Description of the Parameter
150     *@param  attrs             Description of the Parameter
151     *@exception  SAXException  Description of the Exception
152     */
153    public void startElementHandler(
154            String nsURI,
155            String localName,
156            String qName,
157            Attributes attrs)
158             throws SAXException { }
159
160    /**
161     *  Handles basic entry processing for all feature handlers.
162     *
163     *@param  nsURI             Description of the Parameter
164     *@param  localName         Description of the Parameter
165     *@param  qName             Description of the Parameter
166     *@param  attrs             Description of the Parameter
167     *@param  dm                Description of the Parameter
168     *@exception  SAXException  Description of the Exception
169     */
170    public void startElement(
171            String nsURI,
172            String localName,
173            String qName,
174            Attributes attrs,
175            DelegationManager dm)
176             throws SAXException {
177        level++;
178
179        // perform delegation
180        // we must delegate only on features that are directly attached.
181        // if I do not check that that's so, any element of a kind I delegate
182        // on will be detected any depth within unrecognized tags.
183        if (level == 2) {
184//        System.out.println("StaxFeaturehandler.startElement starting. localName: " + localName + " " + level);
185            for (int i = handlers.size() - 1; i >= 0; --i) {
186                Binding b = (Binding) handlers.get(i);
187                if (b.recognizer.filterStartElement(nsURI, localName, qName, attrs)) {
188                    dm.delegate(b.handlerFactory.getHandler(this));
189                    return;
190                }
191            }
192        }
193
194        // call the element specific handler now.
195        // remember that if we we have a delegation failure we pass here too!
196        if (level == 1) {
197            startElementHandler(nsURI, localName, qName, attrs);
198        }
199    }
200
201    /**
202     *  Element specific exit handler Subclass to do anything useful.
203     *
204     *@param  nsURI             Description of the Parameter
205     *@param  localName         Description of the Parameter
206     *@param  qName             Description of the Parameter
207     *@param  handler           Description of the Parameter
208     *@exception  SAXException  Description of the Exception
209     */
210    public void endElementHandler(
211            String nsURI,
212            String localName,
213            String qName,
214            StAXContentHandler handler)
215             throws SAXException { }
216
217
218    /**
219     *  Handles basic exit processing.
220     *
221     *@param  nsURI             Description of the Parameter
222     *@param  localName         Description of the Parameter
223     *@param  qName             Description of the Parameter
224     *@param  handler           Description of the Parameter
225     *@exception  SAXException  Description of the Exception
226     */
227    public void endElement(
228            String nsURI,
229            String localName,
230            String qName,
231            StAXContentHandler handler)
232             throws SAXException {
233//      System.out.println("StAXFeatureHandler endElement called, localName, level: " + localName + " " + stackLevel);
234        if ((--level) == 0) {
235            endElementHandler(nsURI, localName, qName, handler);
236        }
237    }
238}
239