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 }