Package com.habitsoft.kiyaa.rebind

Source Code of com.habitsoft.kiyaa.rebind.ClonerGenerator$ClonerGeneratorInstance

package com.habitsoft.kiyaa.rebind;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JArrayType;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JField;
import com.google.gwt.core.ext.typeinfo.JMethod;
import com.google.gwt.core.ext.typeinfo.JParameterizedType;
import com.google.gwt.core.ext.typeinfo.JType;

public class ClonerGenerator extends BaseGenerator {

  @Override
  protected GeneratorInstance createGeneratorInstance() {
    return new ClonerGeneratorInstance();
  }

  class ClonerGeneratorInstance extends GeneratorInstance {

    Set<String> doneTypes = new TreeSet<String>();
    List<JClassType> beanTypes = new ArrayList<JClassType>();
   
    @Override
    protected void generateClassBody() throws UnableToCompleteException {
      // Find the type to clone
      JClassType[] implementedInterfaces = baseType.getImplementedInterfaces();
      for(JClassType iface : implementedInterfaces) {
        JParameterizedType parameterizedType = iface.isParameterized();
        if(parameterizedType == null)
          continue;
        if(parameterizedType.getSimpleSourceName().equals("Cloner")) {
          JClassType[] typeArgs = parameterizedType.getTypeArgs();
          if(typeArgs.length != 1) {
            logger.log(TreeLogger.ERROR, "Cloner interface must be parameterized to the type of object to clone", null);
            throw new UnableToCompleteException();
          }
          beanTypes.add(typeArgs[0]);
        }
      }
     
      if(beanTypes.isEmpty()) {
        logger.log(TreeLogger.ERROR, "Cloner class must implement the Cloner<T> interface", null);
        throw new UnableToCompleteException();
      }
      for(int i=0; i < beanTypes.size(); i++) {
        JClassType beanType = beanTypes.get(i);
        generateCloner(beanType);
      }
     
    }

    private void generateCloner(JClassType beanType) {
      String className = beanType.getParameterizedQualifiedSourceName();
      if(doneTypes.add(className)) {
        sw.println("public "+className+" clone("+className+" src) {");
        sw.indent();
        sw.println("if(src == null) return null;");
     
        sw.println(className+" dest = new "+className+"();");
       
        sw.println("clone(src, dest);");
        sw.println("return dest;");
        sw.outdent();
        sw.println("}");
       
        sw.println("public void clone("+className+" src, "+className+" dest) {");
        sw.indent();
        generateCloneFields(beanType);
        sw.outdent();
        sw.println("}");
       
        sw.println("public java.util.Set<String> diff("+className+" a, "+className+" b) {");
        sw.indent();
        sw.println("java.util.TreeSet<String> diffs = new java.util.TreeSet<String>();");
        generateGetDifferences(beanType, "a", "b");
        sw.println("return diffs;");
        sw.outdent();
        sw.println("}");
       
      }
    }

    private void generateCloneFields(JClassType beanType) {
      if(beanType.getQualifiedSourceName().startsWith("java.lang"))
        return;
      generateCloneFields(beanType.getSuperclass());
      JField[] fields = beanType.getFields();
      for(JField field : fields) {
        JClassType targetType = beanType;
        String capFieldName = capitalize(field.getName());
        JMethod getter = targetType.findMethod("get"+capFieldName, new JType[0]);
        if(getter == null) getter = targetType.findMethod("is"+capFieldName, new JType[0]);
        JType type = field.getType();
        JMethod setter = targetType.findMethod("set"+capFieldName, new JType[]{type});
        if(getter != null && setter != null) {
          String copyValue = "src."+getter.getName()+"()";
         
          copyValue = copyField(type, copyValue, capFieldName);
          sw.println("dest.set"+capFieldName+"("+copyValue+");");
        }
      }
    }

    private void generateGetDifferences(JClassType beanType, String firstObject, String secondObject) {
      if(beanType.getQualifiedSourceName().startsWith("java.lang"))
        return;
      generateGetDifferences(beanType.getSuperclass(), firstObject, secondObject);
      JField[] fields = beanType.getFields();
      for(JField field : fields) {
        JClassType targetType = beanType;
        String capFieldName = capitalize(field.getName());
        JMethod getter = targetType.findMethod("get"+capFieldName, new JType[0]);
        if(getter == null) getter = targetType.findMethod("is"+capFieldName, new JType[0]);
        JType type = field.getType();
        if(getter != null) {
          String firstValue = firstObject+"."+getter.getName()+"()";
          String secondValue = secondObject+"."+getter.getName()+"()";
          generateCompareValue(field.getName(), type, firstValue,
              secondValue);
        }
      }
    }

