private void invokeRemove(
      MethodVisitor mv,
      String wrapperName,
      ClassDefinition core,
      String fieldName,
      FieldDefinition field) {
    mv.visitLdcInsn(fieldName);
    mv.visitVarInsn(ALOAD, 1);
    mv.visitMethodInsn(
        INVOKEVIRTUAL,
        Type.getInternalName(String.class),
        "equals",
        "(" + Type.getDescriptor(Object.class) + ")Z");
    Label l1 = new Label();
    mv.visitJumpInsn(IFEQ, l1);

    TraitFactory.invokeExtractor(mv, wrapperName, trait, core, field);

    if (BuildUtils.isPrimitive(field.getTypeName())) {
      TraitFactory.valueOf(mv, field.getTypeName());
    }
    mv.visitVarInsn(ASTORE, 2);

    TraitFactory.invokeInjector(mv, wrapperName, trait, core, field, true, 1);

    mv.visitVarInsn(ALOAD, 2);
    mv.visitInsn(ARETURN);
    mv.visitLabel(l1);
  }
  private void buildValues(
      ClassVisitor cw,
      String wrapperName,
      String coreName,
      ClassDefinition trait,
      ClassDefinition core,
      BitSet mask) {
    String internalWrapper = BuildUtils.getInternalType(wrapperName);

    MethodVisitor mv =
        cw.visitMethod(
            ACC_PUBLIC,
            "values",
            "()" + Type.getDescriptor(Collection.class),
            "()Ljava/util/Collection<Ljava/lang/Object;>;",
            null);
    mv.visitCode();

    mv.visitTypeInsn(NEW, Type.getInternalName(ArrayList.class));
    mv.visitInsn(DUP);
    mv.visitMethodInsn(INVOKESPECIAL, Type.getInternalName(ArrayList.class), "<init>", "()V");
    mv.visitVarInsn(ASTORE, 1);

    for (FieldDefinition field : core.getFieldsDefinitions()) {
      mv.visitVarInsn(ALOAD, 1);

      TraitFactory.invokeExtractor(mv, wrapperName, trait, core, field);

      if (BuildUtils.isPrimitive(field.getTypeName())) {
        TraitFactory.valueOf(mv, field.getTypeName());
      }

      mv.visitMethodInsn(
          INVOKEINTERFACE,
          Type.getInternalName(Collection.class),
          "add",
          "(" + Type.getDescriptor(Object.class) + ")Z");
      mv.visitInsn(POP);
    }

    mv.visitVarInsn(ALOAD, 1);
    mv.visitVarInsn(ALOAD, 0);
    mv.visitFieldInsn(GETFIELD, internalWrapper, "map", Type.getDescriptor(Map.class));
    mv.visitMethodInsn(
        INVOKEINTERFACE,
        Type.getInternalName(Map.class),
        "values",
        "()" + Type.getDescriptor(Collection.class));
    mv.visitMethodInsn(
        INVOKEINTERFACE,
        Type.getInternalName(Collection.class),
        "addAll",
        "(" + Type.getDescriptor(Collection.class) + ")Z");
    mv.visitInsn(POP);
    mv.visitVarInsn(ALOAD, 1);
    mv.visitInsn(ARETURN);

    //        mv.visitMaxs( core.getFieldsDefinitions().size() > 0 ? 3 : 2, 2);
    mv.visitMaxs(0, 0);
    mv.visitEnd();
  }
  private void buildContainsValue(
      ClassWriter cw,
      String wrapperName,
      String coreName,
      ClassDefinition trait,
      ClassDefinition core,
      BitSet mask) {
    String internalWrapper = BuildUtils.getInternalType(wrapperName);

    MethodVisitor mv =
        cw.visitMethod(
            ACC_PUBLIC, "containsValue", "(" + Type.getDescriptor(Object.class) + ")Z", null, null);
    mv.visitCode();

    // null check
    mv.visitVarInsn(ALOAD, 1);
    Label l99 = new Label();
    mv.visitJumpInsn(IFNONNULL, l99);

    for (FieldDefinition field : core.getFieldsDefinitions()) {
      if (!BuildUtils.isPrimitive(field.getTypeName())) {
        TraitFactory.invokeExtractor(mv, wrapperName, trait, core, field);
        Label l1 = new Label();
        mv.visitJumpInsn(IFNONNULL, l1);
        mv.visitInsn(ICONST_1);
        mv.visitInsn(IRETURN);
        mv.visitLabel(l1);
      }
    }

    mv.visitVarInsn(ALOAD, 0);
    mv.visitFieldInsn(GETFIELD, internalWrapper, "map", Type.getDescriptor(Map.class));
    mv.visitInsn(ACONST_NULL);
    mv.visitMethodInsn(
        INVOKEINTERFACE,
        Type.getInternalName(Map.class),
        "containsValue",
        "(" + Type.getDescriptor(Object.class) + ")Z");
    mv.visitInsn(IRETURN);
    mv.visitLabel(l99);

    // non-null values check
    for (FieldDefinition field : core.getFieldsDefinitions()) {

      mv.visitVarInsn(ALOAD, 1);

      TraitFactory.invokeExtractor(mv, wrapperName, trait, core, field);

      if (BuildUtils.isPrimitive(field.getTypeName())) {
        TraitFactory.valueOf(mv, field.getTypeName());
      }
      mv.visitMethodInsn(
          INVOKEVIRTUAL,
          Type.getInternalName(Object.class),
          "equals",
          "(" + Type.getDescriptor(Object.class) + ")Z");

      Label l0 = new Label();
      mv.visitJumpInsn(IFEQ, l0);
      mv.visitInsn(ICONST_1);
      mv.visitInsn(IRETURN);
      mv.visitLabel(l0);
    }

    mv.visitVarInsn(ALOAD, 0);
    mv.visitFieldInsn(GETFIELD, internalWrapper, "map", Type.getDescriptor(Map.class));
    mv.visitVarInsn(ALOAD, 1);
    mv.visitMethodInsn(
        INVOKEINTERFACE,
        Type.getInternalName(Map.class),
        "containsValue",
        "(" + Type.getDescriptor(Object.class) + ")Z");
    mv.visitInsn(IRETURN);
    //        mv.visitMaxs( core.getFieldsDefinitions().size() > 0 ? 3 : 2, 2 );
    mv.visitMaxs(0, 0);
    mv.visitEnd();
  }