/* * The contents of this file are subject to the terms * of the Common Development and Distribution License * (the "License"). You may not use this file except * in compliance with the License. * * You can obtain a copy of the license at * http://www.opensource.org/licenses/cddl1.php * See the License for the specific language governing * permissions and limitations under the License. */ /* * ResourceClassGenerator.java * * Created on June 1, 2006, 5:23 PM * */ package org.jvnet.ws.wadl2java; import com.sun.codemodel.JBlock; import com.sun.codemodel.JClass; import com.sun.codemodel.JClassAlreadyExistsException; import com.sun.codemodel.JCodeModel; import com.sun.codemodel.JDefinedClass; import com.sun.codemodel.JDocComment; import com.sun.codemodel.JExpr; import com.sun.codemodel.JExpression; import com.sun.codemodel.JFieldRef; import com.sun.codemodel.JFieldVar; import com.sun.codemodel.JInvocation; import com.sun.codemodel.JMethod; import com.sun.codemodel.JMod; import com.sun.codemodel.JPackage; import com.sun.codemodel.JType; import com.sun.codemodel.JVar; import org.jvnet.ws.wadl.*; import org.jvnet.ws.wadl.util.DSDispatcher; import org.jvnet.ws.wadl.util.JAXBDispatcher; import org.jvnet.ws.wadl.util.UriBuilder; import org.jvnet.ws.wadl2java.ast.FaultNode; import org.jvnet.ws.wadl2java.ast.MethodNode; import org.jvnet.ws.wadl2java.ast.PathSegment; import org.jvnet.ws.wadl2java.ast.RepresentationNode; import org.jvnet.ws.wadl2java.ast.ResourceNode; import org.jvnet.ws.wadl2java.ast.ResourceTypeNode; import com.sun.tools.xjc.api.Mapping; import com.sun.tools.xjc.api.S2JJAXBModel; import java.io.IOException; import java.net.MalformedURLException; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBException; import javax.xml.namespace.QName; /** * Generator class for nested static classes used to represent web resources * @author mh124079 */ public class ResourceClassGenerator { private ResourceNode resource; private JPackage pkg; private S2JJAXBModel s2jModel; private JCodeModel codeModel; private JFieldVar $jaxbDispatcher; private JFieldVar $dsDispatcher; private JFieldVar $uriBuilder; private JFieldVar $jaxbContext; private JFieldVar $templateMatrixParamValMap; private JDefinedClass $class = null; private JavaDocUtil javaDoc; private String generatedPackages; /** * Creates a new instance of ResourceClassGenerator * @param javaDoc a JavaDocUtil instance for use when generating documentation * @param s2jModel the schema2java model to use for element to class mapping lookups * @param codeModel code model instance to use when generating code * @param pkg package for new classes * @param resource the resource element for which to generate a class */ public ResourceClassGenerator(S2JJAXBModel s2jModel, JCodeModel codeModel, JPackage pkg, String generatedPackages, JavaDocUtil javaDoc, ResourceNode resource) { this.resource = resource; this.codeModel = codeModel; this.javaDoc = javaDoc; this.s2jModel = s2jModel; this.pkg = pkg; this.generatedPackages = generatedPackages; } /** * Creates a new instance of ResourceClassGenerator * @param javaDoc a JavaDocUtil instance for use when generating documentation * @param s2jModel the schema2java model to use for element to class mapping lookups * @param codeModel code model instance to use when generating code * @param pkg package for new classes * @param clazz the existing class */ public ResourceClassGenerator(S2JJAXBModel s2jModel, JCodeModel codeModel, JPackage pkg, String generatedPackages, JavaDocUtil javaDoc, JDefinedClass clazz) { this.resource = null; this.codeModel = codeModel; this.javaDoc = javaDoc; this.s2jModel = s2jModel; this.pkg = pkg; this.$class = clazz; this.generatedPackages = generatedPackages; } /** * Get the class for which methods will be generated * @return the class or null if no class has yet been generated. */ public JDefinedClass getGeneratedClass() { return $class; } /** * Generate a static member class that represents a WADL resource. * @param parentClass the parent class for the generated class * @return the generated class * @throws com.sun.codemodel.JClassAlreadyExistsException if a class with * the same name already exists */ public JDefinedClass generateClass(JDefinedClass parentClass) throws JClassAlreadyExistsException { JDefinedClass $impl = parentClass._class(JMod.PUBLIC | JMod.STATIC, resource.getClassName()); for (ResourceTypeNode t: resource.getResourceTypes()) { $impl._implements(t.getGeneratedInterface()); } javaDoc.generateClassDoc(resource, $impl); $jaxbDispatcher = $impl.field(JMod.PRIVATE, JAXBDispatcher.class, "_jaxbDispatcher"); $dsDispatcher = $impl.field(JMod.PRIVATE, DSDispatcher.class, "_dsDispatcher"); $uriBuilder = $impl.field(JMod.PRIVATE, UriBuilder.class, "_uriBuilder"); $jaxbContext = $impl.field(JMod.PRIVATE, JAXBContext.class, "_jc"); JClass mapOfStringObject = codeModel.ref(HashMap.class).narrow(String.class, Object.class); $templateMatrixParamValMap = $impl.field(JMod.PRIVATE, mapOfStringObject, "_templateAndMatrixParameterValues"); // generate constructor with parameters for each WADL defined path parameter JMethod $ctor = $impl.constructor(JMod.PUBLIC); JDocComment jdoc = $ctor.javadoc(); jdoc.append(Wadl2JavaMessages.CREATE_INSTANCE()); for (PathSegment segment: resource.getPathSegments()) { for (Param p: segment.getTemplateParameters()) { $ctor.param(GeneratorUtil.getJavaType(p, codeModel, $impl, javaDoc), GeneratorUtil.makeParamName(p.getName())); javaDoc.generateParamDoc(p, $ctor); generateBeanProperty($impl, p, false); } for (Param p: segment.getMatrixParameters()) { if (p.isRequired()) { $ctor.param(GeneratorUtil.getJavaType(p, codeModel, $impl, javaDoc), GeneratorUtil.makeParamName(p.getName())); javaDoc.generateParamDoc(p, $ctor); } generateBeanProperty($impl, p, false); } } $ctor._throws(JAXBException.class); JBlock $ctorBody = $ctor.body(); if (generatedPackages.length() > 0) { // codegen: jc = JAXBContext.newInstance("com.example.test"); $ctorBody.assign($jaxbContext, codeModel.ref(JAXBContext.class).staticInvoke("newInstance").arg(JExpr.lit(generatedPackages))); // codegen: jaxbDispatcher = new JAXBDispatcher(jc); $ctorBody.assign($jaxbDispatcher, JExpr._new(codeModel.ref(JAXBDispatcher.class)).arg($jaxbContext)); } // codegen: dsDispatcher = new DSDispatcher(); $ctorBody.assign($dsDispatcher, JExpr._new(codeModel.ref(DSDispatcher.class))); // codegen: uriBuilder = new UriBuilder(); $ctorBody.assign($uriBuilder, JExpr._new(codeModel.ref(UriBuilder.class))); // codegen: java.util.List<String> matrixParamSet; JClass listOfString = codeModel.ref(List.class).narrow(String.class); JVar $matrixParamSet = $ctorBody.decl(listOfString, "_matrixParamSet"); for (PathSegment segment: resource.getPathSegments()) { // codegen: matrixParamSet = uriBuilder.addPathSegment(...) $ctorBody.assign($matrixParamSet, $uriBuilder.invoke("addPathSegment").arg(JExpr.lit(segment.getTemplate()))); for (Param p: segment.getMatrixParameters()) { // codegen: matrixParamSet.add(...) $ctorBody.invoke($matrixParamSet, "add").arg(JExpr.lit(p.getName())); } } // codegen: templateAndMatrixParameterValues = new HashMap<String, Object>(); $ctorBody.assign($templateMatrixParamValMap, JExpr._new(mapOfStringObject)); for (PathSegment segment: resource.getPathSegments()) { for (Param p: segment.getTemplateParameters()) { // codegen: templateAndMatrixParameterValues.put(name, value); $ctorBody.invoke($templateMatrixParamValMap, "put").arg(JExpr.lit(p.getName())).arg(JExpr.ref(GeneratorUtil.makeParamName(p.getName()))); } for (Param p: segment.getMatrixParameters()) { if (p.isRequired()) { // codegen: templateAndMatrixParameterValues.put(name, value); $ctorBody.invoke($templateMatrixParamValMap, "put").arg(JExpr.lit(p.getName())).arg(JExpr.ref(GeneratorUtil.makeParamName(p.getName()))); } } } $class = $impl; return $class; } /** * Create an exception class that wraps an element used for indicating a fault * condition. * @param f the WADL <code>fault</code> element for which to generate the exception class. * @return the generated exception class. */ protected JDefinedClass generateExceptionClass(FaultNode f) { JDefinedClass $exCls = null; String exName = f.getClassName(); try { $exCls = pkg._class( JMod.PUBLIC, exName); $exCls._extends(Exception.class); Mapping m = s2jModel.get(f.getElement()); if (m==null) System.err.println(Wadl2JavaMessages.ELEMENT_NOT_FOUND(f.getElement().toString())); JType detailType = m==null ? codeModel._ref(Object.class) : m.getType().getTypeClass(); JVar $detailField = $exCls.field(JMod.PRIVATE, detailType, "m_faultInfo"); JMethod $ctor = $exCls.constructor(JMod.PUBLIC); JVar $msg = $ctor.param(String.class, "message"); JVar $detail = $ctor.param(detailType, "faultInfo"); JBlock $ctorBody = $ctor.body(); $ctorBody.directStatement("super(message);"); $ctorBody.assign($detailField, $detail); JMethod $faultInfoGetter = $exCls.method(JMod.PUBLIC, detailType, "getFaultInfo"); $faultInfoGetter.body()._return($detailField); } catch (JClassAlreadyExistsException ex) { $exCls = ex.getExistingClass(); } return $exCls; } /** * Generate a set of method declarations for a WADL <code>method</code> element. * * Generates two Java methods per returned representation type for each request * type, one with all optional parameters and one without. I.e. if the WADL method * specifies two possible request repreesentation formats and three supported * response representation formats, this method will generate twelve Java methods, * one for each combination. * * @param isAbstract controls whether the generated methods will have a body (false) * or not (true) * @param method the WADL <code>method</code> element to process. */ protected void generateMethodDecls(MethodNode method, boolean isAbstract) { List<RepresentationNode> supportedInputs = method.getSupportedInputs(); List<RepresentationNode> supportedOutputs = method.getSupportedOutputs(); Map<JType, JDefinedClass> exceptionMap = new HashMap<JType, JDefinedClass>(); for (FaultNode f: method.getFaults()) { if (f.getElement()==null) {// skip fault for which there's no XML System.err.println(Wadl2JavaMessages.FAULT_NO_ELEMENT()); continue; } JDefinedClass generatedException = generateExceptionClass(f); Mapping m = s2jModel.get(f.getElement()); if (m==null) System.err.println(Wadl2JavaMessages.ELEMENT_NOT_FOUND(f.getElement().toString())); JType faultType = m==null ? codeModel._ref(Object.class) : m.getType().getTypeClass(); exceptionMap.put(faultType, generatedException); } if (supportedInputs.size()==0) { // no input representations, just query parameters // for each output representation if (supportedOutputs.size() == 0) { generateMethodVariants(exceptionMap, method, false, null, null, isAbstract); if (method.hasOptionalParameters()) generateMethodVariants(exceptionMap, method, true, null, null, isAbstract); } else { for (RepresentationNode returnType: supportedOutputs) { generateMethodVariants(exceptionMap, method, false, null, returnType, isAbstract); if (method.hasOptionalParameters()) generateMethodVariants(exceptionMap, method, true, null, returnType, isAbstract); } } } else { // for each possible input representation for (RepresentationNode inputType: supportedInputs) { // for each combination of input and output representation if (supportedOutputs.size() == 0) { generateMethodVariants(exceptionMap, method, false, inputType, null, isAbstract); if (method.hasOptionalParameters()) generateMethodVariants(exceptionMap, method, true, inputType, null, isAbstract); } else { for (RepresentationNode returnType: supportedOutputs) { generateMethodVariants(exceptionMap, method, false, inputType, returnType, isAbstract); if (method.hasOptionalParameters()) generateMethodVariants(exceptionMap, method, true, inputType, returnType, isAbstract); } } } } } /** * Get the Java type generated for the specified XML element name. * * Note that the specified element must be declared as a top-level element in a * schema imported by the WADL file otherwise no such Java type will have been * generated and this method will return <code>Object</code>. * @param element the name of the XML element. * @return the Java type that was generated for the specified element or null * if no matching generated type was found. */ protected JType getTypeFromElement(QName element) { Mapping m = s2jModel.get(element); if (m==null) System.err.println(Wadl2JavaMessages.ELEMENT_NOT_FOUND(element.toString())); JType type = m==null ? null : m.getType().getTypeClass(); return type; } /** * Generate one or two Java methods for a specified combination of WADL * <code>method</code>, * input <code>representation</code> and output <code>representation</code> * elements. Always generates one method that works with DataSources and * generates an additional method that uses JAXB when XML representations are used * and the document element is specified. * * @param isAbstract controls whether the generated methods will have a body (false) * or not (true) * @param exceptionMap maps generated types to the corresponding exception class. Used to generate the * throws clause for the method and the code to map output types to exceptions when * the output type is designated as a fault. * @param method the WADL <code>method</code> element for the Java method being generated. * @param includeOptionalParams whether to include optional parameters in the method signature or not. * @param inputRep the WADL <code>representation</code> element for the request format. * @param outputRep the WADL <code>representation</code> element for the response format. */ protected void generateMethodVariants(Map<JType, JDefinedClass> exceptionMap, MethodNode method, boolean includeOptionalParams, RepresentationNode inputRep, RepresentationNode outputRep, boolean isAbstract) { generateDSMethodDecl(exceptionMap, method, includeOptionalParams, inputRep, outputRep, isAbstract); generateJAXBMethodDecl(exceptionMap, method, includeOptionalParams, inputRep, outputRep, isAbstract); } /** * Generate a name for the method * @param method the WADL <code>method</code> element for the Java method being generated. * @param inputRep the WADL <code>representation</code> element for the request format. * @param outputRep the WADL <code>representation</code> element for the response format. * @param returnType a reference to the Java return type * @return a suitable method name */ protected String getMethodName(MethodNode method, RepresentationNode inputRep, RepresentationNode outputRep, JType returnType) { StringBuilder buf = new StringBuilder(); buf.append(method.getName().toLowerCase()); if (inputRep != null) { if (inputRep.getId() != null) { buf.append(inputRep.getId().substring(0,1).toUpperCase()); buf.append(inputRep.getId().substring(1).toLowerCase()); } else { buf.append(inputRep.getMediaTypeAsClassName()); } } if (returnType != null) { buf.append("As"); buf.append(returnType.name()); } else if (outputRep != null) { buf.append("As"); buf.append(outputRep.getMediaTypeAsClassName()); } else if (inputRep != null) { buf.append(inputRep.getMediaTypeAsClassName()); } return buf.toString(); } /** * Generate a Java method for a specified combination of WADL <code>method</code>, * input <code>representation</code> and output <code>representation</code> * elements. * @param isAbstract controls whether the generated methods will have a body (false) * or not (true) * @param exceptionMap maps generated types to the corresponding exception class. Used to generate the * throws clause for the method and the code to map output types to exceptions when * the output type is designated as a fault. * @param method the WADL <code>method</code> element for the Java method being generated. * @param includeOptionalParams whether to include optional parameters in the method signature or not. * @param inputRep the WADL <code>representation</code> element for the request format. * @param outputRep the WADL <code>representation</code> element for the response format. */ protected void generateJAXBMethodDecl(Map<JType, JDefinedClass> exceptionMap, MethodNode method, boolean includeOptionalParams, RepresentationNode inputRep, RepresentationNode outputRep, boolean isAbstract) { // check if JAXB can be used with available information if ((outputRep != null && outputRep.getElement() == null) || (inputRep != null && inputRep.getElement() == null)) return; // work out the method return type and the type of any input representation JType inputType=null, returnType=null; if (inputRep != null) { inputType = getTypeFromElement(inputRep.getElement()); if (inputType == null) return; } if (outputRep != null) { returnType = getTypeFromElement(outputRep.getElement()); if (returnType == null) return; } else returnType = codeModel.VOID; // generate a name for the method String methodName = getMethodName(method, inputRep, outputRep, returnType); // create the method JMethod $genMethod = $class.method(JMod.PUBLIC, returnType, methodName); javaDoc.generateMethodDoc(method, $genMethod); if (outputRep != null) javaDoc.generateReturnDoc(outputRep, $genMethod); // add throws for any required exceptions $genMethod._throws(JAXBException.class); $genMethod._throws(MalformedURLException.class); $genMethod._throws(IOException.class); for (JDefinedClass $ex: exceptionMap.values()) { $genMethod._throws($ex); } // add a parameter for the input representation (if required) if (inputType != null) { $genMethod.param(inputType, "input"); javaDoc.generateParamDoc(inputRep, $genMethod); } // add a parameter for each query parameter List<Param> params = method.getRequiredParameters(); if (includeOptionalParams) params.addAll(method.getOptionalParameters()); for (Param q: params) { // skip fixed value parameters in the method arguments if (q.getFixed() != null) continue; JClass javaType = GeneratorUtil.getJavaType(q, codeModel, $class, javaDoc); String paramName = q.getName().equals("input") ? "queryInput" : q.getName(); q.setName(paramName); javaDoc.generateParamDoc(q, $genMethod); if (q.isRepeating()) $genMethod.param(codeModel.ref(List.class).narrow(javaType), GeneratorUtil.makeParamName(q.getName())); else $genMethod.param(javaType, GeneratorUtil.makeParamName(q.getName())); } if (!isAbstract) { // add the method body JBlock $methodBody = $genMethod.body(); JClass mapOfString = codeModel.ref(HashMap.class).narrow(String.class, Object.class); JVar $queryParamMap = $methodBody.decl(mapOfString, "_queryParameterValues", JExpr._new(mapOfString)); JVar $headerParamMap = $methodBody.decl(mapOfString, "_headerParameterValues", JExpr._new(mapOfString)); for (Param q: params) { if (!includeOptionalParams && !q.isRequired() && q.getFixed()==null) continue; JFieldRef $paramArg = JExpr.ref(GeneratorUtil.makeParamName(q.getName())); // check that required variables aren't null if (q.isRequired() && q.getFixed()==null) { JBlock $throwBlock = $methodBody._if($paramArg.eq(JExpr._null()))._then(); $throwBlock._throw(JExpr._new(codeModel.ref( IllegalArgumentException.class)).arg( JExpr.lit(Wadl2JavaMessages.PARAMETER_REQUIRED(q.getName(), methodName)))); } JVar $paramMap = q.getStyle() == ParamStyle.QUERY ? $queryParamMap : $headerParamMap; JInvocation addParamToMap = $methodBody.invoke($paramMap, "put"); if (q.getFixed()!=null) addParamToMap.arg(JExpr.lit(q.getName())).arg(JExpr.lit(q.getFixed())); else addParamToMap.arg(JExpr.lit(q.getName())).arg($paramArg); } generateJAXBDBody(method, exceptionMap, outputRep, returnType, $queryParamMap, $headerParamMap, inputRep, $methodBody); } } /** * Generate a Java method for a specified combination of WADL <code>method</code>, * input <code>representation</code> and output <code>representation</code> * elements. * @param isAbstract controls whether the generated methods will have a body (false) * or not (true) * @param exceptionMap maps generated types to the corresponding exception class. Used to generate the * throws clause for the method and the code to map output types to exceptions when * the output type is designated as a fault. * @param method the WADL <code>method</code> element for the Java method being generated. * @param includeOptionalParams whether to include optional parameters in the method signature or not. * @param inputRep the WADL <code>representation</code> element for the request format. * @param outputRep the WADL <code>representation</code> element for the response format. */ protected void generateDSMethodDecl(Map<JType, JDefinedClass> exceptionMap, MethodNode method, boolean includeOptionalParams, RepresentationNode inputRep, RepresentationNode outputRep, boolean isAbstract) { // work out the method return type and the type of any input representation JType inputType=null, returnType=null; if (inputRep != null) inputType = codeModel._ref(javax.activation.DataSource.class); if (outputRep != null) returnType = codeModel._ref(javax.activation.DataSource.class); else returnType = codeModel.VOID; // generate a name for the method String methodName = getMethodName(method, inputRep, outputRep, null); // create the method JMethod $genMethod = $class.method(JMod.PUBLIC, returnType, methodName); javaDoc.generateMethodDoc(method, $genMethod); if (outputRep != null) javaDoc.generateReturnDoc(outputRep, $genMethod); // add throws for any required exceptions $genMethod._throws(MalformedURLException.class); $genMethod._throws(IOException.class); // add a parameter for the input representation (if required) if (inputType != null) { $genMethod.param(inputType, "input"); javaDoc.generateParamDoc(inputRep, $genMethod); } // add a parameter for each query parameter List<Param> params = method.getRequiredParameters(); if (includeOptionalParams) params.addAll(method.getOptionalParameters()); for (Param q: params) { // skip fixed value query parameters in the method arguments if (q.getFixed() != null) continue; JClass javaType = GeneratorUtil.getJavaType(q, codeModel, $class, javaDoc); String paramName = q.getName().equals("input") ? "queryInput" : q.getName(); q.setName(paramName); javaDoc.generateParamDoc(q, $genMethod); if (q.isRepeating()) $genMethod.param(codeModel.ref(List.class).narrow(javaType), GeneratorUtil.makeParamName(q.getName())); else $genMethod.param(javaType, GeneratorUtil.makeParamName(q.getName())); } if (!isAbstract) { // add the method body JBlock $methodBody = $genMethod.body(); JClass mapOfString = codeModel.ref(HashMap.class).narrow(String.class, Object.class); JVar $queryParamMap = $methodBody.decl(mapOfString, "_queryParameterValues", JExpr._new(mapOfString)); JVar $headerParamMap = $methodBody.decl(mapOfString, "_headerParameterValues", JExpr._new(mapOfString)); for (Param q: params) { if (!includeOptionalParams && !q.isRequired() && q.getFixed()==null) continue; JFieldRef $paramArg = JExpr.ref(GeneratorUtil.makeParamName(q.getName())); // check that required variables aren't null if (q.isRequired() && q.getFixed()==null) { JBlock $throwBlock = $methodBody._if($paramArg.eq(JExpr._null()))._then(); $throwBlock._throw(JExpr._new(codeModel.ref( IllegalArgumentException.class)).arg( JExpr.lit(Wadl2JavaMessages.PARAMETER_REQUIRED(q.getName(), methodName)))); } JVar $paramMap = q.getStyle() == ParamStyle.QUERY ? $queryParamMap : $headerParamMap; JInvocation addParamToMap = $methodBody.invoke($paramMap, "put"); if (q.getFixed()!=null) addParamToMap.arg(JExpr.lit(q.getName())).arg(JExpr.lit(q.getFixed())); else addParamToMap.arg(JExpr.lit(q.getName())).arg($paramArg); } generateDSDBody(method, outputRep, returnType, $queryParamMap, $headerParamMap, inputRep, $methodBody); } } /** * Generate a method body that uses a JAXBDispatcher, used when the payloads are XML * @param method the method to generate a body for * @param exceptionMap the generated exceptions that the method can raise * @param outputRep the output representation * @param returnType the type of the method return * @param $queryParamValueMap a reference to the parameterMap variable in the generated code * @param inputRep the input representation * @param $methodBody a reference to the method body in which to generate code */ protected void generateJAXBDBody(final MethodNode method, final Map<JType, JDefinedClass> exceptionMap, final RepresentationNode outputRep, final JType returnType, final JVar $queryParamValueMap, final JVar $headerParamValueMap, final RepresentationNode inputRep, final JBlock $methodBody) { JExpression $url = $methodBody.decl(codeModel.ref(String.class), "_url", $uriBuilder.invoke("buildUri").arg($templateMatrixParamValMap).arg($queryParamValueMap)); JInvocation $executeMethod = $jaxbDispatcher.invoke("do"+method.getName()); if (method.getName().equals("POST") || method.getName().equals("PUT")) { if (inputRep == null) { $executeMethod.arg(JExpr._null()); $executeMethod.arg(JExpr._null()); } else { $executeMethod.arg(JExpr.ref("input")); $executeMethod.arg(JExpr.lit(inputRep.getMediaType())); } } $executeMethod.arg($url); $executeMethod.arg($headerParamValueMap); if (outputRep != null && outputRep.getMediaType() != null) $executeMethod.arg(JExpr.lit(outputRep.getMediaType())); else $executeMethod.arg(JExpr._null()); JVar $retVal = $methodBody.decl(codeModel.ref(Object.class), "_retVal", $executeMethod); JBlock $nullBlock = $methodBody._if($retVal.eq(JExpr._null()))._then(); if (outputRep != null) $nullBlock._return(JExpr._null()); else $nullBlock._return(); JClass jaxbElementType = codeModel.ref(JAXBElement.class); $nullBlock = $methodBody._if(JExpr.invoke(JExpr.dotclass(jaxbElementType), "isInstance").arg($retVal))._then(); JVar $jaxbelement = $nullBlock.decl(jaxbElementType, "jaxbElement", JExpr.cast(jaxbElementType, $retVal)); $nullBlock.assign($retVal, $jaxbelement.invoke("getValue")); // check type of returned object and throw generated exception if // it matches a fault declared in the description for (JType faultType: exceptionMap.keySet()) { JDefinedClass matchingException = exceptionMap.get(faultType); JBlock $throwBlock = $methodBody._if(JExpr.invoke(JExpr.dotclass(faultType.boxify()), "isInstance").arg($retVal))._then(); $throwBlock._throw(JExpr._new(matchingException).arg(JExpr.lit(Wadl2JavaMessages.INVOCATION_FAILED())).arg(JExpr.cast(faultType,$retVal))); } if (outputRep != null) $methodBody._return(JExpr.cast(returnType,$retVal)); else $methodBody._return(); } /** * Generate a method body that uses a DSDispatcher, used when the payloads are not XML * @param method the method to generate a body for * @param outputRep the output representation * @param returnType the type of the method return * @param $queryParamValueMap a reference to the parameterMap variable in the generated code * @param inputRep the input representation * @param $methodBody a reference to the method body in which to generate code */ protected void generateDSDBody(final MethodNode method, final RepresentationNode outputRep, final JType returnType, final JVar $queryParamValueMap, final JVar $headerParamValueMap, final RepresentationNode inputRep, final JBlock $methodBody) { JExpression $url = $methodBody.decl(codeModel.ref(String.class), "_url", $uriBuilder.invoke("buildUri").arg($templateMatrixParamValMap).arg($queryParamValueMap)); JInvocation $executeMethod = $dsDispatcher.invoke("do"+method.getName()); if (method.getName().equals("POST") || method.getName().equals("PUT")) { if (inputRep == null) { $executeMethod.arg(JExpr._null()); $executeMethod.arg(JExpr._null()); } else { $executeMethod.arg(JExpr.ref("input")); $executeMethod.arg(JExpr.lit(inputRep.getMediaType())); } } $executeMethod.arg($url); $executeMethod.arg($headerParamValueMap); if (outputRep != null && outputRep.getMediaType() != null) $executeMethod.arg(JExpr.lit(outputRep.getMediaType())); else $executeMethod.arg(JExpr._null()); JExpression $retVal = $methodBody.decl(codeModel.ref(javax.activation.DataSource.class), "_retVal", $executeMethod); if (outputRep != null) $methodBody._return($retVal); else $methodBody._return(); } /** * Generate a bean setter and getter for a parameter * @param $impl The class or interface to add the bean setter and getter to * @param p the WADL parameter for which to create the setter and getter * @param isAbstract controls whether a method body is created (false) or not (true). Set to true * for interface methods, false for class methods */ public void generateBeanProperty(JDefinedClass $impl, Param p, boolean isAbstract) { JType propertyType = GeneratorUtil.getJavaType(p, codeModel, $impl, javaDoc); String paramName = GeneratorUtil.makeParamName(p.getName()); String propertyName = paramName.substring(0,1).toUpperCase()+paramName.substring(1); // getter JMethod $getter = $impl.method(JMod.PUBLIC, propertyType, "get"+propertyName); JDocComment jdoc = $getter.javadoc(); jdoc.append("Get "+p.getName()); javaDoc.generateReturnDoc(p, $getter); if (!isAbstract) { JBlock $getterBody = $getter.body(); // codegen: return ((Type) templateAndMatrixParameterValues.get("name")); $getterBody._return(JExpr.cast(propertyType, $templateMatrixParamValMap.invoke("get").arg(JExpr.lit(p.getName())))); } // setter JMethod $setter = $impl.method(JMod.PUBLIC, codeModel.VOID, "set"+propertyName); jdoc = $setter.javadoc(); jdoc.append("Set "+p.getName()); $setter.param(propertyType, paramName); javaDoc.generateParamDoc(p, $setter); if (!isAbstract) { JBlock $setterBody = $setter.body(); // codegen: templateAndMatrixParameterValues.put("name", value); $setterBody.invoke($templateMatrixParamValMap, "put").arg(JExpr.lit(p.getName())).arg(JExpr.ref(paramName)); } } }