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 }