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