001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.camel.view;
018    
019    import java.io.PrintWriter;
020    import java.util.List;
021    import java.util.Map;
022    import java.util.Set;
023    
024    import org.apache.camel.model.FromDefinition;
025    import org.apache.camel.model.MulticastDefinition;
026    import org.apache.camel.model.ProcessorDefinition;
027    import org.apache.camel.model.RouteDefinition;
028    import static org.apache.camel.util.ObjectHelper.isEmpty;
029    import static org.apache.camel.util.StringHelper.xmlEncode;
030    
031    /**
032     * @version 
033     */
034    public class XmlGraphGenerator extends GraphGeneratorSupport {
035        private boolean addUrl = true;
036    
037        public XmlGraphGenerator(String dir) {
038            super(dir, ".xml");
039        }
040    
041        protected void generateFile(PrintWriter writer, Map<String, List<RouteDefinition>> map) {
042            writer.println("<?xml version='1.0' encoding='UTF-8'?>");
043            writer.println("<Graph>");
044            writer.println();
045    
046            if (map.size() > 0) {
047                writer.println("<Node id='root' name='Camel Routes' description='Collection of Camel Routes' nodeType='root'/>");
048            }
049            printRoutes(writer, map);
050    
051            writer.println();
052            writer.println("</Graph>");
053        }
054    
055        protected void printRoutes(PrintWriter writer, Map<String, List<RouteDefinition>> map) {
056            Set<Map.Entry<String, List<RouteDefinition>>> entries = map.entrySet();
057            for (Map.Entry<String, List<RouteDefinition>> entry : entries) {
058                String group = entry.getKey();
059                printRoutes(writer, group, entry.getValue());
060            }
061        }
062    
063        protected void printRoutes(PrintWriter writer, String group, List<RouteDefinition> routes) {
064            group = xmlEncode(group);
065            if (group != null) {
066                int idx = group.lastIndexOf('.');
067                String name = group;
068                if (idx > 0 && idx < group.length() - 1) {
069                    name = group.substring(idx + 1);
070                }
071                writer.println("<Node id='" + group + "' name='" + name + "' description='" + group + "' nodeType='group'/>");
072                writer.println("<Edge fromID='root' toID='" + group + "'/>");
073            }
074            for (RouteDefinition route : routes) {
075                List<FromDefinition> inputs = route.getInputs();
076                boolean first = true;
077                for (FromDefinition input : inputs) {
078                    NodeData nodeData = getNodeData(input);
079                    if (first) {
080                        first = false;
081                        if (group != null) {
082                            writer.println("<Edge fromID='" + group + "' toID='" + xmlEncode(nodeData.id) + "'/>");
083                        }
084                    }
085                    printRoute(writer, route, nodeData);
086                }
087                writer.println();
088            }
089        }
090    
091        protected void printRoute(PrintWriter writer, final RouteDefinition route, NodeData nodeData) {
092            printNode(writer, nodeData);
093    
094            NodeData from = nodeData;
095            for (ProcessorDefinition<?> output : route.getOutputs()) {
096                NodeData newData = printNode(writer, from, output);
097                from = newData;
098            }
099        }
100    
101        protected NodeData printNode(PrintWriter writer, NodeData fromData, ProcessorDefinition<?> node) {
102            if (node instanceof MulticastDefinition) {
103                // no need for a multicast node
104                List<ProcessorDefinition<?>> outputs = node.getOutputs();
105                for (ProcessorDefinition<?> output : outputs) {
106                    printNode(writer, fromData, output);
107                }
108                return fromData;
109            }
110            NodeData toData = getNodeData(node);
111    
112            printNode(writer, toData);
113    
114            if (fromData != null) {
115                writer.print("<Edge fromID=\"");
116                writer.print(xmlEncode(fromData.id));
117                writer.print("\" toID=\"");
118                writer.print(xmlEncode(toData.id));
119                String association = toData.edgeLabel;
120                if (isEmpty(association)) {
121                    writer.print("\" association=\"");
122                    writer.print(xmlEncode(association));
123                }
124                writer.println("\"/>");
125            }
126    
127            // now lets write any children
128            List<ProcessorDefinition<?>> outputs = toData.outputs;
129            if (outputs != null) {
130                for (ProcessorDefinition<?> output : outputs) {
131                    NodeData newData = printNode(writer, toData, output);
132                    if (!isMulticastNode(node)) {
133                        toData = newData;
134                    }
135                }
136            }
137            return toData;
138        }
139    
140        protected void printNode(PrintWriter writer, NodeData data) {
141            if (!data.nodeWritten) {
142                data.nodeWritten = true;
143    
144                writer.println();
145                writer.print("<Node id=\"");
146                writer.print(xmlEncode(data.id));
147                writer.print("\" name=\"");
148                String name = data.label;
149                if (isEmpty(name)) {
150                    name = data.tooltop;
151                }
152                writer.print(xmlEncode(name));
153                writer.print("\" nodeType=\"");
154                String nodeType = data.image;
155                if (isEmpty(nodeType)) {
156                    nodeType = data.shape;
157                    if (isEmpty(nodeType)) {
158                        nodeType = "node";
159                    }
160                }
161                writer.print(xmlEncode(nodeType));
162                writer.print("\" description=\"");
163                writer.print(xmlEncode(data.tooltop));
164                if (addUrl) {
165                    writer.print("\" url=\"");
166                    writer.print(xmlEncode(data.url));
167                }
168                writer.println("\"/>");
169            }
170        }
171    
172    }