001    /**
002     * Copyright 2004-2014 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.util.ArrayList;
019    import java.util.List;
020    import java.util.Map;
021    import javax.xml.namespace.QName;
022    import org.kuali.rice.core.api.criteria.Predicate;
023    import org.kuali.rice.core.api.criteria.PredicateFactory;
024    import org.kuali.rice.core.api.criteria.QueryByCriteria;
025    import org.kuali.rice.core.api.resourceloader.GlobalResourceLoader;
026    import org.kuali.rice.krad.web.form.LookupForm;
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.ServiceMethodParameter;
032    import org.kuali.student.contract.model.XmlType;
033    import org.kuali.student.contract.model.util.ModelFinder;
034    import org.kuali.student.contract.writer.JavaClassWriter;
035    import org.kuali.student.contract.writer.service.GetterSetterNameCalculator;
036    
037    /**
038     *
039     * @author nwright
040     */
041    public class AdminUiLookupableWriter extends JavaClassWriter {
042    
043        private ServiceContractModel model;
044        private ModelFinder finder;
045        private String directory;
046        private String rootPackage;
047        private String servKey;
048        private Service service;
049        private XmlType xmlType;
050        private List<ServiceMethod> methods;
051    
052        public AdminUiLookupableWriter(ServiceContractModel model,
053                String directory,
054                String rootPackage,
055                String servKey,
056                XmlType xmlType,
057                List<ServiceMethod> methods) {
058            super(directory + "/" + "java", calcPackage(servKey, rootPackage, xmlType), calcClassName(servKey, xmlType));
059            this.model = model;
060            this.finder = new ModelFinder(model);
061            this.directory = directory;
062            this.rootPackage = rootPackage;
063            this.servKey = servKey;
064            service = finder.findService(servKey);
065            this.xmlType = xmlType;
066            this.methods = methods;
067        }
068    
069        public static String calcPackage(String servKey, String rootPackage, XmlType xmlType) {
070            return AdminUiInquirableWriter.calcPackage(servKey, rootPackage, xmlType);
071        }
072    
073        public static String calcClassName(String servKey, String xmlTypeName) {
074            return GetterSetterNameCalculator.calcInitUpper(xmlTypeName) + "AdminLookupableImpl";
075        }
076    
077        public static String calcClassName(String servKey, XmlType xmlType) {
078            return calcClassName(servKey, xmlType.getName());
079        }
080    
081        public static String calcDecoratorClassName(String servKey) {
082            return GetterSetterNameCalculator.calcInitUpper(servKey + "ServiceDecorator");
083        }
084    
085        private static enum MethodType {
086    
087            VALIDATE, CREATE, UPDATE
088        };
089    
090        private MethodType calcMethodType(ServiceMethod method) {
091            if (method.getName().startsWith("validate")) {
092                return MethodType.VALIDATE;
093            }
094            if (method.getName().startsWith("create")) {
095                return MethodType.CREATE;
096            }
097            if (method.getName().startsWith("update")) {
098                return MethodType.UPDATE;
099            }
100            return null;
101        }
102    
103        /**
104         * Write out the entire file
105         *
106         * @param out
107         */
108        public void write() {
109            indentPrint("public class " + calcClassName(servKey, xmlType));
110            println(" extends LookupableImpl");
111            importsAdd("org.kuali.rice.krad.lookup.LookupableImpl");
112            openBrace();
113            writeLogic();
114            closeBrace();
115    
116            this.writeJavaClassAndImportsOutToFile();
117            this.getOut().close();
118        }
119    
120        private void writeLogic() {
121    
122            String initUpper = GetterSetterNameCalculator.calcInitUpper(servKey);
123            String initLower = GetterSetterNameCalculator.calcInitLower(servKey);
124            String infoClass = GetterSetterNameCalculator.calcInitUpper(xmlType.getName());
125            String serviceClass = GetterSetterNameCalculator.calcInitUpper(service.getName());
126            String serviceVar = GetterSetterNameCalculator.calcInitLower(service.getName());
127            importsAdd(service.getImplProject() + "." + service.getName());
128            importsAdd("org.apache.log4j.Logger");
129            indentPrintln("private static final Logger LOG = Logger.getLogger(" + calcClassName(servKey, xmlType) + ".class);");
130            indentPrintln("private transient " + serviceClass + " " + serviceVar + ";");
131            indentPrintln ("private static final long serialVersionUID = 1L;");
132    
133            println("");
134            indentPrintln("@Override");
135            importsAdd(xmlType.getJavaPackage() + "." + infoClass);
136            importsAdd(List.class.getName());
137            importsAdd(Map.class.getName());
138            importsAdd(LookupForm.class.getName());
139            importsAdd(QueryByCriteria.class.getName());
140            importsAdd(Predicate.class.getName());
141            importsAdd(PredicateFactory.class.getName());
142            importsAdd(GlobalResourceLoader.class.getName());
143            XmlType contextInfo = finder.findXmlType("contextInfo");
144            importsAdd(contextInfo.getJavaPackage() + "." + contextInfo.getName());
145            importsAdd("org.kuali.student.common.util.ContextBuilder");
146            importsAdd(PredicateFactory.class.getName());
147            importsAdd(ArrayList.class.getName());
148            importsAdd(QName.class.getName());
149    //        importsAdd (PredicateFactory.class.getName());
150            indentPrintln("protected List<" + infoClass + "> getSearchResults(LookupForm lookupForm, Map<String, String> fieldValues, boolean unbounded)");
151            openBrace();
152            indentPrintln("QueryByCriteria.Builder qBuilder = QueryByCriteria.Builder.create();");
153            indentPrintln("List<Predicate> pList = new ArrayList<Predicate>();");
154            indentPrintln("for (String fieldName : fieldValues.keySet())");
155            openBrace();
156            indentPrintln("String value = fieldValues.get(fieldName);");
157            indentPrintln("if (value != null && !value.isEmpty())");
158            openBrace();
159            indentPrintln("if (fieldName.equals(\"maxResultsToReturn\"))");
160            openBrace();
161            indentPrintln("qBuilder.setMaxResults (Integer.parseInt(value));");
162            indentPrintln("continue;");
163            closeBrace();
164            indentPrintln("pList.add(PredicateFactory.equal(fieldName, value));");
165            closeBrace();
166            closeBrace();
167            indentPrintln("if (!pList.isEmpty())");
168            openBrace();
169            indentPrintln("qBuilder.setPredicates(PredicateFactory.and(pList.toArray(new Predicate[pList.size()])));");
170            closeBrace();
171            indentPrintln("try");
172            openBrace();
173            String searchMethodName = calcSearchMethodName();
174            if (searchMethodName == null) {
175                indentPrintln("// WARNING: Missing searchMethod please add it to the service contract: " + servKey + "." + xmlType.getName());
176                searchMethodName = "searchFor" + GetterSetterNameCalculator.calcInitUpper(xmlType.getName()) + "s";
177            }
178            indentPrintln("List<" + infoClass + "> list = this.get" + serviceClass + "()." + searchMethodName + "(qBuilder.build(), getContextInfo());");
179            indentPrintln("return list;");
180            closeBrace();
181            indentPrintln("catch (Exception ex) {");
182            indentPrintln("    throw new RuntimeException(ex);");
183            indentPrintln("}");
184            closeBrace();
185    
186            AdminUiInquirableWriter.writeServiceGetterAndSetter(this, serviceClass, serviceVar, xmlType);
187        }
188    
189        private String calcSearchMethodName() {
190            ServiceMethod method = this.findSearchMethod();
191            if (method != null) {
192                return method.getName();
193            }
194            return null;
195        }
196    
197        private ServiceMethod findSearchMethod() {
198            return findSearchMethod(xmlType, methods);
199        }
200    
201        public static ServiceMethod findSearchMethod(XmlType xmlType, List<ServiceMethod> methods) {
202            for (ServiceMethod method : methods) {
203                if (hasProperReturnTypeForSearchMethod(xmlType, method)) {
204                    if (hasProperParameterForSearchMethod(xmlType, method)) {
205                        return method;
206                    }
207                }
208            }
209            return null;
210        }
211    
212        private static boolean hasProperReturnTypeForSearchMethod(XmlType xmlType, ServiceMethod method) {
213            String returnValueTypeLower = method.getReturnValue().getType().toLowerCase();
214            if (returnValueTypeLower.endsWith("List".toLowerCase())) {
215                if (returnValueTypeLower.startsWith(xmlType.getName().toLowerCase())) {
216                    return true;
217                }
218            }
219            if (returnValueTypeLower.endsWith("QueryResults".toLowerCase())) {
220                if (returnValueTypeLower.startsWith(xmlType.getName().toLowerCase())) {
221                    return true;
222                }
223            }
224            return false;
225        }
226    
227        private static boolean hasProperParameterForSearchMethod(XmlType xmlType, ServiceMethod method) {
228            for (ServiceMethodParameter parameter : method.getParameters()) {
229                if (parameter.getType().equals("QueryByCriteria")) {
230                    return true;
231                }
232            }
233            return false;
234        }
235    }