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