package org.automon.aspects;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.automon.monitors.NullImp;
import org.automon.monitors.OpenMon;

/**
 * aspectj compile time weaving using ajc
 *  cd /Users/stevesouza/gitrepo/testproject/playground/src/main/javastyle
 *  ajc -source 5 com/stevesouza/aspectj/*.javastyle
 *  javastyle com.stevesouza.aspectj.MessageCommunicator
 *
 * for nonaspectj version:
 *  javac com/stevesouza/aspectj/*.javastyle
 *
 */
@Aspect
public abstract class AutomonAspect  {

    private OpenMon openMon = new NullImp();
    protected  boolean enable = true;

    public boolean isEnabled() {
        return enable;
    }

    public void enable(boolean shouldEnable) {
        enable = shouldEnable;
    }



    @Around("monitor()")
    public Object monitorPerformance(ProceedingJoinPoint pjp) throws Throwable {
        // Note context is typically a Timer/Monitor object though to this advice it is simply
        // an object and the advice doesn't care what the intent of the context/object is.
        Object context = openMon.start(pjp);
        try {
            Object retVal = pjp.proceed();
            openMon.stop(context);
            return retVal;
        } catch (Throwable throwable) {
            openMon.stop(context, throwable);
            throw throwable;
        }
    }

    @AfterThrowing(pointcut = "exceptions()", throwing = "e")
    public void monitorExceptions(JoinPoint joinPoint, Throwable e) {
            System.out.println();
            System.out.println("Exception: "+e);
            System.out.println(" jp.getKind()=" + joinPoint.getKind());
            System.out.println(" jp.getStaticPart()="+joinPoint.getStaticPart());
            //Object[] argValues = joinPoint.getArgs();
            Signature signature = joinPoint.getSignature();
            //System.out.println(" jp.getSignature().getClass()="+signature.getClass());
            openMon.exception(e.getClass().getName()); // java.lang.RuntimeException

        // Note would have to look at all the special cases here.
            if (signature instanceof MethodSignature) {
                MethodSignature methodSignature =  (MethodSignature) signature;
                String[]argNames = methodSignature.getParameterNames();
                //for (int i = 0; i < argNames.length; i++) {
                //    printMe("  argName, argValue", argNames[i] + ", " + argValues[i]);
                //}
            }
    }


    public OpenMon getOpenMon() {
        return openMon;
    }

    public void setOpenMon(OpenMon openMon) {
        this.openMon = openMon;
    }

    @Pointcut("user_monitor() && sys_monitor()")
    public void monitor() {

    }

    @Pointcut()
    public abstract void sys_monitor();

    @Pointcut()
    public abstract void user_monitor();

    @Pointcut("user_exceptions() && sys_exceptions()")
    public void exceptions() {
    }

    @Pointcut()
    public abstract void sys_exceptions();

    @Pointcut()
    public abstract void user_exceptions();


}

@@ -454,306 +454,351 @@
 %0A * 
-a
+A
 spect
-j compile time weaving using ajc%0A *  cd /Users/stevesouza/gitrepo/testproject/playground/src/main/javastyle%0A *  ajc -source 5 com/stevesouza/aspectj/*.javastyle%0A *  javastyle com.stevesouza.aspectj.MessageCommunicator%0A *%0A * for nonaspectj version:
+ that advises the %7B@link org.aspectj.lang.annotation.Around%7D and %7B@link org.aspectj.lang.annotation.AfterThrowing%7D annotations.%0A * The appropriate methods on %7B@link org.automon.monitors.OpenMon%7D methods are called and they typically time methods and count any exceptions
 %0A * 
- javac com/stevesouza/aspectj/*.javasty
+thrown however other behavior such as logging is also possib
 le
+.
 %0A *%0A
@@ -1082,16 +1082,430 @@
     %7D%0A%0A%0A
+    /**%0A     * Advice that wraps the given pointcut and calls the appropriate %7B@link org.automon.monitors.OpenMon%7D method at the beginning and end%0A     * of the method call.%0A     *%0A     * @param pjp Information on the %7B@link org.aspectj.lang.JoinPoint%7D%0A     * @return The advised methods value or void.%0A     * @throws Throwable If the method throws a %7B@link java.lang.Throwable%7D the advice will rethrow it.%0A     */
 %0A    @Ar

refactor - comments