View Javadoc

1   /**
2    * Copyright 2004-2013 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.student.contract.model.util;
17  
18  import java.util.HashSet;
19  import java.util.LinkedHashSet;
20  import java.util.Set;
21  import org.kuali.student.contract.model.Lookup;
22  
23  import org.kuali.student.contract.model.MessageStructure;
24  import org.kuali.student.contract.model.ServiceContractModel;
25  import org.kuali.student.contract.model.ServiceMethod;
26  import org.kuali.student.contract.model.ServiceMethodParameter;
27  import org.kuali.student.contract.model.XmlType;
28  import org.kuali.student.contract.writer.HtmlWriter;
29  import org.slf4j.Logger;
30  import org.slf4j.LoggerFactory;
31  
32  /**
33   *
34   * @author nwright
35   */
36  public class HtmlContractMessageStructureWriter {
37  
38  	private static final Logger log = LoggerFactory.getLogger(HtmlContractMessageStructureWriter.class);
39  	
40      private XmlType xmlType;
41      private HtmlWriter writer;
42      private ServiceContractModel model;
43      private ModelFinder finder;
44  
45      public HtmlContractMessageStructureWriter(XmlType xmlType, String directory,
46              ServiceContractModel model) {
47          this.xmlType = xmlType;
48          this.writer = new HtmlWriter(directory, xmlType.getName() + ".html",
49                  xmlType.getName());
50          this.model = model;
51          this.finder = new ModelFinder(this.model);
52      }
53  
54      private String initUpper(String str) {
55          if (str == null) {
56              return null;
57          }
58          if (str.length() == 0) {
59              return str;
60          }
61          if (str.length() == 1) {
62              return str.toUpperCase();
63          }
64          return str.substring(0, 1).toUpperCase() + str.substring(1);
65      }
66  
67      private boolean isMainMessageStructure(XmlType xmlType) {
68          if (!HtmlContractMessageStructureWriter.calcOtherXmlTypeUsages(model,
69                  xmlType).isEmpty()) {
70              return false;
71          }
72          return true;
73      }
74  
75      public void write(String projectVersion, String formattedDate) {
76         
77          this.writeStyleSheet();
78         
79          
80          if (this.isMainMessageStructure(xmlType)) {
81          	VersionLinesUtility.writeVersionTag(writer, "<a href=\"index.html\">home</a>", "<a href=\"../dictionarydocs/" + initUpper(xmlType.getName()) + ".html\">dictionary doc</a>", projectVersion, formattedDate);
82          }
83          else 
84          	VersionLinesUtility.writeVersionTag(writer, "<a href=\"index.html\">home</a>", "" ,projectVersion, formattedDate);
85          
86  
87          writer.writeTag("h1", xmlType.getName());
88          
89          writer.indentPrintln("<table id=\"structureMetaTable\">");
90          writer.indentPrintln("<tr>");
91          writer.writeTag("th", "class=h", "Name");
92          writer.writeTag("td", "id=structureName colspan=2", xmlType.getName());
93          writer.indentPrintln("</tr>");
94  //  writer.indentPrintln ("<tr>");
95  //  writer.writeTag ("th", "class=h", "Version");
96  //  writer.writeTag ("td", "id=structureVersion colspan=2", xmlType.getVersion ());
97  //  writer.indentPrintln ("</tr>");
98          writer.indentPrintln("<tr>");
99          writer.writeTag("th", "rowspan=3 class=h", "Usage");
100         writer.indentPrint("<td id=\"structureVersion\" colspan=2>");
101         for (String servKey : xmlType.getService().split(",")) {
102             writer.indentPrintln("<a href=\"" + servKey + "Service" + ".html" + "\">"
103                     + servKey + "Service" + "</a>");
104         }
105         writer.indentPrint("</td>");
106 
107         writer.indentPrintln("</tr>");
108         writer.indentPrintln("<tr>");
109         writer.writeTag("th", "class=h", "");
110         writer.indentPrint("<td id=\"structureVersion\" colspan=2>");
111         for (ServiceMethod method : this.calcUsageByMethods(xmlType)) {
112             writer.indentPrintln("<a href=\"" + method.getService() + "Service"
113                     + ".html" + "#" + method.getService() + "-"
114                     + method.getName() + "\">"
115                     + method.getName() + "</a>");
116         }
117         writer.indentPrint("</td>");
118         writer.indentPrintln("</tr>");
119         writer.indentPrintln("<tr>");
120         writer.writeTag("th", "class=h", "");
121         writer.indentPrint("<td id=\"structureVersion\" colspan=2>");
122         for (String xmlTypeName : this.calcOtherXmlTypeUsages(xmlType)) {
123             XmlType usageType = finder.findXmlType(xmlTypeName);
124             if (usageType == null) {
125                 throw new NullPointerException("Coud not find XmlType with name="
126                         + xmlTypeName);
127             }
128             writer.indentPrintln("<a href=\"" + usageType.getName() + ".html" + "\">"
129                     + usageType.getName() + "</a>");
130         }
131         writer.indentPrint("</td>");
132         writer.indentPrintln("</tr>");
133 
134         writer.writeTag("th", "class=h", "Type");
135         writer.writeTag("td", "id=structureVersion colspan=2",
136                 xmlType.getPrimitive());
137         writer.indentPrintln("</tr>");
138         writer.indentPrintln("</table>");
139 
140         writer.writeTag("h2", "Description");
141         writer.indentPrintln(this.addHTMLBreaks(calcDescription (xmlType)));
142 
143         if (!xmlType.getPrimitive().equals(XmlType.COMPLEX)) {
144             return;
145         }
146         writer.indentPrintln(
147                 "<h2><a name=\"StructureDefinition\"></a>Structure Definition</h2>");
148 
149 
150         writer.indentPrintln("<table class=\"structTable\">");
151         writer.indentPrintln("<tr>");
152         writer.indentPrintln("<th class=\"h\">ShortName</th>");
153         writer.indentPrintln("<th class=\"h\">Name</th>");
154         writer.indentPrintln("<th class=\"h\">Type</th>");
155         writer.indentPrintln("<th class=\"h\">Description</th>");
156         writer.indentPrintln("<th class=\"h\">Required?</th>");
157         writer.indentPrintln("<th class=\"h\">Read only?</th>");
158         writer.indentPrintln("<th class=\"h\">Lookup (WIP)</th>");
159         writer.indentPrintln("<th class=\"h\">Implementation Notes</th>");
160         writer.indentPrintln("</tr>");
161 
162         for (MessageStructure ms : finder.findMessageStructures(xmlType.getName())) {
163             this.writeMessageStructure(ms);
164         }
165         writer.indentPrintln("</table>");
166         writer.writeHeaderBodyAndFooterOutToFile();
167     }
168 
169     
170      private String calcDescription(XmlType xmlType) {
171         StringBuilder sb = new StringBuilder();
172         String newLine = "";
173         if (xmlType.getDesc() != null && !xmlType.getDesc().trim().isEmpty()) {
174             sb.append(newLine);
175             newLine = "\n";
176             sb.append(xmlType.getDesc ());
177         }
178         if (xmlType.isDeprecated()) {
179             sb.append(newLine);
180             newLine = "\n";
181             sb.append("============== Deprecated ===============");
182         }
183         return sb.toString();
184     }
185 
186     private String checkForNbsp(String str) {
187         if (str == null) {
188             return "&nbsp;";
189         }
190         if (str.trim().isEmpty()) {
191             return "&nbsp;";
192         }
193         return str;
194     }
195 
196     private String addHTMLBreaks(String str) {
197         if (str == null) {
198             return "&nbsp;";
199         }
200         return str.replaceAll("(\r\n|\r|\n|\n\r)", "<br>");
201     }
202 
203     public static Set<String> calcUsageByService(ServiceContractModel mdl, XmlType xmlType) {
204         Set<String> services = new HashSet();
205         for (ServiceMethod method : calcUsageByMethods(mdl, xmlType)) {
206             services.add(method.getService());
207         }
208         return services;
209     }
210 
211     private Set<ServiceMethod> calcUsageByMethods(XmlType xmlType) {
212         return calcUsageByMethods(model, xmlType);
213     }
214 
215     public static Set<ServiceMethod> calcUsageByMethods(ServiceContractModel mdl, XmlType xmlType) {
216         Set<ServiceMethod> methods = new LinkedHashSet();
217         for (ServiceMethod method : mdl.getServiceMethods()) {
218             if (stripListFromType(method.getReturnValue().getType()).equalsIgnoreCase(xmlType.getName())) {
219                 methods.add(method);
220                 continue;
221             }
222             for (ServiceMethodParameter param : method.getParameters()) {
223                 if (stripListFromType(param.getType()).equalsIgnoreCase(xmlType.getName())) {
224                     methods.add(method);
225                     break;
226                 }
227             }
228         }
229         return methods;
230     }
231 
232     private Set<String> calcOtherXmlTypeUsages(XmlType xmlType) {
233         return calcOtherXmlTypeUsages(model, xmlType);
234     }
235 
236     public static Set<String> calcOtherXmlTypeUsages(ServiceContractModel mdl,
237             XmlType xmlType) {
238         Set<String> xmlTypeNames = new LinkedHashSet();
239         for (MessageStructure ms : mdl.getMessageStructures()) {
240             if (ms.getType() == null) {
241                 throw new NullPointerException(ms.getId() + " has no type set");
242             }
243             if (stripListFromType(ms.getType()).equalsIgnoreCase(xmlType.getName())) {
244                 xmlTypeNames.add(ms.getXmlObject());
245             }
246         }
247         return xmlTypeNames;
248     }
249 
250     private void writeMessageStructure(MessageStructure ms) {
251         writer.indentPrintln("<tr>");
252         writer.writeTag("td", "class=\"structSName\"", ms.getShortName());
253         writer.writeTag("td", "class=\"structLName\"", ms.getName());
254         XmlType subType = finder.findXmlType(this.stripListFromType(ms.getType()));
255         if (subType == null) {
256 //            for (XmlType xmlt : model.getXmlTypes()) {
257 //                System.out.println(this.getClass().getSimpleName() + ": "
258 //                        + xmlt.getName());
259 //            }
260 //            throw new NullPointerException(ms.getXmlObject() + "." + ms.getShortName()
261 //                    + " has type " + ms.getType()
262 //                    + " was not found in list of known types");
263         	
264         	log.error (ms.getXmlObject() + "." + ms.getShortName()
265                   + " has type " + ms.getType()
266                   + " was not found in list of known types");
267         	return;
268         }
269         if (subType.getPrimitive().equals(XmlType.COMPLEX)) {
270             writer.indentPrint("<td class=\"structType\">");
271             writer.indentPrintln("<a href=\"" + subType.getName() + ".html" + "\">"
272                     + ms.getType() + "</a>");
273             writer.indentPrint("</td>");
274         } else {
275             writer.writeTag("td", "class=\"structType\"", ms.getType());
276         }
277         writer.writeTag("td", "class=\"structDesc\"", addHTMLBreaks(missingData(
278                 calcDescription(ms))));
279         writer.writeTag("td", "class=\"structOpt\"", checkForNbsp(ms.getRequired()));
280         writer.writeTag("td", "class=\"structOpt\"", checkForNbsp(ms.getReadOnly()));
281 
282         writer.writeTag("td", "class=\"structCard\"", addHTMLBreaks (checkForNbsp (calcLookup (ms.getLookup ()))));
283 //      writer.writeTag ("td", "class=\"structStatus\"", ms.getStatus ());
284         writer.writeTag("td", "class=\"commentsDesc\"", addHTMLBreaks(this.checkForNbsp(ms.getImplNotes())));
285         writer.indentPrintln("</tr>");
286 
287 //  writer.indentPrintln ("</table>");
288 //  writer.indentPrintln ("<p>");
289 
290 //  writer.indentPrintln ("<p>");
291     }
292 
293     private String calcLookup(Lookup lookup) {
294         if (lookup == null) {
295             return null;
296         }
297         StringBuilder sb = new StringBuilder();
298         String newLine = "\n";
299         sb.append(lookup.getServiceKey());
300         sb.append(":");
301         sb.append(lookup.getXmlTypeName());
302         if (lookup.getGetMethod() != null) {
303             sb.append(newLine);
304             sb.append(lookup.getGetMethod());
305         }
306         if (lookup.getSearchMethod() != null) {
307             sb.append(newLine);
308             sb.append(lookup.getSearchMethod());
309             if (lookup.getAdditionalCriteria() != null) {
310                 sb.append(newLine);
311                 sb.append(lookup.getAdditionalCriteria().toString());
312             }
313         }
314         return sb.toString();
315     }
316     
317     private String calcDescription(MessageStructure ms) {
318         StringBuilder sb = new StringBuilder();
319         String newLine = "";
320         if (ms.getDescription() != null && !ms.getDescription().trim().isEmpty()) {
321             sb.append(newLine);
322             newLine = "\n";
323             sb.append(ms.getDescription());
324         }
325         if (ms.isDeprecated()) {
326             sb.append(newLine);
327             newLine = "\n";
328             sb.append("============== Deprecated ===============");
329         }
330         return sb.toString();
331     }
332 
333     private String missingData(String str) {
334         if (str == null) {
335             return "???";
336         }
337         if (str.trim().isEmpty()) {
338             return "???";
339         }
340         return str;
341     }
342 
343     private static String stripListFromType(String type) {
344         if (type.endsWith("List")) {
345             return type.substring(0, type.length() - "List".length());
346         }
347         return type;
348     }
349 
350     public void writeStyleSheet() {
351         writer.indentPrintln("<style type=\"text/css\">");
352         writer.indentPrintln("");
353         writer.indentPrintln("table#structureMetaTable {");
354         writer.indentPrintln("border-collapse:collapse;");
355         writer.indentPrintln("border:1px solid #000000;");
356         writer.indentPrintln("width:95%;");
357         writer.indentPrintln("}");
358         writer.indentPrintln("table#structureMetaTable th.h {");
359         writer.indentPrintln("border:1px solid #000000;");
360         writer.indentPrintln("background-color:#eeeeee;");
361         writer.indentPrintln("width:15%;");
362         writer.indentPrintln("}");
363         writer.indentPrintln("table#structureMetaTable td#structureName {");
364         writer.indentPrintln("border:1px solid #000000;");
365         writer.indentPrintln("width:85%;");
366         writer.indentPrintln("}");
367         writer.indentPrintln("table#structureMetaTable td#structureVersion {");
368         writer.indentPrintln("border:1px solid #000000;");
369         writer.indentPrintln("width:70%;");
370         writer.indentPrintln("}");
371         writer.indentPrintln("table#structureMetaTable td#structureVersionHistory {");
372         writer.indentPrintln("border:1px solid #000000;");
373         writer.indentPrintln("width:15%;");
374         writer.indentPrintln("}");
375         writer.indentPrintln("");
376         writer.indentPrintln("</style>");
377 
378         writer.indentPrintln("<style type=\"text/css\">");
379         writer.indentPrintln("");
380         writer.indentPrintln("table.structTable {");
381         writer.indentPrintln("border-collapse:collapse;");
382         writer.indentPrintln("border:1px solid #000000;");
383         writer.indentPrintln("width:95%;");
384         writer.indentPrintln("}");
385         writer.indentPrintln("");
386         writer.indentPrintln("table.structTable td.d {");
387         writer.indentPrintln("border:1px solid #000000;");
388         writer.indentPrintln("}");
389         writer.indentPrintln("");
390         writer.indentPrintln("table.structTable th.h {");
391         writer.indentPrintln("border:1px solid #000000;");
392         writer.indentPrintln("background-color:#eeeeee;");
393         writer.indentPrintln("}");
394         writer.indentPrintln("");
395         writer.indentPrintln("table.structTable td.structSName {");
396         writer.indentPrintln("border:1px solid #000000;");
397         writer.indentPrintln("background-color:#f2f2f2;");
398         writer.indentPrintln("color:#222222;");
399         writer.indentPrintln("text-align:left;");
400         writer.indentPrintln("vertical-align:top;");
401         writer.indentPrintln("font-weight:bold;");
402         writer.indentPrintln("font-style:italic;");
403         writer.indentPrintln("");
404         writer.indentPrintln("}");
405         writer.indentPrintln("");
406         writer.indentPrintln("table.structTable td.structLName {");
407         writer.indentPrintln("border:1px solid #000000;");
408         writer.indentPrintln("background:#ffffff;");
409         writer.indentPrintln("vertical-align:top;");
410         writer.indentPrintln("");
411         writer.indentPrintln("}");
412         writer.indentPrintln("");
413         writer.indentPrintln("table.structTable td.structType {");
414         writer.indentPrintln("border:1px solid #000000;");
415         writer.indentPrintln("background:#ffffff;");
416         writer.indentPrintln("vertical-align:top;");
417         writer.indentPrintln("font-style:italic;");
418         writer.indentPrintln("");
419         writer.indentPrintln("}");
420         writer.indentPrintln("");
421         writer.indentPrintln("table.structTable td.structDesc {");
422         writer.indentPrintln("border:1px solid #000000;");
423         writer.indentPrintln("background:#ffffff;");
424         writer.indentPrintln("vertical-align:top;");
425         writer.indentPrintln("");
426         writer.indentPrintln("}");
427         writer.indentPrintln("");
428         writer.indentPrintln("table.structTable td.structOpt {");
429         writer.indentPrintln("border:1px solid #000000;");
430         writer.indentPrintln("background:#ffffff;");
431         writer.indentPrintln("vertical-align:top;");
432         writer.indentPrintln("text-align: center;");
433         writer.indentPrintln("}");
434         writer.indentPrintln("");
435         writer.indentPrintln("table.structTable td.structReq {");
436         writer.indentPrintln("border:1px solid #000000;");
437         writer.indentPrintln("background:#ccccff;");
438         writer.indentPrintln("vertical-align:top;");
439         writer.indentPrintln("text-align: center;");
440         writer.indentPrintln("}");
441         writer.indentPrintln("");
442         writer.indentPrintln("");
443         writer.indentPrintln("table.structTable td.structCard {");
444         writer.indentPrintln("border:1px solid #000000;");
445         writer.indentPrintln("background:#ffffff;");
446         writer.indentPrintln("vertical-align:top;");
447         writer.indentPrintln("text-align: center;");
448         writer.indentPrintln("}");
449         writer.indentPrintln("");
450         writer.indentPrintln("table.structTable td.structAttr {");
451         writer.indentPrintln("border:1px solid #000000;");
452         writer.indentPrintln("background:#ffffff;");
453         writer.indentPrintln("vertical-align:top;");
454         writer.indentPrintln("text-align: center;");
455         writer.indentPrintln("}");
456         writer.indentPrintln("");
457         writer.indentPrintln("table.structTable td.structElem {");
458         writer.indentPrintln("border:1px solid #000000;");
459         writer.indentPrintln("background:#ccccff;");
460         writer.indentPrintln("vertical-align:top;");
461         writer.indentPrintln("text-align: center;");
462         writer.indentPrintln("}");
463         writer.indentPrintln("");
464         writer.indentPrintln("table.structTable td.structStatus {");
465         writer.indentPrintln("border:1px solid #000000;");
466         writer.indentPrintln("background:#ffffff;");
467         writer.indentPrintln("vertical-align:top;");
468         writer.indentPrintln("text-align: center;");
469         writer.indentPrintln("");
470         writer.indentPrintln("}");
471         writer.indentPrintln("");
472         writer.indentPrintln("table.structTable td.commentsDesc {");
473         writer.indentPrintln("border:1px solid #000000;");
474         writer.indentPrintln("background:#ffffff;");
475         writer.indentPrintln("vertical-align:top;");
476         writer.indentPrintln("");
477         writer.indentPrintln("}");
478         writer.indentPrintln("");
479         writer.indentPrintln("");
480         writer.indentPrintln("</style>");
481 
482 
483     }
484 }