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