gov.nih.nci.restgen.codegen.RESTfulResourceGenerator.java Source code

Java tutorial

Introduction

Here is the source code for gov.nih.nci.restgen.codegen.RESTfulResourceGenerator.java

Source

/*L
 *  Copyright Ekagra Software Technologies Ltd.
 *  Copyright SAIC, SAIC-Frederick
 *
 *  Distributed under the OSI-approved BSD 3-Clause License.
 *  See http://ncip.github.com/cacore-sdk/LICENSE.txt for details.
 */

package gov.nih.nci.restgen.codegen;

import gov.nih.nci.restgen.mapping.model.Implementation;
import gov.nih.nci.restgen.mapping.model.Input;
import gov.nih.nci.restgen.mapping.model.Mapping;
import gov.nih.nci.restgen.mapping.model.Method;
import gov.nih.nci.restgen.mapping.model.Operation;
import gov.nih.nci.restgen.mapping.model.Options;
import gov.nih.nci.restgen.mapping.model.Output;
import gov.nih.nci.restgen.mapping.model.Resource;
import gov.nih.nci.restgen.util.GeneratorUtil;
import gov.nih.nci.restgen.util.JarHelper;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Annotation;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import org.antlr.stringtemplate.StringTemplate;
import org.antlr.stringtemplate.StringTemplateGroup;
import org.apache.bcel.classfile.ClassParser;
import org.apache.bcel.classfile.JavaClass;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.springframework.core.annotation.AnnotationUtils;

import com.predic8.schema.ComplexType;
import com.predic8.schema.Element;
import com.predic8.schema.Schema;
import com.predic8.schema.TypeDefinition;
import com.predic8.wsdl.Binding;
import com.predic8.wsdl.Definitions;
import com.predic8.wsdl.Fault;
import com.predic8.wsdl.Port;
import com.predic8.wsdl.PortType;
import com.predic8.wsdl.Service;
import com.predic8.wsdl.WSDLParser;

/**
 * RESTful resource generator
 * This generator works with EJB and SOAP web service mapping and generate RESTful resources. 
 * StringTemplate is used to for code template. Generator parsess mapping information and 
 * populates code template with values.
 * @author konkapv
 *
 */
public class RESTfulResourceGenerator extends Generator {

    /**
     * Constructor 
     * @param context
     */
    public RESTfulResourceGenerator(GeneratorContext context) {
        super(context);
    }

    protected void init() {
        getContext().getLogger().info("Generating RESTful resource...");
    }

    protected void preProcess() {
        //getContext().getLogger().info("Generating RESTful resource...preProcess");
    }

    protected void validate() {
        //getContext().getLogger().info("Generating RESTful resource...validate");
    }

    /**
     * Generate RESTful resource based on mapping to EJB or SOAP web service.
     */
    public void runProcess() throws GeneratorException {
        //getContext().getLogger().info("Generating RESTful resource...runProcess started");
        Mapping mapping = context.getMapping();
        if (mapping.getOptions().getWrapperType().equals(Options.SOAP_SERVICE))
            runProcessSOAP();
        else if (mapping.getOptions().getWrapperType().equals(Options.EJB))
            runProcessEJB();
        else
            throw new GeneratorException("Invalid wrapper type.");
    }

