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