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