com.webcohesion.enunciate.modules.java_xml_client.JavaXMLClientModule.java Source code

Java tutorial

Introduction

Here is the source code for com.webcohesion.enunciate.modules.java_xml_client.JavaXMLClientModule.java

Source

/*
 * Copyright 2006-2008 Web Cohesion
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.webcohesion.enunciate.modules.java_xml_client;

import com.sun.tools.javac.api.JavacTool;
import com.webcohesion.enunciate.Enunciate;
import com.webcohesion.enunciate.EnunciateContext;
import com.webcohesion.enunciate.EnunciateException;
import com.webcohesion.enunciate.api.resources.MediaTypeDescriptor;
import com.webcohesion.enunciate.api.resources.Method;
import com.webcohesion.enunciate.api.resources.Resource;
import com.webcohesion.enunciate.api.resources.ResourceGroup;
import com.webcohesion.enunciate.artifacts.ArtifactType;
import com.webcohesion.enunciate.artifacts.ClientLibraryArtifact;
import com.webcohesion.enunciate.artifacts.FileArtifact;
import com.webcohesion.enunciate.facets.FacetFilter;
import com.webcohesion.enunciate.javac.decorations.SourcePosition;
import com.webcohesion.enunciate.metadata.DocumentationExample;
import com.webcohesion.enunciate.module.*;
import com.webcohesion.enunciate.modules.jaxb.EnunciateJaxbContext;
import com.webcohesion.enunciate.modules.jaxb.JaxbModule;
import com.webcohesion.enunciate.modules.jaxb.model.QNameEnumTypeDefinition;
import com.webcohesion.enunciate.modules.jaxb.model.Registry;
import com.webcohesion.enunciate.modules.jaxb.model.SchemaInfo;
import com.webcohesion.enunciate.modules.jaxb.model.TypeDefinition;
import com.webcohesion.enunciate.modules.jaxb.model.util.JAXBErrors;
import com.webcohesion.enunciate.modules.jaxrs.JaxrsModule;
import com.webcohesion.enunciate.modules.jaxws.JaxwsModule;
import com.webcohesion.enunciate.modules.jaxws.WsdlInfo;
import com.webcohesion.enunciate.modules.jaxws.model.*;
import com.webcohesion.enunciate.util.AntPatternMatcher;
import com.webcohesion.enunciate.util.freemarker.*;
import freemarker.cache.URLTemplateLoader;
import freemarker.core.Environment;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateExceptionHandler;
import org.apache.commons.configuration.HierarchicalConfiguration;

import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;

/**
 * @author Ryan Heaton
 */
