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