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