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(xmlType.getDesc()));
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 private String checkForNbsp(String str) {
161 if (str == null) {
162 return " ";
163 }
164 if (str.trim().isEmpty()) {
165 return " ";
166 }
167 return str;
168 }
169
170 private String addHTMLBreaks(String str) {
171 if (str == null) {
172 return " ";
173 }
174 return str.replaceAll("(\r\n|\r|\n|\n\r)", "<br>");
175 }
176
177 public static Set<String> calcUsageByService(ServiceContractModel mdl, XmlType xmlType) {
178 Set<String> services = new HashSet();
179 for (ServiceMethod method : calcUsageByMethods(mdl, xmlType)) {
180 services.add(method.getService());
181 }
182 return services;
183 }
184
185 private Set<ServiceMethod> calcUsageByMethods(XmlType xmlType) {
186 return calcUsageByMethods(model, xmlType);
187 }
188
189 public static Set<ServiceMethod> calcUsageByMethods(ServiceContractModel mdl, XmlType xmlType) {
190 Set<ServiceMethod> methods = new LinkedHashSet();
191 for (ServiceMethod method : mdl.getServiceMethods()) {
192 if (stripListFromType(method.getReturnValue().getType()).equalsIgnoreCase(xmlType.getName())) {
193 methods.add(method);
194 continue;
195 }
196 for (ServiceMethodParameter param : method.getParameters()) {
197 if (stripListFromType(param.getType()).equalsIgnoreCase(xmlType.getName())) {
198 methods.add(method);
199 break;
200 }
201 }
202 }
203 return methods;
204 }
205
206 private Set<String> calcOtherXmlTypeUsages(XmlType xmlType) {
207 return calcOtherXmlTypeUsages(model, xmlType);
208 }
209
210 public static Set<String> calcOtherXmlTypeUsages(ServiceContractModel mdl,
211 XmlType xmlType) {
212 Set<String> xmlTypeNames = new LinkedHashSet();
213 for (MessageStructure ms : mdl.getMessageStructures()) {
214 if (ms.getType() == null) {
215 throw new NullPointerException(ms.getId() + " has no type set");
216 }
217 if (stripListFromType(ms.getType()).equalsIgnoreCase(xmlType.getName())) {
218 xmlTypeNames.add(ms.getXmlObject());
219 }
220 }
221 return xmlTypeNames;
222 }
223
224 private void writeMessageStructure(MessageStructure ms) {
225 writer.indentPrintln("<tr>");
226 writer.writeTag("td", "class=\"structSName\"", ms.getShortName());
227 writer.writeTag("td", "class=\"structLName\"", ms.getName());
228 XmlType subType = finder.findXmlType(this.stripListFromType(ms.getType()));
229 if (subType == null) {
230 for (XmlType xmlt : model.getXmlTypes()) {
231 System.out.println(this.getClass().getSimpleName() + ": "
232 + xmlt.getName());
233 }
234 throw new NullPointerException(ms.getXmlObject() + "." + ms.getShortName()
235 + " has type " + ms.getType()
236 + " was not found in list of known types");
237 }
238 if (subType.getPrimitive().equals(XmlType.COMPLEX)) {
239 writer.indentPrint("<td class=\"structType\">");
240 writer.indentPrintln("<a href=\"" + subType.getName() + ".html" + "\">"
241 + ms.getType() + "</a>");
242 writer.indentPrint("</td>");
243 } else {
244 writer.writeTag("td", "class=\"structType\"", ms.getType());
245 }
246 writer.writeTag("td", "class=\"structDesc\"", addHTMLBreaks(missingData(
247 ms.getDescription())));
248 writer.writeTag("td", "class=\"structOpt\"", checkForNbsp(ms.getRequired()));
249 writer.writeTag("td", "class=\"structOpt\"", checkForNbsp(ms.getReadOnly()));
250
251 writer.writeTag("td", "class=\"structCard\"", ms.getCardinality());
252 writer.writeTag("td", "class=\"structAttr\"", ms.getXmlAttribute());
253 // writer.writeTag ("td", "class=\"structStatus\"", ms.getStatus ());
254 writer.writeTag("td", "class=\"commentsDesc\"", this.checkForNbsp(ms.getImplNotes()));
255 writer.indentPrintln("</tr>");
256
257 // writer.indentPrintln ("</table>");
258 // writer.indentPrintln ("<p>");
259
260 // writer.indentPrintln ("<p>");
261 }
262
263 private String missingData(String str) {
264 if (str == null) {
265 return "???";
266 }
267 if (str.trim().isEmpty()) {
268 return "???";
269 }
270 return str;
271 }
272
273 private static String stripListFromType(String type) {
274 if (type.endsWith("List")) {
275 return type.substring(0, type.length() - "List".length());
276 }
277 return type;
278 }
279
280 public void writeStyleSheet() {
281 writer.indentPrintln("<style type=\"text/css\">");
282 writer.indentPrintln("");
283 writer.indentPrintln("table#structureMetaTable {");
284 writer.indentPrintln("border-collapse:collapse;");
285 writer.indentPrintln("border:1px solid #000000;");
286 writer.indentPrintln("width:95%;");
287 writer.indentPrintln("}");
288 writer.indentPrintln("table#structureMetaTable th.h {");
289 writer.indentPrintln("border:1px solid #000000;");
290 writer.indentPrintln("background-color:#eeeeee;");
291 writer.indentPrintln("width:15%;");
292 writer.indentPrintln("}");
293 writer.indentPrintln("table#structureMetaTable td#structureName {");
294 writer.indentPrintln("border:1px solid #000000;");
295 writer.indentPrintln("width:85%;");
296 writer.indentPrintln("}");
297 writer.indentPrintln("table#structureMetaTable td#structureVersion {");
298 writer.indentPrintln("border:1px solid #000000;");
299 writer.indentPrintln("width:70%;");
300 writer.indentPrintln("}");
301 writer.indentPrintln("table#structureMetaTable td#structureVersionHistory {");
302 writer.indentPrintln("border:1px solid #000000;");
303 writer.indentPrintln("width:15%;");
304 writer.indentPrintln("}");
305 writer.indentPrintln("");
306 writer.indentPrintln("</style>");
307
308 writer.indentPrintln("<style type=\"text/css\">");
309 writer.indentPrintln("");
310 writer.indentPrintln("table.structTable {");
311 writer.indentPrintln("border-collapse:collapse;");
312 writer.indentPrintln("border:1px solid #000000;");
313 writer.indentPrintln("width:95%;");
314 writer.indentPrintln("}");
315 writer.indentPrintln("");
316 writer.indentPrintln("table.structTable td.d {");
317 writer.indentPrintln("border:1px solid #000000;");
318 writer.indentPrintln("}");
319 writer.indentPrintln("");
320 writer.indentPrintln("table.structTable th.h {");
321 writer.indentPrintln("border:1px solid #000000;");
322 writer.indentPrintln("background-color:#eeeeee;");
323 writer.indentPrintln("}");
324 writer.indentPrintln("");
325 writer.indentPrintln("table.structTable td.structSName {");
326 writer.indentPrintln("border:1px solid #000000;");
327 writer.indentPrintln("background-color:#f2f2f2;");
328 writer.indentPrintln("color:#222222;");
329 writer.indentPrintln("text-align:left;");
330 writer.indentPrintln("vertical-align:top;");
331 writer.indentPrintln("font-weight:bold;");
332 writer.indentPrintln("font-style:italic;");
333 writer.indentPrintln("");
334 writer.indentPrintln("}");
335 writer.indentPrintln("");
336 writer.indentPrintln("table.structTable td.structLName {");
337 writer.indentPrintln("border:1px solid #000000;");
338 writer.indentPrintln("background:#ffffff;");
339 writer.indentPrintln("vertical-align:top;");
340 writer.indentPrintln("");
341 writer.indentPrintln("}");
342 writer.indentPrintln("");
343 writer.indentPrintln("table.structTable td.structType {");
344 writer.indentPrintln("border:1px solid #000000;");
345 writer.indentPrintln("background:#ffffff;");
346 writer.indentPrintln("vertical-align:top;");
347 writer.indentPrintln("font-style:italic;");
348 writer.indentPrintln("");
349 writer.indentPrintln("}");
350 writer.indentPrintln("");
351 writer.indentPrintln("table.structTable td.structDesc {");
352 writer.indentPrintln("border:1px solid #000000;");
353 writer.indentPrintln("background:#ffffff;");
354 writer.indentPrintln("vertical-align:top;");
355 writer.indentPrintln("");
356 writer.indentPrintln("}");
357 writer.indentPrintln("");
358 writer.indentPrintln("table.structTable td.structOpt {");
359 writer.indentPrintln("border:1px solid #000000;");
360 writer.indentPrintln("background:#ffffff;");
361 writer.indentPrintln("vertical-align:top;");
362 writer.indentPrintln("text-align: center;");
363 writer.indentPrintln("}");
364 writer.indentPrintln("");
365 writer.indentPrintln("table.structTable td.structReq {");
366 writer.indentPrintln("border:1px solid #000000;");
367 writer.indentPrintln("background:#ccccff;");
368 writer.indentPrintln("vertical-align:top;");
369 writer.indentPrintln("text-align: center;");
370 writer.indentPrintln("}");
371 writer.indentPrintln("");
372 writer.indentPrintln("");
373 writer.indentPrintln("table.structTable td.structCard {");
374 writer.indentPrintln("border:1px solid #000000;");
375 writer.indentPrintln("background:#ffffff;");
376 writer.indentPrintln("vertical-align:top;");
377 writer.indentPrintln("text-align: center;");
378 writer.indentPrintln("}");
379 writer.indentPrintln("");
380 writer.indentPrintln("table.structTable td.structAttr {");
381 writer.indentPrintln("border:1px solid #000000;");
382 writer.indentPrintln("background:#ffffff;");
383 writer.indentPrintln("vertical-align:top;");
384 writer.indentPrintln("text-align: center;");
385 writer.indentPrintln("}");
386 writer.indentPrintln("");
387 writer.indentPrintln("table.structTable td.structElem {");
388 writer.indentPrintln("border:1px solid #000000;");
389 writer.indentPrintln("background:#ccccff;");
390 writer.indentPrintln("vertical-align:top;");
391 writer.indentPrintln("text-align: center;");
392 writer.indentPrintln("}");
393 writer.indentPrintln("");
394 writer.indentPrintln("table.structTable td.structStatus {");
395 writer.indentPrintln("border:1px solid #000000;");
396 writer.indentPrintln("background:#ffffff;");
397 writer.indentPrintln("vertical-align:top;");
398 writer.indentPrintln("text-align: center;");
399 writer.indentPrintln("");
400 writer.indentPrintln("}");
401 writer.indentPrintln("");
402 writer.indentPrintln("table.structTable td.commentsDesc {");
403 writer.indentPrintln("border:1px solid #000000;");
404 writer.indentPrintln("background:#ffffff;");
405 writer.indentPrintln("vertical-align:top;");
406 writer.indentPrintln("");
407 writer.indentPrintln("}");
408 writer.indentPrintln("");
409 writer.indentPrintln("");
410 writer.indentPrintln("</style>");
411
412
413 }
414 }