View Javadoc

1   /*
2    * $Id: OASTHandler.java,v 1.18 2005/05/31 23:28:07 jlerner Exp $
3    *
4    * Copyright (c) 1999-2004, BBN Technologies, LLC.
5    * All rights reserved.
6    * http://www.daml.org/legal/opensource/bbn_license.html
7    */
8   package com.bbn.swede.core.dom;
9   
10  import org.xml.sax.Attributes;
11  import org.xml.sax.Locator;
12  import org.xml.sax.SAXException;
13  import org.xml.sax.helpers.DefaultHandler;
14  
15  import com.bbn.swede.core.OWLCore;
16  
17  /***
18   * SAX2 event handler for parsing an OWL file into an OAST.
19   * @author jlerner
20   */
21  public class OASTHandler extends DefaultHandler
22  {
23     /***
24      * Called after CDATA is parsed to set the literal node's location.  The
25      * default implementation does nothing, so nodes will have to be located
26      * en masse after the parse is complete.
27      * @param parent The parent of the node to locate
28      * @param lit The literal node to locate
29      */
30     protected void locateNode(OASTNode parent, Literal lit)
31     {
32     };
33     /***
34      * Called after an attribute is parsed to set its location.  The
35      * default implementation does nothing, so nodes will have to be located
36      * en masse after the parse is complete.
37      * @param parent The parent of the node to locate
38      * @param node The attribute node to locate
39      */
40     protected void locateNode(OASTNode parent, AttributeNode node)
41     {
42     };
43     /***
44      * Called after an open tag is parsed to set the tag node's start offset.  
45      * The default implementation does nothing, so nodes will have to be located
46      * en masse after the parse is complete.
47      * @param node The tag node to locate
48      */
49     protected void locateNodeBegin(OASTNode node)
50     {
51     };
52     /***
53      * Called after a close tag is parsed to set the tag node's length.  
54      * The default implementation does nothing, so nodes will have to be located
55      * en masse after the parse is complete.
56      * @param node The tag node to locate
57      */
58     protected void locateNodeEnd(OASTNode node)
59     {
60     };
61     /***
62      * Called at the beginning of the parse to set the size and position of the 
63      * root element for the parse.  The default implementation does nothing, 
64      * so nodes will have to be located en masse after the parse is complete.
65      * @param root The root node
66      */
67     protected void locateRootNode(OASTNode root)
68     {
69     };
70  
71     /***
72      * The root node of the parse.
73      */
74     protected OASTNode _root;
75     /***
76      * The node currently being handled.
77      */
78     protected OASTNode _nodeCurrent;
79     /***
80      * Creates an OASTHandler.
81      * @param root The node to treat as the document root
82      */
83     public OASTHandler(OASTNode root)
84     {
85        _root = root;
86        _nodeCurrent = root;
87     }
88  
89     /***
90      * Cleans up resources used by the handler.
91      */
92     public void dispose()
93     {
94     }
95  
96     private Locator _locator;
97     /*
98      *  (non-Javadoc)
99      * @see org.xml.sax.ContentHandler#setDocumentLocator(org.xml.sax.Locator)
100     */
101    public void setDocumentLocator(Locator locator)
102    {
103       super.setDocumentLocator(locator);
104       _locator = locator;
105    }
106 
107    /*
108     *  (non-Javadoc)
109     * @see org.xml.sax.ContentHandler#endElement(java.lang.String, java.lang.String, java.lang.String)
110     */
111    public void endElement(String uri, String localName, String qName)
112       throws SAXException
113    {
114       super.endElement(uri, localName, qName);
115       if (OASTNode.match(qName, _nodeCurrent.getNodeType()))
116       {
117          locateNodeEnd(_nodeCurrent);
118 
119          _nodeCurrent = _nodeCurrent.getParent();
120       }
121    }
122 
123    /*
124     *  (non-Javadoc)
125     * @see org.xml.sax.ContentHandler#startElement(java.lang.String, 
126     *       java.lang.String, java.lang.String, org.xml.sax.Attributes)
127     */
128    public void startElement(
129       String uri,
130       String localName,
131       String qName,
132       Attributes attributes)
133       throws SAXException
134    {
135       super.startElement(uri, localName, qName, attributes);
136       OASTNode node = null;
137       node = _nodeCurrent.createChild(qName);
138       if (node != null)
139       {
140          _nodeCurrent = node;
141 
142          locateNodeBegin(_nodeCurrent);
143          processAttributes(_nodeCurrent, attributes);
144       }
145    }
146 
147    /***
148     * Helper method for parsing the attributes found for a begin tag.  Each
149     * individual attribute in the collection is added to the OAST as an
150     * attribute node, with the begin tag node as its parent.
151     * @param parent The begin tag node
152     * @param attributes The collection of attributes associated with the begin
153     *                   tag.
154     */
155    protected void processAttributes(OASTNode parent, Attributes attributes)
156    {
157       for (int i = 0; i < attributes.getLength(); i++)
158       {
159          String sQName = attributes.getQName(i);
160          String sValue = attributes.getValue(i);
161          AttributeNode nodeAttrib = parent.createChildAttribute(sQName, sValue);
162          if (nodeAttrib == null)
163          {
164             continue;
165          }
166          locateNode(parent, nodeAttrib);
167       }
168    }
169 
170    /*
171     *  (non-Javadoc)
172     * @see org.xml.sax.ContentHandler#characters(char[], int, int)
173     */
174    public void characters(char[] ch, int start, int length) throws SAXException
175    {
176       super.characters(ch, start, length);
177       String s = new String(ch, start, length);
178       if (s.trim().length() == 0)
179       {
180          return;
181       }
182       OASTNode[] children = _nodeCurrent.getChildren();
183       if (children.length > 0)
184       {
185          OASTNode lastChild = children[children.length - 1];
186          if (lastChild instanceof Literal)
187          {
188             //lastChild should already have been expanded to encompass the
189             //entire CDATA section being processed here, so just ignore the
190             //characters now being processed.  This is a workaround for the
191             //problem where SAX likes to tell you about the first 40 characters
192             //of CDATA and then any additional characters beyond that with two
193             //separate calls for no good reason.
194             return;
195          }
196       }
197       Literal l = new Literal(s);
198       _nodeCurrent.appendChild(l);
199       OASTNode nodePrev = _nodeCurrent.getPreviousChild(l);
200       if (nodePrev != null && nodePrev instanceof Literal)
201       {
202          Literal lit = (Literal) nodePrev;
203          try
204          {
205             lit.setText(lit.getText() + l.getText());
206             _nodeCurrent.remove(l, false);
207          }
208          catch (OASTException e)
209          {
210             OWLCore.logError(OWLCore.getID(), "Error merging literals during parse", e);
211          }
212       }
213       locateNode(_nodeCurrent, l);
214    }
215 
216    /*
217     *  (non-Javadoc)
218     * @see org.xml.sax.ContentHandler#startDocument()
219     */
220    public void startDocument() throws SAXException
221    {
222       super.startDocument();
223       locateRootNode(_root);
224    }
225 
226 }