KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > xml > refactoring > ui > tree > GraphHelper


1 /*
2  * GraphHelper.java
3  *
4  * Created on January 29, 2007, 4:38 PM
5  *
6  * To change this template, choose Tools | Template Manager
7  * and open the template in the editor.
8  */

9
10 package org.netbeans.modules.xml.refactoring.ui.tree;
11
12 import java.awt.Color JavaDoc;
13 import java.awt.Image JavaDoc;
14 import java.beans.BeanInfo JavaDoc;
15 import java.text.MessageFormat JavaDoc;
16 import java.util.ArrayList JavaDoc;
17 import java.util.HashMap JavaDoc;
18 import java.util.Hashtable JavaDoc;
19 import java.util.Iterator JavaDoc;
20 import java.util.List JavaDoc;
21 import java.util.Map JavaDoc;
22 import javax.swing.ImageIcon JavaDoc;
23 import org.netbeans.api.project.Project;
24 import org.netbeans.api.project.SourceGroup;
25 import org.netbeans.modules.refactoring.api.RefactoringElement;
26 import org.netbeans.modules.refactoring.spi.RefactoringElementImplementation;
27 import org.netbeans.modules.refactoring.spi.ui.TreeElement;
28 import org.netbeans.modules.xml.nbprefuse.AnalysisConstants;
29 import org.netbeans.modules.xml.refactoring.FauxRefactoringElement;
30 import org.netbeans.modules.xml.refactoring.RefactoringManager;
31 import org.netbeans.modules.xml.refactoring.Usage;
32 import org.netbeans.modules.xml.refactoring.UsageGroup;
33 import org.netbeans.modules.xml.refactoring.spi.UIHelper;
34 import org.netbeans.modules.xml.refactoring.ui.readers.WhereUsedReader;
35 import org.netbeans.modules.xml.refactoring.ui.util.AnalysisUtilities;
36 import org.netbeans.modules.xml.xam.Component;
37 import org.netbeans.modules.xml.xam.Named;
38 import org.netbeans.modules.xml.xam.Referenceable;
39 import org.netbeans.modules.xml.xam.dom.DocumentModel;
40 import org.openide.filesystems.FileObject;
41 import org.openide.filesystems.FileUtil;
42 import org.openide.util.NbBundle;
43 import org.openide.util.Utilities;
44 import prefuse.data.Edge;
45 import prefuse.data.Graph;
46 import prefuse.data.Node;
47
48 /**
49  *
50  * @author Sonali
51  */

