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 org.kuali.rice.core.api.criteria.CriteriaLookupService;
034 import org.kuali.rice.core.api.criteria.GenericQueryResults;
035 import org.springframework.transaction.annotation.Transactional;
036
037 /**
038 *
039 * @author nwright
040 */
041 public class JpaImplServiceWriter extends JavaClassWriter {
042
043 private static Logger log = LoggerFactory.getLogger(JpaImplServiceWriter.class);
044
045 //////////////////////////////
046 // Constants
047 //////////////////////////////
048 /**
049 * The standard type of methods used in our Service contract.
050 */
051 protected static enum MethodType {
052
053 VALIDATE,
054 CREATE,
055 CREATE_BULK,
056 ADD,
057 UPDATE,
058 UPDATE_OTHER,
059 DELETE,
060 REMOVE,
061 DELETE_OTHER,
062 GET_CREATE,
063 GET_BY_ID,
064 GET_BY_IDS,
065 RICE_GET_BY_NAMESPACE_AND_NAME,
066 GET_IDS_BY_TYPE,
067 GET_IDS_BY_OTHER,
068 GET_INFOS_BY_OTHER,
069 GET_TYPE,
070 GET_TYPES,
071 SEARCH_FOR_IDS,
072 SEARCH_FOR_INFOS,
073 UNKNOWN
074 };
075
076 //////////////////////////////
077 // Data Variables
078 //////////////////////////////
079 protected ServiceContractModel model;
080 protected ModelFinder finder;
081 private String directory;
082 /**
083 * The package name is stored in the service object itself (the package spec
084 * kept moving around so I assumed the actual service name was unique but
085 * ran into a problem when we included rice because they have a StateService
086 * meaning US states and we have a StateService meaning the state of the
087 * object so I added logic to detect rice and prepend that "RICE." to it
088 */
089 private String rootPackage;
090
091 /**
092 * Name of the service being operated on. If it is a RICE service it is
093 * prefixed with RICE. [11:32:18 AM] Norman Wright: short name... I think it
094 * gets it by taking the java class SimpleName and stripping off the word
095 * "Service" and I think making it lower case. [11:32:24 AM] Norman Wright:
096 * so OrganizationService becomes organization
097 */
098 protected String servKey;
099
100 protected List<ServiceMethod> methods;
101
102 /**
103 * A flag that holds if the service is an R1 service.
104 */
105 private boolean isR1;
106
107 //////////////////////////
108 // Constructor
109 //////////////////////////
110 public JpaImplServiceWriter(ServiceContractModel model,
111 String directory,
112 String rootPackage,
113 String servKey,
114 List<ServiceMethod> methods,
115 boolean isR1) {
116 super(directory, calcPackage(servKey, rootPackage), calcClassName(servKey));
117 this.model = model;
118 this.finder = new ModelFinder(model);
119 this.directory = directory;
120 this.rootPackage = rootPackage;
121 this.servKey = servKey;
122 this.methods = methods;
123 this.isR1 = isR1;
124 }
125
126 public JpaImplServiceWriter(ServiceContractModel model,
127 String directory,
128 String rootPackage,
129 String servKey,
130 List<ServiceMethod> methods,
131 boolean isR1,
132 String packageName,
133 String className) {
134 super(directory, packageName, className);
135 this.model = model;
136 this.finder = new ModelFinder(model);
137 this.directory = directory;
138 this.rootPackage = rootPackage;
139 this.servKey = servKey;
140 this.methods = methods;
141 this.isR1 = isR1;
142 }
143
144 /////////////////////////
145 // Functional Methods
146 /////////////////////////
147 /**
148 * Returns the jpa implementation package name.
149 *
150 * @param servKey
151 * @param rootPackage
152 * @return
153 */
154 public static String calcPackage(String servKey, String rootPackage) {
155 String pack = rootPackage + ".";
156 // String pack = rootPackage + "." + servKey.toLowerCase() + ".";
157 // StringBuffer buf = new StringBuffer (service.getVersion ().length ());
158 // for (int i = 0; i < service.getVersion ().length (); i ++)
159 // {
160 // char c = service.getVersion ().charAt (i);
161 // c = Character.toLowerCase (c);
162 // if (Character.isLetter (c))
163 // {
164 // buf.append (c);
165 // continue;
166 // }
167 // if (Character.isDigit (c))
168 // {
169 // buf.append (c);
170 // }
171 // }
172 // pack = pack + buf.toString ();
173 pack = pack + "service.impl.jpa." + servKey.toLowerCase();
174 return pack;
175 }
176
177 /**
178 * Checks if this is a RICE service.
179 *
180 * @return true if this is a RICE service.
181 */
182 private boolean isRice() {
183 if (this.servKey.startsWith("RICE.")) {
184 return true;
185 }
186 return false;
187 }
188
189 protected static String fixServKey(String servKey) {
190 if (servKey.startsWith("RICE.")) {
191 return servKey.substring("RICE.".length());
192 }
193 return servKey;
194 }
195
196 /**
197 * Given the service key (name), returns a calculated class name for the jpa
198 * impl.
199 */
200 public static String calcClassName(String servKey) {
201 return GetterSetterNameCalculator.calcInitUpper(fixServKey(servKey) + "ServiceJpaImpl");
202 }
203
204 public static String calcServiceInterfaceClassName(String servKey) {
205 return GetterSetterNameCalculator.calcInitUpper(fixServKey(servKey) + "Service");
206 }
207
208 /**
209 * Analyses the method and returns a MethodType enum that describes what
210 * type of method this is.
211 */
212 protected MethodType calcMethodType(ServiceMethod method) {
213 // if (method.getName().equals("getInstructionalDaysForTerm")) {
214 // System.out.println("debug here");
215 // }
216 if (this.isRice()) {
217 if (method.getName().contains("ByNamespaceCodeAndName")) {
218 return MethodType.RICE_GET_BY_NAMESPACE_AND_NAME;
219 }
220 if (method.getName().contains("ByNameAndNamespace")) {
221 return MethodType.RICE_GET_BY_NAMESPACE_AND_NAME;
222 }
223 if (method.getName().startsWith("get")) {
224 if (method.getParameters().size() == 1) {
225 if (!method.getReturnValue().getType().endsWith("List")) {
226 if (method.getParameters().get(0).getName().equals("id")) {
227 return MethodType.GET_BY_ID;
228 }
229
230 } else {
231 if (method.getParameters().get(0).getName().equals("ids")) {
232 return MethodType.GET_BY_IDS;
233 }
234 }
235 }
236 }
237 }
238 if (method.getName().startsWith("validate")) {
239 return MethodType.VALIDATE;
240 }
241 if (method.getName().startsWith("create")) {
242 if (method.getName().startsWith("createBatch")) {
243 return MethodType.CREATE_BULK;
244 }
245 if (method.getName().startsWith("createSocRolloverResultItems")) {
246 return MethodType.CREATE_BULK;
247 }
248 if (method.getName().contains("FromExisting")) {
249 return MethodType.CREATE_BULK;
250 }
251 ServiceMethodParameter infoParam = this.findInfoParameter(method);
252 if (infoParam == null) {
253 return MethodType.CREATE_BULK;
254 }
255 if (method.getReturnValue().getType().endsWith("List")) {
256 return MethodType.CREATE_BULK;
257 }
258 return MethodType.CREATE;
259 }
260 if (method.getName().startsWith("add")) {
261 return MethodType.ADD;
262 }
263 if (method.getName().startsWith("update")) {
264 if (this.findInfoParameter(method) != null) {
265 return MethodType.UPDATE;
266 }
267 return MethodType.UPDATE_OTHER;
268 }
269 if (method.getName().startsWith("delete")) {
270 if (method.getName().contains("By")) {
271 if (!method.getName().startsWith("deleteBy")) {
272 return MethodType.DELETE_OTHER;
273 }
274 }
275 if (method.getName().contains("For")) {
276 if (!method.getName().startsWith("deleteFor")) {
277 return MethodType.DELETE_OTHER;
278 }
279 }
280 return MethodType.DELETE;
281 }
282 if (method.getName().startsWith("remove")) {
283 return MethodType.REMOVE;
284 }
285
286 if (method.getName().startsWith("getCreate")) {
287 return MethodType.GET_CREATE;
288 }
289
290 if (method.getName().startsWith("get")) {
291 if (method.getName().endsWith("ByIds")) {
292 return MethodType.GET_BY_IDS;
293 }
294 if (method.getName().endsWith("ByKeys")) {
295 return MethodType.GET_BY_IDS;
296 }
297 if (method.getName().endsWith("ByType")) {
298 return MethodType.GET_IDS_BY_TYPE;
299 }
300 if (method.getReturnValue().getType().endsWith("TypeInfo")) {
301 return MethodType.GET_TYPE;
302 }
303 if (method.getReturnValue().getType().endsWith("TypeInfoList")) {
304 return MethodType.GET_TYPES;
305 }
306 if (method.getName().endsWith("ByType")) {
307 return MethodType.GET_IDS_BY_TYPE;
308 }
309 String splitName = splitCamelCase(method.getName());
310 if (splitName.contains(" By ")) {
311 if (method.getReturnValue().getType().equals("StringList")) {
312 return MethodType.GET_IDS_BY_OTHER;
313 }
314 if (method.getReturnValue().getType().endsWith("InfoList")) {
315 return MethodType.GET_INFOS_BY_OTHER;
316 }
317 return MethodType.UNKNOWN;
318 }
319 if (splitName.contains(" For ")) {
320 if (method.getReturnValue().getType().equals("StringList")) {
321 return MethodType.GET_IDS_BY_OTHER;
322 }
323 if (method.getReturnValue().getType().endsWith("InfoList")) {
324 return MethodType.GET_INFOS_BY_OTHER;
325 }
326 return MethodType.UNKNOWN;
327 }
328 if (method.getParameters().size() >= 1 && method.getParameters().size() <= 2) {
329 if (!method.getReturnValue().getType().endsWith("List")) {
330 if (method.getParameters().get(0).getName().endsWith("Id")) {
331 return MethodType.GET_BY_ID;
332 }
333 if (method.getParameters().get(0).getName().endsWith("Key")) {
334 return MethodType.GET_BY_ID;
335 }
336 }
337 }
338 }
339 if (method.getName().startsWith("searchFor")) {
340 if (method.getName().endsWith("Ids")) {
341 return MethodType.SEARCH_FOR_IDS;
342 }
343 if (method.getName().endsWith("Keys")) {
344 return MethodType.SEARCH_FOR_IDS;
345 }
346 return MethodType.SEARCH_FOR_INFOS;
347 }
348
349 return MethodType.UNKNOWN;
350 }
351
352 // got this from
353 // http://stackoverflow.com/questions/2559759/how-do-i-convert-camelcase-into-human-readable-names-in-java
354 private static String splitCamelCase(String s) {
355 if (s == null) {
356 return null;
357 }
358 return s.replaceAll(String.format("%s|%s|%s",
359 "(?<=[A-Z])(?=[A-Z][a-z])", "(?<=[^A-Z])(?=[A-Z])",
360 "(?<=[A-Za-z])(?=[^A-Za-z])"), " ");
361 }
362
363 /**
364 * Write out the entire file
365 */
366 public void write() {
367 indentPrintln("@Transactional(readOnly = true, noRollbackFor = {DoesNotExistException.class}, rollbackFor = {Throwable.class})");
368 importsAdd(Transactional.class.getName());
369 indentPrint("public class " + calcClassName(servKey));
370 println(" implements " + calcServiceInterfaceClassName(servKey));
371 Service serv = finder.findService(servKey);
372 importsAdd(serv.getImplProject() + "." + serv.getName());
373 openBrace();
374 // put all the cache variables at the top
375 indentPrintln("// dao variables ");
376 jpaEntitiesWritten.clear();
377 for (ServiceMethod method : methods) {
378 MethodType methodType = calcMethodType(method);
379 switch (methodType) {
380 case CREATE:
381 case GET_TYPE:
382 case GET_BY_ID:
383 writeDaoVariable(method);
384 }
385 }
386
387 for (ServiceMethod method : methods) {
388 MethodType methodType = calcMethodType(method);
389 println("");
390 // indentPrintln("/**");
391 // indentPrintWrappedComment(method.getDescription());
392 // indentPrintln("* ");
393 // for (ServiceMethodParameter param : method.getParameters()) {
394 // indentPrintWrappedComment("@param " + param.getName() + " - "
395 // + param.getType() + " - "
396 // + param.getDescription());
397 // }
398 // indentPrintWrappedComment("@return " + method.getReturnValue().
399 // getDescription());
400 // indentPrintln("*/");
401 indentPrintln("@Override");
402 switch (methodType) {
403 case CREATE:
404 indentPrintln("@Transactional");
405 break;
406 case ADD:
407 indentPrintln("@Transactional");
408 break;
409 case UPDATE:
410 indentPrintln("@Transactional");
411 break;
412 case DELETE:
413 indentPrintln("@Transactional");
414 break;
415 case REMOVE:
416 indentPrintln("@Transactional");
417 break;
418 case GET_BY_ID:
419 indentPrintln("@Transactional(readOnly = true)");
420 break;
421 case GET_BY_IDS:
422 indentPrintln("@Transactional(readOnly = true)");
423 break;
424 case GET_IDS_BY_TYPE:
425 indentPrintln("@Transactional(readOnly = true)");
426 break;
427 case GET_IDS_BY_OTHER:
428 indentPrintln("@Transactional(readOnly = true)");
429 break;
430 case GET_INFOS_BY_OTHER:
431 indentPrintln("@Transactional(readOnly = true)");
432 break;
433 case GET_TYPE:
434 indentPrintln("@Transactional(readOnly = true)");
435 break;
436 case GET_TYPES:
437 indentPrintln("@Transactional(readOnly = true)");
438 break;
439 case RICE_GET_BY_NAMESPACE_AND_NAME:
440 indentPrintln("@Transactional(readOnly = true)");
441 break;
442 default:
443 }
444 String type = method.getReturnValue().getType();
445 String realType = stripList(type);
446 indentPrint("public " + calcType(type, realType) + " " + method.getName()
447 + "(");
448 // now do parameters
449 String comma = "";
450 for (ServiceMethodParameter param : method.getParameters()) {
451 type = param.getType();
452 realType = stripList(type);
453 print(comma);
454 print(calcType(type, realType));
455 print(" ");
456 print(param.getName());
457 comma = ", ";
458 }
459 println(")");
460 // now do exceptions
461 comma = "throws ";
462 incrementIndent();
463 for (ServiceMethodError error : method.getErrors()) {
464 indentPrint(comma);
465 String exceptionClassName = calcExceptionClassName(error);
466 String exceptionPackageName = this.calcExceptionPackageName(error);
467 println(exceptionClassName);
468 this.importsAdd(exceptionPackageName + "." + exceptionClassName);
469 comma = " ,";
470 }
471 decrementIndent();
472 openBrace();
473 indentPrintln("// " + methodType);
474 switch (methodType) {
475 case VALIDATE:
476 writeValidate(method);
477 break;
478 case CREATE:
479 writeCreate(method);
480 break;
481 case ADD:
482 writeAdd(method);
483 break;
484 case UPDATE:
485 writeUpdate(method);
486 break;
487 case DELETE:
488 writeDelete(method);
489 break;
490 case REMOVE:
491 writeRemove(method);
492 break;
493 case GET_BY_ID:
494 writeGetById(method);
495 break;
496 case GET_BY_IDS:
497 writeGetByIds(method);
498 break;
499 case GET_IDS_BY_TYPE:
500 writeGetIdsByType(method);
501 break;
502 case GET_IDS_BY_OTHER:
503 writeGetIdsByOther(method);
504 break;
505 case GET_INFOS_BY_OTHER:
506 writeGetInfosByOther(method);
507 break;
508 case SEARCH_FOR_IDS:
509 writeSearchForIds(method);
510 break;
511 case SEARCH_FOR_INFOS:
512 writeSearchForInfos(method);
513 break;
514 case GET_TYPE:
515 writeGetType(method);
516 break;
517 case GET_TYPES:
518 writeGetTypes(method);
519 break;
520 case RICE_GET_BY_NAMESPACE_AND_NAME:
521 writeRiceGetByNamespaceAndName(method);
522 break;
523 default:
524 writeThrowsNotImplemented(method);
525 }
526 closeBrace();
527 }
528
529 closeBrace();
530
531 this.writeJavaClassAndImportsOutToFile();
532 this.getOut().close();
533 }
534
535 private String getInvalidParameterException() {
536 if (this.isRice()) {
537 return "RiceIllegalArgumentException";
538 }
539 return "InvalidParameterException";
540 }
541
542 private String getOperationFailedException() {
543 if (this.isRice()) {
544 return "RiceIllegalArgumentException";
545 }
546 return "OperationFailedException";
547 }
548
549 private String getDoesNotExistException() {
550 if (this.isRice()) {
551 return "RiceIllegalArgumentException";
552 }
553 return "DoesNotExistException";
554 }
555
556 private String getVersionMismatchException() {
557 if (this.isRice()) {
558 return "RiceIllegalStateException";
559 }
560 return "VersionMismatchException";
561 }
562
563 private void writeThrowsNotImplemented(ServiceMethod method) {
564 indentPrintln("throw new " + this.getOperationFailedException() + " (\"" + method.getName() + " has not been implemented\");");
565 }
566
567 protected String initLower(String str) {
568 return str.substring(0, 1).toLowerCase() + str.substring(1);
569 }
570
571 private String calcCriteriaLookupServiceVariableName(ServiceMethod method) {
572 String objectName = calcObjectName(method);
573 String variableName = initLower(objectName) + "CriteriaLookupService";
574 return variableName;
575 }
576
577 private void writeValidate(ServiceMethod method) {
578 indentPrintln("return new ArrayList<ValidationResultInfo> ();");
579 this.importsAdd(ArrayList.class.getName());
580 }
581 private final Set<String> jpaEntitiesWritten = new HashSet<String>();
582
583 private void writeDaoVariable(ServiceMethod method) {
584 String objectName = calcObjectName(method);
585 String className = objectName + "Dao";
586 String variableName = calcDaoVariableName(method);
587 if (jpaEntitiesWritten.add(variableName)) {
588 XmlType xmlType = finder.findXmlType(objectName + "Info");
589 if (xmlType == null) {
590 System.out.println ("Cannot write DAO because the object does not follow patterns. ObjectName="
591 + objectName + " method=" + method);
592 return;
593 }
594 new JpaEntityWriter(model, directory, rootPackage, servKey, methods, xmlType, isR1).write();
595 new JpaDaoWriter(model, directory, rootPackage, servKey, methods, xmlType, isR1).write();
596 println("");
597 indentPrintln("private " + className + " " + variableName + ";");
598 println("");
599 indentPrintln("public void set" + className + "(" + className + " " + variableName + ") {");
600 incrementIndent();
601 indentPrintln("this." + variableName + " = " + variableName + ";");
602 decrementIndent();
603 indentPrintln("}");
604 println("");
605 indentPrintln("public " + className + " get" + className + "() {");
606 incrementIndent();
607 indentPrintln("return this." + variableName + ";");
608 decrementIndent();
609 indentPrintln("}");
610
611 variableName = calcCriteriaLookupServiceVariableName(method);
612
613 importsAdd(CriteriaLookupService.class.getName());
614 className = "CriteriaLookupService";
615 println("");
616 indentPrintln("// Criteria Lookup for this object");
617 indentPrintln("private " + className + " " + variableName + ";");
618 println("");
619 indentPrintln("public void set" + initUpper(variableName) + "(" + className + " " + variableName + ") {");
620 incrementIndent();
621 indentPrintln("this." + variableName + " = " + variableName + ";");
622 decrementIndent();
623 indentPrintln("}");
624 println("");
625 indentPrintln("public " + className + " get" + initUpper(variableName) + "() {");
626 incrementIndent();
627 indentPrintln("return this." + variableName + ";");
628 decrementIndent();
629 indentPrintln("}");
630
631 }
632 }
633
634 private void writeCreate(ServiceMethod method) {
635
636 // holdInfo.setPersonId(personId);
637 // holdInfo.setHoldIssueId(issueId);
638 // holdInfo.setTypeKey(holdTypeKey);
639 //
640 // HoldIssueEntity holdIssueEntity = holdIssueDao.find(issueId);
641 // if (holdIssueEntity == null) {
642 // throw new InvalidParameterException(issueId);
643 // }
644 // AppliedHoldEntity entity = new AppliedHoldEntity(holdInfo);
645 // entity.setHoldIssue(holdIssueEntity);
646 // entity.setEntityCreated(context);
647 // appliedHoldDao.persist(entity);
648 // appliedHoldDao.getEm().flush();
649 // return entity.toDto();
650 String daoVariable = calcDaoVariableName(method);
651 String entityClassName = calcEntityClassName(method);
652 ServiceMethodParameter typeParam = this.findTypeParameter(method);
653 ServiceMethodParameter infoParam = this.findInfoParameter(method);
654 ServiceMethodParameter contextParam = this.findContextParameter(method);
655 String objectName = calcObjectName(method);
656 String infoName = objectName;
657 if (!this.isRice()) {
658 infoName = infoName + "Info";
659 }
660 String daoName = calcDaoVariableName(method);
661 if (typeParam != null) {
662 indentPrintln(infoParam.getName() + ".setTypeKey (" + typeParam.getName() + ");");
663 }
664 if (method.getParameters().size() > 3) {
665 indentPrintln("//TODO: JPAIMPL overwrite the rest of the readonly fields that are specified on the create in the info object");
666 }
667 indentPrintln(entityClassName + " entity = new " + entityClassName + "(" + infoParam.getName() + ");");
668 indentPrintln("entity.setEntityCreated(" + contextParam.getName() + ");");
669 indentPrintln(daoVariable + ".persist(entity);");
670 indentPrintln(daoVariable + ".getEm().flush();");
671 indentPrintln("return entity.toDto();");
672 }
673
674 private void writeAdd(ServiceMethod method) {
675 indentPrintln ("//TODO: JPAIMPL this needs to be implemented");
676 indentPrintln ("throw new OperationFailedException (\"Not implemented\");");
677 }
678
679 private ServiceMethodParameter findIdParameter(ServiceMethod method) {
680 String idFieldName = calcObjectName(method) + "Id";
681 for (ServiceMethodParameter parameter : method.getParameters()) {
682 if (parameter.getType().equals("String")) {
683 if (parameter.getName().equals(idFieldName)) {
684 return parameter;
685 }
686 }
687 }
688
689 // if only one parameter and it is a string then grab that
690 if (method.getParameters().size() == 1) {
691 for (ServiceMethodParameter parameter : method.getParameters()) {
692 if (parameter.getType().equals("String")) {
693 return parameter;
694 }
695 }
696 }
697 // can't find name exactly
698 for (ServiceMethodParameter parameter : method.getParameters()) {
699 if (parameter.getType().equals("String")) {
700 if (parameter.getName().endsWith("Id")) {
701 return parameter;
702 }
703 }
704 }
705 // can't find name exactly try key
706 for (ServiceMethodParameter parameter : method.getParameters()) {
707 if (parameter.getType().equals("String")) {
708 if (!parameter.getName().endsWith("TypeKey")) {
709 if (parameter.getName().endsWith("Key")) {
710 return parameter;
711 }
712 }
713 }
714 }
715 log.warn("Could not find the Id paramter for " + method.getService() + "." + method.getName() + " so returning the first one");
716 return method.getParameters().get(0);
717 }
718
719 private ServiceMethodParameter findContextParameter(ServiceMethod method) {
720 for (ServiceMethodParameter parameter : method.getParameters()) {
721 if (parameter.getType().equals("ContextInfo")) {
722 return parameter;
723 }
724 }
725 return null;
726 }
727
728 private ServiceMethodParameter findInfoParameter(ServiceMethod method) {
729 String objectName = calcObjectName(method);
730 if (!this.isRice()) {
731 objectName = objectName + "Info";
732 }
733 for (ServiceMethodParameter parameter : method.getParameters()) {
734 if (parameter.getType().equals(objectName)) {
735 return parameter;
736 }
737 }
738 if (method.getParameters().size() >= 1) {
739 return method.getParameters().get(0);
740 }
741 return null;
742 }
743
744 private ServiceMethodParameter findTypeParameter(ServiceMethod method) {
745 for (ServiceMethodParameter parameter : method.getParameters()) {
746 if (parameter.getType().equals("String")) {
747 if (parameter.getName().endsWith("TypeKey")) {
748 return parameter;
749 }
750 if (parameter.getName().endsWith("Type")) {
751 return parameter;
752 }
753 }
754 }
755 return null;
756 }
757
758 private String calcDaoVariableName(ServiceMethod method) {
759 String daoVariableName = this.calcObjectName(method);
760 daoVariableName = this.initLower(daoVariableName) + "Dao";
761 return daoVariableName;
762 }
763
764 private String calcEntityClassName(ServiceMethod method) {
765 String objectName = this.calcObjectName(method);
766 objectName = objectName + "Entity";
767 return objectName;
768 }
769
770 protected String calcObjectName(ServiceMethod method) {
771 if (method.getName().startsWith("create")) {
772 return method.getName().substring("create".length());
773 }
774 if (method.getName().startsWith("update")) {
775 return method.getName().substring("update".length());
776 }
777 if (method.getName().startsWith("validate")) {
778 return method.getName().substring("validate".length());
779 }
780 if (method.getName().startsWith("delete")) {
781 return method.getName().substring("delete".length());
782 }
783 if (method.getName().startsWith("get")) {
784 if (method.getReturnValue().getType().equals("StringList")) {
785 if (method.getName().contains("IdsBy")) {
786 return method.getName().substring("get".length(),
787 method.getName().indexOf("IdsBy"));
788 }
789 if (method.getName().contains("KeysBy")) {
790 return method.getName().substring("get".length(),
791 method.getName().indexOf("KeysBy"));
792 }
793 if (method.getName().contains("IdsFor")) {
794 return method.getName().substring("get".length(),
795 method.getName().indexOf("IdsFor"));
796 }
797 if (method.getName().contains("With")) {
798 return method.getName().substring("get".length(),
799 method.getName().indexOf("With"));
800 }
801 if (method.getName().contains("By")) {
802 return method.getName().substring("get".length(),
803 method.getName().indexOf("By"));
804 }
805 return method.getName().substring("get".length());
806 }
807 String name = method.getReturnValue().getType();
808 if (name.endsWith("List")) {
809 name = name.substring(0, name.length() - "List".length());
810 }
811 if (name.endsWith("Info")) {
812 name = name.substring(0, name.length() - "Info".length());
813 }
814 return name;
815 }
816
817 if (method.getName().startsWith("searchFor")) {
818 if (method.getReturnValue().getType().equals("StringList")) {
819 if (method.getName().endsWith("Ids")) {
820 return method.getName().substring("searchFor".length(),
821 method.getName().indexOf("Ids"));
822 }
823 if (method.getName().endsWith("Keys")) {
824 return method.getName().substring("get".length(),
825 method.getName().indexOf("Keys"));
826 }
827 return method.getName().substring("searchFor".length());
828 }
829 String name = method.getReturnValue().getType();
830 if (name.endsWith("List")) {
831 name = name.substring(0, name.length() - "List".length());
832 }
833 if (name.endsWith("Info")) {
834 name = name.substring(0, name.length() - "Info".length());
835 }
836 return name;
837 }
838 if (method.getName().startsWith("add")) {
839 return method.getName().substring("add".length());
840 }
841 if (method.getName().startsWith("remove")) {
842 return method.getName().substring("remove".length());
843 }
844 String returnType = this.stripList(method.getReturnValue().getType());
845 XmlType type = this.finder.findXmlType(returnType);
846 if (type.getPrimitive().equals(XmlType.COMPLEX)) {
847 return returnType;
848 }
849 throw new IllegalArgumentException(method.getName());
850 }
851
852 private void writeUpdate(ServiceMethod method) {
853 // if (!holdId.equals(holdInfo.getId())) {
854 // throw new InvalidParameterException(holdId + " does not match the id in the object " + holdInfo.getId());
855 // }
856 // AppliedHoldEntity entity = appliedHoldDao.find(holdId);
857 // if (null == entity) {
858 // throw new DoesNotExistException(holdId);
859 // }
860 // entity.fromDto(holdInfo);
861 // entity.setEntityUpdated(context);
862 // entity = appliedHoldDao.merge(entity);
863 // appliedHoldDao.getEm().flush(); // need to flush to get the version indicator updated
864 // return entity.toDto();
865 ServiceMethodParameter idParam = this.findIdParameter(method);
866 ServiceMethodParameter infoParam = this.findInfoParameter(method);
867 ServiceMethodParameter contextParam = this.findContextParameter(method);
868 String daoVariable = calcDaoVariableName(method);
869 String entityClassName = calcEntityClassName(method);
870 if (infoParam == null) {
871 throw new NullPointerException(method.getName());
872 }
873 String objectName = calcObjectName(method);
874 String infoName = objectName;
875 if (!this.isRice()) {
876 infoName = infoName + "Info";
877 }
878 if (idParam != null) {
879 if (!this.isRice()) {
880 indentPrintln("if (!" + idParam.getName() + ".equals (" + infoParam.getName() + ".getId())) {");
881 indentPrintln(" throw new " + this.getInvalidParameterException() + " (\"The id parameter does not match the id on the info object\");");
882 indentPrintln("}");
883 }
884 }
885 indentPrintln(entityClassName + " entity = " + daoVariable + ".find(" + idParam.getName() + ");");
886 indentPrintln("if (entity == null) {");
887 incrementIndent();
888 indentPrintln("throw new DoesNotExistException(" + idParam.getName() + ");");
889 decrementIndent();
890 indentPrintln("}");
891 indentPrintln("entity.fromDto(" + infoParam.getName() + ");");
892 indentPrintln("entity.setEntityUpdated(" + contextParam.getName() + ");");
893 indentPrintln("entity = " + daoVariable + ".merge(entity);");
894 indentPrintln("return entity.toDto();");
895 }
896
897 private void writeDelete(ServiceMethod method) {
898 // AppliedHoldEntity entity = appliedHoldDao.find(holdId);
899 // if (null == entity) {
900 // throw new DoesNotExistException(holdId);
901 // }
902 // appliedHoldDao.remove(entity);
903 // StatusInfo status = new StatusInfo();
904 // status.setSuccess(Boolean.TRUE);
905 // return status;
906 ServiceMethodParameter idParam = this.findIdParameter(method);
907 String daoVariable = calcDaoVariableName(method);
908 String entityClassName = calcEntityClassName(method);
909 indentPrintln(entityClassName + " entity = " + daoVariable + ".find(" + idParam.getName() + ");");
910 indentPrintln("if (entity == null) {");
911 incrementIndent();
912 indentPrintln("throw new DoesNotExistException(" + idParam.getName() + ");");
913 decrementIndent();
914 indentPrintln("}");
915 indentPrintln(daoVariable + ".remove(entity);");
916 indentPrintln("StatusInfo status = new StatusInfo();");
917 importsAdd("org.kuali.student.r2.common.dto.StatusInfo");
918 indentPrintln("status.setSuccess(Boolean.TRUE);");
919 indentPrintln("return status;");
920 }
921
922 private void writeRemove(ServiceMethod method) {
923 indentPrintln ("//TODO: JPAIMPL this needs to be implemented");
924 indentPrintln ("throw new OperationFailedException (\"Not implemented\");");
925 }
926
927 private void writeGetById(ServiceMethod method) {
928 // AppliedHoldEntity entity = appliedHoldDao.find(holdId);
929 // if (entity == null) {
930 // throw new DoesNotExistException(holdId);
931 // }
932 // return entity.toDto();
933 ServiceMethodParameter idParam = this.findIdParameter(method);
934 String daoVariable = calcDaoVariableName(method);
935 String entityClassName = calcEntityClassName(method);
936 indentPrintln(entityClassName + " entity = " + daoVariable + ".find(" + idParam.getName() + ");");
937 indentPrintln("if (entity == null) {");
938 incrementIndent();
939 indentPrintln("throw new DoesNotExistException(" + idParam.getName() + ");");
940 decrementIndent();
941 indentPrintln("}");
942 indentPrintln("return entity.toDto();");
943 }
944
945 private void writeGetByIds(ServiceMethod method) {
946 // List<HoldIssueEntity> holdIssues = holdIssueDao.findByIds(issueIds);
947 // List<HoldIssueInfo> result = new ArrayList<HoldIssueInfo>(holdIssues.size());
948 // for (HoldIssueEntity entity : holdIssues) {
949 // if (entity == null) {
950 // // if one of the entities from "findByIds" is returned as null, then one of the keys in the list was not found
951 // throw new DoesNotExistException();
952 // }
953 // result.add(entity.toDto());
954 // }
955 // return result;
956 String daoVariable = calcDaoVariableName(method);
957 String entityClassName = calcEntityClassName(method);
958 String objectName = this.calcObjectName(method);
959 ServiceMethodParameter idListParam = this.findIdListParameter(method);
960 String infoName = objectName;
961 infoName = infoName + "Info";
962 this.importsAdd(ArrayList.class.getName());
963 indentPrintln("List<" + entityClassName + "> entities = " + daoVariable + ".findByIds(" + idListParam.getName() + ");");
964 indentPrintln("List<" + infoName + "> list = new ArrayList<" + infoName + "> (entities.size());");
965 indentPrintln("for (" + entityClassName + " entity : entities) {");
966 incrementIndent();
967 indentPrintln("if (entity == null) {");
968 incrementIndent();
969 indentPrintln("throw new DoesNotExistException();");
970 decrementIndent();
971 indentPrintln("}");
972 indentPrintln("list.add(entity.toDto());");
973 decrementIndent();
974 indentPrintln("}");
975 indentPrintln("return list;");
976 }
977
978 private String calcNamedQuery(ServiceMethod method) {
979 String objectName = calcObjectName(method);
980 String name = method.getName();
981 if (name.startsWith("get")) {
982 name = name.substring("get".length());
983 }
984 if (name.startsWith(objectName)) {
985 name = name.substring(objectName.length());
986 }
987 // if (name.startsWith("Ids")) {
988 // name = name.substring("Ids".length());
989 // }
990 // if (name.isEmpty()) {
991 // throw new RuntimeException (method.getName());
992 // }
993 // remove plural
994 if (!method.getReturnValue().getType().equals("StringList")) {
995 if (name.startsWith("s")) {
996 name = name.substring("s".length());
997 }
998 }
999 // add back the get
1000 name = "get" + name;
1001 return name;
1002 }
1003
1004 private void writeGetIdsByOther(ServiceMethod method) {
1005 // return appliedHoldDao.getIdsByIssue(issueId);
1006 String objectName = this.calcObjectName(method);
1007 String infoName = objectName;
1008 if (!this.isRice()) {
1009 infoName = infoName + "Info";
1010 }
1011 String daoVariableName = calcDaoVariableName(method);
1012 String namedQuery = calcNamedQuery(method);
1013 indentPrint("return " + daoVariableName + "." + namedQuery + "(");
1014 String comma = "";
1015 for (ServiceMethodParameter param : method.getParameters()) {
1016 if (param.getType().equals("ContextInfo")) {
1017 continue;
1018 }
1019 print(comma);
1020 comma = ", ";
1021 print(param.getName());
1022 }
1023 println(");");
1024 }
1025
1026 private ServiceMethodParameter findCriteriaParam(ServiceMethod method) {
1027 for (ServiceMethodParameter param : method.getParameters()) {
1028 if (param.getType().equals("QueryByCriteria")) {
1029 return param;
1030 }
1031 }
1032 return null;
1033 }
1034
1035 private void writeSearchForIds(ServiceMethod method) {
1036 // List<String> results = new ArrayList<String>();
1037 // GenericQueryResults<AppliedHoldEntity> appliedHolds = criteriaLookupService.lookup(AppliedHoldEntity.class, criteria);
1038 // if (null != appliedHolds && appliedHolds.getResults().size() > 0) {
1039 // for (AppliedHoldEntity appliedHold : appliedHolds.getResults()) {
1040 // results.add(appliedHold.getId());
1041 // }
1042 // }
1043 // return results;
1044 String objectName = this.calcObjectName(method);
1045 String infoName = objectName;
1046 if (!this.isRice()) {
1047 infoName = infoName + "Info";
1048 }
1049 String criteriaLookupVariableName = calcCriteriaLookupServiceVariableName(method);
1050 String entityClassName = this.calcEntityClassName(method);
1051 ServiceMethodParameter criteriaParam = findCriteriaParam(method);
1052 importsAdd(CriteriaLookupService.class.getName());
1053 importsAdd(ArrayList.class.getName());
1054 importsAdd(List.class.getName());
1055 indentPrintln("List<String> results = new ArrayList<String>();");
1056 importsAdd (GenericQueryResults.class.getName ());
1057 indentPrintln("GenericQueryResults<" + entityClassName + "> entities");
1058 indentPrintln(" = " + criteriaLookupVariableName + ".lookup(" + entityClassName + ".class, " + criteriaParam.getName() + ");");
1059 indentPrintln("if (null != entities && !entities.getResults().isEmpty()) {");
1060 incrementIndent();
1061 indentPrintln("for (" + entityClassName + " entity : entities.getResults()) {");
1062 incrementIndent();
1063 indentPrintln("results.add(entity.getId());");
1064 decrementIndent();
1065 indentPrintln("}");
1066 decrementIndent();
1067 indentPrintln("}");
1068 indentPrintln("return results;");
1069 }
1070
1071 private void writeSearchForInfos(ServiceMethod method) {
1072 // List<AppliedHoldInfo> results = new ArrayList<AppliedHoldInfo>();
1073 // GenericQueryResults<AppliedHoldEntity> appliedHolds = criteriaLookupService.lookup(AppliedHoldEntity.class, criteria);
1074 // if (null != appliedHolds && appliedHolds.getResults().size() > 0) {
1075 // for (AppliedHoldEntity appliedHold : appliedHolds.getResults()) {
1076 // results.add(appliedHold.toDto());
1077 // }
1078 // }
1079 // return results;
1080 String objectName = this.calcObjectName(method);
1081 String criteriaLookupVariableName = calcCriteriaLookupServiceVariableName(method);
1082 String entityClassName = this.calcEntityClassName(method);
1083 String infoName = this.calcInfoName(method);
1084 ServiceMethodParameter criteriaParam = findCriteriaParam(method);
1085 importsAdd(CriteriaLookupService.class.getName());
1086 importsAdd(ArrayList.class.getName());
1087 importsAdd(List.class.getName());
1088 indentPrintln("List<" + infoName + "> results = new ArrayList<" + infoName + ">();");
1089 importsAdd (GenericQueryResults.class.getName ());
1090 indentPrintln("GenericQueryResults<" + entityClassName + "> entities");
1091 indentPrintln(" = " + criteriaLookupVariableName + ".lookup(" + entityClassName + ".class, " + criteriaParam.getName() + ");");
1092 indentPrintln("if (null != entities && !entities.getResults().isEmpty()) {");
1093 incrementIndent();
1094 indentPrintln("for (" + entityClassName + " entity : entities.getResults()) {");
1095 incrementIndent();
1096 indentPrintln("results.add(entity.toDto());");
1097 decrementIndent();
1098 indentPrintln("}");
1099 decrementIndent();
1100 indentPrintln("}");
1101 indentPrintln("return results;");
1102 }
1103
1104 private ServiceMethodParameter getTypeParameter(ServiceMethod method) {
1105 ServiceMethodParameter fallbackParam = null;
1106 for (ServiceMethodParameter parameter : method.getParameters()) {
1107 if (parameter.getName().endsWith("TypeKey")) {
1108 return parameter;
1109 }
1110 if (parameter.getType().equals("String")) {
1111 if (parameter.getName().toLowerCase().contains("type")) {
1112 fallbackParam = parameter;
1113 }
1114 }
1115 }
1116 return fallbackParam;
1117 }
1118
1119 private String calcInfoName(ServiceMethod method) {
1120 String objectName = this.calcObjectName(method);
1121 String infoName = objectName;
1122 if (!this.isRice()) {
1123 infoName = infoName + "Info";
1124 }
1125 return infoName;
1126 }
1127
1128 private void writeGetIdsByType(ServiceMethod method) {
1129 String objectName = this.calcObjectName(method);
1130 String infoName = this.calcInfoName(method);
1131 String daoVariable = calcDaoVariableName(method);
1132 ServiceMethodParameter typeParam = this.getTypeParameter(method);
1133 if (typeParam == null) {
1134
1135 }
1136 indentPrintln("return " + daoVariable + ".getIdsByType(" + typeParam.getName() + ");");
1137 }
1138
1139 private void writeRiceGetByNamespaceAndName(ServiceMethod method) {
1140 indentPrintln ("//TODO: JPAIMPL this needs to be implemented");
1141 indentPrintln ("throw new OperationFailedException (\"Not implemented\");");
1142 }
1143
1144 private void writeGetInfosByOther(ServiceMethod method) {
1145 // List<AppliedHoldEntity> entities = this.appliedHoldDao.getByPerson(personId);
1146 // List<AppliedHoldInfo> result = new ArrayList<AppliedHoldInfo>(entities.size());
1147 // for (AppliedHoldEntity entity : entities) {
1148 // result.add(entity.toDto());
1149 // }
1150 // return result;
1151 String objectName = this.calcObjectName(method);
1152 String infoName = objectName;
1153 if (!this.isRice()) {
1154 infoName = infoName + "Info";
1155 }
1156 String daoVariableName = calcDaoVariableName(method);
1157 String namedQuery = calcNamedQuery(method);
1158 String entityClassName = calcEntityClassName(method);
1159 indentPrint("List<" + entityClassName + "> entities = " + daoVariableName + "." + namedQuery + "(");
1160 String comma = "";
1161 for (ServiceMethodParameter param : method.getParameters()) {
1162 if (param.getType().equals("ContextInfo")) {
1163 continue;
1164 }
1165 print(comma);
1166 comma = ", ";
1167 print(param.getName());
1168 }
1169 println(");");
1170 this.importsAdd(ArrayList.class.getName());
1171 indentPrintln("List<" + infoName + "> list = new ArrayList<" + infoName + "> (entities.size());");
1172 indentPrintln("for (" + entityClassName + " entity: entities) {");
1173 indentPrintln(" list.add (entity.toDto ());");
1174 indentPrintln("}");
1175 indentPrintln("return list;");
1176 }
1177
1178 private void writeGetType(ServiceMethod method) {
1179 indentPrintln ("//TODO: JPAIMPL this needs to be implemented");
1180 indentPrintln ("throw new OperationFailedException (\"Not implemented\");");
1181 }
1182
1183 private void writeGetTypes(ServiceMethod method) {
1184 indentPrintln ("//TODO: JPAIMPL this needs to be implemented");
1185 indentPrintln ("throw new OperationFailedException (\"Not implemented\");");
1186 }
1187
1188 private String initUpper(String str) {
1189 return str.substring(0, 1).toUpperCase() + str.substring(1);
1190 }
1191
1192 private ServiceMethodParameter findIdListParameter(ServiceMethod method) {
1193 String idFieldName = calcObjectName(method) + "Ids";
1194 if (this.isRice()) {
1195 idFieldName = "ids";
1196 }
1197 for (ServiceMethodParameter parameter : method.getParameters()) {
1198 if (parameter.getType().equals("StringList")) {
1199 if (parameter.getName().equals(idFieldName)) {
1200 return parameter;
1201 }
1202 }
1203 }
1204 // can't find name exactly
1205 for (ServiceMethodParameter parameter : method.getParameters()) {
1206 if (parameter.getType().equals("StringList")) {
1207 if (parameter.getName().endsWith("Ids")) {
1208 return parameter;
1209 }
1210 }
1211 }
1212 // can't find name exactly try key
1213 for (ServiceMethodParameter parameter : method.getParameters()) {
1214 if (parameter.getType().equals("StringList")) {
1215 if (parameter.getName().endsWith("Keys")) {
1216 return parameter;
1217 }
1218 }
1219 }
1220 return null;
1221 }
1222
1223 private String stripList(String str) {
1224 return GetterSetterNameCalculator.stripList(str);
1225 }
1226
1227 private String calcExceptionClassName(ServiceMethodError error) {
1228 if (error.getClassName() == null) {
1229 return ServiceExceptionWriter.calcClassName(error.getType());
1230 }
1231 return error.getClassName();
1232 }
1233
1234 private String calcExceptionPackageName(ServiceMethodError error) {
1235 if (error.getClassName() == null) {
1236 return ServiceExceptionWriter.calcPackage(rootPackage);
1237 }
1238 return error.getPackageName();
1239 }
1240
1241 private String calcType(String type, String realType) {
1242 XmlType t = finder.findXmlType(this.stripList(type));
1243 String retType = MessageStructureTypeCalculator.calculate(this, model, type, realType,
1244 t.getJavaPackage());
1245 if (this.isRice()) {
1246 if (retType.equals("Boolean")) {
1247 retType = "boolean";
1248 }
1249 if (retType.equals("Void")) {
1250 retType = "void";
1251 }
1252 }
1253 return retType;
1254 }
1255 }