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 }