PageRenderTime 42ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/bundles/plugins-trunk/XML/xml/parser/ConstructTreeHandler.java

#
Java | 245 lines | 169 code | 42 blank | 34 comment | 20 complexity | dda4280062d678af2441a7fe8d8b4527 MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-1.0, Apache-2.0, LGPL-2.0, LGPL-3.0, GPL-2.0, CC-BY-SA-3.0, LGPL-2.1, GPL-3.0, MPL-2.0-no-copyleft-exception, IPL-1.0
  1. /*
  2. * ConstructTreeHandler.java - construcs the SideKick tree from SAX parser
  3. * :tabSize=8:indentSize=8:noTabs=false:
  4. * :folding=explicit:collapseFolds=1:
  5. *
  6. * Copyright (C) 2011 Eric Le Lay
  7. *
  8. * The XML plugin is licensed under the GNU General Public License, with
  9. * the following exception:
  10. *
  11. * "Permission is granted to link this code with software released under
  12. * the Apache license version 1.1, for example used by the Xerces XML
  13. * parser package."
  14. */
  15. package xml.parser;
  16. import java.util.HashMap;
  17. import java.util.Stack;
  18. import javax.swing.text.Position;
  19. import javax.swing.tree.DefaultMutableTreeNode;
  20. import org.gjt.sp.jedit.Buffer;
  21. import org.gjt.sp.jedit.jEdit;
  22. import org.gjt.sp.util.Log;
  23. import org.xml.sax.Attributes;
  24. import org.xml.sax.ContentHandler;
  25. import org.xml.sax.Locator;
  26. import org.xml.sax.SAXException;
  27. import org.xml.sax.ext.DefaultHandler2;
  28. import xml.XmlParsedData;
  29. //{{{ Handler class
  30. class ConstructTreeHandler extends DefaultHandler2 implements ContentHandler
  31. {
  32. /**
  33. *
  34. */
  35. private final XercesParserImpl xercesParserImpl;
  36. // {{{ members
  37. Buffer buffer;
  38. ErrorListErrorHandler errorHandler;
  39. CharSequence text;
  40. XmlParsedData data;
  41. HashMap<String, String> declaredPrefixes;
  42. Stack<DefaultMutableTreeNode> currentNodeStack;
  43. Locator loc;
  44. boolean empty;
  45. /** used to install the locator in the resolver */
  46. private MyEntityResolver resolver;
  47. // }}}
  48. // {{{ Handler constructor
  49. ConstructTreeHandler(XercesParserImpl xercesParserImpl, Buffer buffer, CharSequence text, ErrorListErrorHandler errorHandler,
  50. XmlParsedData data, MyEntityResolver resolver)
  51. {
  52. this.xercesParserImpl = xercesParserImpl;
  53. this.buffer = buffer;
  54. this.text = text;
  55. this.errorHandler = errorHandler;
  56. this.data = data;
  57. this.currentNodeStack = new Stack<DefaultMutableTreeNode>();
  58. this.empty = true;
  59. this.resolver = resolver;
  60. } // }}}
  61. //{{{ setDocumentLocator() method
  62. public void setDocumentLocator(Locator locator)
  63. {
  64. loc = locator;
  65. resolver.setDocumentLocator(locator);
  66. } //}}}
  67. //{{{ startPrefixMapping() method
  68. public void startPrefixMapping(String prefix, String uri)
  69. {
  70. if(declaredPrefixes == null)declaredPrefixes = new HashMap<String,String>();
  71. declaredPrefixes.put(uri,prefix);
  72. } //}}}
  73. //{{{ startElement() method
  74. public void startElement(String namespaceURI,
  75. String lName, // local name
  76. String qName, // qualified name
  77. Attributes attrs) throws SAXException
  78. {
  79. if(this.xercesParserImpl.stopped)
  80. throw new XercesParserImpl.StoppedException();
  81. empty = true;
  82. String currentURI = xml.PathUtilities.urlToPath(loc.getSystemId());
  83. // what do we do in this case?
  84. if(loc.getLineNumber() == -1){
  85. Log.log(Log.WARNING,XercesParserImpl.class,"no location for "+qName);
  86. return;
  87. }
  88. if(!buffer.getPath().equals(currentURI))
  89. return;
  90. buffer.readLock();
  91. try
  92. {
  93. int line = Math.min(buffer.getLineCount() - 1,
  94. loc.getLineNumber() - 1);
  95. int column = loc.getColumnNumber() - 1;
  96. int offset = Math.min(text.length() - 1,
  97. buffer.getLineStartOffset(line)
  98. + column - 1);
  99. offset = findTagStart(offset);
  100. Position pos = buffer.createPosition(offset);
  101. XmlTag newTag = createTag(qName, namespaceURI==null ? "" : namespaceURI, pos, attrs);
  102. newTag.namespaceBindings = declaredPrefixes;
  103. declaredPrefixes = null;
  104. DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(newTag);
  105. if(!currentNodeStack.isEmpty())
  106. {
  107. DefaultMutableTreeNode node = (DefaultMutableTreeNode)
  108. currentNodeStack.peek();
  109. node.insert(newNode,node.getChildCount());
  110. }
  111. else
  112. data.root.insert(newNode,0);
  113. currentNodeStack.push(newNode);
  114. }
  115. finally
  116. {
  117. buffer.readUnlock();
  118. }
  119. } //}}}
  120. private XmlTag createTag(String qname, String namespaceURI, Position pos, Attributes attrs) {
  121. String tagClassName = jEdit.getProperty("xml.xmltag." + buffer.getMode().toString());
  122. if (tagClassName != null) {
  123. try {
  124. Class tagClass = Class.forName(tagClassName);
  125. java.lang.reflect.Constructor con = tagClass.getConstructor(String.class, String.class, Position.class, Attributes.class);
  126. return (XmlTag)con.newInstance(qname, namespaceURI, pos, attrs);
  127. }
  128. catch (Exception e) {
  129. // ignored, just return an XmlTag if this fails
  130. e.printStackTrace();
  131. }
  132. }
  133. return new XmlTag(qname, namespaceURI, pos, attrs);
  134. }
  135. //{{{ endElement() method
  136. public void endElement(String namespaceURI,
  137. String sName, // simple name
  138. String qName // qualified name
  139. ) throws SAXException
  140. {
  141. if(this.xercesParserImpl.stopped)
  142. throw new XercesParserImpl.StoppedException();
  143. if(!buffer.getPath().equals(xml.PathUtilities.urlToPath(loc.getSystemId())))
  144. return;
  145. // what do we do in this case?
  146. if(loc.getLineNumber() == -1)
  147. return;
  148. buffer.readLock();
  149. try
  150. {
  151. DefaultMutableTreeNode node = (DefaultMutableTreeNode)
  152. currentNodeStack.peek();
  153. XmlTag tag = (XmlTag)node.getUserObject();
  154. if(tag.getName().equals(qName))
  155. {
  156. int line = Math.min(buffer.getLineCount() - 1,
  157. loc.getLineNumber() - 1);
  158. int column = loc.getColumnNumber() - 1;
  159. int offset = Math.min(buffer.getLength(),
  160. buffer.getLineStartOffset(line)
  161. + column);
  162. tag.setEnd(buffer.createPosition(offset));
  163. tag.empty = empty;
  164. currentNodeStack.pop();
  165. }
  166. }
  167. finally
  168. {
  169. buffer.readUnlock();
  170. }
  171. empty = false;
  172. } //}}}
  173. //{{{ characters() method
  174. public void characters (char ch[], int start, int length)
  175. throws SAXException
  176. {
  177. if(this.xercesParserImpl.stopped)
  178. throw new XercesParserImpl.StoppedException();
  179. empty = false;
  180. // currentNodeStack is empty for compound documents in the "root" document
  181. // where text appears in nodes that are not kept in the Sidekick tree
  182. // see test_data/compound_documents
  183. if(!currentNodeStack.isEmpty()){
  184. DefaultMutableTreeNode node = currentNodeStack.peek();
  185. XmlTag tag = (XmlTag)node.getUserObject();
  186. if (tag.canAddCharacters()) {
  187. char[] chBis = new char[length];
  188. System.arraycopy(ch,start,chBis,0,length);
  189. tag.addCharacters(chBis);
  190. }
  191. }
  192. } //}}}
  193. //{{{ findTagStart() method
  194. private int findTagStart(int offset)
  195. {
  196. for(int i = offset; i >= 0; i--)
  197. {
  198. if(text.charAt(i) == '<')
  199. return i;
  200. }
  201. return 0;
  202. } //}}}
  203. }// }}}