/**
  * Adds the mixin field to the target class.
  *
  * @param fieldInfo
  * @param deploymentModel
  * @param mixinDef
  */
 private void addMixinField(
     final MixinFieldInfo fieldInfo,
     final DeploymentModel deploymentModel,
     final MixinDefinition mixinDef) {
   final String signature = fieldInfo.mixinClassInfo.getSignature();
   int modifiers = 0;
   if (deploymentModel.equals(DeploymentModel.PER_CLASS)
       || deploymentModel.equals(DeploymentModel.PER_JVM)) {
     fieldInfo.isStatic = true;
     fieldInfo.isPerJVM = deploymentModel.equals(DeploymentModel.PER_JVM);
     modifiers = ACC_PRIVATE + ACC_FINAL + ACC_STATIC + ACC_SYNTHETIC;
   } else if (deploymentModel.equals(DeploymentModel.PER_INSTANCE)) {
     fieldInfo.isStatic = false;
     modifiers = ACC_PRIVATE + ACC_FINAL + ACC_SYNTHETIC;
   } else {
     throw new DefinitionException(
         "deployment model ["
             + mixinDef.getDeploymentModel()
             + "] for mixin ["
             + mixinDef.getMixinImpl().getName()
             + "] is not supported");
   }
   if (mixinDef.isTransient()) {
     modifiers += ACC_TRANSIENT;
   }
   cv.visitField(modifiers, fieldInfo.fieldName, signature, null, null);
   m_mixinFields.put(mixinDef.getMixinImpl(), fieldInfo);
 }
  /** Adds mixin fields and methods to the target class. */
  private void addMixinMembers() {
    int index = 0;
    for (Iterator it = m_ctx.getDefinitions().iterator(); it.hasNext(); ) {
      List mixinDefs = ((SystemDefinition) it.next()).getMixinDefinitions(m_expressionContext);

      // check for method clashes
      Set interfaceSet = new HashSet();
      for (Iterator it2 = mixinDefs.iterator(); it2.hasNext(); ) {
        interfaceSet.addAll(((MixinDefinition) it2.next()).getInterfaceClassNames());
      }
      // FIXME AVP refactor to handle precedence injection
      //            if (ClassInfoHelper.hasMethodClash(interfaceSet, m_ctx.getLoader())) {
      //                return;
      //            }

      for (Iterator it2 = mixinDefs.iterator(); it2.hasNext(); ) {
        final MixinDefinition mixinDef = (MixinDefinition) it2.next();
        final ClassInfo mixinImpl = mixinDef.getMixinImpl();
        final DeploymentModel deploymentModel = mixinDef.getDeploymentModel();

        if (m_mixinFields.containsKey(mixinImpl)) {
          continue;
        }
        final MixinFieldInfo fieldInfo = new MixinFieldInfo();
        fieldInfo.fieldName = MIXIN_FIELD_NAME + index;
        fieldInfo.mixinClassInfo = mixinImpl;

        addMixinField(fieldInfo, deploymentModel, mixinDef);
        addMixinMethods(fieldInfo, mixinDef);

        index++;
        m_isAdvised = true;
      }
    }
  }
  /**
   * Adds the mixin methods to the target class.
   *
   * @param fieldInfo
   * @param mixinDef
   */
  private void addMixinMethods(final MixinFieldInfo fieldInfo, final MixinDefinition mixinDef) {
    for (Iterator it3 = mixinDef.getMethodsToIntroduce().iterator(); it3.hasNext(); ) {
      MethodInfo methodInfo = (MethodInfo) it3.next();
      final String methodName = methodInfo.getName();
      final String methodSignature = methodInfo.getSignature();

      if (m_addedMethods.contains(
          AlreadyAddedMethodVisitor.getMethodKey(methodName, methodSignature))) {
        continue;
      }

      MethodVisitor mv =
          cv.visitMethod(ACC_PUBLIC + ACC_SYNTHETIC, methodName, methodSignature, null, null);
      if (fieldInfo.isStatic) {
        mv.visitFieldInsn(
            GETSTATIC,
            m_declaringTypeName,
            fieldInfo.fieldName,
            fieldInfo.mixinClassInfo.getSignature());
      } else {
        mv.visitVarInsn(ALOAD, 0);
        mv.visitFieldInsn(
            GETFIELD,
            m_declaringTypeName,
            fieldInfo.fieldName,
            fieldInfo.mixinClassInfo.getSignature());
      }
      AsmHelper.loadArgumentTypes(mv, Type.getArgumentTypes(methodSignature), false);
      mv.visitMethodInsn(
          INVOKEVIRTUAL,
          fieldInfo.mixinClassInfo.getName().replace('.', '/'),
          methodName,
          methodSignature);
      AsmHelper.addReturnStatement(mv, Type.getReturnType(methodSignature));
      mv.visitMaxs(0, 0);
    }
  }