001 /** 002 * Copyright 2004-2014 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.opensource.org/licenses/ecl2.php 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.Date; 019 import java.util.LinkedHashSet; 020 import java.util.List; 021 import java.util.Set; 022 023 import org.kuali.student.contract.model.Service; 024 import org.kuali.student.contract.model.ServiceContractModel; 025 import org.kuali.student.contract.model.ServiceMethod; 026 import org.kuali.student.contract.model.ServiceMethodError; 027 import org.kuali.student.contract.model.ServiceMethodParameter; 028 import org.kuali.student.contract.model.XmlType; 029 import org.kuali.student.contract.writer.HtmlWriter; 030 031 /** 032 * 033 * @author nwright 034 */ 035 public class HtmlContractServiceWriter { 036 037 private Service service; 038 private HtmlWriter writer; 039 private ServiceContractModel model; 040 private ModelFinder finder; 041 042 public HtmlContractServiceWriter(Service service, String directory, 043 ServiceContractModel model) { 044 this.service = service; 045 this.writer = new HtmlWriter(directory, service.getKey() + "Service" + ".html", 046 service.getName()); 047 this.model = model; 048 this.finder = new ModelFinder(this.model); 049 } 050 051 public void write(String projectVersion, String formattedDate) { 052 this.writeStyleSheet(); 053 054 055 VersionLinesUtility.writeVersionTag(writer, "<a href=\"index.html\">home</a>", "", projectVersion, formattedDate); 056 057 writer.writeTag("h1", service.getName()); 058 059 writer.indentPrintln("<table id=\"serviceMetaTable\">"); 060 writer.indentPrintln("<tr>"); 061 writer.writeTag("th", "class=h", "Key"); 062 writer.writeTag("td", "id=serviceName colspan=2", service.getKey()); 063 writer.indentPrintln("</tr>"); 064 065 writer.indentPrintln("<tr>"); 066 writer.writeTag("th", "class=h", "Version"); 067 writer.writeTag("td", "id=serviceVersion colspan=2", service.getVersion()); 068 writer.indentPrintln("</tr>"); 069 writer.indentPrintln("<tr>"); 070 writer.writeTag("th", "class=h", "Included Services"); 071 072 writer.writeTag("td", "id=serviceVersion colspan=2", calcIncludedServices( 073 service.getIncludedServices())); 074 writer.indentPrintln("</tr>"); 075 076 writer.indentPrintln("<tr>"); 077 writer.writeTag("th", "class=h", "Java Package"); 078 079 writer.writeTag("td", "id=serviceVersion colspan=2", service.getImplProject()); 080 writer.indentPrintln("</tr>"); 081 082 083 writer.indentPrintln("</table>"); 084 085 // writer.indentPrintln ("<div class=\"panel\" style=\"border-width: 1px;\">"); 086 // writer.indentPrintln ("<div class=\"panelHeader\" style=\"border-bottom-width: 1px;\">"); 087 writer.indentPrintln("<p>"); 088 // writer.indentPrintln("<table id=\"serviceMetaTable\">"); 089 // writer.indentPrintln("<tr>"); 090 // writer.indentPrintln("<td>"); 091 writer.indentPrintln( 092 "<div class=\"panel\" style=\"background-color: rgb(255, 255, 255); border: 1px solid rgb(204, 204, 204);\">"); 093 writer.indentPrintln( 094 "<div class=\"panelHeader\" style=\"border-bottom: 1px solid rgb(204, 204, 204); background-color: rgb(238, 238, 238);\">"); 095 writer.indentPrintln(this.addHTMLBreaks(service.getComments())); 096 writer.indentPrintln("</div>"); 097 writer.indentPrintln("</div>"); 098 // writer.indentPrintln("</td>"); 099 // writer.indentPrintln("</tr>"); 100 // writer.indentPrintln("</table>"); 101 102 // writer.indentPrintln ("</div>"); 103 // writer.indentPrintln ("</div>"); 104 105 writer.indentPrintln("<p>"); 106 writer.indentPrintln( 107 "<div class=\"panel\" style=\"background-color: rgb(255, 255, 255); border: 1px solid rgb(204, 204, 204);\">"); 108 writer.indentPrintln( 109 "<div class=\"panelHeader\" style=\"border-bottom: 1px solid rgb(204, 204, 204); background-color: rgb(238, 238, 238);\">"); 110 writer.indentPrintln("<b><a name=\"ListOfOperations\"></a>Operations</b>"); 111 writer.indentPrintln( 112 "</div><div class=\"panelContent\" style=\"background-color: rgb(255, 255, 255);\">"); 113 writer.indentPrintln("<ul>"); 114 for (ServiceMethod method : finder.getServiceMethodsInService( 115 service.getKey())) { 116 writer.indentPrint("<li>"); 117 writer.print("<a href=\"#" + method.getService() + "-" + method.getName() 118 + "\">" + method.getName() + "</a>"); 119 writer.print("</li>"); 120 } 121 writer.indentPrintln("</ul>"); 122 writer.indentPrintln("</div>"); 123 writer.indentPrintln("</div>"); 124 125 // now write out the root message structures 126 writer.indentPrintln( 127 "<div class=\"panel\" style=\"background-color: rgb(255, 255, 255); border: 1px solid rgb(204, 204, 204);\">"); 128 writer.indentPrintln( 129 "<div class=\"panelHeader\" style=\"border-bottom: 1px solid rgb(204, 204, 204); background-color: rgb(238, 238, 238);\">"); 130 writer.indentPrintln( 131 "<b><a name=\"MainMessageStructures\"></a>Main Message Structures</b>"); 132 writer.indentPrintln( 133 "</div><div class=\"panelContent\" style=\"background-color: rgb(255, 255, 255);\">"); 134 135 writer.indentPrintln("<ul>"); 136 for (XmlType type : this.calcMainMessageStructures()) { 137 writer.indentPrint("<li>"); 138 writer.print("<a href=\"" + type.getName() + ".html" 139 + "\">" + type.getName() + "</a>"); 140 writer.print("</li>"); 141 } 142 writer.indentPrintln("</ul>"); 143 144 145 for (ServiceMethod method : finder.getServiceMethodsInService( 146 service.getKey())) { 147 this.writeMethod(method); 148 } 149 150 writer.writeHeaderBodyAndFooterOutToFile(); 151 152 writer.getOut().close(); 153 } 154 155 private String calcIncludedServices(List<String> includedServices) { 156 if (includedServices == null) { 157 return " "; 158 } 159 if (includedServices.isEmpty()) { 160 return " "; 161 } 162 StringBuilder bldr = new StringBuilder(); 163 String comma = ""; 164 for (String includedService : includedServices) { 165 bldr.append(comma); 166 comma = ", "; 167 bldr.append("<a href=\"" + includedService + ".html" 168 + "\">" + includedService + "</a>"); 169 } 170 return bldr.toString(); 171 } 172 173 private Set<XmlType> calcMainMessageStructures() { 174 return calcMainMessageStructures(model, service.getKey()); 175 } 176 177 public static Set<XmlType> calcMainMessageStructures(ServiceContractModel mdl, 178 String serviceOptionaFilter) { 179 ModelFinder fndr = new ModelFinder(mdl); 180 Set<XmlType> types = new LinkedHashSet(); 181 for (ServiceMethod method : mdl.getServiceMethods()) { 182 if (serviceOptionaFilter != null) { 183 if (!method.getService().equalsIgnoreCase(serviceOptionaFilter)) { 184 continue; 185 } 186 } 187 XmlType type = fndr.findXmlType(stripListFromType(method.getReturnValue().getType())); 188 if (type != null) { 189 if (type.getPrimitive().equalsIgnoreCase(XmlType.COMPLEX)) { 190 types.add(type); 191 } 192 } 193 194 for (ServiceMethodParameter param : method.getParameters()) { 195 type = fndr.findXmlType(stripListFromType(param.getType())); 196 if (type != null) { 197 if (type.getPrimitive().equalsIgnoreCase(XmlType.COMPLEX)) { 198 types.add(type); 199 } 200 } 201 break; 202 } 203 } 204 return types; 205 } 206 207 private String addHTMLBreaks(String str) { 208 if (str == null) { 209 return " "; 210 } 211 return str.replaceAll("(\r\n|\r|\n|\n\r)", "<br>"); 212 } 213 214 public void writeMethod(ServiceMethod method) { 215 writer.indentPrintln("<p>"); 216 writer.indentPrintln("<a name=\"" + method.getService() + "-" 217 + method.getName() + "\"></a>"); 218 writer.indentPrintln("<p>"); 219 writer.indentPrintln("<table class=\"methodTable\">"); 220 221 writer.indentPrintln("<tr>"); 222 writer.writeTag("th", "class=h", "Method"); 223 writer.writeTag("th", "class=h colspan=3 class=\"methodName\"", 224 method.getName()); 225 writer.indentPrintln("</tr>"); 226 227 writer.indentPrintln("<tr>"); 228 writer.writeTag("th", "class=h", "Description"); 229 writer.writeTag("td", "colspan=3 class=\"methodDesc\"", 230 this.addHTMLBreaks(calcDescription(method))); 231 writer.indentPrintln("</tr>"); 232 233 if (method.getImplNotes() != null && !method.getImplNotes().isEmpty()) { 234 writer.indentPrintln("<tr>"); 235 writer.writeTag("th", "class=h", "Implementation Notes"); 236 writer.writeTag("td", "colspan=3 class=\"methodDesc\"", 237 this.addHTMLBreaks(method.getImplNotes())); 238 writer.indentPrintln("</tr>"); 239 } 240 241 if (method.getParameters().isEmpty()) { 242 writer.indentPrintln("<tr>"); 243 writer.writeTag("th", "class=h", "Parameters"); 244 writer.writeTag("td", "class=\"methodParamType\"", "None"); 245 writer.writeTag("td", "class=\"methodParamName\"", "None"); 246 writer.writeTag("td", "class=\"methodParamDesc\"", "No Parameters"); 247 writer.indentPrintln("</tr>"); 248 } else { 249 boolean firstTime = true; 250 for (ServiceMethodParameter param : method.getParameters()) { 251 writer.indentPrintln("<tr>"); 252 if (firstTime) { 253 writer.writeTag("th", "class=h rowspan=" + method.getParameters().size(), 254 "Parameters"); 255 firstTime = false; 256 } 257 writer.indentPrint("<td class=\"methodParamType\">"); 258 writer.indentPrintln("<a href=\"" + stripListFromType(param.getType()) 259 + ".html" + "\">" 260 + param.getType() + "</a>"); 261 writer.indentPrint("</td>"); 262 writer.writeTag("td", "class=\"methodParamName\"", param.getName()); 263 writer.writeTag("td", "class=\"methodParamDesc\"", this.addHTMLBreaks( 264 param.getDescription())); 265 writer.indentPrintln("</tr>"); 266 } 267 } 268 writer.indentPrintln("<tr>"); 269 writer.writeTag("th", "class=h", "Return"); 270 writer.indentPrint("<td colspan=2 class=\"methodReturnType\">"); 271 writer.indentPrintln("<a href=\"" + stripListFromType( 272 method.getReturnValue().getType()) 273 + ".html" + "\">" 274 + method.getReturnValue().getType() + "</a>"); 275 writer.indentPrint("</td>"); 276 writer.writeTag("td", "class=\"methodReturnDesc\"", 277 this.addHTMLBreaks( 278 method.getReturnValue().getDescription())); 279 writer.indentPrintln("</tr>"); 280 writer.indentPrintln("</tr>"); 281 282 if (method.getErrors().isEmpty()) { 283 writer.indentPrintln("<tr>"); 284 writer.writeTag("th", "class=h", "Errors"); 285 writer.writeTag("td", "class=\"methodErrorType\" colspan=2", "NONE"); 286 writer.writeTag("td", "class=\"methodErrorDesc\"", "No Errors"); 287 writer.indentPrintln("</tr>"); 288 } else { 289 boolean firstTime = true; 290 for (ServiceMethodError error : method.getErrors()) { 291 writer.indentPrintln("<tr>"); 292 if (firstTime) { 293 writer.writeTag("th", "class=h rowspan=" + method.getErrors().size(), 294 "Errors"); 295 firstTime = false; 296 } 297 writer.writeTag("td", "class=\"methodErrorType\" colspan=2", 298 error.getType()); // TODO wrap in link to type 299 writer.writeTag("td", "class=\"methodErrorDesc\"", this.addHTMLBreaks( 300 error.getDescription())); 301 writer.indentPrintln("</tr>"); 302 } 303 } 304 writer.indentPrintln("</table>"); 305 writer.indentPrintln("<p>"); 306 writer.indentPrintln("<a href=\"#ListOfOperations\">Back to Operations</a>"); 307 writer.indentPrintln("<p>"); 308 } 309 310 private String calcDescription(ServiceMethod method) { 311 StringBuilder sb = new StringBuilder(); 312 String newLine = ""; 313 if (method.getDescription() != null && !method.getDescription().trim().isEmpty()) { 314 sb.append(newLine); 315 newLine = "\n"; 316 sb.append(method.getDescription()); 317 } 318 if (method.isDeprecated()) { 319 sb.append(newLine); 320 newLine = "\n"; 321 sb.append("============== Deprecated ==============="); 322 } 323 return sb.toString(); 324 } 325 326 private static String stripListFromType(String type) { 327 if (type.endsWith("List")) { 328 return type.substring(0, type.length() - "List".length()); 329 } 330 return type; 331 } 332 333 public void writeStyleSheet() { 334 writer.indentPrintln("<style type=\"text/css\">"); 335 writer.indentPrintln(""); 336 writer.indentPrintln("table#serviceMetaTable {"); 337 writer.indentPrintln("border-collapse:collapse;"); 338 writer.indentPrintln("border:1px solid #000000;"); 339 writer.indentPrintln("width:95%;"); 340 writer.indentPrintln("}"); 341 writer.indentPrintln("table#serviceMetaTable th.h {"); 342 writer.indentPrintln("border:1px solid #000000;"); 343 writer.indentPrintln("background-color:#eeeeee;"); 344 writer.indentPrintln("width:15%;"); 345 writer.indentPrintln("}"); 346 writer.indentPrintln("table#serviceMetaTable td#serviceName {"); 347 writer.indentPrintln("border:1px solid #000000;"); 348 writer.indentPrintln("width:85%;"); 349 writer.indentPrintln("}"); 350 writer.indentPrintln("table#serviceMetaTable td#serviceVersion {"); 351 writer.indentPrintln("border:1px solid #000000;"); 352 writer.indentPrintln("width:70%;"); 353 writer.indentPrintln("}"); 354 writer.indentPrintln("table#serviceMetaTable td#serviceVersionHistory {"); 355 writer.indentPrintln("border:1px solid #000000;"); 356 writer.indentPrintln("width:15%;"); 357 writer.indentPrintln("}"); 358 writer.indentPrintln(""); 359 writer.indentPrintln("</style>"); 360 361 362 writer.indentPrintln("<style type=\"text/css\">"); 363 writer.indentPrintln(""); 364 writer.indentPrintln("table.methodTable {"); 365 writer.indentPrintln("border-collapse:collapse;"); 366 writer.indentPrintln("border:1px solid #000000;"); 367 writer.indentPrintln("width:95%;"); 368 writer.indentPrintln("}"); 369 writer.indentPrintln(""); 370 writer.indentPrintln("table.methodTable td.d {"); 371 writer.indentPrintln("border:1px solid #000000;"); 372 writer.indentPrintln("}"); 373 writer.indentPrintln(""); 374 writer.indentPrintln("table.methodTable th.h {"); 375 writer.indentPrintln("border:1px solid #000000;"); 376 writer.indentPrintln("background-color:#eeeeee;"); 377 writer.indentPrintln("width:15%;"); 378 writer.indentPrintln("}"); 379 writer.indentPrintln(""); 380 writer.indentPrintln("table.methodTable td.methodName {"); 381 writer.indentPrintln("border:1px solid #000000;"); 382 writer.indentPrintln("background-color:#f2f2f2;"); 383 writer.indentPrintln("color:#222222;"); 384 writer.indentPrintln("text-align:center;"); 385 writer.indentPrintln("width:85%;"); 386 writer.indentPrintln("font-weight:bold;"); 387 writer.indentPrintln("font-style:italic;"); 388 writer.indentPrintln("}"); 389 writer.indentPrintln(""); 390 writer.indentPrintln("table.methodTable td.methodDesc {"); 391 writer.indentPrintln("border:1px solid #000000;"); 392 writer.indentPrintln("width:85%;"); 393 writer.indentPrintln("}"); 394 writer.indentPrintln(""); 395 writer.indentPrintln("table.methodTable td.methodParamType {"); 396 writer.indentPrintln("border:1px solid #000000;"); 397 writer.indentPrintln("width:21%;"); 398 writer.indentPrintln("font-style:italic;"); 399 writer.indentPrintln("}"); 400 writer.indentPrintln("table.methodTable td.methodParamName {"); 401 writer.indentPrintln("border:1px solid #000000;"); 402 writer.indentPrintln("width:21%;"); 403 writer.indentPrintln("}"); 404 writer.indentPrintln("table.methodTable td.methodParamDesc {"); 405 writer.indentPrintln("border:1px solid #000000;"); 406 writer.indentPrintln("width:43%;"); 407 writer.indentPrintln("}"); 408 writer.indentPrintln("table.methodTable td.methodReturnType {"); 409 writer.indentPrintln("border:1px solid #000000;"); 410 writer.indentPrintln("width:42%;"); 411 writer.indentPrintln("font-style:italic;"); 412 writer.indentPrintln("}"); 413 writer.indentPrintln(""); 414 writer.indentPrintln("table.methodTable td.methodReturnDesc {"); 415 writer.indentPrintln("border:1px solid #000000;"); 416 writer.indentPrintln("width:43%;"); 417 writer.indentPrintln("}"); 418 writer.indentPrintln(""); 419 writer.indentPrintln("table.methodTable td.methodErrors {"); 420 writer.indentPrintln("border:1px solid #000000;"); 421 writer.indentPrintln("width:85%;"); 422 writer.indentPrintln("}"); 423 writer.indentPrintln(""); 424 writer.indentPrintln(""); 425 writer.indentPrintln("table.methodTable td.methodErrorType {"); 426 writer.indentPrintln("border:1px solid #000000;"); 427 writer.indentPrintln("width:42%;"); 428 writer.indentPrintln("font-style:italic;"); 429 writer.indentPrintln("}"); 430 writer.indentPrintln("table.methodTable td.methodErrorDesc {"); 431 writer.indentPrintln("border:1px solid #000000;"); 432 writer.indentPrintln("width:43%;"); 433 writer.indentPrintln("}"); 434 writer.indentPrintln(""); 435 writer.indentPrintln("table.methodTable td.capabilityDesc {"); 436 writer.indentPrintln("border:1px solid #000000;"); 437 writer.indentPrintln("background:#ffffff;"); 438 writer.indentPrintln("}"); 439 writer.indentPrintln(""); 440 writer.indentPrintln("table.methodTable td.usecaseDesc {"); 441 writer.indentPrintln("border:1px solid #000000;"); 442 writer.indentPrintln("background:#ffffff;"); 443 writer.indentPrintln("}"); 444 writer.indentPrintln(""); 445 writer.indentPrintln("table.methodTable td.commentsDesc {"); 446 writer.indentPrintln("border:1px solid #000000;"); 447 writer.indentPrintln("background:#ffffff;"); 448 writer.indentPrintln("}"); 449 writer.indentPrintln("</style>"); 450 451 } 452 }