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