Package gwt.mosaic.rebind.beans

Source Code of gwt.mosaic.rebind.beans.BeanAdapterWriter$JavaBeanProperty

package gwt.mosaic.rebind.beans;

import gwt.mosaic.client.beans.AbstractBeanAdapter;
import gwt.mosaic.client.beans.BeanAdapter;
import gwt.mosaic.client.beans.BeanAdapterFactory;
import gwt.mosaic.client.beans.GetterMethod;
import gwt.mosaic.client.beans.SetterMethod;
import gwt.mosaic.client.events.HasPropertyChangeHandlers;

import java.beans.Introspector;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;

import com.google.gwt.core.client.GWT;
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.JParameter;
import com.google.gwt.core.ext.typeinfo.JType;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.uibinder.rebind.IndentedWriter;
import com.google.gwt.uibinder.rebind.MortalLogger;

/**
* Write for GWT BeanAdapter generated classes.
*/
class BeanAdapterWriter {

  class JavaBeanProperty {
    String name;
    String propertyType;
    JMethod getter;
    JMethod setter;

    public JavaBeanProperty(String name) {
      this.name = name;
    }
  }

  public static final String LISTENERS_SUFFIX = "Listeners";
  public static final String PROPERTY_CHANGE_SUFFIX = "Changed";

  /**
   * The type we have been asked to generate, e.g. MyBeanAdapter.
   */
  private final JClassType baseClass;

  /**
   * The name of the class we're creating, e.g. MyBeanAdapterImpl.
   */
  private final String implClassName;

  private final TypeOracle oracle;
  private final MortalLogger logger;

  private final JClassType beanType;

  private HashMap<String, JavaBeanProperty> javaBeanProperties = new HashMap<String, JavaBeanProperty>();
  private HashSet<String> properties = new HashSet<String>();
  private HashSet<String> notifyingProperties = new HashSet<String>();

  public BeanAdapterWriter(JClassType baseClass, String implClassName,
      TypeOracle oracle, MortalLogger logger)
      throws UnableToCompleteException {
    this.baseClass = baseClass;
    this.implClassName = implClassName;
    this.oracle = oracle;
    this.logger = logger;

    // Check for possible misuse 'GWT.create(BeanAdapter.class)'
    JClassType beanAdapterItself = oracle.findType(BeanAdapter.class
        .getCanonicalName());
    if (beanAdapterItself.equals(baseClass)) {
      die("You must use a subtype of BeanAdapter in GWT.create(). E.g.,\n"
          + "  interface MyBeanAdapter extends BeanAdapter<JavaBean> {}\n"
          + "  GWT.create(MyBeanAdapter.class);");
    }

    JClassType[] beanAdapterTypes = baseClass.getImplementedInterfaces();
    if (beanAdapterTypes.length == 0) {
      throw new RuntimeException("No implemented interfaces for "
          + baseClass.getName());
    }
    JClassType beanAdapterType = beanAdapterTypes[0];

    JClassType[] typeArgs = beanAdapterType.isParameterized().getTypeArgs();
    if (typeArgs.length != 1) {
      throw new RuntimeException(
          "Java bean type parameter is required for type %s"
              + beanAdapterType.getName());
    }
    beanType = typeArgs[0];
  }

  public JClassType getBaseClass() {
    return baseClass;
  }

  public String getImplClassName() {
    return implClassName;
  }

  public TypeOracle getOracle() {
    return oracle;
  }

  public MortalLogger getLogger() {
    return logger;
  }

  public JClassType getBeanType() {
    return beanType;
  }

  public void lookupNotifyingProperties(JClassType type) {
    JClassType[] implInterfaces = type.getImplementedInterfaces();

    if (implInterfaces == null || implInterfaces.length == 0) {
      return;
    }

    JClassType hasPropertyChangeHandlers = oracle
        .findType(HasPropertyChangeHandlers.class.getName());
    for (JClassType implInterface : implInterfaces) {
      if (!hasPropertyChangeHandlers.isAssignableFrom(implInterface)) {
        continue;
      }

      if (null != implInterface.isParameterized()) {
        continue;
      }

      String implInterfaceName = implInterface.getName();
      if (implInterfaceName.startsWith("Has")
          && implInterfaceName.endsWith("ChangeHandlers")) {
        String propertyName = implInterfaceName.substring(
            "Has".length(), implInterfaceName.length()
                - "ChangeHandlers".length());
        propertyName = Introspector.decapitalize(propertyName);

        if (properties.contains(propertyName)) {
          notifyingProperties.add(propertyName);

          notifyingProperties.add(propertyName);
        }
      }
    }
  }

