org.sprintapi.hyperdata.gwt.BeanAdapterGenerator.java Source code

Java tutorial

Introduction

Here is the source code for org.sprintapi.hyperdata.gwt.BeanAdapterGenerator.java

Source

/*
 *  Copyright 2012 sprintapi.org
 *
 *  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 org.sprintapi.hyperdata.gwt;

import java.io.PrintWriter;
import java.lang.annotation.Annotation;

import org.sprintapi.hyperdata.HyperdataContainer;
import org.sprintapi.hyperdata.HyperdataIgnore;
import org.sprintapi.hyperdata.MetadataContainer;
import org.sprintapi.hyperdata.gwt.client.bean.BeanAdapter;

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.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JMethod;
import com.google.gwt.core.ext.typeinfo.JParameterizedType;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
import com.google.gwt.user.rebind.SourceWriter;

public class BeanAdapterGenerator extends Generator {

    @Override
    public String generate(TreeLogger logger, GeneratorContext context, String requestedClass)
            throws UnableToCompleteException {

        TypeOracle typeOracle = context.getTypeOracle();

        JClassType objectType = typeOracle.findType(requestedClass);
        if (objectType == null) {
            logger.log(TreeLogger.ERROR, "Could not find type: " + requestedClass);
            throw new UnableToCompleteException();
        }

        String implTypeName = objectType.getSimpleSourceName() + "Impl";

        String implPackageName = objectType.getPackage().getName();

        JClassType[] implementedTypes = objectType.getImplementedInterfaces();

        // Can only implement one interface
        if ((implementedTypes == null) || (implementedTypes.length != 1)
                || !implementedTypes[0].getQualifiedSourceName().equals(BeanAdapter.class.getName())) {
            logger.log(TreeLogger.ERROR, "The type: " + requestedClass + " must implement only one interface: "
                    + BeanAdapter.class.getName());
            throw new UnableToCompleteException();
        }

        // Get parameterized type
        JParameterizedType parameterType = implementedTypes[0].isParameterized();

        if (parameterType == null) {
            logger.log(TreeLogger.ERROR, "The type: " + requestedClass
                    + " must implement only one parameterized interface: " + BeanAdapter.class.getName());
            throw new UnableToCompleteException();
        }

        JClassType parameterizedType = parameterType.getTypeArgs()[0];

        ClassSourceFileComposerFactory composerFactory = new ClassSourceFileComposerFactory(implPackageName,
                implTypeName);

        composerFactory.addImplementedInterface(objectType.getQualifiedSourceName());

        PrintWriter printWriter = context.tryCreate(logger, implPackageName, implTypeName);

        if (printWriter != null) {
            SourceWriter sourceWriter = composerFactory.createSourceWriter(context, printWriter);

            composeSetPropertyValueMethod(sourceWriter, parameterizedType);
            composeGetPropertyValueMethod(sourceWriter, parameterizedType);
            composeGetPropertiesMethod(sourceWriter, parameterizedType);
            composeGetBeanClassMethod(sourceWriter, parameterizedType);
            composeGetBeanAttributesMethod(sourceWriter, parameterizedType);
            composeCreateInstanceMethod(sourceWriter, parameterizedType);
            sourceWriter.commit(logger);
        }
        return implPackageName + "." + implTypeName;
    }

    private void composeSetPropertyValueMethod(SourceWriter sourceWriter, JClassType parameterizedType) {
        sourceWriter.print("public void setPropertyValue(" + parameterizedType.getQualifiedSourceName()
                + " object, String name, java.lang.Object value) throws org.sprintapi.hyperdata.gwt.client.AdapterException {");
        if (parameterizedType.getInheritableMethods() != null) {
            int count = 0;
            for (JMethod method : parameterizedType.getInheritableMethods()) {
                if (method.isAnnotationPresent(HyperdataIgnore.class)) {
                    continue;
                }
                if (method.isPublic() && method.getName().startsWith("set")) {
                    if (count > 0) {
                        sourceWriter.print(" else ");
                    }
                    sourceWriter
                            .print("name = java.lang.Character.toUpperCase(name.charAt(0)) + name.substring(1);");
                    sourceWriter
                            .print("if (\"" + method.getName().substring("get".length()) + "\".equals(name)) {");
                    //TODO check value type
                    //TODO isPrimitive
                    sourceWriter.print("  object." + method.getName() + "(("
                            + method.getParameterTypes()[0].getQualifiedSourceName() + ")value);");
                    sourceWriter.print("  return;");
                    sourceWriter.print("}");
                    count += 1;
                }
            }
        }
        //        sourceWriter.print("  throw new org.sprintapi.gwt.converter.client.ConverterException(\"There is no getter for '\" + name  + \"'.\");");
        sourceWriter.print("}");
    }

    private void composeGetPropertyValueMethod(SourceWriter sourceWriter, JClassType parameterizedType) {
        sourceWriter.print("public java.lang.Object getPropertyValue(" + parameterizedType.getQualifiedSourceName()
                + " object, String name) throws org.sprintapi.hyperdata.gwt.client.AdapterException {");

        if (parameterizedType.getInheritableMethods() != null) {
            int count = 0;
            for (JMethod method : parameterizedType.getInheritableMethods()) {
                if (method.isAnnotationPresent(HyperdataIgnore.class)) {
                    continue;
                }
                if (method.isPublic() && method.getName().startsWith("get")) {
                    if (count > 0) {
                        sourceWriter.print(" else ");
                    }
                    sourceWriter
                            .print("name = java.lang.Character.toUpperCase(name.charAt(0)) + name.substring(1);");
                    sourceWriter
                            .print("if (\"" + method.getName().substring("get".length()) + "\".equals(name)) {");
                    //TODO check the return type
                    //TODO isPrimitive
                    sourceWriter.print("  return object." + method.getName() + "();");
                    sourceWriter.print("}");
                    count += 1;
                }
            }
        }
        sourceWriter.print(" return null;");
        //sourceWriter.print("  throw new org.sprintapi.gwt.converter.client.ConverterException(\"There is no getter for '\" + name  + \"'.\");");
        sourceWriter.print("}");
    }

    private void composeGetPropertiesMethod(SourceWriter sourceWriter, JClassType parameterizedType) {
        sourceWriter
                .print("public org.sprintapi.hyperdata.gwt.client.bean.BeanPropertyDescriptor[] getProperties() {");
        sourceWriter.print("  return new org.sprintapi.hyperdata.gwt.client.bean.BeanPropertyDescriptor[]{");

        int count = 0;
        if (parameterizedType.getInheritableMethods() != null) {
            for (JMethod method : parameterizedType.getInheritableMethods()) {
                count = doComposeGetPropertiesMethod(sourceWriter, method, count);
            }
        }

        sourceWriter.print("  };");
        sourceWriter.print("}");
    }

    private int doComposeGetPropertiesMethod(SourceWriter sourceWriter, JMethod method, int count) {
        if (method.isAnnotationPresent(HyperdataIgnore.class) || method.getName().equals("getClass")) {
            return count;
        }
        if (method.isPublic() && method.getName().startsWith("get")) {
            if (count > 0) {
                sourceWriter.print(",");
            }
            String methodName = method.getName().substring("get".length());
            if (methodName.trim().isEmpty()) {
                return count;
            }
            methodName = Character.toLowerCase(methodName.charAt(0)) + methodName.substring(1);

            sourceWriter.print("new org.sprintapi.hyperdata.gwt.client.bean.BeanPropertyDescriptorImpl(" + "\""
                    + methodName + "\", " + method.getReturnType().getQualifiedSourceName() + ".class" + ", null"); //TODO kind

            MetadataContainer meta = method.getAnnotation(MetadataContainer.class);
            if (meta != null) {

                sourceWriter.print(", new org.sprintapi.hyperdata.gwt.client.bean.HyperBeanPropertyAttributes(");
                sourceWriter.print(")");
            } else {
                sourceWriter.print(", null");
            }

            sourceWriter.print(")");
            count += 1;
        }
        return count;
    }

    private void composeGetBeanClassMethod(SourceWriter sourceWriter, JClassType parameterizedType) {
        sourceWriter.print("public Class<" + parameterizedType.getQualifiedSourceName() + "> getBeanClass() {");
        sourceWriter.print("  return " + parameterizedType.getQualifiedSourceName() + ".class;");
        sourceWriter.print("}");
    }

    private void composeGetBeanAttributesMethod(SourceWriter sourceWriter, JClassType parameterizedType) {
        sourceWriter.print("public org.sprintapi.hyperdata.gwt.client.bean.HyperBeanAttributes getAttributes() {");

        HyperdataContainer hyperbean = parameterizedType.getAnnotation(HyperdataContainer.class);
        if (hyperbean != null) {
            sourceWriter.print("  return new org.sprintapi.hyperdata.gwt.client.bean.HyperBeanAttributes(");
            if (hyperbean.profile() != null) {
                sourceWriter.print("new String[]{");
                boolean next = false;
                for (String profile : hyperbean.profile()) {
                    if (next) {
                        sourceWriter.print(",");
                    }
                    sourceWriter.print("\"" + profile + "\"");
                    next = true;
                }
                sourceWriter.print("}");
            }
            sourceWriter.print(");");
        } else {
            sourceWriter.print("  return null;");
        }
        sourceWriter.print("}");
    }

    private void composeCreateInstanceMethod(SourceWriter sourceWriter, JClassType parameterizedType) {
        sourceWriter.print("public " + parameterizedType.getQualifiedSourceName() + " createInstance() {");
        sourceWriter.print("  return new " + parameterizedType.getQualifiedSourceName() + "();");
        sourceWriter.print("}");
    }

}