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 }