View Javadoc
1   /**
2    * Copyright 2004-2014 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.jpa.mojo;
17  
18  import org.kuali.student.contract.model.Service;
19  import org.kuali.student.contract.model.ServiceContractModel;
20  import org.kuali.student.contract.model.ServiceMethod;
21  import org.kuali.student.contract.model.ServiceMethodError;
22  import org.kuali.student.contract.model.ServiceMethodParameter;
23  import org.kuali.student.contract.model.XmlType;
24  import org.kuali.student.contract.model.util.ModelFinder;
25  import org.kuali.student.contract.writer.JavaClassWriter;
26  import org.kuali.student.contract.writer.service.GetterSetterNameCalculator;
27  import org.kuali.student.contract.writer.service.MessageStructureTypeCalculator;
28  import org.kuali.student.contract.writer.service.ServiceExceptionWriter;
29  import org.slf4j.Logger;
30  import org.slf4j.LoggerFactory;
31  
32  import java.util.*;
33  import javax.persistence.Entity;
34  import javax.persistence.NamedQueries;
35  import javax.persistence.NamedQuery;
36  import javax.persistence.Table;
37  import org.kuali.rice.core.api.criteria.CriteriaLookupService;
38  import org.kuali.student.contract.model.MessageStructure;
39  
40  /**
41   *
42   * @author nwright
43   */
44  public class JpaAttributeEntityWriter extends JavaClassWriter {
45  
46      private static final Logger log = LoggerFactory.getLogger(JpaAttributeEntityWriter.class);
47  
48      //////////////////////////////
49      // Constants
50      //////////////////////////////
51      /**
52       * The standard type of methods used in our Service contract.
53       */
54      protected static enum MethodType {
55  
56          VALIDATE,
57          CREATE,
58          CREATE_BULK,
59          ADD,
60          UPDATE,
61          UPDATE_OTHER,
62          DELETE,
63          REMOVE,
64          DELETE_OTHER,
65          GET_CREATE,
66          GET_BY_ID,
67          GET_BY_IDS,
68          RICE_GET_BY_NAMESPACE_AND_NAME,
69          GET_IDS_BY_TYPE,
70          GET_IDS_BY_OTHER,
71          GET_INFOS_BY_OTHER,
72          GET_TYPE,
73          GET_TYPES,
74          SEARCH_FOR_IDS,
75          SEARCH_FOR_INFOS,
76          UNKNOWN
77      };
78  
79      //////////////////////////////
80      // Data Variables
81      //////////////////////////////
82      protected ServiceContractModel model;
83      protected ModelFinder finder;
84      private String directory;
85      private XmlType xmlType;
86      /**
87       * The package name is stored in the service object itself (the package spec
88       * kept moving around so I assumed the actual service name was unique but
89       * ran into a problem when we included rice because they have a StateService
90       * meaning US states and we have a StateService meaning the state of the
91       * object so I added logic to detect rice and prepend that "RICE." to it
92       */
93      private String rootPackage;
94  
95      /**
96       * Name of the service being operated on. If it is a RICE service it is
97       * prefixed with RICE. [11:32:18 AM] Norman Wright: short name... I think it
98       * gets it by taking the java class SimpleName and stripping off the word
99       * "Service" and I think making it lower case. [11:32:24 AM] Norman Wright:
100      * so OrganizationService becomes organization
101      */
102     protected String servKey;
103     /**
104      * A flag that holds if the service is an R1 service.
105      */
106     private boolean isR1;
107     private List<ServiceMethod> methods;
108     private String mainEntityName;
109 
110     //////////////////////////
111     // Constructor
112     //////////////////////////
113     public JpaAttributeEntityWriter(ServiceContractModel model,
114             String directory,
115             String rootPackage,
116             String servKey,
117             List<ServiceMethod> methods,
118             XmlType xmlType,
119             boolean isR1,
120             String mainEntityName) {
121         super(directory, calcPackage(servKey, rootPackage), calcClassName(servKey, xmlType));
122         this.model = model;
123         this.finder = new ModelFinder(model);
124         this.directory = directory;
125         this.rootPackage = rootPackage;
126         this.servKey = servKey;
127         this.methods = methods;
128         this.xmlType = xmlType;
129         this.isR1 = isR1;
130         this.mainEntityName = mainEntityName;
131         
132     }
133 
134     public JpaAttributeEntityWriter(ServiceContractModel model,
135             String directory,
136             String rootPackage,
137             String servKey,
138             List<ServiceMethod> methods,
139             XmlType xmlType,
140             boolean isR1,
141             String packageName,
142             String className) {
143         super(directory, packageName, className);
144         this.model = model;
145         this.finder = new ModelFinder(model);
146         this.directory = directory;
147         this.rootPackage = rootPackage;
148         this.servKey = servKey;
149         this.methods = methods;
150         this.xmlType = xmlType;
151         this.isR1 = isR1;
152     }
153 
154     /////////////////////////
155     // Functional Methods
156     /////////////////////////
157     /**
158      * Returns the jpa implementation package name.
159      *
160      * @param servKey
161      * @param rootPackage
162      * @return
163      */
164     public static String calcPackage(String servKey, String rootPackage) {
165         String pack = rootPackage + ".";
166 //        String pack = rootPackage + "." + servKey.toLowerCase() + ".";
167 //  StringBuffer buf = new StringBuffer (service.getVersion ().length ());
168 //  for (int i = 0; i < service.getVersion ().length (); i ++)
169 //  {
170 //   char c = service.getVersion ().charAt (i);
171 //   c = Character.toLowerCase (c);
172 //   if (Character.isLetter (c))
173 //   {
174 //    buf.append (c);
175 //    continue;
176 //   }
177 //   if (Character.isDigit (c))
178 //   {
179 //    buf.append (c);
180 //   }
181 //  }
182 //  pack = pack + buf.toString ();
183         pack = pack + "service.impl.jpa." + servKey.toLowerCase();
184         return pack;
185     }
186 
187     /**
188      * Checks if this is a RICE service.
189      *
190      * @return true if this is a RICE service.
191      */
192     private boolean isRice() {
193         if (this.servKey.startsWith("RICE.")) {
194             return true;
195         }
196         return false;
197     }
198 
199     protected static String fixServKey(String servKey) {
200         if (servKey.startsWith("RICE.")) {
201             return servKey.substring("RICE.".length());
202         }
203         return servKey;
204     }
205 
206     /**
207      * Given the service key (name), returns a calculated class name for the jpa
208      * impl.
209      */
210     public static String calcClassName(String servKey, XmlType xmlType) {
211         String name = GetterSetterNameCalculator.calcInitUpper(xmlType.getName());
212         if (name.endsWith ("Info")) {
213             name = name.substring(0, name.length() - "Info".length());
214         }
215         name = name + "AttributeEntity";
216         return name;
217     }
218 
219     /**
220      * Analyses the method and returns a MethodType enum that describes what
221      * type of method this is.
222      */
223     protected MethodType calcMethodType(ServiceMethod method) {
224         if (this.isRice()) {
225             if (method.getName().contains("ByNamespaceCodeAndName")) {
226                 return MethodType.RICE_GET_BY_NAMESPACE_AND_NAME;
227             }
228             if (method.getName().contains("ByNameAndNamespace")) {
229                 return MethodType.RICE_GET_BY_NAMESPACE_AND_NAME;
230             }
231             if (method.getName().startsWith("get")) {
232                 if (method.getParameters().size() == 1) {
233                     if (!method.getReturnValue().getType().endsWith("List")) {
234                         if (method.getParameters().get(0).getName().equals("id")) {
235                             return MethodType.GET_BY_ID;
236                         }
237 
238                     } else {
239                         if (method.getParameters().get(0).getName().equals("ids")) {
240                             return MethodType.GET_BY_IDS;
241                         }
242                     }
243                 }
244             }
245         }
246         if (method.getName().startsWith("validate")) {
247             return MethodType.VALIDATE;
248         }
249         if (method.getName().startsWith("create")) {
250             if (this.findInfoParameter(method) != null) {
251                 return MethodType.CREATE;
252             }
253             return MethodType.CREATE_BULK;
254         }
255         if (method.getName().startsWith("add")) {
256             return MethodType.ADD;
257         }
258         if (method.getName().startsWith("update")) {
259             if (this.findInfoParameter(method) != null) {
260                 return MethodType.UPDATE;
261             }
262             return MethodType.UPDATE_OTHER;
263         }
264         if (method.getName().startsWith("delete")) {
265             if (method.getName().contains("By")) {
266                 if (!method.getName().startsWith("deleteBy")) {
267                     return MethodType.DELETE_OTHER;
268                 }
269             }
270             if (method.getName().contains("For")) {
271                 if (!method.getName().startsWith("deleteFor")) {
272                     return MethodType.DELETE_OTHER;
273                 }
274             }
275             return MethodType.DELETE;
276         }
277         if (method.getName().startsWith("remove")) {
278             return MethodType.REMOVE;
279         }
280 
281         if (method.getName().startsWith("getCreate")) {
282             return MethodType.GET_CREATE;
283         }
284 
285         if (method.getName().startsWith("get")) {
286             if (method.getName().endsWith("ByIds")) {
287                 return MethodType.GET_BY_IDS;
288             }
289             if (method.getName().endsWith("ByKeys")) {
290                 return MethodType.GET_BY_IDS;
291             }
292             if (method.getName().endsWith("ByType")) {
293                 return MethodType.GET_IDS_BY_TYPE;
294             }
295             if (method.getReturnValue().getType().endsWith("TypeInfo")) {
296                 return MethodType.GET_TYPE;
297             }
298             if (method.getReturnValue().getType().endsWith("TypeInfoList")) {
299                 return MethodType.GET_TYPES;
300             }
301             if (method.getName().endsWith("ByType")) {
302                 return MethodType.GET_IDS_BY_TYPE;
303             }
304             if (method.getParameters().size() >= 1 && method.getParameters().size() <= 2) {
305                 if (!method.getReturnValue().getType().endsWith("List")) {
306 //                    if (method.getParameters().get(0).getName().endsWith("Id")) {
307                     return MethodType.GET_BY_ID;
308 //                    }
309                 }
310             }
311             if (method.getName().contains("By")) {
312                 if (method.getReturnValue().getType().equals("StringList")) {
313                     return MethodType.GET_IDS_BY_OTHER;
314                 }
315                 if (method.getReturnValue().getType().endsWith("InfoList")) {
316                     return MethodType.GET_INFOS_BY_OTHER;
317                 }
318             }
319         }
320         if (method.getName().startsWith("searchFor")) {
321             if (method.getName().endsWith("Ids")) {
322                 return MethodType.SEARCH_FOR_IDS;
323             }
324             if (method.getName().endsWith("Keys")) {
325                 return MethodType.SEARCH_FOR_IDS;
326             }
327             return MethodType.SEARCH_FOR_INFOS;
328         }
329 
330         return MethodType.UNKNOWN;
331     }
332 
333     private String calcTableName(XmlType xmlType) {
334         String tableName = xmlType.getTableName();
335         if (tableName != null) {
336             return tableName;
337         }
338         return calcTableName(xmlType.getName());
339     }
340 
341     private String calcTableName(String name) {
342         if (name.endsWith("Info")) {
343             name = name.substring(0, name.length() - "Info".length());
344         }
345         String tableName = "KSEN_" + splitCamelCase(name) + "_ATTR";
346         return tableName.toUpperCase();
347     }
348 
349     // got this from
350     // http://stackoverflow.com/questions/2559759/how-do-i-convert-camelcase-into-human-readable-names-in-java
351     private static String splitCamelCase(String s) {
352         if (s == null) {
353             return null;
354         }
355         return s.replaceAll(String.format("%s|%s|%s",
356                 "(?<=[A-Z])(?=[A-Z][a-z])", "(?<=[^A-Z])(?=[A-Z])",
357                 "(?<=[A-Za-z])(?=[^A-Za-z])"), "_");
358     }
359 
360     /**
361      * Write out the entire file
362      */
363     public void write() {
364         String className = calcClassName (servKey, xmlType);
365         indentPrintln("@Entity");
366         importsAdd(Entity.class.getName());
367         String tableName = calcTableName(xmlType);
368         indentPrintln("@Table(name = \"" + tableName + "\")");
369         importsAdd(Table.class.getName());
370         indentPrint("public class " + calcClassName(servKey, xmlType));
371         println (" extends BaseAttributeEntity<" + mainEntityName + "> ");
372         importsAdd ("org.kuali.student.r2.common.entity.BaseAttributeEntity");
373         openBrace();
374         println ("");
375         indentPrintln ("public " + className + "() {");
376         indentPrintln ("    super();");
377         indentPrintln ("}");
378         
379         println ("");
380         importsAdd("org.kuali.student.r2.common.infc.Attribute");
381         indentPrintln ("public " + className + "(Attribute att, " + mainEntityName + " owner) {");
382         indentPrintln ("    super(att, owner);");
383         indentPrintln ("}");
384 
385         closeBrace();
386 
387         this.writeJavaClassAndImportsOutToFile();
388         this.getOut().close();
389     }
390 
391     private String getInvalidParameterException() {
392         if (this.isRice()) {
393             return "RiceIllegalArgumentException";
394         }
395         return "InvalidParameterException";
396     }
397 
398     private String getOperationFailedException() {
399         if (this.isRice()) {
400             return "RiceIllegalArgumentException";
401         }
402         return "OperationFailedException";
403     }
404 
405     private String getDoesNotExistException() {
406         if (this.isRice()) {
407             return "RiceIllegalArgumentException";
408         }
409         return "DoesNotExistException";
410     }
411 
412     private String getVersionMismatchException() {
413         if (this.isRice()) {
414             return "RiceIllegalStateException";
415         }
416         return "VersionMismatchException";
417     }
418 
419     private void writeThrowsNotImplemented(ServiceMethod method) {
420         indentPrintln("throw new " + this.getOperationFailedException() + " (\"" + method.getName() + " has not been implemented\");");
421     }
422 
423     protected String initLower(String str) {
424         return str.substring(0, 1).toLowerCase() + str.substring(1);
425     }
426 
427     private void writeBoilerPlate() {
428         if (this.isRice()) {
429             return;
430         }
431         println("");
432         indentPrintln("private StatusInfo newStatus() {");
433         indentPrintln("     StatusInfo status = new StatusInfo();");
434         indentPrintln("     status.setSuccess(Boolean.TRUE);");
435         indentPrintln("     return status;");
436         indentPrintln("}");
437 
438         this.writeBoilerPlateR2();
439     }
440 
441     private void writeBoilerPlateR2() {
442         importsAdd("org.kuali.student.r2.common.dto.MetaInfo");
443         println("");
444 
445         indentPrintln("private MetaInfo newMeta(ContextInfo context) {");
446         indentPrintln("     MetaInfo meta = new MetaInfo();");
447         indentPrintln("     meta.setCreateId(context.getPrincipalId());");
448         importsAdd(Date.class.getName());
449         indentPrintln("     meta.setCreateTime(new Date());");
450         indentPrintln("     meta.setUpdateId(context.getPrincipalId());");
451         indentPrintln("     meta.setUpdateTime(meta.getCreateTime());");
452         indentPrintln("     meta.setVersionInd(\"0\");");
453         indentPrintln("     return meta;");
454         indentPrintln("}");
455         println("");
456         indentPrintln("private MetaInfo updateMeta(MetaInfo old, ContextInfo context) {");
457         indentPrintln("     MetaInfo meta = new MetaInfo(old);");
458         indentPrintln("     meta.setUpdateId(context.getPrincipalId());");
459         indentPrintln("     meta.setUpdateTime(new Date());");
460         indentPrintln("     meta.setVersionInd((Integer.parseInt(meta.getVersionInd()) + 1) + \"\");");
461         indentPrintln("     return meta;");
462         indentPrintln("}");
463         println("");
464 
465     }
466 
467     private String calcCriteriaLookupServiceVariableName(ServiceMethod method) {
468         String objectName = calcObjectName(method);
469         String variableName = initLower(objectName) + "CriteriaLookupService";
470         return variableName;
471     }
472 
473     private void writeValidate(ServiceMethod method) {
474         indentPrintln("return new ArrayList<ValidationResultInfo> ();");
475         this.importsAdd(ArrayList.class.getName());
476     }
477     private final Set<String> jpaEntitiesWritten = new HashSet<String>();
478 
479     private void writeDaoVariable(ServiceMethod method) {
480         String objectName = calcObjectName(method);
481         String className = objectName + "Dao";
482         String variableName = calcDaoVariableName(method);
483         if (jpaEntitiesWritten.add(variableName)) {
484             println("");
485             indentPrintln("private " + className + " " + variableName + ";");
486             println("");
487             indentPrintln("public void set" + className + "(" + className + " " + variableName + ") {");
488             incrementIndent();
489             indentPrintln("this." + variableName + " = " + variableName + ";");
490             decrementIndent();
491             indentPrintln("}");
492             println("");
493             indentPrintln("public " + className + " get" + className + "() {");
494             incrementIndent();
495             indentPrintln("return this." + variableName + ";");
496             decrementIndent();
497             indentPrintln("}");
498 
499             variableName = calcCriteriaLookupServiceVariableName(method);
500             importsAdd(CriteriaLookupService.class.getName());
501             className = "CriteriaLookupService";
502             println("");
503             indentPrintln("// Criteria Lookup for this object");
504             indentPrintln("private " + className + " " + variableName + ";");
505             println("");
506             indentPrintln("public void set" + className + "(" + className + " " + variableName + ") {");
507             incrementIndent();
508             indentPrintln("this." + variableName + " = " + variableName + ";");
509             decrementIndent();
510             indentPrintln("}");
511             println("");
512             indentPrintln("public " + className + " get" + className + "() {");
513             incrementIndent();
514             indentPrintln("return this." + variableName + ";");
515             decrementIndent();
516             indentPrintln("}");
517 
518         }
519     }
520 
521 
522     private ServiceMethodParameter findIdParameter(ServiceMethod method) {
523         String idFieldName = calcObjectName(method) + "Id";
524         for (ServiceMethodParameter parameter : method.getParameters()) {
525             if (parameter.getType().equals("String")) {
526                 if (parameter.getName().equals(idFieldName)) {
527                     return parameter;
528                 }
529             }
530         }
531 
532         // if only one parameter and it is a string then grab that
533         if (method.getParameters().size() == 1) {
534             for (ServiceMethodParameter parameter : method.getParameters()) {
535                 if (parameter.getType().equals("String")) {
536                     return parameter;
537                 }
538             }
539         }
540         // can't find name exactly 
541         for (ServiceMethodParameter parameter : method.getParameters()) {
542             if (parameter.getType().equals("String")) {
543                 if (parameter.getName().endsWith("Id")) {
544                     return parameter;
545                 }
546             }
547         }
548         // can't find name exactly try key 
549         for (ServiceMethodParameter parameter : method.getParameters()) {
550             if (parameter.getType().equals("String")) {
551                 if (!parameter.getName().endsWith("TypeKey")) {
552                     if (parameter.getName().endsWith("Key")) {
553                         return parameter;
554                     }
555                 }
556             }
557         }
558         log.warn("Could not find the Id paramter for {}.{} so returning the first one", method.getService(), method.getName());
559         return method.getParameters().get(0);
560     }
561 
562     private ServiceMethodParameter findContextParameter(ServiceMethod method) {
563         for (ServiceMethodParameter parameter : method.getParameters()) {
564             if (parameter.getType().equals("ContextInfo")) {
565                 return parameter;
566             }
567         }
568         return null;
569     }
570 
571     private ServiceMethodParameter findInfoParameter(ServiceMethod method) {
572         String objectName = calcObjectName(method);
573         if (!this.isRice()) {
574             objectName = objectName + "Info";
575         }
576         for (ServiceMethodParameter parameter : method.getParameters()) {
577             if (parameter.getType().equals(objectName)) {
578                 return parameter;
579             }
580         }
581         if (method.getParameters().size() >= 1) {
582             return method.getParameters().get(0);
583         }
584         return null;
585     }
586 
587     private ServiceMethodParameter findTypeParameter(ServiceMethod method) {
588         for (ServiceMethodParameter parameter : method.getParameters()) {
589             if (parameter.getType().equals("String")) {
590                 if (parameter.getName().endsWith("TypeKey")) {
591                     return parameter;
592                 }
593                 if (parameter.getName().endsWith("Type")) {
594                     return parameter;
595                 }
596             }
597         }
598         return null;
599     }
600 
601     private String calcDaoVariableName(ServiceMethod method) {
602         String daoVariableName = this.calcObjectName(method);
603         daoVariableName = this.initLower(daoVariableName) + "Dao";
604         return daoVariableName;
605     }
606 
607     private String calcEntityClassName(ServiceMethod method) {
608         String objectName = this.calcObjectName(method);
609         objectName = objectName + "Entity";
610         return objectName;
611     }
612 
613     protected String calcObjectName(ServiceMethod method) {
614         if (method.getName().startsWith("create")) {
615             return method.getName().substring("create".length());
616         }
617         if (method.getName().startsWith("update")) {
618             return method.getName().substring("update".length());
619         }
620         if (method.getName().startsWith("validate")) {
621             return method.getName().substring("validate".length());
622         }
623         if (method.getName().startsWith("delete")) {
624             return method.getName().substring("delete".length());
625         }
626         if (method.getName().startsWith("get")) {
627             if (method.getReturnValue().getType().equals("StringList")) {
628                 if (method.getName().contains("IdsBy")) {
629                     return method.getName().substring("get".length(),
630                             method.getName().indexOf("IdsBy"));
631                 }
632                 if (method.getName().contains("KeysBy")) {
633                     return method.getName().substring("get".length(),
634                             method.getName().indexOf("KeysBy"));
635                 }
636                 if (method.getName().contains("IdsFor")) {
637                     return method.getName().substring("get".length(),
638                             method.getName().indexOf("IdsFor"));
639                 }
640                 if (method.getName().contains("With")) {
641                     return method.getName().substring("get".length(),
642                             method.getName().indexOf("With"));
643                 }
644                 if (method.getName().contains("By")) {
645                     return method.getName().substring("get".length(),
646                             method.getName().indexOf("By"));
647                 }
648                 return method.getName().substring("get".length());
649             }
650             String name = method.getReturnValue().getType();
651             if (name.endsWith("List")) {
652                 name = name.substring(0, name.length() - "List".length());
653             }
654             if (name.endsWith("Info")) {
655                 name = name.substring(0, name.length() - "Info".length());
656             }
657             return name;
658         }
659 
660         if (method.getName().startsWith("searchFor")) {
661             if (method.getReturnValue().getType().equals("StringList")) {
662                 if (method.getName().endsWith("Ids")) {
663                     return method.getName().substring("searchFor".length(),
664                             method.getName().indexOf("Ids"));
665                 }
666                 if (method.getName().endsWith("Keys")) {
667                     return method.getName().substring("get".length(),
668                             method.getName().indexOf("Keys"));
669                 }
670                 return method.getName().substring("searchFor".length());
671             }
672             String name = method.getReturnValue().getType();
673             if (name.endsWith("List")) {
674                 name = name.substring(0, name.length() - "List".length());
675             }
676             if (name.endsWith("Info")) {
677                 name = name.substring(0, name.length() - "Info".length());
678             }
679             return name;
680         }
681         if (method.getName().startsWith("add")) {
682             return method.getName().substring("add".length());
683         }
684         if (method.getName().startsWith("remove")) {
685             return method.getName().substring("remove".length());
686         }
687         String returnType = this.stripList(method.getReturnValue().getType());
688         XmlType type = this.finder.findXmlType(returnType);
689         if (type.getPrimitive().equals(XmlType.COMPLEX)) {
690             return returnType;
691         }
692         throw new IllegalArgumentException(method.getName());
693     }
694 
695     private String calcNamedQuery(ServiceMethod method) {
696         String objectName = calcObjectName(method);
697         String name = method.getName();
698         if (name.startsWith("get")) {
699             name = name.substring("get".length());
700         }
701         if (name.startsWith(objectName)) {
702             name = name.substring(objectName.length());
703         }
704 //        if (name.startsWith("Ids")) {
705 //            name = name.substring("Ids".length());
706 //        }
707 //        if (name.isEmpty()) {
708 //            throw new RuntimeException (method.getName());
709 //        }
710         // remove plural
711         if (!method.getReturnValue().getType().equals("StringList")) {
712             if (name.startsWith("s")) {
713                 name = name.substring("s".length());
714             }
715         }
716         // add back the get
717         name = "get" + name;
718         return name;
719     }
720 
721 
722     private ServiceMethodParameter findCriteriaParam(ServiceMethod method) {
723         for (ServiceMethodParameter param : method.getParameters()) {
724             if (param.getType().equals("QueryByCriteria")) {
725                 return param;
726             }
727         }
728         return null;
729     }
730 
731     private ServiceMethodParameter getTypeParameter(ServiceMethod method) {
732         ServiceMethodParameter fallbackParam = null;
733         for (ServiceMethodParameter parameter : method.getParameters()) {
734             if (parameter.getName().endsWith("TypeKey")) {
735                 return parameter;
736             }
737             if (parameter.getType().equals("String")) {
738                 if (parameter.getName().toLowerCase().contains("type")) {
739                     fallbackParam = parameter;
740                 }
741             }
742         }
743         return fallbackParam;
744     }
745 
746     private String calcInfoName(ServiceMethod method) {
747         String objectName = this.calcObjectName(method);
748         String infoName = objectName;
749         if (!this.isRice()) {
750             infoName = infoName + "Info";
751         }
752         return infoName;
753     }
754 
755     private void writeGetIdsByType(ServiceMethod method) {
756         String objectName = this.calcObjectName(method);
757         String infoName = this.calcInfoName(method);
758         String daoVariable = calcDaoVariableName(method);
759         ServiceMethodParameter typeParam = this.getTypeParameter(method);
760         if (typeParam == null) {
761 
762         }
763         indentPrintln("return " + daoVariable + ".getIdsByType(" + typeParam.getName() + ");");
764     }
765 
766     private String initUpper(String str) {
767         return str.substring(0, 1).toUpperCase() + str.substring(1);
768     }
769 
770     private ServiceMethodParameter findIdListParameter(ServiceMethod method) {
771         String idFieldName = calcObjectName(method) + "Ids";
772         if (this.isRice()) {
773             idFieldName = "ids";
774         }
775         for (ServiceMethodParameter parameter : method.getParameters()) {
776             if (parameter.getType().equals("StringList")) {
777                 if (parameter.getName().equals(idFieldName)) {
778                     return parameter;
779                 }
780             }
781         }
782         // can't find name exactly 
783         for (ServiceMethodParameter parameter : method.getParameters()) {
784             if (parameter.getType().equals("StringList")) {
785                 if (parameter.getName().endsWith("Ids")) {
786                     return parameter;
787                 }
788             }
789         }
790         // can't find name exactly try key 
791         for (ServiceMethodParameter parameter : method.getParameters()) {
792             if (parameter.getType().equals("StringList")) {
793                 if (parameter.getName().endsWith("Keys")) {
794                     return parameter;
795                 }
796             }
797         }
798         return null;
799     }
800 
801     private String stripList(String str) {
802         return GetterSetterNameCalculator.stripList(str);
803     }
804 
805     private String calcExceptionClassName(ServiceMethodError error) {
806         if (error.getClassName() == null) {
807             return ServiceExceptionWriter.calcClassName(error.getType());
808         }
809         return error.getClassName();
810     }
811 
812     private String calcExceptionPackageName(ServiceMethodError error) {
813         if (error.getClassName() == null) {
814             return ServiceExceptionWriter.calcPackage(rootPackage);
815         }
816         return error.getPackageName();
817     }
818 
819     private String calcType(String type, String realType) {
820         XmlType t = finder.findXmlType(this.stripList(type));
821         String retType = MessageStructureTypeCalculator.calculate(this, model, type, realType,
822                 t.getJavaPackage());
823         if (this.isRice()) {
824             if (retType.equals("Boolean")) {
825                 retType = "boolean";
826             }
827             if (retType.equals("Void")) {
828                 retType = "void";
829             }
830         }
831         return retType;
832     }
833 }