    private void generateCompareValue(String fieldName,
        JType type, String firstValue, String secondValue) {
      JArrayType arrayType = type.isArray();
      if(arrayType != null) {
        JType eltType = type.isArray().getComponentType();
        generateCompareArray(fieldName, firstValue, secondValue,
            eltType);
      } else {
        String test = type.isPrimitive() != null ? firstValue+" != "+secondValue
            : firstValue+" != "+secondValue+" && ("+firstValue+" == null || "+secondValue+" == null || ! "+firstValue+".equals("+secondValue+"))";
        sw.println("if("+test+") diffs.add(\""+fieldName+"\");");
      }
    }

    private void generateCompareArray(String fieldName,
        String firstValue, String secondValue, JType eltType) {
      sw.println("if(!java.util.Arrays.equals("+firstValue+", "+secondValue+")) {");
      sw.indent();
      sw.println("diffs.add(\""+fieldName+"\");");
      sw.println("int count = Math.min("+firstValue+" == null ? 0 : "+firstValue+".length, "+secondValue+" == null ? 0 : "+secondValue+".length);");
      sw.println("for(int i=0; i < count; i++) {");
      sw.indent();
      String eltName = fieldName+"[\"+i+\"]";
      generateCompareValue(eltName, eltType, firstValue+"[i]", secondValue+"[i]");
      sw.outdent();
      sw.println("}");
      sw.println("int maxCount = Math.max("+firstValue+" == null ? 0 : "+firstValue+".length, "+secondValue+" == null ? 0 : "+secondValue+".length);");
      sw.println("for(int i=count; i < maxCount; i++) {");
      sw.indent();
      sw.indentln("diffs.add(\""+eltName+"\");");
      sw.outdent();
      sw.println("}");
      sw.outdent();
      sw.println("}");
    }
   
    private String copyField(JType type, String copyValue, String capFieldName) {
      // Don't copy primitive types, or immutable types
      if(type.isPrimitive() != null
        || type.isEnum() != null
        || type.getQualifiedSourceName().startsWith("java.lang.")
        || type.getQualifiedSourceName().startsWith("java.math."))
        return copyValue;
     
      // Deep copy arrays
      JArrayType array = type.isArray();
      if(array != null) {
        String arrayTypeName = array.getParameterizedQualifiedSourceName();
        String compTypeName = array.getComponentType().getParameterizedQualifiedSourceName();
        String arrayName = "dest"+capFieldName;
        sw.println(arrayTypeName+" src"+capFieldName+" = "+copyValue+";");
        sw.println(arrayTypeName+" "+arrayName+";");
        sw.println("if(src"+capFieldName+" != null) {");
        sw.indent();
        sw.println(arrayName+" = new "+compTypeName+"[src"+capFieldName+".length];");
        sw.println("int "+arrayName+"Count = 0;");
        sw.println("for(int i=0; i < "+arrayName+".length; i++) {");
        sw.indent();
        sw.println(arrayName+"[i] = "+copyField(array.getComponentType(), "src"+capFieldName+"[i]", capFieldName+"Elt")+";");
        sw.outdent();
        sw.println("}");
        sw.outdent();
        sw.println("} else {");
        sw.indentln(arrayName+" = null;");
        sw.println("}");
        copyValue = "dest"+capFieldName;
      }
     
      // Deep copy objects
      JClassType cls = type.isClassOrInterface();
      if(cls != null) {
          if(cls.findMethod("clone", new JType[0]) != null) {
            copyValue = "("+cls.getParameterizedQualifiedSourceName()+") "+copyValue;
          } else {
            beanTypes.add(cls);
            copyValue = "clone("+copyValue+")";
          }
      }
      return copyValue;
    }
   
  }
}
TOP

Related Classes of com.habitsoft.kiyaa.rebind.ClonerGenerator$ClonerGeneratorInstance

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.