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 */ 016package org.kuali.student.jpa.mojo; 017 018import org.kuali.student.contract.model.Service; 019import org.kuali.student.contract.model.ServiceContractModel; 020import org.kuali.student.contract.model.ServiceMethod; 021import org.kuali.student.contract.model.ServiceMethodError; 022import org.kuali.student.contract.model.ServiceMethodParameter; 023import org.kuali.student.contract.model.XmlType; 024import org.kuali.student.contract.model.util.ModelFinder; 025import org.kuali.student.contract.writer.JavaClassWriter; 026import org.kuali.student.contract.writer.service.GetterSetterNameCalculator; 027import org.kuali.student.contract.writer.service.MessageStructureTypeCalculator; 028import org.kuali.student.contract.writer.service.ServiceExceptionWriter; 029import org.slf4j.Logger; 030import org.slf4j.LoggerFactory; 031 032import java.util.*; 033import org.kuali.rice.core.api.criteria.CriteriaLookupService; 034import org.kuali.rice.core.api.criteria.GenericQueryResults; 035import org.springframework.transaction.annotation.Transactional; 036 037/** 038 * 039 * @author nwright 040 */ 041public class JpaImplServiceWriter extends JavaClassWriter { 042 043 private static final 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 indentPrint("public class " + calcClassName(servKey)); 368 println(" implements " + calcServiceInterfaceClassName(servKey)); 369 Service serv = finder.findService(servKey); 370 importsAdd(serv.getImplProject() + "." + serv.getName()); 371 openBrace(); 372 // put all the cache variables at the top 373 indentPrintln("// dao variables "); 374 jpaEntitiesWritten.clear(); 375 for (ServiceMethod method : methods) { 376 MethodType methodType = calcMethodType(method); 377 switch (methodType) { 378 case CREATE: 379 case GET_TYPE: 380 case GET_BY_ID: 381 writeDaoVariable(method); 382 } 383 } 384 385 for (ServiceMethod method : methods) { 386 MethodType methodType = calcMethodType(method); 387 println(""); 388// indentPrintln("/**"); 389// indentPrintWrappedComment(method.getDescription()); 390// indentPrintln("* "); 391// for (ServiceMethodParameter param : method.getParameters()) { 392// indentPrintWrappedComment("@param " + param.getName() + " - " 393// + param.getType() + " - " 394// + param.getDescription()); 395// } 396// indentPrintWrappedComment("@return " + method.getReturnValue(). 397// getDescription()); 398// indentPrintln("*/"); 399 indentPrintln("@Override"); 400 switch (methodType) { 401 case CREATE: 402 indentPrintln("@Transactional(readOnly = false, rollbackFor = {Throwable.class})"); 403 importsAdd(Transactional.class.getName()); 404 break; 405 case ADD: 406 indentPrintln("@Transactional(readOnly = false, rollbackFor = {Throwable.class})"); 407 importsAdd(Transactional.class.getName()); 408 break; 409 case UPDATE: 410 indentPrintln("@Transactional(readOnly = false, rollbackFor = {Throwable.class})"); 411 importsAdd(Transactional.class.getName()); 412 break; 413 case DELETE: 414 indentPrintln("@Transactional(readOnly = false, rollbackFor = {Throwable.class})"); 415 importsAdd(Transactional.class.getName()); 416 break; 417 case REMOVE: 418 indentPrintln("@Transactional(readOnly = false, rollbackFor = {Throwable.class})"); 419 importsAdd(Transactional.class.getName()); 420 break; 421 case GET_BY_ID: 422 indentPrintln("@Transactional(readOnly = true, noRollbackFor = {DoesNotExistException.class}, rollbackFor = {Throwable.class}))"); 423 importsAdd(Transactional.class.getName()); 424 break; 425 case GET_BY_IDS: 426 indentPrintln("@Transactional(readOnly = true, noRollbackFor = {DoesNotExistException.class}, rollbackFor = {Throwable.class}))"); 427 importsAdd(Transactional.class.getName()); 428 break; 429 case GET_IDS_BY_TYPE: 430 indentPrintln("@Transactional(readOnly = true, noRollbackFor = {DoesNotExistException.class}, rollbackFor = {Throwable.class}))"); 431 importsAdd(Transactional.class.getName()); 432 break; 433 case GET_IDS_BY_OTHER: 434 indentPrintln("@Transactional(readOnly = true, noRollbackFor = {DoesNotExistException.class}, rollbackFor = {Throwable.class}))"); 435 importsAdd(Transactional.class.getName()); 436 break; 437 case GET_INFOS_BY_OTHER: 438 indentPrintln("@Transactional(readOnly = true, noRollbackFor = {DoesNotExistException.class}, rollbackFor = {Throwable.class}))"); 439 importsAdd(Transactional.class.getName()); 440 break; 441 case GET_TYPE: 442 indentPrintln("@Transactional(readOnly = true, noRollbackFor = {DoesNotExistException.class}, rollbackFor = {Throwable.class}))"); 443 importsAdd(Transactional.class.getName()); 444 break; 445 case GET_TYPES: 446 indentPrintln("@Transactional(readOnly = true, noRollbackFor = {DoesNotExistException.class}, rollbackFor = {Throwable.class}))"); 447 importsAdd(Transactional.class.getName()); 448 break; 449 case RICE_GET_BY_NAMESPACE_AND_NAME: 450 indentPrintln("@Transactional(readOnly = true, noRollbackFor = {DoesNotExistException.class}, rollbackFor = {Throwable.class}))"); 451 importsAdd(Transactional.class.getName()); 452 break; 453 default: 454 indentPrintln("//TODO: JPAIMPL check and set the right transactional values for this method"); 455 indentPrintln("//@Transactional(readOnly = true, noRollbackFor = {DoesNotExistException.class}, rollbackFor = {Throwable.class}))"); 456 importsAdd(Transactional.class.getName()); 457 } 458 String type = method.getReturnValue().getType(); 459 String realType = stripList(type); 460 indentPrint("public " + calcType(type, realType) + " " + method.getName() 461 + "("); 462 // now do parameters 463 String comma = ""; 464 for (ServiceMethodParameter param : method.getParameters()) { 465 type = param.getType(); 466 realType = stripList(type); 467 print(comma); 468 print(calcType(type, realType)); 469 print(" "); 470 print(param.getName()); 471 comma = ", "; 472 } 473 println(")"); 474 // now do exceptions 475 comma = "throws "; 476 incrementIndent(); 477 for (ServiceMethodError error : method.getErrors()) { 478 indentPrint(comma); 479 String exceptionClassName = calcExceptionClassName(error); 480 String exceptionPackageName = this.calcExceptionPackageName(error); 481 println(exceptionClassName); 482 this.importsAdd(exceptionPackageName + "." + exceptionClassName); 483 comma = " ,"; 484 } 485 decrementIndent(); 486 openBrace(); 487 indentPrintln("// " + methodType); 488 switch (methodType) { 489 case VALIDATE: 490 writeValidate(method); 491 break; 492 case CREATE: 493 writeCreate(method); 494 break; 495 case ADD: 496 writeAdd(method); 497 break; 498 case UPDATE: 499 writeUpdate(method); 500 break; 501 case DELETE: 502 writeDelete(method); 503 break; 504 case REMOVE: 505 writeRemove(method); 506 break; 507 case GET_BY_ID: 508 writeGetById(method); 509 break; 510 case GET_BY_IDS: 511 writeGetByIds(method); 512 break; 513 case GET_IDS_BY_TYPE: 514 writeGetIdsByType(method); 515 break; 516 case GET_IDS_BY_OTHER: 517 writeGetIdsByOther(method); 518 break; 519 case GET_INFOS_BY_OTHER: 520 writeGetInfosByOther(method); 521 break; 522 case SEARCH_FOR_IDS: 523 writeSearchForIds(method); 524 break; 525 case SEARCH_FOR_INFOS: 526 writeSearchForInfos(method); 527 break; 528 case GET_TYPE: 529 writeGetType(method); 530 break; 531 case GET_TYPES: 532 writeGetTypes(method); 533 break; 534 case RICE_GET_BY_NAMESPACE_AND_NAME: 535 writeRiceGetByNamespaceAndName(method); 536 break; 537 default: 538 writeThrowsNotImplemented(method); 539 } 540 closeBrace(); 541 } 542 543 closeBrace(); 544 545 this.writeJavaClassAndImportsOutToFile(); 546 this.getOut().close(); 547 } 548 549 private String getInvalidParameterException() { 550 if (this.isRice()) { 551 return "RiceIllegalArgumentException"; 552 } 553 return "InvalidParameterException"; 554 } 555 556 private String getOperationFailedException() { 557 if (this.isRice()) { 558 return "RiceIllegalArgumentException"; 559 } 560 return "OperationFailedException"; 561 } 562 563 private String getDoesNotExistException() { 564 if (this.isRice()) { 565 return "RiceIllegalArgumentException"; 566 } 567 return "DoesNotExistException"; 568 } 569 570 private String getVersionMismatchException() { 571 if (this.isRice()) { 572 return "RiceIllegalStateException"; 573 } 574 return "VersionMismatchException"; 575 } 576 577 private void writeThrowsNotImplemented(ServiceMethod method) { 578 indentPrintln("throw new " + this.getOperationFailedException() + " (\"" + method.getName() + " has not been implemented\");"); 579 } 580 581 protected String initLower(String str) { 582 return str.substring(0, 1).toLowerCase() + str.substring(1); 583 } 584 585 private String calcCriteriaLookupServiceVariableName(ServiceMethod method) { 586 String objectName = calcObjectName(method); 587 String variableName = initLower(objectName) + "CriteriaLookupService"; 588 return variableName; 589 } 590 591 private void writeValidate(ServiceMethod method) { 592 indentPrintln("return new ArrayList<ValidationResultInfo> ();"); 593 this.importsAdd(ArrayList.class.getName()); 594 } 595 private final Set<String> jpaEntitiesWritten = new HashSet<String>(); 596 597 private void writeDaoVariable(ServiceMethod method) { 598 String objectName = calcObjectName(method); 599 String className = objectName + "Dao"; 600 String variableName = calcDaoVariableName(method); 601 if (jpaEntitiesWritten.add(variableName)) { 602 XmlType xmlType = finder.findXmlType(objectName + "Info"); 603 if (xmlType == null) { 604 System.out.println("Cannot write DAO because the object does not follow patterns. ObjectName=" 605 + objectName + " method=" + method); 606 return; 607 } 608 new JpaEntityWriter(model, directory, rootPackage, servKey, methods, xmlType, isR1).write(); 609 new JpaDaoWriter(model, directory, rootPackage, servKey, methods, xmlType, isR1).write(); 610 println(""); 611 indentPrintln("private " + className + " " + variableName + ";"); 612 println(""); 613 indentPrintln("public void set" + className + "(" + className + " " + variableName + ") {"); 614 incrementIndent(); 615 indentPrintln("this." + variableName + " = " + variableName + ";"); 616 decrementIndent(); 617 indentPrintln("}"); 618 println(""); 619 indentPrintln("public " + className + " get" + className + "() {"); 620 incrementIndent(); 621 indentPrintln("return this." + variableName + ";"); 622 decrementIndent(); 623 indentPrintln("}"); 624 625 variableName = calcCriteriaLookupServiceVariableName(method); 626 627 importsAdd(CriteriaLookupService.class.getName()); 628 className = "CriteriaLookupService"; 629 println(""); 630 indentPrintln("// Criteria Lookup for this object"); 631 indentPrintln("private " + className + " " + variableName + ";"); 632 println(""); 633 indentPrintln("public void set" + initUpper(variableName) + "(" + className + " " + variableName + ") {"); 634 incrementIndent(); 635 indentPrintln("this." + variableName + " = " + variableName + ";"); 636 decrementIndent(); 637 indentPrintln("}"); 638 println(""); 639 indentPrintln("public " + className + " get" + initUpper(variableName) + "() {"); 640 incrementIndent(); 641 indentPrintln("return this." + variableName + ";"); 642 decrementIndent(); 643 indentPrintln("}"); 644 645 } 646 } 647 648 private void writeCreate(ServiceMethod method) { 649 650// holdInfo.setPersonId(personId); 651// holdInfo.setHoldIssueId(issueId); 652// holdInfo.setTypeKey(holdTypeKey); 653// 654// HoldIssueEntity holdIssueEntity = holdIssueDao.find(issueId); 655// if (holdIssueEntity == null) { 656// throw new InvalidParameterException(issueId); 657// } 658// AppliedHoldEntity entity = new AppliedHoldEntity(holdInfo); 659// entity.setHoldIssue(holdIssueEntity); 660// entity.setEntityCreated(context); 661// appliedHoldDao.persist(entity); 662// appliedHoldDao.getEm().flush(); 663// return entity.toDto(); 664 String daoVariable = calcDaoVariableName(method); 665 String entityClassName = calcEntityClassName(method); 666 ServiceMethodParameter typeParam = this.findTypeParameter(method); 667 ServiceMethodParameter infoParam = this.findInfoParameter(method); 668 ServiceMethodParameter contextParam = this.findContextParameter(method); 669 String objectName = calcObjectName(method); 670 String infoName = objectName; 671 if (!this.isRice()) { 672 infoName = infoName + "Info"; 673 } 674 String daoName = calcDaoVariableName(method); 675 if (typeParam != null) { 676 indentPrintln(infoParam.getName() + ".setTypeKey (" + typeParam.getName() + ");"); 677 } 678 if (method.getParameters().size() > 3) { 679 indentPrintln("//TODO: JPAIMPL overwrite the rest of the readonly fields that are specified on the create in the info object"); 680 } 681 indentPrintln(entityClassName + " entity = new " + entityClassName + "(" + infoParam.getName() + ");"); 682 indentPrintln("entity.setEntityCreated(" + contextParam.getName() + ");"); 683 indentPrintln(daoVariable + ".persist(entity);"); 684 indentPrintln(daoVariable + ".getEm().flush();"); 685 indentPrintln("return entity.toDto();"); 686 } 687 688 private void writeAdd(ServiceMethod method) { 689 indentPrintln("//TODO: JPAIMPL this needs to be implemented"); 690 indentPrintln("throw new OperationFailedException (\"Not implemented\");"); 691 } 692 693 private ServiceMethodParameter findIdParameter(ServiceMethod method) { 694 String idFieldName = calcObjectName(method) + "Id"; 695 for (ServiceMethodParameter parameter : method.getParameters()) { 696 if (parameter.getType().equals("String")) { 697 if (parameter.getName().equals(idFieldName)) { 698 return parameter; 699 } 700 } 701 } 702 703 // if only one parameter and it is a string then grab that 704 if (method.getParameters().size() == 1) { 705 for (ServiceMethodParameter parameter : method.getParameters()) { 706 if (parameter.getType().equals("String")) { 707 return parameter; 708 } 709 } 710 } 711 // can't find name exactly 712 for (ServiceMethodParameter parameter : method.getParameters()) { 713 if (parameter.getType().equals("String")) { 714 if (parameter.getName().endsWith("Id")) { 715 return parameter; 716 } 717 } 718 } 719 // can't find name exactly try key 720 for (ServiceMethodParameter parameter : method.getParameters()) { 721 if (parameter.getType().equals("String")) { 722 if (!parameter.getName().endsWith("TypeKey")) { 723 if (parameter.getName().endsWith("Key")) { 724 return parameter; 725 } 726 } 727 } 728 } 729 log.warn("Could not find the Id paramter for {}.{} so returning the first one", method.getService(), method.getName()); 730 return method.getParameters().get(0); 731 } 732 733 private ServiceMethodParameter findContextParameter(ServiceMethod method) { 734 for (ServiceMethodParameter parameter : method.getParameters()) { 735 if (parameter.getType().equals("ContextInfo")) { 736 return parameter; 737 } 738 } 739 return null; 740 } 741 742 private ServiceMethodParameter findInfoParameter(ServiceMethod method) { 743 String objectName = calcObjectName(method); 744 if (!this.isRice()) { 745 objectName = objectName + "Info"; 746 } 747 for (ServiceMethodParameter parameter : method.getParameters()) { 748 if (parameter.getType().equals(objectName)) { 749 return parameter; 750 } 751 } 752 if (method.getParameters().size() >= 1) { 753 return method.getParameters().get(0); 754 } 755 return null; 756 } 757 758 private ServiceMethodParameter findTypeParameter(ServiceMethod method) { 759 for (ServiceMethodParameter parameter : method.getParameters()) { 760 if (parameter.getType().equals("String")) { 761 if (parameter.getName().endsWith("TypeKey")) { 762 return parameter; 763 } 764 if (parameter.getName().endsWith("Type")) { 765 return parameter; 766 } 767 } 768 } 769 return null; 770 } 771 772 private String calcDaoVariableName(ServiceMethod method) { 773 String daoVariableName = this.calcObjectName(method); 774 daoVariableName = this.initLower(daoVariableName) + "Dao"; 775 return daoVariableName; 776 } 777 778 private String calcEntityClassName(ServiceMethod method) { 779 String objectName = this.calcObjectName(method); 780 objectName = objectName + "Entity"; 781 return objectName; 782 } 783 784 protected String calcObjectName(ServiceMethod method) { 785 if (method.getName().startsWith("create")) { 786 return method.getName().substring("create".length()); 787 } 788 if (method.getName().startsWith("update")) { 789 return method.getName().substring("update".length()); 790 } 791 if (method.getName().startsWith("validate")) { 792 return method.getName().substring("validate".length()); 793 } 794 if (method.getName().startsWith("delete")) { 795 return method.getName().substring("delete".length()); 796 } 797 if (method.getName().startsWith("get")) { 798 if (method.getReturnValue().getType().equals("StringList")) { 799 if (method.getName().contains("IdsBy")) { 800 return method.getName().substring("get".length(), 801 method.getName().indexOf("IdsBy")); 802 } 803 if (method.getName().contains("KeysBy")) { 804 return method.getName().substring("get".length(), 805 method.getName().indexOf("KeysBy")); 806 } 807 if (method.getName().contains("IdsFor")) { 808 return method.getName().substring("get".length(), 809 method.getName().indexOf("IdsFor")); 810 } 811 if (method.getName().contains("With")) { 812 return method.getName().substring("get".length(), 813 method.getName().indexOf("With")); 814 } 815 if (method.getName().contains("By")) { 816 return method.getName().substring("get".length(), 817 method.getName().indexOf("By")); 818 } 819 return method.getName().substring("get".length()); 820 } 821 String name = method.getReturnValue().getType(); 822 if (name.endsWith("List")) { 823 name = name.substring(0, name.length() - "List".length()); 824 } 825 if (name.endsWith("Info")) { 826 name = name.substring(0, name.length() - "Info".length()); 827 } 828 return name; 829 } 830 831 if (method.getName().startsWith("searchFor")) { 832 if (method.getReturnValue().getType().equals("StringList")) { 833 if (method.getName().endsWith("Ids")) { 834 return method.getName().substring("searchFor".length(), 835 method.getName().indexOf("Ids")); 836 } 837 if (method.getName().endsWith("Keys")) { 838 return method.getName().substring("get".length(), 839 method.getName().indexOf("Keys")); 840 } 841 return method.getName().substring("searchFor".length()); 842 } 843 String name = method.getReturnValue().getType(); 844 if (name.endsWith("List")) { 845 name = name.substring(0, name.length() - "List".length()); 846 } 847 if (name.endsWith("Info")) { 848 name = name.substring(0, name.length() - "Info".length()); 849 } 850 return name; 851 } 852 if (method.getName().startsWith("add")) { 853 return method.getName().substring("add".length()); 854 } 855 if (method.getName().startsWith("remove")) { 856 return method.getName().substring("remove".length()); 857 } 858 String returnType = this.stripList(method.getReturnValue().getType()); 859 XmlType type = this.finder.findXmlType(returnType); 860 if (type.getPrimitive().equals(XmlType.COMPLEX)) { 861 return returnType; 862 } 863 throw new IllegalArgumentException(method.getName()); 864 } 865 866 private void writeUpdate(ServiceMethod method) { 867// if (!holdId.equals(holdInfo.getId())) { 868// throw new InvalidParameterException(holdId + " does not match the id in the object " + holdInfo.getId()); 869// } 870// AppliedHoldEntity entity = appliedHoldDao.find(holdId); 871// if (null == entity) { 872// throw new DoesNotExistException(holdId); 873// } 874// entity.fromDto(holdInfo); 875// entity.setEntityUpdated(context); 876// entity = appliedHoldDao.merge(entity); 877// appliedHoldDao.getEm().flush(); // need to flush to get the version indicator updated 878// return entity.toDto(); 879 ServiceMethodParameter idParam = this.findIdParameter(method); 880 ServiceMethodParameter infoParam = this.findInfoParameter(method); 881 ServiceMethodParameter contextParam = this.findContextParameter(method); 882 String daoVariable = calcDaoVariableName(method); 883 String entityClassName = calcEntityClassName(method); 884 if (infoParam == null) { 885 throw new NullPointerException(method.getName()); 886 } 887 String objectName = calcObjectName(method); 888 String infoName = objectName; 889 if (!this.isRice()) { 890 infoName = infoName + "Info"; 891 } 892 if (idParam != null) { 893 if (!this.isRice()) { 894 indentPrintln("if (!" + idParam.getName() + ".equals (" + infoParam.getName() + ".getId())) {"); 895 indentPrintln(" throw new " + this.getInvalidParameterException() + " (\"The id parameter does not match the id on the info object\");"); 896 indentPrintln("}"); 897 } 898 } 899 indentPrintln(entityClassName + " entity = " + daoVariable + ".find(" + idParam.getName() + ");"); 900 indentPrintln("if (entity == null) {"); 901 incrementIndent(); 902 indentPrintln("throw new DoesNotExistException(" + idParam.getName() + ");"); 903 decrementIndent(); 904 indentPrintln("}"); 905 indentPrintln("entity.fromDto(" + infoParam.getName() + ");"); 906 indentPrintln("entity.setEntityUpdated(" + contextParam.getName() + ");"); 907 indentPrintln("entity = " + daoVariable + ".merge(entity);"); 908 indentPrintln("return entity.toDto();"); 909 } 910 911 private void writeDelete(ServiceMethod method) { 912// AppliedHoldEntity entity = appliedHoldDao.find(holdId); 913// if (null == entity) { 914// throw new DoesNotExistException(holdId); 915// } 916// appliedHoldDao.remove(entity); 917// StatusInfo status = new StatusInfo(); 918// status.setSuccess(Boolean.TRUE); 919// return status; 920 ServiceMethodParameter idParam = this.findIdParameter(method); 921 String daoVariable = calcDaoVariableName(method); 922 String entityClassName = calcEntityClassName(method); 923 indentPrintln(entityClassName + " entity = " + daoVariable + ".find(" + idParam.getName() + ");"); 924 indentPrintln("if (entity == null) {"); 925 incrementIndent(); 926 indentPrintln("throw new DoesNotExistException(" + idParam.getName() + ");"); 927 decrementIndent(); 928 indentPrintln("}"); 929 indentPrintln(daoVariable + ".remove(entity);"); 930 indentPrintln("StatusInfo status = new StatusInfo();"); 931 importsAdd("org.kuali.student.r2.common.dto.StatusInfo"); 932 indentPrintln("status.setSuccess(Boolean.TRUE);"); 933 indentPrintln("return status;"); 934 } 935 936 private void writeRemove(ServiceMethod method) { 937 indentPrintln("//TODO: JPAIMPL this needs to be implemented"); 938 indentPrintln("throw new OperationFailedException (\"Not implemented\");"); 939 } 940 941 private void writeGetById(ServiceMethod method) { 942// AppliedHoldEntity entity = appliedHoldDao.find(holdId); 943// if (entity == null) { 944// throw new DoesNotExistException(holdId); 945// } 946// return entity.toDto(); 947 ServiceMethodParameter idParam = this.findIdParameter(method); 948 String daoVariable = calcDaoVariableName(method); 949 String entityClassName = calcEntityClassName(method); 950 indentPrintln(entityClassName + " entity = " + daoVariable + ".find(" + idParam.getName() + ");"); 951 indentPrintln("if (entity == null) {"); 952 incrementIndent(); 953 indentPrintln("throw new DoesNotExistException(" + idParam.getName() + ");"); 954 decrementIndent(); 955 indentPrintln("}"); 956 indentPrintln("return entity.toDto();"); 957 } 958 959 private void writeGetByIds(ServiceMethod method) { 960// List<HoldIssueEntity> holdIssues = holdIssueDao.findByIds(issueIds); 961// List<HoldIssueInfo> result = new ArrayList<HoldIssueInfo>(holdIssues.size()); 962// for (HoldIssueEntity entity : holdIssues) { 963// if (entity == null) { 964// // if one of the entities from "findByIds" is returned as null, then one of the keys in the list was not found 965// throw new DoesNotExistException(); 966// } 967// result.add(entity.toDto()); 968// } 969// return result; 970 String daoVariable = calcDaoVariableName(method); 971 String entityClassName = calcEntityClassName(method); 972 String objectName = this.calcObjectName(method); 973 ServiceMethodParameter idListParam = this.findIdListParameter(method); 974 String infoName = objectName; 975 infoName = infoName + "Info"; 976 this.importsAdd(ArrayList.class.getName()); 977 indentPrintln("List<" + entityClassName + "> entities = " + daoVariable + ".findByIds(" + idListParam.getName() + ");"); 978 indentPrintln("List<" + infoName + "> list = new ArrayList<" + infoName + "> (entities.size());"); 979 indentPrintln("for (" + entityClassName + " entity : entities) {"); 980 incrementIndent(); 981 indentPrintln("if (entity == null) {"); 982 incrementIndent(); 983 indentPrintln("throw new DoesNotExistException();"); 984 decrementIndent(); 985 indentPrintln("}"); 986 indentPrintln("list.add(entity.toDto());"); 987 decrementIndent(); 988 indentPrintln("}"); 989 indentPrintln("return list;"); 990 } 991 992 private String calcNamedQuery(ServiceMethod method) { 993 String objectName = calcObjectName(method); 994 String name = method.getName(); 995 if (name.startsWith("get")) { 996 name = name.substring("get".length()); 997 } 998 if (name.startsWith(objectName)) { 999 name = name.substring(objectName.length()); 1000 } 1001// if (name.startsWith("Ids")) { 1002// name = name.substring("Ids".length()); 1003// } 1004// if (name.isEmpty()) { 1005// throw new RuntimeException (method.getName()); 1006// } 1007 // remove plural 1008 if (!method.getReturnValue().getType().equals("StringList")) { 1009 if (name.startsWith("s")) { 1010 name = name.substring("s".length()); 1011 } 1012 } 1013 // add back the get 1014 name = "get" + name; 1015 return name; 1016 } 1017 1018 private void writeGetIdsByOther(ServiceMethod method) { 1019// return appliedHoldDao.getIdsByIssue(issueId); 1020 String objectName = this.calcObjectName(method); 1021 String infoName = objectName; 1022 if (!this.isRice()) { 1023 infoName = infoName + "Info"; 1024 } 1025 String daoVariableName = calcDaoVariableName(method); 1026 String namedQuery = calcNamedQuery(method); 1027 indentPrint("return " + daoVariableName + "." + namedQuery + "("); 1028 String comma = ""; 1029 for (ServiceMethodParameter param : method.getParameters()) { 1030 if (param.getType().equals("ContextInfo")) { 1031 continue; 1032 } 1033 print(comma); 1034 comma = ", "; 1035 print(param.getName()); 1036 } 1037 println(");"); 1038 } 1039 1040 private ServiceMethodParameter findCriteriaParam(ServiceMethod method) { 1041 for (ServiceMethodParameter param : method.getParameters()) { 1042 if (param.getType().equals("QueryByCriteria")) { 1043 return param; 1044 } 1045 } 1046 return null; 1047 } 1048 1049 private void writeSearchForIds(ServiceMethod method) { 1050// List<String> results = new ArrayList<String>(); 1051// GenericQueryResults<AppliedHoldEntity> appliedHolds = criteriaLookupService.lookup(AppliedHoldEntity.class, criteria); 1052// if (null != appliedHolds && appliedHolds.getResults().size() > 0) { 1053// for (AppliedHoldEntity appliedHold : appliedHolds.getResults()) { 1054// results.add(appliedHold.getId()); 1055// } 1056// } 1057// return results; 1058 String objectName = this.calcObjectName(method); 1059 String infoName = objectName; 1060 if (!this.isRice()) { 1061 infoName = infoName + "Info"; 1062 } 1063 String criteriaLookupVariableName = calcCriteriaLookupServiceVariableName(method); 1064 String entityClassName = this.calcEntityClassName(method); 1065 ServiceMethodParameter criteriaParam = findCriteriaParam(method); 1066 importsAdd(CriteriaLookupService.class.getName()); 1067 importsAdd(ArrayList.class.getName()); 1068 importsAdd(List.class.getName()); 1069 indentPrintln("List<String> results = new ArrayList<String>();"); 1070 importsAdd(GenericQueryResults.class.getName()); 1071 indentPrintln("GenericQueryResults<" + entityClassName + "> entities"); 1072 indentPrintln(" = " + criteriaLookupVariableName + ".lookup(" + entityClassName + ".class, " + criteriaParam.getName() + ");"); 1073 indentPrintln("if (null != entities && !entities.getResults().isEmpty()) {"); 1074 incrementIndent(); 1075 indentPrintln("for (" + entityClassName + " entity : entities.getResults()) {"); 1076 incrementIndent(); 1077 indentPrintln("results.add(entity.getId());"); 1078 decrementIndent(); 1079 indentPrintln("}"); 1080 decrementIndent(); 1081 indentPrintln("}"); 1082 indentPrintln("return results;"); 1083 } 1084 1085 private void writeSearchForInfos(ServiceMethod method) { 1086// List<AppliedHoldInfo> results = new ArrayList<AppliedHoldInfo>(); 1087// GenericQueryResults<AppliedHoldEntity> appliedHolds = criteriaLookupService.lookup(AppliedHoldEntity.class, criteria); 1088// if (null != appliedHolds && appliedHolds.getResults().size() > 0) { 1089// for (AppliedHoldEntity appliedHold : appliedHolds.getResults()) { 1090// results.add(appliedHold.toDto()); 1091// } 1092// } 1093// return results; 1094 String objectName = this.calcObjectName(method); 1095 String criteriaLookupVariableName = calcCriteriaLookupServiceVariableName(method); 1096 String entityClassName = this.calcEntityClassName(method); 1097 String infoName = this.calcInfoName(method); 1098 ServiceMethodParameter criteriaParam = findCriteriaParam(method); 1099 importsAdd(CriteriaLookupService.class.getName()); 1100 importsAdd(ArrayList.class.getName()); 1101 importsAdd(List.class.getName()); 1102 indentPrintln("List<" + infoName + "> results = new ArrayList<" + infoName + ">();"); 1103 importsAdd(GenericQueryResults.class.getName()); 1104 indentPrintln("GenericQueryResults<" + entityClassName + "> entities"); 1105 indentPrintln(" = " + criteriaLookupVariableName + ".lookup(" + entityClassName + ".class, " + criteriaParam.getName() + ");"); 1106 indentPrintln("if (null != entities && !entities.getResults().isEmpty()) {"); 1107 incrementIndent(); 1108 indentPrintln("for (" + entityClassName + " entity : entities.getResults()) {"); 1109 incrementIndent(); 1110 indentPrintln("results.add(entity.toDto());"); 1111 decrementIndent(); 1112 indentPrintln("}"); 1113 decrementIndent(); 1114 indentPrintln("}"); 1115 indentPrintln("return results;"); 1116 } 1117 1118 private ServiceMethodParameter getTypeParameter(ServiceMethod method) { 1119 ServiceMethodParameter fallbackParam = null; 1120 for (ServiceMethodParameter parameter : method.getParameters()) { 1121 if (parameter.getName().endsWith("TypeKey")) { 1122 return parameter; 1123 } 1124 if (parameter.getType().equals("String")) { 1125 if (parameter.getName().toLowerCase().contains("type")) { 1126 fallbackParam = parameter; 1127 } 1128 } 1129 } 1130 return fallbackParam; 1131 } 1132 1133 private String calcInfoName(ServiceMethod method) { 1134 String objectName = this.calcObjectName(method); 1135 String infoName = objectName; 1136 if (!this.isRice()) { 1137 infoName = infoName + "Info"; 1138 } 1139 return infoName; 1140 } 1141 1142 private void writeGetIdsByType(ServiceMethod method) { 1143 String objectName = this.calcObjectName(method); 1144 String infoName = this.calcInfoName(method); 1145 String daoVariable = calcDaoVariableName(method); 1146 ServiceMethodParameter typeParam = this.getTypeParameter(method); 1147 if (typeParam == null) { 1148 1149 } 1150 indentPrintln("return " + daoVariable + ".getIdsByType(" + typeParam.getName() + ");"); 1151 } 1152 1153 private void writeRiceGetByNamespaceAndName(ServiceMethod method) { 1154 indentPrintln("//TODO: JPAIMPL this needs to be implemented"); 1155 indentPrintln("throw new OperationFailedException (\"Not implemented\");"); 1156 } 1157 1158 private void writeGetInfosByOther(ServiceMethod method) { 1159// List<AppliedHoldEntity> entities = this.appliedHoldDao.getByPerson(personId); 1160// List<AppliedHoldInfo> result = new ArrayList<AppliedHoldInfo>(entities.size()); 1161// for (AppliedHoldEntity entity : entities) { 1162// result.add(entity.toDto()); 1163// } 1164// return result; 1165 String objectName = this.calcObjectName(method); 1166 String infoName = objectName; 1167 if (!this.isRice()) { 1168 infoName = infoName + "Info"; 1169 } 1170 String daoVariableName = calcDaoVariableName(method); 1171 String namedQuery = calcNamedQuery(method); 1172 String entityClassName = calcEntityClassName(method); 1173 indentPrint("List<" + entityClassName + "> entities = " + daoVariableName + "." + namedQuery + "("); 1174 String comma = ""; 1175 for (ServiceMethodParameter param : method.getParameters()) { 1176 if (param.getType().equals("ContextInfo")) { 1177 continue; 1178 } 1179 print(comma); 1180 comma = ", "; 1181 print(param.getName()); 1182 } 1183 println(");"); 1184 this.importsAdd(ArrayList.class.getName()); 1185 indentPrintln("List<" + infoName + "> list = new ArrayList<" + infoName + "> (entities.size());"); 1186 indentPrintln("for (" + entityClassName + " entity: entities) {"); 1187 indentPrintln(" list.add (entity.toDto ());"); 1188 indentPrintln("}"); 1189 indentPrintln("return list;"); 1190 } 1191 1192 private void writeGetType(ServiceMethod method) { 1193 indentPrintln("//TODO: JPAIMPL this needs to be implemented"); 1194 indentPrintln("throw new OperationFailedException (\"Not implemented\");"); 1195 } 1196 1197 private void writeGetTypes(ServiceMethod method) { 1198 indentPrintln("//TODO: JPAIMPL this needs to be implemented"); 1199 indentPrintln("throw new OperationFailedException (\"Not implemented\");"); 1200 } 1201 1202 private String initUpper(String str) { 1203 return str.substring(0, 1).toUpperCase() + str.substring(1); 1204 } 1205 1206 private ServiceMethodParameter findIdListParameter(ServiceMethod method) { 1207 String idFieldName = calcObjectName(method) + "Ids"; 1208 if (this.isRice()) { 1209 idFieldName = "ids"; 1210 } 1211 for (ServiceMethodParameter parameter : method.getParameters()) { 1212 if (parameter.getType().equals("StringList")) { 1213 if (parameter.getName().equals(idFieldName)) { 1214 return parameter; 1215 } 1216 } 1217 } 1218 // can't find name exactly 1219 for (ServiceMethodParameter parameter : method.getParameters()) { 1220 if (parameter.getType().equals("StringList")) { 1221 if (parameter.getName().endsWith("Ids")) { 1222 return parameter; 1223 } 1224 } 1225 } 1226 // can't find name exactly try key 1227 for (ServiceMethodParameter parameter : method.getParameters()) { 1228 if (parameter.getType().equals("StringList")) { 1229 if (parameter.getName().endsWith("Keys")) { 1230 return parameter; 1231 } 1232 } 1233 } 1234 return null; 1235 } 1236 1237 private String stripList(String str) { 1238 return GetterSetterNameCalculator.stripList(str); 1239 } 1240 1241 private String calcExceptionClassName(ServiceMethodError error) { 1242 if (error.getClassName() == null) { 1243 return ServiceExceptionWriter.calcClassName(error.getType()); 1244 } 1245 return error.getClassName(); 1246 } 1247 1248 private String calcExceptionPackageName(ServiceMethodError error) { 1249 if (error.getClassName() == null) { 1250 return ServiceExceptionWriter.calcPackage(rootPackage); 1251 } 1252 return error.getPackageName(); 1253 } 1254 1255 private String calcType(String type, String realType) { 1256 XmlType t = finder.findXmlType(this.stripList(type)); 1257 String retType = MessageStructureTypeCalculator.calculate(this, model, type, realType, 1258 t.getJavaPackage()); 1259 if (this.isRice()) { 1260 if (retType.equals("Boolean")) { 1261 retType = "boolean"; 1262 } 1263 if (retType.equals("Void")) { 1264 retType = "void"; 1265 } 1266 } 1267 return retType; 1268 } 1269}