1   /*
2    *  Lax.java
3    *
4    *  Copyright (c) 1998-2001, The University of Sheffield.
5    *
6    *  This file is part of GATE (see http://gate.ac.uk/), and is free
7    *  software, licenced under the GNU Library General Public License,
8    *  Version 2, June 1991 (in the distribution as file licence.html,
9    *  and also available at http://gate.ac.uk/gate/licence.html).
10   *
11   *  Cristian URSU, 07/July/2000
12   *
13   *  $Id: Lax.java,v 1.8 2001/07/05 12:26:17 cursu Exp $
14   */
15  
16  package gate.util;
17  
18  import org.xml.sax.*;
19  import java.lang.reflect.*;
20  import javax.xml.parsers.*;
21  import org.w3c.dom.*;
22  import org.xml.sax.SAXException;
23  import org.xml.sax.SAXParseException;
24  import java.util.*;
25  import java.io.*;
26  
27  /** LAX (LazyProgrammer Api for XML) layer for a SAX parser,
28    * based on Sun's JAXP layer...so it works with any JAXP compliant parser
29    */
30  public class Lax extends org.xml.sax.helpers.DefaultHandler {
31  
32    /** Debug flag */
33    private static final boolean DEBUG = false;
34  
35    // LAX translates XML content into method calls on this object
36    private Vector _vecHandlers = null;
37  
38    private Vector _vecTags = null;
39  
40    private static Class[] _caNoArgs = null;
41  
42    private static Class[] _caAttrList = null;
43  
44    private static Class[] _caString = null;
45  
46    private LaxErrorHandler _seh = null;
47  
48    private boolean _validatingParser = false;
49  
50    private boolean _namespaceAwareParser = false;
51  
52    // Initialize class arrays used for reflection
53    static {
54      _caNoArgs = new Class[] {};
55      _caAttrList = new Class[] {org.xml.sax.Attributes.class};
56      _caString = new Class[] {java.lang.String.class};
57    }
58  
59    /**
60      * Lax default constructor
61      */
62    public Lax(LaxErrorHandler leh) {
63      super();
64      _vecHandlers = new Vector();
65      _vecTags = new Vector();
66      _seh = leh;
67    }
68  
69    /**
70      * Lax ctor with a single handler
71      */
72    public Lax(Object handler_ , LaxErrorHandler leh) {
73      super();
74      _vecHandlers = new Vector();
75      _vecTags = new Vector();
76      addHandler(handler_);
77      _seh = leh;
78    }
79  
80    /**
81      * Sets the CustomErrorHandler
82      * @param leh gate.util.LaxErrorHandler
83      */
84    public void setErrorHandler(LaxErrorHandler leh) {
85      _seh = leh;
86    }
87  
88    /**
89      * Get the CustomErrorHandler
90      * @return gate.util.LaxErrorHandler
91      */
92    public gate.util.LaxErrorHandler getErrorHandler() {
93      return _seh;
94    }
95  
96    /**
97      * Sets the parser to be a validating one
98      * implicit parameter is false (so the parser is not a validating one)
99      * @param validating boolean
100     */
101   public void setValidating(boolean validating) {
102     _validatingParser = validating;
103   }
104 
105   /**
106     * Get the validating property
107     * @return boolean
108     */
109   public boolean getValidating(){
110     return _validatingParser;
111   }
112 
113   /**
114     * Sets the parser to be a namespaces aware one
115     * implicit parameter is false (so the parser is not a namespaces aware one)
116     * @param namespacesAware boolean
117     */
118   public void setNamespacesAware(boolean namespacesAware) {
119     _namespaceAwareParser = namespacesAware;
120   }
121 
122   /**
123     * Get the namespacesAware property
124     * @return boolean
125     */
126   public boolean getNamespacesAware(){
127     return _namespaceAwareParser;
128   }
129 
130   /**
131     * Add a handler to the list of handler objects.
132     * @param objHandler_ java.lang.Object
133     */
134   public void addHandler(Object objHandler_) {
135     _vecHandlers.addElement(objHandler_);
136   }
137 
138   /**
139     * Handle an incoming block of text by calling the textOf method for the
140     * current tag.
141     */
142   public void characters(char[] caChars, int iStart, int iEnd)
143                                                           throws SAXException {
144     String sCurrentTag = sCurrentTag();
145 
146     if (sCurrentTag != null) {
147       int i;
148       String sTextMethodName = "textOf" + sCurrentTag;
149       String sArg = null;
150 
151       // Call every text method for current tag found in the list of handlers.
152       for (i = 0; i < _vecHandlers.size(); i++) {
153         Object oThisHandler = _vecHandlers.elementAt(i);
154         Method mTextMethod = mFindMethod(oThisHandler, sTextMethodName, _caString);
155         if (mTextMethod != null) {
156           try {
157             if (sArg == null) {
158               sArg = new String(caChars, iStart, iEnd);
159             }
160             mTextMethod.invoke(oThisHandler, new Object[] { sArg });
161           } catch (InvocationTargetException ex) {
162             Err.println(ex);
163           } catch (IllegalAccessException ex) {
164             Err.println(ex);
165           }
166         }
167       }
168     }
169   } // characters
170 
171   /**
172     * endDocument method comment.
173     */
174   public void endDocument() throws org.xml.sax.SAXException {
175   }
176 
177   /**
178     * Call all end tag methods in the handler list
179     */
180   public void endElement (String uri, String qName, String sTag)
181                                                           throws SAXException{
182     int i;
183     String sEndMethodName = "end" + sTag;
184 
185     // Call every tag start method for this tag found in the list of handlers.
186     for (i = 0; i < _vecHandlers.size(); i++) {
187       Object oThisHandler = _vecHandlers.elementAt(i);
188       Method mEndMethod = mFindMethod(oThisHandler, sEndMethodName, _caNoArgs);
189       if (mEndMethod != null) {
190         try {
191           mEndMethod.invoke(oThisHandler, new Object[] {});
192         } catch (InvocationTargetException ex) {
193           Err.println(ex);
194         } catch (IllegalAccessException ex) {
195           Err.println(ex);
196         }
197       }
198     }
199     popTag();
200   } // endElement
201 
202   /**
203     * error method comment.
204     */
205   public void error(SAXParseException ex) throws SAXException {
206     _seh.error(ex);
207   }
208 
209   /**
210     * fatalError method comment.
211     */
212   public void fatalError(SAXParseException ex) throws SAXException {
213     _seh.fatalError(ex);
214   }
215 
216   /**
217     * Return a method of object oHandler
218     * with the given name and argument list, or null if not found
219     * @return java.lang.reflect.Method
220     * @param oHandler java.lang.Object - The handler object to search for a
221     * method.
222     * @param sTag java.lang.String - The tag to find.
223     */
224   private Method mFindMethod(Object oHandler, String sMethodName,
225                                                               Class[] caArgs) {
226     Method m = null;
227     Class classOfHandler = oHandler.getClass();
228 
229     // Find a method with the given name and argument list
230     try {
231       m = classOfHandler.getMethod(sMethodName, caArgs);
232     } catch (NoSuchMethodException ex) {
233       // Ignore exception - no such method exists.
234     }
235     return m;
236   } // mFindMethod
237 
238   public void parseXmlDocument(java.io.File xmlFile) {
239     try {
240       // Get a "parser factory", an an object that creates parsers
241       SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
242 
243       // Set up the factory to create the appropriate type of parser
244       saxParserFactory.setValidating(_validatingParser);
245       saxParserFactory.setNamespaceAware(_namespaceAwareParser);
246 
247       SAXParser parser = saxParserFactory.newSAXParser();
248 
249       parser.parse(xmlFile, this);
250     } catch (Exception ex) {
251       ex.printStackTrace(Err.getPrintWriter());
252       // System.exit(2);
253     }
254   } // parseXmlDocument
255 
256   public void parseXmlDocument(org.xml.sax.InputSource xmlInputSource) {
257     try {
258       // Get a "parser factory", an an object that creates parsers
259       SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
260 
261       // Set up the factory to create the appropriate type of parser
262       saxParserFactory.setValidating(_validatingParser);
263       saxParserFactory.setNamespaceAware(_namespaceAwareParser);
264 
265       SAXParser parser = saxParserFactory.newSAXParser();
266 
267       parser.parse(xmlInputSource, this);
268     } catch (Exception ex) {
269       ex.printStackTrace(Err.getPrintWriter());
270       // System.exit(2);
271     }
272   } // parseXmlDocument
273 
274   public void parseXmlDocument(java.io.InputStream  xmlInputStream) {
275     try {
276       // Get a "parser factory", an an object that creates parsers
277       SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
278 
279       // Set up the factory to create the appropriate type of parser
280       saxParserFactory.setValidating(_validatingParser);
281       saxParserFactory.setNamespaceAware(_namespaceAwareParser);
282 
283       SAXParser parser = saxParserFactory.newSAXParser();
284 
285       parser.parse(xmlInputStream, this);
286     } catch (Exception ex) {
287       ex.printStackTrace(Err.getPrintWriter());
288       // System.exit(2);
289     }
290   } // parseXmlDocument(java.io.InputStream  xmlInputStream)
291 
292   public void parseXmlDocument(java.lang.String xmlURI) {
293     try {
294       // Get a "parser factory", an an object that creates parsers
295       SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
296 
297       // Set up the factory to create the appropriate type of parser
298       saxParserFactory.setValidating(_validatingParser);
299       saxParserFactory.setNamespaceAware(_namespaceAwareParser);
300 
301       SAXParser parser = saxParserFactory.newSAXParser();
302 
303       parser.parse(xmlURI, this);
304     } catch (Exception ex) {
305       ex.printStackTrace(Err.getPrintWriter());
306       //System.exit(2);
307     }
308   } // parseXmlDocument(java.lang.String xmlURI)
309 
310   /**
311     * Pop tag off of tag stack.
312     */
313   private void popTag() {
314     _vecTags.removeElementAt(_vecTags.size() - 1);
315   }
316 
317   /**
318     * Push tag onto tag stack.
319     * @param sTag java.lang.String
320     */
321   private void pushTag(String sTag) {
322     _vecTags.addElement(sTag);
323   }
324 
325   /**
326     * Return tag at top of tag stack. At any particular point in the parse,
327     * this string represents the tag being processed.
328     * @return java.lang.String
329     */
330   private String sCurrentTag() {
331     int iIndex = _vecTags.size() - 1;
332     if (iIndex >= 0) {
333       return (String)(_vecTags.elementAt(_vecTags.size() - 1));
334     } else {
335       return null;
336     }
337   } // sCurrentTag()
338 
339   /**
340     * startDocument method comment.
341     */
342   public void startDocument() throws org.xml.sax.SAXException {
343   }
344 
345   /**
346     * Call all start methods for this tag.
347     */
348   public void startElement (String uri, String qName, String sTag,
349                                                             Attributes alAttrs){
350 
351     int i;
352     String sStartMethodName = "start" + sTag;
353 
354     pushTag(sTag);
355 
356     // Call every tag start method for this tag found in the list of handlers.
357     for (i = 0; i < _vecHandlers.size(); i++) {
358       Object oThisHandler = _vecHandlers.elementAt(i);
359       Method mStartMethod = mFindMethod(
360                               oThisHandler, sStartMethodName, _caAttrList);
361       if (mStartMethod == null) {
362         mStartMethod = mFindMethod(oThisHandler, sStartMethodName, _caNoArgs);
363       }
364       if (mStartMethod != null) {
365 
366         try {
367           // Call start method with or without attribute list
368           Class[] caMethodArgs = mStartMethod.getParameterTypes();
369           if (caMethodArgs.length == 0) {
370             mStartMethod.invoke(oThisHandler, new Object[] {});
371           } else {
372             mStartMethod.invoke(oThisHandler, new Object[] {alAttrs});
373           }
374         } catch (InvocationTargetException ex) {
375           Err.println(ex);
376         } catch (IllegalAccessException ex) {
377           Err.println(ex);
378         }
379       }
380     }
381   } // startElement
382 
383   /**
384     * warning method comment.
385     */
386   public void warning(SAXParseException ex) throws SAXException {
387     _seh.warning(ex);
388   }
389 
390 } // class Lax
391