1 /*
   2  * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package com.sun.tools.internal.ws.processor.modeler.annotation;
  27 
  28 import com.sun.codemodel.internal.CodeWriter;
  29 import com.sun.codemodel.internal.JAnnotationArrayMember;
  30 import com.sun.codemodel.internal.JAnnotationUse;
  31 import com.sun.codemodel.internal.JBlock;
  32 import com.sun.codemodel.internal.JCodeModel;
  33 import com.sun.codemodel.internal.JCommentPart;
  34 import com.sun.codemodel.internal.JDefinedClass;
  35 import com.sun.codemodel.internal.JDocComment;
  36 import com.sun.codemodel.internal.JExpr;
  37 import com.sun.codemodel.internal.JFieldVar;
  38 import com.sun.codemodel.internal.JMethod;
  39 import com.sun.codemodel.internal.JMod;
  40 import com.sun.codemodel.internal.JType;
  41 import com.sun.codemodel.internal.JVar;
  42 import com.sun.codemodel.internal.writer.ProgressCodeWriter;
  43 import com.sun.tools.internal.jxc.ap.InlineAnnotationReaderImpl;
  44 import com.sun.tools.internal.jxc.model.nav.ApNavigator;
  45 import com.sun.tools.internal.ws.ToolVersion;
  46 import com.sun.tools.internal.ws.processor.generator.GeneratorBase;
  47 import com.sun.tools.internal.ws.processor.generator.GeneratorConstants;
  48 import com.sun.tools.internal.ws.processor.generator.Names;
  49 import com.sun.tools.internal.ws.processor.modeler.ModelerException;
  50 import com.sun.tools.internal.ws.processor.util.DirectoryUtil;
  51 import com.sun.tools.internal.ws.resources.WebserviceapMessages;
  52 import com.sun.tools.internal.ws.util.ClassNameInfo;
  53 import com.sun.tools.internal.ws.wscompile.FilerCodeWriter;
  54 import com.sun.tools.internal.ws.wscompile.WsgenOptions;
  55 import com.sun.tools.internal.ws.wsdl.document.soap.SOAPStyle;
  56 import com.sun.xml.internal.bind.v2.model.annotation.AnnotationReader;
  57 import com.sun.xml.internal.bind.v2.model.nav.Navigator;
  58 import com.sun.xml.internal.ws.model.AbstractWrapperBeanGenerator;
  59 import com.sun.xml.internal.ws.spi.db.BindingHelper;
  60 import com.sun.xml.internal.ws.util.StringUtils;
  61 
  62 import javax.jws.Oneway;
  63 import javax.jws.WebMethod;
  64 import javax.jws.WebService;
  65 import javax.lang.model.element.ExecutableElement;
  66 import javax.lang.model.element.Name;
  67 import javax.lang.model.element.TypeElement;
  68 import javax.lang.model.type.DeclaredType;
  69 import javax.lang.model.type.MirroredTypeException;
  70 import javax.lang.model.type.TypeKind;
  71 import javax.lang.model.type.TypeMirror;
  72 import javax.xml.bind.annotation.XmlAccessType;
  73 import javax.xml.bind.annotation.XmlAccessorType;
  74 import javax.xml.bind.annotation.XmlAttachmentRef;
  75 import javax.xml.bind.annotation.XmlElement;
  76 import javax.xml.bind.annotation.XmlList;
  77 import javax.xml.bind.annotation.XmlMimeType;
  78 import javax.xml.bind.annotation.XmlRootElement;
  79 import javax.xml.bind.annotation.XmlType;
  80 import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
  81 import javax.xml.namespace.QName;
  82 import javax.xml.ws.RequestWrapper;
  83 import javax.xml.ws.ResponseWrapper;
  84 import javax.xml.ws.WebFault;
  85 import javax.xml.ws.WebServiceException;
  86 import java.io.File;
  87 import java.io.IOException;
  88 import java.lang.annotation.Annotation;
  89 import java.util.Collection;
  90 import java.util.HashSet;
  91 import java.util.List;
  92 import java.util.Set;
  93 
  94 import static com.sun.codemodel.internal.ClassType.CLASS;
  95 import static com.sun.tools.internal.ws.processor.modeler.annotation.WebServiceConstants.BEAN;
  96 import static com.sun.tools.internal.ws.processor.modeler.annotation.WebServiceConstants.FAULT_INFO;
  97 import static com.sun.tools.internal.ws.processor.modeler.annotation.WebServiceConstants.JAXWS_PACKAGE_PD;
  98 import static com.sun.tools.internal.ws.processor.modeler.annotation.WebServiceConstants.PD_JAXWS_PACKAGE_PD;
  99 import static com.sun.tools.internal.ws.processor.modeler.annotation.WebServiceConstants.RESPONSE;
 100 
 101 /**
 102  * This class generates the request/response and Exception Beans
 103  * used by the JAX-WS runtime.
 104  *
 105  * @author  WS Development Team
 106  */
 107 public class WebServiceWrapperGenerator extends WebServiceVisitor {
 108     private Set<String> wrapperNames;
 109     private Set<String> processedExceptions;
 110     private JCodeModel cm;
 111     private final MakeSafeTypeVisitor makeSafeVisitor;
 112 
 113     private static final FieldFactory FIELD_FACTORY = new FieldFactory();
 114 
 115     private final AbstractWrapperBeanGenerator ap_generator =
 116             new ApWrapperBeanGenerator(InlineAnnotationReaderImpl.theInstance,
 117                     new ApNavigator(builder.getProcessingEnvironment()), FIELD_FACTORY);
 118 
 119     private final class ApWrapperBeanGenerator extends AbstractWrapperBeanGenerator<TypeMirror, TypeElement, ExecutableElement, MemberInfo> {
 120 
 121         protected ApWrapperBeanGenerator(
 122                 AnnotationReader<TypeMirror, TypeElement, ?, ExecutableElement> annReader,
 123                 Navigator<TypeMirror, TypeElement, ?, ExecutableElement> nav, BeanMemberFactory<TypeMirror, MemberInfo> beanMemberFactory) {
 124             super(annReader, nav, beanMemberFactory);
 125         }
 126 
 127         @Override
 128         protected TypeMirror getSafeType(TypeMirror type) {
 129             return WebServiceWrapperGenerator.this.getSafeType(type);
 130         }
 131 
 132         @Override
 133         protected TypeMirror getHolderValueType(TypeMirror paramType) {
 134             return builder.getHolderValueType(paramType);
 135         }
 136 
 137         @Override
 138         protected boolean isVoidType(TypeMirror type) {
 139             return type != null && type.getKind().equals(TypeKind.VOID);
 140         }
 141 
 142     }
 143 
 144     private static final class FieldFactory implements AbstractWrapperBeanGenerator.BeanMemberFactory<TypeMirror, MemberInfo> {
 145 
 146         @Override
 147         public MemberInfo createWrapperBeanMember(TypeMirror paramType,
 148                                                   String paramName, List<Annotation> jaxb) {
 149             return new MemberInfo(paramType, paramName, jaxb);
 150         }
 151     }
 152 
 153     public WebServiceWrapperGenerator(ModelBuilder builder, AnnotationProcessorContext context) {
 154         super(builder, context);
 155         makeSafeVisitor = new MakeSafeTypeVisitor(builder.getProcessingEnvironment());
 156     }
 157 
 158     @Override
 159     protected void processWebService(WebService webService, TypeElement d) {
 160         cm = new JCodeModel();
 161         wrapperNames = new HashSet<String>();
 162         processedExceptions = new HashSet<String>();
 163     }
 164 
 165     @Override
 166     protected void postProcessWebService(WebService webService, TypeElement d) {
 167         super.postProcessWebService(webService, d);
 168         doPostProcessWebService(webService, d);
 169     }
 170 
 171     @SuppressWarnings("CallToThreadDumpStack")
 172     protected void doPostProcessWebService(WebService webService, TypeElement d) {
 173         if (cm != null) {
 174             File sourceDir = builder.getSourceDir();
 175             assert(sourceDir != null);
 176             WsgenOptions options = builder.getOptions();
 177             try {
 178                 CodeWriter cw = new FilerCodeWriter(sourceDir, options);
 179                 if(options.verbose)
 180                     cw = new ProgressCodeWriter(cw, System.out);
 181                 cm.build(cw);
 182             } catch (IOException e) {
 183                 e.printStackTrace();
 184             }
 185         }
 186     }
 187 
 188     @Override
 189     protected void processMethod(ExecutableElement method, WebMethod webMethod) {
 190         builder.log("WrapperGen - method: "+method);
 191         builder.log("method.getDeclaringType(): " + method.asType());
 192         if (wrapped && soapStyle.equals(SOAPStyle.DOCUMENT)) {
 193             generateWrappers(method, webMethod);
 194         }
 195         generateExceptionBeans(method);
 196     }
 197 
 198     private boolean generateExceptionBeans(ExecutableElement method) {
 199         String beanPackage = packageName + PD_JAXWS_PACKAGE_PD.getValue();
 200         if (packageName.length() == 0)
 201             beanPackage = JAXWS_PACKAGE_PD.getValue();
 202         boolean beanGenerated = false;
 203         for (TypeMirror thrownType : method.getThrownTypes()) {
 204             TypeElement typeDecl = (TypeElement) ((DeclaredType) thrownType).asElement();
 205             if (typeDecl == null) {
 206                 builder.processError(WebserviceapMessages.WEBSERVICEAP_COULD_NOT_FIND_TYPEDECL(
 207                         thrownType.toString(), context.getRound()));
 208                 return false;
 209             }
 210             boolean tmp = generateExceptionBean(typeDecl, beanPackage);
 211             beanGenerated = beanGenerated || tmp;
 212         }
 213         return beanGenerated;
 214     }
 215 
 216     private boolean duplicateName(String name) {
 217         for (String str : wrapperNames) {
 218             if (str.equalsIgnoreCase(name))
 219         return true;
 220         }
 221         wrapperNames.add(name);
 222     return false;
 223     }
 224 
 225     private boolean generateWrappers(ExecutableElement method, WebMethod webMethod) {
 226         boolean isOneway = method.getAnnotation(Oneway.class) != null;
 227         String beanPackage = packageName + PD_JAXWS_PACKAGE_PD.getValue();
 228         if (packageName.length() == 0)
 229             beanPackage = JAXWS_PACKAGE_PD.getValue();
 230         Name methodName = method.getSimpleName();
 231         String operationName = builder.getOperationName(methodName);
 232         operationName = webMethod != null && webMethod.operationName().length() > 0 ?
 233                 webMethod.operationName() : operationName;
 234         String reqName = operationName;
 235         String resName = operationName + WebServiceConstants.RESPONSE.getValue();
 236         String reqNamespace = typeNamespace;
 237         String resNamespace = typeNamespace;
 238 
 239         String requestClassName = beanPackage + StringUtils.capitalize(method.getSimpleName().toString());
 240         RequestWrapper reqWrapper = method.getAnnotation(RequestWrapper.class);
 241         if (reqWrapper != null) {
 242             if (reqWrapper.className().length() > 0)
 243                 requestClassName = reqWrapper.className();
 244             if (reqWrapper.localName().length() > 0)
 245                 reqName = reqWrapper.localName();
 246             if (reqWrapper.targetNamespace().length() > 0)
 247                 reqNamespace = reqWrapper.targetNamespace();
 248         }
 249         builder.log("requestWrapper: "+requestClassName);
 250 ///// fix for wsgen CR 6442344
 251         File file = new File(DirectoryUtil.getOutputDirectoryFor(requestClassName, builder.getSourceDir()),
 252                 Names.stripQualifier(requestClassName) + GeneratorConstants.JAVA_SRC_SUFFIX.getValue());
 253         builder.getOptions().addGeneratedFile(file);
 254 //////////
 255         boolean canOverwriteRequest = builder.canOverWriteClass(requestClassName);
 256         if (!canOverwriteRequest) {
 257             builder.log("Class " + requestClassName + " exists. Not overwriting.");
 258         }
 259         if (duplicateName(requestClassName) && canOverwriteRequest) {
 260             builder.processError(WebserviceapMessages.WEBSERVICEAP_METHOD_REQUEST_WRAPPER_BEAN_NAME_NOT_UNIQUE(
 261                     typeElement.getQualifiedName(), method.toString()));
 262         }
 263 
 264         String responseClassName = null;
 265         boolean canOverwriteResponse = canOverwriteRequest;
 266         if (!isOneway) {
 267             responseClassName = beanPackage+StringUtils.capitalize(method.getSimpleName().toString())+RESPONSE.getValue();
 268             ResponseWrapper resWrapper = method.getAnnotation(ResponseWrapper.class);
 269             if(resWrapper != null) {
 270                 if (resWrapper.className().length() > 0)
 271                     responseClassName = resWrapper.className();
 272                 if (resWrapper.localName().length() > 0)
 273                     resName = resWrapper.localName();
 274                 if (resWrapper.targetNamespace().length() > 0)
 275                     resNamespace = resWrapper.targetNamespace();
 276             }
 277             canOverwriteResponse = builder.canOverWriteClass(responseClassName);
 278             if (!canOverwriteResponse) {
 279                 builder.log("Class " + responseClassName + " exists. Not overwriting.");
 280             }
 281             if (duplicateName(responseClassName) && canOverwriteResponse) {
 282                 builder.processError(WebserviceapMessages.WEBSERVICEAP_METHOD_RESPONSE_WRAPPER_BEAN_NAME_NOT_UNIQUE(
 283                         typeElement.getQualifiedName(), method.toString()));
 284             }
 285             file = new File(DirectoryUtil.getOutputDirectoryFor(responseClassName, builder.getSourceDir()),
 286                     Names.stripQualifier(responseClassName) + GeneratorConstants.JAVA_SRC_SUFFIX.getValue());
 287             builder.getOptions().addGeneratedFile(file);
 288         }
 289         //ArrayList<MemberInfo> reqMembers = new ArrayList<MemberInfo>();
 290         //ArrayList<MemberInfo> resMembers = new ArrayList<MemberInfo>();
 291         WrapperInfo reqWrapperInfo = new WrapperInfo(requestClassName);
 292         //reqWrapperInfo.setMembers(reqMembers);
 293         WrapperInfo resWrapperInfo = null;
 294         if (!isOneway) {
 295             resWrapperInfo = new WrapperInfo(responseClassName);
 296             //resWrapperInfo.setMembers(resMembers);
 297         }
 298         seiContext.setReqWrapperOperation(method, reqWrapperInfo);
 299         if (!isOneway)
 300             seiContext.setResWrapperOperation(method, resWrapperInfo);
 301         try {
 302             if (!canOverwriteRequest && !canOverwriteResponse) {
 303                 return false;
 304             }
 305 
 306             JDefinedClass reqCls = null;
 307             if (canOverwriteRequest) {
 308                 reqCls = getCMClass(requestClassName, CLASS);
 309             }
 310 
 311             JDefinedClass resCls = null;
 312             if (!isOneway && canOverwriteResponse) {
 313                 resCls = getCMClass(responseClassName, CLASS);
 314             }
 315 
 316             // XMLElement Declarations
 317             writeXmlElementDeclaration(reqCls, reqName,reqNamespace);
 318             writeXmlElementDeclaration(resCls, resName, resNamespace);
 319 
 320             List<MemberInfo> reqMembers = ap_generator.collectRequestBeanMembers(method);
 321             List<MemberInfo> resMembers = ap_generator.collectResponseBeanMembers(method);
 322 
 323             // XmlType
 324             writeXmlTypeDeclaration(reqCls, reqName, reqNamespace, reqMembers);
 325             writeXmlTypeDeclaration(resCls, resName, resNamespace, resMembers);
 326 
 327             // class members
 328             writeMembers(reqCls, reqMembers);
 329             writeMembers(resCls, resMembers);
 330 
 331         } catch (Exception e) {
 332             throw new ModelerException("modeler.nestedGeneratorError",e);
 333         }
 334         return true;
 335     }
 336 
 337 //    private List<Annotation> collectJAXBAnnotations(Declaration decl) {
 338 //        List<Annotation> jaxbAnnotation = new ArrayList<Annotation>();
 339 //        for(Class jaxbClass : jaxbAnns) {
 340 //            Annotation ann = decl.getAnnotation(jaxbClass);
 341 //            if (ann != null) {
 342 //                jaxbAnnotation.add(ann);
 343 //            }
 344 //        }
 345 //        return jaxbAnnotation;
 346 //    }
 347 
 348     private TypeMirror getSafeType(TypeMirror type) {
 349         return makeSafeVisitor.visit(type, builder.getProcessingEnvironment().getTypeUtils());
 350     }
 351 
 352     private JType getType(TypeMirror typeMirror) {
 353         String type = typeMirror.toString();
 354         try {
 355 //            System.out.println("typeName: "+typeName);
 356             return cm.parseType(type);
 357 //            System.out.println("type: "+type);
 358         } catch (ClassNotFoundException e) {
 359             return cm.ref(type);
 360         }
 361     }
 362 
 363     private void writeMembers(JDefinedClass cls, Collection<MemberInfo> members) {
 364         if (cls == null)
 365             return;
 366         for (MemberInfo memInfo : members) {
 367             JType type = getType(memInfo.getParamType());
 368             JFieldVar field = cls.field(JMod.PRIVATE, type, memInfo.getParamName());
 369             annotateParameterWithJaxbAnnotations(memInfo, field);
 370         }
 371         for (MemberInfo memInfo : members) {
 372             writeMember(cls, memInfo.getParamType(),
 373                     memInfo.getParamName());
 374         }
 375     }
 376 
 377     private void annotateParameterWithJaxbAnnotations(MemberInfo memInfo, JFieldVar field) {
 378         List<Annotation> jaxbAnnotations = memInfo.getJaxbAnnotations();
 379         for(Annotation ann : jaxbAnnotations) {
 380             if (ann instanceof XmlMimeType) {
 381                 JAnnotationUse jaxbAnn = field.annotate(XmlMimeType.class);
 382                 jaxbAnn.param("value", ((XmlMimeType)ann).value());
 383             } else if (ann instanceof XmlJavaTypeAdapter) {
 384                 JAnnotationUse jaxbAnn = field.annotate(XmlJavaTypeAdapter.class);
 385                 XmlJavaTypeAdapter ja = (XmlJavaTypeAdapter) ann;
 386                 try {
 387                     ja.value();
 388                     throw new AssertionError();
 389                 } catch (MirroredTypeException e) {
 390                     jaxbAnn.param("value",getType(e.getTypeMirror()));
 391                 }
 392                 // XmlJavaTypeAdapter.type() is for package only. No need to copy.
 393             } else if (ann instanceof XmlAttachmentRef) {
 394                 field.annotate(XmlAttachmentRef.class);
 395             } else if (ann instanceof XmlList){
 396                 field.annotate(XmlList.class);
 397             } else if (ann instanceof XmlElement) {
 398                 XmlElement elemAnn = (XmlElement)ann;
 399                 JAnnotationUse jAnn = field.annotate(XmlElement.class);
 400                 jAnn.param("name", elemAnn.name());
 401                 jAnn.param("namespace", elemAnn.namespace());
 402                 if (elemAnn.nillable()) {
 403                     jAnn.param("nillable", true);
 404                 }
 405                 if (elemAnn.required()) {
 406                      jAnn.param("required", true);
 407                 }
 408             } else {
 409                 throw new WebServiceException("SEI Parameter cannot have this JAXB annotation: " + ann);
 410             }
 411         }
 412     }
 413 
 414     protected JDefinedClass getCMClass(String className, com.sun.codemodel.internal.ClassType type) {
 415         JDefinedClass cls;
 416         try {
 417             cls = cm._class(className, type);
 418         } catch (com.sun.codemodel.internal.JClassAlreadyExistsException e){
 419             cls = cm._getClass(className);
 420         }
 421         return cls;
 422     }
 423 
 424     private boolean generateExceptionBean(TypeElement thrownDecl, String beanPackage) {
 425         if (!builder.isServiceException(thrownDecl.asType()))
 426             return false;
 427 
 428         String exceptionName = ClassNameInfo.getName(thrownDecl.getQualifiedName().toString());
 429         if (processedExceptions.contains(exceptionName))
 430             return false;
 431         processedExceptions.add(exceptionName);
 432         WebFault webFault = thrownDecl.getAnnotation(WebFault.class);
 433         String className = beanPackage+ exceptionName + BEAN.getValue();
 434 
 435         Collection<MemberInfo> members = ap_generator.collectExceptionBeanMembers(thrownDecl);
 436         boolean isWSDLException = isWSDLException(members, thrownDecl);
 437         String namespace = typeNamespace;
 438         String name = exceptionName;
 439         FaultInfo faultInfo;
 440         if (isWSDLException) {
 441             TypeMirror beanType =  getFaultInfoMember(members).getParamType();
 442             faultInfo = new FaultInfo(TypeMonikerFactory.getTypeMoniker(beanType), true);
 443             namespace = webFault.targetNamespace().length()>0 ?
 444                                webFault.targetNamespace() : namespace;
 445             name = webFault.name().length()>0 ?
 446                           webFault.name() : name;
 447             faultInfo.setElementName(new QName(namespace, name));
 448             seiContext.addExceptionBeanEntry(thrownDecl.getQualifiedName(), faultInfo, builder);
 449             return false;
 450         }
 451         if (webFault != null) {
 452             namespace = webFault.targetNamespace().length()>0 ?
 453                         webFault.targetNamespace() : namespace;
 454             name = webFault.name().length()>0 ?
 455                    webFault.name() : name;
 456             className = webFault.faultBean().length()>0 ?
 457                         webFault.faultBean() : className;
 458 
 459         }
 460         JDefinedClass cls = getCMClass(className, CLASS);
 461         faultInfo = new FaultInfo(className, false);
 462 
 463         if (duplicateName(className)) {
 464             builder.processError(WebserviceapMessages.WEBSERVICEAP_METHOD_EXCEPTION_BEAN_NAME_NOT_UNIQUE(
 465                     typeElement.getQualifiedName(), thrownDecl.getQualifiedName()));
 466         }
 467 
 468         boolean canOverWriteBean = builder.canOverWriteClass(className);
 469         if (!canOverWriteBean) {
 470             builder.log("Class " + className + " exists. Not overwriting.");
 471             seiContext.addExceptionBeanEntry(thrownDecl.getQualifiedName(), faultInfo, builder);
 472             return false;
 473         }
 474         if (seiContext.getExceptionBeanName(thrownDecl.getQualifiedName()) != null)
 475             return false;
 476 
 477         //write class comment - JAXWS warning
 478         JDocComment comment = cls.javadoc();
 479         for (String doc : GeneratorBase.getJAXWSClassComment(ToolVersion.VERSION.MAJOR_VERSION)) {
 480             comment.add(doc);
 481         }
 482 
 483         // XmlElement Declarations
 484         writeXmlElementDeclaration(cls, name, namespace);
 485 
 486         // XmlType Declaration
 487         //members = sortMembers(members);
 488         XmlType xmlType = thrownDecl.getAnnotation(XmlType.class);
 489         String xmlTypeName = (xmlType != null && !xmlType.name().equals("##default")) ? xmlType.name() : exceptionName;
 490         String xmlTypeNamespace = (xmlType != null && !xmlType.namespace().equals("##default")) ? xmlType.namespace() : typeNamespace;
 491         writeXmlTypeDeclaration(cls, xmlTypeName, xmlTypeNamespace, members);
 492 
 493         writeMembers(cls, members);
 494 
 495         seiContext.addExceptionBeanEntry(thrownDecl.getQualifiedName(), faultInfo, builder);
 496         return true;
 497     }
 498 
 499     protected boolean isWSDLException(Collection<MemberInfo> members, TypeElement thrownDecl) {
 500         WebFault webFault = thrownDecl.getAnnotation(WebFault.class);
 501         return webFault != null && members.size() == 2 && getFaultInfoMember(members) != null;
 502     }
 503 
 504     /*
 505      * Returns the corresponding MemberInfo for getFaultInfo()
 506      * method of an exception. Returns null, if that method is not there.
 507      */
 508     private MemberInfo getFaultInfoMember(Collection<MemberInfo> members) {
 509         for(MemberInfo member : members) {
 510             if (member.getParamName().equals(FAULT_INFO.getValue())) {
 511                 return member;
 512             }
 513         }
 514         return null;
 515     }
 516 
 517     private void writeXmlElementDeclaration(JDefinedClass cls, String elementName, String namespaceUri) {
 518 
 519        if (cls == null)
 520             return;
 521         JAnnotationUse xmlRootElementAnn = cls.annotate(XmlRootElement.class);
 522         xmlRootElementAnn.param("name", elementName);
 523         if (namespaceUri.length() > 0) {
 524             xmlRootElementAnn.param("namespace", namespaceUri);
 525         }
 526         JAnnotationUse xmlAccessorTypeAnn = cls.annotate(cm.ref(XmlAccessorType.class));
 527         xmlAccessorTypeAnn.param("value", XmlAccessType.FIELD);
 528     }
 529 
 530     private void writeXmlTypeDeclaration(JDefinedClass cls, String typeName, String namespaceUri,
 531                                          Collection<MemberInfo> members) {
 532         if (cls == null)
 533             return;
 534         JAnnotationUse xmlTypeAnn = cls.annotate(cm.ref(XmlType.class));
 535         xmlTypeAnn.param("name", typeName);
 536         xmlTypeAnn.param("namespace", namespaceUri);
 537         if (members.size() > 1) {
 538             JAnnotationArrayMember paramArray = xmlTypeAnn.paramArray("propOrder");
 539             for (MemberInfo memInfo : members) {
 540                 paramArray.param(memInfo.getParamName());
 541             }
 542         }
 543     }
 544 
 545     private void writeMember(JDefinedClass cls, TypeMirror paramType,
 546                              String paramName) {
 547 
 548         if (cls == null)
 549             return;
 550 
 551         String accessorName =BindingHelper.mangleNameToPropertyName(paramName);
 552         String getterPrefix = paramType.toString().equals("boolean")? "is" : "get";
 553         JType propType = getType(paramType);
 554         JMethod m = cls.method(JMod.PUBLIC, propType, getterPrefix+ accessorName);
 555         JDocComment methodDoc = m.javadoc();
 556         JCommentPart ret = methodDoc.addReturn();
 557         ret.add("returns "+propType.name());
 558         JBlock body = m.body();
 559         body._return( JExpr._this().ref(paramName) );
 560 
 561         m = cls.method(JMod.PUBLIC, cm.VOID, "set"+accessorName);
 562         JVar param = m.param(propType, paramName);
 563         methodDoc = m.javadoc();
 564         JCommentPart part = methodDoc.addParam(paramName);
 565         part.add("the value for the "+ paramName+" property");
 566         body = m.body();
 567         body.assign( JExpr._this().ref(paramName), param );
 568     }
 569 }