com.google.gct.intellij.endpoints.generator.template.TemplateHelper.java Source code

Java tutorial

Introduction

Here is the source code for com.google.gct.intellij.endpoints.generator.template.TemplateHelper.java

Source

/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * 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.google.gct.intellij.endpoints.generator.template;

import com.google.common.base.Charsets;
import com.google.common.io.Resources;
import com.google.gct.intellij.endpoints.util.PsiUtils;

import com.intellij.ide.highlighter.JavaFileType;
import com.intellij.ide.highlighter.XmlFileType;
import com.intellij.openapi.fileTypes.PlainTextFileType;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiField;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiJavaFile;
import com.intellij.psi.util.PropertyUtil;

import java.beans.Introspector;
import java.io.IOException;
import java.net.URL;

/**
 * Functionality to help load in templates for AppEngine endpoints module
 */
public class TemplateHelper {

    /**
     * Helper class to track of ownerDomain and packagePath information for a
     * given Cloud Endpoint.
     */
    public static class EndpointPackageInfo {

        private final String ownerDomain;
        private final String packagePath;

        public EndpointPackageInfo(String ownerDomain, String packagePath) {
            this.ownerDomain = ownerDomain;
            this.packagePath = packagePath;
        }

        public String getOwnerDomain() {
            return ownerDomain;
        }

        public String getPackagePath() {
            return packagePath;
        }

        /**
         * Returns ownerDomain.packagePath, unless ownerDomain is empty. In that
         * case, just ownerDomain is returned.
         */
        @Override
        public String toString() {
            return (packagePath.length() == 0 ? ownerDomain : ownerDomain + "." + packagePath);
        }
    }

    /**
     * Given a root package, generates the Cloud Endpoint ownerDomain and
     * packagePath information.
     *
     * If rootPackage is com.foo.bar, then the ownerDomain will be "foo.com", and
     * the packagePath will be "bar".
     *
     * As another example, if the rootPackage is "com.foo.bar.baz", the
     * ownerDomain is still "foo.com", and the packgePath is "bar.baz".
     *
     * In the case where the rootPackage has only two components, packagePath is
     * the empty string.
     *
     * If rootPackage has less than two components, then
     * <code>DEFAULT_PACKAGE_INFO</code> will be returned.
     *
     * @param rootPackage the root package. Cannot be null.
     */
    public static EndpointPackageInfo getEndpointPackageInfo(String rootPackage) {

        assert (rootPackage != null);

        String[] packageComponents = rootPackage.split("\\.");

        String ownerDomain = "";
        String packagePath = "";

        if (packageComponents.length < 2) {
            return DEFAULT_PACKAGE_INFO;
        } else {
            ownerDomain = packageComponents[1] + "." + packageComponents[0];
            for (int i = 2; i < packageComponents.length; i++) {
                packagePath += packageComponents[i];
                if (i != packageComponents.length - 1) {
                    packagePath += ".";
                }
            }
        }

        return new EndpointPackageInfo(ownerDomain, packagePath);
    }

    public static final EndpointPackageInfo DEFAULT_PACKAGE_INFO = new EndpointPackageInfo("mycompany.com",
            "services");

    private static final String FILE_TEMPLATE_MANAGER_FACTORY_CLASS = "ManagerFactoryClass.java.template";
    private static final String FILE_TEMPLATE_JPA_SWARM_SERVICE = "JpaSwarmService.java.template";
    private static final String FILE_TEMPLATE_PERSISTENCE_XML = "persistence.xml.template";
    private static final String FILE_TEMPLATE_WEB_XML = "web.xml.template";
    private static final String FILE_TEMPLATE_APPENGINE_WEB_XML = "appengine-web.xml.template";
    private static final String FILE_TEMPLATE_POM_XML = "pom.xml.template";
    private static final String FILE_TEMPLATE_BUILD_GRADLE = "build.gradle.template";