    /**
     * Generate RESTful resource based on SOAP web service mapaping
     * 
     * @throws GeneratorException
     */
    private void runProcessSOAP() throws GeneratorException {
        Mapping mapping = context.getMapping();
        List<Resource> resources = mapping.getResources();
        StringTemplateGroup group = new StringTemplateGroup("restful");
        StringTemplate putTemplate = null;
        StringTemplate postTemplate = null;
        StringTemplate getTemplate = null;
        StringTemplate deleteTemplate = null;

        WSDLParser parser = new WSDLParser();

        Definitions defs = parser.parse(context.getMapping().getOptions().getWsdlLocation());

        for (Resource resource : resources) {
            StringTemplate resourceTemplate = group.getInstanceOf("gov/nih/nci/restgen/templates/RESTfulResource");
            String resourceName = resource.getName();
            List<Method> methods = resource.getMethods();
            List<String> getMethodStr = new ArrayList<String>();
            List<String> putMethodStr = new ArrayList<String>();
            List<String> postMethodStr = new ArrayList<String>();
            List<String> deleteMethodStr = new ArrayList<String>();
            int counter = 1;
            for (Method method : methods) {
                getTemplate = group.getInstanceOf("gov/nih/nci/restgen/templates/GetMethodSOAP");
                postTemplate = group.getInstanceOf("gov/nih/nci/restgen/templates/PostMethodSOAP");
                deleteTemplate = group.getInstanceOf("gov/nih/nci/restgen/templates/DeleteMethodSOAP");
                putTemplate = group.getInstanceOf("gov/nih/nci/restgen/templates/PutMethodSOAP");
                String methodName = resource.getName() + counter;
                if (method.getName().equals(Method.GET)) {
                    String getString = generateMethod(resourceName, method, getTemplate, methodName, defs);
                    getMethodStr.add(getString);
                } else if (method.getName().equals(Method.PUT)) {
                    String putString = generateMethod(resourceName, method, putTemplate, methodName, defs);
                    putMethodStr.add(putString);
                } else if (method.getName().equals(Method.POST)) {
                    String postString = generateMethod(resourceName, method, postTemplate, methodName, defs);
                    postMethodStr.add(postString);
                } else if (method.getName().equals(Method.DELETE)) {
                    String deleteString = generateMethod(resourceName, method, deleteTemplate, methodName, defs);
                    deleteMethodStr.add(deleteString);
                }
                counter++;
            }
            resourceTemplate.setAttribute("packageName", Constants.GENERATOR_PKG_NAME);
            resourceTemplate.setAttribute("ResourcePath", resource.getPath());
            resourceTemplate.setAttribute("ResourceName", resourceName);

            for (String str : getMethodStr) {
                resourceTemplate.setAttribute("GetMethods", str);
            }

            for (String str : putMethodStr) {
                resourceTemplate.setAttribute("PutMethods", str);
            }

            for (String str : postMethodStr) {
                resourceTemplate.setAttribute("PostMethods", str);
            }

            for (String str : deleteMethodStr) {
                resourceTemplate.setAttribute("DeleteMethods", str);
            }

            resourceTemplate.setAttribute("importStatements", "import gov.nih.nci.restgen.generated.client.*;");
            GeneratorUtil.writeFile(mapping.getOptions().getOutputPath() + getFileOutputPath(),
                    resourceName + "Resource.java", resourceTemplate.toString());
        }
    }

    private void processPojo(Resource resource) throws GeneratorException {
        if (context.getMapping().getOptions().getWrapperType().equals(Options.EJB)) {

            String libDest = context.getMapping().getOptions().getOutputPath() + File.separator + "web"
                    + File.separator + "WEB-INF";

            String sourcePath = resource.getPojoLocation();
            File jarSrcFile = new File(sourcePath);
            String jarFileName = null;
            if (sourcePath.lastIndexOf(File.separator) > 0)
                jarFileName = sourcePath.substring(sourcePath.lastIndexOf(File.separator) + 1, sourcePath.length());
            else
                jarFileName = sourcePath;

            StringTemplateGroup group = new StringTemplateGroup("restful");
            StringTemplate indexTemplate = group.getInstanceOf("gov/nih/nci/restgen/templates/JAXBIndex");

            jarFileName = jarFileName.substring(0, jarFileName.indexOf(".")) + ".jar";
            if (sourcePath.endsWith(".jar")) {
                File destFile = new File(libDest + File.separator + "lib" + File.separator + jarFileName);
                try {
                    JarFile file = new JarFile(jarSrcFile);
                    String oldDir = "";
                    String dirName = "";
                    boolean firstIter = true;
                    boolean generate = false;
                    for (Enumeration<JarEntry> enums = file.entries(); enums.hasMoreElements();) {
                        JarEntry entry = (JarEntry) enums.nextElement();

                        if (entry.getName().endsWith(".class")) {
                            dirName = entry.getName().substring(0, entry.getName().lastIndexOf("/"));
                            if (firstIter) {
                                firstIter = false;
                                oldDir = dirName;
                            }
                            String fileName = entry.getName().substring(entry.getName().lastIndexOf("/") + 1,
                                    entry.getName().indexOf(".class"));
                            generate = true;
                            indexTemplate.setAttribute("ClassName", fileName);
                            if (!oldDir.equals(dirName)) {
                                dirName = dirName.replace("/", File.separator);
                                GeneratorUtil.writeFile(
                                        context.getMapping().getOptions().getOutputPath() + getFileOutputPath()
                                                + File.separator + "web" + File.separator + "WEB-INF"
                                                + File.separator + "classes" + File.separator + dirName,
                                        "jaxb.index", indexTemplate.toString());
                                indexTemplate = group.getInstanceOf("gov/nih/nci/restgen/templates/JAXBIndex");
                                generate = false;
                            }
                        }

                        //System.out.println(entry.getName());   
                    }
                    if (generate) {
                        dirName = dirName.replace("/", File.separator);

                        GeneratorUtil.writeFile(context.getMapping().getOptions().getOutputPath() + File.separator
                                + "web" + File.separator + "WEB-INF" + File.separator + "classes" + File.separator
                                + dirName, "jaxb.index", indexTemplate.toString());
                    }
                    GeneratorUtil.copyFile(jarSrcFile, destFile);
                } catch (IOException e) {
                    e.printStackTrace();
                    throw new GeneratorException("Failed to copy POJO jar into output lib folder");
                }
            } else {
                try {
                    String pojoLocation = resource.getPojoLocation();
                    File file = new File(pojoLocation);
                    InputStream is = new FileInputStream(file);
                    ClassParser cp = new ClassParser(is, file.getName());
                    JavaClass javaClass = cp.parse();
                    String packageName = javaClass.getPackageName();
                    String dirStart = null;
                    if (packageName.indexOf(".") > 0) {
                        dirStart = packageName.substring(0, packageName.indexOf("."));
                    } else
                        dirStart = packageName;

                    String outDirName = libDest + File.separator + "classes" + File.separator
                            + packageName.replace(".", File.separator);
                    File outDir = new File(outDirName);
                    if (!outDir.exists())
                        outDir.mkdirs();

                    File jarDestClassFile = new File(outDirName + File.separator + javaClass.getFileName());
                    File jarSrcClassFile = new File(pojoLocation);
                    GeneratorUtil.copyFile(jarSrcClassFile, jarDestClassFile);
                    //               GeneratorUtil.copyDir(jarSrcDir, libDest + File.separator
                    //                     + "classes");
                    String dirName = packageName.replace(".", File.separator);
                    String entry = javaClass.getFileName().substring(0, javaClass.getFileName().indexOf(".class"));
                    indexTemplate.setAttribute("ClassName", entry);

                    GeneratorUtil.writeFile(context.getMapping().getOptions().getOutputPath() + File.separator
                            + "web" + File.separator + "WEB-INF" + File.separator + "classes" + File.separator
                            + dirName, "jaxb.index", indexTemplate.toString());

                } catch (IOException e) {
                    e.printStackTrace();
                    throw new GeneratorException("Failed to generate web archive file.", e);
                }
            }
        }
    }

