PageRenderTime 98ms CodeModel.GetById 76ms app.highlight 18ms RepoModel.GetById 1ms 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
  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 */
 15package xml.parser;
 16
 17import java.util.HashMap;
 18import java.util.Stack;
 19
 20import javax.swing.text.Position;
 21import javax.swing.tree.DefaultMutableTreeNode;
 22
 23import org.gjt.sp.jedit.Buffer;
 24import org.gjt.sp.jedit.jEdit;
 25import org.gjt.sp.util.Log;
 26import org.xml.sax.Attributes;
 27import org.xml.sax.ContentHandler;
 28import org.xml.sax.Locator;
 29import org.xml.sax.SAXException;
 30import org.xml.sax.ext.DefaultHandler2;
 31
 32import xml.XmlParsedData;
 33
 34//{{{ Handler class
 35class ConstructTreeHandler extends DefaultHandler2 implements ContentHandler
 36{
 37    /**
 38	 * 
 39	 */
 40	private final XercesParserImpl xercesParserImpl;
 41
 42	// {{{ members
 43	Buffer buffer;
 44
 45	ErrorListErrorHandler errorHandler;
 46	CharSequence text;
 47	XmlParsedData data;
 48	
 49	HashMap<String, String> declaredPrefixes;
 50	Stack<DefaultMutableTreeNode> currentNodeStack;
 51	Locator loc;
 52	boolean empty;
 53
 54	/** used to install the locator in the resolver */
 55	private MyEntityResolver resolver;
 56	
 57	// }}}
 58	// {{{ Handler constructor
 59	ConstructTreeHandler(XercesParserImpl xercesParserImpl, Buffer buffer, CharSequence text, ErrorListErrorHandler errorHandler,
 60		XmlParsedData data, MyEntityResolver resolver)
 61	{
 62		this.xercesParserImpl = xercesParserImpl;
 63		this.buffer = buffer;
 64		this.text = text;
 65		this.errorHandler = errorHandler;
 66		this.data = data;
 67		this.currentNodeStack = new Stack<DefaultMutableTreeNode>();
 68		this.empty = true;
 69		this.resolver = resolver;
 70	} // }}}
 71
 72	//{{{ setDocumentLocator() method
 73	public void setDocumentLocator(Locator locator)
 74	{
 75		loc = locator;
 76		resolver.setDocumentLocator(locator);
 77	} //}}}
 78
 79	//{{{ startPrefixMapping() method
 80	public void startPrefixMapping(String prefix, String uri)
 81	{
 82		if(declaredPrefixes == null)declaredPrefixes = new HashMap<String,String>();
 83		declaredPrefixes.put(uri,prefix);
 84
 85		
 86	} //}}}
 87
 88
 89	//{{{ startElement() method
 90	public void startElement(String namespaceURI,
 91		String lName, // local name
 92		String qName, // qualified name
 93		Attributes attrs) throws SAXException
 94	{
 95		if(this.xercesParserImpl.stopped)
 96			throw new XercesParserImpl.StoppedException();
 97
 98		empty = true;
 99
100		String currentURI = xml.PathUtilities.urlToPath(loc.getSystemId());
101
102		// what do we do in this case?
103		if(loc.getLineNumber() == -1){
104			Log.log(Log.WARNING,XercesParserImpl.class,"no location for "+qName);
105			return;
106		}
107		
108		if(!buffer.getPath().equals(currentURI))
109			return;
110
111		buffer.readLock();
112
113		try
114		{
115			int line = Math.min(buffer.getLineCount() - 1,
116				loc.getLineNumber() - 1);
117			int column = loc.getColumnNumber() - 1;
118			int offset = Math.min(text.length() - 1,
119				buffer.getLineStartOffset(line)
120				+ column - 1);
121
122			offset = findTagStart(offset);
123			Position pos = buffer.createPosition(offset);
124
125			XmlTag newTag = createTag(qName, namespaceURI==null ? "" : namespaceURI, pos, attrs);
126			newTag.namespaceBindings = declaredPrefixes;
127			declaredPrefixes = null;
128			
129			DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(newTag);
130
131			if(!currentNodeStack.isEmpty())
132			{
133				DefaultMutableTreeNode node = (DefaultMutableTreeNode)
134					currentNodeStack.peek();
135
136				node.insert(newNode,node.getChildCount());
137			}
138			else
139				data.root.insert(newNode,0);
140
141			currentNodeStack.push(newNode);
142		}
143		finally
144		{
145			buffer.readUnlock();
146		}
147	} //}}}
148	
149	private XmlTag createTag(String qname, String namespaceURI, Position pos, Attributes attrs) {
150	    String tagClassName = jEdit.getProperty("xml.xmltag." + buffer.getMode().toString());
151	    if (tagClassName != null) {
152	        try {
153	            Class tagClass = Class.forName(tagClassName);
154	            java.lang.reflect.Constructor con = tagClass.getConstructor(String.class, String.class, Position.class, Attributes.class);
155	            return (XmlTag)con.newInstance(qname, namespaceURI, pos, attrs);
156	        }
157	        catch (Exception e) {
158	             // ignored, just return an XmlTag if this fails   
159	             e.printStackTrace();
160	        }
161	    }
162	    return new XmlTag(qname, namespaceURI, pos, attrs);   
163	}
164
165	//{{{ endElement() method
166	public void endElement(String namespaceURI,
167		String sName, // simple name
168		String qName  // qualified name
169		) throws SAXException
170	{
171		if(this.xercesParserImpl.stopped)
172			throw new XercesParserImpl.StoppedException();
173
174		if(!buffer.getPath().equals(xml.PathUtilities.urlToPath(loc.getSystemId())))
175			return;
176              
177		// what do we do in this case?
178		if(loc.getLineNumber() == -1)
179			return;
180
181		buffer.readLock();
182
183		try
184		{
185			DefaultMutableTreeNode node = (DefaultMutableTreeNode)
186				currentNodeStack.peek();
187			XmlTag tag = (XmlTag)node.getUserObject();
188			if(tag.getName().equals(qName))
189			{
190				int line = Math.min(buffer.getLineCount() - 1,
191					loc.getLineNumber() - 1);
192				int column = loc.getColumnNumber() - 1;
193				int offset = Math.min(buffer.getLength(),
194					buffer.getLineStartOffset(line)
195					+ column);
196
197				tag.setEnd(buffer.createPosition(offset));
198				tag.empty = empty;
199				currentNodeStack.pop();
200			}
201		}
202		finally
203		{
204			buffer.readUnlock();
205		}
206
207		empty = false;
208	} //}}}
209
210	//{{{ characters() method
211	public void characters (char ch[], int start, int length)
212		throws SAXException
213	{
214		if(this.xercesParserImpl.stopped)
215			throw new XercesParserImpl.StoppedException();
216
217		empty = false;
218		// currentNodeStack is empty for compound documents in the "root" document
219		// where text appears in nodes that are not kept in the Sidekick tree
220		// see test_data/compound_documents
221		if(!currentNodeStack.isEmpty()){
222			DefaultMutableTreeNode node = currentNodeStack.peek();
223			XmlTag tag = (XmlTag)node.getUserObject();
224			if (tag.canAddCharacters()) {
225				 char[] chBis = new char[length];
226				 System.arraycopy(ch,start,chBis,0,length);
227				 tag.addCharacters(chBis);   
228			}
229		}
230	} //}}}
231
232	
233	//{{{ findTagStart() method
234	private int findTagStart(int offset)
235	{
236		for(int i = offset; i >= 0; i--)
237		{
238			if(text.charAt(i) == '<')
239				return i;
240		}
241
242		return 0;
243	} //}}}
244
245}// }}}