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 }