    private static final String TEMPLATE_MAVEN_ARTIFACT_NAME = "@MavenArtifactName@";
    private static final String TEMPLATE_APP_ID = "@AppId@";
    private static final String TEMPLATE_API_KEY = "@ApiKey@";
    private static final String TEMPLATE_API_NAME = "@ApiName@";
    private static final String TEMPLATE_ENDPOINT_OWNER_DOMAIN = "@EndpointOwnerDomain@";
    private static final String TEMPLATE_ENDPOINT_PACKAGE_PATH = "@EndpointPackagePath@";
    private static final String TEMPLATE_ENTITY_NAME = "@EntityName@";
    private static final String TEMPLATE_ENTITY_NAME_LOWER_CASE = "@EntityNameLowerCase@";
    private static final String TEMPLATE_ID_TYPE = "@IdType@";
    private static final String TEMPLATE_ID_GETTER = "@GetId@";
    private static final String TEMPLATE_PACKAGE = "@PackageName@";
    private static final String TEMPLATE_PERSISTENCE_PACKAGE_1 = "@PersistencePackageName1@";
    private static final String TEMPLATE_PERSISTENCE_PACKAGE_2 = "@PersistencePackageName2@";
    private static final String TEMPLATE_SERVICE_NAME = "@ServiceName@";
    private static final String TEMPLATE_SWARM_TYPE = "@SwarmType@";
    private static final String TEMPLATE_SWARM_FACTORY_TYPE = "@SwarmFactoryType@";
    private static final String TEMPLATE_FACTORY_CREATE = "@FactoryCreate@";

    private static final String SERVICE_CLASS_SUFFIX = "Endpoint";

    /**
     * Given the name of an entity, return the name of the API that GPE will
     * generate if generating a Cloud Endpoint for the entity.
     */
    public static String getApiNameFromEntityName(String entityName) {
        return getServiceNameFromEntityName(entityName).toLowerCase();
    }

    /**
     * Given the name of an entity, return the name of the Endpoint class that GPE
     * will generate for it.
     */
    public static String getServiceNameFromEntityName(String entityName) {
        return entityName + SERVICE_CLASS_SUFFIX;
    }

    private final String entityClass;
    private final String entityServiceClass;
    private final String idType;
    private final String idGetter;
    private final String javaPackage;
    private final Project project;

    // TODO: maybe this can just be all static functions
    public TemplateHelper(PsiClass javaClass, PsiField idField) {
        this.javaPackage = ((PsiJavaFile) javaClass.getContainingFile()).getPackageName();
        this.project = javaClass.getProject();
        this.entityClass = javaClass.getName();
        this.idGetter = PropertyUtil.suggestGetterName(idField.getName(), idField.getType()); //<-- should probably do a check to make sure this exists
        this.idType = idField.getType().getPresentableText();
        this.entityServiceClass = getServiceNameFromEntityName(entityClass);
    }

    /**
     * NOTE : requires runWriteAction
     * Load in entity manager factory as java file
     * @throws IOException
     */
    public static PsiFile loadJpaEntityManagerFactoryClass(Project project, String javaPackage) throws IOException {
        String templateString = getTemplateResourceAsString(FILE_TEMPLATE_MANAGER_FACTORY_CLASS);

        templateString = templateString.replaceAll(TEMPLATE_PACKAGE, javaPackage);
        templateString = templateString.replaceAll(TEMPLATE_PERSISTENCE_PACKAGE_1,
                "javax.persistence.EntityManagerFactory");
        templateString = templateString.replaceAll(TEMPLATE_PERSISTENCE_PACKAGE_2, "javax.persistence.Persistence");
        templateString = templateString.replaceAll(TEMPLATE_SWARM_TYPE, "Entity");
        templateString = templateString.replaceAll(TEMPLATE_SWARM_FACTORY_TYPE, "EMF");
        templateString = templateString.replaceAll(TEMPLATE_FACTORY_CREATE,
                "Persistence.createEntityManagerFactory");

        return PsiUtils.createFormattedFile(project, "EMF.java", JavaFileType.INSTANCE, templateString);
    }

