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.contract.writer.service;
017    
018    import java.util.*;
019    import org.kuali.student.contract.model.*;
020    import org.kuali.student.contract.model.util.ModelFinder;
021    import org.kuali.student.contract.writer.JavaClassWriter;
022    
023    /**
024     *
025     * @author nwright
026     */
027    public class MockImplServiceWriter extends JavaClassWriter {
028    
029        private ServiceContractModel model;
030        private ModelFinder finder;
031        private String directory;
032        private String rootPackage;
033        private String servKey;
034        private List<ServiceMethod> methods;
035        private boolean isR1;
036    
037        public MockImplServiceWriter(ServiceContractModel model,
038                String directory,
039                String rootPackage,
040                String servKey,
041                List<ServiceMethod> methods,
042                boolean isR1) {
043            super(directory, calcPackage(servKey, rootPackage), calcClassName(servKey));
044            this.model = model;
045            this.finder = new ModelFinder(model);
046            this.directory = directory;
047            this.rootPackage = rootPackage;
048            this.servKey = servKey;
049            this.methods = methods;
050            this.isR1 = isR1;
051        }
052    
053        public static String calcPackage(String servKey, String rootPackage) {
054            String pack = rootPackage + ".";
055    //        String pack = rootPackage + "." + servKey.toLowerCase() + ".";
056    //  StringBuffer buf = new StringBuffer (service.getVersion ().length ());
057    //  for (int i = 0; i < service.getVersion ().length (); i ++)
058    //  {
059    //   char c = service.getVersion ().charAt (i);
060    //   c = Character.toLowerCase (c);
061    //   if (Character.isLetter (c))
062    //   {
063    //    buf.append (c);
064    //    continue;
065    //   }
066    //   if (Character.isDigit (c))
067    //   {
068    //    buf.append (c);
069    //   }
070    //  }
071    //  pack = pack + buf.toString ();
072            pack = pack + "service.impl.mock";
073            return pack;
074        }
075    
076        public static String calcClassName(String servKey) {
077            return GetterSetterNameCalculator.calcInitUpper(servKey + "ServiceMockImpl");
078        }
079    
080        public static String calcServiceInterfaceClassName(String servKey) {
081            return GetterSetterNameCalculator.calcInitUpper(servKey + "Service");
082        }
083    
084        private static enum MethodType {
085    
086            VALIDATE,
087            CREATE,
088            CREATE_BULK,
089            ADD,
090            UPDATE,
091            UPDATE_OTHER,
092            DELETE,
093            REMOVE,
094            DELETE_OTHER,
095            GET_CREATE,
096            GET_BY_ID,
097            GET_BY_IDS,
098            GET_IDS_BY_TYPE,
099            GET_IDS_BY_OTHER,
100            GET_INFOS_BY_OTHER,
101            GET_TYPE,
102            GET_TYPES,
103            UNKNOWN
104        };
105    
106        private MethodType calcMethodType(ServiceMethod method) {
107            if (method.getName().startsWith("validate")) {
108                return MethodType.VALIDATE;
109            }
110            if (method.getName().startsWith("create")) {
111                if (this.findInfoParameter(method) != null) {
112                    return MethodType.CREATE;
113                }
114                return MethodType.CREATE_BULK;
115            }
116            if (method.getName().startsWith("add")) {
117                return MethodType.ADD;
118            }
119            if (method.getName().startsWith("update")) {
120                if (this.findInfoParameter(method) != null) {
121                    return MethodType.UPDATE;
122                }
123                return MethodType.UPDATE_OTHER;
124            }
125            if (method.getName().startsWith("delete")) {
126                if (method.getName().contains("By")) {
127                    if (!method.getName().startsWith("deleteBy")) {
128                        return MethodType.DELETE_OTHER;
129                    }
130                }
131                if (method.getName().contains("For")) {
132                    if (!method.getName().startsWith("deleteFor")) {
133                        return MethodType.DELETE_OTHER;
134                    }
135                }
136                return MethodType.DELETE;
137            }
138            if (method.getName().startsWith("remove")) {
139                return MethodType.REMOVE;
140            }
141            
142            if (method.getName().startsWith("getCreate")) {
143                return MethodType.GET_CREATE;            
144            }
145            if (method.getName().startsWith("get")) {
146                if (method.getName().endsWith("ByIds")) {
147                    return MethodType.GET_BY_IDS;
148                }
149                if (method.getName().endsWith("ByType")) {
150                    return MethodType.GET_IDS_BY_TYPE;
151                }
152                if (method.getReturnValue().getType().endsWith("TypeInfo")) {
153                    return MethodType.GET_TYPE;
154                }
155                if (method.getReturnValue().getType().endsWith("TypeInfoList")) {
156                    return MethodType.GET_TYPES;
157                }
158                if (method.getName().endsWith("ByType")) {
159                    return MethodType.GET_IDS_BY_TYPE;
160                }
161                if (method.getParameters().size() >= 1 && method.getParameters().size() <= 2) {
162                    if (!method.getReturnValue().getType().endsWith("List")) {
163                        if (method.getParameters().get(0).getName().endsWith("Id")) {
164                            return MethodType.GET_BY_ID;
165                        }
166                    }
167                }
168                if (method.getName().contains("By")) {
169                    if (method.getReturnValue().getType().equals("StringList")) {
170                        return MethodType.GET_IDS_BY_OTHER;
171                    }
172                    if (method.getReturnValue().getType().endsWith("InfoList")) {
173                        return MethodType.GET_INFOS_BY_OTHER;
174                    }
175                }
176            }
177    
178            return MethodType.UNKNOWN;
179        }
180    
181        /**
182         * Write out the entire file
183         *
184         * @param out
185         */
186        public void write() {
187            indentPrint("public class " + calcClassName(servKey));
188            println(" implements " + calcServiceInterfaceClassName(servKey));
189            Service serv = finder.findService(servKey);
190            importsAdd(serv.getImplProject() + "." + serv.getName());
191            openBrace();
192            for (ServiceMethod method : methods) {
193                MethodType methodType = calcMethodType(method);
194                switch (methodType) {
195                    case CREATE:
196                    case ADD:
197                    case GET_TYPE:
198                        writeCacheVariable(method);
199                }
200                indentPrintln("");
201    //            indentPrintln("/**");
202    //            indentPrintWrappedComment(method.getDescription());
203    //            indentPrintln("* ");
204    //            for (ServiceMethodParameter param : method.getParameters()) {
205    //                indentPrintWrappedComment("@param " + param.getName() + " - "
206    //                        + param.getType() + " - "
207    //                        + param.getDescription());
208    //            }
209    //            indentPrintWrappedComment("@return " + method.getReturnValue().
210    //                    getDescription());
211    //            indentPrintln("*/");
212                indentPrintln("@Override");
213                String type = method.getReturnValue().getType();
214                String realType = stripList(type);
215                indentPrint("public " + calcType(type, realType) + " " + method.getName()
216                        + "(");
217                // now do parameters
218                String comma = "";
219                for (ServiceMethodParameter param : method.getParameters()) {
220                    type = param.getType();
221                    realType = stripList(type);
222                    print(comma);
223                    print(calcType(type, realType));
224                    print(" ");
225                    print(param.getName());
226                    comma = ", ";
227                }
228                println(")");
229                // now do exceptions
230                comma = "throws ";
231                incrementIndent();
232                for (ServiceMethodError error : method.getErrors()) {
233                    indentPrint(comma);
234                    String exceptionClassName = calcExceptionClassName(error);
235                    String exceptionPackageName = this.calcExceptionPackageName(error);
236                    println(exceptionClassName);
237                    this.importsAdd(exceptionPackageName + "." + exceptionClassName);
238                    comma = "      ,";
239                }
240                decrementIndent();
241                openBrace();
242                switch (methodType) {
243                    case VALIDATE:
244                        writeValidate(method);
245                        break;
246                    case CREATE:
247                        writeCreate(method);
248                        break;
249                    case ADD:
250                        writeAdd(method);
251                        break;
252                    case UPDATE:
253                        writeUpdate(method);
254                        break;
255                    case DELETE:
256                        writeDelete(method);
257                        break;
258                    case REMOVE:
259                        writeRemove(method);
260                        break;
261                    case GET_BY_ID:
262                        writeGetById(method);
263                        break;
264                    case GET_BY_IDS:
265                        writeGetByIds(method);
266                        break;
267                    case GET_IDS_BY_TYPE:
268                        writeGetIdsByType(method);
269                        break;
270                    case GET_IDS_BY_OTHER:
271                        writeGetIdsByOther(method);
272                        break;
273                    case GET_INFOS_BY_OTHER:
274                        writeGetInfosByOther(method);
275                        break;
276                    case GET_TYPE:
277                        writeGetType(method);
278                        break;
279                    case GET_TYPES:
280                        writeGetTypes(method);
281                        break;
282                    default:
283                        writeThrowsNotImplemented(method);
284                }
285                closeBrace();
286            }
287    
288            writeBoilerPlate();
289            closeBrace();
290    
291            this.writeJavaClassAndImportsOutToFile();
292            this.getOut().close();
293        }
294    
295        private void writeThrowsNotImplemented(ServiceMethod method) {
296            indentPrintln("throw new OperationFailedException (\"" + method.getName() + " has not been implemented\");");
297        }
298    
299        private String initLower(String str) {
300            return str.substring(0, 1).toLowerCase() + str.substring(1);
301        }
302    
303        private void writeBoilerPlate() {
304            indentPrintln("");
305            indentPrintln("private StatusInfo newStatus() {");
306            indentPrintln("     StatusInfo status = new StatusInfo();");
307            indentPrintln("     status.setSuccess(Boolean.TRUE);");
308            indentPrintln("     return status;");
309            indentPrintln("}");
310            if (isR1) {
311                this.writeBoilerPlateR1();
312            } else {
313                this.writeBoilerPlateR2();
314            }
315    
316        }
317    
318        private void writeBoilerPlateR1() {
319            importsAdd("org.kuali.student.common.dto.MetaInfo");
320            indentPrintln("");
321    
322            indentPrintln("private MetaInfo newMeta() {");
323            indentPrintln("     MetaInfo meta = new MetaInfo();");
324            indentPrintln("     meta.setCreateId(\"MOCKUSER\");");
325            importsAdd(Date.class.getName());
326            indentPrintln("     meta.setCreateTime(new Date());");
327            indentPrintln("     meta.setUpdateId(\"MOCKUSER\");");
328            indentPrintln("     meta.setUpdateTime(meta.getCreateTime());");
329            indentPrintln("     meta.setVersionInd(\"0\");");
330            indentPrintln("     return meta;");
331            indentPrintln("}");
332            indentPrintln("");
333            indentPrintln("private MetaInfo updateMeta(MetaInfo meta) {");
334            indentPrintln("     meta.setUpdateId(\"MOCKUSER\");");
335            indentPrintln("     meta.setUpdateTime(new Date());");
336            indentPrintln("     meta.setVersionInd((Integer.parseInt(meta.getVersionInd()) + 1) + \"\");");
337            indentPrintln("     return meta;");
338            indentPrintln("}");
339            indentPrintln("");
340    
341        }
342    
343        private void writeBoilerPlateR2() {
344            importsAdd("org.kuali.student.r2.common.dto.MetaInfo");
345            indentPrintln("");
346    
347            indentPrintln("private MetaInfo newMeta(ContextInfo context) {");
348            indentPrintln("     MetaInfo meta = new MetaInfo();");
349            indentPrintln("     meta.setCreateId(context.getPrincipalId());");
350            importsAdd(Date.class.getName());
351            indentPrintln("     meta.setCreateTime(new Date());");
352            indentPrintln("     meta.setUpdateId(context.getPrincipalId());");
353            indentPrintln("     meta.setUpdateTime(meta.getCreateTime());");
354            indentPrintln("     meta.setVersionInd(\"0\");");
355            indentPrintln("     return meta;");
356            indentPrintln("}");
357            indentPrintln("");
358            indentPrintln("private MetaInfo updateMeta(MetaInfo old, ContextInfo context) {");
359            indentPrintln("     MetaInfo meta = new MetaInfo(old);");
360            indentPrintln("     meta.setUpdateId(context.getPrincipalId());");
361            indentPrintln("     meta.setUpdateTime(new Date());");
362            indentPrintln("     meta.setVersionInd((Integer.parseInt(meta.getVersionInd()) + 1) + \"\");");
363            indentPrintln("     return meta;");
364            indentPrintln("}");
365            indentPrintln("");
366    
367        }
368    
369        private void writeValidate(ServiceMethod method) {
370            indentPrintln("// validate");
371            indentPrintln("return new ArrayList<ValidationResultInfo> ();");
372    
373    
374            this.importsAdd(ArrayList.class.getName());
375        }
376    
377        private void writeCacheVariable(ServiceMethod method) {
378            indentPrintln("// cache variable ");
379            String objectName = calcObjectName(method);
380            String mapName = calcMapName(method);
381            indentPrintln("// The LinkedHashMap is just so the values come back in a predictable order");
382            indentPrintln("private Map<String, " + objectName + "Info> " + mapName + " = new LinkedHashMap<String, " + objectName + "Info>();");
383            importsAdd(Map.class.getName());
384            importsAdd(LinkedHashMap.class.getName());
385        }
386    
387        private void writeCreate(ServiceMethod method) {
388            indentPrintln("// create ");
389            ServiceMethodParameter typeParam = this.findTypeParameter(method);
390            ServiceMethodParameter infoParam = this.findInfoParameter(method);
391            ServiceMethodParameter contextParam = this.findContextParameter(method);
392            String objectName = calcObjectName(method);
393            String infoName = objectName + "Info";
394            String mapName = calcMapName(method);
395    
396            if (typeParam != null) {
397                indentPrintln("if (!" + typeParam.getName() + ".equals (" + infoParam.getName() + ".getTypeKey())) {");
398                indentPrintln("    throw new InvalidParameterException (\"The type parameter does not match the type on the info object\");");
399                indentPrintln("}");
400            }
401            if (method.getParameters().size() > 3) {
402                indentPrintln("// TODO: check the rest of the readonly fields that are specified on the create to make sure they match the info object");
403            }
404            if (isR1) {
405                indentPrintln("// don't have deep copy in R1 contracts so just use the object");
406                indentPrintln(infoName + " copy = " + infoParam.getName() + ";");
407            } else {
408                indentPrintln(infoName + " copy = new " + infoName + "(" + infoParam.getName() + ");");
409            }
410            indentPrintln("if (copy.getId() == null) {");
411            indentPrintln("   copy.setId(" + mapName + ".size() + \"\");");
412            indentPrintln("}");
413            if (contextParam != null) {
414                indentPrintln("copy.setMeta(newMeta(" + contextParam.getName() + "));");
415            }
416            indentPrintln(mapName + ".put(copy.getId(), copy);");
417            if (isR1) {
418                indentPrintln("return copy;");
419            } else {
420                indentPrintln("return new " + infoName + "(copy);");
421            }
422        }
423    
424        private void writeAdd(ServiceMethod method) {
425            indentPrintln("// Add ");
426            ServiceMethodParameter typeParam = this.findTypeParameter(method);
427            ServiceMethodParameter infoParam = this.findInfoParameter(method);
428            ServiceMethodParameter contextParam = this.findContextParameter(method);
429            String objectName = calcObjectName(method);
430            String infoName = objectName + "Info";
431            String mapName = calcMapName(method);
432    
433            if (typeParam != null) {
434                indentPrintln("if (!" + typeParam.getName() + ".equals (" + infoParam.getName() + ".getTypeKey())) {");
435                indentPrintln("    throw new InvalidParameterException (\"The type parameter does not match the type on the info object\");");
436                indentPrintln("}");
437            }
438            if (method.getParameters().size() > 3) {
439                indentPrintln("// TODO: check the rest of the readonly fields that are specified on the create to make sure they match the info object");
440            }
441            if (isR1) {
442                indentPrintln("// don't have deep copy in R1 contracts so just use the object");
443                indentPrintln(infoName + " copy = " + infoParam.getName() + ";");
444            } else {
445                indentPrintln(infoName + " copy = new " + infoName + "(" + infoParam.getName() + ");");
446            }
447            indentPrintln("if (copy.getId() == null) {");
448            indentPrintln("   copy.setId(" + mapName + ".size() + \"\");");
449            indentPrintln("}");
450            if (contextParam != null) {
451                indentPrintln("copy.setMeta(newMeta(" + contextParam.getName() + "));");
452            }
453            indentPrintln(mapName + ".put(copy.getId(), copy);");
454            if (isR1) {
455                indentPrintln("return copy;");
456            } else {
457                indentPrintln("return new " + infoName + "(copy);");
458            }
459        }
460    
461        private ServiceMethodParameter findIdParameter(ServiceMethod method) {
462            String idFieldName = calcObjectName(method) + "Id";
463            for (ServiceMethodParameter parameter : method.getParameters()) {
464                if (parameter.getType().equals("String")) {
465                    if (parameter.getName().equals(idFieldName)) {
466                        return parameter;
467                    }
468                }
469            }
470    
471            // if only one parameter and it is a string then grab that
472            if (method.getParameters().size() == 1) {
473                for (ServiceMethodParameter parameter : method.getParameters()) {
474                    if (parameter.getType().equals("String")) {
475                        return parameter;
476                    }
477                }
478            }
479            // can't find name exactly 
480            for (ServiceMethodParameter parameter : method.getParameters()) {
481                if (parameter.getType().equals("String")) {
482                    if (parameter.getName().endsWith("Id")) {
483                        return parameter;
484                    }
485                }
486            }
487            // can't find name exactly try key 
488            for (ServiceMethodParameter parameter : method.getParameters()) {
489                if (parameter.getType().equals("String")) {
490                    if (!parameter.getName().endsWith("TypeKey")) {
491                        if (parameter.getName().endsWith("Key")) {
492                            return parameter;
493                        }
494                    }
495                }
496            }
497            System.out.println ("Could not find the Id paramter for " + method.getService() + "." + method.getName() + " so returning the first one");
498            return method.getParameters().get(0);
499        }
500    
501        private ServiceMethodParameter findContextParameter(ServiceMethod method) {
502            for (ServiceMethodParameter parameter : method.getParameters()) {
503                if (parameter.getType().equals("ContextInfo")) {
504                    return parameter;
505                }
506            }
507            return null;
508        }
509    
510        private ServiceMethodParameter findInfoParameter(ServiceMethod method) {
511            String objectName = calcObjectName(method) + "Info";
512            for (ServiceMethodParameter parameter : method.getParameters()) {
513                if (parameter.getType().equals(objectName)) {
514                    return parameter;
515                }
516            }
517            if (method.getParameters().size() >= 1) {
518                return method.getParameters().get(0);
519            }
520            return null;
521        }
522    
523        private ServiceMethodParameter findTypeParameter(ServiceMethod method) {
524            for (ServiceMethodParameter parameter : method.getParameters()) {
525                if (parameter.getType().equals("String")) {
526                    if (parameter.getName().endsWith("TypeKey")) {
527                        return parameter;
528                    }
529                    if (parameter.getName().endsWith("Type")) {
530                        return parameter;
531                    }
532                }
533            }
534            return null;
535        }
536    
537        private String calcMapName(ServiceMethod method) {
538            String mapName = this.calcObjectName(method);
539            mapName = this.initLower(mapName) + "Map";
540            return mapName;
541        }
542    
543        private String calcObjectName(ServiceMethod method) {
544            if (method.getName().startsWith("create")) {
545                return method.getName().substring("create".length());
546            }
547            if (method.getName().startsWith("update")) {
548                return method.getName().substring("update".length());
549            }
550            if (method.getName().startsWith("validate")) {
551                return method.getName().substring("validate".length());
552            }
553            if (method.getName().startsWith("delete")) {
554                return method.getName().substring("delete".length());
555            }
556            if (method.getName().startsWith("get")) {
557                if (method.getReturnValue().getType().equals("StringList")) {
558                    if (method.getName().contains("IdsBy")) {
559                        return method.getName().substring("get".length(),
560                                method.getName().indexOf("IdsBy"));
561                    }
562                    if (method.getName().contains("IdsFor")) {
563                        return method.getName().substring("get".length(),
564                                method.getName().indexOf("IdsFor"));
565                    }
566                    return method.getName().substring("get".length());
567                }
568                String name = method.getReturnValue().getType();
569                if (name.endsWith("List")) {
570                    name = name.substring(0, name.length() - "List".length());
571                }
572                if (name.endsWith("Info")) {
573                    name = name.substring(0, name.length() - "Info".length());
574                }
575                return name;
576            }
577            if (method.getName().startsWith("add")) {
578                return method.getName().substring("add".length());
579            }
580            if (method.getName().startsWith("remove")) {
581                return method.getName().substring("remove".length());
582            }
583    
584            throw new IllegalArgumentException(method.getName());
585        }
586    
587        private void writeUpdate(ServiceMethod method) {
588            indentPrintln("// update");
589            ServiceMethodParameter idParam = this.findIdParameter(method);
590            ServiceMethodParameter infoParam = this.findInfoParameter(method);
591            ServiceMethodParameter contextParam = this.findContextParameter(method);
592            if (infoParam == null) {
593                throw new NullPointerException(method.getName());
594            }
595            String objectName = calcObjectName(method);
596            String infoName = objectName + "Info";
597            String mapName = calcMapName(method);
598            if (idParam != null) {
599                indentPrintln("if (!" + idParam.getName() + ".equals (" + infoParam.getName() + ".getId())) {");
600                indentPrintln("    throw new InvalidParameterException (\"The id parameter does not match the id on the info object\");");
601                indentPrintln("}");
602            }
603            if (isR1) {
604                indentPrintln("// don't have deep copy in R1 contracts so just use the object");
605                indentPrintln(infoName + " copy = " + infoParam.getName() + ";");
606            } else {
607                indentPrintln(infoName + " copy = new " + infoName + "(" + infoParam.getName() + ");");
608            }
609            if (contextParam != null) {
610                indentPrintln(infoName + " old = this.get" + objectName + "(" + infoParam.getName() + ".getId(), " + contextParam.getName() + ");");
611            } else {
612                indentPrintln(infoName + " old = this.get" + objectName + "(" + infoParam.getName() + ".getId());");
613            }
614            if (isR1) {
615                indentPrintln("if (!old.getMetaInfo().getVersionInd().equals(copy.getMetaInfo().getVersionInd())) {");
616                indentPrintln("    throw new VersionMismatchException(old.getMetaInfo().getVersionInd());");
617                indentPrintln("}");
618                if (contextParam != null) {
619                    indentPrintln("copy.setMeta(updateMeta(copy.getMetaInfo()));");
620                }
621            } else {
622                indentPrintln("if (!old.getMeta().getVersionInd().equals(copy.getMeta().getVersionInd())) {");
623                indentPrintln("    throw new VersionMismatchException(old.getMeta().getVersionInd());");
624                indentPrintln("}");
625                if (contextParam != null) {
626                    indentPrintln("copy.setMeta(updateMeta(copy.getMeta(), " + contextParam.getName() + "));");
627                }
628            }
629            indentPrintln("this." + mapName + " .put(" + infoParam.getName() + ".getId(), copy);");
630            if (isR1) {
631                indentPrintln("return copy;");
632            } else {
633                indentPrintln("return new " + infoName + "(copy);");
634            }
635    
636        }
637    
638        private void writeDelete(ServiceMethod method) {
639            ServiceMethodParameter idParam = this.findIdParameter(method);
640            String mapName = calcMapName(method);
641            indentPrintln("if (this." + mapName + ".remove(" + idParam.getName() + ") == null) {");
642            indentPrintln("   throw new DoesNotExistException(" + idParam.getName() + ");");
643            indentPrintln("}");
644            indentPrintln("return newStatus();");
645        }
646    
647        private void writeRemove(ServiceMethod method) {
648            ServiceMethodParameter idParam = this.findIdParameter(method);
649            String mapName = calcMapName(method);
650            indentPrintln("if (this." + mapName + ".remove(" + idParam.getName() + ") == null) {");
651            indentPrintln("   throw new DoesNotExistException(" + idParam.getName() + ");");
652            indentPrintln("}");
653            indentPrintln("return newStatus();");
654        }
655    
656        private void writeGetById(ServiceMethod method) {
657            ServiceMethodParameter idParam = this.findIdParameter(method);
658            String mapName = calcMapName(method);
659            indentPrintln("if (!this." + mapName + ".containsKey(" + idParam.getName() + ")) {");
660            indentPrintln("   throw new DoesNotExistException(" + idParam.getName() + ");");
661            indentPrintln("}");        
662            String objectName = calcObjectName(method);
663            String infoName = objectName + "Info";
664            if (isR1) {
665                 indentPrintln("return this." + mapName + ".get (" + idParam.getName() + ");");
666            } else {
667                indentPrintln("return new " + infoName + "(this." + mapName + ".get (" + idParam.getName() + "));");
668            }
669            
670        }
671    
672        private void writeGetByIds(ServiceMethod method) {
673            String objectName = this.calcObjectName(method);
674            String infoName = objectName + "Info";
675            ServiceMethodParameter idListParam = this.findIdListParameter(method);
676            ServiceMethodParameter contextParam = this.findContextParameter(method);
677            indentPrintln("List<" + infoName + "> list = new ArrayList<" + infoName + "> ();");
678            indentPrintln("for (String id: " + idListParam.getName() + ") {");
679            indentPrintln("    list.add (this.get" + objectName + "(id, " + contextParam.getName() + "));");
680            indentPrintln("}");
681            indentPrintln("return list;");
682        }
683    
684        private void writeGetIdsByOther(ServiceMethod method) {
685            String objectName = this.calcObjectName(method);
686            String infoName = objectName + "Info";
687            String mapName = calcMapName(method);
688            indentPrintln("List<String> list = new ArrayList<String> ();");
689            indentPrintln("for (" + infoName + " info: " + mapName + ".values ()) {");
690            for (ServiceMethodParameter parameter : method.getParameters()) {
691                if (parameter.getType().equals("ContextInfo")) {
692                    continue;
693                }
694                incrementIndent();
695                indentPrintln("if (" + parameter.getName() + ".equals(info.get" + initUpper(parameter.getName()) + "())) {");
696            }
697            indentPrintln("    list.add (info.getId ());");
698            for (ServiceMethodParameter parameter : method.getParameters()) {
699                if (parameter.getType().equals("ContextInfo")) {
700                    continue;
701                }
702                indentPrintln("}");
703                decrementIndent();
704            }
705            indentPrintln("}");
706            indentPrintln("return list;");
707        }
708    
709        private void writeGetIdsByType(ServiceMethod method) {
710            String objectName = this.calcObjectName(method);
711            String infoName = objectName + "Info";
712            String mapName = calcMapName(method);
713            indentPrintln("List<String> list = new ArrayList<String> ();");
714            indentPrintln("for (" + infoName + " info: " + mapName + ".values ()) {");
715            for (ServiceMethodParameter parameter : method.getParameters()) {
716                if (parameter.getType().equals("ContextInfo")) {
717                    continue;
718                }
719                incrementIndent();
720                indentPrintln("if (" + parameter.getName() + ".equals(info.getTypeKey())) {");
721            }
722            indentPrintln("    list.add (info.getId ());");
723            for (ServiceMethodParameter parameter : method.getParameters()) {
724                if (parameter.getType().equals("ContextInfo")) {
725                    continue;
726                }
727                indentPrintln("}");
728                decrementIndent();
729            }
730            indentPrintln("}");
731            indentPrintln("return list;");
732        }
733    
734        private void writeGetInfosByOther(ServiceMethod method) {
735            String objectName = this.calcObjectName(method);
736            String infoName = objectName + "Info";
737            String mapName = calcMapName(method);
738            indentPrintln("List<" + infoName + "> list = new ArrayList<" + infoName + "> ();");
739            indentPrintln("for (" + infoName + " info: " + mapName + ".values ()) {");
740            for (ServiceMethodParameter parameter : method.getParameters()) {
741                if (parameter.getType().equals("ContextInfo")) {
742                    continue;
743                }
744                incrementIndent();
745                indentPrintln("if (" + parameter.getName() + ".equals(info.get" + initUpper(parameter.getName()) + "())) {");
746            }
747            indentPrintln("    list.add (info);");
748            for (ServiceMethodParameter parameter : method.getParameters()) {
749                if (parameter.getType().equals("ContextInfo")) {
750                    continue;
751                }
752                indentPrintln("}");
753                decrementIndent();
754            }
755            indentPrintln("}");
756            indentPrintln("return list;");
757        }
758    
759        private void writeGetType(ServiceMethod method) {
760            ServiceMethodParameter idParam = this.findIdParameter(method);
761            String mapName = calcMapName(method);
762            indentPrintln("if (!this." + mapName + ".containsKey(" + idParam.getName() + ")) {");
763            indentPrintln("   throw new DoesNotExistException(" + idParam.getName() + ");");
764            indentPrintln("}");
765            indentPrintln("return this." + mapName + ".get (" + idParam.getName() + ");");
766        }
767    
768        private void writeGetTypes(ServiceMethod method) {
769            ServiceMethodParameter idParam = this.findIdParameter(method);
770            String mapName = calcMapName(method);
771            String objectName = this.calcObjectName(method);
772            String infoName = objectName + "Info";
773            indentPrintln("return new ArrayList<" + infoName + ">(" + mapName + ".values ());");
774        }
775    
776        private String initUpper(String str) {
777            return str.substring(0, 1).toUpperCase() + str.substring(1);
778        }
779    
780        private ServiceMethodParameter findIdListParameter(ServiceMethod method) {
781            String idFieldName = calcObjectName(method) + "Ids";
782            for (ServiceMethodParameter parameter : method.getParameters()) {
783                if (parameter.getType().equals("StringList")) {
784                    if (parameter.getName().equals(idFieldName)) {
785                        return parameter;
786                    }
787                }
788            }
789            // can't find name exactly 
790            for (ServiceMethodParameter parameter : method.getParameters()) {
791                if (parameter.getType().equals("StringList")) {
792                    if (parameter.getName().endsWith("Ids")) {
793                        return parameter;
794                    }
795                }
796            }
797            // can't find name exactly try key 
798            for (ServiceMethodParameter parameter : method.getParameters()) {
799                if (parameter.getType().equals("StringList")) {
800                    if (parameter.getName().endsWith("Keys")) {
801                        return parameter;
802                    }
803                }
804            }
805            return null;
806        }
807    
808        private String stripList(String str) {
809            return GetterSetterNameCalculator.stripList(str);
810        }
811    
812        private String calcExceptionClassName(ServiceMethodError error) {
813            if (error.getClassName() == null) {
814                return ServiceExceptionWriter.calcClassName(error.getType());
815            }
816            return error.getClassName();
817        }
818    
819        private String calcExceptionPackageName(ServiceMethodError error) {
820            if (error.getClassName() == null) {
821                return ServiceExceptionWriter.calcPackage(rootPackage);
822            }
823            return error.getPackageName();
824        }
825    
826        private String calcType(String type, String realType) {
827            XmlType t = finder.findXmlType(this.stripList(type));
828            return MessageStructureTypeCalculator.calculate(this, model, type, realType,
829                    t.getJavaPackage());
830        }
831    }