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(String projectVersion, String formattedDate) {
071
072 this.writeStyleSheet();
073
074
075 if (this.isMainMessageStructure(xmlType)) {
076 VersionLinesUtility.writeVersionTag(writer, "<a href=\"index.html\">home</a>", "<a href=\"../dictionarydocs/" + initUpper(xmlType.getName()) + ".html\">dictionary doc</a>", projectVersion, formattedDate);
077 }
078 else
079 VersionLinesUtility.writeVersionTag(writer, "<a href=\"index.html\">home</a>", "" ,projectVersion, formattedDate);
080
081
082 writer.writeTag("h1", xmlType.getName());
083
084 writer.indentPrintln("<table id=\"structureMetaTable\">");
085 writer.indentPrintln("<tr>");
086 writer.writeTag("th", "class=h", "Name");
087 writer.writeTag("td", "id=structureName colspan=2", xmlType.getName());
088 writer.indentPrintln("</tr>");
089 // writer.indentPrintln ("<tr>");
090 // writer.writeTag ("th", "class=h", "Version");
091 // writer.writeTag ("td", "id=structureVersion colspan=2", xmlType.getVersion ());
092 // writer.indentPrintln ("</tr>");
093 writer.indentPrintln("<tr>");
094 writer.writeTag("th", "rowspan=3 class=h", "Usage");
095 writer.indentPrint("<td id=\"structureVersion\" colspan=2>");
096 for (String servKey : xmlType.getService().split(",")) {
097 writer.indentPrintln("<a href=\"" + servKey + "Service" + ".html" + "\">"
098 + servKey + "Service" + "</a>");
099 }
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 // writer.indentPrintln ("<th class=\"h\">Status</th>");
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 // writer.writeTag ("td", "class=\"structStatus\"", ms.getStatus ());
277 writer.writeTag("td", "class=\"commentsDesc\"", addHTMLBreaks(this.checkForNbsp(ms.getImplNotes())));
278 writer.indentPrintln("</tr>");
279
280 // writer.indentPrintln ("</table>");
281 // writer.indentPrintln ("<p>");
282
283 // writer.indentPrintln ("<p>");
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 }