    private void processJNDIProperties(Method method) throws GeneratorException {
        if (method.getImplementation().getClientType() != null
                && method.getImplementation().getClientType().equals(Implementation.EJB_REMOTE)) {
            String jndiDest = context.getMapping().getOptions().getOutputPath() + File.separator + "web"
                    + File.separator + "WEB-INF" + File.separator + "classes";

            File jndiDestFolder = new File(jndiDest);
            if (!jndiDestFolder.exists()) {
                jndiDestFolder.mkdirs();
            }

            String jndiFilePath = method.getImplementation().getJndiProperties();
            String jndiFileName = jndiFilePath.substring(jndiFilePath.lastIndexOf(File.separator) + 1);
            File destFile = new File(jndiDest + File.separator + jndiFileName);
            File srcFile = new File(jndiFilePath);
            try {
                GeneratorUtil.copyFile(srcFile, destFile);
            } catch (IOException e) {
                e.printStackTrace();
                throw new GeneratorException("Failed to copy POJO jar into output lib folder");
            }
        }
    }

    private void runProcessEJB() throws GeneratorException {
        Mapping mapping = context.getMapping();
        List<Resource> resources = mapping.getResources();
        StringTemplateGroup group = new StringTemplateGroup("restfulejb");
        StringTemplate getTemplate = null;
        StringTemplate postTemplate = null;
        StringTemplate deleteTemplate = null;
        StringTemplate putTemplate = null;
        StringTemplate resourceTemplate = group.getInstanceOf("gov/nih/nci/restgen/templates/RESTfulResource");
        StringTemplate indexTemplate = group.getInstanceOf("gov/nih/nci/restgen/templates/JAXBIndex");

        for (Resource resource : resources) {
            String resourceName = resource.getName();
            List<Method> methods = resource.getMethods();
            List<String> getMethodStr = new ArrayList<String>();
            List<String> putMethodStr = new ArrayList<String>();
            List<String> postMethodStr = new ArrayList<String>();
            List<String> deleteMethodStr = new ArrayList<String>();
            int counter = 1;
            for (Method method : methods) {
                String methodName = resource.getName() + counter;
                if (method.getName().equals(Method.GET)) {
                    if (method.getImplementation().getClientType().equals(Implementation.EJB_LOCAL)) {
                        getTemplate = group.getInstanceOf("gov/nih/nci/restgen/templates/GetMethodEJBLocal");
                    } else if (method.getImplementation().getClientType().equals(Implementation.EJB_REMOTE)) {
                        getTemplate = group.getInstanceOf("gov/nih/nci/restgen/templates/GetMethodEJBRemote");
                    }
                    String getString = generateMethodEJB(resourceName, method, methodName, getTemplate);
                    getMethodStr.add(getString);
                } else if (method.getName().equals(Method.PUT)) {
                    if (method.getImplementation().getClientType().equals(Implementation.EJB_LOCAL)) {
                        putTemplate = group.getInstanceOf("gov/nih/nci/restgen/templates/PutMethodEJBLocal");
                    } else if (method.getImplementation().getClientType().equals(Implementation.EJB_REMOTE)) {
                        putTemplate = group.getInstanceOf("gov/nih/nci/restgen/templates/PutMethodEJBRemote");
                    }
                    String putString = generateMethodEJB(resourceName, method, methodName, putTemplate);
                    putMethodStr.add(putString);
                } else if (method.getName().equals(Method.POST)) {
                    if (method.getImplementation().getClientType().equals(Implementation.EJB_LOCAL)) {
                        postTemplate = group.getInstanceOf("gov/nih/nci/restgen/templates/PostMethodEJBLocal");
                    } else if (method.getImplementation().getClientType().equals(Implementation.EJB_REMOTE)) {
                        postTemplate = group.getInstanceOf("gov/nih/nci/restgen/templates/PostMethodEJBRemote");
                    }
                    String postString = generateMethodEJB(resourceName, method, methodName, postTemplate);
                    postMethodStr.add(postString);
                } else if (method.getName().equals(Method.DELETE)) {
                    if (method.getImplementation().getClientType().equals(Implementation.EJB_LOCAL)) {
                        deleteTemplate = group.getInstanceOf("gov/nih/nci/restgen/templates/DeleteMethodEJBLocal");
                    } else if (method.getImplementation().getClientType().equals(Implementation.EJB_REMOTE)) {
                        deleteTemplate = group.getInstanceOf("gov/nih/nci/restgen/templates/DeleteMethodEJBRemote");
                    }
                    String deleteString = generateMethodEJB(resourceName, method, methodName, deleteTemplate);
                    deleteMethodStr.add(deleteString);
                }
                processJNDIProperties(method);
                processPojo(resource);
                processEJBJar(method);
                counter++;
            }
            resourceTemplate.setAttribute("packageName", Constants.GENERATOR_PKG_NAME);
            resourceTemplate.setAttribute("ResourcePath", resource.getPath());
            resourceTemplate.setAttribute("ResourceName", resourceName);

            for (String str : getMethodStr) {
                resourceTemplate.setAttribute("GetMethods", str);
            }

            for (String str : putMethodStr) {
                resourceTemplate.setAttribute("PutMethods", str);
            }

            for (String str : postMethodStr) {
                resourceTemplate.setAttribute("PostMethods", str);
            }

            for (String str : deleteMethodStr) {
                resourceTemplate.setAttribute("DeleteMethods", str);
            }

            GeneratorUtil.writeFile(mapping.getOptions().getOutputPath() + getFileOutputPath(),
                    resourceName + "Resource.java", resourceTemplate.toString());
        }
    }