  void lookupJavaBeanPropertyAccessors(JClassType type) {
    JMethod[] methods = type.getOverridableMethods();
    for (JMethod method : methods) {
      if (!method.isPublic() || method.isStatic()) {
        continue;
      }
      if (method.getName().startsWith("set")
          && method.getParameters().length == 1) {

        String name = Introspector.decapitalize(method.getName()
            .substring(3));

        String propertyType = null;
        JParameter[] parameters = method.getParameters();
        if (parameters.length == 1) {
          JParameter parameter = parameters[0];
          JType parameterType = parameter.getType().getErasedType();
          if (parameterType.isPrimitive() != null) {
            propertyType = parameterType.isPrimitive()
                .getQualifiedBoxedSourceName();
          } else {
            propertyType = parameterType
                .getParameterizedQualifiedSourceName();
          }
        } else {
          warn("Property '" + name + "' has " + parameters.length
              + " parameters: " + parameters + "!");
          continue;
        }

        JavaBeanProperty property = javaBeanProperties.get(name + '#'
            + propertyType);

        if (property == null) {
          property = new JavaBeanProperty(name);
          javaBeanProperties.put(name + '#' + propertyType, property);
        }

        property.setter = method;

        if (property.propertyType == null) {
          property.propertyType = propertyType;
        }

      } else if (method.getName().startsWith("get")
          && method.getParameters().length == 0) {

        String name = Introspector.decapitalize(method.getName()
            .substring(3));

        String propertyType = null;
        JType retType = method.getReturnType().getErasedType();
        if (retType.isPrimitive() != null) {
          propertyType = retType.isPrimitive()
              .getQualifiedBoxedSourceName();
        } else {
          propertyType = retType
              .getParameterizedQualifiedSourceName();
        }

        JavaBeanProperty property = javaBeanProperties.get(name + "#"
            + propertyType);

        if (property == null) {
          property = new JavaBeanProperty(name);
          javaBeanProperties.put(name + "#" + propertyType, property);
        }

        property.getter = method;

        if (property.propertyType == null) {
          property.propertyType = propertyType;
        }

        properties.add(name);

      } else if (method.getName().startsWith("is")
          && method.getParameters().length == 0) {

        String name = Introspector.decapitalize(method.getName()
            .substring(2));

        String propertyType = null;
        JType retType = method.getReturnType().getErasedType();
        if (retType.isPrimitive() != null) {
          propertyType = retType.isPrimitive()
              .getQualifiedBoxedSourceName();
        } else {
          propertyType = retType
              .getParameterizedQualifiedSourceName();
        }

        JavaBeanProperty property = javaBeanProperties.get(name + "#"
            + propertyType);

        if (property == null) {
          property = new JavaBeanProperty(name);
          javaBeanProperties.put(name + "#" + propertyType, property);
        }

        property.getter = method;

        if (property.propertyType == null) {
          property.propertyType = propertyType;
        }

        properties.add(name);
      }
    }
  }

  public void writeBeanAdapter(IndentedWriter w)
      throws UnableToCompleteException {
    writePackage(w);
    w.newline();

    writeImports(w);
    w.newline();

    writeClassOpen(w);
    w.indent();

    // w.newline();
    // writeBeanAdapterFactoryRegistration(w);
    // w.newline();

    // default constructor
    w.write("public %s() {", implClassName);
    w.indent();

    Collection<JavaBeanProperty> javaBeanProperties = this.javaBeanProperties
        .values();

    for (JavaBeanProperty property : javaBeanProperties) {
      if (property.getter != null) {
        writeGetter(w, property);
      }
      if (property.setter != null) {
        writeSetter(w, property);
      }
    }

    w.newline();
    writeNotifyingProperties(w);
    w.newline();

    // close default constructor
    w.outdent();
    w.write("}");

    // close class
    w.outdent();
    w.write("}");
  }

  private void writeNotifyingProperties(IndentedWriter w) {
    for (String notifyingProperty : notifyingProperties) {
      w.write("notifyingProperties.add(\"%s\");", notifyingProperty);
    }
  }

