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.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            String pack = rootPackage + "." + servKey.toLowerCase();
071    //  StringBuffer buf = new StringBuffer (service.getVersion ().length ());
072    //  for (int i = 0; i < service.getVersion ().length (); i ++)
073    //  {
074    //   char c = service.getVersion ().charAt (i);
075    //   c = Character.toLowerCase (c);
076    //   if (Character.isLetter (c))
077    //   {
078    //    buf.append (c);
079    //    continue;
080    //   }
081    //   if (Character.isDigit (c))
082    //   {
083    //    buf.append (c);
084    //   }
085    //  }
086    //  pack = pack + buf.toString ();
087    //        pack = pack + "service.decorators";
088            return pack;
089    //        return rootPackage;
090        }
091    
092        public static String calcClassName(String servKey, String xmlTypeName) {
093            return GetterSetterNameCalculator.calcInitUpper(xmlTypeName) + "AdminLookupableImpl";
094        }
095    
096        public static String calcClassName(String servKey, XmlType xmlType) {
097            return calcClassName(servKey, xmlType.getName());
098        }
099    
100        public static String calcDecoratorClassName(String servKey) {
101            return GetterSetterNameCalculator.calcInitUpper(servKey + "ServiceDecorator");
102        }
103    
104        private static enum MethodType {
105    
106            VALIDATE, CREATE, UPDATE
107        };
108    
109        private MethodType calcMethodType(ServiceMethod method) {
110            if (method.getName().startsWith("validate")) {
111                return MethodType.VALIDATE;
112            }
113            if (method.getName().startsWith("create")) {
114                return MethodType.CREATE;
115            }
116            if (method.getName().startsWith("update")) {
117                return MethodType.UPDATE;
118            }
119            return null;
120        }
121    
122        /**
123         * Write out the entire file
124         *
125         * @param out
126         */
127        public void write() {
128            indentPrint("public class " + calcClassName(servKey, xmlType));
129            println(" extends LookupableImpl");
130            importsAdd("org.kuali.rice.krad.lookup.LookupableImpl");
131            openBrace();
132            writeLogic();
133            closeBrace();
134    
135            this.writeJavaClassAndImportsOutToFile();
136            this.getOut().close();
137        }
138    
139        private void writeLogic() {
140    
141            String initUpper = GetterSetterNameCalculator.calcInitUpper(servKey);
142            String initLower = GetterSetterNameCalculator.calcInitLower(servKey);
143            String infoClass = GetterSetterNameCalculator.calcInitUpper(xmlType.getName());
144            String serviceClass = GetterSetterNameCalculator.calcInitUpper(service.getName());
145            String serviceVar = GetterSetterNameCalculator.calcInitLower(service.getName());
146            importsAdd(service.getImplProject() + "." + service.getName());
147            importsAdd("org.apache.log4j.Logger");
148            indentPrintln("private static final Logger LOG = Logger.getLogger(" + calcClassName(servKey, xmlType) + ".class);");
149            indentPrintln("private transient " + serviceClass + " " + serviceVar + ";");
150    
151            println("");
152            indentPrintln("@Override");
153            importsAdd(xmlType.getJavaPackage() + "." + infoClass);
154            importsAdd(List.class.getName());
155            importsAdd(Map.class.getName());
156            importsAdd(LookupForm.class.getName());
157            importsAdd(QueryByCriteria.class.getName());
158            importsAdd(Predicate.class.getName());
159            importsAdd(PredicateFactory.class.getName());
160            importsAdd(GlobalResourceLoader.class.getName());
161            XmlType contextInfo = finder.findXmlType("contextInfo");
162            importsAdd(contextInfo.getJavaPackage() + "." + contextInfo.getName());
163            importsAdd("org.kuali.student.common.util.ContextBuilder");
164            importsAdd(PredicateFactory.class.getName());
165            importsAdd(ArrayList.class.getName());
166            importsAdd(QName.class.getName());
167    //        importsAdd (PredicateFactory.class.getName());
168            indentPrintln("protected List<" + infoClass + "> getSearchResults(LookupForm lookupForm, Map<String, String> fieldValues, boolean unbounded)");
169            openBrace();
170            indentPrintln("QueryByCriteria.Builder qBuilder = QueryByCriteria.Builder.create();");
171            indentPrintln("List<Predicate> pList = new ArrayList<Predicate>();");
172            indentPrintln("for (String fieldName : fieldValues.keySet())");
173            openBrace();
174            indentPrintln("String value = fieldValues.get(fieldName);");
175            indentPrintln("if (value != null && !value.isEmpty())");
176            openBrace();
177            indentPrintln("if (fieldName.equals(\"maxResultsToReturn\"))");
178            openBrace();
179            indentPrintln("qBuilder.setMaxResults (Integer.parseInt(value));");
180            indentPrintln("continue;");
181            closeBrace();
182            indentPrintln("pList.add(PredicateFactory.equal(fieldName, value));");
183            closeBrace();
184            closeBrace();
185            indentPrintln("if (!pList.isEmpty())");
186            openBrace();
187            indentPrintln("qBuilder.setPredicates(PredicateFactory.and(pList.toArray(new Predicate[pList.size()])));");
188            closeBrace();
189            indentPrintln("try");
190            openBrace();
191            String searchMethodName = calcSearchMethodName();
192            if (searchMethodName == null) {
193                indentPrintln("// WARNING: Missing searchMethod please add it to the service contract: " + servKey + "." + xmlType.getName());
194                searchMethodName = "searchFor" + GetterSetterNameCalculator.calcInitUpper(xmlType.getName()) + "s";
195            }
196            indentPrintln("List<" + infoClass + "> list = this.get" + serviceClass + "()." + searchMethodName + "(qBuilder.build(), getContextInfo());");
197            indentPrintln("return list;");
198            closeBrace();
199            indentPrintln("catch (Exception ex) {");
200            indentPrintln("    throw new RuntimeException(ex);");
201            indentPrintln("}");
202            closeBrace();
203    
204            AdminUiInquirableWriter.writeServiceGetterAndSetter(this, serviceClass, serviceVar, xmlType);
205        }
206    
207        private String calcSearchMethodName() {
208            ServiceMethod method = this.findSearchMethod();
209            if (method != null) {
210                return method.getName();
211            }
212            return null;
213        }
214    
215        private ServiceMethod findSearchMethod() {
216            return findSearchMethod(xmlType, methods);
217        }
218    
219        public static ServiceMethod findSearchMethod(XmlType xmlType, List<ServiceMethod> methods) {
220            for (ServiceMethod method : methods) {
221                if (hasProperReturnTypeForSearchMethod(xmlType, method)) {
222                    if (hasProperParameterForSearchMethod(xmlType, method)) {
223                        return method;
224                    }
225                }
226            }
227            return null;
228        }
229    
230        private static boolean hasProperReturnTypeForSearchMethod(XmlType xmlType, ServiceMethod method) {
231            String returnValueTypeLower = method.getReturnValue().getType().toLowerCase();
232            if (returnValueTypeLower.endsWith("List".toLowerCase())) {
233                if (returnValueTypeLower.startsWith(xmlType.getName().toLowerCase())) {
234                    return true;
235                }
236            }
237            if (returnValueTypeLower.endsWith("QueryResults".toLowerCase())) {
238                if (returnValueTypeLower.startsWith(xmlType.getName().toLowerCase())) {
239                    return true;
240                }
241            }
242            return false;
243        }
244    
245        private static boolean hasProperParameterForSearchMethod(XmlType xmlType, ServiceMethod method) {
246            for (ServiceMethodParameter parameter : method.getParameters()) {
247                if (parameter.getType().equals("QueryByCriteria")) {
248                    return true;
249                }
250            }
251            return false;
252        }
253    }