52 public class GraphHelper {
53     
54         private static final ImageIcon JavaDoc FIND_USAGES_ICON = new ImageIcon JavaDoc(
55             Utilities.loadImage(
56             "org/netbeans/modules/refactoring/api/resources/"+
57             "findusages.png"));
58     
59     public static final prefuse.data.Schema FIND_USAGES_NODES_SCHEMA =
60             new prefuse.data.Schema(); // prefuse graph schema
61
static {
62         FIND_USAGES_NODES_SCHEMA.addColumn(AnalysisConstants.LABEL,
63                 String JavaDoc.class, AnalysisConstants.EMPTY_STRING);
64         FIND_USAGES_NODES_SCHEMA.addColumn(AnalysisConstants.ID,
65                 String JavaDoc.class, AnalysisConstants.EMPTY_STRING);
66         FIND_USAGES_NODES_SCHEMA.addColumn(
67                 AnalysisConstants.COMPONENT_TYPE_NAME,
68                 String JavaDoc.class, AnalysisConstants.EMPTY_STRING);
69         FIND_USAGES_NODES_SCHEMA.addColumn(AnalysisConstants.ELEMENT_TYPE,
70                 String JavaDoc.class, AnalysisConstants.EMPTY_STRING);
71         // type of a GE, LE, GA, or LA
72

73         FIND_USAGES_NODES_SCHEMA.addColumn(AnalysisConstants.XML_FILENAME,
74                 String JavaDoc.class, AnalysisConstants.EMPTY_STRING);
75         FIND_USAGES_NODES_SCHEMA.addColumn(AnalysisConstants.FILE_OBJECT,
76                 FileObject.class);
77         FIND_USAGES_NODES_SCHEMA.addColumn(AnalysisConstants.FILE_TYPE,
78                 String JavaDoc.class, AnalysisConstants.EMPTY_STRING);
79         FIND_USAGES_NODES_SCHEMA.addColumn(AnalysisConstants.TOOLTIP,
80                 String JavaDoc.class, AnalysisConstants.EMPTY_STRING); // name
81
FIND_USAGES_NODES_SCHEMA.addColumn(AnalysisConstants.USER_OBJECT,
82                 Object JavaDoc.class);
83      // FIND_USAGES_NODES_SCHEMA.addColumn(AnalysisConstants.OPENIDE_NODE,
84
// org.openide.nodes.Node.class);
85
FIND_USAGES_NODES_SCHEMA.addColumn(AnalysisConstants.JAVA_AWT_IMAGE,
86                 Image JavaDoc.class);
87         FIND_USAGES_NODES_SCHEMA.addColumn(AnalysisConstants.REFACTORING_ELEMENT,
88                 RefactoringElement.class);
89         
90         // used to set node visible or not visible, depending on whether the
91
// file node is expanded or collapsed
92
// -1 = always visible, any other value matches a
93
// FILE_NODE_FILE_GROUP
94
// the file node itself has a FILE_GROUP of -1 because it is always
95
// visible
96
FIND_USAGES_NODES_SCHEMA.addColumn(AnalysisConstants.FILE_GROUP,
97                 int.class, -1);
98         // a File Node has a positive value for this column, other nodes
99
// have a -1 value
100
FIND_USAGES_NODES_SCHEMA.addColumn(
101                 AnalysisConstants.FILE_NODE_FILE_GROUP, int.class, -1);
102         // assigned number of schema file group
103

104         FIND_USAGES_NODES_SCHEMA.addColumn(AnalysisConstants.IS_PRIMITIVE,
105                 boolean.class, false); // is builtin type
106
FIND_USAGES_NODES_SCHEMA.addColumn(AnalysisConstants.IS_QUERY_NODE,
107                 boolean.class, false);
108         FIND_USAGES_NODES_SCHEMA.addColumn(AnalysisConstants.IS_USAGE_NODE,
109                 boolean.class, false);
110         FIND_USAGES_NODES_SCHEMA.addColumn(AnalysisConstants.IS_FILE_NODE,
111                 boolean.class, false);
112         FIND_USAGES_NODES_SCHEMA.addColumn(AnalysisConstants.IS_EXPANDED,
113                 boolean.class, false);
114         FIND_USAGES_NODES_SCHEMA.addColumn(AnalysisConstants.MOUSEOVER,
115                 boolean.class, false);
116     }
117     
118      public static final prefuse.data.Schema FIND_USAGES_EDGES_SCHEMA =
119             new prefuse.data.Schema(); // prefuse graph schema
120
static {
121         FIND_USAGES_EDGES_SCHEMA.addColumn(AnalysisConstants.LABEL,
122                 String JavaDoc.class, AnalysisConstants.EMPTY_STRING);
123         FIND_USAGES_EDGES_SCHEMA.addColumn(AnalysisConstants.EDGE_TYPE,
124                 String JavaDoc.class, AnalysisConstants.EMPTY_STRING);
125         // "file-edge-type" "generalization", "reference" "composition"
126

127         FIND_USAGES_EDGES_SCHEMA.addColumn(AnalysisConstants.TOOLTIP,
128                 String JavaDoc.class, AnalysisConstants.EMPTY_STRING);
129         // used to set edge visible or not visible, depending on whether the
130
// file node is expanded or collapsed
131
// -1 = always visible, any other value matches a
132
// FILE_NODE_FILE_GROUP
133
// the file node itself has a FILE_GROUP of -1 because it is
134
// always visible
135
FIND_USAGES_EDGES_SCHEMA.addColumn(AnalysisConstants.FILE_GROUP,
136                 int.class, -1);
137     }
138     
139     Graph graph;
140     Referenceable queryComponent;
141     boolean isPrimitive;
142     
143     /** Creates a new instance of GraphHelper */
144     public GraphHelper(Referenceable query) {
145         this.queryComponent = query;
146     }
147     
148     public Graph loadGraph(ArrayList JavaDoc<TreeElement> elements) {
149         graph = new Graph(true); // isDirected
150
graph.getNodeTable().addColumns(FIND_USAGES_NODES_SCHEMA);
151         graph.getEdgeTable().addColumns(FIND_USAGES_EDGES_SCHEMA);
152         
153         List JavaDoc componentsInGraph = new ArrayList JavaDoc();
154         List JavaDoc<FileObject> files = new ArrayList JavaDoc<FileObject>();
155         Map JavaDoc<FileObject, Node> fileNodes = new Hashtable JavaDoc<FileObject, Node>();
156         int fileGroupNumber = 0;
157         int usagesCount = 0;
158         
159         Node queryNode = createQueryNode(graph, queryComponent, getUIHelper(queryComponent), false,componentsInGraph, false, fileGroupNumber);
160         
161    
162          // *****************************
163
// *** FILE NODE
164
// *****************************
165
// create file node and attach it to the query node
166
for(int i =0; i < elements.size(); i++ ){
167       
168             TreeElement usageNode = elements.get(i);
169             
170             //get the RefactoringElement
171
RefactoringElement usageElement =(RefactoringElement)usageNode.getUserObject();
172             
173              //For the 0 usages case, we get a FauxTreeElement. Dont graph this map
174
//the only way of finding its a faux element is by looking at its composite object
175
if (usageElement.getComposite() instanceof Referenceable)
176                 break;
177             
178             //First lets create a file node
179
//one file node per file object
180

181             FileObject fo = usageElement.getParentFile();
182             Node parent = null;
183             if( !(files.contains(fo)) ) {
184                 Node fileNode = createFileNode(graph, queryComponent, fo, queryNode, ++fileGroupNumber);
185
186               // create a special edge from the file node to the query node
187
// that will be visible when the file node is collapsed
188
// This edge uses the default prefuse renderer, e.g.,
189
// a small solid arrow head
190
// When the file node is expanded, this edge will be
191
// hidden. See FindUsagesFocusControl (double click)
192
Edge fileEdge = graph.addEdge(fileNode,queryNode);
193                   fileEdge.setString(AnalysisConstants.EDGE_TYPE, AnalysisConstants.FILE_EDGE_TYPE);
194                   fileEdge.setInt(AnalysisConstants.FILE_GROUP, fileGroupNumber);
195
196                   files.add(fo);
197                   parent = fileNode;
198                   fileNodes.put(fo, fileNode);
199             } else {
200                 parent = fileNodes.get(fo);
201             }
202             
203             Node child = null;
204             TreeElement leaf = usageNode;
205             
206             while( (leaf.getParent(true)) instanceof TreeElement ) {
207                 Node pn = null;
208                 
209                 Object JavaDoc userObject = leaf.getUserObject();
210                 
211                 //we dont want to draw grap beyond the file unlike the Jtree that goes all the way to project
212
if( (userObject instanceof FileObject) ){
213                     break;
214                 }
215                 if(componentsInGraph.contains(userObject)){
216                     //there's already a node for this
217
pn= findDup(graph,userObject);
218                     assert pn !=null:"Cannot find node for User Object" + userObject;
219                 }
220                 
221                 if(pn == null){
222                     pn = createNode(leaf, graph, componentsInGraph, queryComponent, fileGroupNumber);
223                 }
224                 
225                 //// To find out if this tree element is a usage node, we would need to check if there's a corresponding
226
//// refactoring element. only leaf nodes have corresponding refactoring elements
227
AnalysisUtilities.ToolTipLine topLine = null;
228                 if(userObject instanceof RefactoringElement){
229                     pn.setBoolean(AnalysisConstants.IS_USAGE_NODE, true);
230                     pn.set(AnalysisConstants.REFACTORING_ELEMENT, (RefactoringElement)userObject);
231                     
232                     topLine = new AnalysisUtilities.ToolTipLine((MessageFormat.format(NbBundle.getMessage(WhereUsedReader.class, "LBL_Uses_Component"),
233                             new Object JavaDoc[] {queryNode.getString(AnalysisConstants.LABEL) })),
234                             100,
235                             Color.BLACK.getRGB(),
236                             AnalysisUtilities.ToolTipLine.
237                             HorizontalAlignment.CENTER);
238                     // Connect this usage node to the Query Node
239
// with the appropriate edge (composition or reference)
240
Object JavaDoc obj= ((RefactoringElement)userObject).getComposite();
241                      if(obj instanceof Usage)
242                          addApppropriateEdge(graph, pn, queryNode, fileGroupNumber,((Usage)obj).getType() );
243                      else
244                          addApppropriateEdge(graph, pn, queryNode, fileGroupNumber, null);
245                      
246                     child=pn;
247                     leaf = leaf.getParent(true);
248                     continue;
249                 }
250                 
251                   
252                AnalysisUtilities.ToolTipLine typeLine =
253                         new AnalysisUtilities.ToolTipLine(getCompTypeDisplayName(pn),
254                         100,
255                         Color.BLACK.getRGB(),
256                         AnalysisUtilities.ToolTipLine.
257                         HorizontalAlignment.CENTER);
258                 String JavaDoc toolTip = AnalysisUtilities.createHTMLToolTip(
259                         new AnalysisUtilities.ToolTipLine[] {topLine, typeLine});
260                 pn.setString(AnalysisConstants.TOOLTIP, toolTip);
261                 
262                 
263                 // connect it to its parent
264
addApppropriateEdge(graph, child, pn, fileGroupNumber, null);
265                 child = pn;
266                 leaf = leaf.getParent(true);
267             }
268             
269             //Connect last node to file node
270
addApppropriateEdge(graph, child, parent, fileGroupNumber, null);
271         }
272         
273         return graph;
274         
275     }
276     
277       
278    
279     
280     private static Node createQueryNode(Graph graph, Referenceable query, UIHelper uiHelper, boolean isPrimitive, List JavaDoc<Component> componentsInGraph,
281             boolean showOnlyDerivations, int fileGroupNumber ) {
282         
283         Node queryNode = null;
284         Component queryComponent = null;
285         if (query instanceof Component) {
286             queryComponent = (Component) query;
287         } else {
288             if (query instanceof DocumentModel) {
289                 queryComponent = ((DocumentModel) query).getRootComponent();
290             }
291         }
292         String JavaDoc name = "";
293         if (uiHelper == null){
294             if (query instanceof Named){
295                 name = ((Named)Named.class.cast(query)).getName();
296             }
297         } else {
298             name = uiHelper.getDisplayNode(queryComponent).getName();
299         }
300             
301             
302             queryNode = graph.addNode();
303             queryNode.setBoolean(AnalysisConstants.IS_PRIMITIVE, isPrimitive);
304             queryNode.setString(AnalysisConstants.LABEL, name);
305             queryNode.setString(AnalysisConstants.COMPONENT_TYPE_NAME, "" ); //NOI18N
306
queryNode.set(AnalysisConstants.USER_OBJECT, query );
307             queryNode.setInt(AnalysisConstants.FILE_GROUP, fileGroupNumber);
308             
309            
310             
311        // }
312

313         queryNode.setBoolean(AnalysisConstants.IS_QUERY_NODE, true);
314         // unset the FILE_GROUP because this node is always visible
315
queryNode.setInt(AnalysisConstants.FILE_GROUP,-1);
316         // reset IS_PRIMITIVE in case it is
317
queryNode.setBoolean(AnalysisConstants.IS_PRIMITIVE, isPrimitive);
318         
319         AnalysisUtilities.ToolTipLine topLine = new AnalysisUtilities.ToolTipLine((
320                 showOnlyDerivations?
321                     NbBundle.getMessage(WhereUsedReader.class,
322                 "LBL_Base_Complex_Type"):
323                     NbBundle.getMessage(WhereUsedReader.class,
324                 "LBL_Query_Component")),
325                 100,
326                 Color.BLACK.getRGB(),
327                 AnalysisUtilities.ToolTipLine.HorizontalAlignment.CENTER);
328         String JavaDoc compType = getCompTypeDisplayName(queryNode);
329         AnalysisUtilities.ToolTipLine typeLine = new AnalysisUtilities.ToolTipLine(
330                 compType,
331                 100,
332                 Color.BLACK.getRGB(),
333                 AnalysisUtilities.ToolTipLine.HorizontalAlignment.CENTER);
334         String JavaDoc toolTip = AnalysisUtilities.createHTMLToolTip(new AnalysisUtilities.ToolTipLine[] {
335             topLine, typeLine});
336         
337         queryNode.setString(AnalysisConstants.TOOLTIP, toolTip);
338         return queryNode;
339     }
340     
341      private static Node createNode(TreeElement displayNode, Graph graph, List JavaDoc componentsInGraph, Referenceable queryComponent, int fileGroupNumber){
342         Node n = graph.addNode();
343         
344         if(componentsInGraph !=null) {
345             componentsInGraph.add(displayNode.getUserObject());
346         }
347      
348         n.setBoolean(AnalysisConstants.IS_PRIMITIVE, false);
349         n.setString(AnalysisConstants.LABEL, displayNode.getText(true));
350         n.set(AnalysisConstants.USER_OBJECT,displayNode.getUserObject() );
351         n.setInt(AnalysisConstants.FILE_GROUP, fileGroupNumber);
352         n.set(AnalysisConstants.JAVA_AWT_IMAGE,( (ImageIcon JavaDoc)displayNode.getIcon()).getImage());
353         
354         return n;
355     }
356     
357     private static UIHelper getUIHelper(Referenceable component) {
358         return RefactoringManager.getInstance().getTargetComponentUIHelper(component);
359     }
360     
361     private static String JavaDoc getCompTypeDisplayName(final Node pn) {
362         String JavaDoc compType = null;
363         if (pn.canGetBoolean(AnalysisConstants.IS_PRIMITIVE) && pn.getBoolean(AnalysisConstants.IS_PRIMITIVE)){
364             compType = NbBundle.getMessage(WhereUsedReader.class, "LBL_Primitive_Type");
365         } else {
366             compType = pn.getString(AnalysisConstants.COMPONENT_TYPE_NAME);
367         }
368         return compType;
369     }
370     
371     /**
372      * Adds a Reference edge or Generalization edge from
373      * "from" node to the queryNode
374      * or adds composition edge if edgeType is null
375      *
376      */

377     private static void addApppropriateEdge(Graph graph, Node from, Node queryNode, int fileGroupNumber, Usage.Type edgeType){
378         Edge edge = graph.addEdge(from, queryNode);
379 // edge.setBoolean(AnalysisConstants.SHOW, isVisible);
380
edge.setInt(AnalysisConstants.FILE_GROUP, Integer.valueOf(fileGroupNumber));
381         if ( edgeType == Usage.Type.GENERALIZATION){
382             edge.setString(AnalysisConstants.EDGE_TYPE, AnalysisConstants.GENERALIZATION);
383         } else if ( edgeType == Usage.Type.REFERENCE){
384             edge.setString(AnalysisConstants.EDGE_TYPE,
385                     AnalysisConstants.REFERENCE);
386             from.setString(AnalysisConstants.LABEL,
387                     MessageFormat.format(NbBundle.getMessage(
388                     WhereUsedReader.class,
389                     "LBL_References_Ref"),
390                     new Object JavaDoc[]
391             {queryNode.getString(AnalysisConstants.LABEL)}));
392         } else {
393             edge.setString(AnalysisConstants.EDGE_TYPE, AnalysisConstants.COMPOSITION);
394         }
395     }
396     
397     private static Node createFileNode(Graph graph, Referenceable queryComp,
398             FileObject fobj, Node queryNode, int fileGroupNumber){
399         if (queryComp == null || fobj == null){
400             return null;
401         }
402         String JavaDoc fileType = AnalysisUtilities.getXmlFileType(fobj);
403         Node n = graph.addNode();
404         n.setString(AnalysisConstants.FILE_TYPE,fileType);
405         n.setInt(AnalysisConstants.FILE_NODE_FILE_GROUP, fileGroupNumber);
406         n.setBoolean(AnalysisConstants.IS_EXPANDED, false);
407         n.setBoolean(AnalysisConstants.IS_FILE_NODE, true);
408         n.set(AnalysisConstants.JAVA_AWT_IMAGE, AnalysisUtilities.getImage(fobj));
409         if (fobj != null){
410             n.setString(
411                     AnalysisConstants.LABEL, fobj.getName()+"."+fobj.getExt()); // NOI18N
412
n.setString(
413                     AnalysisConstants.XML_FILENAME,
414                     fobj.getName()+"."+fobj.getExt()); // NOI18N
415
n.set(AnalysisConstants.FILE_OBJECT, fobj);
416             
417             // "Schema file containing usages of XYZ"
418
AnalysisUtilities.ToolTipLine topLine = new AnalysisUtilities.ToolTipLine(
419                     MessageFormat.format(
420                     NbBundle.getMessage(WhereUsedReader.class,
421                     "LBL_Xml_File_With_Usages"),new Object JavaDoc[]{
422                 AnalysisUtilities.getXmlFileTypeDisplayName(fileType),
423                 queryNode.getString(AnalysisConstants.LABEL)}),
424                     100,
425                     Color.BLACK.getRGB(),
426                     AnalysisUtilities.ToolTipLine.HorizontalAlignment.CENTER);
427             AnalysisUtilities.ToolTipLine typeLine =
428                     new AnalysisUtilities.ToolTipLine(
429                     FileUtil.getFileDisplayName(fobj),
430                     100,
431                     Color.BLACK.getRGB(),
432                     AnalysisUtilities.ToolTipLine.HorizontalAlignment.CENTER);
433             String JavaDoc toolTip = AnalysisUtilities.createHTMLToolTip(
434                     new AnalysisUtilities.ToolTipLine[] {topLine, typeLine});
435             
436             n.setString(AnalysisConstants.TOOLTIP,
437                     toolTip);
438         }
439         return n;
440     }
441     
442     
443      private static Node findDup(Graph graph, Object JavaDoc sc){
444         Iterator JavaDoc it = graph.nodes();
445         while (it.hasNext()){
446             Node n= Node.class.cast(it.next());
447             Object JavaDoc nodeSC = n.get(AnalysisConstants.USER_OBJECT);
448             if ((n.canGetBoolean(AnalysisConstants.IS_FILE_NODE) && n.getBoolean(AnalysisConstants.IS_FILE_NODE) == false)&& nodeSC != null){
449                 if (nodeSC == sc){
450                     return n;
451                 }
452             }
453         }
454         return null;
455     }
456     
457 }
458
Popular Tags