001 /* 002 * Copyright 2009 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.osedu.org/licenses/ECL-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package org.kuali.student.mock.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.impl.ServiceContractModelPescXsdLoader; 025 import org.kuali.student.contract.model.util.ModelFinder; 026 import org.kuali.student.contract.writer.JavaClassWriter; 027 import org.kuali.student.contract.writer.service.GetterSetterNameCalculator; 028 import org.kuali.student.contract.writer.service.MessageStructureTypeCalculator; 029 import org.kuali.student.contract.writer.service.ServiceExceptionWriter; 030 import org.slf4j.Logger; 031 import org.slf4j.LoggerFactory; 032 033 import java.util.*; 034 035 /** 036 * 037 * @author nwright 038 */ 039 public class MockImplServiceWriter extends JavaClassWriter { 040 041 private static Logger log = LoggerFactory.getLogger(MockImplServiceWriter.class); 042 043 ////////////////////////////// 044 // Constants 045 ////////////////////////////// 046 047 /** 048 * The standard type of methods used in our Service contract. 049 */ 050 protected static enum MethodType { 051 052 VALIDATE, 053 CREATE, 054 CREATE_BULK, 055 ADD, 056 UPDATE, 057 UPDATE_OTHER, 058 DELETE, 059 REMOVE, 060 DELETE_OTHER, 061 GET_CREATE, 062 GET_BY_ID, 063 GET_BY_IDS, 064 RICE_GET_BY_NAMESPACE_AND_NAME, 065 GET_IDS_BY_TYPE, 066 GET_IDS_BY_OTHER, 067 GET_INFOS_BY_OTHER, 068 GET_TYPE, 069 GET_TYPES, 070 UNKNOWN 071 }; 072 073 ////////////////////////////// 074 // Data Variables 075 ////////////////////////////// 076 077 protected ServiceContractModel model; 078 protected ModelFinder finder; 079 private String directory; 080 /** 081 * The package name is stored in the service object itself (the package spec kept 082 * moving around so I assumed the actual service name was unique but ran into a problem 083 * when we included rice because they have a StateService meaning US states and we have 084 * a StateService meaning the state of the object so I added logic to detect rice and 085 * prepend that "RICE." to it 086 */ 087 private String rootPackage; 088 089 /** 090 * Name of the service being operated on. 091 * If it is a RICE service it is prefixed with RICE. 092 * [11:32:18 AM] Norman Wright: short name... I think it gets it by taking the java class SimpleName and stripping off the word "Service" and I think making it lower case. 093 * [11:32:24 AM] Norman Wright: so OrganizationService becomes organization 094 */ 095 protected String servKey; 096 097 protected List<ServiceMethod> methods; 098 099 /** 100 * A flag that holds if the service is an R1 service. 101 */ 102 private boolean isR1; 103 104 ////////////////////////// 105 // Constructor 106 ////////////////////////// 107 108 public MockImplServiceWriter(ServiceContractModel model, 109 String directory, 110 String rootPackage, 111 String servKey, 112 List<ServiceMethod> methods, 113 boolean isR1) { 114 super(directory, calcPackage(servKey, rootPackage), calcClassName(servKey)); 115 this.model = model; 116 this.finder = new ModelFinder(model); 117 this.directory = directory; 118 this.rootPackage = rootPackage; 119 this.servKey = servKey; 120 this.methods = methods; 121 this.isR1 = isR1; 122 } 123 124 public MockImplServiceWriter(ServiceContractModel model, 125 String directory, 126 String rootPackage, 127 String servKey, 128 List<ServiceMethod> methods, 129 boolean isR1, 130 String packageName, 131 String className) { 132 super(directory, packageName, className); 133 this.model = model; 134 this.finder = new ModelFinder(model); 135 this.directory = directory; 136 this.rootPackage = rootPackage; 137 this.servKey = servKey; 138 this.methods = methods; 139 this.isR1 = isR1; 140 } 141 142 ///////////////////////// 143 // Functional Methods 144 ///////////////////////// 145 146 /** 147 * Returns the mock implementation package name. 148 * @param servKey 149 * @param rootPackage 150 * @return 151 */ 152 public static String calcPackage(String servKey, String rootPackage) { 153 String pack = rootPackage + "."; 154 // String pack = rootPackage + "." + servKey.toLowerCase() + "."; 155 // StringBuffer buf = new StringBuffer (service.getVersion ().length ()); 156 // for (int i = 0; i < service.getVersion ().length (); i ++) 157 // { 158 // char c = service.getVersion ().charAt (i); 159 // c = Character.toLowerCase (c); 160 // if (Character.isLetter (c)) 161 // { 162 // buf.append (c); 163 // continue; 164 // } 165 // if (Character.isDigit (c)) 166 // { 167 // buf.append (c); 168 // } 169 // } 170 // pack = pack + buf.toString (); 171 pack = pack + "service.impl.mock"; 172 return pack; 173 } 174 175 /** 176 * Checks if this is a RICE service. 177 * @return true if this is a RICE service. 178 */ 179 private boolean isRice() { 180 if (this.servKey.startsWith("RICE.")) { 181 return true; 182 } 183 return false; 184 } 185 186 protected static String fixServKey(String servKey) { 187 if (servKey.startsWith("RICE.")) { 188 return servKey.substring("RICE.".length()); 189 } 190 return servKey; 191 } 192 193 /** 194 * Given the service key (name), returns a calculated class name for the mock impl. 195 */ 196 public static String calcClassName(String servKey) { 197 return GetterSetterNameCalculator.calcInitUpper(fixServKey(servKey) + "ServiceMockImpl"); 198 } 199 200 public static String calcServiceInterfaceClassName(String servKey) { 201 return GetterSetterNameCalculator.calcInitUpper(fixServKey(servKey) + "Service"); 202 } 203 204 /** 205 * Analyses the method and returns a MethodType enum that describes what type of method this is. 206 */ 207 protected MethodType calcMethodType(ServiceMethod method) { 208 if (this.isRice()) { 209 if (method.getName().contains("ByNamespaceCodeAndName")) { 210 return MethodType.RICE_GET_BY_NAMESPACE_AND_NAME; 211 } 212 if (method.getName().contains("ByNameAndNamespace")) { 213 return MethodType.RICE_GET_BY_NAMESPACE_AND_NAME; 214 } 215 if (method.getName().startsWith("get")) { 216 if (method.getParameters().size() == 1) { 217 if (!method.getReturnValue().getType().endsWith("List")) { 218 if (method.getParameters().get(0).getName().equals("id")) { 219 return MethodType.GET_BY_ID; 220 } 221 222 } else { 223 if (method.getParameters().get(0).getName().equals("ids")) { 224 return MethodType.GET_BY_IDS; 225 } 226 } 227 } 228 } 229 } 230 if (method.getName().startsWith("validate")) { 231 return MethodType.VALIDATE; 232 } 233 if (method.getName().startsWith("create")) { 234 if (this.findInfoParameter(method) != null) { 235 return MethodType.CREATE; 236 } 237 return MethodType.CREATE_BULK; 238 } 239 if (method.getName().startsWith("add")) { 240 return MethodType.ADD; 241 } 242 if (method.getName().startsWith("update")) { 243 if (this.findInfoParameter(method) != null) { 244 return MethodType.UPDATE; 245 } 246 return MethodType.UPDATE_OTHER; 247 } 248 if (method.getName().startsWith("delete")) { 249 if (method.getName().contains("By")) { 250 if (!method.getName().startsWith("deleteBy")) { 251 return MethodType.DELETE_OTHER; 252 } 253 } 254 if (method.getName().contains("For")) { 255 if (!method.getName().startsWith("deleteFor")) { 256 return MethodType.DELETE_OTHER; 257 } 258 } 259 return MethodType.DELETE; 260 } 261 if (method.getName().startsWith("remove")) { 262 return MethodType.REMOVE; 263 } 264 265 if (method.getName().startsWith("getCreate")) { 266 return MethodType.GET_CREATE; 267 } 268 269 if (method.getName().startsWith("get")) { 270 if (method.getName().endsWith("ByIds")) { 271 return MethodType.GET_BY_IDS; 272 } 273 if (method.getName().endsWith("ByType")) { 274 return MethodType.GET_IDS_BY_TYPE; 275 } 276 if (method.getReturnValue().getType().endsWith("TypeInfo")) { 277 return MethodType.GET_TYPE; 278 } 279 if (method.getReturnValue().getType().endsWith("TypeInfoList")) { 280 return MethodType.GET_TYPES; 281 } 282 if (method.getName().endsWith("ByType")) { 283 return MethodType.GET_IDS_BY_TYPE; 284 } 285 if (method.getParameters().size() >= 1 && method.getParameters().size() <= 2) { 286 if (!method.getReturnValue().getType().endsWith("List")) { 287 if (method.getParameters().get(0).getName().endsWith("Id")) { 288 return MethodType.GET_BY_ID; 289 } 290 } 291 } 292 if (method.getName().contains("By")) { 293 if (method.getReturnValue().getType().equals("StringList")) { 294 return MethodType.GET_IDS_BY_OTHER; 295 } 296 if (method.getReturnValue().getType().endsWith("InfoList")) { 297 return MethodType.GET_INFOS_BY_OTHER; 298 } 299 } 300 } 301 302 return MethodType.UNKNOWN; 303 } 304 305 /** 306 * Write out the entire file 307 */ 308 public void write() { 309 indentPrint("public class " + calcClassName(servKey)); 310 println(" implements MockService, " + calcServiceInterfaceClassName(servKey)); 311 importsAdd ("org.kuali.student.common.mock.MockService"); 312 Service serv = finder.findService(servKey); 313 importsAdd(serv.getImplProject() + "." + serv.getName()); 314 openBrace(); 315 // put all the cache variables at the top 316 indentPrintln("// cache variable "); 317 indentPrintln("// The LinkedHashMap is just so the values come back in a predictable order"); 318 cacheVariablesWritten.clear(); 319 for (ServiceMethod method : methods) { 320 MethodType methodType = calcMethodType(method); 321 switch (methodType) { 322 case CREATE: 323 case ADD: 324 case GET_TYPE: 325 case GET_BY_ID: 326 writeCacheVariable(method); 327 } 328 } 329 println (""); 330 indentPrintln ("@Override"); 331 indentPrintln ("public void clear()"); 332 openBrace (); 333 cacheVariablesWritten.clear(); 334 for (ServiceMethod method : methods) { 335 MethodType methodType = calcMethodType(method); 336 switch (methodType) { 337 case CREATE: 338 case ADD: 339 case GET_TYPE: 340 case GET_BY_ID: 341 writeCacheVariableClear(method); 342 } 343 } 344 closeBrace (); 345 println (""); 346 347 for (ServiceMethod method : methods) { 348 MethodType methodType = calcMethodType(method); 349 indentPrintln(""); 350 // indentPrintln("/**"); 351 // indentPrintWrappedComment(method.getDescription()); 352 // indentPrintln("* "); 353 // for (ServiceMethodParameter param : method.getParameters()) { 354 // indentPrintWrappedComment("@param " + param.getName() + " - " 355 // + param.getType() + " - " 356 // + param.getDescription()); 357 // } 358 // indentPrintWrappedComment("@return " + method.getReturnValue(). 359 // getDescription()); 360 // indentPrintln("*/"); 361 indentPrintln("@Override"); 362 String type = method.getReturnValue().getType(); 363 String realType = stripList(type); 364 indentPrint("public " + calcType(type, realType) + " " + method.getName() 365 + "("); 366 // now do parameters 367 String comma = ""; 368 for (ServiceMethodParameter param : method.getParameters()) { 369 type = param.getType(); 370 realType = stripList(type); 371 print(comma); 372 print(calcType(type, realType)); 373 print(" "); 374 print(param.getName()); 375 comma = ", "; 376 } 377 println(")"); 378 // now do exceptions 379 comma = "throws "; 380 incrementIndent(); 381 for (ServiceMethodError error : method.getErrors()) { 382 indentPrint(comma); 383 String exceptionClassName = calcExceptionClassName(error); 384 String exceptionPackageName = this.calcExceptionPackageName(error); 385 println(exceptionClassName); 386 this.importsAdd(exceptionPackageName + "." + exceptionClassName); 387 comma = " ,"; 388 } 389 decrementIndent(); 390 openBrace(); 391 indentPrintln("// " + methodType); 392 switch (methodType) { 393 case VALIDATE: 394 writeValidate(method); 395 break; 396 case CREATE: 397 writeCreate(method); 398 break; 399 case ADD: 400 writeAdd(method); 401 break; 402 case UPDATE: 403 writeUpdate(method); 404 break; 405 case DELETE: 406 writeDelete(method); 407 break; 408 case REMOVE: 409 writeRemove(method); 410 break; 411 case GET_BY_ID: 412 writeGetById(method); 413 break; 414 case GET_BY_IDS: 415 writeGetByIds(method); 416 break; 417 case GET_IDS_BY_TYPE: 418 writeGetIdsByType(method); 419 break; 420 case GET_IDS_BY_OTHER: 421 writeGetIdsByOther(method); 422 break; 423 case GET_INFOS_BY_OTHER: 424 writeGetInfosByOther(method); 425 break; 426 case GET_TYPE: 427 writeGetType(method); 428 break; 429 case GET_TYPES: 430 writeGetTypes(method); 431 break; 432 case RICE_GET_BY_NAMESPACE_AND_NAME: 433 writeRiceGetByNamespaceAndName(method); 434 break; 435 default: 436 writeThrowsNotImplemented(method); 437 } 438 closeBrace(); 439 } 440 441 writeBoilerPlate(); 442 closeBrace(); 443 444 this.writeJavaClassAndImportsOutToFile(); 445 this.getOut().close(); 446 } 447 448 private String getInvalidParameterException() { 449 if (this.isRice()) { 450 return "RiceIllegalArgumentException"; 451 } 452 return "InvalidParameterException"; 453 } 454 455 private String getOperationFailedException() { 456 if (this.isRice()) { 457 return "RiceIllegalArgumentException"; 458 } 459 return "OperationFailedException"; 460 } 461 462 private String getDoesNotExistException() { 463 if (this.isRice()) { 464 return "RiceIllegalArgumentException"; 465 } 466 return "DoesNotExistException"; 467 } 468 469 private String getVersionMismatchException() { 470 if (this.isRice()) { 471 return "RiceIllegalStateException"; 472 } 473 return "VersionMismatchException"; 474 } 475 476 private void writeThrowsNotImplemented(ServiceMethod method) { 477 indentPrintln("throw new " + this.getOperationFailedException() + " (\"" + method.getName() + " has not been implemented\");"); 478 } 479 480 protected String initLower(String str) { 481 return str.substring(0, 1).toLowerCase() + str.substring(1); 482 } 483 484 private void writeBoilerPlate() { 485 if (this.isRice()) { 486 return; 487 } 488 indentPrintln(""); 489 indentPrintln("private StatusInfo newStatus() {"); 490 indentPrintln(" StatusInfo status = new StatusInfo();"); 491 indentPrintln(" status.setSuccess(Boolean.TRUE);"); 492 indentPrintln(" return status;"); 493 indentPrintln("}"); 494 if (isR1) { 495 this.writeBoilerPlateR1(); 496 } else { 497 this.writeBoilerPlateR2(); 498 } 499 } 500 501 private void writeBoilerPlateR1() { 502 importsAdd("org.kuali.student.common.dto.MetaInfo"); 503 indentPrintln(""); 504 505 indentPrintln("private MetaInfo newMeta() {"); 506 indentPrintln(" MetaInfo meta = new MetaInfo();"); 507 indentPrintln(" meta.setCreateId(\"MOCKUSER\");"); 508 importsAdd(Date.class.getName()); 509 indentPrintln(" meta.setCreateTime(new Date());"); 510 indentPrintln(" meta.setUpdateId(\"MOCKUSER\");"); 511 indentPrintln(" meta.setUpdateTime(meta.getCreateTime());"); 512 indentPrintln(" meta.setVersionInd(\"0\");"); 513 indentPrintln(" return meta;"); 514 indentPrintln("}"); 515 indentPrintln(""); 516 indentPrintln("private MetaInfo updateMeta(MetaInfo meta) {"); 517 indentPrintln(" meta.setUpdateId(\"MOCKUSER\");"); 518 indentPrintln(" meta.setUpdateTime(new Date());"); 519 indentPrintln(" meta.setVersionInd((Integer.parseInt(meta.getVersionInd()) + 1) + \"\");"); 520 indentPrintln(" return meta;"); 521 indentPrintln("}"); 522 indentPrintln(""); 523 524 } 525 526 private void writeBoilerPlateR2() { 527 importsAdd("org.kuali.student.r2.common.dto.MetaInfo"); 528 indentPrintln(""); 529 530 indentPrintln("private MetaInfo newMeta(ContextInfo context) {"); 531 indentPrintln(" MetaInfo meta = new MetaInfo();"); 532 indentPrintln(" meta.setCreateId(context.getPrincipalId());"); 533 importsAdd(Date.class.getName()); 534 indentPrintln(" meta.setCreateTime(new Date());"); 535 indentPrintln(" meta.setUpdateId(context.getPrincipalId());"); 536 indentPrintln(" meta.setUpdateTime(meta.getCreateTime());"); 537 indentPrintln(" meta.setVersionInd(\"0\");"); 538 indentPrintln(" return meta;"); 539 indentPrintln("}"); 540 indentPrintln(""); 541 indentPrintln("private MetaInfo updateMeta(MetaInfo old, ContextInfo context) {"); 542 indentPrintln(" MetaInfo meta = new MetaInfo(old);"); 543 indentPrintln(" meta.setUpdateId(context.getPrincipalId());"); 544 indentPrintln(" meta.setUpdateTime(new Date());"); 545 indentPrintln(" meta.setVersionInd((Integer.parseInt(meta.getVersionInd()) + 1) + \"\");"); 546 indentPrintln(" return meta;"); 547 indentPrintln("}"); 548 indentPrintln(""); 549 550 } 551 552 private void writeValidate(ServiceMethod method) { 553 indentPrintln("return new ArrayList<ValidationResultInfo> ();"); 554 this.importsAdd(ArrayList.class.getName()); 555 } 556 private Set<String> cacheVariablesWritten = new HashSet<String>(); 557 558 private void writeCacheVariable(ServiceMethod method) { 559 String objectName = calcObjectName(method); 560 if (!this.isRice()) { 561 objectName = objectName + "Info"; 562 } 563 String mapName = calcMapName(method); 564 if (cacheVariablesWritten.add(mapName)) { 565 indentPrintln("private Map<String, " + objectName + "> " + mapName + " = new LinkedHashMap<String, " + objectName + ">();"); 566 importsAdd(Map.class.getName()); 567 importsAdd(LinkedHashMap.class.getName()); 568 } 569 } 570 571 private void writeCacheVariableClear(ServiceMethod method) { 572 String objectName = calcObjectName(method); 573 if (!this.isRice()) { 574 objectName = objectName + "Info"; 575 } 576 String mapName = calcMapName(method); 577 if (cacheVariablesWritten.add(mapName)) { 578 indentPrintln("this." + mapName + ".clear ();"); 579 } 580 } 581 582 private void writeCreate(ServiceMethod method) { 583 ServiceMethodParameter typeParam = this.findTypeParameter(method); 584 ServiceMethodParameter infoParam = this.findInfoParameter(method); 585 ServiceMethodParameter contextParam = this.findContextParameter(method); 586 String objectName = calcObjectName(method); 587 String infoName = objectName; 588 if (!this.isRice()) { 589 infoName = infoName + "Info"; 590 } 591 String mapName = calcMapName(method); 592 593 if (this.isRice()) { 594 indentPrintln(infoName + " orig = this.get" + infoName + "ByNamespaceCodeAndName(" + infoParam.getName() + ".getNamespaceCode(), " + infoParam.getName() + ".getName());"); 595 indentPrintln("if (orig != null)"); 596 openBrace(); 597 indentPrintln("throw new RiceIllegalArgumentException (" + infoParam.getName() + ".getNamespaceCode() + \".\" + " + infoParam.getName() + ".getName());"); 598 closeBrace(); 599 } 600 if (typeParam != null) { 601 indentPrintln("if (!" + typeParam.getName() + ".equals (" + infoParam.getName() + ".getTypeKey())) {"); 602 indentPrintln(" throw new " + this.getInvalidParameterException() + " (\"The type parameter does not match the type on the info object\");"); 603 indentPrintln("}"); 604 } 605 if (method.getParameters().size() > 3) { 606 indentPrintln("// TODO: check the rest of the readonly fields that are specified on the create to make sure they match the info object"); 607 } 608 if (this.isR1) { 609 indentPrintln("// don't have deep copy in R1 contracts so just use the object"); 610 indentPrintln(infoName + " copy = " + infoParam.getName() + ";"); 611 } else if (this.isRice()) { 612 indentPrintln(infoName + ".Builder copy = " + infoName + ".Builder.create (" + infoParam.getName() + ");"); 613 } else { 614 indentPrintln(infoName + " copy = new " + infoName + "(" + infoParam.getName() + ");"); 615 } 616 indentPrintln("if (copy.getId() == null) {"); 617 // indentPrintln(" copy.setId(" + mapName + ".size() + \"\");"); 618 importsAdd("org.kuali.student.common.util.UUIDHelper"); 619 indentPrintln(" copy.setId(UUIDHelper.genStringUUID());"); 620 indentPrintln("}"); 621 if (contextParam != null) { 622 indentPrintln("copy.setMeta(newMeta(" + contextParam.getName() + "));"); 623 } 624 if (isR1) { 625 indentPrintln(mapName + ".put(copy.getId(), copy);"); 626 indentPrintln("// don't have deep copy in R1 contracts so just use the object"); 627 indentPrintln("return copy;"); 628 } else if (this.isRice()) { 629 indentPrintln (infoParam.getName() + " = copy.build ();"); 630 indentPrintln(mapName + ".put(" + infoParam.getName() + ".getId(), " + infoParam.getName() + ");"); 631 indentPrintln("return " + infoParam.getName() + ";"); 632 } else { 633 indentPrintln(mapName + ".put(copy.getId(), copy);"); 634 indentPrintln("return new " + infoName + "(copy);"); 635 } 636 } 637 638 private void writeAdd(ServiceMethod method) { 639 ServiceMethodParameter typeParam = this.findTypeParameter(method); 640 ServiceMethodParameter infoParam = this.findInfoParameter(method); 641 ServiceMethodParameter contextParam = this.findContextParameter(method); 642 String objectName = calcObjectName(method); 643 String infoName = objectName; 644 if (!this.isRice()) { 645 infoName = infoName + "Info"; 646 } 647 String mapName = calcMapName(method); 648 649 if (typeParam != null) { 650 indentPrintln("if (!" + typeParam.getName() + ".equals (" + infoParam.getName() + ".getTypeKey())) {"); 651 indentPrintln(" throw new " + this.getInvalidParameterException() + " (\"The type parameter does not match the type on the info object\");"); 652 indentPrintln("}"); 653 } 654 if (method.getParameters().size() > 3) { 655 indentPrintln("// TODO: check the rest of the readonly fields that are specified on the create to make sure they match the info object"); 656 } 657 if (isR1) { 658 indentPrintln("// don't have deep copy in R1 contracts so just use the object"); 659 indentPrintln(infoName + " copy = " + infoParam.getName() + ";"); 660 } else if (this.isRice()) { 661 indentPrintln(infoName + ".Builder copy = " + infoName + ".Builder.create (" + infoParam.getName() + ");"); 662 } else { 663 indentPrintln(infoName + " copy = new " + infoName + "(" + infoParam.getName() + ");"); 664 } 665 indentPrintln("if (copy.getId() == null) {"); 666 // indentPrintln(" copy.setId(" + mapName + ".size() + \"\");"); 667 importsAdd("org.kuali.student.common.util.UUIDHelper"); 668 indentPrintln(" copy.setId(UUIDHelper.genStringUUID());"); 669 indentPrintln("}"); 670 if (contextParam != null) { 671 indentPrintln("copy.setMeta(newMeta(" + contextParam.getName() + "));"); 672 } 673 if (isR1) { 674 indentPrintln(mapName + ".put(copy.getId(), copy);"); 675 indentPrintln("// don't have deep copy in R1 contracts so just use the object"); 676 indentPrintln("return copy;"); 677 } else if (this.isRice()) { 678 indentPrintln (infoParam.getName() + " = copy.build ();"); 679 indentPrintln(mapName + ".put(" + infoParam.getName() + ".getId(), " + infoParam.getName() + ");"); 680 indentPrintln("return " + infoParam.getName() + ";"); 681 } else { 682 indentPrintln(mapName + ".put(copy.getId(), copy);"); 683 indentPrintln("return new " + infoName + "(copy);"); 684 } 685 } 686 687 private ServiceMethodParameter findIdParameter(ServiceMethod method) { 688 String idFieldName = calcObjectName(method) + "Id"; 689 for (ServiceMethodParameter parameter : method.getParameters()) { 690 if (parameter.getType().equals("String")) { 691 if (parameter.getName().equals(idFieldName)) { 692 return parameter; 693 } 694 } 695 } 696 697 // if only one parameter and it is a string then grab that 698 if (method.getParameters().size() == 1) { 699 for (ServiceMethodParameter parameter : method.getParameters()) { 700 if (parameter.getType().equals("String")) { 701 return parameter; 702 } 703 } 704 } 705 // can't find name exactly 706 for (ServiceMethodParameter parameter : method.getParameters()) { 707 if (parameter.getType().equals("String")) { 708 if (parameter.getName().endsWith("Id")) { 709 return parameter; 710 } 711 } 712 } 713 // can't find name exactly try key 714 for (ServiceMethodParameter parameter : method.getParameters()) { 715 if (parameter.getType().equals("String")) { 716 if (!parameter.getName().endsWith("TypeKey")) { 717 if (parameter.getName().endsWith("Key")) { 718 return parameter; 719 } 720 } 721 } 722 } 723 log.warn("Could not find the Id paramter for " + method.getService() + "." + method.getName() + " so returning the first one"); 724 return method.getParameters().get(0); 725 } 726 727 private ServiceMethodParameter findContextParameter(ServiceMethod method) { 728 for (ServiceMethodParameter parameter : method.getParameters()) { 729 if (parameter.getType().equals("ContextInfo")) { 730 return parameter; 731 } 732 } 733 return null; 734 } 735 736 private ServiceMethodParameter findInfoParameter(ServiceMethod method) { 737 String objectName = calcObjectName(method); 738 if (!this.isRice()) { 739 objectName = objectName + "Info"; 740 } 741 for (ServiceMethodParameter parameter : method.getParameters()) { 742 if (parameter.getType().equals(objectName)) { 743 return parameter; 744 } 745 } 746 if (method.getParameters().size() >= 1) { 747 return method.getParameters().get(0); 748 } 749 return null; 750 } 751 752 private ServiceMethodParameter findTypeParameter(ServiceMethod method) { 753 for (ServiceMethodParameter parameter : method.getParameters()) { 754 if (parameter.getType().equals("String")) { 755 if (parameter.getName().endsWith("TypeKey")) { 756 return parameter; 757 } 758 if (parameter.getName().endsWith("Type")) { 759 return parameter; 760 } 761 } 762 } 763 return null; 764 } 765 766 private String calcMapName(ServiceMethod method) { 767 String mapName = this.calcObjectName(method); 768 mapName = this.initLower(mapName) + "Map"; 769 return mapName; 770 } 771 772 protected String calcObjectName(ServiceMethod method) { 773 if (method.getName().startsWith("create")) { 774 return method.getName().substring("create".length()); 775 } 776 if (method.getName().startsWith("update")) { 777 return method.getName().substring("update".length()); 778 } 779 if (method.getName().startsWith("validate")) { 780 return method.getName().substring("validate".length()); 781 } 782 if (method.getName().startsWith("delete")) { 783 return method.getName().substring("delete".length()); 784 } 785 if (method.getName().startsWith("get")) { 786 if (method.getReturnValue().getType().equals("StringList")) { 787 if (method.getName().contains("IdsBy")) { 788 return method.getName().substring("get".length(), 789 method.getName().indexOf("IdsBy")); 790 } 791 if (method.getName().contains("IdsFor")) { 792 return method.getName().substring("get".length(), 793 method.getName().indexOf("IdsFor")); 794 } 795 return method.getName().substring("get".length()); 796 } 797 String name = method.getReturnValue().getType(); 798 if (name.endsWith("List")) { 799 name = name.substring(0, name.length() - "List".length()); 800 } 801 if (name.endsWith("Info")) { 802 name = name.substring(0, name.length() - "Info".length()); 803 } 804 return name; 805 } 806 if (method.getName().startsWith("add")) { 807 return method.getName().substring("add".length()); 808 } 809 if (method.getName().startsWith("remove")) { 810 return method.getName().substring("remove".length()); 811 } 812 String returnType = this.stripList(method.getReturnValue().getType()); 813 XmlType type = this.finder.findXmlType(returnType); 814 if (type.getPrimitive().equals(XmlType.COMPLEX)) { 815 return returnType; 816 } 817 throw new IllegalArgumentException(method.getName()); 818 } 819 820 private void writeUpdate(ServiceMethod method) { 821 ServiceMethodParameter idParam = this.findIdParameter(method); 822 ServiceMethodParameter infoParam = this.findInfoParameter(method); 823 ServiceMethodParameter contextParam = this.findContextParameter(method); 824 if (infoParam == null) { 825 throw new NullPointerException(method.getName()); 826 } 827 String objectName = calcObjectName(method); 828 String infoName = objectName; 829 if (!this.isRice()) { 830 infoName = infoName + "Info"; 831 } 832 String mapName = calcMapName(method); 833 if (idParam != null) { 834 if (!this.isRice()) { 835 indentPrintln("if (!" + idParam.getName() + ".equals (" + infoParam.getName() + ".getId())) {"); 836 indentPrintln(" throw new " + this.getInvalidParameterException() + " (\"The id parameter does not match the id on the info object\");"); 837 indentPrintln("}"); 838 } 839 } 840 if (isR1) { 841 indentPrintln("// don't have deep copy in R1 contracts so just use the object"); 842 indentPrintln(infoName + " copy = " + infoParam.getName() + ";"); 843 } else if (this.isRice()) { 844 indentPrintln(infoName + ".Builder copy = " + infoName + ".Builder.create (" + infoParam.getName() + ");"); 845 } else { 846 indentPrintln(infoName + " copy = new " + infoName + "(" + infoParam.getName() + ");"); 847 } 848 if (contextParam != null) { 849 indentPrintln(infoName + " old = this.get" + objectName + "(" + infoParam.getName() + ".getId(), " + contextParam.getName() + ");"); 850 } else { 851 indentPrintln(infoName + " old = this.get" + objectName + "(" + infoParam.getName() + ".getId());"); 852 } 853 if (isR1) { 854 indentPrintln("if (!old.getMetaInfo().getVersionInd().equals(copy.getMetaInfo().getVersionInd())) {"); 855 indentPrintln(" throw new " + this.getVersionMismatchException() + "(old.getMetaInfo().getVersionInd());"); 856 indentPrintln("}"); 857 if (contextParam != null) { 858 indentPrintln("copy.setMeta(updateMeta(copy.getMetaInfo()));"); 859 } 860 } else if (this.isRice()) { 861 indentPrintln("if (!old.getVersionNumber().equals(copy.getVersionNumber())) {"); 862 indentPrintln(" throw new " + this.getVersionMismatchException() + "(\"\" + old.getVersionNumber());"); 863 indentPrintln("}"); 864 indentPrintln("copy.setVersionNumber(copy.getVersionNumber() + 1);"); 865 } else { 866 indentPrintln("if (!old.getMeta().getVersionInd().equals(copy.getMeta().getVersionInd())) {"); 867 indentPrintln(" throw new " + this.getVersionMismatchException() + "(old.getMeta().getVersionInd());"); 868 indentPrintln("}"); 869 if (contextParam != null) { 870 indentPrintln("copy.setMeta(updateMeta(copy.getMeta(), contextInfo));"); 871 } 872 } 873 if (isR1) { 874 indentPrintln("this." + mapName + " .put(" + infoParam.getName() + ".getId(), copy);"); 875 indentPrintln("// don't have deep copy in R1 contracts so just use the object"); 876 indentPrintln("return copy;"); 877 } else if (this.isRice()) { 878 indentPrintln (infoParam.getName() + " = copy.build ();"); 879 indentPrintln("this." + mapName + " .put(" + infoParam.getName() + ".getId(), " + infoParam.getName() + ");"); 880 indentPrintln("return " + infoParam.getName() + ";"); 881 } else { 882 indentPrintln("this." + mapName + " .put(" + infoParam.getName() + ".getId(), copy);"); 883 indentPrintln("return new " + infoName + "(copy);"); 884 } 885 886 } 887 888 private void writeDelete(ServiceMethod method) { 889 ServiceMethodParameter idParam = this.findIdParameter(method); 890 String mapName = calcMapName(method); 891 indentPrintln("if (this." + mapName + ".remove(" + idParam.getName() + ") == null) {"); 892 indentPrintln(" throw new " + this.getOperationFailedException() + "(" + idParam.getName() + ");"); 893 indentPrintln("}"); 894 indentPrintln("return newStatus();"); 895 } 896 897 private void writeRemove(ServiceMethod method) { 898 ServiceMethodParameter idParam = this.findIdParameter(method); 899 String mapName = calcMapName(method); 900 indentPrintln("if (this." + mapName + ".remove(" + idParam.getName() + ") == null) {"); 901 indentPrintln(" throw new " + this.getOperationFailedException() + "(" + idParam.getName() + ");"); 902 indentPrintln("}"); 903 indentPrintln("return newStatus();"); 904 } 905 906 private void writeGetById(ServiceMethod method) { 907 ServiceMethodParameter idParam = this.findIdParameter(method); 908 String mapName = calcMapName(method); 909 indentPrintln("if (!this." + mapName + ".containsKey(" + idParam.getName() + ")) {"); 910 indentPrintln(" throw new " + this.getOperationFailedException() + "(" + idParam.getName() + ");"); 911 indentPrintln("}"); 912 String objectName = calcObjectName(method); 913 String infoName = objectName; 914 if (!this.isRice()) { 915 infoName = infoName + "Info"; 916 } 917 if (isR1) { 918 indentPrintln("// r1 objects do not have deep cody"); 919 indentPrintln("return this." + mapName + ".get (" + idParam.getName() + ");"); 920 } else if (this.isRice()) { 921 indentPrintln("return this." + mapName + ".get (" + idParam.getName() + ");"); 922 } else { 923 indentPrintln("return new " + infoName + "(this." + mapName + ".get (" + idParam.getName() + "));"); 924 } 925 926 } 927 928 private void writeGetByIds(ServiceMethod method) { 929 String objectName = this.calcObjectName(method); 930 String infoName = objectName; 931 if (!this.isRice()) { 932 infoName = infoName + "Info"; 933 } 934 ServiceMethodParameter idListParam = this.findIdListParameter(method); 935 ServiceMethodParameter contextParam = this.findContextParameter(method); 936 this.importsAdd(ArrayList.class.getName()); 937 indentPrintln("List<" + infoName + "> list = new ArrayList<" + infoName + "> ();"); 938 939 indentPrintln("for (String id: " + idListParam.getName() + ") {"); 940 if (this.isRice()) { 941 indentPrintln(" list.add (this.get" + objectName + "(id));"); 942 } else { 943 indentPrintln(" list.add (this.get" + objectName + "(id, " + contextParam.getName() + "));"); 944 } 945 indentPrintln("}"); 946 indentPrintln("return list;"); 947 } 948 949 private void writeGetIdsByOther(ServiceMethod method) { 950 String objectName = this.calcObjectName(method); 951 String infoName = objectName; 952 if (!this.isRice()) { 953 infoName = infoName + "Info"; 954 } 955 String mapName = calcMapName(method); 956 this.importsAdd(ArrayList.class.getName()); 957 indentPrintln("List<String> list = new ArrayList<String> ();"); 958 indentPrintln("for (" + infoName + " info: " + mapName + ".values ()) {"); 959 for (ServiceMethodParameter parameter : method.getParameters()) { 960 if (parameter.getType().equals("ContextInfo")) { 961 continue; 962 } 963 incrementIndent(); 964 indentPrintln("if (" + parameter.getName() + ".equals(info.get" + initUpper(parameter.getName()) + "())) {"); 965 } 966 indentPrintln(" list.add (info.getId ());"); 967 for (ServiceMethodParameter parameter : method.getParameters()) { 968 if (parameter.getType().equals("ContextInfo")) { 969 continue; 970 } 971 indentPrintln("}"); 972 decrementIndent(); 973 } 974 indentPrintln("}"); 975 indentPrintln("return list;"); 976 } 977 978 private void writeGetIdsByType(ServiceMethod method) { 979 String objectName = this.calcObjectName(method); 980 String infoName = objectName; 981 if (!this.isRice()) { 982 infoName = infoName + "Info"; 983 } 984 String mapName = calcMapName(method); 985 this.importsAdd(ArrayList.class.getName()); 986 indentPrintln("List<String> list = new ArrayList<String> ();"); 987 indentPrintln("for (" + infoName + " info: " + mapName + ".values ()) {"); 988 for (ServiceMethodParameter parameter : method.getParameters()) { 989 if (parameter.getType().equals("ContextInfo")) { 990 continue; 991 } 992 incrementIndent(); 993 indentPrintln("if (" + parameter.getName() + ".equals(info.getTypeKey())) {"); 994 } 995 indentPrintln(" list.add (info.getId ());"); 996 for (ServiceMethodParameter parameter : method.getParameters()) { 997 if (parameter.getType().equals("ContextInfo")) { 998 continue; 999 } 1000 indentPrintln("}"); 1001 decrementIndent(); 1002 } 1003 indentPrintln("}"); 1004 indentPrintln("return list;"); 1005 } 1006 1007 private void writeRiceGetByNamespaceAndName(ServiceMethod method) { 1008 String objectName = this.calcObjectName(method); 1009 String infoName = objectName; 1010 if (!this.isRice()) { 1011 infoName = infoName + "Info"; 1012 } 1013 String mapName = calcMapName(method); 1014 indentPrintln("for (" + infoName + " info: " + mapName + ".values ()) {"); 1015 for (ServiceMethodParameter parameter : method.getParameters()) { 1016 incrementIndent(); 1017 indentPrintln("if (" + parameter.getName() + ".equals(info.get" + initUpper(parameter.getName()) + "())) {"); 1018 } 1019 indentPrintln(" return " + infoName + ".Builder.create (info).build ();"); 1020 for (ServiceMethodParameter parameter : method.getParameters()) { 1021 indentPrintln("}"); 1022 decrementIndent(); 1023 } 1024 indentPrintln("}"); 1025 indentPrintln("throw new RiceIllegalArgumentException ();"); 1026 } 1027 1028 private void writeGetInfosByOther(ServiceMethod method) { 1029 String objectName = this.calcObjectName(method); 1030 String infoName = objectName; 1031 if (!this.isRice()) { 1032 infoName = infoName + "Info"; 1033 } 1034 String mapName = calcMapName(method); 1035 this.importsAdd(ArrayList.class.getName()); 1036 indentPrintln("List<" + infoName + "> list = new ArrayList<" + infoName + "> ();"); 1037 indentPrintln("for (" + infoName + " info: " + mapName + ".values ()) {"); 1038 for (ServiceMethodParameter parameter : method.getParameters()) { 1039 if (parameter.getType().equals("ContextInfo")) { 1040 continue; 1041 } 1042 incrementIndent(); 1043 indentPrintln("if (" + parameter.getName() + ".equals(info.get" + initUpper(parameter.getName()) + "())) {"); 1044 } 1045 indentPrintln(" list.add (new " + infoName + "(info));"); 1046 for (ServiceMethodParameter parameter : method.getParameters()) { 1047 if (parameter.getType().equals("ContextInfo")) { 1048 continue; 1049 } 1050 indentPrintln("}"); 1051 decrementIndent(); 1052 } 1053 indentPrintln("}"); 1054 indentPrintln("return list;"); 1055 } 1056 1057 private void writeGetType(ServiceMethod method) { 1058 ServiceMethodParameter idParam = this.findIdParameter(method); 1059 String mapName = calcMapName(method); 1060 indentPrintln("if (!this." + mapName + ".containsKey(" + idParam.getName() + ")) {"); 1061 indentPrintln(" throw new " + this.getOperationFailedException() + "(" + idParam.getName() + ");"); 1062 indentPrintln("}"); 1063 indentPrintln("return this." + mapName + ".get (" + idParam.getName() + ");"); 1064 } 1065 1066 private void writeGetTypes(ServiceMethod method) { 1067 String mapName = calcMapName(method); 1068 String objectName = this.calcObjectName(method); 1069 String infoName = objectName; 1070 if (!this.isRice()) { 1071 infoName = infoName + "Info"; 1072 } 1073 this.importsAdd(ArrayList.class.getName()); 1074 indentPrintln("return new ArrayList<" + infoName + ">(" + mapName + ".values ());"); 1075 } 1076 1077 private String initUpper(String str) { 1078 return str.substring(0, 1).toUpperCase() + str.substring(1); 1079 } 1080 1081 private ServiceMethodParameter findIdListParameter(ServiceMethod method) { 1082 String idFieldName = calcObjectName(method) + "Ids"; 1083 if (this.isRice()) { 1084 idFieldName = "ids"; 1085 } 1086 for (ServiceMethodParameter parameter : method.getParameters()) { 1087 if (parameter.getType().equals("StringList")) { 1088 if (parameter.getName().equals(idFieldName)) { 1089 return parameter; 1090 } 1091 } 1092 } 1093 // can't find name exactly 1094 for (ServiceMethodParameter parameter : method.getParameters()) { 1095 if (parameter.getType().equals("StringList")) { 1096 if (parameter.getName().endsWith("Ids")) { 1097 return parameter; 1098 } 1099 } 1100 } 1101 // can't find name exactly try key 1102 for (ServiceMethodParameter parameter : method.getParameters()) { 1103 if (parameter.getType().equals("StringList")) { 1104 if (parameter.getName().endsWith("Keys")) { 1105 return parameter; 1106 } 1107 } 1108 } 1109 return null; 1110 } 1111 1112 private String stripList(String str) { 1113 return GetterSetterNameCalculator.stripList(str); 1114 } 1115 1116 private String calcExceptionClassName(ServiceMethodError error) { 1117 if (error.getClassName() == null) { 1118 return ServiceExceptionWriter.calcClassName(error.getType()); 1119 } 1120 return error.getClassName(); 1121 } 1122 1123 private String calcExceptionPackageName(ServiceMethodError error) { 1124 if (error.getClassName() == null) { 1125 return ServiceExceptionWriter.calcPackage(rootPackage); 1126 } 1127 return error.getPackageName(); 1128 } 1129 1130 private String calcType(String type, String realType) { 1131 XmlType t = finder.findXmlType(this.stripList(type)); 1132 String retType = MessageStructureTypeCalculator.calculate(this, model, type, realType, 1133 t.getJavaPackage()); 1134 if (this.isRice()) { 1135 if (retType.equals("Boolean")) { 1136 retType = "boolean"; 1137 } 1138 if (retType.equals("Void")) { 1139 retType = "void"; 1140 } 1141 } 1142 return retType; 1143 } 1144 }