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