/* * $Id$ * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.struts2.sitegraph.renderers; import com.opensymphony.xwork2.ActionChainResult; import com.opensymphony.xwork2.config.entities.ActionConfig; import com.opensymphony.xwork2.config.entities.ResultConfig; import org.apache.struts2.sitegraph.StrutsConfigRetriever; import org.apache.struts2.sitegraph.entities.Target; import org.apache.struts2.sitegraph.entities.View; import org.apache.struts2.sitegraph.model.*; import java.io.IOException; import java.io.Writer; import java.util.*; /** * Renders flow diagram to the console at info level */ public class DOTRenderer { private Writer writer; private List<TempLink> links = new ArrayList<TempLink>(); public DOTRenderer(Writer writer) { this.writer = writer; } public void render(String ns) { Graph graph = new Graph(); TreeMap<ViewNode, View> viewMap = new TreeMap<ViewNode, View>(new Comparator<ViewNode>() { public int compare(ViewNode v1, ViewNode v2) { return v1.getFullName().compareTo(v2.getFullName()); } }); Set<String> namespaces = StrutsConfigRetriever.getNamespaces(); for (String namespace : namespaces) { if (!namespace.startsWith(ns)) { continue; } SubGraph subGraph = graph.create(namespace); Set<String> actionNames = StrutsConfigRetriever.getActionNames(namespace); for (String actionName : actionNames) { ActionConfig actionConfig = StrutsConfigRetriever.getActionConfig(namespace, actionName); ActionNode action = new ActionNode(actionName); subGraph.addNode(action); Set<String> resultNames = actionConfig.getResults().keySet(); for (String resultName : resultNames) { ResultConfig resultConfig = actionConfig.getResults().get(resultName); String resultClassName = resultConfig.getClassName(); if (resultClassName.equals(ActionChainResult.class.getName())) { } else if (resultClassName.contains("Dispatcher") || resultClassName.contains("Velocity") || resultClassName.contains("Freemarker")) { if (resultConfig.getParams().get("location") == null) { continue; } String location = getViewLocation(resultConfig.getParams().get("location"), namespace); // FIXME: work with new configuration style if (location.endsWith("action")) { addTempLink(action, location, Link.TYPE_RESULT, resultConfig.getName()); } else { ViewNode view = new ViewNode(stripLocation(location)); subGraph.addNode(view); addTempLink(action, location, Link.TYPE_RESULT, resultConfig.getName()); View viewFile = getView(namespace, actionName, resultName, location); if (viewFile != null) { viewMap.put(view, viewFile); } } } else if (resultClassName.contains("Jasper")) { } else if (resultClassName.contains("XSLT")) { } else if (resultClassName.contains("Redirect")) { // check if the redirect is to an action -- if so, link it String locationConfig = resultConfig.getParams().get("location"); if (locationConfig == null) { locationConfig = resultConfig.getParams().get("actionName"); } String location = getViewLocation(locationConfig, namespace); // FIXME: work with new configuration style if (location.endsWith("action")) { addTempLink(action, location, Link.TYPE_REDIRECT, resultConfig.getName()); } else { ViewNode view = new ViewNode(stripLocation(location)); subGraph.addNode(view); addTempLink(action, location, Link.TYPE_REDIRECT, resultConfig.getName()); View viewFile = getView(namespace, actionName, resultName, location); if (viewFile != null) { viewMap.put(view, viewFile); } } } } } } // now look for links in the view for (Map.Entry<ViewNode, View> viewNodeViewEntry : viewMap.entrySet()) { ViewNode view = viewNodeViewEntry.getKey(); View viewFile = viewNodeViewEntry.getValue(); Set<Target> targets = viewFile.getTargets(); for (Target target : targets) { String viewTarget = target.getTarget(); addTempLink(view, viewTarget, target.getType(), ""); } } // finally, let's match up these links as real Link objects for (TempLink temp : links) { String location = temp.location; // FIXME: work with new configuration style if (location.endsWith("action")) { location = location.substring(0, location.indexOf("action") - 1); if (location.indexOf('!') != -1) { temp.label = temp.label + "\\n(" + location.substring(location.indexOf('!')) + ")"; location = location.substring(0, location.indexOf('!')); } } SiteGraphNode to = graph.findNode(location, temp.node); if (to != null) { graph.addLink(new Link(temp.node, to, temp.typeResult, temp.label)); } } try { //writer.write(graph.to_s(true)); graph.render(new IndentWriter(writer)); writer.flush(); writer.close(); } catch (IOException e) { e.printStackTrace(); } } private void addTempLink(SiteGraphNode node, String location, int type, String label) { links.add(new TempLink(node, location, type, label)); } private String stripLocation(String location) { return location.substring(location.lastIndexOf('/') + 1); } private View getView(String namespace, String actionName, String resultName, String location) { int type = View.TYPE_JSP; if (location.endsWith(".fm") || location.endsWith(".ftl")) { type = View.TYPE_FTL; } else if (location.endsWith(".vm")) { type = View.TYPE_VM; } return StrutsConfigRetriever.getView(namespace, actionName, resultName, type); } private String getViewLocation(String location, String namespace) { String view; if (!location.startsWith("/")) { view = namespace + "/" + location; } else { view = location; } if (view.indexOf('?') != -1) { view = view.substring(0, view.indexOf('?')); } return view; } class TempLink { SiteGraphNode node; String location; int typeResult; String label; public TempLink(SiteGraphNode node, String location, int typeResult, String label) { this.node = node; this.location = location; this.typeResult = typeResult; this.label = label; } public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof TempLink)) return false; final TempLink tempLink = (TempLink) o; if (typeResult != tempLink.typeResult) return false; if (label != null ? !label.equals(tempLink.label) : tempLink.label != null) return false; if (location != null ? !location.equals(tempLink.location) : tempLink.location != null) return false; if (node != null ? !node.equals(tempLink.node) : tempLink.node != null) return false; return true; } public int hashCode() { int result; result = (node != null ? node.hashCode() : 0); result = 29 * result + (location != null ? location.hashCode() : 0); result = 29 * result + typeResult; result = 29 * result + (label != null ? label.hashCode() : 0); return result; } } }