View Javadoc

1   /*
2    * Copyright 2011 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.osedu.org/licenses/ECL-2.0
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.ArrayList;
19  import java.util.Collections;
20  import java.util.Comparator;
21  import java.util.Date;
22  import java.util.Enumeration;
23  import java.util.List;
24  import java.util.Stack;
25  
26  import org.kuali.student.contract.model.MessageStructure;
27  import org.kuali.student.contract.model.Service;
28  import org.kuali.student.contract.model.ServiceContractModel;
29  import org.kuali.student.contract.model.XmlType;
30  import org.kuali.student.contract.writer.HtmlWriter;
31  
32  /**
33   *
34   * @author nwright
35   */
36  public class HtmlContractWriter {
37  
38      private HtmlWriter writer;
39      private ServiceContractModel model;
40      private ModelFinder finder;
41      private String directory;
42  
43      public HtmlContractWriter(String directory,
44              ServiceContractModel model) {
45          this.writer = new HtmlWriter(directory, "index.html",
46                  "Service Contracts Index");
47          this.directory = directory;
48          this.model = model;
49          this.finder = new ModelFinder(this.model);
50      }
51  
52      public void write(String projectVersion, String formattedDate) {
53          this.writeIndexPage(projectVersion, formattedDate);
54          for (Service service : model.getServices()) {
55              HtmlContractServiceWriter swriter = new HtmlContractServiceWriter(service,
56                      directory,
57                      model);
58              swriter.write(projectVersion, formattedDate);
59          }
60          for (XmlType xmlType : model.getXmlTypes()) {
61              HtmlContractMessageStructureWriter msWriter =
62                      new HtmlContractMessageStructureWriter(
63                      xmlType,
64                      directory,
65                      model);
66              msWriter.write(projectVersion, formattedDate);
67          }
68      }
69      private static final Comparator<XmlType> XML_TYPE_NAME_COMPARATOR =
70              new Comparator<XmlType>() {
71  
72                  @Override
73                  public int compare(XmlType e1, XmlType e2) {
74                      return e1.getName().toLowerCase().compareTo(e2.getName().toLowerCase());
75                  }
76              };
77      private static final Comparator<Service> SERVICE_NAME_COMPARATOR =
78              new Comparator<Service>() {
79  
80                  @Override
81                  public int compare(Service e1, Service e2) {
82                      return e1.getName().compareTo(e2.getName());
83                  }
84              };
85      private static final Comparator<Service> SERVICE_IMPL_NAME_COMPARATOR =
86              new Comparator<Service>() {
87  
88                  @Override
89                  public int compare(Service e1, Service e2) {
90                      String x1 = calcArea(e1) + "." + e1.getName();
91                      String x2 = calcArea(e2) + "." + e2.getName();
92                      return x1.compareTo(x2);
93                  }
94              };
95  
96      private void writeIndexPage(String projectVersion, String formattedDate) {
97          
98          VersionLinesUtility.writeVersionTag(writer, "<a href=\"index.html\">Home</a>", "<a href=\"../dictionarydocs/index.html\">Dictionary Docs Home</a>", projectVersion, formattedDate);
99          
100         writer.writeTag("h1", "Service Contracts");
101         
102         
103 
104         writer.indentPrintln(
105                 "<div class=\"panel\" style=\"background-color: rgb(255, 255, 255); border: 1px solid rgb(204, 204, 204);\">");
106         writer.indentPrintln(
107                 "<div class=\"panelHeader\" style=\"border-bottom: 1px solid rgb(204, 204, 204); background-color: rgb(238, 238, 238);\">");
108         writer.indentPrintln("<b><a name=\"Services\"></a>Services</b>");
109         writer.indentPrintln(
110                 "</div><div class=\"panelContent\" style=\"background-color: rgb(255, 255, 255);\">");
111         writer.indentPrintln("<ul>");
112         List<Service> services = new ArrayList(model.getServices());
113         Collections.sort(services, SERVICE_IMPL_NAME_COMPARATOR);
114         String oldArea = "";
115         for (Service service : services) {
116             String newArea = calcArea(service);
117             if (!newArea.equals(oldArea)) {
118                 if (!oldArea.isEmpty()) {
119                     writer.indentPrintln("</ul>");
120                     writer.decrementIndent();
121                 }
122                 writer.indentPrintln("<li>" + calcArea(service) + "</li>");
123                 writer.incrementIndent();
124                 writer.indentPrintln("<ul>");
125                 oldArea = newArea;
126             }
127             writer.indentPrint("<li>");
128             writer.print("<a href=\"" + service.getName() + ".html"
129                     + "\">" + service.getName() + "</a>");
130             writer.print("</li>");
131         }
132         writer.indentPrintln("</ul>");
133         writer.decrementIndent();
134         writer.indentPrintln("</ul>");        
135         writer.indentPrintln("</div>");
136         writer.indentPrintln("</div>");
137 
138         this.writeMainOrRootList();
139 
140         this.writeAlphabeticalList();
141 
142         writer.writeHeaderBodyAndFooterOutToFile();
143 
144     }
145 
146     private static String calcArea(Service service) {
147         return calcArea(service.getImplProject());
148     }
149 
150     private static String calcArea(String implProject) {
151         // group all student services together
152         if (implProject.startsWith("org.kuali.student")) {
153             return "Kuali Student Services";
154         }
155         if (implProject.startsWith("org.kuali.")) {
156             implProject = implProject.substring("org.kuali.".length());
157         }
158         if (implProject.contains(".api.")) {
159             implProject = implProject.substring(0, implProject.indexOf(".api."));
160         }
161         return implProject;
162     }
163 
164     private void writeMainOrRootList() {
165         Stack<String> stack = new Stack();
166         List<XmlType> types = this.getMainMessageStructures();
167         writer.indentPrintln(
168                 "<div class=\"panel\" style=\"background-color: rgb(255, 255, 255); border: 1px solid rgb(204, 204, 204);\">");
169         writer.indentPrintln(
170                 "<div class=\"panelHeader\" style=\"border-bottom: 1px solid rgb(204, 204, 204); background-color: rgb(238, 238, 238);\">");
171         writer.indentPrintln(
172                 "<b><a name=\"MessageStructures\"></a> " + types.size() + " Main (root) Message Structures</b>");
173         writer.indentPrintln(
174                 "</div><div class=\"panelContent\" style=\"background-color: rgb(255, 255, 255);\">");
175         writer.indentPrintln("<ul>");
176         for (XmlType type : types) {
177             this.writeLink(type);
178             if (!stack.contains(type.getName())) {
179                 stack.push(type.getName());
180                 this.writeSubStructures(type, stack);
181                 stack.pop();
182             }
183         }
184         writer.indentPrintln("</ul>");
185         writer.indentPrintln("</div>");
186         writer.indentPrintln("</div>");
187     }
188 
189     private String stripListOffEnd(String name) {
190         if (name.endsWith("List")) {
191             return name.substring(0, name.length() - "List".length());
192         }
193         return name;
194     }
195 
196     private void writeSubStructures(XmlType type, Stack<String> stack) {
197         boolean first = true;
198         for (MessageStructure ms : finder.findMessageStructures(type.getName())) {
199             XmlType st = finder.findXmlType(this.stripListOffEnd(ms.getType()));
200             if (st == null) {
201                 throw new NullPointerException(ms.getType() + " does not exist in list of types with parents " + calcParents(stack));
202             }
203             if (!st.getPrimitive().equalsIgnoreCase(XmlType.COMPLEX)) {
204                 continue;
205             }
206             if (first) {
207                 first = false;
208                 writer.indentPrintln("<ul>");
209             }
210             this.writeLink(st);
211             if (!stack.contains(st.getName())) {
212                 stack.push(st.getName());
213                 this.writeSubStructures(st, stack);
214                 stack.pop();
215             }
216         }
217         if (!first) {
218             writer.indentPrintln("</ul>");
219         }
220     }
221 
222     private String calcParents(Stack<String> stack) {
223         StringBuilder sb = new StringBuilder();
224         String dot = "";
225         Enumeration<String> en = stack.elements();
226         while (en.hasMoreElements()) {
227             sb.append(dot);
228             dot = ".";
229             sb.append(en.nextElement());
230         }
231         return sb.toString();
232     }
233 
234     private void writeLink(XmlType type) {
235         writer.indentPrint("<li>");
236         writer.print("<a href=\"" + type.getName() + ".html"
237                 + "\">" + type.getName() + "</a>");
238         writer.print("</li>");
239     }
240 
241     private List<XmlType> getMainMessageStructures() {
242         List<XmlType> types = new ArrayList(model.getXmlTypes().size());
243         for (XmlType type : this.getComplexMessageStructures()) {
244             if (isMainMessageStructure(type)) {
245                 types.add(type);
246             }
247         }
248         Collections.sort(types, XML_TYPE_NAME_COMPARATOR);
249         return types;
250     }
251 
252     private boolean isMainMessageStructure(XmlType xmlType) {
253         if (!HtmlContractMessageStructureWriter.calcOtherXmlTypeUsages(model,
254                 xmlType).isEmpty()) {
255             return false;
256         }
257         return true;
258     }
259 
260     private List<XmlType> getComplexMessageStructures() {
261         List<XmlType> types = new ArrayList(model.getXmlTypes().size());
262         for (XmlType type : model.getXmlTypes()) {
263             if (type.getPrimitive() == null) {
264                 throw new NullPointerException(type.getName()
265                         + " has no primitive flag set");
266             }
267             if (type.getPrimitive().equals(XmlType.COMPLEX)) {
268                 types.add(type);
269             }
270         }
271         Collections.sort(types, XML_TYPE_NAME_COMPARATOR);
272         return types;
273     }
274 
275     private void writeAlphabeticalList() {
276         List<XmlType> types = this.getComplexMessageStructures();
277         writer.indentPrintln(
278                 "<div class=\"panel\" style=\"background-color: rgb(255, 255, 255); border: 1px solid rgb(204, 204, 204);\">");
279         writer.indentPrintln(
280                 "<div class=\"panelHeader\" style=\"border-bottom: 1px solid rgb(204, 204, 204); background-color: rgb(238, 238, 238);\">");
281         writer.indentPrintln(
282                 "<b><a name=\"MessageStructures\"></a>All " + types.size() + " Message Structures in Alphabetical Order</b>");
283         writer.indentPrintln(
284                 "</div><div class=\"panelContent\" style=\"background-color: rgb(255, 255, 255);\">");
285         writer.indentPrintln("<ul>");
286         for (XmlType type : types) {
287             this.writeLink(type);
288         }
289         writer.indentPrintln("</ul>");
290         writer.indentPrintln("</div>");
291         writer.indentPrintln("</div>");
292     }
293 }