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 "&nbsp;";
144            }
145            if (includedServices.isEmpty()) {
146                return "&nbsp;";
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 "&nbsp;";
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    }