    private void processEJBJar(Method method) throws GeneratorException {
        if (context.getMapping().getOptions().getWrapperType().equals(Options.EJB)) {
            String ejbLoc = context.getMapping().getOptions().getEjbLocation();
            File src = new File(ejbLoc);
            String ejbFileName = ejbLoc.substring(ejbLoc.lastIndexOf(File.separator) + 1);
            String jarDest = context.getMapping().getOptions().getOutputPath() + File.separator + "web"
                    + File.separator + "WEB-INF" + File.separator + "lib" + File.separator + ejbFileName;
            File dest = new File(jarDest);
            try {
                GeneratorUtil.copyFile(src, dest);
                String outputPath = context.getMapping().getOptions().getOutputPath() + File.separator + "web"
                        + File.separator + "temp";
                if (method.getImplementation().getClientType().equals(Implementation.EJB_REMOTE)) {
                    String deletePathName = outputPath + File.separator + "META-INF";
                    new JarHelper().removeJarEntry(jarDest, deletePathName, outputPath);
                }
            } catch (IOException e) {
                e.printStackTrace();
                throw new GeneratorException("Failed to copy EJB jar to output lib folder");
            }
        }

    }

    private String generateMethodEJB(String resourceName, Method method, String methodName, StringTemplate template)
            throws GeneratorException {
        Implementation impl = method.getImplementation();

        template.setAttribute("MethodName", methodName);
        template.setAttribute("ResourceName", resourceName);

        JarFile jarFile = null;
        org.jdom2.Document doc = null;
        try {
            jarFile = new JarFile(context.getMapping().getOptions().getEjbLocation());
            JarEntry jarEntry = jarFile.getJarEntry("META-INF/ejb-jar.xml");
            if (jarEntry != null) {
                InputStream is = jarFile.getInputStream(jarEntry);
                SAXBuilder sax = new SAXBuilder();
                doc = sax.build(is);

            } else
                throw new GeneratorException("Invalid EJB JAR path. Unable to load ejb-jar.xml");
        } catch (IOException e) {
            throw new GeneratorException("Failed to load EJB JAR. ", e);
        } catch (JDOMException e) {
            throw new GeneratorException("Failed to load EJB JAR ejb-jar.xml ", e);
        }

        org.jdom2.Element root = doc.getRootElement();

        org.jdom2.Element eBeans = root.getChild("enterprise-beans", root.getNamespace());
        List<org.jdom2.Element> sessionBeans = eBeans.getChildren("session", root.getNamespace());
        String ejbHomeName = null;
        String ejbRemoteName = null;

        boolean foundService = false;
        for (org.jdom2.Element sessionBean : sessionBeans) {
            org.jdom2.Element ejbName = sessionBean.getChild("ejb-name", root.getNamespace());

            if (ejbName.getValue().equals(impl.getName())) {
                foundService = true;
                org.jdom2.Element ejbHome = sessionBean.getChild("home", root.getNamespace());
                ejbHomeName = ejbHome.getValue();
                org.jdom2.Element ejbRemote = sessionBean.getChild("remote", root.getNamespace());
                ejbRemoteName = ejbRemote.getValue();
                break;
            }
        }

        if (!foundService)
            throw new GeneratorException("Unable to find EJB from ejb-jar.xml for " + impl.getName());

        String returnType = getOperationReturnType(impl);
        if (!returnType.equals("void")) {
            template.setAttribute("ReturnTypeNotVoid", true);
            template.setAttribute("PostReturnType", returnType);
            template.setAttribute("PutReturnType", returnType);
            template.setAttribute("DeleteReturnType", returnType);
        } else {
            template.setAttribute("ReturnTypeResponse", true);
            template.setAttribute("PostReturnType", "Response");
            template.setAttribute("PutReturnType", "Response");
            template.setAttribute("DeleteReturnType", "Response");

        }

        template.setAttribute("ReturnType", returnType);
        String pathParamPath = getOperationPath(impl, method.getName());
        if (pathParamPath != null) {
            template.setAttribute("PathParamPath", "@Path(\"" + pathParamPath + "\")");
            template.setAttribute("PathParamPathShort", pathParamPath);
        }

        template.setAttribute("PathParam", getOperationPathParams(method, impl));
        template.setAttribute("HomeInterface", ejbHomeName);
        template.setAttribute("RemoteInterface", ejbRemoteName);
        template.setAttribute("OperationName", impl.getOperation().getName());
        String operationParams = getOperationParams(impl);
        //if (operationParams != null)
        //   operationParams = operationParams + ", ";
        template.setAttribute("OperationParameters", operationParams);
        template.setAttribute("RequestType", getRequestTypes(impl));
        template.setAttribute("OperationParamNames", getOperationParams(impl));

        if (impl.getClientType().equals(Implementation.EJB_REMOTE)) {
            String jndiPath = impl.getJndiProperties();
            String fileName = jndiPath.substring(jndiPath.lastIndexOf(File.separator) + 1);
            template.setAttribute("JNDIProperties", fileName);
        }
        template.setAttribute("JNDIName", impl.getJndiName());
        return template.toString();
    }

