View Javadoc

1   /*
2    * $Id: DOTRenderer.java 651946 2008-04-27 13:41:38Z apetrelli $
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  package org.apache.struts2.sitegraph.renderers;
23  
24  import java.io.IOException;
25  import java.io.Writer;
26  import java.util.ArrayList;
27  import java.util.Comparator;
28  import java.util.Iterator;
29  import java.util.List;
30  import java.util.Map;
31  import java.util.Set;
32  import java.util.TreeMap;
33  
34  import org.apache.struts2.StrutsConstants;
35  import org.apache.struts2.sitegraph.StrutsConfigRetriever;
36  import org.apache.struts2.sitegraph.entities.Target;
37  import org.apache.struts2.sitegraph.entities.View;
38  import org.apache.struts2.sitegraph.model.ActionNode;
39  import org.apache.struts2.sitegraph.model.Graph;
40  import org.apache.struts2.sitegraph.model.IndentWriter;
41  import org.apache.struts2.sitegraph.model.Link;
42  import org.apache.struts2.sitegraph.model.SiteGraphNode;
43  import org.apache.struts2.sitegraph.model.SubGraph;
44  import org.apache.struts2.sitegraph.model.ViewNode;
45  
46  import com.opensymphony.xwork2.ActionChainResult;
47  import com.opensymphony.xwork2.config.entities.ActionConfig;
48  import com.opensymphony.xwork2.config.entities.ResultConfig;
49  
50  /***
51   * Renders flow diagram to the console at info level
52   */
53  public class DOTRenderer {
54  
55      private Writer writer;
56      private List links = new ArrayList();
57  
58      public DOTRenderer(Writer writer) {
59          this.writer = writer;
60      }
61  
62      public void render(String ns) {
63          Graph graph = new Graph();
64  
65          TreeMap viewMap = new TreeMap(new Comparator() {
66              public int compare(Object o1, Object o2) {
67                  ViewNode v1 = (ViewNode) o1;
68                  ViewNode v2 = (ViewNode) o2;
69  
70                  return v1.getFullName().compareTo(v2.getFullName());
71              }
72          });
73  
74          Set namespaces = StrutsConfigRetriever.getNamespaces();
75          for (Iterator iter = namespaces.iterator(); iter.hasNext();) {
76              String namespace = (String) iter.next();
77  
78              if (!namespace.startsWith(ns)) {
79                  continue;
80              }
81  
82              SubGraph subGraph = graph.create(namespace);
83  
84              Set actionNames = StrutsConfigRetriever.getActionNames(namespace);
85              for (Iterator iterator = actionNames.iterator(); iterator.hasNext();) {
86                  String actionName = (String) iterator.next();
87                  ActionConfig actionConfig = StrutsConfigRetriever.getActionConfig(namespace,
88                          actionName);
89  
90                  ActionNode action = new ActionNode(actionName);
91                  subGraph.addNode(action);
92  
93                  Set resultNames = actionConfig.getResults().keySet();
94                  for (Iterator iterator2 = resultNames.iterator(); iterator2.hasNext();) {
95                      String resultName = (String) iterator2.next();
96                      ResultConfig resultConfig = ((ResultConfig) actionConfig.getResults().get(resultName));
97                      String resultClassName = resultConfig.getClassName();
98  
99                      if (resultClassName.equals(ActionChainResult.class.getName())) {
100 
101                     } else if (resultClassName.indexOf("Dispatcher") != -1
102                             || resultClassName.indexOf("Velocity") != -1
103                             || resultClassName.indexOf("Freemarker") != -1) {
104                         if (resultConfig.getParams().get("location") == null) {
105                             continue;
106                         }
107 
108                         String location = getViewLocation((String) resultConfig.getParams().get("location"), namespace);
109                         //  FIXME: work with new configuration style                        
110                         if (location.endsWith("action")) {
111                             addTempLink(action, location, Link.TYPE_RESULT, resultConfig.getName());
112                         } else {
113                             ViewNode view = new ViewNode(stripLocation(location));
114                             subGraph.addNode(view);
115 
116                             addTempLink(action, location, Link.TYPE_RESULT, resultConfig.getName());
117 
118                             View viewFile = getView(namespace, actionName, resultName, location);
119                             if (viewFile != null) {
120                                 viewMap.put(view, viewFile);
121                             }
122                         }
123                     } else if (resultClassName.indexOf("Jasper") != -1) {
124 
125                     } else if (resultClassName.indexOf("XSLT") != -1) {
126 
127                     } else if (resultClassName.indexOf("Redirect") != -1) {
128                         // check if the redirect is to an action -- if so, link it
129                         String locationConfig = (String) resultConfig.getParams().get("location");
130                         if (locationConfig == null) {
131                             locationConfig = (String) resultConfig.getParams().get("actionName");
132                         }
133                         String location = getViewLocation(locationConfig, namespace);
134                         //  FIXME: work with new configuration style
135                         if (location.endsWith("action")) {
136                             addTempLink(action, location, Link.TYPE_REDIRECT, resultConfig.getName());
137                         } else {
138                             ViewNode view = new ViewNode(stripLocation(location));
139                             subGraph.addNode(view);
140 
141                             addTempLink(action, location, Link.TYPE_REDIRECT, resultConfig.getName());
142 
143                             View viewFile = getView(namespace, actionName, resultName, location);
144                             if (viewFile != null) {
145                                 viewMap.put(view, viewFile);
146                             }
147                         }
148                     }
149                 }
150             }
151         }
152 
153         // now look for links in the view
154         for (Iterator iterator = viewMap.entrySet().iterator(); iterator.hasNext();) {
155             Map.Entry entry = (Map.Entry) iterator.next();
156             ViewNode view = (ViewNode) entry.getKey();
157             View viewFile = (View) entry.getValue();
158             Set targets = viewFile.getTargets();
159             for (Iterator iterator1 = targets.iterator(); iterator1.hasNext();) {
160                 Target target = (Target) iterator1.next();
161                 String viewTarget = target.getTarget();
162                 addTempLink(view, viewTarget, target.getType(), "");
163             }
164         }
165 
166         // finally, let's match up these links as real Link objects
167         for (Iterator iterator = links.iterator(); iterator.hasNext();) {
168             TempLink temp = (TempLink) iterator.next();
169             String location = temp.location;
170             
171             // FIXME: work with new configuration style
172             if (location.endsWith("action")) {
173                 location = location.substring(0, location.indexOf("action") - 1);
174 
175                 if (location.indexOf('!') != -1) {
176                     temp.label = temp.label + "//n(" + location.substring(location.indexOf('!')) + ")";
177                     location = location.substring(0, location.indexOf('!'));
178                 }
179             }
180             SiteGraphNode to = graph.findNode(location, temp.node);
181             if (to != null) {
182                 graph.addLink(new Link(temp.node, to, temp.typeResult, temp.label));
183             }
184         }
185 
186         try {
187             //writer.write(graph.to_s(true));
188             graph.render(new IndentWriter(writer));
189             writer.flush();
190             writer.close();
191         } catch (IOException e) {
192             e.printStackTrace();
193         }
194     }
195 
196     private void addTempLink(SiteGraphNode node, String location, int type, String label) {
197         links.add(new TempLink(node, location, type, label));
198     }
199 
200     private String stripLocation(String location) {
201         return location.substring(location.lastIndexOf('/') + 1);
202     }
203 
204     private View getView(String namespace, String actionName, String resultName, String location) {
205         int type = View.TYPE_JSP;
206         if (location.endsWith(".fm") || location.endsWith(".ftl")) {
207             type = View.TYPE_FTL;
208         } else if (location.endsWith(".vm")) {
209             type = View.TYPE_VM;
210         }
211         return StrutsConfigRetriever.getView(namespace, actionName, resultName, type);
212     }
213 
214     private String getViewLocation(String location, String namespace) {
215         String view = null;
216         if (!location.startsWith("/")) {
217             view = namespace + "/" + location;
218         } else {
219             view = location;
220         }
221 
222         if (view.indexOf('?') != -1) {
223             view = view.substring(0, view.indexOf('?'));
224         }
225 
226         return view;
227     }
228 
229     class TempLink {
230         SiteGraphNode node;
231         String location;
232         int typeResult;
233         String label;
234 
235         public TempLink(SiteGraphNode node, String location, int typeResult, String label) {
236             this.node = node;
237             this.location = location;
238             this.typeResult = typeResult;
239             this.label = label;
240         }
241 
242         public boolean equals(Object o) {
243             if (this == o) return true;
244             if (!(o instanceof TempLink)) return false;
245 
246             final TempLink tempLink = (TempLink) o;
247 
248             if (typeResult != tempLink.typeResult) return false;
249             if (label != null ? !label.equals(tempLink.label) : tempLink.label != null) return false;
250             if (location != null ? !location.equals(tempLink.location) : tempLink.location != null) return false;
251             if (node != null ? !node.equals(tempLink.node) : tempLink.node != null) return false;
252 
253             return true;
254         }
255 
256         public int hashCode() {
257             int result;
258             result = (node != null ? node.hashCode() : 0);
259             result = 29 * result + (location != null ? location.hashCode() : 0);
260             result = 29 * result + typeResult;
261             result = 29 * result + (label != null ? label.hashCode() : 0);
262             return result;
263         }
264     }
265 }