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 */
016package org.kuali.student.contract.model.util;
017
018import java.util.Date;
019import java.util.LinkedHashSet;
020import java.util.List;
021import java.util.Set;
022
023import org.kuali.student.contract.model.Service;
024import org.kuali.student.contract.model.ServiceContractModel;
025import org.kuali.student.contract.model.ServiceMethod;
026import org.kuali.student.contract.model.ServiceMethodError;
027import org.kuali.student.contract.model.ServiceMethodParameter;
028import org.kuali.student.contract.model.XmlType;
029import org.kuali.student.contract.writer.HtmlWriter;
030
031/**
032 *
033 * @author nwright
034 */
035public 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 "&nbsp;";
158        }
159        if (includedServices.isEmpty()) {
160            return "&nbsp;";
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 "&nbsp;";
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}