private void addWriteToParcelMethod(HelperClassBuilder builder) throws ProcessorError {
    ClassName targetClassName = builder.getArgClassName();
    String target = "target";
    String parcel = "parcel";

    MethodSpec.Builder method =
        MethodSpec.methodBuilder(METHOD_NAME_WRITE_TO_PARCEL)
            .addAnnotation(
                WeaveBuilder.weave()
                    .method(METHOD_NAME_WRITE_TO_PARCEL, Parcel.class, int.class)
                    .placed(WeaveBuilder.MethodWeaveType.AFTER_SUPER)
                    .withStatement(
                        "%s.%s(this, $1);",
                        fullName(builder.getClassName()), METHOD_NAME_WRITE_TO_PARCEL)
                    .build())
            .addModifiers(Modifier.PUBLIC, Modifier.STATIC);

    addClassAsParameter(method, targetClassName, target);
    method.addParameter(Parcel.class, parcel);

    for (int i = 0, c = mFields.size(); i < c; i++) {
      Field field = mFields.get(i);
      CallFormat writeCall = Parceler.writeCall(field.element);

      if (writeCall == null) {
        continue; // TODO : should throw exception or ignore field ?!
      }

      Pair<String, List<Object>> mappedWriteCall = mapCall(field, writeCall, target, parcel);
      method.addStatement(
          mappedWriteCall.fst, mappedWriteCall.snd.toArray(new Object[mappedWriteCall.snd.size()]));
    }

    builder.getBuilder().addMethod(method.build());
  }
  private void addReadFromParcelMethod(HelperClassBuilder builder) throws ProcessorError {
    ClassName targetClassName = builder.getArgClassName();
    String target = "target";
    String parcel = "parcel";

    MethodSpec.Builder method =
        MethodSpec.methodBuilder(METHOD_NAME_READ_FROM_PARCEL)
            .addAnnotation(
                WeaveBuilder.weave()
                    .constructor(Parcel.class)
                    .withStatement(
                        "%s.%s(this, $1);",
                        fullName(builder.getClassName()), METHOD_NAME_READ_FROM_PARCEL)
                    .build())
            .addModifiers(Modifier.PUBLIC, Modifier.STATIC);

    addClassAsParameter(method, targetClassName, target);
    method.addParameter(Parcel.class, parcel);

    for (int i = 0, c = mFields.size(); i < c; i++) {
      Field field = mFields.get(i);
      CallFormat readCall = Parceler.readCall(field.element);

      if (readCall == null) {
        continue; // TODO : should throw exception or ignore field ?!
      }

      Pair<String, List<Object>> mappedReadCall = mapCall(field, readCall, target, parcel);
      String format = mappedReadCall.fst;
      List<Object> args = mappedReadCall.snd;
      if (field.isAccessible()) {
        format = String.format("$N.$N = %s", format);
        args.add(0, field.element.getSimpleName());
        args.add(0, target);
      } else {
        format = String.format("$N.$N(%s)", format);
        args.add(0, field.setter.getSimpleName());
        args.add(0, target);
      }

      method.addStatement(format, args.toArray(new Object[args.size()]));
    }

    builder.getBuilder().addMethod(method.build());
  }
  private void addCreatorField(HelperClassBuilder builder) {
    FieldSpec.Builder field =
        FieldSpec.builder(
            ParameterizedTypeName.get(
                ClassName.get(Parcelable.Creator.class), builder.getArgClassName()),
            FIELD_NAME_CREATOR,
            Modifier.PUBLIC,
            Modifier.STATIC,
            Modifier.FINAL);

    field.addAnnotation(
        WeaveBuilder.weave()
            .field()
            .withStatement("%s.%s", fullName(builder.getClassName()), FIELD_NAME_CREATOR)
            .build());
    field.initializer(
        "new $T<$T>() {\n"
            + "\t@$T\n"
            + "\tpublic $T createFromParcel($T in) {\n"
            + "\t\treturn new $T(in);\n"
            + "\t}\n"
            + "\t@$T\n"
            + "\tpublic $T[] newArray(int size) {\n"
            + "\t\treturn new $T[size];\n"
            + "\t}\n"
            + "}",
        Parcelable.Creator.class,
        builder.getArgClassName(),
        Override.class,
        builder.getArgClassName(),
        Parcel.class,
        builder.getArgClassName(),
        Override.class,
        builder.getArgClassName(),
        builder.getArgClassName());

    builder.getBuilder().addField(field.build());
  }