ru.fly.shared.bean.BeanGenerator.java Source code

Java tutorial

Introduction

Here is the source code for ru.fly.shared.bean.BeanGenerator.java

Source

/*
 * Copyright 2015 Valeriy Filatov.
 *
 * 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 ru.fly.shared.bean;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

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.TypeOracle;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
import com.google.gwt.user.rebind.SourceWriter;

public class BeanGenerator extends Generator {

    private String beanModelName = BeanModel.class.getSimpleName();

    private TypeOracle oracle;
    private List<JClassType> beans = new ArrayList<JClassType>();
    private JClassType beanType;

    @Override
    public String generate(TreeLogger logger, GeneratorContext context, String typeName)
            throws UnableToCompleteException {
        oracle = context.getTypeOracle();
        beanType = oracle.findType(BaseModel.class.getName());

        JClassType[] types = oracle.getTypes();
        for (JClassType type : types) {
            if (type.isAssignableTo(beanType)) {
                beans.add(type);
            }
        }
        final String genPackageName = BeanGenerator.class.getPackage().getName();
        final String genClassName = "BeanFactoryImpl";

        ClassSourceFileComposerFactory composer = new ClassSourceFileComposerFactory(genPackageName, genClassName);
        composer.setSuperclass(BeanFactory.class.getCanonicalName());

        PrintWriter pw = context.tryCreate(logger, genPackageName, genClassName);
        if (pw != null) {
            SourceWriter sw = composer.createSourceWriter(context, pw);
            sw.println("public " + beanModelName + " create(Object obj) {");
            sw.println("String className = obj.getClass().getName();");
            for (JClassType bean : beans) {
                sw.println("if(className.equals(\"" + bean.getQualifiedSourceName() + "\")){");
                sw.println("return (" + beanModelName + ") new " + createBean(bean, logger, context) + "(obj);");
                sw.println("}");
            }
            sw.println("return null;");
            sw.println("}");
            sw.commit(logger);
        }

        return composer.getCreatedClassName();
    }

    protected String createBean(JClassType bean, TreeLogger logger, GeneratorContext context) {
        final String genPackageName = bean.getPackage().getName();
        final String genClassName = beanModelName + "_" + bean.getQualifiedSourceName().replace(".", "_");

        ClassSourceFileComposerFactory composer = new ClassSourceFileComposerFactory(genPackageName, genClassName);
        composer.setSuperclass(BeanModel.class.getCanonicalName());

        PrintWriter pw = context.tryCreate(logger, genPackageName, genClassName);
        if (pw != null) {
            SourceWriter sw = composer.createSourceWriter(context, pw);
            sw.println("private Object obj;");
            sw.println("private java.util.List<String> fields = new java.util.ArrayList<String>();");

            sw.println("public " + genClassName + "(Object obj){");
            sw.println("  this.obj = obj;");
            List<String> fields = findFields(bean);
            for (String fld : fields) {
                sw.println("  fields.add(\"" + fld + "\");");
            }
            sw.println("}");

            sw.println("public java.util.List<String> getFields(){ return fields; }");

            List<JMethod> getters = findGetters(bean);
            sw.println("public Object get(String field){");
            for (JMethod method : getters) {
                String f = method.getName();
                if (f.startsWith("get")) {
                    f = f.replaceFirst("get", "");
                } else if (f.startsWith("is")) {
                    f = f.replaceFirst("is", "");
                }
                f = f.substring(0, 1).toLowerCase() + f.substring(1);
                sw.println("  if(field.equals(\"" + f + "\"))");
                sw.println("    return ((" + bean.getQualifiedSourceName() + ")obj)." + method.getName() + "();");

                JClassType retType = method.getReturnType().isClass();
                if (retType != null && retType.isAssignableTo(beanType)) {
                    buildGettersForSubBean(sw, bean, retType, f, method.getName() + "()", 0);
                }
            }
            sw.println("return null;");
            sw.println("}");

            List<JMethod> setters = findSetters(bean);
            sw.println("public void set(String field, Object value){");
            for (JMethod method : setters) {
                String f = method.getName().replaceFirst("set", "");
                ;
                f = f.substring(0, 1).toLowerCase() + f.substring(1);
                sw.println("  if(field.equals(\"" + f + "\"))");
                String castType = method.getParameters()[0].getType().getQualifiedSourceName();
                if (!castType.contains("."))
                    castType = castType.substring(0, 1).toUpperCase() + castType.substring(1);
                sw.println("    ((" + bean.getQualifiedSourceName() + ")obj)." + method.getName() + "((" + castType
                        + ")value);");
            }
            sw.println("}");

            sw.commit(logger);
        }

        return composer.getCreatedClassName();
    }

    public void buildGettersForSubBean(SourceWriter sw, JClassType parentBean, JClassType bean, String filedName,
            String methodName, int level) {
        List<JMethod> getters = findGetters(bean);
        for (JMethod method : getters) {
            String f = method.getName();
            if (f.startsWith("get")) {
                f = f.replaceFirst("get", "");
            } else if (f.startsWith("is")) {
                f = f.replaceFirst("is", "");
            }
            f = f.substring(0, 1).toLowerCase() + f.substring(1);
            sw.println("if(field.equals(\"" + filedName + "." + f + "\"))");
            sw.println("return ((" + parentBean.getQualifiedSourceName() + ")obj)." + methodName + "."
                    + method.getName() + "();");

            JClassType retType = method.getReturnType().isClass();
            if (retType != null && retType.isAssignableTo(beanType) && level < 4) {
                buildGettersForSubBean(sw, parentBean, retType, filedName + "." + f,
                        methodName + "." + method.getName() + "()", level + 1);
            }
        }
    }

    protected List<String> findFields(JClassType cls) {
        Set<String> getters = new HashSet<String>();
        Set<String> setters = new HashSet<String>();
        addField(cls, getters, setters);
        List<String> ret = new ArrayList<String>();
        for (String fld : getters) {
            if (setters.contains(fld))
                ret.add(fld);
        }
        return ret;
    }

    protected void addField(JClassType cls, Set<String> getters, Set<String> setters) {
        if (cls == null) {
            return;
        }
        // ignore methods of Object
        if (cls.isInterface() != null || cls.getSuperclass() != null) {
            addField(cls.getSuperclass(), getters, setters);
            for (JMethod m : cls.getMethods()) {
                if (m.isPublic() || m.isProtected()) {
                    String name = m.getName();
                    if ((name.matches("get.*") || name.matches("is.*")) && m.getParameters().length == 0) {
                        if (name.startsWith("get"))
                            name = name.replaceFirst("get", "");
                        else if (name.startsWith("is"))
                            name = name.replaceFirst("is", "");
                        getters.add(name.substring(0, 1).toLowerCase() + name.substring(1));
                    } else if (name.matches("set.*") && m.getParameters().length == 1) {
                        name = name.replaceFirst("set", "");
                        setters.add(name.substring(0, 1).toLowerCase() + name.substring(1));
                    }
                }
            }
        }
    }

    protected List<JMethod> findGetters(JClassType cls) {
        List<JMethod> methods = new ArrayList<JMethod>();
        addGetters(cls, methods);
        return methods;
    }

    protected void addGetters(JClassType cls, List<JMethod> methods) {
        if (cls == null) {
            return;
        }
        // ignore methods of Object
        if (cls.isInterface() != null || cls.getSuperclass() != null) {
            addGetters(cls.getSuperclass(), methods);
            for (JMethod m : cls.getMethods()) {
                if (m.isPublic() || m.isProtected()) {
                    String name = m.getName();
                    if ((name.matches("get.*") || name.matches("is.*")) && m.getParameters().length == 0) {
                        methods.add(m);
                    }
                }
            }
        }
    }

    protected List<JMethod> findSetters(JClassType cls) {
        List<JMethod> methods = new ArrayList<JMethod>();
        addSetters(cls, methods);
        return methods;
    }

    protected void addSetters(JClassType cls, List<JMethod> methods) {
        if (cls == null) {
            return;
        }
        if (cls.isInterface() != null || cls.getSuperclass() != null) {
            addSetters(cls.getSuperclass(), methods);
            for (JMethod m : cls.getMethods()) {
                if (m.isPublic() || m.isProtected()) {
                    String name = m.getName();
                    if (name.matches("set.*") && m.getParameters().length == 1) {
                        methods.add(m);
                    }
                }
            }
        }

    }

}