001 /*
002 * Copyright 2011 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.osedu.org/licenses/ECL-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.kuali.student.contract.model.util;
017
018 import java.util.HashSet;
019 import java.util.LinkedHashSet;
020 import java.util.Set;
021
022 import org.kuali.student.contract.model.MessageStructure;
023 import org.kuali.student.contract.model.ServiceContractModel;
024 import org.kuali.student.contract.model.ServiceMethod;
025 import org.kuali.student.contract.model.ServiceMethodParameter;
026 import org.kuali.student.contract.model.XmlType;
027 import org.kuali.student.contract.writer.HtmlWriter;
028 import org.slf4j.Logger;
029 import org.slf4j.LoggerFactory;
030
031 /**
032 *
033 * @author nwright
034 */
035 public class HtmlContractMessageStructureWriter {
036
037 private static final Logger log = LoggerFactory.getLogger(HtmlContractMessageStructureWriter.class);
038
039 private XmlType xmlType;
040 private HtmlWriter writer;
041 private ServiceContractModel model;
042 private ModelFinder finder;
043
044 public HtmlContractMessageStructureWriter(XmlType xmlType, String directory,
045 ServiceContractModel model) {
046 this.xmlType = xmlType;
047 this.writer = new HtmlWriter(directory, xmlType.getName() + ".html",
048 xmlType.getName());
049 this.model = model;
050 this.finder = new ModelFinder(this.model);
051 }
052
053 private String initUpper(String str) {
054 if (str == null) {
055 return null;
056 }
057 if (str.length() == 0) {
058 return str;
059 }
060 if (str.length() == 1) {
061 return str.toUpperCase();
062 }
063 return str.substring(0, 1).toUpperCase() + str.substring(1);
064 }
065
066 private boolean isMainMessageStructure(XmlType xmlType) {
067 if (!HtmlContractMessageStructureWriter.calcOtherXmlTypeUsages(model,
068 xmlType).isEmpty()) {
069 return false;
070 }
071 return true;
072 }
073
074 public void write(String projectVersion, String formattedDate) {
075
076 this.writeStyleSheet();
077
078
079 if (this.isMainMessageStructure(xmlType)) {
080 VersionLinesUtility.writeVersionTag(writer, "<a href=\"index.html\">home</a>", "<a href=\"../dictionarydocs/" + initUpper(xmlType.getName()) + ".html\">dictionary doc</a>", projectVersion, formattedDate);
081 }
082 else
083 VersionLinesUtility.writeVersionTag(writer, "<a href=\"index.html\">home</a>", "" ,projectVersion, formattedDate);
084
085
086 writer.writeTag("h1", xmlType.getName());
087
088 writer.indentPrintln("<table id=\"structureMetaTable\">");
089 writer.indentPrintln("<tr>");
090 writer.writeTag("th", "class=h", "Name");
091 writer.writeTag("td", "id=structureName colspan=2", xmlType.getName());
092 writer.indentPrintln("</tr>");
093 // writer.indentPrintln ("<tr>");
094 // writer.writeTag ("th", "class=h", "Version");
095 // writer.writeTag ("td", "id=structureVersion colspan=2", xmlType.getVersion ());
096 // writer.indentPrintln ("</tr>");
097 writer.indentPrintln("<tr>");
098 writer.writeTag("th", "rowspan=3 class=h", "Usage");
099 writer.indentPrint("<td id=\"structureVersion\" colspan=2>");
100 for (String servKey : xmlType.getService().split(",")) {
101 writer.indentPrintln("<a href=\"" + servKey + "Service" + ".html" + "\">"
102 + servKey + "Service" + "</a>");
103 }
104 writer.indentPrint("</td>");
105
106 writer.indentPrintln("</tr>");
107 writer.indentPrintln("<tr>");
108 writer.writeTag("th", "class=h", "");
109 writer.indentPrint("<td id=\"structureVersion\" colspan=2>");
110 for (ServiceMethod method : this.calcUsageByMethods(xmlType)) {
111 writer.indentPrintln("<a href=\"" + method.getService() + "Service"
112 + ".html" + "#" + method.getService() + "-"
113 + method.getName() + "\">"
114 + method.getName() + "</a>");
115 }
116 writer.indentPrint("</td>");
117 writer.indentPrintln("</tr>");
118 writer.indentPrintln("<tr>");
119 writer.writeTag("th", "class=h", "");
120 writer.indentPrint("<td id=\"structureVersion\" colspan=2>");
121 for (String xmlTypeName : this.calcOtherXmlTypeUsages(xmlType)) {
122 XmlType usageType = finder.findXmlType(xmlTypeName);
123 if (usageType == null) {
124 throw new NullPointerException("Coud not find XmlType with name="
125 + xmlTypeName);
126 }
127 writer.indentPrintln("<a href=\"" + usageType.getName() + ".html" + "\">"
128 + usageType.getName() + "</a>");
129 }
130 writer.indentPrint("</td>");
131 writer.indentPrintln("</tr>");
132
133 writer.writeTag("th", "class=h", "Type");
134 writer.writeTag("td", "id=structureVersion colspan=2",
135 xmlType.getPrimitive());
136 writer.indentPrintln("</tr>");
137 writer.indentPrintln("</table>");
138
139 writer.writeTag("h2", "Description");
140 writer.indentPrintln(this.addHTMLBreaks(calcDescription (xmlType)));
141
142 if (!xmlType.getPrimitive().equals(XmlType.COMPLEX)) {
143 return;
144 }
145 writer.indentPrintln(
146 "<h2><a name=\"StructureDefinition\"></a>Structure Definition</h2>");
147
148
149 writer.indentPrintln("<table class=\"structTable\">");
150 writer.indentPrintln("<tr>");
151 writer.indentPrintln("<th class=\"h\">ShortName</th>");
152 writer.indentPrintln("<th class=\"h\">Name</th>");
153 writer.indentPrintln("<th class=\"h\">Type</th>");
154 writer.indentPrintln("<th class=\"h\">Description</th>");
155 writer.indentPrintln("<th class=\"h\">Required?</th>");
156 writer.indentPrintln("<th class=\"h\">Read only?</th>");
157 writer.indentPrintln("<th class=\"h\">Cardinality</th>");
158 writer.indentPrintln("<th class=\"h\">XML Attribute?</th>");
159 // writer.indentPrintln ("<th class=\"h\">Status</th>");
160 writer.indentPrintln("<th class=\"h\">Implementation Notes</th>");
161 writer.indentPrintln("</tr>");
162
163 for (MessageStructure ms : finder.findMessageStructures(xmlType.getName())) {
164 this.writeMessageStructure(ms);
165 }
166 writer.indentPrintln("</table>");
167 writer.writeHeaderBodyAndFooterOutToFile();
168 }
169
170
171 private String calcDescription(XmlType xmlType) {
172 StringBuilder sb = new StringBuilder();
173 String newLine = "";
174 if (xmlType.getDesc() != null && !xmlType.getDesc().trim().isEmpty()) {
175 sb.append(newLine);
176 newLine = "\n";
177 sb.append(xmlType.getDesc ());
178 }
179 if (xmlType.isDeprecated()) {
180 sb.append(newLine);
181 newLine = "\n";
182 sb.append("============== Deprecated ===============");
183 }
184 return sb.toString();
185 }
186
187 private String checkForNbsp(String str) {
188 if (str == null) {
189 return " ";
190 }
191 if (str.trim().isEmpty()) {
192 return " ";
193 }
194 return str;
195 }
196
197 private String addHTMLBreaks(String str) {
198 if (str == null) {
199 return " ";
200 }
201 return str.replaceAll("(\r\n|\r|\n|\n\r)", "<br>");
202 }
203
204 public static Set<String> calcUsageByService(ServiceContractModel mdl, XmlType xmlType) {
205 Set<String> services = new HashSet();
206 for (ServiceMethod method : calcUsageByMethods(mdl, xmlType)) {
207 services.add(method.getService());
208 }
209 return services;
210 }
211
212 private Set<ServiceMethod> calcUsageByMethods(XmlType xmlType) {
213 return calcUsageByMethods(model, xmlType);
214 }
215
216 public static Set<ServiceMethod> calcUsageByMethods(ServiceContractModel mdl, XmlType xmlType) {
217 Set<ServiceMethod> methods = new LinkedHashSet();
218 for (ServiceMethod method : mdl.getServiceMethods()) {
219 if (stripListFromType(method.getReturnValue().getType()).equalsIgnoreCase(xmlType.getName())) {
220 methods.add(method);
221 continue;
222 }
223 for (ServiceMethodParameter param : method.getParameters()) {
224 if (stripListFromType(param.getType()).equalsIgnoreCase(xmlType.getName())) {
225 methods.add(method);
226 break;
227 }
228 }
229 }
230 return methods;
231 }
232
233 private Set<String> calcOtherXmlTypeUsages(XmlType xmlType) {
234 return calcOtherXmlTypeUsages(model, xmlType);
235 }
236
237 public static Set<String> calcOtherXmlTypeUsages(ServiceContractModel mdl,
238 XmlType xmlType) {
239 Set<String> xmlTypeNames = new LinkedHashSet();
240 for (MessageStructure ms : mdl.getMessageStructures()) {
241 if (ms.getType() == null) {
242 throw new NullPointerException(ms.getId() + " has no type set");
243 }
244 if (stripListFromType(ms.getType()).equalsIgnoreCase(xmlType.getName())) {
245 xmlTypeNames.add(ms.getXmlObject());
246 }
247 }
248 return xmlTypeNames;
249 }
250
251 private void writeMessageStructure(MessageStructure ms) {
252 writer.indentPrintln("<tr>");
253 writer.writeTag("td", "class=\"structSName\"", ms.getShortName());
254 writer.writeTag("td", "class=\"structLName\"", ms.getName());
255 XmlType subType = finder.findXmlType(this.stripListFromType(ms.getType()));
256 if (subType == null) {
257 // for (XmlType xmlt : model.getXmlTypes()) {
258 // System.out.println(this.getClass().getSimpleName() + ": "
259 // + xmlt.getName());
260 // }
261 // throw new NullPointerException(ms.getXmlObject() + "." + ms.getShortName()
262 // + " has type " + ms.getType()
263 // + " was not found in list of known types");
264
265 log.error (ms.getXmlObject() + "." + ms.getShortName()
266 + " has type " + ms.getType()
267 + " was not found in list of known types");
268 return;
269 }
270 if (subType.getPrimitive().equals(XmlType.COMPLEX)) {
271 writer.indentPrint("<td class=\"structType\">");
272 writer.indentPrintln("<a href=\"" + subType.getName() + ".html" + "\">"
273 + ms.getType() + "</a>");
274 writer.indentPrint("</td>");
275 } else {
276 writer.writeTag("td", "class=\"structType\"", ms.getType());
277 }
278 writer.writeTag("td", "class=\"structDesc\"", addHTMLBreaks(missingData(
279 calcDescription(ms))));
280 writer.writeTag("td", "class=\"structOpt\"", checkForNbsp(ms.getRequired()));
281 writer.writeTag("td", "class=\"structOpt\"", checkForNbsp(ms.getReadOnly()));
282
283 writer.writeTag("td", "class=\"structCard\"", ms.getCardinality());
284 writer.writeTag("td", "class=\"structAttr\"", ms.getXmlAttribute());
285 // writer.writeTag ("td", "class=\"structStatus\"", ms.getStatus ());
286 writer.writeTag("td", "class=\"commentsDesc\"", addHTMLBreaks(this.checkForNbsp(ms.getImplNotes())));
287 writer.indentPrintln("</tr>");
288
289 // writer.indentPrintln ("</table>");
290 // writer.indentPrintln ("<p>");
291
292 // writer.indentPrintln ("<p>");
293 }
294
295 private String calcDescription(MessageStructure ms) {
296 StringBuilder sb = new StringBuilder();
297 String newLine = "";
298 if (ms.getDescription() != null && !ms.getDescription().trim().isEmpty()) {
299 sb.append(newLine);
300 newLine = "\n";
301 sb.append(ms.getDescription());
302 }
303 if (ms.isDeprecated()) {
304 sb.append(newLine);
305 newLine = "\n";
306 sb.append("============== Deprecated ===============");
307 }
308 return sb.toString();
309 }
310
311 private String missingData(String str) {
312 if (str == null) {
313 return "???";
314 }
315 if (str.trim().isEmpty()) {
316 return "???";
317 }
318 return str;
319 }
320
321 private static String stripListFromType(String type) {
322 if (type.endsWith("List")) {
323 return type.substring(0, type.length() - "List".length());
324 }
325 return type;
326 }
327
328 public void writeStyleSheet() {
329 writer.indentPrintln("<style type=\"text/css\">");
330 writer.indentPrintln("");
331 writer.indentPrintln("table#structureMetaTable {");
332 writer.indentPrintln("border-collapse:collapse;");
333 writer.indentPrintln("border:1px solid #000000;");
334 writer.indentPrintln("width:95%;");
335 writer.indentPrintln("}");
336 writer.indentPrintln("table#structureMetaTable th.h {");
337 writer.indentPrintln("border:1px solid #000000;");
338 writer.indentPrintln("background-color:#eeeeee;");
339 writer.indentPrintln("width:15%;");
340 writer.indentPrintln("}");
341 writer.indentPrintln("table#structureMetaTable td#structureName {");
342 writer.indentPrintln("border:1px solid #000000;");
343 writer.indentPrintln("width:85%;");
344 writer.indentPrintln("}");
345 writer.indentPrintln("table#structureMetaTable td#structureVersion {");
346 writer.indentPrintln("border:1px solid #000000;");
347 writer.indentPrintln("width:70%;");
348 writer.indentPrintln("}");
349 writer.indentPrintln("table#structureMetaTable td#structureVersionHistory {");
350 writer.indentPrintln("border:1px solid #000000;");
351 writer.indentPrintln("width:15%;");
352 writer.indentPrintln("}");
353 writer.indentPrintln("");
354 writer.indentPrintln("</style>");
355
356 writer.indentPrintln("<style type=\"text/css\">");
357 writer.indentPrintln("");
358 writer.indentPrintln("table.structTable {");
359 writer.indentPrintln("border-collapse:collapse;");
360 writer.indentPrintln("border:1px solid #000000;");
361 writer.indentPrintln("width:95%;");
362 writer.indentPrintln("}");
363 writer.indentPrintln("");
364 writer.indentPrintln("table.structTable td.d {");
365 writer.indentPrintln("border:1px solid #000000;");
366 writer.indentPrintln("}");
367 writer.indentPrintln("");
368 writer.indentPrintln("table.structTable th.h {");
369 writer.indentPrintln("border:1px solid #000000;");
370 writer.indentPrintln("background-color:#eeeeee;");
371 writer.indentPrintln("}");
372 writer.indentPrintln("");
373 writer.indentPrintln("table.structTable td.structSName {");
374 writer.indentPrintln("border:1px solid #000000;");
375 writer.indentPrintln("background-color:#f2f2f2;");
376 writer.indentPrintln("color:#222222;");
377 writer.indentPrintln("text-align:left;");
378 writer.indentPrintln("vertical-align:top;");
379 writer.indentPrintln("font-weight:bold;");
380 writer.indentPrintln("font-style:italic;");
381 writer.indentPrintln("");
382 writer.indentPrintln("}");
383 writer.indentPrintln("");
384 writer.indentPrintln("table.structTable td.structLName {");
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.structType {");
392 writer.indentPrintln("border:1px solid #000000;");
393 writer.indentPrintln("background:#ffffff;");
394 writer.indentPrintln("vertical-align:top;");
395 writer.indentPrintln("font-style:italic;");
396 writer.indentPrintln("");
397 writer.indentPrintln("}");
398 writer.indentPrintln("");
399 writer.indentPrintln("table.structTable td.structDesc {");
400 writer.indentPrintln("border:1px solid #000000;");
401 writer.indentPrintln("background:#ffffff;");
402 writer.indentPrintln("vertical-align:top;");
403 writer.indentPrintln("");
404 writer.indentPrintln("}");
405 writer.indentPrintln("");
406 writer.indentPrintln("table.structTable td.structOpt {");
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.structReq {");
414 writer.indentPrintln("border:1px solid #000000;");
415 writer.indentPrintln("background:#ccccff;");
416 writer.indentPrintln("vertical-align:top;");
417 writer.indentPrintln("text-align: center;");
418 writer.indentPrintln("}");
419 writer.indentPrintln("");
420 writer.indentPrintln("");
421 writer.indentPrintln("table.structTable td.structCard {");
422 writer.indentPrintln("border:1px solid #000000;");
423 writer.indentPrintln("background:#ffffff;");
424 writer.indentPrintln("vertical-align:top;");
425 writer.indentPrintln("text-align: center;");
426 writer.indentPrintln("}");
427 writer.indentPrintln("");
428 writer.indentPrintln("table.structTable td.structAttr {");
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.structElem {");
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("table.structTable td.structStatus {");
443 writer.indentPrintln("border:1px solid #000000;");
444 writer.indentPrintln("background:#ffffff;");
445 writer.indentPrintln("vertical-align:top;");
446 writer.indentPrintln("text-align: center;");
447 writer.indentPrintln("");
448 writer.indentPrintln("}");
449 writer.indentPrintln("");
450 writer.indentPrintln("table.structTable td.commentsDesc {");
451 writer.indentPrintln("border:1px solid #000000;");
452 writer.indentPrintln("background:#ffffff;");
453 writer.indentPrintln("vertical-align:top;");
454 writer.indentPrintln("");
455 writer.indentPrintln("}");
456 writer.indentPrintln("");
457 writer.indentPrintln("");
458 writer.indentPrintln("</style>");
459
460
461 }
462 }