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
029 /**
030 *
031 * @author nwright
032 */
033 public class HtmlContractMessageStructureWriter {
034
035 private XmlType xmlType;
036 private HtmlWriter writer;
037 private ServiceContractModel model;
038 private ModelFinder finder;
039
040 public HtmlContractMessageStructureWriter(XmlType xmlType, String directory,
041 ServiceContractModel model) {
042 this.xmlType = xmlType;
043 this.writer = new HtmlWriter(directory, xmlType.getName() + ".html",
044 xmlType.getName());
045 this.model = model;
046 this.finder = new ModelFinder(this.model);
047 }
048
049 private String initUpper(String str) {
050 if (str == null) {
051 return null;
052 }
053 if (str.length() == 0) {
054 return str;
055 }
056 if (str.length() == 1) {
057 return str.toUpperCase();
058 }
059 return str.substring(0, 1).toUpperCase() + str.substring(1);
060 }
061
062 private boolean isMainMessageStructure(XmlType xmlType) {
063 if (!HtmlContractMessageStructureWriter.calcOtherXmlTypeUsages(model,
064 xmlType).isEmpty()) {
065 return false;
066 }
067 return true;
068 }
069
070 public void write() {
071 writer.println("<a href=\"index.html\">home</a>");
072 if (this.isMainMessageStructure(xmlType)) {
073 writer.println("<a href=\"../dictionarydocs/" + initUpper(xmlType.getName()) + ".html\">dictionary doc</a>");
074 }
075 this.writeStyleSheet();
076 writer.writeTag("h1", xmlType.getName());
077
078 writer.indentPrintln("<table id=\"structureMetaTable\">");
079 writer.indentPrintln("<tr>");
080 writer.writeTag("th", "class=h", "Name");
081 writer.writeTag("td", "id=structureName colspan=2", xmlType.getName());
082 writer.indentPrintln("</tr>");
083 // writer.indentPrintln ("<tr>");
084 // writer.writeTag ("th", "class=h", "Version");
085 // writer.writeTag ("td", "id=structureVersion colspan=2", xmlType.getVersion ());
086 // writer.indentPrintln ("</tr>");
087 writer.indentPrintln("<tr>");
088 writer.writeTag("th", "rowspan=3 class=h", "Usage");
089 writer.indentPrint("<td id=\"structureVersion\" colspan=2>");
090 for (String servKey : xmlType.getService().split(",")) {
091 writer.indentPrintln("<a href=\"" + servKey + "Service" + ".html" + "\">"
092 + servKey + "Service" + "</a>");
093 }
094 writer.indentPrint("</td>");
095
096 writer.indentPrintln("</tr>");
097 writer.indentPrintln("<tr>");
098 writer.writeTag("th", "class=h", "");
099 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 // writer.indentPrintln ("<th class=\"h\">Status</th>");
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 // writer.writeTag ("td", "class=\"structStatus\"", ms.getStatus ());
271 writer.writeTag("td", "class=\"commentsDesc\"", addHTMLBreaks(this.checkForNbsp(ms.getImplNotes())));
272 writer.indentPrintln("</tr>");
273
274 // writer.indentPrintln ("</table>");
275 // writer.indentPrintln ("<p>");
276
277 // writer.indentPrintln ("<p>");
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 }