1 /** 2 * Redistribution and use in source and binary forms, with or without 3 * modification, are permitted provided that the following conditions are 4 * met : 5 * 6 * . Redistributions of source code must retain the above copyright 7 * notice, this list of conditions and the following disclaimer. 8 * 9 * . Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * . The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 25 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 package cppncss.measure; 30 31 import java.util.ArrayList; 32 import java.util.List; 33 import java.util.TreeSet; 34 import cpptools.Options; 35 36 /** 37 * Collects measures. 38 * <p> 39 * The results are sorted according to the value of the first measure. 40 * <p> 41 * The different measures for a given item must be recorded one after another. 42 * 43 * @author Mathieu Champlon 44 */ 45 public final class MeasureCollector implements Collector 46 { 47 private final int threshold; 48 private final TreeSet<Measure> result = new TreeSet<Measure>(); 49 private final List<String> labels = new ArrayList<String>(); 50 private final MeasureObserver observer; 51 private String index; 52 private String filename; 53 54 /** 55 * Create a measure collector. 56 * 57 * @param options the options 58 * @param observer an observer to be notified of the results 59 */ 60 public MeasureCollector( final Options options, final MeasureObserver observer ) 61 { 62 if( observer == null ) 63 throw new IllegalArgumentException( "argument 'observer' is null" ); 64 this.threshold = getThreshold( options ); 65 this.observer = observer; 66 } 67 68 private int getThreshold( final Options options ) 69 { 70 if( !options.hasOption( "n" ) ) 71 return -1; 72 final List<String> thresholds = options.getOptionPropertyValues( "n" ); 73 if( thresholds.size() > 1 ) 74 throw new IllegalArgumentException( "invalid multiple -n arguments" ); 75 final int value = Integer.parseInt( thresholds.get( 0 ) ); 76 if( value < 0 ) 77 throw new IllegalArgumentException( "invalid negative -n argument" ); 78 return value; 79 } 80 81 /** 82 * {@inheritDoc} 83 */ 84 public void notify( final String label, final String item, final int line, final int count ) 85 { 86 if( !labels.contains( label ) ) 87 labels.add( label ); 88 if( index == null ) 89 index = label; 90 if( index.equals( label ) ) 91 insert( item, line, count ); 92 else 93 update( item, line, count ); 94 } 95 96 private void update( final String item, final int line, final int count ) 97 { 98 for( Measure measure : result ) 99 measure.update( item, filename, line, count ); 100 } 101 102 private void insert( final String item, final int line, final int count ) 103 { 104 result.add( new Measure( item, filename, line, count ) ); 105 if( threshold >= 0 && result.size() > threshold ) 106 result.remove( result.last() ); 107 } 108 109 /** 110 * {@inheritDoc} 111 */ 112 public void changed( final String filename ) 113 { 114 this.filename = filename; 115 } 116 117 /** 118 * {@inheritDoc} 119 */ 120 public void flush() 121 { 122 observer.notify( labels ); 123 for( Measure measure : result ) 124 measure.accept( observer ); 125 } 126 }