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.HashSet;
019    import java.util.LinkedHashSet;
020    import java.util.Set;
021    
022    import org.kuali.student.contract.model.MessageStructure;
023    import org.kuali.student.contract.model.ServiceContractModel;
024    import org.kuali.student.contract.model.ServiceMethod;
025    import org.kuali.student.contract.model.ServiceMethodParameter;
026    import org.kuali.student.contract.model.XmlType;
027    import org.kuali.student.contract.writer.HtmlWriter;
028    
029    /**
030     *
031     * @author nwright
032     */
033    public class HtmlContractMessageStructureWriter {
034    
035        private XmlType xmlType;
036        private HtmlWriter writer;
037        private ServiceContractModel model;
038        private ModelFinder finder;
039    
040        public HtmlContractMessageStructureWriter(XmlType xmlType, String directory,
041                ServiceContractModel model) {
042            this.xmlType = xmlType;
043            this.writer = new HtmlWriter(directory, xmlType.getName() + ".html",
044                    xmlType.getName());
045            this.model = model;
046            this.finder = new ModelFinder(this.model);
047        }
048    
049        private String initUpper(String str) {
050            if (str == null) {
051                return null;
052            }
053            if (str.length() == 0) {
054                return str;
055            }
056            if (str.length() == 1) {
057                return str.toUpperCase();
058            }
059            return str.substring(0, 1).toUpperCase() + str.substring(1);
060        }
061    
062        private boolean isMainMessageStructure(XmlType xmlType) {
063            if (!HtmlContractMessageStructureWriter.calcOtherXmlTypeUsages(model,
064                    xmlType).isEmpty()) {
065                return false;
066            }
067            return true;
068        }
069    
070        public void write() {
071            writer.println("<a href=\"index.html\">home</a>");
072            if (this.isMainMessageStructure(xmlType)) {
073                writer.println("<a href=\"../dictionarydocs/" + initUpper(xmlType.getName()) + ".html\">dictionary doc</a>");
074            }
075            this.writeStyleSheet();
076            writer.writeTag("h1", xmlType.getName());
077    
078            writer.indentPrintln("<table id=\"structureMetaTable\">");
079            writer.indentPrintln("<tr>");
080            writer.writeTag("th", "class=h", "Name");
081            writer.writeTag("td", "id=structureName colspan=2", xmlType.getName());
082            writer.indentPrintln("</tr>");
083    //  writer.indentPrintln ("<tr>");
084    //  writer.writeTag ("th", "class=h", "Version");
085    //  writer.writeTag ("td", "id=structureVersion colspan=2", xmlType.getVersion ());
086    //  writer.indentPrintln ("</tr>");
087            writer.indentPrintln("<tr>");
088            writer.writeTag("th", "rowspan=3 class=h", "Usage");
089            writer.indentPrint("<td id=\"structureVersion\" colspan=2>");
090            for (String servKey : xmlType.getService().split(",")) {
091                writer.indentPrintln("<a href=\"" + servKey + "Service" + ".html" + "\">"
092                        + servKey + "Service" + "</a>");
093            }
094            writer.indentPrint("</td>");
095    
096            writer.indentPrintln("</tr>");
097            writer.indentPrintln("<tr>");
098            writer.writeTag("th", "class=h", "");
099            writer.indentPrint("<td id=\"structureVersion\" colspan=2>");
100            for (ServiceMethod method : this.calcUsageByMethods(xmlType)) {
101                writer.indentPrintln("<a href=\"" + method.getService() + "Service"
102                        + ".html" + "#" + method.getService() + "-"
103                        + method.getName() + "\">"
104                        + method.getName() + "</a>");
105            }
106            writer.indentPrint("</td>");
107            writer.indentPrintln("</tr>");
108            writer.indentPrintln("<tr>");
109            writer.writeTag("th", "class=h", "");
110            writer.indentPrint("<td id=\"structureVersion\" colspan=2>");
111            for (String xmlTypeName : this.calcOtherXmlTypeUsages(xmlType)) {
112                XmlType usageType = finder.findXmlType(xmlTypeName);
113                if (usageType == null) {
114                    throw new NullPointerException("Coud not find XmlType with name="
115                            + xmlTypeName);
116                }
117                writer.indentPrintln("<a href=\"" + usageType.getName() + ".html" + "\">"
118                        + usageType.getName() + "</a>");
119            }
120            writer.indentPrint("</td>");
121            writer.indentPrintln("</tr>");
122    
123            writer.writeTag("th", "class=h", "Type");
124            writer.writeTag("td", "id=structureVersion colspan=2",
125                    xmlType.getPrimitive());
126            writer.indentPrintln("</tr>");
127            writer.indentPrintln("</table>");
128    
129            writer.writeTag("h2", "Description");
130            writer.indentPrintln(this.addHTMLBreaks(calcDescription (xmlType)));
131    
132            if (!xmlType.getPrimitive().equals(XmlType.COMPLEX)) {
133                return;
134            }
135            writer.indentPrintln(
136                    "<h2><a name=\"StructureDefinition\"></a>Structure Definition</h2>");
137    
138    
139            writer.indentPrintln("<table class=\"structTable\">");
140            writer.indentPrintln("<tr>");
141            writer.indentPrintln("<th class=\"h\">ShortName</th>");
142            writer.indentPrintln("<th class=\"h\">Name</th>");
143            writer.indentPrintln("<th class=\"h\">Type</th>");
144            writer.indentPrintln("<th class=\"h\">Description</th>");
145            writer.indentPrintln("<th class=\"h\">Required?</th>");
146            writer.indentPrintln("<th class=\"h\">Read only?</th>");
147            writer.indentPrintln("<th class=\"h\">Cardinality</th>");
148            writer.indentPrintln("<th class=\"h\">XML Attribute?</th>");
149    //        writer.indentPrintln ("<th class=\"h\">Status</th>"); 
150            writer.indentPrintln("<th class=\"h\">Implementation Notes</th>");
151            writer.indentPrintln("</tr>");
152    
153            for (MessageStructure ms : finder.findMessageStructures(xmlType.getName())) {
154                this.writeMessageStructure(ms);
155            }
156            writer.indentPrintln("</table>");
157            writer.writeHeaderBodyAndFooterOutToFile();
158        }
159    
160        
161         private String calcDescription(XmlType xmlType) {
162            StringBuilder sb = new StringBuilder();
163            String newLine = "";
164            if (xmlType.getDesc() != null && !xmlType.getDesc().trim().isEmpty()) {
165                sb.append(newLine);
166                newLine = "\n";
167                sb.append(xmlType.getDesc ());
168            }
169            if (xmlType.isDeprecated()) {
170                sb.append(newLine);
171                newLine = "\n";
172                sb.append("============== Deprecated ===============");
173            }
174            return sb.toString();
175        }
176    
177        private String checkForNbsp(String str) {
178            if (str == null) {
179                return "&nbsp;";
180            }
181            if (str.trim().isEmpty()) {
182                return "&nbsp;";
183            }
184            return str;
185        }
186    
187        private String addHTMLBreaks(String str) {
188            if (str == null) {
189                return "&nbsp;";
190            }
191            return str.replaceAll("(\r\n|\r|\n|\n\r)", "<br>");
192        }
193    
194        public static Set<String> calcUsageByService(ServiceContractModel mdl, XmlType xmlType) {
195            Set<String> services = new HashSet();
196            for (ServiceMethod method : calcUsageByMethods(mdl, xmlType)) {
197                services.add(method.getService());
198            }
199            return services;
200        }
201    
202        private Set<ServiceMethod> calcUsageByMethods(XmlType xmlType) {
203            return calcUsageByMethods(model, xmlType);
204        }
205    
206        public static Set<ServiceMethod> calcUsageByMethods(ServiceContractModel mdl, XmlType xmlType) {
207            Set<ServiceMethod> methods = new LinkedHashSet();
208            for (ServiceMethod method : mdl.getServiceMethods()) {
209                if (stripListFromType(method.getReturnValue().getType()).equalsIgnoreCase(xmlType.getName())) {
210                    methods.add(method);
211                    continue;
212                }
213                for (ServiceMethodParameter param : method.getParameters()) {
214                    if (stripListFromType(param.getType()).equalsIgnoreCase(xmlType.getName())) {
215                        methods.add(method);
216                        break;
217                    }
218                }
219            }
220            return methods;
221        }
222    
223        private Set<String> calcOtherXmlTypeUsages(XmlType xmlType) {
224            return calcOtherXmlTypeUsages(model, xmlType);
225        }
226    
227        public static Set<String> calcOtherXmlTypeUsages(ServiceContractModel mdl,
228                XmlType xmlType) {
229            Set<String> xmlTypeNames = new LinkedHashSet();
230            for (MessageStructure ms : mdl.getMessageStructures()) {
231                if (ms.getType() == null) {
232                    throw new NullPointerException(ms.getId() + " has no type set");
233                }
234                if (stripListFromType(ms.getType()).equalsIgnoreCase(xmlType.getName())) {
235                    xmlTypeNames.add(ms.getXmlObject());
236                }
237            }
238            return xmlTypeNames;
239        }
240    
241        private void writeMessageStructure(MessageStructure ms) {
242            writer.indentPrintln("<tr>");
243            writer.writeTag("td", "class=\"structSName\"", ms.getShortName());
244            writer.writeTag("td", "class=\"structLName\"", ms.getName());
245            XmlType subType = finder.findXmlType(this.stripListFromType(ms.getType()));
246            if (subType == null) {
247                for (XmlType xmlt : model.getXmlTypes()) {
248                    System.out.println(this.getClass().getSimpleName() + ": "
249                            + xmlt.getName());
250                }
251                throw new NullPointerException(ms.getXmlObject() + "." + ms.getShortName()
252                        + " has type " + ms.getType()
253                        + " was not found in list of known types");
254            }
255            if (subType.getPrimitive().equals(XmlType.COMPLEX)) {
256                writer.indentPrint("<td class=\"structType\">");
257                writer.indentPrintln("<a href=\"" + subType.getName() + ".html" + "\">"
258                        + ms.getType() + "</a>");
259                writer.indentPrint("</td>");
260            } else {
261                writer.writeTag("td", "class=\"structType\"", ms.getType());
262            }
263            writer.writeTag("td", "class=\"structDesc\"", addHTMLBreaks(missingData(
264                    calcDescription(ms))));
265            writer.writeTag("td", "class=\"structOpt\"", checkForNbsp(ms.getRequired()));
266            writer.writeTag("td", "class=\"structOpt\"", checkForNbsp(ms.getReadOnly()));
267    
268            writer.writeTag("td", "class=\"structCard\"", ms.getCardinality());
269            writer.writeTag("td", "class=\"structAttr\"", ms.getXmlAttribute());
270    //      writer.writeTag ("td", "class=\"structStatus\"", ms.getStatus ());
271            writer.writeTag("td", "class=\"commentsDesc\"", addHTMLBreaks(this.checkForNbsp(ms.getImplNotes())));
272            writer.indentPrintln("</tr>");
273    
274    //  writer.indentPrintln ("</table>");
275    //  writer.indentPrintln ("<p>");
276    
277    //  writer.indentPrintln ("<p>");
278        }
279    
280        private String calcDescription(MessageStructure ms) {
281            StringBuilder sb = new StringBuilder();
282            String newLine = "";
283            if (ms.getDescription() != null && !ms.getDescription().trim().isEmpty()) {
284                sb.append(newLine);
285                newLine = "\n";
286                sb.append(ms.getDescription());
287            }
288            if (ms.isDeprecated()) {
289                sb.append(newLine);
290                newLine = "\n";
291                sb.append("============== Deprecated ===============");
292            }
293            return sb.toString();
294        }
295    
296        private String missingData(String str) {
297            if (str == null) {
298                return "???";
299            }
300            if (str.trim().isEmpty()) {
301                return "???";
302            }
303            return str;
304        }
305    
306        private static String stripListFromType(String type) {
307            if (type.endsWith("List")) {
308                return type.substring(0, type.length() - "List".length());
309            }
310            return type;
311        }
312    
313        public void writeStyleSheet() {
314            writer.indentPrintln("<style type=\"text/css\">");
315            writer.indentPrintln("");
316            writer.indentPrintln("table#structureMetaTable {");
317            writer.indentPrintln("border-collapse:collapse;");
318            writer.indentPrintln("border:1px solid #000000;");
319            writer.indentPrintln("width:95%;");
320            writer.indentPrintln("}");
321            writer.indentPrintln("table#structureMetaTable th.h {");
322            writer.indentPrintln("border:1px solid #000000;");
323            writer.indentPrintln("background-color:#eeeeee;");
324            writer.indentPrintln("width:15%;");
325            writer.indentPrintln("}");
326            writer.indentPrintln("table#structureMetaTable td#structureName {");
327            writer.indentPrintln("border:1px solid #000000;");
328            writer.indentPrintln("width:85%;");
329            writer.indentPrintln("}");
330            writer.indentPrintln("table#structureMetaTable td#structureVersion {");
331            writer.indentPrintln("border:1px solid #000000;");
332            writer.indentPrintln("width:70%;");
333            writer.indentPrintln("}");
334            writer.indentPrintln("table#structureMetaTable td#structureVersionHistory {");
335            writer.indentPrintln("border:1px solid #000000;");
336            writer.indentPrintln("width:15%;");
337            writer.indentPrintln("}");
338            writer.indentPrintln("");
339            writer.indentPrintln("</style>");
340    
341            writer.indentPrintln("<style type=\"text/css\">");
342            writer.indentPrintln("");
343            writer.indentPrintln("table.structTable {");
344            writer.indentPrintln("border-collapse:collapse;");
345            writer.indentPrintln("border:1px solid #000000;");
346            writer.indentPrintln("width:95%;");
347            writer.indentPrintln("}");
348            writer.indentPrintln("");
349            writer.indentPrintln("table.structTable td.d {");
350            writer.indentPrintln("border:1px solid #000000;");
351            writer.indentPrintln("}");
352            writer.indentPrintln("");
353            writer.indentPrintln("table.structTable th.h {");
354            writer.indentPrintln("border:1px solid #000000;");
355            writer.indentPrintln("background-color:#eeeeee;");
356            writer.indentPrintln("}");
357            writer.indentPrintln("");
358            writer.indentPrintln("table.structTable td.structSName {");
359            writer.indentPrintln("border:1px solid #000000;");
360            writer.indentPrintln("background-color:#f2f2f2;");
361            writer.indentPrintln("color:#222222;");
362            writer.indentPrintln("text-align:left;");
363            writer.indentPrintln("vertical-align:top;");
364            writer.indentPrintln("font-weight:bold;");
365            writer.indentPrintln("font-style:italic;");
366            writer.indentPrintln("");
367            writer.indentPrintln("}");
368            writer.indentPrintln("");
369            writer.indentPrintln("table.structTable td.structLName {");
370            writer.indentPrintln("border:1px solid #000000;");
371            writer.indentPrintln("background:#ffffff;");
372            writer.indentPrintln("vertical-align:top;");
373            writer.indentPrintln("");
374            writer.indentPrintln("}");
375            writer.indentPrintln("");
376            writer.indentPrintln("table.structTable td.structType {");
377            writer.indentPrintln("border:1px solid #000000;");
378            writer.indentPrintln("background:#ffffff;");
379            writer.indentPrintln("vertical-align:top;");
380            writer.indentPrintln("font-style:italic;");
381            writer.indentPrintln("");
382            writer.indentPrintln("}");
383            writer.indentPrintln("");
384            writer.indentPrintln("table.structTable td.structDesc {");
385            writer.indentPrintln("border:1px solid #000000;");
386            writer.indentPrintln("background:#ffffff;");
387            writer.indentPrintln("vertical-align:top;");
388            writer.indentPrintln("");
389            writer.indentPrintln("}");
390            writer.indentPrintln("");
391            writer.indentPrintln("table.structTable td.structOpt {");
392            writer.indentPrintln("border:1px solid #000000;");
393            writer.indentPrintln("background:#ffffff;");
394            writer.indentPrintln("vertical-align:top;");
395            writer.indentPrintln("text-align: center;");
396            writer.indentPrintln("}");
397            writer.indentPrintln("");
398            writer.indentPrintln("table.structTable td.structReq {");
399            writer.indentPrintln("border:1px solid #000000;");
400            writer.indentPrintln("background:#ccccff;");
401            writer.indentPrintln("vertical-align:top;");
402            writer.indentPrintln("text-align: center;");
403            writer.indentPrintln("}");
404            writer.indentPrintln("");
405            writer.indentPrintln("");
406            writer.indentPrintln("table.structTable td.structCard {");
407            writer.indentPrintln("border:1px solid #000000;");
408            writer.indentPrintln("background:#ffffff;");
409            writer.indentPrintln("vertical-align:top;");
410            writer.indentPrintln("text-align: center;");
411            writer.indentPrintln("}");
412            writer.indentPrintln("");
413            writer.indentPrintln("table.structTable td.structAttr {");
414            writer.indentPrintln("border:1px solid #000000;");
415            writer.indentPrintln("background:#ffffff;");
416            writer.indentPrintln("vertical-align:top;");
417            writer.indentPrintln("text-align: center;");
418            writer.indentPrintln("}");
419            writer.indentPrintln("");
420            writer.indentPrintln("table.structTable td.structElem {");
421            writer.indentPrintln("border:1px solid #000000;");
422            writer.indentPrintln("background:#ccccff;");
423            writer.indentPrintln("vertical-align:top;");
424            writer.indentPrintln("text-align: center;");
425            writer.indentPrintln("}");
426            writer.indentPrintln("");
427            writer.indentPrintln("table.structTable td.structStatus {");
428            writer.indentPrintln("border:1px solid #000000;");
429            writer.indentPrintln("background:#ffffff;");
430            writer.indentPrintln("vertical-align:top;");
431            writer.indentPrintln("text-align: center;");
432            writer.indentPrintln("");
433            writer.indentPrintln("}");
434            writer.indentPrintln("");
435            writer.indentPrintln("table.structTable td.commentsDesc {");
436            writer.indentPrintln("border:1px solid #000000;");
437            writer.indentPrintln("background:#ffffff;");
438            writer.indentPrintln("vertical-align:top;");
439            writer.indentPrintln("");
440            writer.indentPrintln("}");
441            writer.indentPrintln("");
442            writer.indentPrintln("");
443            writer.indentPrintln("</style>");
444    
445    
446        }
447    }