001 /**
002 * Copyright 2004-2013 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.opensource.org/licenses/ecl2.php
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.admin.ui.mojo;
017
018 import java.io.File;
019 import java.io.FileNotFoundException;
020 import java.io.FileOutputStream;
021 import java.io.PrintStream;
022 import java.util.ArrayList;
023 import java.util.List;
024 import java.util.Stack;
025 import org.kuali.student.contract.model.Lookup;
026 import org.kuali.student.contract.model.MessageStructure;
027 import org.kuali.student.contract.model.Service;
028
029 import org.kuali.student.contract.model.ServiceContractModel;
030 import org.kuali.student.contract.model.ServiceMethod;
031 import org.kuali.student.contract.model.XmlType;
032 import org.kuali.student.contract.model.impl.ServiceContractModelQDoxLoader;
033 import org.kuali.student.contract.model.util.ModelFinder;
034 import org.kuali.student.contract.writer.XmlWriter;
035 import org.kuali.student.contract.writer.service.GetterSetterNameCalculator;
036 import org.slf4j.Logger;
037 import org.slf4j.LoggerFactory;
038
039 /**
040 *
041 * @author nwright
042 */
043 public class AdminUiLookupViewBeanWriter {
044
045 private static final Logger log = LoggerFactory.getLogger(AdminUiLookupViewBeanWriter.class);
046
047 private ServiceContractModel model;
048 private ModelFinder finder;
049 private String directory;
050 private String rootPackage;
051 private String servKey;
052 private Service service;
053 private XmlType xmlType;
054 private List<ServiceMethod> methods;
055 private XmlWriter out;
056 String fileName;
057 String fullDirectoryPath;
058
059 public AdminUiLookupViewBeanWriter(ServiceContractModel model,
060 String directory,
061 String rootPackage,
062 String servKey,
063 XmlType xmlType,
064 List<ServiceMethod> methods) {
065 this.model = model;
066 this.finder = new ModelFinder(model);
067 this.directory = directory;
068 this.rootPackage = rootPackage;
069 this.servKey = servKey;
070 service = finder.findService(servKey);
071 this.xmlType = xmlType;
072 this.methods = methods;
073 }
074
075 /**
076 * Write out the entire file
077 *
078 * @param out
079 */
080 public void write() {
081 initXmlWriter();
082 writeBoilerPlate();
083 writeBean();
084 }
085
086 private void writeBean() {
087 String infoClass = GetterSetterNameCalculator.calcInitUpper(xmlType.getName());
088 String serviceClass = GetterSetterNameCalculator.calcInitUpper(service.getName());
089 String serviceVar = GetterSetterNameCalculator.calcInitLower(service.getName());
090 String serviceContract = service.getImplProject() + "." + service.getName();
091 String lookupable = AdminUiLookupableWriter.calcPackage(servKey, rootPackage, xmlType) + "."
092 + AdminUiLookupableWriter.calcClassName(servKey, xmlType);
093 String viewId = "KS-" + infoClass + "-AdminLookupView";
094 out.println("");
095 out.incrementIndent();
096 out.indentPrintln("<import resource=\"classpath:ks-" + infoClass + "-dictionary.xml\"/>");
097 out.indentPrintln("<import resource=\"classpath:UifKSDefinitions.xml\"/>");
098 out.indentPrintln("<!-- **********************************************");
099 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 }