All Downloads are FREE. Search and download functionalities are using the official Maven repository.

patterntesting.runtime.log.AbstractSequenceDiagramAspect.aj Maven / Gradle / Ivy

Go to download

PatternTesting Runtime (patterntesting-rt) is the runtime component for the PatternTesting framework. It provides the annotations and base classes for the PatternTesting testing framework (e.g. patterntesting-check, patterntesting-concurrent or patterntesting-exception) but can be also used standalone for classpath monitoring or profiling. It uses AOP and AspectJ to perform this feat.

There is a newer version: 2.4.0
Show newest version
/*
 * $Id: AbstractSequenceDiagramAspect.aj,v 1.19 2014/01/24 22:13:58 oboehm Exp $
 *
 * Copyright (c) 2013 by Oliver Boehm
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express orimplied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 * (c)reated 06.09.2013 by oliver ([email protected])
 */

package patterntesting.runtime.log;

import java.io.File;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.SuppressAjWarnings;
import org.slf4j.*;

import patterntesting.runtime.annotation.DrawSequenceDiagram;
import patterntesting.runtime.util.JoinPointHelper;

/**
 * This aspect provides the generation of sequence diagrams. To avaoid to
 * much details in the generated diagrams only the call of public methods
 * are logged.
 * 
 * @author oliver
 * @since 1.3.1 (06.09.2013)
 */
public abstract aspect AbstractSequenceDiagramAspect {
    
    private static Logger log = LoggerFactory.getLogger(AbstractSequenceDiagramAspect.class);
    private static SequenceGrapher grapher;
    private static List grapherList = new CopyOnWriteArrayList();
    
    static {
        grapherList.add(grapher);
    }
    
    /**
     * Start the painting of the diagram to file given by the annotation.
     *
     * @param diagramAnnotation the diagramAnnotation annotation with the file
     *        name
     */
    protected synchronized void startDiagram(final DrawSequenceDiagram diagramAnnotation) {
        File file = new File(diagramAnnotation.value());
        startDiagram(file);
        grapher.setExcludeFilter(diagramAnnotation.excluded());
    }

    /**
     * Start the painting of the diagram to the given file.
     *
     * @param file the file
     */
    private void startDiagram(File file) {
        grapher = new SequenceGrapher(file);
        grapherList.add(grapher);
        log.trace("Generation of sequence diagram to {} started.", file);
    }
    
    /**
     * If the executed joinpoint is not part of the logged diagram it will
     * be added to the diagramm.
     *
     * @param jp the execution joinpoint
     */
    protected void addToDiagram(final JoinPoint jp) {
        grapher.execute(jp);
    }
    
    /**
     * Close diagram.
     */
    protected synchronized void closeDiagram() {
        grapher.close();
        log.trace("Sequence diagram closed.");
        int n = grapherList.size();
        grapherList.remove(n - 1);
        grapher = grapherList.get(n - 2);
    }

    /**
     * Application code.
     */
    public abstract pointcut applicationCode();
    
    /**
     * We exclude here all classes of PatternTesting. Except those (test)
     * classes which are needed to test this aspect here.
     */
    @SuppressAjWarnings({"adviceDidNotMatch", "unmatchedSuperTypeInCall"})
    private pointcut intersection() :
        (applicationCode() && !within(patterntesting.runtime..*)) ||
        (applicationCode() && within(SequenceDiagramTest))
//        applicationCode()
//        && !within(*Recorder)
//        && !within(*Player)
//        && !within(AbstractLogger)
//        && !within(AbstractSequenceDiagramAspect)
//        && !within(SequenceGrapher)
//        && !within(SimpleLog)
//        && !within(Trace)
//        && !within(patterntesting.runtime.*)
//        && !within(patterntesting.runtime.d*..*)
//        && !within(patterntesting.runtime.e*..*)
//        && !within(patterntesting.runtime.i*..*)
//        && !within(patterntesting.runtime.j*..*)
//        && !within(patterntesting.runtime.m*..*)
//        && !within(patterntesting.runtime.n*..*)
//        && !within(patterntesting.runtime.u*..*)
        ;
        
    private pointcut callAllMethods() :
        call(public !static * *.*(..)) && !(call(public * java.lang.*.valueOf(*)));

    private pointcut callVoidMethods() :
        call(public !static void *.*(..));

    private pointcut callReturningMethods() :
        callAllMethods() && !callVoidMethods();
    
    private pointcut callConstructor() :
        call(*..*.new(..));// && !call(java..*.new(..));
    
    /**
     * Logs the creation of an object in the sequence diagram.
     */
    @SuppressAjWarnings({"adviceDidNotMatch"})
    Object around() : intersection() && callConstructor() {
        Object created = proceed();
        log.trace("--- <> ---> {}", created);
        grapher.createMessage(thisJoinPoint, created);
        return created;
    }

    /**
     * Logs a call in the sequence diagram.
     */
    @SuppressAjWarnings({"adviceDidNotMatch"})
    before() : intersection() && callAllMethods() {
        Object caller = thisJoinPoint.getThis();
        if (caller == null) {
            caller = JoinPointHelper.getCallerClass();
        }
        log.trace("{}: --- {} -->", caller, thisJoinPoint);
        grapher.message(caller, thisJoinPoint);
    }

    /**
     * Here we are back from the method call.
     */
    @SuppressAjWarnings({"adviceDidNotMatch"})
    after() : intersection() && callVoidMethods() {
        log.trace("<-----: {}", thisJoinPoint);
        grapher.returnMessage(thisJoinPoint);
    }

    /**
     * Here we are back from the method call and return a value.
     */
    @SuppressAjWarnings({"adviceDidNotMatch"})
    after() returning (Object ret): intersection() && callReturningMethods() {
        log.trace("<-- {} ---: {}", ret, thisJoinPoint);
        grapher.returnMessage(thisJoinPoint, ret);
    }

}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy