1 package net.sf.mvnflexreports;
2
3 import java.io.File;
4 import java.util.HashSet;
5 import java.util.List;
6 import java.util.Map;
7 import java.util.Set;
8
9 import org.apache.maven.doxia.sink.Sink;
10 import org.apache.maven.plugin.logging.Log;
11
12 import uk.co.badgersinfoil.metaas.dom.ASClassType;
13 import uk.co.badgersinfoil.metaas.dom.ASField;
14 import uk.co.badgersinfoil.metaas.dom.ASInterfaceType;
15 import uk.co.badgersinfoil.metaas.dom.ASMethod;
16 import uk.co.badgersinfoil.metaas.dom.ASType;
17 import uk.co.badgersinfoil.metaas.dom.Visibility;
18
19 /***
20 * @author Rémi Flament
21 *
22 */
23 public class ActionScriptUMLReportGenerator extends AbstractGraphvizMavenReportGenerator {
24
25 private String classFillColor;
26
27 private String interfaceFillColor;
28
29 private String mxmlFillColor;
30
31 private boolean showAttributesAndMethods = true;
32
33 private boolean showAssociations = true;
34
35 public void setShowAssociations(boolean showAssociations) {
36 this.showAssociations = showAssociations;
37 }
38
39 public void setShowAttributesAndMethods(boolean showAttributesAndMethods) {
40 this.showAttributesAndMethods = showAttributesAndMethods;
41 }
42
43 public ActionScriptUMLReportGenerator(Sink sink) {
44 this.sink = sink;
45 }
46
47 /***
48 * Method that returns the title
49 *
50 * @return a String that contains the title
51 */
52 private String getTitle() {
53 return "Actionscript UML Maven Report";
54 }
55
56 /***
57 * Method that generates the start
58 */
59 public void beginDocument() {
60 sink.head();
61 sink.title();
62 sink.text(getTitle());
63 sink.title_();
64 sink.head_();
65
66 sink.body();
67
68 sink.section1();
69 sink.sectionTitle1();
70 sink.text(getTitle());
71 sink.sectionTitle1_();
72
73 sink.paragraph();
74 sink.text(this.getTitle());
75 sink.link_();
76 sink.paragraph_();
77
78 }
79
80 @SuppressWarnings("unchecked")
81 private String generateGraphviz(List<ASType> asTypes) {
82
83 Set<String> names = new HashSet<String>();
84
85 for (ASType type : asTypes) {
86 names.add(type.getName());
87 }
88
89 StringBuilder builder = new StringBuilder();
90
91 builder.append("digraph application {\n");
92
93 builder.append(" rankdir=" + layout + "\n");
94 builder.append(" fontname = \"" + fontName + "\"\n");
95 builder.append(" fontsize = " + fontSize + "\n");
96 builder.append(" node [\n");
97 builder.append(" fontname = \"" + fontName + "\"\n");
98 builder.append(" fontsize = " + fontSize + "\n");
99 builder.append(" shape = Mrecord\n");
100 builder.append(" color = black\n");
101 builder.append(" style = filled\n");
102 builder.append(" fillcolor = " + classFillColor + "\n");
103 builder.append(" ]\n");
104 builder.append(" edge [\n");
105 builder.append(" fontname = \"" + fontName + "\"\n");
106 builder.append(" fontsize = " + fontSize + "\n");
107 builder.append(" ]\n");
108
109 for (ASType type : asTypes) {
110 builder.append(" " + type.getName() + " [\n");
111
112 if (type instanceof ASInterfaceType) {
113 builder.append(" fillcolor = " + interfaceFillColor + "\n");
114 } else {
115 List l = type.getMetaTagsWithName("MXML");
116 if (l != null && l.size() > 0) {
117 builder.append(" fillcolor = " + mxmlFillColor + "\n");
118 }
119 }
120
121 builder.append(" label = \"{");
122 if (type instanceof ASInterfaceType) {
123 builder.append("//<//<Interface//>//>//n");
124 }
125
126 List l = type.getMetaTagsWithName("RemoteClass");
127 if (l != null && l.size() > 0) {
128 builder.append("//<//<RemoteClass//>//>//n");
129 }
130
131 l = type.getMetaTagsWithName("MXML");
132 if (l != null && l.size() > 0) {
133 builder.append("//<//<MXML Component//>//>//n");
134 }
135
136 builder.append(type.getName());
137
138 if (showAttributesAndMethods) {
139 boolean firstMethod = true;
140
141 for (ASMethod method : (List<ASMethod>) type.getMethods()) {
142 if (firstMethod) {
143 builder.append("|");
144 firstMethod = false;
145 }
146 if (method.getVisibility() == Visibility.PUBLIC) {
147 builder.append("+ ");
148 } else if (method.getVisibility() == Visibility.PRIVATE) {
149 builder.append("- ");
150 }
151 builder.append(method.getName() + "() : " + method.getType());
152 builder.append("//l");
153 }
154
155 if (type instanceof ASClassType) {
156 ASClassType classType = (ASClassType) type;
157 boolean firstField = true;
158
159 for (ASField field : (List<ASField>) classType.getFields()) {
160 if (firstField) {
161 builder.append("|");
162 firstField = false;
163 }
164
165 if (field.getVisibility() == Visibility.PUBLIC) {
166 builder.append("+ ");
167 } else if (field.getVisibility() == Visibility.PRIVATE) {
168 builder.append("- ");
169 }
170 builder.append(field.getName() + " : " + field.getType());
171 builder.append("//l");
172 }
173
174 }
175 }
176
177 builder.append("}\"\n");
178 builder.append(" ]\n");
179 if (type instanceof ASClassType) {
180 ASClassType classType = (ASClassType) type;
181 if (classType.getSuperclass() != null) {
182 builder.append(" " + classType.getName() + " -> " + classType.getSuperclass() + " [arrowhead = \"empty\"];\n\n");
183 }
184
185 if (classType.getImplementedInterfaces() != null) {
186 for (String string : (List<String>) classType.getImplementedInterfaces()) {
187 builder.append(" " + classType.getName() + " -> " + string + " [arrowhead = \"empty\"];\n\n");
188 }
189 }
190 if (showAssociations) {
191 List<ASField> fields = classType.getFields();
192 for (ASField field : fields) {
193
194 if (names.contains(field.getType())) {
195 builder.append(" " + field.getType() + " -> " + type.getName() + " [arrowhead = \"none\" taillabel = \"0..1\"];\n");
196 }
197 }
198 }
199 }
200
201 }
202
203 builder.append("}\n");
204 return builder.toString();
205 }
206
207 /***
208 * Method that generates the contents
209 *
210 */
211 public void generate(File root, Map<String, List<ASType>> asTypes, List<ActionScriptParseError> actionScriptParseErrors, File outputDirectory, Log log) throws Exception {
212 beginDocument();
213
214 try {
215 sink.section2();
216 sink.sectionTitle2();
217 sink.text("Graphical view");
218 sink.sectionTitle2_();
219 sink.section2_();
220
221 for (Map.Entry<String, List<ASType>> entry : asTypes.entrySet()) {
222 sink.section3();
223 sink.sectionTitle3();
224 sink.text(entry.getKey().equals("") == false ? "Package " + entry.getKey() : "Root package");
225 sink.sectionTitle3_();
226 sink.section3_();
227 String text = this.generateGraphviz(entry.getValue());
228 invokeDot(text, "asuml-" + entry.getKey(), outputDirectory.getAbsolutePath(), log);
229 sink.lineBreak();
230 sink.rawText("<img src='images/asuml-" + entry.getKey() + ".png' />");
231 sink.lineBreak();
232 }
233
234 } catch (Exception e) {
235 log.error("Cannot generate graphical view !", e);
236 }
237
238 if (actionScriptParseErrors != null && actionScriptParseErrors.size() > 0) {
239 sink.section2();
240 sink.sectionTitle2();
241 sink.text("Parsing errors");
242 sink.sectionTitle2_();
243 sink.section2_();
244
245 sink.paragraph();
246 sink.table();
247 sink.tableRow();
248 sink.tableHeaderCell();
249 sink.text("Filename");
250 sink.tableHeaderCell_();
251 sink.tableHeaderCell();
252 sink.text("Error");
253 sink.tableHeaderCell_();
254
255 for (ActionScriptParseError actionScriptParseError : actionScriptParseErrors) {
256
257 sink.tableRow();
258 sink.tableCell();
259 sink.text(actionScriptParseError.getSourceFile().getPath().substring(root.getAbsolutePath().length() + 1));
260 sink.tableCell_();
261 sink.tableCell();
262 sink.text(actionScriptParseError.getError());
263 sink.tableCell_();
264 sink.tableRow_();
265
266 }
267 sink.table_();
268 sink.paragraph_();
269 }
270 sink.body_();
271 sink.flush();
272 sink.close();
273 }
274
275 public String getClassFillColor() {
276 return classFillColor;
277 }
278
279 public void setClassFillColor(String classFillColor) {
280 this.classFillColor = classFillColor;
281 }
282
283 public String getInterfaceFillColor() {
284 return interfaceFillColor;
285 }
286
287 public void setInterfaceFillColor(String interfaceFillColor) {
288 this.interfaceFillColor = interfaceFillColor;
289 }
290
291 public void setMxmlFillColor(String mxmlFillColor) {
292 this.mxmlFillColor = mxmlFillColor;
293 }
294
295 }