package lawOfDemeter; import java.util.*; import org.aspectj.lang.JoinPoint; /** * The StatMonitor aspect is part of a Law of Demeter Checker - a set of * classes and aspects that verify a given program does not violate * the Law of Demeter. This aspect monitors all of the checks made by the * Checker aspect, keeping track of various statistics. * * An interesting feature of this design is that this aspect uses pointcuts * defined in the checker aspect that describe methods in the checker aspect * which signal what type of check has been made. This is has many similarities * to an event throw -> catch implimentation, but the classes invloved do not * need to impliment the standard Java Interfaces that would normally be involved. * * @author Modifications made by Paul Freeman */ public aspect StatMonitor { // statistcs variables initialized before every main method execution private long totalChecks; private long numViolations; private Vector validChecks; /** * @return Returns the total number of checks made. */ public long getTotalChecked(){ return totalChecks; } /** * @return Returns the total number of violations found. */ public long getTotalViolations(){ return numViolations; } /** * @return Returns the number of valid checks as a Vector where:
* - position 0 = total valid checks
* - position i = total valid checks where i = num of matches perCheck
*/ public Vector getValidChecks(){ return validChecks; } // initialize statistical variables before(): Any.MainMethodExecution(){ totalChecks = 0; numViolations = 0; validChecks = new Vector(); validChecks.add(new Long(0)); // set the total valid counts = 0 } // increase the total count of checks before(): Any.ToCheck(){ totalChecks++; } // increase the violation count before(JoinPoint tjp): Checker.Violation(tjp){ numViolations++; } // increase the correct count before(JoinPoint tjp, Vector binsIn): Checker.Success(tjp, binsIn) { addToStats(binsIn.size()); } // Keeps track of the valid count statistics private void addToStats(int binCount){ //initialize count being increased if necessary try{ if(validChecks.elementAt(binCount) == null) validChecks.setElementAt(new Long(0), binCount); }catch(java.lang.ArrayIndexOutOfBoundsException e){ validChecks.setSize(binCount + 1); validChecks.setElementAt(new Long(0), binCount); } // increase counts Long val = new Long(((Long)validChecks.elementAt(0)).longValue() + 1); // total count validChecks.setElementAt(val, 0); val = new Long(((Long)validChecks.elementAt(binCount)).longValue() + 1); validChecks.setElementAt(val, binCount); } // prints statistics when program is done executing after(): Any.MainMethodExecution(){ long totalValid = ((Long)validChecks.elementAt(0)).longValue(); // produce headings System.out.println("\nStatistics:"); System.out.println("Type \t\tCount\t%Total\t%Valid"); System.out.println("Total Checks\t\t" + totalChecks); // produce violation statistics System.out.println("Violations \t\t" + numViolations + "\t"+ percent(numViolations, totalChecks, 2)); // produce valid percents long thisCount; for(int i = 0; i < validChecks.size(); i++){ String statement; if(i==0){statement = "Valid Checks";} else if(i==1){statement = "As "+i+" Supplier";} else{statement = "As "+i+" Suppliers";} if(validChecks.elementAt(i) == null){ thisCount = 0; }else{ thisCount = ((Long)validChecks.elementAt(i)).longValue(); } statement += "\t\t" + thisCount + "\t"+ percent(thisCount, totalChecks, 2); // add the % of valid stat if applicable if(i != 0){ statement += "\t" + percent(thisCount, totalValid, 2); } System.out.println(statement); } } // returns a double representing the percent of the numerator in the denominator private double percent(long noom, long denom, int numDec){ if(denom == 0){return 0;} return fix((double)noom/(double)denom * 100, numDec); } // fixes a double to a certain number of decimal places - does not round private double fix(double aDouble, int numDec){ try{ String d = new String(new Double(aDouble).toString()); int dotPos = d.indexOf('.'); int len = d.length(); int lastPos = dotPos + numDec + 1; if(lastPos > len){lastPos = len;} return new Double(d.substring(0, lastPos)).doubleValue(); }catch(java.lang.NumberFormatException e){ return 0; } } }