/**
  * Makes the given class visitor visit this field.
  *
  * @param cv a class visitor.
  */
 public void accept(final ClassVisitor cv) {
   FieldVisitor fv = cv.visitField(access, name, desc, signature, value);
   if (fv == null) {
     return;
   }
   int i, n;
   n = visibleAnnotations == null ? 0 : visibleAnnotations.size();
   for (i = 0; i < n; ++i) {
     AnnotationNode an = visibleAnnotations.get(i);
     an.accept(fv.visitAnnotation(an.desc, true));
   }
   n = invisibleAnnotations == null ? 0 : invisibleAnnotations.size();
   for (i = 0; i < n; ++i) {
     AnnotationNode an = invisibleAnnotations.get(i);
     an.accept(fv.visitAnnotation(an.desc, false));
   }
   n = visibleTypeAnnotations == null ? 0 : visibleTypeAnnotations.size();
   for (i = 0; i < n; ++i) {
     TypeAnnotationNode an = visibleTypeAnnotations.get(i);
     an.accept(fv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc, true));
   }
   n = invisibleTypeAnnotations == null ? 0 : invisibleTypeAnnotations.size();
   for (i = 0; i < n; ++i) {
     TypeAnnotationNode an = invisibleTypeAnnotations.get(i);
     an.accept(fv.visitTypeAnnotation(an.typeRef, an.typePath, an.desc, false));
   }
   n = attrs == null ? 0 : attrs.size();
   for (i = 0; i < n; ++i) {
     fv.visitAttribute(attrs.get(i));
   }
   fv.visitEnd();
 }
  protected void buildFields(ClassWriter cw, EnumClassDefinition classDef) {
    FieldVisitor fv;
    for (FieldDefinition fld : classDef.getFieldsDefinitions()) {
      fv =
          cw.visitField(
              ACC_PRIVATE + ACC_FINAL,
              fld.getName(),
              BuildUtils.getTypeDescriptor(fld.getTypeName()),
              null,
              null);
      fv.visitEnd();
    }

    {
      fv =
          cw.visitField(
              ACC_PRIVATE + ACC_STATIC, "$context", "Lorg/mvel2/ParserContext;", null, null);
      fv.visitEnd();
    }
  }
  protected void buildLiterals(ClassWriter cw, EnumClassDefinition classDef) {
    FieldVisitor fv;
    for (EnumLiteralDefinition lit : classDef.getEnumLiterals()) {
      fv =
          cw.visitField(
              ACC_PUBLIC + ACC_FINAL + ACC_STATIC + ACC_ENUM,
              lit.getName(),
              BuildUtils.getTypeDescriptor(classDef.getClassName()),
              null,
              null);
      fv.visitEnd();
    }

    {
      fv =
          cw.visitField(
              ACC_PRIVATE + ACC_FINAL + ACC_STATIC + ACC_SYNTHETIC,
              "$VALUES",
              "[" + BuildUtils.getTypeDescriptor(classDef.getClassName()),
              null,
              null);
      fv.visitEnd();
    }
  }
  public byte[] buildClass(ClassDefinition core)
      throws IOException, IntrospectionException, SecurityException, IllegalArgumentException,
          ClassNotFoundException, NoSuchMethodException, IllegalAccessException,
          InvocationTargetException, InstantiationException, NoSuchFieldException {

    Class coreKlazz = core.getDefinedClass();
    String coreName = coreKlazz.getName();
    String wrapperName = coreName + "Wrapper";

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

    cw.visit(
        V1_5,
        ACC_PUBLIC + ACC_SUPER,
        BuildUtils.getInternalType(wrapperName),
        BuildUtils.getTypeDescriptor(coreName)
            + "Lorg/drools/factmodel/traits/CoreWrapper<"
            + BuildUtils.getTypeDescriptor(coreName)
            + ">;",
        BuildUtils.getInternalType(coreName),
        new String[] {
          Type.getInternalName(CoreWrapper.class), Type.getInternalName(Externalizable.class)
        });

    {
      fv = cw.visitField(ACC_PRIVATE, "core", BuildUtils.getTypeDescriptor(coreName), null, null);
      fv.visitEnd();
    }
    {
      fv =
          cw.visitField(
              ACC_PRIVATE,
              TraitableBean.MAP_FIELD_NAME,
              Type.getDescriptor(Map.class),
              "Ljava/util/Map<Ljava/lang/String;Ljava/lang/Object;>;",
              null);
      fv.visitEnd();
    }
    {
      fv =
          cw.visitField(
              ACC_PRIVATE,
              TraitableBean.TRAITSET_FIELD_NAME,
              Type.getDescriptor(Map.class),
              "Ljava/util/Map<Ljava/lang/String;Lorg/drools/factmodel/traits/Thing;>;",
              null);
      fv.visitEnd();
    }

    {
      mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
      mv.visitCode();

      mv.visitVarInsn(ALOAD, 0);
      mv.visitMethodInsn(INVOKESPECIAL, BuildUtils.getInternalType(coreName), "<init>", "()V");

      //            mv.visitVarInsn( ALOAD, 0 );
      //            mv.visitTypeInsn( NEW, Type.getInternalName( HashMap.class ) );
      //            mv.visitInsn( DUP );
      //            mv.visitMethodInsn( INVOKESPECIAL, Type.getInternalName( HashMap.class ),
      // "<init>", "()V" );
      //            mv.visitFieldInsn( PUTFIELD,
      //                    BuildUtils.getInternalType( wrapperName ),
      //                    TraitableBean.MAP_FIELD_NAME,
      //                    Type.getDescriptor( Map.class ) );

      //            mv.visitVarInsn( ALOAD, 0 );
      //            mv.visitTypeInsn( NEW, Type.getInternalName( VetoableTypedMap.class ) );
      //            mv.visitInsn( DUP );
      //            mv.visitTypeInsn( NEW, Type.getInternalName( HashMap.class ) );
      //            mv.visitInsn( DUP );
      //            mv.visitMethodInsn( INVOKESPECIAL, Type.getInternalName( HashMap.class ),
      // "<init>", "()V" );
      //            mv.visitMethodInsn( INVOKESPECIAL, Type.getInternalName( VetoableTypedMap.class
      // ), "<init>", "(" + Type.getDescriptor( Map.class ) + ")V" );
      //            mv.visitFieldInsn( PUTFIELD,
      //                    BuildUtils.getInternalType( wrapperName ),
      //                    TraitableBean.TRAITSET_FIELD_NAME,
      //                    Type.getDescriptor( Map.class ) );

      mv.visitInsn(RETURN);
      mv.visitMaxs(0, 0);
      mv.visitEnd();
    }
    if (coreKlazz == null || needsMethod(coreKlazz, "getCore")) {
      {
        mv =
            cw.visitMethod(
                ACC_PUBLIC,
                "getCore",
                "()" + Type.getDescriptor(Object.class),
                "()" + BuildUtils.getTypeDescriptor(coreName),
                null);
        mv.visitCode();
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(
            GETFIELD,
            BuildUtils.getInternalType(wrapperName),
            "core",
            BuildUtils.getTypeDescriptor(coreName));
        mv.visitInsn(ARETURN);
        mv.visitMaxs(0, 0);
        mv.visitEnd();
      }
    }
    if (coreKlazz == null || needsMethod(coreKlazz, "getDynamicProperties")) {
      {
        mv =
            cw.visitMethod(
                ACC_PUBLIC,
                "getDynamicProperties",
                "()" + Type.getDescriptor(Map.class),
                "()Ljava/util/Map<Ljava/lang/String;Ljava/lang/Object;>;",
                null);
        mv.visitCode();
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(
            GETFIELD,
            BuildUtils.getInternalType(wrapperName),
            TraitableBean.MAP_FIELD_NAME,
            Type.getDescriptor(Map.class));
        mv.visitInsn(ARETURN);
        mv.visitMaxs(0, 0);
        mv.visitEnd();

        mv =
            cw.visitMethod(
                ACC_PUBLIC,
                "setDynamicProperties",
                "(" + Type.getDescriptor(Map.class) + ")V",
                "(Ljava/util/Map<Ljava/lang/String;Ljava/lang/Object;>;)V",
                null);
        mv.visitCode();
        mv.visitVarInsn(ALOAD, 0);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitFieldInsn(
            PUTFIELD,
            BuildUtils.getInternalType(wrapperName),
            TraitableBean.MAP_FIELD_NAME,
            Type.getDescriptor(Map.class));
        mv.visitInsn(RETURN);
        mv.visitMaxs(0, 0);
        mv.visitEnd();
      }
    }
    if (coreKlazz == null || needsMethod(coreKlazz, "getTraitMap")) {
      {
        mv =
            cw.visitMethod(
                ACC_PUBLIC,
                "getTraitMap",
                "()" + Type.getDescriptor(Map.class),
                "()Ljava/util/Map<Ljava/lang/String;Lorg/drools/factmodel/traits/Thing;>;",
                null);
        mv.visitCode();
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(
            GETFIELD,
            BuildUtils.getInternalType(wrapperName),
            TraitableBean.TRAITSET_FIELD_NAME,
            Type.getDescriptor(Map.class));
        Label l0 = new Label();
        mv.visitJumpInsn(IFNONNULL, l0);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitTypeInsn(NEW, Type.getInternalName(VetoableTypedMap.class));
        mv.visitInsn(DUP);
        mv.visitTypeInsn(NEW, Type.getInternalName(HashMap.class));
        mv.visitInsn(DUP);
        mv.visitMethodInsn(INVOKESPECIAL, Type.getInternalName(HashMap.class), "<init>", "()V");
        mv.visitMethodInsn(
            INVOKESPECIAL,
            Type.getInternalName(VetoableTypedMap.class),
            "<init>",
            "(" + Type.getDescriptor(Map.class) + ")V");
        mv.visitFieldInsn(
            PUTFIELD,
            BuildUtils.getInternalType(wrapperName),
            TraitableBean.TRAITSET_FIELD_NAME,
            Type.getDescriptor(Map.class));
        mv.visitLabel(l0);
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(
            GETFIELD,
            BuildUtils.getInternalType(wrapperName),
            TraitableBean.TRAITSET_FIELD_NAME,
            Type.getDescriptor(Map.class));
        mv.visitInsn(ARETURN);
        mv.visitMaxs(0, 0);
        mv.visitEnd();
      }
    }
    if (coreKlazz == null || needsMethod(coreKlazz, "setTraitMap", Map.class)) {
      {
        mv = cw.visitMethod(ACC_PUBLIC, "setTraitMap", "(Ljava/util/Map;)V", null, null);
        mv.visitCode();
        mv.visitVarInsn(ALOAD, 0);
        mv.visitTypeInsn(NEW, Type.getInternalName(VetoableTypedMap.class));
        mv.visitInsn(DUP);
        mv.visitVarInsn(ALOAD, 1);
        mv.visitMethodInsn(
            INVOKESPECIAL,
            Type.getInternalName(VetoableTypedMap.class),
            "<init>",
            "(" + Type.getDescriptor(Map.class) + ")V");
        mv.visitFieldInsn(
            PUTFIELD,
            BuildUtils.getInternalType(wrapperName),
            TraitableBean.TRAITSET_FIELD_NAME,
            Type.getDescriptor(Map.class));
        mv.visitInsn(RETURN);
        mv.visitMaxs(0, 0);
        mv.visitEnd();
      }
    }
    if (coreKlazz == null || needsMethod(coreKlazz, "addTrait", String.class, Thing.class)) {
      {
        mv =
            cw.visitMethod(
                ACC_PUBLIC,
                "addTrait",
                "(" + Type.getDescriptor(String.class) + Type.getDescriptor(Thing.class) + ")V",
                "(" + Type.getDescriptor(String.class) + Type.getDescriptor(Thing.class) + ")V",
                null);
        mv.visitCode();
        mv.visitVarInsn(ALOAD, 0);
        mv.visitMethodInsn(
            INVOKEVIRTUAL,
            BuildUtils.getInternalType(wrapperName),
            "getTraitMap",
            "()" + Type.getDescriptor(Map.class));
        mv.visitTypeInsn(CHECKCAST, Type.getInternalName(VetoableTypedMap.class));
        mv.visitVarInsn(ALOAD, 1);
        mv.visitVarInsn(ALOAD, 2);
        mv.visitMethodInsn(
            INVOKEVIRTUAL,
            Type.getInternalName(VetoableTypedMap.class),
            "putSafe",
            "("
                + Type.getDescriptor(String.class)
                + Type.getDescriptor(Thing.class)
                + ")"
                + Type.getDescriptor(Thing.class));
        mv.visitInsn(POP);
        mv.visitInsn(RETURN);
        mv.visitMaxs(0, 0);
        mv.visitEnd();
      }
    }
    if (coreKlazz == null || needsMethod(coreKlazz, "getTrait", String.class)) {
      {
        mv =
            cw.visitMethod(
                ACC_PUBLIC,
                "getTrait",
                "(" + Type.getDescriptor(String.class) + ")" + Type.getDescriptor(Thing.class),
                "(" + Type.getDescriptor(String.class) + ")" + Type.getDescriptor(Thing.class),
                null);
        mv.visitCode();
        mv.visitVarInsn(ALOAD, 0);
        mv.visitMethodInsn(
            INVOKEVIRTUAL,
            BuildUtils.getInternalType(wrapperName),
            "getTraitMap",
            "()" + Type.getDescriptor(Map.class));
        mv.visitVarInsn(ALOAD, 1);
        mv.visitMethodInsn(
            INVOKEINTERFACE,
            Type.getInternalName(Map.class),
            "get",
            "(" + Type.getDescriptor(Object.class) + ")" + Type.getDescriptor(Object.class));
        mv.visitTypeInsn(CHECKCAST, Type.getInternalName(Thing.class));
        mv.visitInsn(ARETURN);
        mv.visitMaxs(0, 0);
        mv.visitEnd();
      }
    }
    if (coreKlazz == null || needsMethod(coreKlazz, "hasTrait", String.class)) {
      {
        mv =
            cw.visitMethod(
                ACC_PUBLIC, "hasTrait", "(" + Type.getDescriptor(String.class) + ")Z", null, null);
        mv.visitCode();
        mv.visitVarInsn(ALOAD, 0);
        mv.visitMethodInsn(
            INVOKEVIRTUAL,
            BuildUtils.getInternalType(wrapperName),
            "getTraitMap",
            "()" + Type.getDescriptor(Map.class));
        mv.visitVarInsn(ALOAD, 1);
        mv.visitMethodInsn(
            INVOKEINTERFACE,
            Type.getInternalName(Map.class),
            "containsKey",
            "(" + Type.getDescriptor(Object.class) + ")Z");
        mv.visitInsn(IRETURN);
        mv.visitMaxs(0, 0);
        mv.visitEnd();
      }
    }
    if (coreKlazz == null || needsMethod(coreKlazz, "removeTrait", String.class)) {
      {
        mv =
            cw.visitMethod(
                ACC_PUBLIC,
                "removeTrait",
                "(" + Type.getDescriptor(String.class) + ")" + Type.getDescriptor(Thing.class),
                "(" + Type.getDescriptor(String.class) + ")" + Type.getDescriptor(Thing.class),
                null);
        mv.visitCode();
        mv.visitVarInsn(ALOAD, 0);
        mv.visitMethodInsn(
            INVOKEVIRTUAL,
            BuildUtils.getInternalType(wrapperName),
            "getTraitMap",
            "()" + Type.getDescriptor(Map.class));
        mv.visitVarInsn(ALOAD, 1);
        mv.visitMethodInsn(
            INVOKEINTERFACE,
            Type.getInternalName(Map.class),
            "remove",
            "(" + Type.getDescriptor(Object.class) + ")" + Type.getDescriptor(Object.class));
        mv.visitTypeInsn(CHECKCAST, Type.getInternalName(Thing.class));
        mv.visitInsn(ARETURN);
        mv.visitMaxs(0, 0);
        mv.visitEnd();
      }
    }
    if (coreKlazz == null || needsMethod(coreKlazz, "getTraits")) {
      {
        mv =
            cw.visitMethod(
                ACC_PUBLIC,
                "getTraits",
                "()" + Type.getDescriptor(Collection.class),
                "()Ljava/util/Collection<Ljava/lang/String;>;",
                null);
        mv.visitCode();
        mv.visitVarInsn(ALOAD, 0);
        mv.visitMethodInsn(
            INVOKEVIRTUAL,
            BuildUtils.getInternalType(wrapperName),
            "getTraitMap",
            "()" + Type.getDescriptor(Map.class));
        mv.visitMethodInsn(
            INVOKEINTERFACE,
            Type.getInternalName(Map.class),
            "keySet",
            "()" + Type.getDescriptor(Set.class));
        mv.visitInsn(ARETURN);
        mv.visitMaxs(0, 0);
        mv.visitEnd();
      }
    }

    {
      mv =
          cw.visitMethod(
              ACC_PUBLIC,
              "writeExternal",
              "(" + Type.getDescriptor(ObjectOutput.class) + ")V",
              null,
              new String[] {Type.getInternalName(IOException.class)});
      mv.visitCode();

      mv.visitVarInsn(ALOAD, 1);
      mv.visitVarInsn(ALOAD, 0);
      mv.visitMethodInsn(
          INVOKEVIRTUAL,
          BuildUtils.getInternalType(wrapperName),
          "getCore",
          "()" + Type.getDescriptor(Object.class));
      mv.visitMethodInsn(
          INVOKEINTERFACE,
          Type.getInternalName(ObjectOutput.class),
          "writeObject",
          "(" + Type.getDescriptor(Object.class) + ")V");

      mv.visitVarInsn(ALOAD, 1);
      mv.visitVarInsn(ALOAD, 0);
      mv.visitFieldInsn(
          GETFIELD,
          BuildUtils.getInternalType(wrapperName),
          TraitableBean.MAP_FIELD_NAME,
          Type.getDescriptor(Map.class));
      mv.visitMethodInsn(
          INVOKEINTERFACE,
          Type.getInternalName(ObjectOutput.class),
          "writeObject",
          "(" + Type.getDescriptor(Object.class) + ")V");

      mv.visitVarInsn(ALOAD, 1);
      mv.visitVarInsn(ALOAD, 0);
      mv.visitFieldInsn(
          GETFIELD,
          BuildUtils.getInternalType(wrapperName),
          TraitableBean.TRAITSET_FIELD_NAME,
          Type.getDescriptor(Map.class));
      mv.visitMethodInsn(
          INVOKEINTERFACE,
          Type.getInternalName(ObjectOutput.class),
          "writeObject",
          "(" + Type.getDescriptor(Object.class) + ")V");

      mv.visitInsn(RETURN);
      mv.visitMaxs(0, 0);
      mv.visitEnd();
    }
    {
      mv =
          cw.visitMethod(
              ACC_PUBLIC,
              "readExternal",
              "(" + Type.getDescriptor(ObjectInput.class) + ")V",
              null,
              new String[] {
                Type.getInternalName(IOException.class),
                Type.getInternalName(ClassNotFoundException.class)
              });
      mv.visitCode();

      mv.visitVarInsn(ALOAD, 0);
      mv.visitVarInsn(ALOAD, 1);
      mv.visitMethodInsn(
          INVOKEINTERFACE,
          Type.getInternalName(ObjectInput.class),
          "readObject",
          "()" + Type.getDescriptor(Object.class));
      mv.visitTypeInsn(CHECKCAST, BuildUtils.getInternalType(coreName));
      mv.visitFieldInsn(
          PUTFIELD,
          BuildUtils.getInternalType(wrapperName),
          "core",
          BuildUtils.getTypeDescriptor(coreName));

      mv.visitVarInsn(ALOAD, 0);
      mv.visitVarInsn(ALOAD, 1);
      mv.visitMethodInsn(
          INVOKEINTERFACE,
          Type.getInternalName(ObjectInput.class),
          "readObject",
          "()" + Type.getDescriptor(Object.class));
      mv.visitTypeInsn(CHECKCAST, Type.getInternalName(Map.class));
      mv.visitFieldInsn(
          PUTFIELD,
          BuildUtils.getInternalType(wrapperName),
          TraitableBean.MAP_FIELD_NAME,
          Type.getDescriptor(Map.class));

      mv.visitVarInsn(ALOAD, 0);
      mv.visitVarInsn(ALOAD, 1);
      mv.visitMethodInsn(
          INVOKEINTERFACE,
          Type.getInternalName(ObjectInput.class),
          "readObject",
          "()" + Type.getDescriptor(Object.class));
      mv.visitTypeInsn(CHECKCAST, Type.getInternalName(Map.class));
      mv.visitFieldInsn(
          PUTFIELD,
          BuildUtils.getInternalType(wrapperName),
          TraitableBean.TRAITSET_FIELD_NAME,
          Type.getDescriptor(Map.class));

      mv.visitInsn(RETURN);
      mv.visitMaxs(0, 0);
      mv.visitEnd();
    }

    {
      mv =
          cw.visitMethod(
              ACC_PUBLIC, "init", "(" + BuildUtils.getTypeDescriptor(coreName) + ")V", null, null);
      mv.visitCode();
      mv.visitVarInsn(ALOAD, 0);
      mv.visitVarInsn(ALOAD, 1);
      mv.visitFieldInsn(
          PUTFIELD,
          BuildUtils.getInternalType(wrapperName),
          "core",
          BuildUtils.getTypeDescriptor(coreName));
      mv.visitInsn(RETURN);
      mv.visitMaxs(0, 0);
      mv.visitEnd();
    }

    Method[] ms = coreKlazz.getMethods();
    for (Method method : ms) {
      if (Modifier.isFinal(method.getModifiers())) {
        continue;
      }

      String signature = TraitFactory.buildSignature(method);
      {
        mv = cw.visitMethod(ACC_PUBLIC, method.getName(), signature, null, null);
        mv.visitCode();
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(
            GETFIELD,
            BuildUtils.getInternalType(wrapperName),
            "core",
            BuildUtils.getTypeDescriptor(coreName));
        int j = 1;
        for (Class arg : method.getParameterTypes()) {
          mv.visitVarInsn(BuildUtils.varType(arg.getName()), j++);
        }
        mv.visitMethodInsn(
            INVOKEVIRTUAL, BuildUtils.getInternalType(coreName), method.getName(), signature);

        mv.visitInsn(BuildUtils.returnType(method.getReturnType().getName()));
        int stack = TraitFactory.getStackSize(method);
        mv.visitMaxs(0, 0);
        mv.visitEnd();
      }
    }

    {
      mv =
          cw.visitMethod(
              ACC_PUBLIC + ACC_BRIDGE + ACC_SYNTHETIC,
              "init",
              "(" + Type.getDescriptor(Object.class) + ")V",
              null,
              null);
      mv.visitCode();
      mv.visitVarInsn(ALOAD, 0);
      mv.visitVarInsn(ALOAD, 1);
      mv.visitTypeInsn(CHECKCAST, BuildUtils.getInternalType(coreName));
      mv.visitMethodInsn(
          INVOKEVIRTUAL,
          BuildUtils.getInternalType(wrapperName),
          "init",
          "(" + BuildUtils.getTypeDescriptor(coreName) + ")V");
      mv.visitInsn(RETURN);
      mv.visitMaxs(0, 0);
      mv.visitEnd();
    }

    {
      mv =
          cw.visitMethod(
              ACC_PUBLIC,
              "denyTrait",
              "(" + Type.getDescriptor(Class.class) + ")V",
              null,
              new String[] {Type.getInternalName(LogicalTypeInconsistencyException.class)});
      mv.visitCode();
      mv.visitVarInsn(ALOAD, 0);
      mv.visitFieldInsn(
          GETFIELD,
          BuildUtils.getInternalType(wrapperName),
          TraitableBean.TRAITSET_FIELD_NAME,
          Type.getDescriptor(Map.class));
      mv.visitTypeInsn(CHECKCAST, Type.getInternalName(VetoableTypedMap.class));
      mv.visitVarInsn(ALOAD, 1);
      mv.visitMethodInsn(
          INVOKEVIRTUAL,
          Type.getInternalName(VetoableTypedMap.class),
          "addToVetoable",
          "(" + Type.getDescriptor(Class.class) + ")V");
      mv.visitInsn(RETURN);
      mv.visitMaxs(0, 0);
      mv.visitEnd();
    }
    {
      mv =
          cw.visitMethod(
              ACC_PUBLIC, "allowTrait", "(" + Type.getDescriptor(Class.class) + ")V", null, null);
      mv.visitCode();
      mv.visitVarInsn(ALOAD, 0);
      mv.visitFieldInsn(
          GETFIELD,
          BuildUtils.getInternalType(wrapperName),
          TraitableBean.TRAITSET_FIELD_NAME,
          Type.getDescriptor(Map.class));
      mv.visitTypeInsn(CHECKCAST, Type.getInternalName(VetoableTypedMap.class));
      mv.visitVarInsn(ALOAD, 1);
      mv.visitMethodInsn(
          INVOKEVIRTUAL,
          Type.getInternalName(VetoableTypedMap.class),
          "removeFromVetoable",
          "(" + Type.getDescriptor(Class.class) + ")V");
      mv.visitInsn(RETURN);
      mv.visitMaxs(0, 0);
      mv.visitEnd();
    }
    cw.visitEnd();

    return cw.toByteArray();
  }
  public byte[] buildClass(ClassDefinition core, ClassLoader classLoader)
      throws IOException, SecurityException, IllegalArgumentException, ClassNotFoundException,
          NoSuchMethodException, IllegalAccessException, InvocationTargetException,
          InstantiationException, NoSuchFieldException {

    FieldVisitor fv;
    MethodVisitor mv;

    // get the method bitmask
    BitSet mask = traitRegistry.getFieldMask(trait.getName(), core.getDefinedClass().getName());

    String name = TraitFactory.getPropertyWrapperName(trait, core);

    String internalWrapper = BuildUtils.getInternalType(name);
    String descrCore = Type.getDescriptor(core.getDefinedClass());
    String internalCore = Type.getInternalName(core.getDefinedClass());

    ClassWriter cw =
        createClassWriter(
            classLoader,
            ACC_PUBLIC + ACC_SUPER,
            internalWrapper,
            Type.getDescriptor(Object.class)
                + Type.getDescriptor(Map.class)
                + Type.getDescriptor(MapWrapper.class),
            //
            // "Ljava/lang/Object;Ljava/util/Map<Ljava/lang/String;Ljava/lang/Object;>;Lorg/drools/factmodel/traits/MapWrapper;",
            Type.getInternalName(Object.class),
            new String[] {
              Type.getInternalName(Map.class),
              Type.getInternalName(MapWrapper.class),
              Type.getInternalName(Serializable.class)
            });

    cw.visitInnerClass(
        Type.getInternalName(Map.Entry.class),
        Type.getInternalName(Map.class),
        "Entry",
        ACC_PUBLIC + ACC_STATIC + ACC_ABSTRACT + ACC_INTERFACE);

    {
      fv = cw.visitField(0, "object", descrCore, null, null);
      fv.visitEnd();
    }

    {
      fv =
          cw.visitField(
              0,
              "map",
              Type.getDescriptor(Map.class),
              "Ljava/util/Map<Ljava/lang/String;Ljava/lang/Object;>;",
              null);
      fv.visitEnd();
    }

    {
      mv =
          cw.visitMethod(
              ACC_PUBLIC,
              "<init>",
              "(" + descrCore + Type.getDescriptor(Map.class) + ")V",
              "(" + descrCore + "Ljava/util/Map<Ljava/lang/String;Ljava/lang/Object;>;)V",
              null);
      mv.visitCode();
      mv.visitVarInsn(ALOAD, 0);
      mv.visitMethodInsn(INVOKESPECIAL, Type.getInternalName(Object.class), "<init>", "()V");
      mv.visitVarInsn(ALOAD, 0);
      mv.visitVarInsn(ALOAD, 1);
      mv.visitFieldInsn(PUTFIELD, internalWrapper, "object", descrCore);
      mv.visitVarInsn(ALOAD, 0);
      mv.visitVarInsn(ALOAD, 2);
      mv.visitFieldInsn(PUTFIELD, internalWrapper, "map", Type.getDescriptor(Map.class));

      mv.visitVarInsn(ALOAD, 1);
      mv.visitVarInsn(ALOAD, 2);
      mv.visitMethodInsn(
          INVOKEVIRTUAL,
          internalCore,
          "_setDynamicProperties",
          "(" + Type.getDescriptor(Map.class) + ")V");

      initSoftFields(mv, trait, core, internalWrapper, mask, 2);

      mv.visitInsn(RETURN);
      mv.visitMaxs(0, 0);
      mv.visitEnd();
    }

    buildSize(cw, name, core.getClassName(), trait, core, mask);

    buildIsEmpty(cw, name, core.getClassName(), trait, core, mask);

    buildGet(cw, name, core.getClassName(), trait, core, mask);

    buildPut(cw, name, core.getClassName(), trait, core, mask);

    buildClear(cw, name, core.getClassName(), trait, core, mask);

    buildRemove(cw, name, core.getClassName(), trait, core, mask);

    buildContainsKey(cw, name, core.getClassName(), trait, core, mask);

    buildContainsValue(cw, name, core.getClassName(), trait, core, mask);

    buildKeyset(cw, name, core.getClassName(), trait, core, mask);

    buildValues(cw, name, core.getClassName(), trait, core, mask);

    buildEntryset(cw, name, core.getClassName(), trait, core, mask);

    buildCommonMethods(cw, name);

    cw.visitEnd();

    return cw.toByteArray();
  }