com.ait.toolkit.rebind.TemplateGenerator.java Source code

Java tutorial

Introduction

Here is the source code for com.ait.toolkit.rebind.TemplateGenerator.java

Source

/**
 Copyright (c) 2014 Ahom Innovation Technologies. All rights reserved.
    
 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.ait.toolkit.rebind;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.URL;

import com.ait.toolkit.core.client.Template;
import com.ait.toolkit.core.client.TemplateResource;
import com.google.gwt.core.ext.Generator;
import com.google.gwt.core.ext.GeneratorContext;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.TreeLogger.Type;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.NotFoundException;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.dev.resource.Resource;
import com.google.gwt.dev.util.Name;
import com.google.gwt.dev.util.Util;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.SafeHtmlUtils;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
import com.google.gwt.user.rebind.SourceWriter;

/**
 * Generator class for Templates
 */
public class TemplateGenerator extends Generator {

    private static final String TEMPLATE_SUFFIX = ".html";
    private JClassType templatesInterface;

    /**
     * Given a TemplateResource interface, return the path to its .html file, suitable for any classloader to find it as a resource. If the .html does not exist or is empty see if
     * the template was declared inline. If no content is found we throw an exception.
     */
    private String getTemplateContent(GeneratorContext context, TreeLogger logger, JClassType interfaceType)
            throws UnableToCompleteException {
        String templateHtmlFile = null;

        TemplateResource annotation = interfaceType.getAnnotation(TemplateResource.class);
        if (annotation == null) {
            // if the interface is defined as a nested class, use the name of
            // the
            // enclosing type
            if (interfaceType.getEnclosingType() != null) {
                interfaceType = interfaceType.getEnclosingType();
            }
            templateHtmlFile = slashify(interfaceType.getQualifiedBinaryName()) + TEMPLATE_SUFFIX;
            logger.log(TreeLogger.INFO, "Template : " + templateHtmlFile);

            InputStream stream = getTemplateResource(context, logger, templateHtmlFile);
            if (stream == null) {
                logger.log(Type.ERROR, "No data could be loaded - no data at path "
                        + interfaceType.getQualifiedBinaryName() + TEMPLATE_SUFFIX);
                throw new UnableToCompleteException();
            }
            return sanitize(Util.readStreamAsString(stream));

        } else {
            // first we look at the HTML File
            templateHtmlFile = annotation.source();

            if (templateHtmlFile.length() > 0) {

                if (!templateHtmlFile.endsWith(TEMPLATE_SUFFIX)) {
                    logger.log(TreeLogger.ERROR, "Template file name must end with " + TEMPLATE_SUFFIX);
                    throw new UnableToCompleteException();
                }

                if (annotation.value().length() != 0) {
                    logger.log(Type.WARN, "Found both source file and inline template, using source file");
                }

                templateHtmlFile = slashify(interfaceType.getPackage().getName()) + "/" + templateHtmlFile;
                InputStream stream = getTemplateResource(context, logger, templateHtmlFile);
                return sanitize(Util.readStreamAsString(stream));

            } else if (annotation.value().length() > 0) {
                return annotation.value();
            } else {
                logger.log(Type.ERROR,
                        "Template annotation found with no contents, cannot generate method , this may cause other failures.");
            }

        }
        return null;
    }

    private static String slashify(String s) {
        return s.replace(".", "/").replace("$", ".");
    }

    private static String sanitize(String input) {
        return input.replace("\n", "").replace("'", "\\'").replace("\"", "\\\"");
    }

    @Override
    public String generate(TreeLogger logger, GeneratorContext context, String typeName)
            throws UnableToCompleteException {
        TypeOracle oracle = context.getTypeOracle();
        this.templatesInterface = oracle.findType(Name.getSourceNameForClass(Template.class));

        JClassType interfaceType;
        try {
            interfaceType = oracle.getType(typeName);
        } catch (NotFoundException e) {
            throw new RuntimeException(e);
        }

        if (interfaceType.isInterface() == null) {
            logger.log(TreeLogger.ERROR, typeName + " is not an interface type");
            throw new UnableToCompleteException();
        }
        if (!interfaceType.isAssignableTo(templatesInterface)) {
            logger.log(Type.ERROR, "This isn't a Template subtype...");
            throw new UnableToCompleteException();
        }

        String content = getTemplateContent(context, logger, interfaceType);
        String packageName = interfaceType.getPackage().getName();
        String className = "Tpl_For_" + interfaceType.getQualifiedSourceName().replace(".", "_") + "_Generated";

        ClassSourceFileComposerFactory composer = new ClassSourceFileComposerFactory(packageName, className);
        composer.addImport(SafeHtml.class.getName());
        composer.addImport(SafeHtmlUtils.class.getName());
        composer.addImplementedInterface(Template.class.getName());

        PrintWriter pw = context.tryCreate(logger, packageName, className);

        if (pw != null) {
            SourceWriter sw = composer.createSourceWriter(context, pw);

            sw.println("  public SafeHtml getContent(){");
            sw.println("      return SafeHtmlUtils.fromSafeConstant(\"" + content + "\");");
            sw.println("  }");
            sw.println("");
            sw.println("");
            sw.println("  public SafeHtml getSafeContent(){");
            sw.println("      return SafeHtmlUtils.fromString(\"" + content + "\");");
            sw.println("  }");

            sw.commit(logger);
        }

        return composer.getCreatedClassName();

    }

    protected InputStream getTemplateResource(GeneratorContext context, TreeLogger l, String markerPath)
            throws UnableToCompleteException {
        // look for a local file first
        String path = slashify(markerPath);
        l.log(Type.INFO, "Current resource path : " + markerPath);
        Resource res = context.getResourcesOracle().getResourceMap().get(path);
        // if not a local path, try an absolute one
        if (res == null) {
            l.log(Type.INFO, "Resource is Null trying with URL ");
            URL url = Thread.currentThread().getContextClassLoader().getResource(markerPath);
            if (url == null) {
                l.log(Type.INFO, "URL seems to be null here ... hmmmmss");
                return null;
            } else {
                l.log(Type.INFO, "URL seems to be NOT null.");
            }
            try {
                return url.openStream();
            } catch (IOException e) {
                l.log(Type.ERROR, "IO Exception occured", e);
                throw new UnableToCompleteException();
            }
        }
        try {
            return res.openContents();
        } catch (Exception e) {
            l.log(Type.ERROR, "Exception occured reading " + path, e);
            throw new UnableToCompleteException();
        }
    }

}