Package com.extjs.gxt.ui.rebind.core

Source Code of com.extjs.gxt.ui.rebind.core.BeanModelGenerator

/*
* Ext GWT 2.2.4 - Ext for GWT
* Copyright(c) 2007-2010, Ext JS, LLC.
* licensing@extjs.com
*
* http://extjs.com/license
*/
package com.extjs.gxt.ui.rebind.core;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import com.extjs.gxt.ui.client.core.FastMap;
import com.extjs.gxt.ui.client.data.BeanModel;
import com.extjs.gxt.ui.client.data.BeanModelFactory;
import com.extjs.gxt.ui.client.data.BeanModelLookup;
import com.extjs.gxt.ui.client.data.BeanModelMarker;
import com.extjs.gxt.ui.client.data.BeanModelTag;
import com.extjs.gxt.ui.client.data.ModelData;
import com.extjs.gxt.ui.client.data.NestedModelUtil;
import com.extjs.gxt.ui.client.data.BeanModelMarker.BEAN;
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.NotFoundException;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
import com.google.gwt.user.rebind.SourceWriter;

public class BeanModelGenerator extends Generator {

  protected TypeOracle oracle;
  protected JClassType beanModelMarkerType;
  protected JClassType beanModelTagType;
  protected List<JClassType> beans;

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

    try {
      // final all beans and bean markers
      beans = new ArrayList<JClassType>();
      JClassType[] types = oracle.getTypes();
      for (JClassType type : types) {
        if (isBeanMarker(type)) {
          beans.add(getMarkerBean(type));
        } else if (isBean(type)) {
          beans.add(type);
        }
      }

      final String genPackageName = BeanModelLookup.class.getPackage().getName();
      final String genClassName = "BeanModelLookupImpl";

      ClassSourceFileComposerFactory composer = new ClassSourceFileComposerFactory(genPackageName, genClassName);
      composer.setSuperclass(BeanModelLookup.class.getCanonicalName());
      composer.addImport(BeanModelFactory.class.getName());
      composer.addImport(Map.class.getName());
      composer.addImport(FastMap.class.getName());

      PrintWriter pw = context.tryCreate(logger, genPackageName, genClassName);

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

        sw.println("private Map<String, BeanModelFactory> m;");

        sw.println("public BeanModelFactory getFactory(Class b) {");
        sw.indent();
        sw.println("String n = b.getName();");
        sw.println("if (m == null) {");
        sw.indentln("m = new FastMap<BeanModelFactory>();");
        sw.println("}");
        sw.println("if (m.get(n) == null) {");
        sw.indent();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < beans.size(); i++) {
          JClassType bean = beans.get(i);
          String name = createBean(bean, logger, context);
          String factory = createFactory(bean, name, logger, context);

          if (i > 0) {
            sw.print(" else ");
          }
          sw.println("if (" + bean.getQualifiedSourceName() + ".class.getName().equals(n)) {");
          sw.indentln("m" + i + "();");

          sb.append("private void m" + i + "() {\n");
          sb.append("  m.put(" + bean.getQualifiedSourceName() + ".class.getName(), new " + factory + "());\n");
          sb.append("}\n");

          sw.print("}");
        }
        sw.outdent();
        sw.println("}");
        sw.println("return m.get(n);");
        sw.outdent();
        sw.println("}");