    /**
     * NOTE : requires runWriteAction
     * Non-static version of {@link #loadJpaEntityManagerFactoryClass(com.intellij.openapi.project.Project, String)}
     * @throws IOException
     */
    public PsiFile loadJpaEntityManagerFactoryClass() throws IOException {
        return loadJpaEntityManagerFactoryClass(project, javaPackage);
    }

    /**
     * NOTE : requires runWriteAction
     * Load in Endpoints template as java file
     * @throws IOException
     */
    public PsiFile loadJpaSwarmServiceClass() throws IOException {

        EndpointPackageInfo endpointPackageInfo = getEndpointPackageInfo(javaPackage);

        String templateString = getTemplateResourceAsString(FILE_TEMPLATE_JPA_SWARM_SERVICE);

        templateString = templateString.replaceAll(TEMPLATE_PACKAGE, javaPackage);
        templateString = templateString.replaceAll(TEMPLATE_SERVICE_NAME, entityServiceClass);
        templateString = templateString.replaceAll(TEMPLATE_API_NAME, getApiNameFromEntityName(entityClass));
        templateString = templateString.replaceAll(TEMPLATE_ENDPOINT_OWNER_DOMAIN,
                endpointPackageInfo.getOwnerDomain());
        templateString = templateString.replaceAll(TEMPLATE_ENDPOINT_PACKAGE_PATH,
                endpointPackageInfo.getPackagePath());
        templateString = templateString.replaceAll(TEMPLATE_ENTITY_NAME, entityClass);
        templateString = templateString.replaceAll(TEMPLATE_ENTITY_NAME_LOWER_CASE,
                Introspector.decapitalize(entityClass));
        templateString = templateString.replaceAll(TEMPLATE_ID_TYPE, idType);
        templateString = templateString.replaceAll(TEMPLATE_ID_GETTER, idGetter);

        return PsiUtils.createFormattedFile(project, entityServiceClass + ".java", JavaFileType.INSTANCE,
                templateString);
    }

    /**
     * NOTE : requires runWriteAction
     * Load in the persistence.xml template
     * @throws IOException
     */
    public static PsiFile loadPersistenceXml(Project project) throws IOException {
        String templateString = getTemplateResourceAsString(FILE_TEMPLATE_PERSISTENCE_XML);

        return PsiUtils.createFormattedFile(project, "persistence.xml", XmlFileType.INSTANCE, templateString);
    }

    /**
     * NOTE : requires runWriteAction
     * load in the gradle build file from templates
     * @throws IOException
     */
    public static PsiFile loadGradleBuildFile(Project project) throws IOException {
        String templateString = getTemplateResourceAsString(FILE_TEMPLATE_BUILD_GRADLE);
        return PsiUtils.createFormattedFile(project, "build.gradle", PlainTextFileType.INSTANCE, templateString);

    }

    /**
     * NOTE : requires runWriteAction
     * Load in the maven pom.xml file
     * @throws IOException
     */
    public static PsiFile generatePomXml(Project project, String packageName, String artifactName)
            throws IOException {
        String templateString = getTemplateResourceAsString(FILE_TEMPLATE_POM_XML);
        templateString = templateString.replaceAll(TEMPLATE_PACKAGE, packageName);
        templateString = templateString.replaceAll(TEMPLATE_MAVEN_ARTIFACT_NAME, artifactName);

        return PsiUtils.createFormattedFile(project, "pom.xml", XmlFileType.INSTANCE, templateString);
    }

    /**
     * NOTE : requires runWriteAction
     * load in the AppEngine web.xml from templates
     * @throws IOException
     */
    public static PsiFile loadWebXml(Project project) throws IOException {
        String templateString = getTemplateResourceAsString(FILE_TEMPLATE_WEB_XML);

        return PsiUtils.createFormattedFile(project, "web.xml", XmlFileType.INSTANCE, templateString);
    }

