public static byte[] createTargetSetterFactory(String factoryName, String className, Type target)
      throws Exception {

    ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
    MethodVisitor mv;

    String factoryType = AsmUtils.toType(factoryName);
    String classType = AsmUtils.toType(className);
    String targetType = AsmUtils.toType(target);

    cw.visit(
        V1_6,
        ACC_FINAL + ACC_PUBLIC + ACC_SUPER,
        factoryType,
        "L" + CELL_HANDLER_FACTORY_TYPE + "<L" + targetType + ";>;",
        CELL_HANDLER_FACTORY_TYPE,
        null);

    {
      mv =
          cw.visitMethod(
              ACC_PUBLIC,
              "<init>",
              "("
                  + AsmUtils.toDeclaredLType(Instantiator.class)
                  + AsmUtils.toDeclaredLType(CsvColumnKey[].class)
                  + AsmUtils.toDeclaredLType(ParsingContextFactory.class)
                  + AsmUtils.toDeclaredLType(FieldMapperErrorHandler.class)
                  + ")V",
              "("
                  + "L"
                  + AsmUtils.toType(Instantiator.class)
                  + "<L"
                  + AsmUtils.toType(CsvMapperCellHandler.class)
                  + "<L"
                  + targetType
                  + ";>;L"
                  + targetType
                  + ";>;"
                  + AsmUtils.toDeclaredLType(CsvColumnKey[].class)
                  + AsmUtils.toDeclaredLType(ParsingContextFactory.class)
                  + "L"
                  + AsmUtils.toType(FieldMapperErrorHandler.class)
                  + "<L"
                  + AsmUtils.toType(CsvColumnKey.class)
                  + ";>;"
                  + ")V",
              null);

      mv.visitCode();
      mv.visitVarInsn(ALOAD, 0);
      mv.visitVarInsn(ALOAD, 1);
      mv.visitVarInsn(ALOAD, 2);
      mv.visitVarInsn(ALOAD, 3);
      mv.visitVarInsn(ALOAD, 4);
      mv.visitMethodInsn(
          INVOKESPECIAL,
          CELL_HANDLER_FACTORY_TYPE,
          "<init>",
          "("
              + AsmUtils.toDeclaredLType(Instantiator.class)
              + AsmUtils.toDeclaredLType(CsvColumnKey[].class)
              + AsmUtils.toDeclaredLType(ParsingContextFactory.class)
              + AsmUtils.toDeclaredLType(FieldMapperErrorHandler.class)
              + ")V",
          false);
      mv.visitInsn(RETURN);
      mv.visitMaxs(5, 5);
      mv.visitEnd();
    }
    {
      mv =
          cw.visitMethod(
              ACC_PUBLIC,
              "newInstance",
              "("
                  + AsmUtils.toDeclaredLType(DelayedCellSetter[].class)
                  + AsmUtils.toDeclaredLType(CellSetter[].class)
                  + ")"
                  + AsmUtils.toDeclaredLType(CsvMapperCellHandler.class),
              "("
                  + "[L"
                  + DELAYED_CELL_SETTER_TYPE
                  + "<L"
                  + targetType
                  + ";*>;"
                  + "[L"
                  + CELL_SETTER_TYPE
                  + "<L"
                  + targetType
                  + ";>;"
                  + ")"
                  + "L"
                  + AsmUtils.toType(CsvMapperCellHandler.class)
                  + "<L"
                  + targetType
                  + ";>;",
              null);
      mv.visitCode();
      mv.visitTypeInsn(NEW, classType);
      mv.visitInsn(DUP);
      mv.visitVarInsn(ALOAD, 0);
      mv.visitFieldInsn(
          GETFIELD, factoryType, "instantiator", AsmUtils.toDeclaredLType(Instantiator.class));
      mv.visitVarInsn(ALOAD, 1);
      mv.visitVarInsn(ALOAD, 2);
      mv.visitVarInsn(ALOAD, 0);
      mv.visitFieldInsn(
          GETFIELD, factoryType, "keys", AsmUtils.toDeclaredLType(CsvColumnKey[].class));
      mv.visitVarInsn(ALOAD, 0);
      mv.visitFieldInsn(
          GETFIELD,
          factoryType,
          "parsingContextFactory",
          AsmUtils.toDeclaredLType(ParsingContextFactory.class));
      mv.visitMethodInsn(
          INVOKEVIRTUAL,
          AsmUtils.toType(ParsingContextFactory.class),
          "newContext",
          "()" + AsmUtils.toDeclaredLType(ParsingContext.class),
          false);
      mv.visitVarInsn(ALOAD, 0);
      mv.visitFieldInsn(
          GETFIELD,
          factoryType,
          "fieldErrorHandler",
          AsmUtils.toDeclaredLType(FieldMapperErrorHandler.class));
      mv.visitMethodInsn(
          INVOKESPECIAL,
          classType,
          "<init>",
          "("
              + AsmUtils.toDeclaredLType(Instantiator.class)
              + AsmUtils.toDeclaredLType(DelayedCellSetter[].class)
              + AsmUtils.toDeclaredLType(CellSetter[].class)
              + AsmUtils.toDeclaredLType(CsvColumnKey[].class)
              + AsmUtils.toDeclaredLType(ParsingContext.class)
              + AsmUtils.toDeclaredLType(FieldMapperErrorHandler.class)
              + ")V",
          false);
      mv.visitInsn(ARETURN);
      mv.visitMaxs(8, 3);
      mv.visitEnd();
    }
    cw.visitEnd();

    return cw.toByteArray();
  }