    private String getOperationReturnType(Implementation impl) {
        Operation operation = impl.getOperation();
        Output output = operation.getOutput();
        if (output == null)
            return "void";
        else
            return output.getType();
    }

    private String getOperationParams(Implementation impl) {
        Operation operation = impl.getOperation();
        List<Input> inputs = operation.getInputs();
        if (inputs == null || inputs.size() == 0)
            return null;

        StringBuffer buffer = new StringBuffer();
        Iterator<Input> iterator = inputs.iterator();
        while (iterator.hasNext()) {
            Input input = (Input) iterator.next();
            buffer.append(input.getName());
            if (iterator.hasNext())
                buffer.append(", ");
        }

        return buffer.toString();
    }

    private String getRequestTypes(Implementation impl) {
        Operation operation = impl.getOperation();
        List<Input> inputs = operation.getInputs();
        if (inputs == null || inputs.size() == 0)
            return null;

        StringBuffer buffer = new StringBuffer();
        Iterator<Input> iterator = inputs.iterator();
        while (iterator.hasNext()) {
            Input input = (Input) iterator.next();
            buffer.append(input.getType() + " " + input.getName());
            if (iterator.hasNext())
                buffer.append(", ");
        }

        return buffer.toString();
    }

    private String getOperationPathParams(Method method, Implementation impl) {
        Operation operation = impl.getOperation();
        List<Input> inputs = operation.getInputs();

        if (inputs == null || inputs.size() == 0)
            return null;

        StringBuffer buffer = new StringBuffer();
        Iterator<Input> iterator = inputs.iterator();
        boolean append = false;
        while (iterator.hasNext()) {
            Input input = (Input) iterator.next();
            buffer.append("@PathParam(\"" + input.getName() + "\") ");
            buffer.append(input.getType() + " " + input.getName());
            append = true;
            if (iterator.hasNext())
                buffer.append(", ");
        }
        if (!method.getName().equals(Method.GET))
            append = false;
        if (append)
            return buffer.toString() + ",";
        else
            return buffer.toString();
    }