  // private void writeBeanAdapterFactoryRegistration(IndentedWriter w) {
  // w.write("static {");
  // w.indent();
  // w.write("BeanAdapterFactory.register(%s.class, new BeanAdapterFactory<%s>() {",
  // beanType.getParameterizedQualifiedSourceName(),
  // beanType.getParameterizedQualifiedSourceName());
  // w.indent();
  // w.write("@Override");
  // w.write("protected BeanAdapter<%s> create(Object value) {",
  // beanType.getParameterizedQualifiedSourceName());
  // w.indent();
  // w.write("BeanAdapter<%s> adapter = GWT.create(%s.class);",
  // beanType.getParameterizedQualifiedSourceName(),
  // baseClass.getParameterizedQualifiedSourceName());
  // w.write("adapter.setBean((%s)value);",
  // beanType.getParameterizedQualifiedSourceName());
  // w.write("return adapter;");
  // w.outdent();
  // w.write("}");
  // w.outdent();
  // w.write("});");
  // w.outdent();
  // w.write("}");
  // }

  private void writeSetter(IndentedWriter w, JavaBeanProperty property) {
    if (property.getter != null) {
      w.write("setterMap.put(\"%s\", new SetterMethod() {", property.name);
    } else {
      w.write("setterMap.put(\"%s\", new SetterMethod() {", property.name
          + "#" + property.propertyType, property.propertyType);
    }
    w.indent();

    w.write("@Override");
    w.write("public void invokeSetterMethod(Object value) {");
    w.indent();
    w.write("try {");
    w.indent();
    w.write("((%s) bean).%s((%s) value);",
        beanType.getParameterizedQualifiedSourceName(),
        property.setter.getName(), property.propertyType);
    w.outdent();
    w.write("} catch (Exception ex) {");
    w.indent();
    w.write("throw new RuntimeException(ex);");
    w.outdent();
    w.write("}");
    w.outdent();
    w.write("}");
    w.outdent();
    w.write("});");
  }

  private void writeGetter(IndentedWriter w, JavaBeanProperty property) {
    w.write("getterMap.put(\"%s\", new GetterMethod() {", property.name);
    w.indent();

    w.write("@Override");
    w.write("public Object invokeGetterMethod() {");
    w.indent();
    w.write("try {");
    w.indent();
    JType retType = property.getter.getReturnType().getErasedType();
    if (retType.isPrimitive() != null) {
      w.write("return (%s) getBean().%s();", retType.isPrimitive()
          .getQualifiedBoxedSourceName(), property.getter.getName());
    } else {
      w.write("return getBean().%s();", property.getter.getName());
    }
    w.outdent();
    w.write("} catch (Exception ex) {");
    w.indent();
    w.write("throw new RuntimeException(ex);");
    w.outdent();
    w.write("}");
    w.outdent();
    w.write("}");

    w.outdent();
    w.write("});");
  }

  private void writeClassOpen(IndentedWriter w) {
    String s = "public class %s extends AbstractBeanAdapter<%s> implements %s {";
    w.write(s, implClassName,
        beanType.getParameterizedQualifiedSourceName(),
        baseClass.getParameterizedQualifiedSourceName());
  }

  private void writeImports(IndentedWriter w) {
    w.write("import %s;", AbstractBeanAdapter.class.getName());
    w.write("import %s;", BeanAdapter.class.getName());
    w.write("import %s;", BeanAdapterFactory.class.getName());
    w.write("import %s;", GetterMethod.class.getName());
    w.write("import %s;", GWT.class.getName());
    w.write("import %s;", SetterMethod.class.getName());
  }

  private void writePackage(IndentedWriter w) {
    String packageName = baseClass.getPackage().getName();
    if (packageName.length() > 0) {
      w.write("package %1$s;", packageName);
    }
  }

  /**
   * Post a warning message.
   */
  public void warn(String message) {
    logger.warn(message);
  }

  /**
   * Post a warning message.
   */
  public void warn(String message, Object... params) {
    logger.warn(message, params);
  }

  /**
   * Post an error message and halt processing. This method always throws an
   * {@link UnableToCompleteException}
   */
  public void die(String message) throws UnableToCompleteException {
    logger.die(message);
  }

  /**
   * Post an error message and halt processing. This method always throws an
   * {@link UnableToCompleteException}
   */
  public void die(String message, Object... params)
      throws UnableToCompleteException {
    logger.die(message, params);
  }

}
TOP

Related Classes of gwt.mosaic.rebind.beans.BeanAdapterWriter$JavaBeanProperty

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.