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.admin.ui.mojo;
17  
18  import java.io.File;
19  import java.io.FileNotFoundException;
20  import java.io.FileOutputStream;
21  import java.io.PrintStream;
22  import java.util.ArrayList;
23  import java.util.List;
24  import java.util.Stack;
25  import org.kuali.student.contract.model.Lookup;
26  import org.kuali.student.contract.model.MessageStructure;
27  import org.kuali.student.contract.model.Service;
28  
29  import org.kuali.student.contract.model.ServiceContractModel;
30  import org.kuali.student.contract.model.ServiceMethod;
31  import org.kuali.student.contract.model.XmlType;
32  import org.kuali.student.contract.model.impl.ServiceContractModelQDoxLoader;
33  import org.kuali.student.contract.model.util.ModelFinder;
34  import org.kuali.student.contract.writer.XmlWriter;
35  import org.kuali.student.contract.writer.service.GetterSetterNameCalculator;
36  import org.slf4j.Logger;
37  import org.slf4j.LoggerFactory;
38  
39  /**
40   *
41   * @author nwright
42   */
43  public class AdminUiLookupViewBeanWriter {
44  
45  	private static final Logger log = LoggerFactory.getLogger(AdminUiLookupViewBeanWriter.class);
46      
47      private ServiceContractModel model;
48      private ModelFinder finder;
49      private String directory;
50      private String rootPackage;
51      private String servKey;
52      private Service service;
53      private XmlType xmlType;
54      private List<ServiceMethod> methods;
55      private XmlWriter out;
56      String fileName;
57      String fullDirectoryPath;
58  
59      public AdminUiLookupViewBeanWriter(ServiceContractModel model,
60              String directory,
61              String rootPackage,
62              String servKey,
63              XmlType xmlType,
64              List<ServiceMethod> methods) {
65          this.model = model;
66          this.finder = new ModelFinder(model);
67          this.directory = directory;
68          this.rootPackage = rootPackage;
69          this.servKey = servKey;
70          service = finder.findService(servKey);
71          this.xmlType = xmlType;
72          this.methods = methods;
73      }
74  
75      /**
76       * Write out the entire file
77       *
78       * @param out
79       */
80      public void write() {
81          initXmlWriter();
82          writeBoilerPlate();
83          writeBean();
84      }
85  
86      private void writeBean() {
87          String infoClass = GetterSetterNameCalculator.calcInitUpper(xmlType.getName());
88          String serviceClass = GetterSetterNameCalculator.calcInitUpper(service.getName());
89          String serviceVar = GetterSetterNameCalculator.calcInitLower(service.getName());
90          String serviceContract = service.getImplProject() + "." + service.getName();
91          String lookupable = AdminUiLookupableWriter.calcPackage(servKey, rootPackage, xmlType) + "."
92                  + AdminUiLookupableWriter.calcClassName(servKey, xmlType);
93          String viewId = "KS-" + infoClass + "-AdminLookupView";
94          out.println("");
95          out.incrementIndent();
96          out.indentPrintln("<import resource=\"classpath:ks-" + infoClass + "-dictionary.xml\"/>");
97          out.indentPrintln("<import resource=\"classpath:UifKSDefinitions.xml\"/>");
98          out.indentPrintln("<!-- **********************************************");
99          out.indentPrintln("Paste this link below into WEB-INF ksAdminLinks.tag or ksMaintenance.tag in KS with Rice Bundled etc");
100         out.indentPrintln("");
101         out.indentPrintln("<li><portal:portalLink displayTitle=\"true\" title=\"" + xmlType.getName() + " Lookup\""
102                 + " url=\"${ConfigProperties.application.url}/kr-krad/lookup?methodToCall=start"
103                 + "&dataObjectClassName=" + xmlType.getJavaPackage() + "." + infoClass + ""
104                 + "&viewId=" + viewId
105                 + "&returnLocation=${ConfigProperties.application.url}/portal.do&hideReturnLink=true\" /></li>");
106         out.indentPrintln ("Also...");
107         out.indentPrintln("Paste bean definition below into the list of dataDictionaryPackages in StudentSpringBeans.xml ");
108         out.indentPrintln ("<value>classpath:" + fullDirectoryPath + "/" + fileName + "</value>");
109         out.indentPrintln("********************************************** -->");
110         out.indentPrintln("<!-- LookupView -->");
111         out.indentPrintln("<bean id=\"" + viewId + "\" parent=\"KS-Uif-LookupView\"");
112         out.incrementIndent();
113         out.indentPrintln("p:title=\"" + xmlType.getName() + " Lookup\"");
114         out.indentPrintln("p:header.headerText=\"" + xmlType.getName() + " Lookup\"");
115         out.indentPrintln("p:dataObjectClassName=\"" + xmlType.getJavaPackage() + "." + infoClass + "\"");
116         out.indentPrintln("p:viewHelperServiceClass=\"" + lookupable + "\">");
117         out.indentPrintln("");
118         out.indentPrintln("<property name=\"criteriaFields\">");
119         out.incrementIndent();
120         out.indentPrintln("<list>");
121         out.incrementIndent();
122         out.indentPrintln("<bean parent=\"Uif-LookupCriteriaInputField\" p:propertyName=\"keywordSearch\"");
123         out.indentPrintln("      p:label=\"Keyword(s)\"");
124         out.indentPrintln("      p:helpSummary=\"Searches fields like name and description to see if they contain the keyword\" />");
125         this.writeFieldsToSearchOn (xmlType, new Stack<XmlType>(), "");
126         out.indentPrintln("<bean parent=\"Uif-LookupCriteriaInputField\" p:propertyName=\"maxResultsToReturn\"");
127         out.indentPrintln("      p:label=\"Max. Results\"");
128         out.indentPrintln("      p:defaultValue=\"50\"");
129         out.indentPrintln("      p:helpSummary=\"The maximum number of results to return from the query, leave null to not limit the results\" />");
130         out.decrementIndent();
131         out.indentPrintln("</list>");
132         out.decrementIndent();
133         out.indentPrintln("</property>");
134         out.indentPrintln("<property name=\"resultFields\">");
135         out.indentPrintln("    <list>");
136         for (MessageStructure ms : this.getFieldsToShowOnLookup()) {
137             String fieldName = GetterSetterNameCalculator.calcInitLower(ms.getShortName());
138             out.indentPrint("        <bean parent=\"Uif-DataField\" p:propertyName=\"" + fieldName + "\"");
139             if (ms.isPrimaryKey()) {
140                 out.println(">");
141                 out.indentPrintln("            <property name=\"inquiry\">");
142                 out.indentPrintln("                <bean parent=\"Uif-Inquiry\" p:dataObjectClassName=\"" + xmlType.getJavaPackage() + "." + xmlType.getName() + "\" p:inquiryParameters=\"" + ms.getShortName() + "\" />");
143                 out.indentPrintln("            </property>");
144                 out.indentPrintln("        </bean>");
145             } else if (AdminUiInquiryViewBeanWriter.shouldDoLookup (ms.getLookup())) {
146                 
147                 out.println(">");
148                 Lookup lookup = ms.getLookup();
149                 XmlType msType = finder.findXmlType(lookup.getXmlTypeName());
150                 MessageStructure pk = this.getPrimaryKey(ms.getLookup().getXmlTypeName());
151                 out.indentPrintln("            <property name=\"inquiry\">");
152                 out.indentPrintln("                <bean parent=\"Uif-Inquiry\" p:dataObjectClassName=\""
153                         + msType.getJavaPackage() + "." + msType.getName()
154                         + "\" p:inquiryParameters=\"" + fieldName + ":" + pk.getShortName() + "\" />");
155                 out.indentPrintln("            </property>");
156                 out.indentPrintln("        </bean>");
157             } else {
158                 out.println(" />");
159             }
160         }
161         out.indentPrintln("    </list>");
162         out.indentPrintln("</property>");
163         out.decrementIndent();
164         out.indentPrintln("</bean>");
165         out.indentPrintln("");
166         out.decrementIndent();
167         out.indentPrintln("</beans>");
168     }
169 
170     
171     private MessageStructure getPrimaryKey(String xmlTypeName) {
172         for (MessageStructure ms : finder.findMessageStructures(xmlTypeName)) {
173             if (ms.isPrimaryKey()) {
174                 return ms;
175             }
176         }
177         throw new NullPointerException ("could not find primary key for " + xmlTypeName);
178     }
179 
180     
181     private void writeFieldsToSearchOn(XmlType type, Stack<XmlType> parents, String prefix) {
182          // avoid recursion
183         if (parents.contains(type)) {
184             return;
185         }
186         parents.push(type);
187         for (MessageStructure ms : finder.findMessageStructures(type.getName())) {
188             String fieldName = GetterSetterNameCalculator.calcInitLower(ms.getShortName());
189             if (!prefix.isEmpty()) {
190                 fieldName = prefix + "." + fieldName;
191             }
192             String fieldNameCamel = GetterSetterNameCalculator.dot2Camel(fieldName);
193             if (ms.getShortName().equalsIgnoreCase("versionInd")) {
194                 out.indentPrintln("<!-- TODO: deal with seaching on the version indicator which is a string in the contract but a number in the database -->");
195                 continue;
196             }
197             if (ms.getType().equalsIgnoreCase("AttributeInfoList")) {
198                 out.indentPrintln("<!-- TODO: deal with dynamic attributes -->");
199                 continue;
200             }
201             if (ms.getShortName ().equalsIgnoreCase("name")) {
202                 out.indentPrintln("<!-- skip name because keyword searching should cover it -->");
203                 continue;
204             }
205             if (ms.getShortName ().equalsIgnoreCase("descr")) {
206                 out.indentPrintln("<!-- skip description because keyword searching should cover it -->");
207                 continue;
208             }
209             if (ms.getType().endsWith("List")) {
210                 out.indentPrintln("<!-- TODO: deal with  " + fieldName + " which is a List -->");
211                 continue;
212             }
213             XmlType fieldType = finder.findXmlType(ms.getType());
214             if (fieldType.getPrimitive().equalsIgnoreCase(XmlType.COMPLEX)) {
215                 // complex sub-types such as rich text 
216                 this.writeFieldsToSearchOn(fieldType, parents, fieldName);
217                 continue;
218             }
219             if (!ms.getType().equalsIgnoreCase("String")) {
220                 out.indentPrintln("<!-- TODO: deal with  " + fieldName + " which is a " + ms.getType() + " -->");
221                 continue;
222             }
223 
224             out.indentPrint("<bean parent=\"Uif-LookupCriteriaInputField\" p:propertyName=\"" + fieldName + "\"");
225             if (!AdminUiInquiryViewBeanWriter.shouldDoLookup (ms.getLookup())) {
226                 out.println(" />");
227                 continue;
228             }
229             out.println(">");
230             out.incrementIndent();
231             XmlType msType = finder.findXmlType(ms.getLookup().getXmlTypeName());
232             if (msType == null) {
233                 throw new NullPointerException ("Processing lookup for: " + type.getName () 
234                         + ms.getName() 
235                         + " lookup=" + ms.getLookup().getXmlTypeName());
236             }
237             out.indentPrintln("<property name=\"quickfinder\">");
238             out.incrementIndent();
239             out.indentPrintln("<bean parent=\"Uif-QuickFinder\" p:dataObjectClassName=\"" + msType.getJavaPackage() + "." + msType.getName() + "\"");
240             MessageStructure pk = this.getPrimaryKey(ms.getLookup().getXmlTypeName());
241             if (pk == null) {
242                 throw new NullPointerException("could not find primary key for " + ms.getId());
243             }
244             out.indentPrintln("p:fieldConversions=\"" + pk.getShortName() + ":" + fieldName + "\" />");
245             out.decrementIndent();
246             out.indentPrintln("</property>");
247             out.decrementIndent();
248             out.indentPrintln("</bean>");
249         }
250         parents.pop();
251     }
252     
253     private List<MessageStructure> getFieldsToSearchOn() {
254         List<MessageStructure> list = new ArrayList<MessageStructure>();
255         for (MessageStructure ms : finder.findMessageStructures(xmlType.getName())) {
256             // lists of values cannot be displayed within a list of values
257             if (ms.getType().endsWith("List")) {
258                 continue;
259             }
260             if (ms.getType().endsWith("List")) {
261                 continue;
262             }
263             XmlType msType = finder.findXmlType(ms.getType());
264             // just show fields on the main object for now don't dive down into complex fields
265             if (msType.getPrimitive().equalsIgnoreCase(XmlType.COMPLEX)) {
266                 continue;
267             }
268         }
269         return list;
270     }
271 
272     private List<MessageStructure> getFieldsToShowOnLookup() {
273         List<MessageStructure> list = new ArrayList<MessageStructure>();
274         for (MessageStructure ms : finder.findMessageStructures(xmlType.getName())) {
275             // lists of values cannot be displayed within a list of values
276             if (ms.getType().endsWith("List")) {
277                 continue;
278             }
279             XmlType msType = finder.findXmlType(ms.getType());
280             // just show fields on the main object for now don't dive down into complex fields
281             if (msType.getPrimitive().equalsIgnoreCase(XmlType.COMPLEX)) {
282                 continue;
283             }
284             list.add(ms);
285         }
286         return list;
287     }
288 
289     private void initXmlWriter() {
290         String infoClass = GetterSetterNameCalculator.calcInitUpper(xmlType.getName());
291         String serviceClass = GetterSetterNameCalculator.calcInitUpper(service.getName());
292         String serviceVar = GetterSetterNameCalculator.calcInitLower(service.getName());
293         String serviceContract = service.getImplProject() + "." + service.getName();
294 
295         fullDirectoryPath = AdminUiLookupableWriter.calcPackage(servKey, rootPackage, xmlType).replace('.', '/');
296         fileName = infoClass + "AdminLookupView.xml";
297 
298         File dir = new File(this.directory);
299 
300         if (!dir.exists()) {
301             if (!dir.mkdirs()) {
302                 throw new IllegalStateException("Could not create directory "
303                         + this.directory);
304             }
305         }
306 
307         String dirStr = this.directory + "/" + "resources" + "/" + fullDirectoryPath;
308         File dirFile = new File(dirStr);
309         if (!dirFile.exists()) {
310             if (!dirFile.mkdirs()) {
311                 throw new IllegalStateException(
312                         "Could not create directory " + dirStr);
313             }
314         }
315         try {
316             PrintStream out = new PrintStream(new FileOutputStream(
317                     dirStr + "/"
318                     + fileName, false));
319             log.info("AdminUILookupViewBeanWriter: writing " + dirStr + "/" + fileName);
320             this.out = new XmlWriter(out, 0);
321         } catch (FileNotFoundException ex) {
322             throw new IllegalStateException(ex);
323         }
324     }
325 
326     private void writeBoilerPlate() {
327         out.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
328         out.println("<beans xmlns=\"http://www.springframework.org/schema/beans\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"");
329         out.println("       xmlns:p=\"http://www.springframework.org/schema/p\"");
330         out.println("       xsi:schemaLocation=\"http://www.springframework.org/schema/beans");
331         out.println("                    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd\">");
332         out.println("    <!--");
333         out.println("     Copyright 2007-2012 The Kuali Foundation");
334         out.println("");
335         out.println("     Licensed under the Educational Community License, Version 2.0 (the \"License\");");
336         out.println("     you may not use this file except in compliance with the License.");
337         out.println("     You may obtain a copy of the License at");
338         out.println("");
339         out.println("     http://www.opensource.org/licenses/ecl2.php");
340         out.println("");
341         out.println("     Unless required by applicable law or agreed to in writing, software");
342         out.println("     distributed under the License is distributed on an \"AS IS\" BASIS,");
343         out.println("     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.");
344         out.println("     See the License for the specific language governing permissions and");
345         out.println("     limitations under the License.");
346         out.println("    -->");
347 
348     }
349 }