Example #1
0
    public void generateClass(ClassVisitor v) {
      ClassEmitter ce = new ClassEmitter(v);

      Method newInstance = ReflectUtils.findNewInstance(keyInterface);
      if (!newInstance.getReturnType().equals(Object.class)) {
        throw new IllegalArgumentException("newInstance method must return Object");
      }

      Type[] parameterTypes = TypeUtils.getTypes(newInstance.getParameterTypes());
      ce.begin_class(
          Constants.V1_2,
          Constants.ACC_PUBLIC,
          getClassName(),
          KEY_FACTORY,
          new Type[] {Type.getType(keyInterface)},
          Constants.SOURCE_FILE);
      EmitUtils.null_constructor(ce);
      EmitUtils.factory_method(ce, ReflectUtils.getSignature(newInstance));

      int seed = 0;
      CodeEmitter e =
          ce.begin_method(Constants.ACC_PUBLIC, TypeUtils.parseConstructor(parameterTypes), null);
      e.load_this();
      e.super_invoke_constructor();
      e.load_this();
      for (int i = 0; i < parameterTypes.length; i++) {
        seed += parameterTypes[i].hashCode();
        ce.declare_field(
            Constants.ACC_PRIVATE | Constants.ACC_FINAL, getFieldName(i), parameterTypes[i], null);
        e.dup();
        e.load_arg(i);
        e.putfield(getFieldName(i));
      }
      e.return_value();
      e.end_method();

      // hash code
      e = ce.begin_method(Constants.ACC_PUBLIC, HASH_CODE, null);
      int hc = (constant != 0) ? constant : PRIMES[(int) (Math.abs(seed) % PRIMES.length)];
      int hm = (multiplier != 0) ? multiplier : PRIMES[(int) (Math.abs(seed * 13) % PRIMES.length)];
      e.push(hc);
      for (int i = 0; i < parameterTypes.length; i++) {
        e.load_this();
        e.getfield(getFieldName(i));
        EmitUtils.hash_code(e, parameterTypes[i], hm, customizer);
      }
      e.return_value();
      e.end_method();

      // equals
      e = ce.begin_method(Constants.ACC_PUBLIC, EQUALS, null);
      Label fail = e.make_label();
      e.load_arg(0);
      e.instance_of_this();
      e.if_jump(e.EQ, fail);
      for (int i = 0; i < parameterTypes.length; i++) {
        e.load_this();
        e.getfield(getFieldName(i));
        e.load_arg(0);
        e.checkcast_this();
        e.getfield(getFieldName(i));
        EmitUtils.not_equals(e, parameterTypes[i], fail, customizer);
      }
      e.push(1);
      e.return_value();
      e.mark(fail);
      e.push(0);
      e.return_value();
      e.end_method();

      // toString
      e = ce.begin_method(Constants.ACC_PUBLIC, TO_STRING, null);
      e.new_instance(Constants.TYPE_STRING_BUFFER);
      e.dup();
      e.invoke_constructor(Constants.TYPE_STRING_BUFFER);
      for (int i = 0; i < parameterTypes.length; i++) {
        if (i > 0) {
          e.push(", ");
          e.invoke_virtual(Constants.TYPE_STRING_BUFFER, APPEND_STRING);
        }
        e.load_this();
        e.getfield(getFieldName(i));
        EmitUtils.append_string(e, parameterTypes[i], EmitUtils.DEFAULT_DELIMITERS, customizer);
      }
      e.invoke_virtual(Constants.TYPE_STRING_BUFFER, TO_STRING);
      e.return_value();
      e.end_method();

      ce.end_class();
    }