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.contract.model.impl; 017 018 import com.thoughtworks.qdox.JavaDocBuilder; 019 import com.thoughtworks.qdox.model.*; 020 import com.thoughtworks.qdox.model.Type; 021 import com.thoughtworks.qdox.model.annotation.AnnotationValue; 022 import org.kuali.student.contract.model.*; 023 import org.kuali.student.contract.model.util.JavaClassAnnotationUtils; 024 import org.slf4j.Logger; 025 import org.slf4j.LoggerFactory; 026 027 import javax.xml.bind.annotation.XmlEnum; 028 import java.io.File; 029 import java.math.BigDecimal; 030 import java.util.*; 031 032 /** 033 * 034 * @author nwright 035 */ 036 public class ServiceContractModelQDoxLoader implements 037 ServiceContractModel { 038 039 private static final Logger log = LoggerFactory.getLogger(ServiceContractModelQDoxLoader.class); 040 041 private static final String LOCALE_KEY_LIST = "LocaleKeyList"; 042 private static final String MESSAGE_GROUP_KEY_LIST = "MessageGroupKeyList"; 043 private static final JavaClass STRING_JAVA_CLASS = new JavaClass( 044 "java.lang.String"); 045 private List<String> sourceDirectories = null; 046 private List<Service> services = null; 047 private List<ServiceMethod> serviceMethods = null; 048 private Map<String, XmlType> xmlTypeMap = null; 049 private List<MessageStructure> messageStructures; 050 private boolean validateKualiStudent; 051 052 public ServiceContractModelQDoxLoader(List<String> sourceDirectories) { 053 this (sourceDirectories, true); 054 } 055 056 public ServiceContractModelQDoxLoader(List<String> sourceDirectories, boolean validateKualiStudent) { 057 this.sourceDirectories = sourceDirectories; 058 this.setValidateKualiStudent(validateKualiStudent); 059 } 060 061 public boolean isValidateKualiStudent() { 062 return validateKualiStudent; 063 } 064 065 public void setValidateKualiStudent(boolean validateKualiStudent) { 066 this.validateKualiStudent = validateKualiStudent; 067 } 068 069 @Override 070 public List<ServiceMethod> getServiceMethods() { 071 if (this.serviceMethods == null) { 072 this.parse(); 073 } 074 return this.serviceMethods; 075 } 076 077 @Override 078 public List<String> getSourceNames() { 079 List<String> list = new ArrayList<String>(this.sourceDirectories.size()); 080 for (String javaFile : this.sourceDirectories) { 081 list.add(javaFile); 082 } 083 return list; 084 } 085 086 @Override 087 public List<Service> getServices() { 088 if (services == null) { 089 this.parse(); 090 } 091 return services; 092 } 093 094 @Override 095 public List<XmlType> getXmlTypes() { 096 if (xmlTypeMap == null) { 097 this.parse(); 098 } 099 return new ArrayList<XmlType>(xmlTypeMap.values()); 100 } 101 102 @Override 103 public List<MessageStructure> getMessageStructures() { 104 if (messageStructures == null) { 105 this.parse(); 106 } 107 return this.messageStructures; 108 } 109 110 private void checkIfExists(String sourceDirectory) { 111 File file = new File(sourceDirectory); 112 if (!file.isDirectory()) { 113 throw new IllegalArgumentException(sourceDirectory + " is not a directory on disk"); 114 } 115 } 116 117 @SuppressWarnings("unchecked") 118 private void parse() { 119 // System.out.println ("ServiceContractModelQDoxLoader: Starting parse"); 120 services = new ArrayList<Service>(); 121 serviceMethods = new ArrayList<ServiceMethod>(); 122 xmlTypeMap = new LinkedHashMap<String, XmlType>(); 123 messageStructures = new ArrayList<MessageStructure>(); 124 125 DefaultDocletTagFactory dtf = new DefaultDocletTagFactory(); 126 127 JavaDocBuilder builder = new JavaDocBuilder(dtf); 128 129 for (String sourceDirectory : sourceDirectories) { 130 checkIfExists(sourceDirectory); 131 builder.addSourceTree(new File(sourceDirectory)); 132 } 133 Set<JavaClass> mergedClasses = new LinkedHashSet<JavaClass>(); 134 135 for (JavaClass javaClass : builder.getClasses()) { 136 137 if (!javaClass.getPackageName().contains("r1")) 138 mergedClasses.add(javaClass); 139 else 140 log.warn("excluding r1 class: " + javaClass.getFullyQualifiedName()); 141 142 } 143 144 List<JavaClass>sortedClasses = new ArrayList<JavaClass>(mergedClasses); 145 146 Collections.sort(sortedClasses); 147 148 for (JavaClass javaClass : sortedClasses) { 149 if (!this.isServiceToProcess(javaClass)) { 150 continue; 151 } 152 // System.out.println ("processing service=" + javaClass.getName ()); 153 Service service = new Service(); 154 services.add(service); 155 service.setKey(calcServiceKey (javaClass)); 156 service.setName(javaClass.getName()); 157 service.setComments(this.calcComment(javaClass)); 158 service.setUrl(this.calcServiceUrl(javaClass)); 159 service.setVersion(this.calcVersion(javaClass)); 160 service.setStatus("???"); 161 service.setIncludedServices(calcIncludedServices(javaClass)); 162 service.setImplProject(javaClass.getPackageName()); 163 164 // for (DocletTag tag : javaClass.getTags ()) 165 // { 166 // System.out.println ("ServiceContractModelQDoxLoader: Class: " 167 // + javaClass.getName () + " has tag=" + dump ( 168 // tag)); 169 // } 170 171 JavaMethod[] methods = getServiceMethods (javaClass); 172 for (JavaMethod javaMethod : methods) { 173 174 ServiceMethod serviceMethod = new ServiceMethod(); 175 serviceMethods.add(serviceMethod); 176 serviceMethod.setService(service.getKey()); 177 serviceMethod.setName(javaMethod.getName()); 178 serviceMethod.setDescription(calcMissing(javaMethod.getComment())); 179 serviceMethod.setParameters(new ArrayList<ServiceMethodParameter>()); 180 serviceMethod.setImplNotes(calcImplementationNotes(javaMethod)); 181 serviceMethod.setDeprecated(isDeprecated(javaMethod)); 182 // for (DocletTag tag : javaMethod.getTags ()) 183 // { 184 // System.out.println ("ServiceContractModelQDoxLoader: Method: " 185 // + service.getName () + "." 186 // + javaMethod.getName () 187 // + " has tag=" + dump (tag)); 188 // } 189 // parameters 190 for (JavaParameter parameter : javaMethod.getParameters()) { 191 ServiceMethodParameter param = new ServiceMethodParameter(); 192 serviceMethod.getParameters().add(param); 193 param.setName(parameter.getName()); 194 param.setType(calcType(parameter.getType())); 195 param.setDescription(calcMissing( 196 calcParameterDescription(javaMethod, 197 param.getName()))); 198 try { 199 addXmlTypeAndMessageStructure(calcRealJavaClass(parameter.getType()), 200 serviceMethod.getService()); 201 } catch (Exception e) { 202 String message= "failed to parameter message structure: " + serviceMethod.getService() + " : " + parameter.getType(); 203 204 log.error (message + " : " + e.getMessage()); 205 log.debug(message, e); 206 } 207 } 208 // errors 209 serviceMethod.setErrors(new ArrayList<ServiceMethodError>()); 210 for (Type exception : javaMethod.getExceptions()) { 211 ServiceMethodError error = new ServiceMethodError(); 212 error.setType(this.calcType(exception.getJavaClass())); 213 error.setDescription(calcMissing( 214 calcExceptionDescription(javaMethod, 215 error.getType()))); 216 error.setPackageName(exception.getJavaClass().getPackageName()); 217 error.setClassName(exception.getJavaClass().getName()); 218 serviceMethod.getErrors().add(error); 219 } 220 // return values 221 ServiceMethodReturnValue rv = new ServiceMethodReturnValue(); 222 serviceMethod.setReturnValue(rv); 223 Type returnType = null; 224 try { 225 returnType = javaMethod.getReturnType(); 226 } catch (NullPointerException ex) { 227 log.error("Nullpointer getting return type: " + javaMethod.getCallSignature()); 228 returnType = null; 229 } 230 231 rv.setType(calcType(returnType)); 232 rv.setDescription(calcMissing(this.calcReturnDescription(javaMethod))); 233 if (returnType != null) { 234 try { 235 236 237 addXmlTypeAndMessageStructure(calcRealJavaClass(returnType), 238 serviceMethod.getService()); 239 } catch (Exception e) { 240 String message = "failed to parse return type message structure: " + serviceMethod.getService() + " : " + returnType; 241 242 log.error (message + " : " + e.getMessage()); 243 log.debug(message, e); 244 } 245 } 246 } 247 } 248 } 249 250 251 private String calcServiceKey(JavaClass javaClass) { 252 String key = javaClass.getName(); 253 if (key.endsWith ("Service")) { 254 key = key.substring(0, key.length() - "Service".length()); 255 } 256 if (javaClass.getPackageName().startsWith("org.kuali.rice.")) { 257 log.warn("WARNING " + " changing servkey for the RICE services to include prefix " 258 + " to disambiguate with Kuali Student StateService See Jira KSENROLL-2892"); 259 key = "RICE." + key; 260 } 261 return key; 262 } 263 264 private JavaMethod[] getServiceMethods(JavaClass javaClass) { 265 266 Set<JavaMethod>methods = new LinkedHashSet<JavaMethod>(); 267 268 /* 269 * As inheritence is useful from a technical level but not as much from a business level 270 * This lets the union of the methods from all of the interfaces be listed in the contract. 271 */ 272 JavaClass[] interfaces = javaClass.getImplementedInterfaces(); 273 274 for (JavaClass intfc : interfaces) { 275 276 if (!isAService(intfc)) { 277 // only add the methods if this is not a service 278 // e.g. extends ServiceBusinessLogic 279 for (JavaMethod javaMethod : intfc.getMethods()) { 280 281 methods.add(javaMethod); 282 } 283 } 284 285 } 286 287 // add the main service methods last incase we override any from the parent interfaces. 288 // note the heirarchy is only guaranteed relative to the target service class (if there are two levels or more of 289 // heirarchy there is no guarantee the method ordering will be correct). 290 for (JavaMethod javaMethod : javaClass.getMethods()) { 291 292 methods.add(javaMethod); 293 } 294 295 return methods.toArray(new JavaMethod[] {}); 296 } 297 298 private boolean isServiceToProcess(JavaClass javaClass) { 299 // System.out.println ("looking if javaClass is a service to process=" + javaClass.getName () + "=" + javaClass.getPackageName ()); 300 301 if (!javaClass.getName().endsWith("Service")) { 302 return false; 303 } 304 if (javaClass.getPackageName().contains(".old.")) { 305 306 return false; 307 } 308 if (javaClass.getPackageName().endsWith(".old")) { 309 return false; 310 } 311 for (Annotation annotation : javaClass.getAnnotations()) { 312 // System.out.println ("looking for webservice tag=" + annotation.getType ().getJavaClass ().getName ()); 313 if (annotation.getType().getJavaClass().getName().equals("WebService")) { 314 // System.out.println ("Processing web service=" + javaClass.getPackageName () 315 // + "." + javaClass.getName ()); 316 return true; 317 } 318 } 319 // This includes RICE's business object services even though they are not web services 320 // because often they are the only real service they have exposed and it helps to document 321 // them to see what the data really is like 322 if (javaClass.getName().endsWith("BoService")) { 323 return true; 324 } 325 // This includes KSA's internal services even though they are not web services 326 if (javaClass.getPackageName().startsWith("com.sigmasys.kuali.ksa.service")) { 327 return true; 328 } 329 if (javaClass.getPackageName().startsWith("org.kuali.mobility")) { 330 return true; 331 } 332 // System.out.println ("skipping service because it is not a web service=" 333 // + javaClass.getPackageName () + "." + javaClass.getName ()); 334 return false; 335 } 336 337 private List<String> calcIncludedServices(JavaClass javaClass) { 338 List<String> includedServices = new ArrayList<String>(); 339 for (JavaClass interfaceClass : javaClass.getImplementedInterfaces()) { 340 if (isAService(interfaceClass)) { 341 // System.out.println("ServiceContractModelQDoxLoader:" + javaClass.getName() 342 // + " implements " + interfaceClass.getName()); 343 includedServices.add(interfaceClass.getName()); 344 } 345 } 346 return includedServices; 347 } 348 349 private boolean isAService(JavaClass interfaceClass) { 350 if (interfaceClass.getName().endsWith("Service")) { 351 return true; 352 } 353 return false; 354 } 355 356 private String calcParameterDescription(JavaMethod method, 357 String parameterName) { 358 for (DocletTag tag : method.getTags()) { 359 if (tag.getName().equals("param")) { 360 if (tag.getValue().startsWith(parameterName + " ")) { 361 return tag.getValue().substring(parameterName.length() + 1); 362 } 363 } 364 } 365 return null; 366 } 367 368 private String calcExceptionDescription(JavaMethod serviceMethod, 369 String exceptionType) { 370 for (DocletTag tag : serviceMethod.getTags()) { 371 if (tag.getName().equals("throws")) { 372 if (tag.getValue().startsWith(exceptionType + " ")) { 373 return tag.getValue().substring(exceptionType.length() + 1); 374 } 375 } 376 } 377 return null; 378 } 379 380 private String calcReturnDescription(JavaMethod serviceMethod) { 381 for (DocletTag tag : serviceMethod.getTags()) { 382 if (tag.getName().equals("return")) { 383 return tag.getValue(); 384 } 385 } 386 return null; 387 } 388 389 private String calcServiceUrl(JavaClass serviceClass) { 390 for (DocletTag tag : serviceClass.getTags()) { 391 if (tag.getName().equals("See")) { 392 return tag.getValue(); 393 } 394 } 395 return null; 396 } 397 398 private void addXmlTypeAndMessageStructure(JavaClass messageStructureJavaClass, 399 String serviceKey) { 400 String name = calcType(messageStructureJavaClass); 401 if (name.endsWith("CallbackService")) { 402 return; 403 } 404 XmlType xmlType = xmlTypeMap.get(name); 405 if (xmlType == null) { 406 xmlType = new XmlType(); 407 xmlTypeMap.put(name, xmlType); 408 xmlType.setName(name); 409 xmlType.setDesc(this.calcMessageStructureDesc(messageStructureJavaClass)); 410 xmlType.setDeprecated(isDeprecated (messageStructureJavaClass)); 411 xmlType.setService(serviceKey); 412 xmlType.setVersion("IGNORE -- SAME AS SERVICE"); 413 xmlType.setPrimitive(calcPrimitive(messageStructureJavaClass)); 414 xmlType.setJavaPackage(calcJavaPackage(messageStructureJavaClass)); 415 if (xmlType.getPrimitive().equals(XmlType.COMPLEX)) { 416 addMessageStructure(messageStructureJavaClass, serviceKey); 417 } 418 419 } else { 420 addServiceToList(xmlType, serviceKey); 421 } 422 } 423 424 private boolean isDeprecated(JavaClass javaClass) { 425 for (Annotation annotation : javaClass.getAnnotations()) { 426 if (annotation.getType().getJavaClass().getName().equals( 427 "Deprecated")) { 428 return true; 429 } 430 } 431 return false; 432 } 433 434 private String calcJavaPackage(JavaClass javaClass) { 435 String packageName = javaClass.getPackageName(); 436 return packageName; 437 } 438 439 private String calcMessageStructureDesc(JavaClass javaClass) { 440 { 441 String desc = javaClass.getComment(); 442 if (desc != null) { 443 if (!desc.isEmpty()) { 444 return desc; 445 } 446 } 447 JavaClass infcClass = this.getMatchingInfc(javaClass); 448 if (infcClass == null) { 449 return null; 450 } 451 return infcClass.getComment(); 452 } 453 } 454 455 private JavaClass getMatchingInfc(JavaClass javaClass) { 456 // ks uses this pattern 457 String nameInfc = javaClass.getName(); 458 if (nameInfc.endsWith("Info")) { 459 nameInfc = nameInfc.substring(0, nameInfc.length() - "Info".length()) 460 + "Infc"; 461 } 462 String nameWithOutInfo = javaClass.getName(); 463 // rice uses this pattern 464 if (nameWithOutInfo.endsWith("Info")) { 465 nameWithOutInfo = nameWithOutInfo.substring(0, nameWithOutInfo.length() 466 - "Info".length()); 467 } 468 for (JavaClass infc : javaClass.getImplementedInterfaces()) { 469 if (infc.getName().equals(nameInfc)) { 470 // System.out.println("found matching interface " + infc.getName()); 471 return infc; 472 } 473 if (infc.getName().equals(nameWithOutInfo)) { 474 return infc; 475 } 476 } 477 return null; 478 } 479 480 private String calcPrimitive(JavaClass javaClass) { 481 if (this.isComplex(javaClass)) { 482 return XmlType.COMPLEX; 483 } 484 return "Primitive"; 485 } 486 487 private String initLower(String str) { 488 if (str == null) { 489 return null; 490 } 491 if (str.length() == 0) { 492 return str; 493 } 494 if (str.length() == 1) { 495 return str.toLowerCase(); 496 } 497 return str.substring(0, 1).toLowerCase() + str.substring(1); 498 } 499 500 private String initUpper(String str) { 501 if (str == null) { 502 return null; 503 } 504 if (str.length() == 0) { 505 return str; 506 } 507 if (str.length() == 1) { 508 return str.toUpperCase(); 509 } 510 return str.substring(0, 1).toUpperCase() + str.substring(1); 511 } 512 513 private Set<String> getShortNames(JavaClass messageStructureJavaClass) { 514 Set<String> fields = getFieldsUsingPropOrder(messageStructureJavaClass); 515 if (fields != null) { 516 return fields; 517 } 518 fields = new LinkedHashSet<String>(); 519 for (JavaMethod method : messageStructureJavaClass.getMethods(true)) { 520 if (isSetterMethodToProcess(method, messageStructureJavaClass.getName())) { 521 String shortName = this.calcShortNameFromSetter(method); 522 fields.add(shortName); 523 continue; 524 } 525 if (isGetterMethodToProcess(method, messageStructureJavaClass.getName())) { 526 String shortName = this.calcShortNameFromGetter(method); 527 fields.add(shortName); 528 continue; 529 } 530 } 531 return fields; 532 } 533 534 private Set<String> getFieldsUsingPropOrder( 535 JavaClass messageStructureJavaClass) { 536 for (Annotation annotation : messageStructureJavaClass.getAnnotations()) { 537 if (annotation.getType().getJavaClass().getName().equals("XmlType")) { 538 AnnotationValue propOrderParam = annotation.getProperty("propOrder"); 539 if (propOrderParam == null) { 540 continue; 541 } 542 Object propOrderValue = propOrderParam.getParameterValue(); 543 if (!(propOrderValue instanceof List)) { 544 continue; 545 } 546 Set<String> fields = new LinkedHashSet<String>(); 547 for (Object value : (List<?>) propOrderValue) { 548 if (value instanceof String) { 549 String shortName = (String) value; 550 shortName = this.stripQuotes(shortName); 551 if (shortName.contains(".Elements.")) { 552 String newShortName = getShortNameFromElements(shortName, messageStructureJavaClass); 553 if (newShortName == null) { 554 continue; 555 } 556 shortName = newShortName; 557 } else if (shortName.startsWith("CoreConstants.CommonElements.")) { 558 String newShortName = getCoreConstants(shortName); 559 if (newShortName == null) { 560 continue; 561 } 562 shortName = newShortName; 563 } 564 if (shortName.equals("_futureElements")) { 565 continue; 566 } 567 shortName = this.initUpper(shortName); 568 fields.add(shortName); 569 } 570 } 571 return fields; 572 } 573 } 574 return null; 575 } 576 577 private String getShortNameFromElements(String shortName, JavaClass messageStructureJavaClass) { 578 JavaClass elementsJavaClass = messageStructureJavaClass.getNestedClassByName("Elements"); 579 if (elementsJavaClass == null) { 580 return null; 581 } 582 String fieldName = shortName.substring(shortName.indexOf(".Elements.") + ".Elements.".length()); 583 JavaField field = elementsJavaClass.getFieldByName(fieldName); 584 String initExpr = field.getInitializationExpression(); 585 return stripQuotes(initExpr); 586 } 587 588 private String getCoreConstants(String shortName) { 589 if (shortName.endsWith("VERSION_NUMBER")) { 590 return "versionNumber"; 591 } 592 if (shortName.endsWith("OBJECT_ID")) { 593 return "objectId"; 594 } 595 if (shortName.endsWith("ACTIVE")) { 596 return "active"; 597 } 598 if (shortName.endsWith("ACTIVE_FROM_DATE")) { 599 return "activeFromDate"; 600 } 601 if (shortName.endsWith("ACTIVE_TO_DATE")) { 602 return "activeToDate"; 603 } 604 if (shortName.endsWith("ATTRIBUTES")) { 605 return "attributes"; 606 } 607 if (shortName.endsWith("FUTURE_ELEMENTS")) { 608 return "_futureElements"; 609 } 610 throw new RuntimeException("Unknown shortName " + shortName); 611 } 612 613 private void addMessageStructure(JavaClass messageStructureJavaClass, 614 String serviceKey) { 615 Set<JavaClass> subObjectsToAdd = new LinkedHashSet<JavaClass>(); 616 for (String shortName : this.getShortNames(messageStructureJavaClass)) { 617 JavaMethod setterMethod = findSetterMethod(messageStructureJavaClass, 618 shortName); 619 JavaMethod getterMethod = findGetterMethod(messageStructureJavaClass, 620 shortName); 621 if (getterMethod == null) { 622 if (this.validateKualiStudent) { 623 throw new IllegalArgumentException("shortName has no corresponding getter method: " 624 + messageStructureJavaClass.getFullyQualifiedName() 625 + "." + shortName); 626 } 627 } 628 JavaField beanField = this.findField(messageStructureJavaClass, 629 shortName, setterMethod); 630 if (beanField == null) { 631 String accessorType = getAccessorType(getterMethod); 632 if ("XmlAccessType.FIELD".equals(accessorType)) { 633 throw new IllegalArgumentException("Setter method has no corresponding bean field: " 634 + messageStructureJavaClass.getName() 635 + "." + getterMethod.getName()); 636 } 637 } 638 // overide the shortName if the bean field has an XmlAttribute name=xxx 639 // this catches the key=id switch 640 if (beanField != null) { 641 for (Annotation annotation : beanField.getAnnotations()) { 642 if (annotation.getType().getJavaClass().getName().equals("XmlAttribute")) { 643 Object nameValue = annotation.getNamedParameter("name"); 644 if (nameValue != null) { 645 shortName = stripQuotes(nameValue.toString()); 646 } 647 } 648 } 649 } 650 shortName = initLower(shortName); 651 MessageStructure ms = new MessageStructure(); 652 messageStructures.add(ms); 653 ms.setXmlObject(messageStructureJavaClass.getName()); 654 ms.setShortName(shortName); 655 ms.setId(ms.getXmlObject() + "." + ms.getShortName()); 656 ms.setName(calcMissing(calcName(messageStructureJavaClass, getterMethod, setterMethod, 657 beanField, shortName))); 658 ms.setType(calcType(messageStructureJavaClass, getterMethod, setterMethod, beanField, shortName)); 659 if (ms.getType().equals("Object")) { 660 log.warn(ms.getId() 661 + " has Object as it's type ==> Changing to String"); 662 ms.setType("String"); 663 } else if (ms.getType().equals("ObjectList")) { 664 log.warn(ms.getId() 665 + " has a list of Objects as it's type ==> Changing to List of String"); 666 ms.setType("StringList"); 667 } 668 ms.setXmlAttribute(this.calcXmlAttribute(beanField)); 669 ms.setRequired(calcRequired(getterMethod, setterMethod, beanField)); 670 ms.setReadOnly(calcReadOnly(getterMethod, setterMethod, beanField)); 671 ms.setCardinality(this.calcCardinality(messageStructureJavaClass, getterMethod, setterMethod, beanField, shortName)); 672 ms.setDescription(calcMissing(calcDescription(messageStructureJavaClass, getterMethod, setterMethod, 673 beanField, shortName))); 674 ms.setImplNotes(calcImplementationNotes(getterMethod, setterMethod, beanField)); 675 ms.setColumnName(calcImplementationColumn(getterMethod, setterMethod, beanField)); 676 ms.setDeprecated(isDeprecated(getterMethod)); 677 ms.setStatus("???"); 678 ms.setLookup(calcLookup (messageStructureJavaClass, getterMethod, setterMethod, 679 beanField, serviceKey, ms.getXmlObject(), shortName, ms.getType())); 680 ms.setPrimaryKey(calcPrimaryKey (messageStructureJavaClass, getterMethod, setterMethod, 681 beanField, serviceKey, ms.getXmlObject(), shortName, ms.getType())); 682 ms.setOverriden(this.calcOverridden(messageStructureJavaClass, getterMethod)); 683 JavaClass subObjToAdd = this.calcRealJavaClassOfGetterReturn(getterMethod); 684 if (subObjToAdd != null) { 685 // if (!subObjToAdd.isEnum()) { 686 if (!subObjToAdd.getName().equals("Object")) { 687 if (!subObjToAdd.getName().equals("LocaleKeyList")) { 688 if (!subObjToAdd.getName().equals("MessageGroupKeyList")) { 689 subObjectsToAdd.add(subObjToAdd); 690 } 691 } 692 } 693 // } 694 } 695 } 696 // now add all it's complex sub-objects if they haven't already been added 697 for (JavaClass subObjectToAdd : subObjectsToAdd) { 698 XmlType xmlType = xmlTypeMap.get(calcType(subObjectToAdd)); 699 if (xmlType == null) { 700 try { 701 addXmlTypeAndMessageStructure(subObjectToAdd, serviceKey); 702 } catch (Exception e) { 703 String message = "failed to parse subobject structure: " + subObjectToAdd + " : " + serviceKey; 704 // log into message 705 log.error (message + " : " + e.getMessage()); 706 // log into debug log 707 log.debug(message, e); 708 } 709 } else { 710 addServiceToList(xmlType, serviceKey); 711 } 712 } 713 return; 714 } 715 716 private String stripList (String type) { 717 if (type == null) { 718 return null; 719 } 720 if (type.endsWith("List")) { 721 return type.substring(0, type.length() - "List".length()); 722 } 723 return type; 724 } 725 726 727 private boolean calcPrimaryKey (JavaClass mainClass, JavaMethod getterMethod, 728 JavaMethod setterMethod, JavaField beanField, String serviceKey, String xmlObject, String shortName, String type) { 729 if (!type.equalsIgnoreCase ("String")) { 730 return false; 731 } 732 if (shortName.equalsIgnoreCase ("Id")) { 733 return true; 734 } 735 if (shortName.equalsIgnoreCase ("Key")) { 736 return true; 737 } 738 // Special fix up for principal 739 // log.warn(serviceKey + ":" + xmlObject + "." + shortName); 740 if (xmlObject.equalsIgnoreCase("Principal")) { 741 if (shortName.equalsIgnoreCase("principalId")) { 742 return true; 743 } 744 } 745 return false; 746 } 747 748 749 private Lookup calcLookup (JavaClass mainClass, JavaMethod getterMethod, 750 JavaMethod setterMethod, JavaField beanField, String serviceKey, String xmlObject, String shortName, String type) { 751 type = this.stripList(type); 752 // all keys and Ids are represented as strings 753 if (!type.equalsIgnoreCase ("String")) { 754 return null; 755 } 756 Lookup lookup = LOOKUP_MAPPINGS.get(shortName); 757 if (lookup == null) { 758 if (this.endsWithIdOrKey(shortName)) { 759 log.warn (serviceKey + ":" + xmlObject + "." + shortName + " ends with id or key but has no lookup defined"); 760 } 761 } 762 return lookup; 763 } 764 765 private boolean endsWithIdOrKey (String shortName) { 766 if (shortName.equals ("Id")) { 767 return false; 768 } 769 if (shortName.equals ("Key")) { 770 return false; 771 } 772 if (shortName.endsWith ("Id")) { 773 return true; 774 } 775 if (shortName.endsWith ("Ids")) { 776 return true; 777 } 778 if (shortName.endsWith ("Key")) { 779 return true; 780 } 781 if (shortName.endsWith ("Keys")) { 782 return true; 783 } 784 return false; 785 } 786 787 private static Map<String, Lookup> LOOKUP_MAPPINGS; 788 789 { 790 // global ones where the name matches the object 791 LOOKUP_MAPPINGS = new LinkedHashMap<String, Lookup> (); 792 LOOKUP_MAPPINGS.put("typeKey", new Lookup ("Type", "TypeInfo")); 793 LOOKUP_MAPPINGS.put("stateKey", new Lookup ("State", "StateInfo")); 794 LOOKUP_MAPPINGS.put("lifecycleKey", new Lookup ("State", "LifecycleInfo")); 795 LOOKUP_MAPPINGS.put("orgId", new Lookup ("Organization", "OrgInfo")); 796 LOOKUP_MAPPINGS.put("orgIds", new Lookup ("Organization", "OrgInfo")); 797 LOOKUP_MAPPINGS.put("organizationId", new Lookup ("Organization", "OrgInfo")); 798 LOOKUP_MAPPINGS.put("organizationIds", new Lookup ("Organization", "OrgInfo")); 799 LOOKUP_MAPPINGS.put("atpId", new Lookup ("Atp", "AtpInfo")); 800 LOOKUP_MAPPINGS.put("atpIds", new Lookup ("Atp", "AtpInfo")); 801 LOOKUP_MAPPINGS.put("termId", new Lookup ("AcademicCalendar", "TermInfo")); 802 LOOKUP_MAPPINGS.put("termIds", new Lookup ("AcademicCalendar", "TermInfo")); 803 LOOKUP_MAPPINGS.put("luiId", new Lookup ("Lui", "LuiInfo")); 804 LOOKUP_MAPPINGS.put("luiIds", new Lookup ("Lui", "LuiInfo")); 805 LOOKUP_MAPPINGS.put("cluId", new Lookup ("Clu", "CluInfo")); 806 LOOKUP_MAPPINGS.put("cluIds", new Lookup ("Clu", "CluInfo")); 807 LOOKUP_MAPPINGS.put("credentialProgramId", new Lookup ("Program", "CredentialProgramInfo")); 808 LOOKUP_MAPPINGS.put("credentialProgramIds", new Lookup ("Program", "CredentialProgramInfo")); 809 LOOKUP_MAPPINGS.put("credentialProgramId", new Lookup ("Program", "CredentialProgramInfo")); 810 LOOKUP_MAPPINGS.put("credentialProgramIds", new Lookup ("Program", "CredentialProgramInfo")); 811 LOOKUP_MAPPINGS.put("coreProgramId", new Lookup ("Program", "CoreProgramInfo")); 812 LOOKUP_MAPPINGS.put("coreProgramIds", new Lookup ("Program", "CoreProgramInfo")); 813 LOOKUP_MAPPINGS.put("resultScaleKey", new Lookup ("LRC", "ResultScaleInfo")); 814 LOOKUP_MAPPINGS.put("resultScaleKeys", new Lookup ("LRC", "ResultScaleInfo")); 815 LOOKUP_MAPPINGS.put("resultValuesGroupKey", new Lookup ("LRC", "ResultValuesGroupInfo")); 816 LOOKUP_MAPPINGS.put("resultValuesGroupKeys", new Lookup ("LRC", "ResultValuesGroupInfo")); 817 LOOKUP_MAPPINGS.put("resultValueKey", new Lookup ("LRC", "ResultValueInfo")); 818 LOOKUP_MAPPINGS.put("resultValueKeys", new Lookup ("LRC", "ResultValueInfo")); 819 LOOKUP_MAPPINGS.put("scheduleId", new Lookup ("Schedule", "ScheduleInfo")); 820 LOOKUP_MAPPINGS.put("scheduleIds", new Lookup ("Schedule", "ScheduleInfo")); 821 LOOKUP_MAPPINGS.put("courseId", new Lookup ("Course", "CourseInfo")); 822 LOOKUP_MAPPINGS.put("courseIds", new Lookup ("Course", "CourseInfo")); 823 LOOKUP_MAPPINGS.put("formatId", new Lookup ("Course", "FormatInfo")); 824 LOOKUP_MAPPINGS.put("formatIds", new Lookup ("Course", "FormatInfo")); 825 LOOKUP_MAPPINGS.put("activityId", new Lookup ("Course", "ActivityInfo")); 826 LOOKUP_MAPPINGS.put("activityIds", new Lookup ("Course", "ActivityInfo")); 827 LOOKUP_MAPPINGS.put("courseOfferingId", new Lookup ("CourseOffering", "CourseOfferingInfo")); 828 LOOKUP_MAPPINGS.put("courseOfferingIds", new Lookup ("CourseOffering", "CourseOfferingInfo")); 829 LOOKUP_MAPPINGS.put("formatOfferingId", new Lookup ("CourseOffering", "FormatOfferingInfo")); 830 LOOKUP_MAPPINGS.put("formatOfferingIds", new Lookup ("CourseOffering", "FormatOfferingInfo")); 831 LOOKUP_MAPPINGS.put("activityOfferingId", new Lookup ("CourseOffering", "ActivityOfferingInfo")); 832 LOOKUP_MAPPINGS.put("activityOfferingIds", new Lookup ("CourseOffering", "ActivityOfferingInfo")); 833 LOOKUP_MAPPINGS.put("socRolloverResultId", new Lookup ("CourseOfferingSet", "SorRolloverResultInfo")); 834 LOOKUP_MAPPINGS.put("socRolloverResultIds", new Lookup ("CourseOfferingSet", "SorRolloverResultInfo")); 835 LOOKUP_MAPPINGS.put("socRolloverResultItemId", new Lookup ("CourseOfferingSet", "SorRolloverResultItemInfo")); 836 LOOKUP_MAPPINGS.put("socRolloverResultItemIds", new Lookup ("CourseOfferingSet", "SorRolloverResultItemInfo")); 837 LOOKUP_MAPPINGS.put("buildingId", new Lookup ("Room", "BuildingInfo")); 838 LOOKUP_MAPPINGS.put("buildingIds", new Lookup ("Room", "BuildingInfo")); 839 LOOKUP_MAPPINGS.put("roomId", new Lookup ("Room", "RoomInfo")); 840 LOOKUP_MAPPINGS.put("roomIds", new Lookup ("Room", "RoomInfo")); 841 LOOKUP_MAPPINGS.put("populationId", new Lookup ("Population", "PopulationInfo")); 842 LOOKUP_MAPPINGS.put("populationIds", new Lookup ("Population", "PopulationInfo")); 843 844 845 // COMMON RICE IDENTITY SERVICE 846 LOOKUP_MAPPINGS.put("principalId", new Lookup ("rice.kim.Identity", "Principal")); 847 LOOKUP_MAPPINGS.put("principalIds", new Lookup ("rice.kim.Identity", "Principal")); 848 // TODO: fix these Ids that currently maps to principal instead of the entity id 849 LOOKUP_MAPPINGS.put("personId", new Lookup ("rice.kim.Identity", "Principal")); 850 LOOKUP_MAPPINGS.put("personIds", new Lookup ("rice.kim.Identity", "Principal")); 851 LOOKUP_MAPPINGS.put("instructorId", new Lookup ("rice.kim.Identity", "Principal")); 852 LOOKUP_MAPPINGS.put("instructorIds", new Lookup ("rice.kim.Identity", "Principal")); 853 LOOKUP_MAPPINGS.put("studentId", new Lookup ("rice.kim.Identity", "Principal")); 854 LOOKUP_MAPPINGS.put("studentIds", new Lookup ("rice.kim.Identity", "Principal")); 855 856 // Common objects 857 // TimeAmount 858 LOOKUP_MAPPINGS.put("atpDurationTypeKey", new Lookup ("Type", "TypeInfo")); 859 LOOKUP_MAPPINGS.put("currencyTypeKey", new Lookup ("Type", "TypeInfo")); 860 // Context 861 LOOKUP_MAPPINGS.put("authenticatedPrincipalId", new Lookup ("rice.kim.Identity", "Principal")); 862 // meta 863 LOOKUP_MAPPINGS.put("createId", new Lookup ("rice.kim.Identity", "Principal")); 864 LOOKUP_MAPPINGS.put("updateId", new Lookup ("rice.kim.Identity", "Principal")); 865 LOOKUP_MAPPINGS.put("agendaId", new Lookup ("rice.krms.Agenda", "Agenda")); 866 LOOKUP_MAPPINGS.put("agendaIds", new Lookup ("rice.krms.Agenda", "Agenda")); 867 LOOKUP_MAPPINGS.put("", new Lookup ("", "")); 868 LOOKUP_MAPPINGS.put("", new Lookup ("", "")); 869 LOOKUP_MAPPINGS.put("", new Lookup ("", "")); 870 LOOKUP_MAPPINGS.put("", new Lookup ("", "")); 871 LOOKUP_MAPPINGS.put("", new Lookup ("", "")); 872 LOOKUP_MAPPINGS.put("", new Lookup ("", "")); 873 LOOKUP_MAPPINGS.put("", new Lookup ("", "")); 874 875 876 // TODO: replace or augment this special list of ones with annotations in the contract itself 877 // program service 878 LOOKUP_MAPPINGS.put("unitsContentOwner", new Lookup ("Organization", "OrgInfo")); 879 LOOKUP_MAPPINGS.put("unitsDeployment", new Lookup ("Organization", "OrgInfo")); 880 LOOKUP_MAPPINGS.put("unitsStudentOversight", new Lookup ("Organization", "OrgInfo")); 881 LOOKUP_MAPPINGS.put("unitsFinancialResources", new Lookup ("Organization", "OrgInfo")); 882 LOOKUP_MAPPINGS.put("unitsFinancialControl", new Lookup ("Organization", "OrgInfo")); 883 LOOKUP_MAPPINGS.put("divisionsContentOwner", new Lookup ("Organization", "OrgInfo")); 884 LOOKUP_MAPPINGS.put("divisionsDeployment", new Lookup ("Organization", "OrgInfo")); 885 LOOKUP_MAPPINGS.put("divisionsStudentOversight", new Lookup ("Organization", "OrgInfo")); 886 LOOKUP_MAPPINGS.put("divisionsFinancialResources", new Lookup ("Organization", "OrgInfo")); 887 LOOKUP_MAPPINGS.put("divisionsFinancialControl", new Lookup ("Organization", "OrgInfo")); 888 LOOKUP_MAPPINGS.put("startTerm", new Lookup ("AcademicCalendar", "TermInfo")); 889 LOOKUP_MAPPINGS.put("endTerm", new Lookup ("AcademicCalendar", "TermInfo")); 890 LOOKUP_MAPPINGS.put("endProgramEntryTerm", new Lookup ("AcademicCalendar", "TermInfo")); 891 LOOKUP_MAPPINGS.put("resultOptions", new Lookup ("LRC", "ResultValuesGroupInfo")); 892 LOOKUP_MAPPINGS.put("programRequirements", new Lookup ("Program", "ProgramRequirementInfo")); 893 // share by program and course 894 LOOKUP_MAPPINGS.put("parentRelType", new Lookup ("Type", "TypeInfo")); 895 LOOKUP_MAPPINGS.put("parentLoRelationid", new Lookup ("LearningObjective", "LoInfo")); 896 897 // type service 898 LOOKUP_MAPPINGS.put("ownerTypeKey", new Lookup ("Type", "TypeInfo")); 899 LOOKUP_MAPPINGS.put("relatedTypeKey", new Lookup ("Type", "TypeInfo")); 900 901 // State service (there are no special purpose ones) 902 903 // LRC service (there are no special purpose ones) 904 905 // atp 906 LOOKUP_MAPPINGS.put("adminOrgId", new Lookup ("Organization", "OrgInfo")); 907 LOOKUP_MAPPINGS.put("relatedAtpId", new Lookup ("Atp", "AtpInfo")); 908 LOOKUP_MAPPINGS.put("relativeAnchorMilestoneId", new Lookup ("Atp", "MilestoneInfo")); 909 910 // Lui 911 LOOKUP_MAPPINGS.put("relatedLuiTypes", new Lookup ("Type", "TypeInfo")); 912 LOOKUP_MAPPINGS.put("relatedLuiId", new Lookup ("Lui", "LuiInfo")); 913 914 // Course Offering 915 LOOKUP_MAPPINGS.put("", new Lookup ("", "")); 916 LOOKUP_MAPPINGS.put("", new Lookup ("", "")); 917 918 // TODO: finish the services 919 LOOKUP_MAPPINGS.put("unitsDeploymentOrgIds", new Lookup ("Organization", "OrgInfo")); 920 LOOKUP_MAPPINGS.put("unitsContentOwnerOrgIds", new Lookup ("Organization", "OrgInfo")); 921 LOOKUP_MAPPINGS.put("unitsContentOwnerId", new Lookup ("Organization", "OrgInfo")); 922 LOOKUP_MAPPINGS.put("jointOfferingIds", new Lookup ("CourseOffering", "CourseOfferingInfo")); 923 LOOKUP_MAPPINGS.put("gradingOptionId", new Lookup ("LRC", "ResultValuesGroupInfo")); 924 LOOKUP_MAPPINGS.put("creditOptionId", new Lookup ("LRC", "ResultValuesGroupInfo")); 925 LOOKUP_MAPPINGS.put("waitlistLevelTypeKey", new Lookup ("Type", "TypeInfo")); 926 LOOKUP_MAPPINGS.put("waitlistTypeKey", new Lookup ("Type", "TypeInfo")); 927 LOOKUP_MAPPINGS.put("activityOfferingTypeKeys", new Lookup ("Type", "TypeInfo")); 928 LOOKUP_MAPPINGS.put("gradeRosterLevelTypeKey", new Lookup ("Type", "TypeInfo")); 929 LOOKUP_MAPPINGS.put("finalExamLevelTypeKey", new Lookup ("Type", "TypeInfo")); 930 LOOKUP_MAPPINGS.put("schedulingStateKey", new Lookup ("State", "StateInfo")); 931 LOOKUP_MAPPINGS.put("gradingOptionKeys", new Lookup ("LRC", "ResultValuesGroupInfo")); 932 LOOKUP_MAPPINGS.put("creditOptionId", new Lookup ("LRC", "ResultValuesGroupInfo")); 933 LOOKUP_MAPPINGS.put("gradingOptionKeys", new Lookup ("", "")); 934 LOOKUP_MAPPINGS.put("", new Lookup ("", "")); 935 LOOKUP_MAPPINGS.put("", new Lookup ("", "")); 936 LOOKUP_MAPPINGS.put("", new Lookup ("", "")); 937 LOOKUP_MAPPINGS.put("", new Lookup ("", "")); 938 LOOKUP_MAPPINGS.put("", new Lookup ("", "")); 939 LOOKUP_MAPPINGS.put("", new Lookup ("", "")); 940 LOOKUP_MAPPINGS.put("", new Lookup ("", "")); 941 LOOKUP_MAPPINGS.put("", new Lookup ("", "")); 942 LOOKUP_MAPPINGS.put("", new Lookup ("", "")); 943 LOOKUP_MAPPINGS.put("", new Lookup ("", "")); 944 LOOKUP_MAPPINGS.put("", new Lookup ("", "")); 945 946 } 947 948 private boolean calcOverridden(JavaClass mainClass, JavaMethod getterMethod) { 949 if (getterMethod == null) { 950 return false; 951 } 952 JavaMethod infcGetter = null; 953 if (getterMethod.getParentClass().isInterface()) { 954 infcGetter = getterMethod; 955 } 956 if (infcGetter == null) { 957 infcGetter = findInterfaceMethod(mainClass, getterMethod, false); 958 } 959 if (infcGetter == null) { 960 return false; 961 } 962 Annotation annotation = this.getAnnotation(infcGetter, null, null, "Override"); 963 if (annotation != null) { 964 return true; 965 } 966 return false; 967 } 968 969 private String calcComment(JavaClass javaClass) { 970 return this.calcComment(javaClass.getComment()); 971 } 972 973 private String calcComment(String comment) { 974 return this.parseCommentVersion(comment)[0]; 975 } 976 977 private String calcVersion(JavaClass javaClass) { 978 DocletTag tag = javaClass.getTagByName("version", true); 979 if (tag != null) { 980 return tag.getValue(); 981 } 982 return this.calcVersion(javaClass.getComment()); 983 } 984 985 private String calcVersion(String comment) { 986 return this.parseCommentVersion(comment)[1]; 987 } 988 989 private String[] parseCommentVersion(String commentVersion) { 990 String[] parsed = new String[2]; 991 if (commentVersion == null) { 992 return parsed; 993 } 994 commentVersion = commentVersion.trim(); 995 int i = commentVersion.toLowerCase().indexOf("\nversion:"); 996 if (i == -1) { 997 parsed[0] = commentVersion; 998 return parsed; 999 } 1000 parsed[1] = commentVersion.substring(i + "\nversion:".length()).trim(); 1001 parsed[0] = commentVersion.substring(0, i).trim(); 1002 1003 return parsed; 1004 } 1005 1006 private Annotation getAnnotation(JavaMethod getterMethod, 1007 JavaMethod setterMethod, JavaField beanField, String type) { 1008 if (beanField != null) { 1009 1010 for (Annotation annotation : beanField.getAnnotations()) { 1011 if (annotation.getType().getJavaClass().getName().equals(type)) { 1012 return annotation; 1013 } 1014 } 1015 } 1016 if (getterMethod != null) { 1017 1018 for (Annotation annotation : getterMethod.getAnnotations()) { 1019 if (annotation.getType().getJavaClass().getName().equals(type)) { 1020 return annotation; 1021 } 1022 } 1023 } 1024 if (setterMethod != null) { 1025 1026 for (Annotation annotation : setterMethod.getAnnotations()) { 1027 if (annotation.getType().getJavaClass().getName().equals(type)) { 1028 return annotation; 1029 } 1030 } 1031 } 1032 return null; 1033 } 1034 1035 private String calcRequired(JavaMethod getterMethod, 1036 JavaMethod setterMethod, JavaField beanField) { 1037 Annotation annotation = this.getAnnotation(getterMethod, setterMethod, beanField, "XmlElement"); 1038 if (annotation == null) { 1039 annotation = this.getAnnotation(getterMethod, setterMethod, beanField, "XmlAttribute"); 1040 } 1041 if (annotation != null) { 1042 Object required = annotation.getNamedParameter("required"); 1043 if (required != null) { 1044 if (required.toString().equalsIgnoreCase("true")) { 1045 return "Required"; 1046 } 1047 } 1048 } 1049 if (getterMethod != null) { 1050 DocletTag tag = getterMethod.getTagByName("required", true); 1051 if (tag != null) { 1052 if (tag.getValue() == null) { 1053 return "Required"; 1054 } 1055 String required = "Required " + tag.getValue(); 1056 return required.trim(); 1057 } 1058 } 1059 return null; 1060 } 1061 1062 private String calcReadOnly(JavaMethod getterMethod, 1063 JavaMethod setterMethod, JavaField beanField) { 1064 if (getterMethod != null) { 1065 DocletTag tag = getterMethod.getTagByName("readOnly", true); 1066 if (tag != null) { 1067 if (tag.getValue() == null) { 1068 return "Read only"; 1069 } 1070 String readOnly = "Read only " + tag.getValue(); 1071 return readOnly.trim(); 1072 } 1073 } 1074 return null; 1075 } 1076 1077 private String calcImplementationNotes(JavaMethod serviceMethod) { 1078 StringBuilder bldr = new StringBuilder(); 1079 String newLine = ""; 1080 for (DocletTag tag : serviceMethod.getTagsByName("impl", true)) { 1081 bldr.append(newLine); 1082 newLine = "\n"; 1083 String value = tag.getValue(); 1084 bldr.append(value); 1085 } 1086 if (hasOverride(serviceMethod)) { 1087 boolean matchJustOnName = true; 1088 JavaMethod overriddenMethod = findInterfaceMethod(serviceMethod.getParentClass(), serviceMethod, matchJustOnName); 1089 if (overriddenMethod == null) { 1090 // do it again so we can debug 1091 findInterfaceMethod(serviceMethod.getParentClass(), serviceMethod, true); 1092 throw new NullPointerException("could not find overridden method or method that has @Override annotation " + serviceMethod.getCallSignature()); 1093 } 1094 bldr.append(newLine); 1095 newLine = "\n"; 1096 bldr.append("Overridden method should be implemented in helper: "); 1097 bldr.append(overriddenMethod.getParentClass().getName()); 1098 } 1099 if (bldr.length() == 0) { 1100 return null; 1101 } 1102 return bldr.toString(); 1103 } 1104 1105 private boolean hasOverride(JavaMethod serviceMethod) { 1106 for (Annotation annotation : serviceMethod.getAnnotations()) { 1107 if (annotation.getType().getJavaClass().getName().equals( 1108 "Override")) { 1109 return true; 1110 } 1111 } 1112 return false; 1113 } 1114 1115 private boolean isDeprecated(JavaMethod serviceMethod) { 1116 for (Annotation annotation : serviceMethod.getAnnotations()) { 1117 if (annotation.getType().getJavaClass().getName().equals( 1118 "Deprecated")) { 1119 return true; 1120 } 1121 } 1122 return false; 1123 } 1124 1125 private String calcImplementationNotes(JavaMethod getterMethod, 1126 JavaMethod setterMethod, JavaField beanField) { 1127 if (getterMethod != null) { 1128 DocletTag tag = getterMethod.getTagByName("impl", true); 1129 if (tag != null) { 1130 return tag.getValue(); 1131 } 1132 } 1133 return null; 1134 } 1135 1136 private String calcImplementationColumn (JavaMethod getterMethod, 1137 JavaMethod setterMethod, JavaField beanField) { 1138 if (getterMethod != null) { 1139 DocletTag tag = getterMethod.getTagByName("implColumn", true); 1140 if (tag != null) { 1141 return tag.getValue(); 1142 } 1143 } 1144 return null; 1145 } 1146 1147 private String calcNameFromShortName(String shortName) { 1148 StringBuilder bldr = new StringBuilder(shortName.length() + 3); 1149 char c = shortName.charAt(0); 1150 bldr.append(Character.toUpperCase(c)); 1151 boolean lastWasUpper = true; 1152 for (int i = 1; i < shortName.length(); i++) { 1153 c = shortName.charAt(i); 1154 if (Character.isUpperCase(c)) { 1155 if (!lastWasUpper) { 1156 bldr.append(" "); 1157 } 1158 } else { 1159 lastWasUpper = false; 1160 } 1161 bldr.append(c); 1162 } 1163 return bldr.toString(); 1164 } 1165 1166 private String calcName(JavaClass mainClass, JavaMethod getterMethod, 1167 JavaMethod setterMethod, JavaField beanField, String shortName) { 1168 String name = this.calcNameFromTag(getterMethod, setterMethod, beanField); 1169 if (name != null) { 1170 return name; 1171 } 1172 name = this.calcNameFromNameEmbeddedInDescription(mainClass, getterMethod, setterMethod, beanField, shortName); 1173 if (name != null) { 1174 return name; 1175 } 1176 return this.calcNameFromShortName(shortName); 1177 } 1178 1179 private String calcNameFromTag(JavaMethod getterMethod, 1180 JavaMethod setterMethod, JavaField beanField) { 1181 if (getterMethod != null) { 1182 DocletTag tag = getterMethod.getTagByName("name", true); 1183 if (tag != null) { 1184 return tag.getValue(); 1185 } 1186 } 1187 return null; 1188 } 1189 1190 private String calcNameFromNameEmbeddedInDescription(JavaClass mainClass, JavaMethod getterMethod, 1191 JavaMethod setterMethod, JavaField beanField, String shortName) { 1192 String nameDesc = this.calcMethodComment(mainClass, getterMethod, setterMethod, 1193 beanField, shortName); 1194 String[] parsed = parseNameDesc(nameDesc); 1195 return parsed[0]; 1196 } 1197 1198 private String[] parseNameDesc(String nameDesc) { 1199 String[] parsed = new String[2]; 1200 if (nameDesc == null) { 1201 return parsed; 1202 } 1203 nameDesc = nameDesc.trim(); 1204 if (!nameDesc.startsWith("Name:")) { 1205 parsed[1] = nameDesc; 1206 return parsed; 1207 } 1208 nameDesc = nameDesc.substring("Name:".length()).trim(); 1209 int i = nameDesc.indexOf("\n"); 1210 if (i == -1) { 1211 parsed[0] = nameDesc.trim(); 1212 return parsed; 1213 } 1214 parsed[0] = nameDesc.substring(0, i).trim(); 1215 parsed[1] = nameDesc.substring(i).trim(); 1216 return parsed; 1217 } 1218 1219 private String calcDescription(JavaClass mainClass, JavaMethod getterMethod, 1220 JavaMethod setterMethod, JavaField beanField, String shortName) { 1221 String nameDesc = this.calcMethodComment(mainClass, getterMethod, setterMethod, 1222 beanField, shortName); 1223 String[] parsed = parseNameDesc(nameDesc); 1224 return parsed[1]; 1225 } 1226 1227 private String calcMethodComment(JavaClass mainClass, JavaMethod getterMethod, 1228 JavaMethod setterMethod, 1229 JavaField beanField, 1230 String shortName) { 1231 String desc = null; 1232 if (getterMethod != null) { 1233 desc = getterMethod.getComment(); 1234 if (isCommentNotEmpty(desc)) { 1235 return desc; 1236 } 1237 // System.out.println("Searching for superclass to find description for field " + shortName); 1238 JavaClass jc = mainClass; 1239 while (true) { 1240 JavaClass superJc = jc.getSuperJavaClass(); 1241 if (superJc == null) { 1242 break; 1243 } 1244 JavaMethod parentGetterMethod = this.findGetterMethod(superJc, shortName); 1245 if (parentGetterMethod != null) { 1246 desc = parentGetterMethod.getComment(); 1247 if (isCommentNotEmpty(desc)) { 1248 return desc; 1249 } 1250 } 1251 jc = superJc; 1252 } 1253 } 1254 if (setterMethod != null) { 1255 desc = setterMethod.getComment(); 1256 if (isCommentNotEmpty(desc)) { 1257 return desc; 1258 } 1259 } 1260 if (beanField != null) { 1261 desc = beanField.getComment(); 1262 if (isCommentNotEmpty(desc)) { 1263 return desc; 1264 } 1265 } 1266 desc = calcMethodCommentRecursively(mainClass, getterMethod); 1267 if (isCommentNotEmpty(desc)) { 1268 return desc; 1269 } 1270 desc = calcMethodCommentRecursively(mainClass, setterMethod); 1271 if (isCommentNotEmpty(desc)) { 1272 return desc; 1273 } 1274 return null; 1275 } 1276 1277 private String calcMethodCommentRecursively(JavaClass mainClass, JavaMethod method) { 1278 if (method == null) { 1279 return null; 1280 } 1281 String desc = method.getComment(); 1282 if (isCommentNotEmpty(desc)) { 1283 return desc; 1284 } 1285 JavaMethod infcMethod = findInterfaceMethod(mainClass, method, false); 1286 if (infcMethod != null) { 1287 desc = infcMethod.getComment(); 1288 if (isCommentNotEmpty(desc)) { 1289 return desc; 1290 } 1291 } 1292 JavaMethod superMethod = findSuperMethod(method); 1293 if (superMethod != null) { 1294 desc = superMethod.getComment(); 1295 if (isCommentNotEmpty(desc)) { 1296 return desc; 1297 } 1298 } 1299 return null; 1300 } 1301 1302 private JavaMethod findSuperMethod(JavaMethod method) { 1303 // System.out.println("Searching for super method for " 1304 // + method.getParentClass().getName() + "." 1305 // + method.getCallSignature()); 1306 for (JavaMethod superMethod : method.getParentClass().getMethods(true)) { 1307 if (method.equals(superMethod)) { 1308 continue; 1309 } 1310 if (method.getCallSignature().equals(superMethod.getCallSignature())) { 1311 return superMethod; 1312 } 1313 } 1314 return null; 1315 } 1316 1317 private JavaMethod findInterfaceMethod(JavaClass mainClass, JavaMethod method, boolean matchJustOnName) { 1318 String callSig = method.getCallSignature(); 1319 if (matchJustOnName) { 1320 callSig = method.getName(); 1321 } 1322 JavaClass classToSearch = mainClass; 1323 // log ("Searching mainClass " + classToSearch.getName() + " for " + callSig, callSig); 1324 while (true) { 1325 for (JavaClass infcClass : classToSearch.getImplementedInterfaces()) { 1326 JavaMethod meth = this.findMethodOnInterfaceRecursively(infcClass, callSig, matchJustOnName); 1327 if (meth != null) { 1328 // recursionCntr = 0; 1329 return meth; 1330 } 1331 } 1332 JavaClass superClass = classToSearch.getSuperJavaClass(); 1333 if (superClass == null) { 1334 // recursionCntr = 0; 1335 // log ("Did not find " + callSig + " on " + mainClass, callSig); 1336 return null; 1337 } 1338 classToSearch = superClass; 1339 // log ("Searching superClass " + classToSearch.getName() + " for " + callSig, callSig); 1340 } 1341 } 1342 1343 // private void log (String message, String callSig) { 1344 // if (callSig.equalsIgnoreCase("getTypeKey()")) { 1345 // for (int i = 0; i < this.recursionCntr; i++) { 1346 // System.out.print (" "); 1347 // } 1348 // System.out.println (message); 1349 // } 1350 // } 1351 // private int recursionCntr = 0; 1352 private JavaMethod findMethodOnInterfaceRecursively(JavaClass infcClass, String callSig, boolean matchJustOnName) { 1353 // recursionCntr++; 1354 // log ("Searching interface " + infcClass.getName() + " for " + callSig, callSig); 1355 for (JavaMethod infcMethod : infcClass.getMethods()) { 1356 if (callSig.equals(infcMethod.getCallSignature())) { 1357 // log (callSig + " found on " + infcClass.getName() + "!!!!!!!!!!!!!!!!", callSig); 1358 // recursionCntr--; 1359 return infcMethod; 1360 } 1361 if (matchJustOnName) { 1362 if (callSig.equals(infcMethod.getName())) { 1363 return infcMethod; 1364 } 1365 } 1366 } 1367 for (JavaClass subInfc : infcClass.getImplementedInterfaces()) { 1368 // log ("Searching sub-interface " + subInfc.getName() + " for " + callSig, callSig); 1369 JavaMethod infcMethod = findMethodOnInterfaceRecursively(subInfc, callSig, matchJustOnName); 1370 if (infcMethod != null) { 1371 // recursionCntr--; 1372 return infcMethod; 1373 } 1374 } 1375 // log (callSig + " not found on " + infcClass.getName(), callSig); 1376 // this.recursionCntr--; 1377 return null; 1378 } 1379 1380 private boolean isCommentNotEmpty(String desc) { 1381 if (desc == null) { 1382 return false; 1383 } 1384 if (desc.trim().isEmpty()) { 1385 return false; 1386 } 1387 if (desc.contains("@inheritDoc")) { 1388 return false; 1389 } 1390 return true; 1391 } 1392 1393 private String getAccessorType(JavaMethod method) { 1394 String accessorType = getAccessorType(method.getAnnotations()); 1395 if (accessorType != null) { 1396 return accessorType; 1397 } 1398 accessorType = getAccessorType(method.getParentClass().getAnnotations()); 1399 return accessorType; 1400 } 1401 1402 private String getAccessorType(Annotation[] annotations) { 1403 for (Annotation annotation : annotations) { 1404 if (annotation.getType().getJavaClass().getName().equals( 1405 "XmlAccessorType")) { 1406 // System.out.println ("Looking for XmlAccessorType annotation = " 1407 // + annotation.getParameterValue ()); 1408 return annotation.getParameterValue().toString(); 1409 } 1410 } 1411 return null; 1412 } 1413 1414 private String stripQuotes(String str) { 1415 if (str.startsWith("\"")) { 1416 str = str.substring(1); 1417 } 1418 if (str.endsWith("\"")) { 1419 str = str.substring(0, str.length() - 1); 1420 } 1421 return str; 1422 } 1423 1424 private String calcMissing(String str) { 1425 if (str == null) { 1426 return "???"; 1427 } 1428 if (str.trim().isEmpty()) { 1429 return "???"; 1430 } 1431 return str; 1432 } 1433 1434 private void addServiceToList(XmlType xmlType, String serviceKey) { 1435 if (!xmlType.getService().contains(serviceKey)) { 1436 xmlType.setService(xmlType.getService() + ", " + serviceKey); 1437 } 1438 } 1439 1440 private String calcXmlAttribute(JavaField beanField) { 1441 if (beanField == null) { 1442 // TODO: worry about checking for this annotation on the method for non-field based AccessorTypes 1443 return "No"; 1444 } 1445 for (Annotation annotation : beanField.getAnnotations()) { 1446 if (annotation.getType().getJavaClass().getName().equals("XmlAttribute")) { 1447 return "Yes"; 1448 } 1449 } 1450 return "No"; 1451 } 1452 1453 private JavaField findField(JavaClass javaClass, String shortName, 1454 JavaMethod setterMethod) { 1455 JavaField field = findField(javaClass, shortName); 1456 if (field != null) { 1457 return field; 1458 } 1459 if (setterMethod != null) { 1460 String paramName = setterMethod.getParameters()[0].getName(); 1461 if (paramName.equalsIgnoreCase(shortName)) { 1462 return null; 1463 } 1464 return findField(javaClass, paramName); 1465 } 1466 return null; 1467 } 1468 1469 private JavaField findField(JavaClass javaClass, String name) { 1470 if (name == null) { 1471 return null; 1472 } 1473 for (JavaField field : javaClass.getFields()) { 1474 if (field.getName().equalsIgnoreCase(name)) { 1475 return field; 1476 } 1477 // TODO: check for shortNames that already start with is so we don't check for isIsEnrollable 1478 if (field.getName().equals("is" + name)) { 1479 return field; 1480 } 1481 } 1482 JavaClass superClass = javaClass.getSuperJavaClass(); 1483 if (superClass == null) { 1484 return null; 1485 } 1486 return findField(superClass, name); 1487 } 1488 1489 private JavaMethod findGetterMethod(JavaClass msClass, String shortName) { 1490 for (JavaMethod method : msClass.getMethods(true)) { 1491 String methodName = method.getName(); 1492 if (methodName.equalsIgnoreCase("get" + shortName)) { 1493 return method; 1494 } 1495 if (methodName.toLowerCase().startsWith("is")) { 1496 if (methodName.equalsIgnoreCase("is" + shortName)) { 1497 return method; 1498 } 1499 // shortName already has "is" in it 1500 if (methodName.equalsIgnoreCase(shortName)) { 1501 return method; 1502 } 1503 } 1504 // TODO: followup on KimEntityResidencyInfo.getInState 1505 if (methodName.equalsIgnoreCase("getInState") && shortName.equalsIgnoreCase( 1506 "InStateFlag")) { 1507 return method; 1508 } 1509 } 1510 return null; 1511 } 1512 1513 private JavaMethod findSetterMethod(JavaClass msClass, String shortName) { 1514 for (JavaMethod method : msClass.getMethods(true)) { 1515 if (method.getName().equals("set" + shortName)) { 1516 return method; 1517 } 1518 // TODO: check for shortNames that already start with is so we don't check for isIsEnrollable 1519 if (method.getName().equals("setIs" + shortName)) { 1520 return method; 1521 } 1522 // TODO: followup on KimEntityResidencyInfo.getInState 1523 if (method.getName().equals("setInStateFlag") && shortName.equals( 1524 "InState")) { 1525 return method; 1526 } 1527 } 1528 return null; 1529 } 1530 private static final String[] SETTER_METHODS_TO_SKIP = { 1531 // Somebody put "convenience" methods on the validation result info 1532 "ValidationResultInfo.setWarning", 1533 "ValidationResultInfo.setError", 1534 // not on original wiki but still defined as a method but not backed by a field so not in wsdl 1535 "CredentialProgramInfo.setDiplomaTitle", 1536 // synonym for the official of setCredentialType 1537 "CredentialProgramInfo.setType", 1538 // not on original wiki but still defined as a method but not backed by a field so not in wsdl 1539 "CredentialProgramInfo.setHegisCode", 1540 "CredentialProgramInfo.setCip2000Code", 1541 "CredentialProgramInfo.setCip2010Code", 1542 "CredentialProgramInfo.setSelectiveEnrollmentCode", 1543 "CoreProgramInfo.setDiplomaTitle", 1544 // synonym for the official of setCredentialType 1545 // "CoreProgramInfo.setType", 1546 // not on original wiki but still defined as a method but not backed by a field so not in wsdl 1547 "CoreProgramInfo.setHegisCode", 1548 "CoreProgramInfo.setCip2000Code", 1549 "CoreProgramInfo.setCip2010Code", 1550 "CoreProgramInfo.setSelectiveEnrollmentCode", 1551 "WhenConstraint.setValue" 1552 }; 1553 private static final String[] GETTER_METHODS_TO_SKIP = { 1554 // Somebody put "convenience" methods on the validation result info 1555 "ValidationResultInfo.getWarning", 1556 "ValidationResultInfo.getError", 1557 // not on original wiki but still defined as a method but not backed by a field so not in wsdl 1558 "CredentialProgramInfo.getDiplomaTitle", 1559 // synonym for the official of setCredentialType 1560 "CredentialProgramInfo.getType", 1561 // not on original wiki but still defined as a method but not backed by a field so not in wsdl 1562 "CredentialProgramInfo.getHegisCode", 1563 "CredentialProgramInfo.getCip2000Code", 1564 "CredentialProgramInfo.getCip2010Code", 1565 "CredentialProgramInfo.getSelectiveEnrollmentCode", 1566 "CoreProgramInfo.getDiplomaTitle", 1567 // synonym for the official of setCredentialType 1568 // "CoreProgramInfo.setType", 1569 // not on original wiki but still defined as a method but not backed by a field so not in wsdl 1570 "CoreProgramInfo.getHegisCode", 1571 "CoreProgramInfo.getCip2000Code", 1572 "CoreProgramInfo.getCip2010Code", 1573 "CoreProgramInfo.getSelectiveEnrollmentCode", 1574 "WhenConstraint.getValue" 1575 }; 1576 1577 private boolean isSetterMethodToProcess(JavaMethod method, String className) { 1578 if (!method.getName().startsWith("set")) { 1579 return false; 1580 } 1581 if (method.getParameters().length != 1) { 1582 return false; 1583 } 1584 if (method.isPrivate()) { 1585 return false; 1586 } 1587 if (method.isProtected()) { 1588 return false; 1589 } 1590 if (method.isStatic()) { 1591 return false; 1592 } 1593 if (method.getParentClass().getPackageName().startsWith("java")) { 1594 return false; 1595 } 1596 String fullName = className + "." + method.getName(); 1597 for (String skip : SETTER_METHODS_TO_SKIP) { 1598 if (skip.equals(fullName)) { 1599 return false; 1600 } 1601 } 1602 // if (method.getParentClass ().isInterface ()) 1603 // { 1604 // return false; 1605 // } 1606 for (Annotation annotation : method.getAnnotations()) { 1607 if (annotation.getType().getJavaClass().getName().equals("XmlTransient")) { 1608 return false; 1609 } 1610 } 1611 return true; 1612 } 1613 1614 private boolean isGetterMethodToProcess(JavaMethod method, String className) { 1615 if (!method.getName().startsWith("get")) { 1616 if (!method.getName().startsWith("is")) { 1617 return false; 1618 } 1619 } 1620 if (method.getParameters().length != 0) { 1621 return false; 1622 } 1623 if (method.isPrivate()) { 1624 return false; 1625 } 1626 if (method.isProtected()) { 1627 return false; 1628 } 1629 if (method.isStatic()) { 1630 return false; 1631 } 1632 if (method.getParentClass().getPackageName().startsWith("java")) { 1633 return false; 1634 } 1635 String fullName = className + "." + method.getName(); 1636 for (String skip : GETTER_METHODS_TO_SKIP) { 1637 if (skip.equals(fullName)) { 1638 return false; 1639 } 1640 } 1641 // if (method.getParentClass ().isInterface ()) 1642 // { 1643 // return false; 1644 // } 1645 for (Annotation annotation : method.getAnnotations()) { 1646 if (annotation.getType().getJavaClass().getName().equals("XmlTransient")) { 1647 return false; 1648 } 1649 } 1650 return true; 1651 } 1652 1653 private String calcShortNameFromSetter(JavaMethod method) { 1654 return method.getName().substring(3); 1655 } 1656 1657 private String calcShortNameFromGetter(JavaMethod method) { 1658 if (method.getName().startsWith("get")) { 1659 return method.getName().substring(3); 1660 } 1661 if (method.getName().startsWith("is")) { 1662 return method.getName().substring(2); 1663 } 1664 throw new IllegalArgumentException(method.getName() 1665 + " does not start with is or get"); 1666 } 1667 1668 private String calcCardinality(JavaClass mainClass, JavaMethod getterMethod, 1669 JavaMethod setterMethod, JavaField beanField, String shortName) { 1670 if (isReturnACollection(mainClass, getterMethod, setterMethod, beanField, shortName)) { 1671 return "Many"; 1672 } 1673 return "One"; 1674 } 1675 1676 private boolean isReturnACollection(JavaClass mainClass, JavaMethod getterMethod, 1677 JavaMethod setterMethod, JavaField beanField, String shortName) { 1678 if (getterMethod != null) { 1679 return isCollection(getterMethod.getReturnType()); 1680 } 1681 if (beanField != null) { 1682 return isCollection(beanField.getType()); 1683 } 1684 // TODO: check setterMethod 1685 return false; 1686 } 1687 1688 private boolean isCollection(Type type) { 1689 JavaClass javaClass = type.getJavaClass(); 1690 return this.isCollection(javaClass); 1691 } 1692 1693 private boolean isCollection(JavaClass javaClass) { 1694 if (javaClass.getName().equals("LocalKeyList")) { 1695 return true; 1696 } 1697 if (javaClass.getName().equals("MessageGroupKeyList")) { 1698 return true; 1699 } 1700 if (javaClass.getName().equals(List.class.getSimpleName())) { 1701 return true; 1702 } 1703 if (javaClass.getName().equals(ArrayList.class.getSimpleName())) { 1704 return true; 1705 } 1706 if (javaClass.getName().equals(Collection.class.getSimpleName())) { 1707 return true; 1708 } 1709 if (javaClass.getName().equals(Set.class.getSimpleName())) { 1710 return true; 1711 } 1712 return false; 1713 } 1714 1715 private String calcType(JavaClass mainClass, JavaMethod getterMethod, 1716 JavaMethod setterMethod, JavaField beanField, String shortName) { 1717 if (getterMethod != null) { 1718 return calcTypeOfGetterMethodReturn(getterMethod); 1719 } 1720 if (beanField != null) { 1721 Type type = beanField.getType(); 1722 return calcType(type); 1723 } 1724 // TODO: calc type based on the setterMethod 1725 return null; 1726 } 1727 1728 private String calcTypeOfGetterMethodReturn(JavaMethod getterMethod) { 1729 Type type = getterMethod.getReturnType(); 1730 return calcType(type); 1731 } 1732 1733 private String calcType(Type type) { 1734 if (type == null) { 1735 return "void"; 1736 } 1737 if (isCollection(type.getJavaClass())) { 1738 return calcType(calcRealJavaClass(type)) + "List"; 1739 } 1740 return calcType(calcRealJavaClass(type)); 1741 } 1742 1743 private Annotation findJavaAnnotation(String name, JavaClass clazz) { 1744 1745 Annotation[] annotations = clazz.getAnnotations(); 1746 1747 for (Annotation annotation : annotations) { 1748 1749 if (annotation.getType().getJavaClass().getName().equals(name)) { 1750 return annotation; 1751 } 1752 } 1753 return null; 1754 } 1755 private String calcType(JavaClass javaClass) { 1756 1757 if (javaClass.isEnum()) { 1758 1759 if (!JavaClassAnnotationUtils.doesAnnotationExist( 1760 XmlEnum.class.getSimpleName(), javaClass)) { 1761 // a rice or other dependency without the @XmlEnum annotation 1762 // present 1763 if (javaClass.getName().equals("WriteAccess")) { 1764 // rice CommonLookupParam 1765 return "String"; 1766 } else if (javaClass.getName().equals("Widget")) { 1767 // rice CommonLookupParam 1768 return "String"; 1769 } else if (javaClass.getName().equals("Usage")) { 1770 // rice 1771 return "String"; 1772 } else { 1773 // this allows the types to be manually specified 1774 // using the full package.classname format. 1775 return javaClass.getFullyQualifiedName(); 1776 } 1777 1778 } 1779 1780 Class<?>annotationSpecifiedType = JavaClassAnnotationUtils.extractXmlEnumValue(javaClass); 1781 1782 return annotationSpecifiedType.getSimpleName(); 1783 1784 } 1785 // this is messed up instead of list of strings it is an object with a list of strings 1786 if (javaClass.getName().equals(LOCALE_KEY_LIST)) { 1787 return "StringList"; 1788 } 1789 if (javaClass.getName().equals(MESSAGE_GROUP_KEY_LIST)) { 1790 return "StringList"; 1791 } 1792 // TODO: figure out why rice stuff translates like this junk? 1793 if (javaClass.getName().equals("java$util$Map")) { 1794 return "Map<String, String>"; 1795 } 1796 if (javaClass.getName().equals("Map")) { 1797 // TODO: make sure it is in fact a String,String map 1798 return "Map<String, String>"; 1799 } 1800 return javaClass.getName(); 1801 } 1802 1803 private JavaClass calcRealJavaClassOfGetterReturn(JavaMethod getterMethod) { 1804 if (getterMethod == null) { 1805 return null; 1806 } 1807 Type type = getterMethod.getReturnType(); 1808 return this.calcRealJavaClass(type); 1809 } 1810 1811 private JavaClass calcRealJavaClass(Type type) { 1812 if (type == null) { 1813 return null; 1814 } 1815 JavaClass javaClass = type.getJavaClass(); 1816 if (javaClass.getName().equals(LOCALE_KEY_LIST)) { 1817 return STRING_JAVA_CLASS; 1818 } 1819 if (javaClass.getName().equals(MESSAGE_GROUP_KEY_LIST)) { 1820 return STRING_JAVA_CLASS; 1821 } 1822 if (!this.isCollection(javaClass)) { 1823 return javaClass; 1824 } 1825 1826 // for (Type t : type.getActualTypeArguments ()) 1827 // { 1828 // System.out.println ("ServiceContractModelQDoxLoader: type arguments = " 1829 // + t.toString ()); 1830 // } 1831 1832 Type[]collectionTypeArguments = type.getActualTypeArguments(); 1833 1834 if (collectionTypeArguments == null) 1835 return new JavaClass (Object.class.getName()); 1836 else 1837 return collectionTypeArguments[0].getJavaClass(); 1838 } 1839 1840 private boolean isComplex(JavaClass javaClass) { 1841 if (javaClass.getName().equals ("void")) { 1842 return false; 1843 } 1844 if (javaClass.isEnum()) { 1845 return false; 1846 } 1847 if (javaClass.getName().equals(String.class.getSimpleName())) { 1848 return false; 1849 } 1850 if (javaClass.getName().equals(Integer.class.getSimpleName())) { 1851 return false; 1852 } 1853 if (javaClass.getName().equals(Date.class.getSimpleName())) { 1854 return false; 1855 } 1856 if (javaClass.getName().equals(Long.class.getSimpleName())) { 1857 return false; 1858 } 1859 if (javaClass.getName().equals(Boolean.class.getSimpleName())) { 1860 return false; 1861 } 1862 if (javaClass.getName().equals(Double.class.getSimpleName())) { 1863 return false; 1864 } 1865 if (javaClass.getName().equals(Float.class.getSimpleName())) { 1866 return false; 1867 } 1868 if (javaClass.getName().equals(int.class.getSimpleName())) { 1869 return false; 1870 } 1871 if (javaClass.getName().equals(long.class.getSimpleName())) { 1872 return false; 1873 } 1874 if (javaClass.getName().equals(boolean.class.getSimpleName())) { 1875 return false; 1876 } 1877 if (javaClass.getName().equals(double.class.getSimpleName())) { 1878 return false; 1879 } 1880 if (javaClass.getName().equals(float.class.getSimpleName())) { 1881 return false; 1882 } 1883 if (javaClass.getName().equals(Map.class.getSimpleName())) { 1884 return false; 1885 } 1886 1887 if (javaClass.getName().equals(String.class.getName())) { 1888 return false; 1889 } 1890 if (javaClass.getName().equals(Integer.class.getName())) { 1891 return false; 1892 } 1893 if (javaClass.getName().equals(Date.class.getName())) { 1894 return false; 1895 } 1896 if (javaClass.getName().equals(Long.class.getName())) { 1897 return false; 1898 } 1899 if (javaClass.getName().equals(Boolean.class.getName())) { 1900 return false; 1901 } 1902 if (javaClass.getName().equals(Double.class.getName())) { 1903 return false; 1904 } 1905 if (javaClass.getName().equals(Float.class.getName())) { 1906 return false; 1907 } 1908 if (javaClass.getName().equals(int.class.getName())) { 1909 return false; 1910 } 1911 if (javaClass.getName().equals(long.class.getName())) { 1912 return false; 1913 } 1914 if (javaClass.getName().equals(boolean.class.getName())) { 1915 return false; 1916 } 1917 if (javaClass.getName().equals(double.class.getName())) { 1918 return false; 1919 } 1920 if (javaClass.getName().equals(float.class.getName())) { 1921 return false; 1922 } 1923 if (javaClass.getName().equals(BigDecimal.class.getSimpleName())) { 1924 return false; 1925 } 1926 if (javaClass.getName().equals(Map.class.getName())) { 1927 return false; 1928 } 1929 if (javaClass.getName().equals(LOCALE_KEY_LIST)) { 1930 return false; 1931 } 1932 if (javaClass.getName().equals(MESSAGE_GROUP_KEY_LIST)) { 1933 return false; 1934 } 1935 if (javaClass.getName().equals("java$util$Map")) { 1936 return false; 1937 } 1938 return true; 1939 } 1940 1941 @Override 1942 public String toString() { 1943 return "ServiceContractModelQDoxLoader{" + 1944 "sourceDirectories=" + sourceDirectories + 1945 ", services=" + services + 1946 ", serviceMethods=" + serviceMethods + 1947 ", xmlTypeMap=" + xmlTypeMap + 1948 ", messageStructures=" + messageStructures + 1949 ", validateKualiStudent=" + validateKualiStudent + 1950 '}'; 1951 } 1952 }