    /**
     * NOTE : requires runWriteAction
     * load in the AppEngine appengine-web.xml from templates
     * @throws IOException
     */
    public static PsiFile generateAppEngineWebXml(Project project, String appId) throws IOException {
        String templateString = getTemplateResourceAsString(FILE_TEMPLATE_APPENGINE_WEB_XML);
        templateString = templateString.replaceAll(TEMPLATE_APP_ID, appId == null ? "" : appId.trim());
        return PsiUtils.createFormattedFile(project, "appengine-web.xml", XmlFileType.INSTANCE, templateString);
    }

    /**
     * NOTE : requires runWriteAction
     * Non-Static version of {@link #loadPersistenceXml(com.intellij.openapi.project.Project)}
     * @throws IOException
     */
    public PsiFile loadPersistenceXml() throws IOException {
        return loadPersistenceXml(project);
    }

    /**
     * NOTE : requires runWriteAction
     * Load in generic java template
     * @throws IOException
     */
    public static PsiFile generateJavaTemplateContent(Project p, String className, String packageName)
            throws IOException {
        String templateString = getTemplateResourceAsString(className + ".java.template");
        templateString = templateString.replaceAll(TEMPLATE_PACKAGE, packageName);
        return PsiUtils.createFormattedFile(p, className + ".java", JavaFileType.INSTANCE, templateString);
    }

    /**
     * Load in generic java template with owner domain information
     * @throws IOException
     */
    public static PsiFile generateJavaTemplateContentWithOwnerDomain(Project p, String className,
            String packageName, EndpointPackageInfo endpointPackageInfo) throws IOException {
        String templateString = getTemplateResourceAsString(className + ".java.template");
        templateString = templateString.replaceAll(TEMPLATE_PACKAGE, packageName);
        templateString = templateString.replaceAll(TEMPLATE_ENDPOINT_OWNER_DOMAIN,
                endpointPackageInfo.getOwnerDomain());
        templateString = templateString.replaceAll(TEMPLATE_ENDPOINT_PACKAGE_PATH,
                endpointPackageInfo.getPackagePath());
        return PsiUtils.createFormattedFile(p, className + ".java", JavaFileType.INSTANCE, templateString);
    }

    /**
     * Load in generic java template with owner domain information and API Key (cloud console)
     * TODO: Maybe make this more generic, take a map?
     * @throws IOException
     */
    public static PsiFile generateJavaSampleTemplateWithOwnerDomainAndApiKey(Project p, String className,
            String packageName, EndpointPackageInfo endpointPackageInfo, String apiKey) throws IOException {
        String templateString = getTemplateResourceAsString(className + ".java.template");
        templateString = templateString.replaceAll(TEMPLATE_PACKAGE, packageName);
        templateString = templateString.replaceAll(TEMPLATE_ENDPOINT_OWNER_DOMAIN,
                endpointPackageInfo.getOwnerDomain());
        templateString = templateString.replaceAll(TEMPLATE_ENDPOINT_PACKAGE_PATH,
                endpointPackageInfo.getPackagePath());
        if (apiKey != null) {
            templateString = templateString.replaceAll(TEMPLATE_API_KEY, apiKey);
        }
        return PsiUtils.createFormattedFile(p, className + ".java", JavaFileType.INSTANCE, templateString);
    }

    /**
     * NOTE : requires runWriteAction
     * load in generic plain text (html, css, js, ...) file
     * @throws IOException
     */
    public static PsiFile generateStaticContent(Project p, String fileName) throws IOException {
        String templateString = getTemplateResourceAsString(fileName);
        return PsiUtils.createFormattedFile(p, fileName, PlainTextFileType.INSTANCE, templateString);
    }

    // requires runWriteAction
    private static String getTemplateResourceAsString(String resourceName) throws IOException {
        URL resourceURL = TemplateHelper.class.getResource(resourceName);
        return Resources.toString(resourceURL, Charsets.UTF_8);
    }

}