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