    private String getOperationPath(Implementation impl, String methodName) {
        if (methodName.equals(Method.POST) || methodName.equals(Method.PUT)) {
            if (impl.getPath() != null && impl.getPath().trim().length() > 0)
                return "/" + impl.getPath();
            else
                return null;
        }
        Operation operation = impl.getOperation();
        List<Input> inputs = operation.getInputs();
        String path = null;

        if (impl.getPath() != null && impl.getPath().trim().length() > 0)
            path = "/" + impl.getPath();

        //if (methodPath != null && methodPath.trim().length() > 0)
        //   path = "/" + methodPath;

        if (inputs == null || inputs.size() == 0)
            return path;

        StringBuffer buffer = new StringBuffer();
        Iterator<Input> iterator = inputs.iterator();
        while (iterator.hasNext()) {
            Input input = (Input) iterator.next();
            buffer.append("/{" + input.getName() + "}");
        }

        if (path != null)
            return path + buffer.toString();
        else
            return buffer.toString();
    }

    private String generateMethod(String resourceName, Method method, StringTemplate template, String methodName,
            Definitions defs) throws GeneratorException {
        template.setAttribute("MethodName", methodName);
        template.setAttribute("ResourceName", resourceName);

        Implementation impl = method.getImplementation();

        boolean operationValid = false;
        for (PortType pt : defs.getPortTypes()) {
            for (com.predic8.wsdl.Operation op : pt.getOperations()) {
                if (impl.getOperation().getName().equals(op.getName())) {
                    operationValid = true;
                    List<Fault> faults = op.getFaults();
                    for (Fault fault : faults) {
                        StringBuffer buffer = new StringBuffer();
                        String faultName = fault.getName();
                        if (!fault.getName().endsWith("Exception"))
                            faultName = fault.getName() + "_Exception";

                        buffer.append("catch(gov.nih.nci.restgen.generated.client." + faultName + " e)\n");
                        buffer.append("{\n");
                        buffer.append("\t e.printStackTrace();\n");
                        buffer.append("\t throw new WebApplicationException(buildResponseError(\"GET_METHOD\", \""
                                + resourceName + "\", \"" + methodName
                                + "\", \"Failed to process GET method\"+ e.toString()).build());\n");
                        buffer.append("}");
                        template.setAttribute("ResourceException", buffer.toString());

                    }
                }
            }
        }

        if (!operationValid) {
            throw new GeneratorException("Operation name mapping is missing for " + impl.getOperation().getName()
                    + ". Aborting the process!! ");
        }

        List<Service> services = defs.getServices();
        String portType = null;
        String portName = null;
        for (Service service : services) {
            List<Port> ports = service.getPorts();

            for (Port port : ports) {
                if (port.getName().equals(impl.getPortName())) {
                    Binding binding = port.getBinding();
                    portType = binding.getType().getLocalPart();
                    portName = port.getName();
                    template.setAttribute("PortType", portType);
                    template.setAttribute("PortName",
                            portName.substring(0, 1).toUpperCase() + portName.substring(1));
                    List<String[]> params = getMethodParameters(portType, impl.getOperation().getName());
                    String[] paramTypes = params.get(0);
                    String[] paramTypeNames = params.get(1);
                    String returnType = getMethodReturnType(portType, impl.getOperation().getName(), defs);
                    StringBuffer buffer = new StringBuffer();
                    for (int i = 0; i < paramTypes.length; i++) {
                        buffer.append(paramTypes[i] + " " + paramTypeNames[i]);
                        if (i < paramTypes.length - 1)
                            buffer.append(", ");
                    }
                    template.setAttribute("RequestType", buffer.toString());

                    buffer = new StringBuffer();
                    for (int i = 0; i < paramTypeNames.length; i++) {
                        buffer.append("\"" + paramTypeNames[i] + "\"");
                        if (i < paramTypeNames.length - 1)
                            buffer.append(", ");
                    }

                    String pathParam = constructPathParam(paramTypeNames, paramTypes, method.getName());
                    String pathParamPath = constructPathParamPath(impl, paramTypeNames, paramTypes,
                            method.getName());
                    String opParams = constructOperationParams(paramTypeNames);

                    if (!returnType.equals("void")) {
                        template.setAttribute("ReturnTypeNotVoid", true);
                        template.setAttribute("PostReturnType", returnType);
                        template.setAttribute("PutReturnType", returnType);
                        template.setAttribute("DeleteReturnType", returnType);
                    } else {
                        template.setAttribute("ReturnTypeResponse", true);
                        template.setAttribute("PostReturnType", "Response");
                        template.setAttribute("PutReturnType", "Response");
                        template.setAttribute("DeleteReturnType", "Response");
                    }
                    template.setAttribute("ReturnType", returnType);
                    if (returnType.startsWith("java.lang"))
                        template.setAttribute("ReturnTypePrimitive", true);
                    else
                        template.setAttribute("ReturnTypePrimitive", false);

                    template.setAttribute("OperationParameters", opParams);
                    if (pathParamPath != null) {
                        template.setAttribute("PathParamPath", "@Path(\"" + pathParamPath + "\")");
                        template.setAttribute("PathParamPathShort", pathParamPath);
                    }
                    template.setAttribute("PathParam", pathParam);
                    template.setAttribute("ParamNames", buffer.toString());
                }
            }
        }

        if (portType == null || portType.trim().length() == 0)
            throw new GeneratorException("Port type information is missing. Please check the WSDL!");

        template.setAttribute("ServiceName", impl.getName());
        template.setAttribute("OperationName", impl.getOperation().getName());
        template.setAttribute("ServiceNamespace", defs.getNamespaceContext().toString());
        template.setAttribute("WSDLURL", context.getMapping().getOptions().getWsdlLocation());

        return template.toString();
    }