public class JavaXMLClientModule extends BasicGeneratingModule
        implements ApiFeatureProviderModule, ProjectExtensionModule {

    private static final String LIRBARY_DESCRIPTION_PROPERTY = "com.webcohesion.enunciate.modules.java_xml_client.EnunciateJavaXMLClientModule#LIRBARY_DESCRIPTION_PROPERTY";

    JaxbModule jaxbModule;
    JaxwsModule jaxwsModule;
    JaxrsModule jaxrsModule;

    /**
     * @return "java-xml"
     */
    @Override
    public String getName() {
        return "java-xml-client";
    }

    @Override
    public List<DependencySpec> getDependencySpecifications() {
        return Arrays.asList((DependencySpec) new DependencySpec() {
            @Override
            public boolean accept(EnunciateModule module) {
                if (module instanceof JaxbModule) {
                    jaxbModule = (JaxbModule) module;
                    return true;
                } else if (module instanceof JaxwsModule) {
                    jaxwsModule = (JaxwsModule) module;
                    return true;
                } else if (module instanceof JaxrsModule) {
                    jaxrsModule = (JaxrsModule) module;
                    return true;
                }

                return module instanceof ApiRegistryProviderModule;
            }

            @Override
            public boolean isFulfilled() {
                return true;
            }

            @Override
            public String toString() {
                return "optional jaxb, optional jaxws, optional jaxrs";
            }
        });
    }

    @Override
    public void call(EnunciateContext context) {
        if (this.jaxbModule == null || this.jaxbModule.getJaxbContext() == null
                || this.jaxbModule.getJaxbContext().getSchemas().isEmpty()) {
            info("No JAXB XML data types: Java XML client will not be generated.");
            return;
        }

        List<String> namingConflicts = JAXBErrors
                .findConflictingAccessorNamingErrors(this.jaxbModule.getJaxbContext());
        if (namingConflicts != null && !namingConflicts.isEmpty()) {
            error("JAXB naming conflicts have been found:");
            for (String namingConflict : namingConflicts) {
                error(namingConflict);
            }
            error("These naming conflicts are often between the field and it's associated property, in which case you need to use one or two of the following strategies to avoid the conflicts:");
            error("1. Explicitly exclude one or the other.");
            error("2. Put the annotations on the property instead of the field.");
            error("3. Tell JAXB to use a different process for detecting accessors using the @XmlAccessorType annotation.");
            throw new EnunciateException("JAXB naming conflicts detected.");
        }

        File sourceDir = generateClientSources();
        File compileDir = compileClientSources(sourceDir);
        File resourcesDir = copyResources();

        packageArtifacts(sourceDir, resourcesDir, compileDir);
    }

    protected File generateClientSources() {
        File sourceDir = getSourceDir();
        sourceDir.mkdirs();

        Map<String, Object> model = new HashMap<String, Object>();

        Map<String, String> conversions = getClientPackageConversions();
        EnunciateJaxbContext jaxbContext = this.jaxbModule.getJaxbContext();
        ClientClassnameForMethod classnameFor = new ClientClassnameForMethod(conversions, jaxbContext);
        model.put("packageFor", new ClientPackageForMethod(conversions, this.context));
        model.put("classnameFor", classnameFor);
        model.put("simpleNameFor", new SimpleNameForMethod(classnameFor));
        model.put("file", new FileDirective(sourceDir, this.enunciate.getLogger()));
        model.put("generatedCodeLicense", this.enunciate.getConfiguration().readGeneratedCodeLicenseFile());
        model.put("annotationValue", new AnnotationValueMethod());

        Set<String> facetIncludes = new TreeSet<String>(this.enunciate.getConfiguration().getFacetIncludes());
        facetIncludes.addAll(getFacetIncludes());
        Set<String> facetExcludes = new TreeSet<String>(this.enunciate.getConfiguration().getFacetExcludes());
        facetExcludes.addAll(getFacetExcludes());
        FacetFilter facetFilter = new FacetFilter(facetIncludes, facetExcludes);

        model.put("isFacetExcluded", new IsFacetExcludedMethod(facetFilter));

        boolean upToDate = isUpToDateWithSources(sourceDir);
        if (!upToDate) {
            try {
                debug("Generating the Java client classes...");

                HashMap<String, WebFault> allFaults = new HashMap<String, WebFault>();
                AntPatternMatcher matcher = new AntPatternMatcher();
                matcher.setPathSeparator(".");

                if (this.jaxwsModule != null) {
                    Set<String> seeAlsos = new TreeSet<String>();
                    // Process the annotations, the request/response beans, and gather the set of web faults
                    // for each endpoint interface.
                    for (WsdlInfo wsdlInfo : this.jaxwsModule.getJaxwsContext().getWsdls().values()) {
                        for (EndpointInterface ei : wsdlInfo.getEndpointInterfaces()) {
                            if (facetFilter.accept(ei)) {
                                for (WebMethod webMethod : ei.getWebMethods()) {
                                    if (facetFilter.accept(webMethod)) {
                                        for (WebMessage webMessage : webMethod.getMessages()) {
                                            if (webMessage instanceof RequestWrapper) {
                                                model.put("message", webMessage);
                                                processTemplate(getTemplateURL("client-request-bean.fmt"), model);
                                                seeAlsos.add(getBeanName(classnameFor,
                                                        ((RequestWrapper) webMessage).getRequestBeanName()));
                                            } else if (webMessage instanceof ResponseWrapper) {
                                                model.put("message", webMessage);
                                                processTemplate(getTemplateURL("client-response-bean.fmt"), model);
                                                seeAlsos.add(getBeanName(classnameFor,
                                                        ((ResponseWrapper) webMessage).getResponseBeanName()));
                                            } else if (webMessage instanceof WebFault) {
                                                WebFault fault = (WebFault) webMessage;
                                                allFaults.put(fault.getQualifiedName().toString(), fault);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }

                    //gather the annotation information and process the possible beans for each web fault.
                    for (WebFault webFault : allFaults.values()) {
                        boolean implicit = webFault.isImplicitSchemaElement();
                        String faultBean = implicit
                                ? getBeanName(classnameFor, webFault.getImplicitFaultBeanQualifiedName())
                                : classnameFor.convert(webFault.getExplicitFaultBeanType());
                        seeAlsos.add(faultBean);

                        if (implicit) {
                            model.put("fault", webFault);
                            processTemplate(getTemplateURL("client-fault-bean.fmt"), model);
                        }
                    }

                    model.put("seeAlsoBeans", seeAlsos);
                    model.put("baseUri", this.enunciate.getConfiguration().getApplicationRoot());
                    for (WsdlInfo wsdlInfo : this.jaxwsModule.getJaxwsContext().getWsdls().values()) {
                        if (wsdlInfo.getWsdlFile() == null) {
                            throw new EnunciateException("WSDL " + wsdlInfo.getId() + " doesn't have a filename.");
                        }

                        for (EndpointInterface ei : wsdlInfo.getEndpointInterfaces()) {
                            if (facetFilter.accept(ei)) {
                                model.put("endpointInterface", ei);
                                model.put("wsdlFileName", wsdlInfo.getFilename());

                                processTemplate(getTemplateURL("client-endpoint-interface.fmt"), model);
                                processTemplate(getTemplateURL("client-soap-endpoint-impl.fmt"), model);
                            }
                        }
                    }

                    for (WebFault webFault : allFaults.values()) {
                        if (useServerSide(webFault, matcher)) {
                            copyServerSideType(sourceDir, webFault);
                        } else {
                            TypeElement superFault = (TypeElement) ((DeclaredType) webFault.getSuperclass())
                                    .asElement();
                            if (superFault != null
                                    && allFaults.containsKey(superFault.getQualifiedName().toString())
                                    && allFaults.get(superFault.getQualifiedName().toString())
                                            .isImplicitSchemaElement()) {
                                model.put("superFault", allFaults.get(superFault.getQualifiedName().toString()));
                            } else {
                                model.remove("superFault");
                            }

                            model.put("fault", webFault);
                            processTemplate(getTemplateURL("client-web-fault.fmt"), model);
                        }
                    }
                }

                for (SchemaInfo schemaInfo : this.jaxbModule.getJaxbContext().getSchemas().values()) {
                    for (TypeDefinition typeDefinition : schemaInfo.getTypeDefinitions()) {
                        if (facetFilter.accept(typeDefinition)) {
                            if (useServerSide(typeDefinition, matcher)) {
                                copyServerSideType(sourceDir, typeDefinition);
                            } else {
                                model.put("rootEl",
                                        this.jaxbModule.getJaxbContext().findElementDeclaration(typeDefinition));
                                model.put("type", typeDefinition);
                                URL template = typeDefinition.isEnum()
                                        ? typeDefinition instanceof QNameEnumTypeDefinition
                                                ? getTemplateURL("client-qname-enum-type.fmt")
                                                : getTemplateURL("client-enum-type.fmt")
                                        : typeDefinition.isSimple() ? getTemplateURL("client-simple-type.fmt")
                                                : getTemplateURL("client-complex-type.fmt");
                                processTemplate(template, model);
                            }
                        }
                    }

                    for (Registry registry : schemaInfo.getRegistries()) {
                        model.put("registry", registry);
                        processTemplate(getTemplateURL("client-registry.fmt"), model);
                    }
                }
            } catch (IOException e) {
                throw new EnunciateException(e);
            } catch (TemplateException e) {
                throw new EnunciateException(e);
            }
        } else {
            info("Skipping generation of Java client sources as everything appears up-to-date...");
        }

        context.setProperty(LIRBARY_DESCRIPTION_PROPERTY, readLibraryDescription(model));

        return sourceDir;
    }

    protected void copyServerSideType(File sourceDir, TypeElement type) throws IOException {
        SourcePosition source = this.context.getProcessingEnvironment().findSourcePosition(type);
        JavaFileObject sourceFile = source.getSourceFile();
        File destFile = getServerSideDestFile(sourceDir, sourceFile, type);
        FileWriter writer = new FileWriter(destFile);
        debug("Writing server-side java type to %s.", destFile);
        writer.write(sourceFile.getCharContent(false).toString());
        writer.flush();
        writer.close();
    }

    protected File getSourceDir() {
        return new File(new File(this.enunciate.getBuildDir(), getName()), "src");
    }

    /**
     * Processes the specified template with the given model.
     *
     * @param templateURL The template URL.
     * @param model       The root model.
     */
    public String processTemplate(URL templateURL, Object model) throws IOException, TemplateException {
        debug("Processing template %s.", templateURL);
        Configuration configuration = new Configuration(Configuration.VERSION_2_3_22);

        configuration.setTemplateLoader(new URLTemplateLoader() {
            protected URL getURL(String name) {
                try {
                    return new URL(name);
                } catch (MalformedURLException e) {
                    return null;
                }
            }
        });

        configuration.setTemplateExceptionHandler(new TemplateExceptionHandler() {
            public void handleTemplateException(TemplateException templateException, Environment environment,
                    Writer writer) throws TemplateException {
                throw templateException;
            }
        });

        configuration.setLocalizedLookup(false);
        configuration.setDefaultEncoding("UTF-8");
        configuration.setObjectWrapper(new JavaXMLClientObjectWrapper());
        Template template = configuration.getTemplate(templateURL.toString());
        StringWriter unhandledOutput = new StringWriter();
        template.process(model, unhandledOutput);
        unhandledOutput.close();
        return unhandledOutput.toString();
    }

    protected File getServerSideDestFile(File sourceDir, JavaFileObject sourceFile, TypeElement declaration) {
        File destDir = sourceDir;
        String packageName = this.context.getProcessingEnvironment().getElementUtils().getPackageOf(declaration)
                .getQualifiedName().toString();
        for (StringTokenizer packagePaths = new StringTokenizer(packageName, "."); packagePaths.hasMoreTokens();) {
            String packagePath = packagePaths.nextToken();
            destDir = new File(destDir, packagePath);
        }
        destDir.mkdirs();
        String simpleFilename = sourceFile.toUri().toString();
        simpleFilename = simpleFilename.substring(simpleFilename.lastIndexOf('/'));
        return new File(destDir, simpleFilename);
    }

    /**
     * Whether to use the server-side declaration for this declaration.
     *
     * @param declaration The declaration.
     * @param matcher     The matcher.
     * @return Whether to use the server-side declaration for this declaration.
     */
    protected boolean useServerSide(TypeElement declaration, AntPatternMatcher matcher) {
        boolean useServerSide = false;

        for (String pattern : getServerSideTypesToUse()) {
            if (matcher.match(pattern, declaration.getQualifiedName().toString())) {
                useServerSide = true;
                break;
            }
        }
        return useServerSide;
    }

    /**
     * Get the bean name for a specified string.
     *
     * @param conversion The conversion to use.
     * @param preconvert The pre-converted fqn.
     * @return The converted fqn.
     */
    protected String getBeanName(ClientClassnameForMethod conversion, String preconvert) {
        String pckg = conversion.convert(preconvert.substring(0, preconvert.lastIndexOf('.')));
        String simpleName = preconvert.substring(preconvert.lastIndexOf('.') + 1);
        return pckg + "." + simpleName;
    }

    protected File compileClientSources(File sourceDir) {
        File compileDir = getCompileDir();
        compileDir.mkdirs();

        //Compile the java files.
        if (!isDisableCompile()) {
            if (!isUpToDateWithSources(compileDir)) {
                List<File> sources = findJavaFiles(sourceDir);
                if (sources != null && !sources.isEmpty()) {
                    String classpath = this.enunciate.writeClasspath(enunciate.getClasspath());
                    JavaCompiler compiler = JavacTool.create();
                    List<String> options = Arrays.asList("-source", "1.5", "-target", "1.5", "-encoding", "UTF-8",
                            "-cp", classpath, "-d", compileDir.getAbsolutePath(), "-nowarn");
                    JavaCompiler.CompilationTask task = compiler.getTask(null, null, null, options, null,
                            compiler.getStandardFileManager(null, null, null).getJavaFileObjectsFromFiles(sources));
                    if (!task.call()) {
                        throw new EnunciateException("Compile failed of Java client-side classes.");
                    }
                } else {
                    debug("No Java XML client classes to compile.");
                }
            } else {
                info("Skipping compilation of Java client classes as everything appears up-to-date...");
            }
        }

        return compileDir;

    }

    private List<File> findJavaFiles(File sourceDir) {
        final ArrayList<File> javaFiles = new ArrayList<File>();
        this.enunciate.visitFiles(sourceDir, Enunciate.JAVA_FILTER, new Enunciate.FileVisitor() {
            @Override
            public void visit(File file) {
                javaFiles.add(file);
            }
        });
        return javaFiles;
    }

    protected File getCompileDir() {
        return new File(new File(this.enunciate.getBuildDir(), getName()), "classes");
    }

    protected File copyResources() {
        File resourcesDir = getResourcesDir();
        resourcesDir.mkdirs();

        try {
            for (WsdlInfo wsdlInfo : this.jaxwsModule.getJaxwsContext().getWsdls().values()) {
                if (wsdlInfo.getWsdlFile() != null) {
                    wsdlInfo.getWsdlFile().writeTo(resourcesDir);
                }
            }

            for (SchemaInfo schemaInfo : this.jaxbModule.getJaxbContext().getSchemas().values()) {
                if (schemaInfo.getSchemaFile() != null) {
                    schemaInfo.getSchemaFile().writeTo(resourcesDir);
                }
            }
        } catch (IOException e) {
            throw new EnunciateException(e);
        }

        return resourcesDir;

    }

    protected File getResourcesDir() {
        return new File(new File(this.enunciate.getBuildDir(), getName()), "resources");
    }

    protected File packageArtifacts(File sourceDir, File resourcesDir, File compileDir) {
        File packageDir = getPackageDir();
        packageDir.mkdirs();

        try {
            String jarName = getJarName();

            File clientJarFile = null;
            if (!isDisableCompile()) {
                clientJarFile = new File(packageDir, jarName);
                if (!isUpToDateWithSources(clientJarFile)) {
                    if (isBundleSourcesWithClasses()) {
                        boolean anyFiles = this.enunciate.zip(clientJarFile, sourceDir, resourcesDir, compileDir);
                        if (!anyFiles) {
                            clientJarFile = null;
                        }
                    } else {
                        boolean anyFiles = this.enunciate.zip(clientJarFile, resourcesDir, compileDir);
                        if (!anyFiles) {
                            clientJarFile = null;
                        }
                    }
                } else {
                    info("Skipping creation of Java client jar as everything appears up-to-date...");
                }
            }

            File clientSourcesJarFile = null;
            if (!isBundleSourcesWithClasses()) {
                clientSourcesJarFile = new File(packageDir, jarName.replaceFirst("\\.jar", "-xml-sources.jar"));
                if (!isUpToDateWithSources(clientSourcesJarFile)) {
                    boolean anyFiles = this.enunciate.zip(clientSourcesJarFile, sourceDir, resourcesDir);
                    if (!anyFiles) {
                        clientSourcesJarFile = null;
                    }
                } else {
                    info("Skipping creation of the Java client source jar as everything appears up-to-date...");
                }
            }

            ClientLibraryArtifact artifactBundle = new ClientLibraryArtifact(getName(), "java.xml.client.library",
                    "Java XML Client Library");
            artifactBundle.setPlatform("Java (Version 5+)");
            //read in the description from file:
            artifactBundle.setDescription((String) context.getProperty(LIRBARY_DESCRIPTION_PROPERTY));
            if (clientJarFile != null) {
                FileArtifact binariesJar = new FileArtifact(getName(), "java.xml.client.library.binaries",
                        clientJarFile);
                binariesJar.setDescription("The binaries for the Java XML client library.");
                binariesJar.setPublic(false);
                binariesJar.setArtifactType(ArtifactType.binaries);
                artifactBundle.addArtifact(binariesJar);
                this.enunciate.addArtifact(binariesJar);
            }

            if (clientSourcesJarFile != null) {
                FileArtifact sourcesJar = new FileArtifact(getName(), "java.xml.client.library.sources",
                        clientSourcesJarFile);
                sourcesJar.setDescription("The sources for the Java XML client library.");
                sourcesJar.setPublic(false);
                sourcesJar.setArtifactType(ArtifactType.sources);
                artifactBundle.addArtifact(sourcesJar);
                this.enunciate.addArtifact(sourcesJar);
            }

            if (clientJarFile != null || clientSourcesJarFile != null) {
                this.enunciate.addArtifact(artifactBundle);
            }
        } catch (IOException e) {
            throw new EnunciateException(e);
        }

        return packageDir;
    }

    protected File getPackageDir() {
        return new File(new File(this.enunciate.getBuildDir(), getName()), "build");
    }

    /**
     * Reads a resource into string form.
     *
     * @return The string form of the resource.
     */
    protected String readLibraryDescription(Map<String, Object> model) {
        model.put("sample_service_method", findExampleWebMethod());
        model.put("sample_resource", findExampleResourceMethod());
        model.put("mediaTypeFor", new MediaTypeForMethod());

        URL res = JavaXMLClientModule.class.getResource("library_description.fmt");
        try {
            return processTemplate(res, model);
        } catch (TemplateException e) {
            throw new EnunciateException(e);
        } catch (IOException e) {
            throw new EnunciateException(e);
        }
    }

    /**
     * Finds an example resource method, according to the following preference order:
     *
     * <ol>
     * <li>The first method annotated with {@link DocumentationExample}.
     * <li>The first web method that returns a declared type.
     * <li>The first web method.
     * </ol>
     *
     * @return An example resource method, or if no good examples were found.
     */
    public WebMethod findExampleWebMethod() {
        WebMethod example = null;
        for (EndpointInterface ei : this.jaxwsModule.getJaxwsContext().getEndpointInterfaces()) {
            for (WebMethod method : ei.getWebMethods()) {
                if (method.getAnnotation(DocumentationExample.class) != null
                        && !method.getAnnotation(DocumentationExample.class).exclude()) {
                    return method;
                } else if (method.getWebResult() != null && method.getWebResult().getType() instanceof DeclaredType
                        && (example == null || example.getWebResult() == null
                                || (!(example.getWebResult().getType() instanceof DeclaredType)))) {
                    example = method;
                } else {
                    //we'll prefer the first one we find with an output.
                    example = example == null ? method : example;
                }
            }
        }
        return example;
    }

    /**
     * Finds an example resource method, according to the following preference order:
     *
     * <ol>
     * <li>The first method annotated with {@link DocumentationExample}.
     * <li>The first method with BOTH an output payload with a known XML element and an input payload with a known XML element.
     * <li>The first method with an output payload with a known XML element.
     * </ol>
     *
     * @return An example resource method, or if no good examples were found.
     */
    public Method findExampleResourceMethod() {
        Method example = null;
        List<ResourceGroup> resourceGroups = this.jaxrsModule.getJaxrsContext().getResourceGroups();
        for (ResourceGroup resourceGroup : resourceGroups) {
            List<Resource> resources = resourceGroup.getResources();
            for (Resource resource : resources) {
                for (Method method : resource.getMethods()) {
                    if (hasXmlResponseEntity(method)) {
                        if (hasXmlRequestEntity(method)) {
                            //we'll prefer one with both an output AND an input.
                            return method;
                        } else {
                            //we'll prefer the first one we find with an output.
                            example = example == null ? method : example;
                        }
                    }
                }
            }
        }

        return example;
    }

    private boolean hasXmlResponseEntity(Method method) {
        if (method.getResponseEntity() != null) {
            for (MediaTypeDescriptor mediaTypeDescriptor : method.getResponseEntity().getMediaTypes()) {
                if (EnunciateJaxbContext.SYNTAX_LABEL.equals(mediaTypeDescriptor.getSyntax())) {
                    return true;
                }
            }
        }
        return false;
    }

    private boolean hasXmlRequestEntity(Method method) {
        if (method.getRequestEntity() != null) {
            for (MediaTypeDescriptor mediaTypeDescriptor : method.getRequestEntity().getMediaTypes()) {
                if (EnunciateJaxbContext.SYNTAX_LABEL.equals(mediaTypeDescriptor.getSyntax())) {
                    return true;
                }
            }
        }
        return false;
    }

    protected URL getTemplateURL(String template) {
        return JavaXMLClientModule.class.getResource(template);
    }

    public String getJarName() {
        return this.config.getString("[@jarName]", getSlug() + "-xml-client.jar");
    }

    public Map<String, String> getClientPackageConversions() {
        List<HierarchicalConfiguration> conversionElements = this.config
                .configurationsAt("package-conversions.convert");
        HashMap<String, String> conversions = new HashMap<String, String>();
        for (HierarchicalConfiguration conversionElement : conversionElements) {
            conversions.put(conversionElement.getString("[@from]"), conversionElement.getString("[@to]"));
        }
        return conversions;
    }

    public Set<String> getServerSideTypesToUse() {
        List<HierarchicalConfiguration> typeElements = this.config.configurationsAt("server-side-type");
        TreeSet<String> types = new TreeSet<String>();
        for (HierarchicalConfiguration typeElement : typeElements) {
            types.add(typeElement.getString("[@pattern]"));
        }
        return types;
    }

    public String getSlug() {
        return this.config.getString("[@slug]", this.enunciate.getConfiguration().getSlug());
    }

    public boolean isBundleSourcesWithClasses() {
        return this.config.getBoolean("[@bundleSourcesWithClasses]", false);
    }

    public List<File> getProjectSources() {
        return Collections.emptyList();
    }

    public List<File> getProjectTestSources() {
        return Arrays.asList(getSourceDir());
    }

    public List<File> getProjectResourceDirectories() {
        return Collections.emptyList();
    }

    public List<File> getProjectTestResourceDirectories() {
        return Arrays.asList(getResourcesDir());
    }

    /**
     * Whether to disable the compilation of the java sources (default: false).
     *
     * @return Whether to disable the compilation of the java sources (default: false).
     */
    public boolean isDisableCompile() {
        return this.config.getBoolean("[@disableCompile]", false);
    }

    public Set<String> getFacetIncludes() {
        List<Object> includes = this.config.getList("facets.include[@name]");
        Set<String> facetIncludes = new TreeSet<String>();
        for (Object include : includes) {
            facetIncludes.add(String.valueOf(include));
        }
        return facetIncludes;
    }

    public Set<String> getFacetExcludes() {
        List<Object> excludes = this.config.getList("facets.exclude[@name]");
        Set<String> facetExcludes = new TreeSet<String>();
        for (Object exclude : excludes) {
            facetExcludes.add(String.valueOf(exclude));
        }
        return facetExcludes;
    }

}