View Javadoc

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