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 }