    private String constructPathParam(String[] paramNames, String[] paramTypes, String methodName)
            throws GeneratorException {
        if ((paramNames.length != paramTypes.length))
            throw new GeneratorException("Failed to parse path paramters.");
        StringBuffer buffer = new StringBuffer();
        boolean found = false;
        for (int i = 0; i < paramNames.length; i++) {
            buffer.append("@PathParam(\"" + paramNames[i] + "\") " + paramTypes[i] + " " + paramNames[i]);
            found = true;
            if (i < paramNames.length - 1)
                buffer.append(", ");
        }
        if (found && methodName.equals(Method.GET))
            return buffer.toString() + ",";
        else
            return buffer.toString();
    }

    private String constructPathParamPath(Implementation impl, String[] paramNames, String[] paramTypes,
            String methodName) throws GeneratorException {

        if (methodName.equals(Method.POST) || methodName.equals(Method.PUT)) {
            if (impl.getPath() != null && impl.getPath().trim().length() > 0)
                return "/" + impl.getPath();
            else
                return null;
        }

        StringBuffer buffer = new StringBuffer();
        if (impl.getPath() != null && impl.getPath().trim().length() > 0)
            buffer.append("/" + impl.getPath());

        if ((paramNames.length != paramTypes.length))
            throw new GeneratorException("Failed to parse path paramters.");

        for (int i = 0; i < paramNames.length; i++) {
            buffer.append("/{" + paramNames[i] + "}");
        }
        return buffer.toString();
    }

    private String constructOperationParams(String[] paramNames) throws GeneratorException {
        if (paramNames == null || paramNames.length == 0)
            return "";
        StringBuffer buffer = new StringBuffer();
        for (int i = 0; i < paramNames.length; i++) {
            buffer.append(paramNames[i]);
            if (i < paramNames.length - 1)
                buffer.append(",");
        }

        return buffer.toString();
    }

