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.jpa.mojo;
017    
018    import org.kuali.student.contract.model.Service;
019    import org.kuali.student.contract.model.ServiceContractModel;
020    import org.kuali.student.contract.model.ServiceMethod;
021    import org.kuali.student.contract.model.ServiceMethodError;
022    import org.kuali.student.contract.model.ServiceMethodParameter;
023    import org.kuali.student.contract.model.XmlType;
024    import org.kuali.student.contract.model.util.ModelFinder;
025    import org.kuali.student.contract.writer.JavaClassWriter;
026    import org.kuali.student.contract.writer.service.GetterSetterNameCalculator;
027    import org.kuali.student.contract.writer.service.MessageStructureTypeCalculator;
028    import org.kuali.student.contract.writer.service.ServiceExceptionWriter;
029    import org.slf4j.Logger;
030    import org.slf4j.LoggerFactory;
031    
032    import java.util.*;
033    import javax.persistence.Entity;
034    import javax.persistence.NamedQueries;
035    import javax.persistence.NamedQuery;
036    import javax.persistence.Table;
037    import org.kuali.rice.core.api.criteria.CriteriaLookupService;
038    import org.kuali.student.contract.model.MessageStructure;
039    
040    /**
041     *
042     * @author nwright
043     */
044    public class JpaAttributeEntityWriter extends JavaClassWriter {
045    
046        private static Logger log = LoggerFactory.getLogger(JpaAttributeEntityWriter.class);
047    
048        //////////////////////////////
049        // Constants
050        //////////////////////////////
051        /**
052         * The standard type of methods used in our Service contract.
053         */
054        protected static enum MethodType {
055    
056            VALIDATE,
057            CREATE,
058            CREATE_BULK,
059            ADD,
060            UPDATE,
061            UPDATE_OTHER,
062            DELETE,
063            REMOVE,
064            DELETE_OTHER,
065            GET_CREATE,
066            GET_BY_ID,
067            GET_BY_IDS,
068            RICE_GET_BY_NAMESPACE_AND_NAME,
069            GET_IDS_BY_TYPE,
070            GET_IDS_BY_OTHER,
071            GET_INFOS_BY_OTHER,
072            GET_TYPE,
073            GET_TYPES,
074            SEARCH_FOR_IDS,
075            SEARCH_FOR_INFOS,
076            UNKNOWN
077        };
078    
079        //////////////////////////////
080        // Data Variables
081        //////////////////////////////
082        protected ServiceContractModel model;
083        protected ModelFinder finder;
084        private String directory;
085        private XmlType xmlType;
086        /**
087         * The package name is stored in the service object itself (the package spec
088         * kept moving around so I assumed the actual service name was unique but
089         * ran into a problem when we included rice because they have a StateService
090         * meaning US states and we have a StateService meaning the state of the
091         * object so I added logic to detect rice and prepend that "RICE." to it
092         */
093        private String rootPackage;
094    
095        /**
096         * Name of the service being operated on. If it is a RICE service it is
097         * prefixed with RICE. [11:32:18 AM] Norman Wright: short name... I think it
098         * gets it by taking the java class SimpleName and stripping off the word
099         * "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 " + method.getService() + "." + method.getName() + " so returning the first one");
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    }