1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.student.contract.model.util;
17
18 import java.util.HashSet;
19 import java.util.LinkedHashSet;
20 import java.util.Set;
21
22 import org.kuali.student.contract.model.MessageStructure;
23 import org.kuali.student.contract.model.ServiceContractModel;
24 import org.kuali.student.contract.model.ServiceMethod;
25 import org.kuali.student.contract.model.ServiceMethodParameter;
26 import org.kuali.student.contract.model.XmlType;
27 import org.kuali.student.contract.writer.HtmlWriter;
28
29
30
31
32
33 public class HtmlContractMessageStructureWriter {
34
35 private XmlType xmlType;
36 private HtmlWriter writer;
37 private ServiceContractModel model;
38 private ModelFinder finder;
39
40 public HtmlContractMessageStructureWriter(XmlType xmlType, String directory,
41 ServiceContractModel model) {
42 this.xmlType = xmlType;
43 this.writer = new HtmlWriter(directory, xmlType.getName() + ".html",
44 xmlType.getName());
45 this.model = model;
46 this.finder = new ModelFinder(this.model);
47 }
48
49 private String initUpper(String str) {
50 if (str == null) {
51 return null;
52 }
53 if (str.length() == 0) {
54 return str;
55 }
56 if (str.length() == 1) {
57 return str.toUpperCase();
58 }
59 return str.substring(0, 1).toUpperCase() + str.substring(1);
60 }
61
62 private boolean isMainMessageStructure(XmlType xmlType) {
63 if (!HtmlContractMessageStructureWriter.calcOtherXmlTypeUsages(model,
64 xmlType).isEmpty()) {
65 return false;
66 }
67 return true;
68 }
69
70 public void write() {
71 writer.println("<a href=\"index.html\">home</a>");
72 if (this.isMainMessageStructure(xmlType)) {
73 writer.println("<a href=\"../dictionarydocs/" + initUpper(xmlType.getName()) + ".html\">dictionary doc</a>");
74 }
75 this.writeStyleSheet();
76 writer.writeTag("h1", xmlType.getName());
77
78 writer.indentPrintln("<table id=\"structureMetaTable\">");
79 writer.indentPrintln("<tr>");
80 writer.writeTag("th", "class=h", "Name");
81 writer.writeTag("td", "id=structureName colspan=2", xmlType.getName());
82 writer.indentPrintln("</tr>");
83
84
85
86
87 writer.indentPrintln("<tr>");
88 writer.writeTag("th", "rowspan=3 class=h", "Usage");
89 writer.indentPrint("<td id=\"structureVersion\" colspan=2>");
90 for (String servKey : xmlType.getService().split(",")) {
91 writer.indentPrintln("<a href=\"" + servKey + "Service" + ".html" + "\">"
92 + servKey + "Service" + "</a>");
93 }
94 writer.indentPrint("</td>");
95
96 writer.indentPrintln("</tr>");
97 writer.indentPrintln("<tr>");
98 writer.writeTag("th", "class=h", "");
99 writer.indentPrint("<td id=\"structureVersion\" colspan=2>");
100 for (ServiceMethod method : this.calcUsageByMethods(xmlType)) {
101 writer.indentPrintln("<a href=\"" + method.getService() + "Service"
102 + ".html" + "#" + method.getService() + "-"
103 + method.getName() + "\">"
104 + method.getName() + "</a>");
105 }
106 writer.indentPrint("</td>");
107 writer.indentPrintln("</tr>");
108 writer.indentPrintln("<tr>");
109 writer.writeTag("th", "class=h", "");
110 writer.indentPrint("<td id=\"structureVersion\" colspan=2>");
111 for (String xmlTypeName : this.calcOtherXmlTypeUsages(xmlType)) {
112 XmlType usageType = finder.findXmlType(xmlTypeName);
113 if (usageType == null) {
114 throw new NullPointerException("Coud not find XmlType with name="
115 + xmlTypeName);
116 }
117 writer.indentPrintln("<a href=\"" + usageType.getName() + ".html" + "\">"
118 + usageType.getName() + "</a>");
119 }
120 writer.indentPrint("</td>");
121 writer.indentPrintln("</tr>");
122
123 writer.writeTag("th", "class=h", "Type");
124 writer.writeTag("td", "id=structureVersion colspan=2",
125 xmlType.getPrimitive());
126 writer.indentPrintln("</tr>");
127 writer.indentPrintln("</table>");
128
129 writer.writeTag("h2", "Description");
130 writer.indentPrintln(this.addHTMLBreaks(calcDescription (xmlType)));
131
132 if (!xmlType.getPrimitive().equals(XmlType.COMPLEX)) {
133 return;
134 }
135 writer.indentPrintln(
136 "<h2><a name=\"StructureDefinition\"></a>Structure Definition</h2>");
137
138
139 writer.indentPrintln("<table class=\"structTable\">");
140 writer.indentPrintln("<tr>");
141 writer.indentPrintln("<th class=\"h\">ShortName</th>");
142 writer.indentPrintln("<th class=\"h\">Name</th>");
143 writer.indentPrintln("<th class=\"h\">Type</th>");
144 writer.indentPrintln("<th class=\"h\">Description</th>");
145 writer.indentPrintln("<th class=\"h\">Required?</th>");
146 writer.indentPrintln("<th class=\"h\">Read only?</th>");
147 writer.indentPrintln("<th class=\"h\">Cardinality</th>");
148 writer.indentPrintln("<th class=\"h\">XML Attribute?</th>");
149
150 writer.indentPrintln("<th class=\"h\">Implementation Notes</th>");
151 writer.indentPrintln("</tr>");
152
153 for (MessageStructure ms : finder.findMessageStructures(xmlType.getName())) {
154 this.writeMessageStructure(ms);
155 }
156 writer.indentPrintln("</table>");
157 writer.writeHeaderBodyAndFooterOutToFile();
158 }
159
160
161 private String calcDescription(XmlType xmlType) {
162 StringBuilder sb = new StringBuilder();
163 String newLine = "";
164 if (xmlType.getDesc() != null && !xmlType.getDesc().trim().isEmpty()) {
165 sb.append(newLine);
166 newLine = "\n";
167 sb.append(xmlType.getDesc ());
168 }
169 if (xmlType.isDeprecated()) {
170 sb.append(newLine);
171 newLine = "\n";
172 sb.append("============== Deprecated ===============");
173 }
174 return sb.toString();
175 }
176
177 private String checkForNbsp(String str) {
178 if (str == null) {
179 return " ";
180 }
181 if (str.trim().isEmpty()) {
182 return " ";
183 }
184 return str;
185 }
186
187 private String addHTMLBreaks(String str) {
188 if (str == null) {
189 return " ";
190 }
191 return str.replaceAll("(\r\n|\r|\n|\n\r)", "<br>");
192 }
193
194 public static Set<String> calcUsageByService(ServiceContractModel mdl, XmlType xmlType) {
195 Set<String> services = new HashSet();
196 for (ServiceMethod method : calcUsageByMethods(mdl, xmlType)) {
197 services.add(method.getService());
198 }
199 return services;
200 }
201
202 private Set<ServiceMethod> calcUsageByMethods(XmlType xmlType) {
203 return calcUsageByMethods(model, xmlType);
204 }
205
206 public static Set<ServiceMethod> calcUsageByMethods(ServiceContractModel mdl, XmlType xmlType) {
207 Set<ServiceMethod> methods = new LinkedHashSet();
208 for (ServiceMethod method : mdl.getServiceMethods()) {
209 if (stripListFromType(method.getReturnValue().getType()).equalsIgnoreCase(xmlType.getName())) {
210 methods.add(method);
211 continue;
212 }
213 for (ServiceMethodParameter param : method.getParameters()) {
214 if (stripListFromType(param.getType()).equalsIgnoreCase(xmlType.getName())) {
215 methods.add(method);
216 break;
217 }
218 }
219 }
220 return methods;
221 }
222
223 private Set<String> calcOtherXmlTypeUsages(XmlType xmlType) {
224 return calcOtherXmlTypeUsages(model, xmlType);
225 }
226
227 public static Set<String> calcOtherXmlTypeUsages(ServiceContractModel mdl,
228 XmlType xmlType) {
229 Set<String> xmlTypeNames = new LinkedHashSet();
230 for (MessageStructure ms : mdl.getMessageStructures()) {
231 if (ms.getType() == null) {
232 throw new NullPointerException(ms.getId() + " has no type set");
233 }
234 if (stripListFromType(ms.getType()).equalsIgnoreCase(xmlType.getName())) {
235 xmlTypeNames.add(ms.getXmlObject());
236 }
237 }
238 return xmlTypeNames;
239 }
240
241 private void writeMessageStructure(MessageStructure ms) {
242 writer.indentPrintln("<tr>");
243 writer.writeTag("td", "class=\"structSName\"", ms.getShortName());
244 writer.writeTag("td", "class=\"structLName\"", ms.getName());
245 XmlType subType = finder.findXmlType(this.stripListFromType(ms.getType()));
246 if (subType == null) {
247 for (XmlType xmlt : model.getXmlTypes()) {
248 System.out.println(this.getClass().getSimpleName() + ": "
249 + xmlt.getName());
250 }
251 throw new NullPointerException(ms.getXmlObject() + "." + ms.getShortName()
252 + " has type " + ms.getType()
253 + " was not found in list of known types");
254 }
255 if (subType.getPrimitive().equals(XmlType.COMPLEX)) {
256 writer.indentPrint("<td class=\"structType\">");
257 writer.indentPrintln("<a href=\"" + subType.getName() + ".html" + "\">"
258 + ms.getType() + "</a>");
259 writer.indentPrint("</td>");
260 } else {
261 writer.writeTag("td", "class=\"structType\"", ms.getType());
262 }
263 writer.writeTag("td", "class=\"structDesc\"", addHTMLBreaks(missingData(
264 calcDescription(ms))));
265 writer.writeTag("td", "class=\"structOpt\"", checkForNbsp(ms.getRequired()));
266 writer.writeTag("td", "class=\"structOpt\"", checkForNbsp(ms.getReadOnly()));
267
268 writer.writeTag("td", "class=\"structCard\"", ms.getCardinality());
269 writer.writeTag("td", "class=\"structAttr\"", ms.getXmlAttribute());
270
271 writer.writeTag("td", "class=\"commentsDesc\"", addHTMLBreaks(this.checkForNbsp(ms.getImplNotes())));
272 writer.indentPrintln("</tr>");
273
274
275
276
277
278 }
279
280 private String calcDescription(MessageStructure ms) {
281 StringBuilder sb = new StringBuilder();
282 String newLine = "";
283 if (ms.getDescription() != null && !ms.getDescription().trim().isEmpty()) {
284 sb.append(newLine);
285 newLine = "\n";
286 sb.append(ms.getDescription());
287 }
288 if (ms.isDeprecated()) {
289 sb.append(newLine);
290 newLine = "\n";
291 sb.append("============== Deprecated ===============");
292 }
293 return sb.toString();
294 }
295
296 private String missingData(String str) {
297 if (str == null) {
298 return "???";
299 }
300 if (str.trim().isEmpty()) {
301 return "???";
302 }
303 return str;
304 }
305
306 private static String stripListFromType(String type) {
307 if (type.endsWith("List")) {
308 return type.substring(0, type.length() - "List".length());
309 }
310 return type;
311 }
312
313 public void writeStyleSheet() {
314 writer.indentPrintln("<style type=\"text/css\">");
315 writer.indentPrintln("");
316 writer.indentPrintln("table#structureMetaTable {");
317 writer.indentPrintln("border-collapse:collapse;");
318 writer.indentPrintln("border:1px solid #000000;");
319 writer.indentPrintln("width:95%;");
320 writer.indentPrintln("}");
321 writer.indentPrintln("table#structureMetaTable th.h {");
322 writer.indentPrintln("border:1px solid #000000;");
323 writer.indentPrintln("background-color:#eeeeee;");
324 writer.indentPrintln("width:15%;");
325 writer.indentPrintln("}");
326 writer.indentPrintln("table#structureMetaTable td#structureName {");
327 writer.indentPrintln("border:1px solid #000000;");
328 writer.indentPrintln("width:85%;");
329 writer.indentPrintln("}");
330 writer.indentPrintln("table#structureMetaTable td#structureVersion {");
331 writer.indentPrintln("border:1px solid #000000;");
332 writer.indentPrintln("width:70%;");
333 writer.indentPrintln("}");
334 writer.indentPrintln("table#structureMetaTable td#structureVersionHistory {");
335 writer.indentPrintln("border:1px solid #000000;");
336 writer.indentPrintln("width:15%;");
337 writer.indentPrintln("}");
338 writer.indentPrintln("");
339 writer.indentPrintln("</style>");
340
341 writer.indentPrintln("<style type=\"text/css\">");
342 writer.indentPrintln("");
343 writer.indentPrintln("table.structTable {");
344 writer.indentPrintln("border-collapse:collapse;");
345 writer.indentPrintln("border:1px solid #000000;");
346 writer.indentPrintln("width:95%;");
347 writer.indentPrintln("}");
348 writer.indentPrintln("");
349 writer.indentPrintln("table.structTable td.d {");
350 writer.indentPrintln("border:1px solid #000000;");
351 writer.indentPrintln("}");
352 writer.indentPrintln("");
353 writer.indentPrintln("table.structTable th.h {");
354 writer.indentPrintln("border:1px solid #000000;");
355 writer.indentPrintln("background-color:#eeeeee;");
356 writer.indentPrintln("}");
357 writer.indentPrintln("");
358 writer.indentPrintln("table.structTable td.structSName {");
359 writer.indentPrintln("border:1px solid #000000;");
360 writer.indentPrintln("background-color:#f2f2f2;");
361 writer.indentPrintln("color:#222222;");
362 writer.indentPrintln("text-align:left;");
363 writer.indentPrintln("vertical-align:top;");
364 writer.indentPrintln("font-weight:bold;");
365 writer.indentPrintln("font-style:italic;");
366 writer.indentPrintln("");
367 writer.indentPrintln("}");
368 writer.indentPrintln("");
369 writer.indentPrintln("table.structTable td.structLName {");
370 writer.indentPrintln("border:1px solid #000000;");
371 writer.indentPrintln("background:#ffffff;");
372 writer.indentPrintln("vertical-align:top;");
373 writer.indentPrintln("");
374 writer.indentPrintln("}");
375 writer.indentPrintln("");
376 writer.indentPrintln("table.structTable td.structType {");
377 writer.indentPrintln("border:1px solid #000000;");
378 writer.indentPrintln("background:#ffffff;");
379 writer.indentPrintln("vertical-align:top;");
380 writer.indentPrintln("font-style:italic;");
381 writer.indentPrintln("");
382 writer.indentPrintln("}");
383 writer.indentPrintln("");
384 writer.indentPrintln("table.structTable td.structDesc {");
385 writer.indentPrintln("border:1px solid #000000;");
386 writer.indentPrintln("background:#ffffff;");
387 writer.indentPrintln("vertical-align:top;");
388 writer.indentPrintln("");
389 writer.indentPrintln("}");
390 writer.indentPrintln("");
391 writer.indentPrintln("table.structTable td.structOpt {");
392 writer.indentPrintln("border:1px solid #000000;");
393 writer.indentPrintln("background:#ffffff;");
394 writer.indentPrintln("vertical-align:top;");
395 writer.indentPrintln("text-align: center;");
396 writer.indentPrintln("}");
397 writer.indentPrintln("");
398 writer.indentPrintln("table.structTable td.structReq {");
399 writer.indentPrintln("border:1px solid #000000;");
400 writer.indentPrintln("background:#ccccff;");
401 writer.indentPrintln("vertical-align:top;");
402 writer.indentPrintln("text-align: center;");
403 writer.indentPrintln("}");
404 writer.indentPrintln("");
405 writer.indentPrintln("");
406 writer.indentPrintln("table.structTable td.structCard {");
407 writer.indentPrintln("border:1px solid #000000;");
408 writer.indentPrintln("background:#ffffff;");
409 writer.indentPrintln("vertical-align:top;");
410 writer.indentPrintln("text-align: center;");
411 writer.indentPrintln("}");
412 writer.indentPrintln("");
413 writer.indentPrintln("table.structTable td.structAttr {");
414 writer.indentPrintln("border:1px solid #000000;");
415 writer.indentPrintln("background:#ffffff;");
416 writer.indentPrintln("vertical-align:top;");
417 writer.indentPrintln("text-align: center;");
418 writer.indentPrintln("}");
419 writer.indentPrintln("");
420 writer.indentPrintln("table.structTable td.structElem {");
421 writer.indentPrintln("border:1px solid #000000;");
422 writer.indentPrintln("background:#ccccff;");
423 writer.indentPrintln("vertical-align:top;");
424 writer.indentPrintln("text-align: center;");
425 writer.indentPrintln("}");
426 writer.indentPrintln("");
427 writer.indentPrintln("table.structTable td.structStatus {");
428 writer.indentPrintln("border:1px solid #000000;");
429 writer.indentPrintln("background:#ffffff;");
430 writer.indentPrintln("vertical-align:top;");
431 writer.indentPrintln("text-align: center;");
432 writer.indentPrintln("");
433 writer.indentPrintln("}");
434 writer.indentPrintln("");
435 writer.indentPrintln("table.structTable td.commentsDesc {");
436 writer.indentPrintln("border:1px solid #000000;");
437 writer.indentPrintln("background:#ffffff;");
438 writer.indentPrintln("vertical-align:top;");
439 writer.indentPrintln("");
440 writer.indentPrintln("}");
441 writer.indentPrintln("");
442 writer.indentPrintln("");
443 writer.indentPrintln("</style>");
444
445
446 }
447 }