/**
  * Filters the classes to be transformed.
  *
  * @param definition the definition
  * @param classMetaData the meta-data for the class
  * @param cg the class to filter
  * @return boolean true if the method should be filtered away
  */
 private boolean classFilter(
     final AspectWerkzDefinition definition,
     final ClassMetaData classMetaData,
     final ClassGen cg) {
   if (cg.isInterface()
       || TransformationUtil.hasSuperClass(
           classMetaData, "org.codehaus.aspectwerkz.attribdef.aspect.Aspect")
       || TransformationUtil.hasSuperClass(
           classMetaData, "org.codehaus.aspectwerkz.xmldef.advice.AroundAdvice")
       || TransformationUtil.hasSuperClass(
           classMetaData, "org.codehaus.aspectwerkz.xmldef.advice.PreAdvice")
       || TransformationUtil.hasSuperClass(
           classMetaData, "org.codehaus.aspectwerkz.xmldef.advice.PostAdvice")) {
     return true;
   }
   String className = cg.getClassName();
   if (definition.inExcludePackage(className)) {
     return true;
   }
   if (!definition.inIncludePackage(className)) {
     return true;
   }
   if (definition.hasExecutionPointcut(classMetaData)
       || definition.hasThrowsPointcut(classMetaData)) {
     return false;
   }
   return true;
 }
 /**
  * Filters the methods to be transformed.
  *
  * @param definition the definition
  * @param classMetaData the class meta-data
  * @param method the method to filter
  * @return boolean
  */
 private boolean methodFilter(
     final AspectWerkzDefinition definition,
     final ClassMetaData classMetaData,
     final MethodMetaData methodMetaData,
     final Method method) {
   if (method.isAbstract()
       || method.isNative()
       || method.getName().equals("<init>")
       || method.getName().equals("<clinit>")
       || method.getName().startsWith(TransformationUtil.ORIGINAL_METHOD_PREFIX)
       || method.getName().equals(TransformationUtil.GET_META_DATA_METHOD)
       || method.getName().equals(TransformationUtil.SET_META_DATA_METHOD)
       || method.getName().equals(TransformationUtil.CLASS_LOOKUP_METHOD)
       || method.getName().equals(TransformationUtil.GET_UUID_METHOD)) {
     return true;
   } else if (definition.hasExecutionPointcut(classMetaData, methodMetaData)) {
     return false;
   } else if (definition.hasThrowsPointcut(classMetaData, methodMetaData)) {
     return false;
   } else {
     return true;
   }
 }
  /**
   * Makes the member method transformations.
   *
   * @param context the transformation context
   * @param klass the class set.
   */
  public void transformCode(final Context context, final Klass klass) {

    // loop over all the definitions
    for (Iterator it = m_definitions.iterator(); it.hasNext(); ) {
      AspectWerkzDefinition definition = (AspectWerkzDefinition) it.next();

      definition.loadAspects(context.getLoader());

      final ClassGen cg = klass.getClassGen();
      ClassMetaData classMetaData = BcelMetaDataMaker.createClassMetaData(context.getJavaClass(cg));

      if (classFilter(definition, classMetaData, cg)) {
        return;
      }

      final InstructionFactory factory = new InstructionFactory(cg);
      final ConstantPoolGen cpg = cg.getConstantPool();
      final Method[] methods = cg.getMethods();

      // get the indexes for the <init> methods
      List initIndexes = new ArrayList();
      for (int i = 0; i < methods.length; i++) {
        if (methods[i].getName().equals("<init>")) {
          initIndexes.add(new Integer(i));
        }
      }

      // build and sort the method lookup list
      final List methodLookupList = new ArrayList();
      for (int i = 0; i < methods.length; i++) {
        MethodMetaData methodMetaData = BcelMetaDataMaker.createMethodMetaData(methods[i]);
        if (methodFilter(definition, classMetaData, methodMetaData, methods[i])) {
          continue;
        }
        methodLookupList.add(methods[i]);
      }

      Collections.sort(methodLookupList, BCELMethodComparator.getInstance());

      final Map methodSequences = new HashMap();
      final List proxyMethods = new ArrayList();
      boolean isClassAdvised = false;
      for (int i = 0; i < methods.length; i++) {
        MethodMetaData methodMetaData = BcelMetaDataMaker.createMethodMetaData(methods[i]);
        // filter the methods
        if (methodFilter(definition, classMetaData, methodMetaData, methods[i])
            || methods[i].isStatic()) {
          continue;
        }

        isClassAdvised = true;
        final MethodGen mg = new MethodGen(methods[i], cg.getClassName(), cpg);

        // take care of identification of overloaded methods by inserting a sequence number
        if (methodSequences.containsKey(methods[i].getName())) {
          int sequence = ((Integer) methodSequences.get(methods[i].getName())).intValue();
          methodSequences.remove(methods[i].getName());
          sequence++;
          methodSequences.put(methods[i].getName(), new Integer(sequence));
        } else {
          methodSequences.put(methods[i].getName(), new Integer(1));
        }

        final int methodLookupId = methodLookupList.indexOf(methods[i]);
        final int methodSequence = ((Integer) methodSequences.get(methods[i].getName())).intValue();

        // handleCallToOverriddenSuperClassMethod(mg, cg, cpg, factory, methodSequence, context);

        addJoinPointField(cpg, cg, mg, methodSequence);

        // get the join point controller
        final String controllerClassName =
            definition.getJoinPointController(classMetaData, methodMetaData);

        // advise all the constructors
        for (Iterator it2 = initIndexes.iterator(); it2.hasNext(); ) {
          final int initIndex = ((Integer) it2.next()).intValue();

          methods[initIndex] =
              createJoinPointField(cpg, cg, methods[initIndex], methods[i], factory, methodSequence)
                  .getMethod();
        }

        proxyMethods.add(
            createProxyMethod(
                cpg,
                cg,
                mg,
                factory,
                methodLookupId,
                methodSequence,
                methods[i].getAccessFlags(),
                definition.getUuid(),
                controllerClassName));

        methods[i] = addPrefixToMethod(mg, methods[i], methodSequence, definition.getUuid());

        mg.setMaxStack();
      }

      if (isClassAdvised) {
        context.markAsAdvised();

        // update the old methods
        cg.setMethods(methods);

        // add the proxy methods
        for (Iterator it2 = proxyMethods.iterator(); it2.hasNext(); ) {
          cg.addMethod((Method) it2.next());
        }
      }
    }
  }