001    /**
002     * Copyright 2004-2013 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 "&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    }