    private List<String[]> getMethodParameters(String portName, String operationName) throws GeneratorException {
        File file = new File(context.getMapping().getOptions().getOutputPath() + File.separator);
        List<String[]> returnType = new ArrayList<String[]>();
        try {
            // Convert File to a URL
            URL url = file.toURI().toURL();
            URL[] urls = new URL[] { url };

            // Create a new class loader with the directory
            ClassLoader cl = new URLClassLoader(urls);

            Class klass = cl.loadClass("gov.nih.nci.restgen.generated.client." + portName);
            java.lang.reflect.Method[] methods = klass.getDeclaredMethods();
            for (int i = 0; i < methods.length; i++) {
                java.lang.reflect.Method cMethod = methods[i];
                if (cMethod.getName().equals(operationName)) {
                    Annotation[][] annotations = cMethod.getParameterAnnotations();
                    Class[] params = cMethod.getParameterTypes();
                    String[] strParams = new String[params.length];
                    String[] strParamNames = new String[params.length];
                    for (int x = 0; x < params.length; x++) {
                        strParams[x] = params[x].getName();
                        for (int j = 0; j < annotations.length; j++) {
                            if (annotations[x][j].annotationType().getName().equals("javax.jws.WebParam")) {
                                strParamNames[x] = (String) AnnotationUtils.getValue(annotations[x][j], "name");
                                break;
                            }
                        }
                    }
                    returnType.add(strParams);
                    returnType.add(strParamNames);

                    return returnType;
                }
            }

        } catch (MalformedURLException e) {
            e.printStackTrace();
            throw new GeneratorException("Failed to load compiled client classes", e);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            throw new GeneratorException("Failed to load compiled client classes", e);
        } catch (SecurityException e) {
            e.printStackTrace();
            throw new GeneratorException("Failed to load compiled client classes", e);
        }
        return null;
    }

    private String getMethodReturnType(String portName, String operationName, Definitions defs)
            throws GeneratorException {
        File file = new File(context.getMapping().getOptions().getOutputPath() + File.separator);

        try {
            URL url = file.toURI().toURL();
            URL[] urls = new URL[] { url };

            ClassLoader cl = new URLClassLoader(urls);

            Class klass = cl.loadClass("gov.nih.nci.restgen.generated.client." + portName);
            java.lang.reflect.Method[] methods = klass.getDeclaredMethods();
            for (int i = 0; i < methods.length; i++) {
                java.lang.reflect.Method cMethod = methods[i];
                if (cMethod.getName().equals(operationName)) {
                    String rType = cMethod.getReturnType().getName();
                    if (rType.startsWith("java.util.")) {
                        String genericType = getOperationReturnTypeFromWSDL(portName, operationName, defs);
                        if (genericType != null) {
                            return rType + "<" + genericType + ">";
                        } else {
                            return rType;
                        }
                    } else if (rType.startsWith("java.lang.")) {
                        return "java.lang.String";
                    } else
                        return rType;

                }
            }

        } catch (MalformedURLException e) {
            e.printStackTrace();
            throw new GeneratorException("Failed to load compiled client classes", e);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            throw new GeneratorException("Failed to load compiled client classes", e);
        }
        return null;
    }

    private String getOperationReturnTypeFromWSDL(String portName, String operationName, Definitions defs)
            throws GeneratorException {
        String returnType = null;
        for (PortType pt : defs.getPortTypes()) {
            for (com.predic8.wsdl.Operation op : pt.getOperations()) {
                if (operationName.equals(op.getName())) {
                    com.predic8.wsdl.Output output = op.getOutput();
                    List<Schema> schemas = defs.getSchemas();
                    String outputName = output.getName();
                    if (outputName == null)
                        outputName = output.getMessage().getName();
                    for (Schema schema : schemas) {
                        //if(schema.getNamespaceContext() != null)
                        //   continue;
                        List<ComplexType> types = schema.getComplexTypes();
                        ComplexType complex = null;
                        if (types.size() != 0) {
                            complex = schema.getComplexType(outputName);
                        }

                        if (complex == null) {
                            try {
                                Element schemaElement = schema.getElement(outputName);
                                complex = (ComplexType) schemaElement.getEmbeddedType();
                            } catch (Exception e) {
                                continue;
                            }
                        }
                        if (complex == null)
                            throw new GeneratorException("Failed to parse complex type for " + output.getName());
                        List<Element> elements = complex.getSequence().getElements();
                        Element element = elements.get(0);
                        String qName = element.getType().getQualifiedName();
                        if (qName.contains(":"))
                            qName = qName.substring(qName.indexOf(":") + 1);

                        String uqName = qName.substring(0, 1).toUpperCase() + qName.substring(1);
                        if (schema.getComplexType(qName) != null)
                            return "gov.nih.nci.restgen.generated.client." + uqName;
                        else
                            return uqName;
                    }
                }
            }
        }
        return returnType;
    }

    protected void postProcess() {
        getContext().getLogger().info("Generating RESTful resource...Completed!");
    }

}