Coverage Report - net.objectlab.qalab.parser.FileStats
 
Classes in this File Line Coverage Branch Coverage Complexity
FileStats
94%
102/108
100%
19/19
2.056
 
 1  
 ////////////////////////////////////////////////////////////////////////////////
 2  
 //
 3  
 //                  ObjectLab is sponsoring QALab
 4  
 // 
 5  
 // Based in London, we are world leaders in the design and development 
 6  
 // of bespoke applications for the Securities Financing markets.
 7  
 // 
 8  
 // <a href="http://www.objectlab.co.uk/open">Click here to learn more</a>
 9  
 //           ___  _     _           _   _          _
 10  
 //          / _ \| |__ (_) ___  ___| |_| |    __ _| |__
 11  
 //         | | | | '_ \| |/ _ \/ __| __| |   / _` | '_ \
 12  
 //         | |_| | |_) | |  __/ (__| |_| |__| (_| | |_) |
 13  
 //          \___/|_.__// |\___|\___|\__|_____\__,_|_.__/
 14  
 //                   |__/
 15  
 //
 16  
 //                   http://www.ObjectLab.co.uk
 17  
 // ---------------------------------------------------------------------------
 18  
 //
 19  
 //QALab is released under the GNU General Public License.
 20  
 //
 21  
 //QALab: Collects QA Statistics from your build over time.
 22  
 //2005+, ObjectLab Ltd
 23  
 //
 24  
 //This library is free software; you can redistribute it and/or
 25  
 //modify it under the terms of the GNU General Public
 26  
 //License as published by the Free Software Foundation; either
 27  
 //version 2.1 of the License, or (at your option) any later version.
 28  
 //
 29  
 //This library is distributed in the hope that it will be useful,
 30  
 //but WITHOUT ANY WARRANTY; without even the implied warranty of
 31  
 //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 32  
 //General Public License for more details.
 33  
 //
 34  
 //You should have received a copy of the GNU General Public
 35  
 //License along with this library; if not, write to the Free Software
 36  
 //Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 37  
 //
 38  
 ////////////////////////////////////////////////////////////////////////////////
 39  
 package net.objectlab.qalab.parser;
 40  
 
 41  
 import net.objectlab.qalab.util.QALabTags;
 42  
 
 43  
 import java.util.Calendar;
 44  
 import java.util.Date;
 45  
 import java.util.Iterator;
 46  
 import java.util.Map;
 47  
 import java.util.Set;
 48  
 import java.util.Stack;
 49  
 
 50  
 /**
 51  
  * As part of the up/down movers task, this class contains info about a given
 52  
  * file.
 53  
  * 
 54  
  * @author Paramjit Rehinsi
 55  
  * @version $Revision: 226 $
 56  
  */
 57  
 public class FileStats {
 58  
     private static final int ONE_DAY = 24;
 59  
 
 60  
     /** the date cut-off, do not include stats if before that date. */
 61  
     private Date startDateCutoff;
 62  
 
 63  
     /** the end date cut-off, do not include stats if after that date. */
 64  252
     private Date endDateCutoff = null;
 65  
 
 66  
     /** buffer for the UP statistics (increased number of violations). */
 67  252
     private StringBuffer upBuf = new StringBuffer();
 68  
 
 69  
     /** buffer for the DOWN statistics (decreased number of violations). */
 70  252
     private StringBuffer downBuf = new StringBuffer();
 71  
 
 72  
     /** file name (typically a .java file). */
 73  
     private String filename;
 74  
 
 75  
     /** path to file. */
 76  
     private String pathToFile;
 77  
 
 78  
     /** type surveyed (checkstyle|findbugs|simian|pmd). */
 79  
     private Map typesSurveyed;
 80  
     
 81  
     /** offset in hours to determine if the stat has fallen to 0 over the last n hours
 82  
      * from the endDateCutoff.
 83  
      */
 84  252
     private int offsetForLastRun = ONE_DAY;
 85  
 
 86  
     /**
 87  
      * @param types
 88  
      *            the types surveyed.
 89  
      * @param fileSurveyed
 90  
      *            the file name surveyed.
 91  
      * @param cutoff
 92  
      *            earliest date to take into account.
 93  
      */
 94  252
     public FileStats(final Map types, final String fileSurveyed, final String pathToFile, final Date cutoff) {
 95  252
         this.typesSurveyed = types;
 96  252
         this.filename = fileSurveyed;
 97  252
         this.pathToFile = pathToFile;
 98  252
         this.startDateCutoff = new Date(cutoff.getTime());
 99  252
     }
 100  
 
 101  
     /**
 102  
      * @return Return filename of this object.
 103  
      */
 104  
     public final String getFileName() {
 105  114
         return filename;
 106  
     }
 107  
 
 108  
     /**
 109  
      * @return Return the XML entry for UP movers (increased violations).
 110  
      */
 111  
     public final String getUpXmlResult() {
 112  252
         return upBuf.toString();
 113  
     }
 114  
 
 115  
     /**
 116  
      * @return Return the XML entry for DOWN movers (decreased violations).
 117  
      */
 118  
     public final String getDownXmlResult() {
 119  252
         return downBuf.toString();
 120  
     }
 121  
 
 122  
     /**
 123  
      * Construct the XML buffers.
 124  
      */
 125  
     public final void constructXML() {
 126  252
         Set keys = (Set) typesSurveyed.keySet();
 127  252
         Iterator i = keys.iterator();
 128  
 
 129  543
         while (i.hasNext()) {
 130  291
             Stack s = (Stack) typesSurveyed.get((String) i.next());
 131  
 
 132  291
             processFilesResultBeans(s);
 133  291
         }
 134  
 
 135  252
         if (upBuf.length() > 0) {
 136  60
             upBuf.insert(0, "  <file name=\"" + getFileName() + "\" path=\"" + getPathToFile() + "\">" + QALabTags.LINE_END);
 137  60
             upBuf.append("  </file>").append(QALabTags.LINE_END);
 138  
         }
 139  
 
 140  252
         if (downBuf.length() > 0) {
 141  54
             downBuf.insert(0, "  <file name=\"" + getFileName() + "\" path=\"" + getPathToFile() + "\">" + QALabTags.LINE_END);
 142  54
             downBuf.append("  </file>").append(QALabTags.LINE_END);
 143  
         }
 144  252
     }
 145  
 
 146  
     /**
 147  
      * Build the XML string depending on whether differences have occured since
 148  
      * the cutoff.
 149  
      * 
 150  
      * @param stack
 151  
      *            each result set in a stack from cutoff.
 152  
      */
 153  
     private void processFilesResultBeans(final Stack stack) {
 154  291
         if (stack.empty()) {
 155  147
             return;
 156  
         }
 157  
 
 158  
         // get a result from stack.
 159  144
         SingleStat currentResult = (SingleStat) stack.pop();
 160  
 
 161  144
         Iterator it = stack.iterator();
 162  
 //        boolean onlyOneResult = !it.hasNext();
 163  
 
 164  
         // set the date of the result.
 165  144
         Calendar currentday = Calendar.getInstance();
 166  144
         currentday.setTime(getEndDateCutoff());
 167  144
         currentday.add(Calendar.HOUR, -offsetForLastRun);
 168  
 
 169  
         // new result -> gone UP!
 170  
         // BUT only if the result is not BEFORE 1 day from the end result
 171  
         // (otherwise we assume that the has been another run which reduced it
 172  
         // to 0, therefore it would not have gone up.
 173  
 //        if (onlyOneResult && fallInWindow(currentResult)
 174  
         /** && !currentResult.getDate().before(currentday.getTime()) */
 175  
 //        ) {
 176  
 //            appendStats(upBuf, null, currentResult);
 177  
 //        }
 178  
 
 179  
         // if the result set is after the cutoff and less than end-1 then
 180  
         // it means that we do NOT have a result for this guy on end
 181  144
         if (/*onlyOneResult && */!currentResult.getDate().before(startDateCutoff)
 182  
                 && currentResult.getDate().before(currentday.getTime())) {
 183  30
             appendStats(downBuf, currentResult, null);
 184  
         }
 185  
 
 186  144
         checkPreviousResults(stack, currentResult, it);
 187  144
     }
 188  
 
 189  
     /**
 190  
      * @param stack
 191  
      * @param currentResult
 192  
      * @param it
 193  
      */
 194  
     private void checkPreviousResults(final Stack stack, SingleStat currentResult, Iterator it) {
 195  
         SingleStat previousResult;
 196  144
         Calendar oneDayBeforeEndCutoff = Calendar.getInstance();
 197  144
         oneDayBeforeEndCutoff.setTime(endDateCutoff);
 198  144
         oneDayBeforeEndCutoff.add(Calendar.HOUR, -offsetForLastRun);
 199  
 
 200  
         // iterate through the previous results.
 201  624
         while (it.hasNext()) {
 202  480
             previousResult = (SingleStat) stack.pop();
 203  
 
 204  480
             int previousCount = previousResult.getStatValue();
 205  480
             final int currentCount = currentResult.getStatValue();
 206  
 
 207  
             // if (previousResult.getDate().before(startDateCutoff)) {
 208  
             // previousCount = 0; // assume 0.
 209  
             // }
 210  
 
 211  480
             final int diff = currentCount - previousCount;
 212  
 
 213  480
             if (diff > 0) {
 214  36
                 handleUp(currentResult, previousResult);
 215  36
             } else if (diff < 0) {
 216  48
                 handleDown(currentResult, previousResult);
 217  48
             } else if (diff == 0 && fallInWindow(currentResult)
 218  
                     && !currentResult.getDate().before(oneDayBeforeEndCutoff.getTime())
 219  
                     && !previousResult.getDate().after(startDateCutoff)) {
 220  
                 // this is the case where we may have had the same number of
 221  
                 // violation outside the window in the past but this should
 222  
                 // count as a NEW violation as it has come back.
 223  0
                 appendStats(upBuf, null, currentResult);
 224  
             }
 225  
 
 226  480
             currentResult = previousResult;
 227  480
         }
 228  
         // if the last resul (earliest) falls in the window, we can assume that
 229  
         // it should be part of the UP category. 
 230  144
         if (fallInWindow(currentResult)) {
 231  66
             appendStats(upBuf, null, currentResult);
 232  
         }
 233  144
     }
 234  
 
 235  
     /**
 236  
      * @param currentResult
 237  
      * @param previousResult
 238  
      */
 239  
     private void handleDown(SingleStat currentResult, SingleStat previousResult) {
 240  48
         if (fallInWindow(currentResult)) {
 241  
             // there are LESS violations this time round.
 242  33
             appendStats(downBuf, previousResult, currentResult);
 243  
         }
 244  48
     }
 245  
 
 246  
     /**
 247  
      * @param currentResult
 248  
      * @param previousResult
 249  
      */
 250  
     private void handleUp(SingleStat currentResult, SingleStat previousResult) {
 251  36
         if (fallInWindow(currentResult)) {
 252  
             // there are MORE violations this time round.
 253  30
             appendStats(upBuf, previousResult, currentResult);
 254  
         }
 255  
 
 256  36
     }
 257  
 
 258  
     /**
 259  
      * return true if the stat falls in the time window.
 260  
      * 
 261  
      * @param stat
 262  
      * @return
 263  
      */
 264  
     private boolean fallInWindow(SingleStat stat) {
 265  624
         return !stat.getDate().before(startDateCutoff) && !stat.getDate().after(endDateCutoff);
 266  
     }
 267  
 
 268  
     /**
 269  
      * Append statistics to up or down buffer.
 270  
      * 
 271  
      * @param buffer
 272  
      *            the up or down buffer
 273  
      * @param previousResult
 274  
      *            can be null (ie 0)
 275  
      * @param currentResult
 276  
      *            can be null (ie 0)
 277  
      */
 278  
     private void appendStats(final StringBuffer buffer, final SingleStat previousResult, final SingleStat currentResult) {
 279  159
         int previousCount = 0;
 280  
 
 281  159
         if (previousResult != null) {
 282  93
             previousCount = previousResult.getStatValue();
 283  
         }
 284  
 
 285  159
         int currentCount = 0;
 286  
 
 287  159
         if (currentResult != null) {
 288  129
             currentCount = currentResult.getStatValue();
 289  
         }
 290  
 
 291  159
         int diff = currentCount - previousCount;
 292  
 
 293  159
         if (diff != 0) {
 294  159
             buffer.append("   <diff previousrun=\"");
 295  
     
 296  159
             if (previousResult != null) {
 297  93
                 writeDate(buffer, previousResult);
 298  93
             } else {
 299  66
                 buffer.append("-");
 300  
             }
 301  
     
 302  159
             buffer.append("\" currentrun=\"");
 303  
     
 304  159
             if (currentResult != null) {
 305  129
                 writeDate(buffer, currentResult);
 306  129
                 buffer.append("\" type=\"").append(currentResult.getType());
 307  129
             } else {
 308  30
                 buffer.append("-");
 309  30
                 buffer.append("\" type=\"").append(previousResult.getType());
 310  
             }
 311  
     
 312  159
             buffer.append("\" previouserrors=\"");
 313  
     
 314  159
             buffer.append(previousCount);
 315  159
             buffer.append("\" currenterrors=\"");
 316  159
             buffer.append(currentCount);
 317  159
             buffer.append("\" diff=\"");
 318  159
             buffer.append(diff);
 319  159
             buffer.append("\"/>").append(QALabTags.LINE_END);
 320  
         }
 321  159
     }
 322  
 
 323  
     /**
 324  
      * @param buffer
 325  
      * @param currentResult
 326  
      */
 327  
     private void writeDate(final StringBuffer buffer, final SingleStat currentResult) {
 328  222
         Date date = currentResult.getDate();
 329  222
         Calendar cal = Calendar.getInstance();
 330  222
         cal.setTime(date);
 331  
 
 332  222
         if (0 == cal.get(Calendar.SECOND) && 0 == cal.get(Calendar.MINUTE) && 0 == cal.get(Calendar.HOUR)) {
 333  0
             buffer.append(QALabTags.DEFAULT_DATE_FORMAT.format(currentResult.getDate()));
 334  0
         } else {
 335  222
             buffer.append(QALabTags.DEFAULT_DATETIME_FORMAT.format(currentResult.getDate()));
 336  
         }
 337  222
     }
 338  
 
 339  
     /**
 340  
      * @param endDate
 341  
      *            The endDateCutoff to set.
 342  
      */
 343  
     public final void setEndDateCutoff(final Date endDate) {
 344  252
         this.endDateCutoff = new Date(endDate.getTime());
 345  252
     }
 346  
 
 347  
     /**
 348  
      * @return Returns the endDateCutoff.
 349  
      */
 350  
     public final Date getEndDateCutoff() {
 351  144
         return new Date(endDateCutoff.getTime());
 352  
     }
 353  
 
 354  
     /**
 355  
      * @return Returns the pathToFile.
 356  
      */
 357  
     public final String getPathToFile() {
 358  114
         return pathToFile;
 359  
     }
 360  
 
 361  
     /**
 362  
      * @param pathToFile
 363  
      *            The pathToFile to set.
 364  
      */
 365  
     public final void setPathToFile(String pathToFile) {
 366  0
         this.pathToFile = pathToFile;
 367  0
     }
 368  
 
 369  
     public int getOffsetForLastRun() {
 370  0
         return offsetForLastRun;
 371  
     }
 372  
 
 373  
     public void setOffsetForLastRun(int offsetForLastRun) {
 374  252
         this.offsetForLastRun = offsetForLastRun;
 375  252
     }
 376  
 }
 377  
 /*
 378  
  *                   ObjectLab is sponsoring QALab
 379  
  * 
 380  
  * Based in London, we are world leaders in the design and development 
 381  
  * of bespoke applications for the securities financing markets.
 382  
  * 
 383  
  * <a href="http://www.objectlab.co.uk/open">Click here to learn more about us</a>
 384  
  *           ___  _     _           _   _          _
 385  
  *          / _ \| |__ (_) ___  ___| |_| |    __ _| |__
 386  
  *         | | | | '_ \| |/ _ \/ __| __| |   / _` | '_ \
 387  
  *         | |_| | |_) | |  __/ (__| |_| |__| (_| | |_) |
 388  
  *          \___/|_.__// |\___|\___|\__|_____\__,_|_.__/
 389  
  *                   |__/
 390  
  *
 391  
  *                     www.ObjectLab.co.uk
 392  
  */