View Javadoc

1   /**
2    * BSD-style license; for more info see http://pmd.sourceforge.net/license.html
3    */
4   package net.sourceforge.pmd.util.viewer.model;
5   
6   import java.io.StringReader;
7   import java.util.ArrayList;
8   import java.util.List;
9   import java.util.logging.Logger;
10  
11  import net.sourceforge.pmd.lang.LanguageVersion;
12  import net.sourceforge.pmd.lang.LanguageVersionHandler;
13  import net.sourceforge.pmd.lang.ast.Node;
14  import net.sourceforge.pmd.lang.ast.ParseException;
15  import net.sourceforge.pmd.lang.ast.xpath.DocumentNavigator;
16  
17  import org.jaxen.BaseXPath;
18  import org.jaxen.JaxenException;
19  import org.jaxen.XPath;
20  
21  public class ViewerModel {
22      private final static Logger LOGGER = Logger.getLogger(ViewerModel.class.getName()); 
23  
24      private List<ViewerModelListener> listeners;
25      private Node rootNode;
26      private List<Node> evaluationResults;
27  
28      public ViewerModel() {
29  	listeners = new ArrayList<ViewerModelListener>(5);
30      }
31  
32      public Node getRootNode() {
33  	return rootNode;
34      }
35  
36      /**
37       * commits source code to the model.
38       * all existing source will be replaced
39       */
40      public void commitSource(String source, LanguageVersion languageVersion) {
41  	LanguageVersionHandler languageVersionHandler = languageVersion.getLanguageVersionHandler();
42  	Node node =  languageVersionHandler
43  		.getParser(languageVersionHandler.getDefaultParserOptions()).parse(null, new StringReader(source));
44  	rootNode = node;
45  	fireViewerModelEvent(new ViewerModelEvent(this, ViewerModelEvent.CODE_RECOMPILED));
46      }
47  
48      /**
49       * determines whether the model has a compiled tree at it's disposal
50       *
51       * @return true if there is an AST, false otherwise
52       */
53      public boolean hasCompiledTree() {
54  	return rootNode != null;
55      }
56  
57      /**
58       * evaluates the given XPath expression against the current tree
59       *
60       * @param xPath     XPath expression to be evaluated
61       * @param evaluator object which requests the evaluation
62       */
63      public void evaluateXPathExpression(String xPath, Object evaluator) throws ParseException, JaxenException {
64  	try 
65  	{
66  	LOGGER.finest("xPath="+xPath);
67  	LOGGER.finest("evaluator="+evaluator);
68  	XPath xpath = new BaseXPath(xPath, new DocumentNavigator());
69  	LOGGER.finest("xpath="+xpath);
70  	LOGGER.finest("rootNode="+rootNode);
71  	try
72  	{
73  		evaluationResults = xpath.selectNodes(rootNode);
74  	}
75  	catch (Exception e)
76  	{
77  		LOGGER.finest("selectNodes problem:");
78  		e.printStackTrace(System.err);
79  	}
80  	LOGGER.finest("evaluationResults="+evaluationResults);
81  	fireViewerModelEvent(new ViewerModelEvent(evaluator, ViewerModelEvent.PATH_EXPRESSION_EVALUATED));
82  	}
83  	catch (JaxenException je)
84  	{
85  	 je.printStackTrace(System.err);
86           throw je;
87  	}
88      }
89  
90      /**
91       * retrieves the results of last evaluation
92       *
93       * @return a list containing the nodes selected by the last XPath expression
94       *         <p/>
95       *         evaluation
96       */
97      public List<Node> getLastEvaluationResults() {
98  	return evaluationResults;
99      }
100 
101     /**
102      * selects the given node in the AST
103      *
104      * @param node     node to be selected
105      * @param selector object which requests the selection
106      */
107     public void selectNode(Node node, Object selector) {
108 	fireViewerModelEvent(new ViewerModelEvent(selector, ViewerModelEvent.NODE_SELECTED, node));
109     }
110 
111     /**
112      * appends the given fragment to the XPath expression
113      *
114      * @param pathFragment fragment to be added
115      * @param appender     object that is trying to append the fragment
116      */
117     public void appendToXPathExpression(String pathFragment, Object appender) {
118 	fireViewerModelEvent(new ViewerModelEvent(appender, ViewerModelEvent.PATH_EXPRESSION_APPENDED, pathFragment));
119     }
120 
121     public void addViewerModelListener(ViewerModelListener l) {
122 	listeners.add(l);
123     }
124 
125     public void removeViewerModelListener(ViewerModelListener l) {
126 	listeners.remove(l);
127     }
128 
129     protected void fireViewerModelEvent(ViewerModelEvent e) {
130 	for (int i = 0; i < listeners.size(); i++) {
131 	    listeners.get(i).viewerModelChanged(e);
132 	}
133     }
134 }