        sw.println(sb.toString());
        sw.commit(logger);
      }

      return composer.getCreatedClassName();

    } catch (Exception e) {
      logger.log(TreeLogger.ERROR, "Class " + typeName + " not found.", e);
      throw new UnableToCompleteException();
    }

  }

  protected String createFactory(JClassType bean, String beanModelName, TreeLogger logger, GeneratorContext context)
      throws Exception {
    final String genPackageName = BeanModelLookup.class.getPackage().getName();
    final String genClassName = "BeanModel_" + bean.getQualifiedSourceName().replace(".", "_") + "_Factory";

    ClassSourceFileComposerFactory composer = new ClassSourceFileComposerFactory(genPackageName, genClassName);
    composer.setSuperclass(BeanModelFactory.class.getCanonicalName());
    PrintWriter pw = context.tryCreate(logger, genPackageName, genClassName);

    if (pw != null) {
      SourceWriter sw = composer.createSourceWriter(context, pw);
      sw.println("public BeanModel newInstance() {");
      sw.println("return new " + beanModelName + "();");
      sw.println("}");
      sw.commit(logger);
    }
    return composer.getCreatedClassName();
  }

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

    ClassSourceFileComposerFactory composer = new ClassSourceFileComposerFactory(genPackageName, genClassName);
    composer.setSuperclass(BeanModel.class.getCanonicalName());
    composer.addImport(BeanModel.class.getName());
    composer.addImport(NestedModelUtil.class.getName());
    PrintWriter pw = context.tryCreate(logger, genPackageName, genClassName);

    if (pw != null) {
      List<JMethod> getters = findGetters(bean);
      List<JMethod> setters = findSetters(bean);
      SourceWriter sw = composer.createSourceWriter(context, pw);

      sw.println("public " + genClassName + "(){");
      for (JMethod method : getters) {
        String s = method.getName();
        String p = lowerFirst(s.substring(s.startsWith("g") ? 3 : 2)); // get or
        // is
        sw.println("beanProperties.add(\"" + p + "\");");
      }
      sw.println("}");

      createGetMethods(getters, sw, bean.getQualifiedSourceName());
      createSetMethods(setters, sw, bean.getQualifiedSourceName());

      // delegate equals to bean
      sw.println("public boolean equals(Object obj) {");
      sw.println("  if (obj instanceof " + "BeanModel" + ") {");
      sw.println("    obj = ((BeanModel)obj).getBean();");
      sw.println("  }");
      sw.println("  return bean.equals(obj);");
      sw.println("}");

      // delegate hashCode to bean
      sw.println("public int hashCode(){");
      sw.println("  return bean.hashCode();");
      sw.println("}");

      sw.commit(logger);
    }
    return composer.getCreatedClassName();
  }

  protected JClassType getMarkerBean(JClassType type) throws NotFoundException {
    BEAN pojo = type.getAnnotation(BEAN.class);
    return oracle.getType(pojo.value().getCanonicalName());
  }

  protected boolean isBean(JClassType type) {
    return !type.equals(beanModelTagType) && type.isAssignableTo(beanModelTagType)
        && !type.isAssignableTo(oracle.findType(ModelData.class.getName()));
  }

  protected boolean isBeanMarker(JClassType type) {
    return !type.equals(beanModelMarkerType) && type.isAssignableTo(beanModelMarkerType)
        && !type.isAssignableTo(oracle.findType(ModelData.class.getName()));
  }

  protected void createGetMethods(List<JMethod> getters, SourceWriter sw, String typeName) {
    sw.println("public <X> X get(String s) {");

    sw.println("if (allowNestedValues && NestedModelUtil.isNestedProperty(s)) {");
    sw.indentln("return (X)NestedModelUtil.getNestedValue(this, s);");
    sw.println("}");

    for (JMethod method : getters) {
      JClassType returnType = method.getReturnType().isClassOrInterface();
      String s = method.getName();
      String p = lowerFirst(s.substring(s.startsWith("g") ? 3 : 2)); // get or

      sw.println("if (s.equals(\"" + p + "\")) {");
      sw.println("Object value = ((" + typeName + ")bean)." + s + "();");

      try {
        if (returnType != null && returnType.isAssignableTo(oracle.getType(List.class.getName()))
            && returnType.isParameterized() != null) {
          JParameterizedType type = returnType.isParameterized();
          JClassType[] params = type.getTypeArgs();
          if (beans.contains(params[0])) {
            sw.println("if (value != null) {");
            sw.indent();
            sw.println("java.util.List list = (java.util.List)value;");
            sw.println("java.util.List list2 = " + BeanModelLookup.class.getCanonicalName() + ".get().getFactory("
                + params[0].getQualifiedSourceName() + ".class).createModel((java.util.Collection) list);");
            sw.outdent();
            sw.println("return (X) list2;");
            sw.println("}");
          }
        } else {
          // swap returnType as generic types were not matching
          // (beans.contains(returnType))
          if (returnType != null) {
            String t = returnType.getQualifiedSourceName();
            if (t.indexOf("extends") == -1) {
              returnType = oracle.getType(t);
            }
          }
          if (beans.contains(returnType)) {
            sw.println("if (value != null) {");
            sw.println("    BeanModel nestedModel = nestedModels.get(s);");
            sw.println("    if (nestedModel != null) {");
            sw.println("      Object bean = nestedModel.getBean();");
            sw.println("      if (!bean.equals(value)){");
            sw.println("        nestedModel = null;");
            sw.println("      }");
            sw.println("    }");
            sw.println("    if (nestedModel == null) {");
            sw.println("        nestedModel = " + BeanModelLookup.class.getCanonicalName() + ".get().getFactory("
                + returnType.getQualifiedSourceName() + ".class).createModel(value);");
            sw.println("        nestedModels.put(s, nestedModel);");
            sw.println("    }");
            sw.println("    return (X)processValue(nestedModel);");
            sw.println("}");
          }
        }
      } catch (Exception e) {
        e.printStackTrace();
      }

      sw.println("return (X)processValue(value);");
      sw.println("}");
    }
    sw.println("return super.get(s);");
    sw.println("}");
  }

  protected String lowerFirst(String propName) {
    if (propName.length() == 0) {
      return propName;
    } else if (propName.length() == 1) {
      return propName.toLowerCase();
    } else {
      return propName.substring(0, 1).toLowerCase() + propName.substring(1);
    }
  }

  protected String getMethodAttributeType(JMethod method) {
    return method.getParameters()[0].getType().getQualifiedSourceName();
  }

  protected void createSetMethods(List<JMethod> properties, SourceWriter sw, String typeName) {
    sw.println("public <X> X set(String s, X val) {");
    sw.indent();
    sw.println("Object obj = val;");
   
    sw.println("if (obj instanceof BeanModel) {");
      sw.println("obj = ((BeanModel) obj).getBean();");
    sw.println("} else if (obj instanceof java.util.List) {");
      sw.println("java.util.List list = new java.util.ArrayList();");
      sw.println("for(Object o : (java.util.List) obj) {");
        sw.println("if(o instanceof BeanModel) {");
          sw.println("list.add(((BeanModel) o).getBean());");
        sw.println("} else {");
          sw.println("list.add(o);");
        sw.println("}");
      sw.println("}");
      sw.println("obj = list;");
    sw.println("}");
   
    sw.println("if (allowNestedValues && val instanceof BeanModel) {");
    sw.indent();
    sw.println("obj = ((BeanModel)val).getBean();");
    sw.println("if (nestedModels.containsKey(s)) {");
    sw.indent();
    sw.println("nestedModels.put(s, (BeanModel)val);");
    sw.outdent();
    sw.println("}");
    sw.outdent();
    sw.println("}");

    sw.println("if (allowNestedValues && NestedModelUtil.isNestedProperty(s)) {");
    sw.indent();
    sw.println("X old = (X) NestedModelUtil.setNestedValue(this, s, val);");
    sw.println("notifyPropertyChanged(s, val, old);");
    sw.println("return old;");
    sw.outdent();
    sw.println("}");

    for (JMethod method : properties) {
      String s = method.getName();
      String p = lowerFirst(s.substring(3));
      String type = getMethodAttributeType(method);

      if (type.indexOf("extends") != -1) {
        type = "java.lang.Object";
      }

      if (type.equals("byte")) {
        type = "Byte";
      } else if (type.equals("char")) {
        type = "Character";
      } else if (type.equals("short")) {
        type = "Short";
      } else if (type.equals("int")) {
        type = "Integer";
      } else if (type.equals("long")) {
        type = "Long";
      } else if (type.equals("float")) {
        type = "Float";
      } else if (type.equals("double")) {
        type = "Double";
      } else if (type.equals("boolean")) {
        type = "Boolean";
      }

      sw.println("if (s.equals(\"" + p + "\")) {");
      sw.indent();
      sw.println("Object old = get(s);");
          
      sw.println("((" + typeName + ")bean)." + s + "((" + type + ")obj);");
      sw.println("notifyPropertyChanged(s, val, old);");
      sw.println("return (X)old;");
      sw.outdent();
      sw.println("}");
    }
    sw.println("return super.set(s, val);");
    sw.outdent();
    sw.println("}");
  }

  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.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);
        }
      }
    }
  }

}
TOP

Related Classes of com.extjs.gxt.ui.rebind.core.BeanModelGenerator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.