• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (C) 2003 Vladimir Roubtsov. All rights reserved.
2  *
3  * This program and the accompanying materials are made available under
4  * the terms of the Common Public License v1.0 which accompanies this distribution,
5  * and is available at http://www.eclipse.org/legal/cpl-v10.html
6  *
7  * $Id: IItemAttribute.java,v 1.1.1.1.2.1 2004/07/10 19:08:50 vlad_r Exp $
8  */
9 package com.vladium.emma.report;
10 
11 import java.text.DecimalFormat;
12 import java.text.FieldPosition;
13 import java.text.NumberFormat;
14 import java.util.Comparator;
15 
16 import com.vladium.util.asserts.$assert;
17 
18 // ----------------------------------------------------------------------------
19 /**
20  * @author Vlad Roubtsov, (C) 2003
21  */
22 public
23 interface IItemAttribute
24 {
25     // public: ................................................................
26 
27     // TODO: this modeling (units is an independent axis) is not ideal, because
28     // not all of the attributes have meaningful separation by unit type
29 
30     // note: the ordering is consistent with code in Factory:
31 
32     int ATTRIBUTE_NAME_ID               = 0;
33     int ATTRIBUTE_CLASS_COVERAGE_ID     = 1;
34     int ATTRIBUTE_METHOD_COVERAGE_ID    = 2;
35     int ATTRIBUTE_BLOCK_COVERAGE_ID     = 3;
36     int ATTRIBUTE_LINE_COVERAGE_ID      = 4;
37 
38     // note: the ordering is consistent with code in Factory and SrcFileItem:
39 
40     int UNITS_COUNT = 0;
41     int UNITS_INSTR = 1;
42 
comparator()43     Comparator /* IItem */ comparator ();
getName()44     String getName ();
format(IItem item, StringBuffer appendTo)45     void format (IItem item, StringBuffer appendTo);
passes(IItem item, int criterion)46     boolean passes (IItem item, int criterion); // ideally, criteria should come from a double-dispatched API
47 
48 
49     abstract class Factory
50     {
getAttribute(final int attributeID, final int unitsID)51         public static IItemAttribute getAttribute (final int attributeID, final int unitsID)
52         {
53             if ($assert.ENABLED) $assert.ASSERT (attributeID >= ATTRIBUTE_NAME_ID && attributeID <= ATTRIBUTE_LINE_COVERAGE_ID, "invalid attribute ID: " + attributeID);
54             if ($assert.ENABLED) $assert.ASSERT (unitsID >= UNITS_COUNT && unitsID <= UNITS_INSTR, "invalid units ID: " + unitsID);
55 
56             return ATTRIBUTES [unitsID][attributeID];
57         }
58 
getAttributes(final int unitsID)59         public static IItemAttribute [] getAttributes (final int unitsID)
60         {
61             if ($assert.ENABLED) $assert.ASSERT (unitsID >= UNITS_COUNT && unitsID <= UNITS_INSTR, "invalid units ID: " + unitsID);
62 
63             return (IItemAttribute []) ATTRIBUTES [unitsID].clone ();
64         }
65 
66         private static abstract class Attribute implements IItemAttribute
67         {
getName()68             public String getName ()
69             {
70                 return m_name;
71             }
72 
Attribute(final String name)73              protected Attribute (final String name)
74             {
75                 if (name == null) throw new IllegalArgumentException ("null input: name");
76 
77                 m_name = name;
78             }
79 
80 
81             private final String m_name;
82 
83         } // end of nested class
84 
85 
86         private static final class NameAttribute extends Attribute
87                                                  implements IItemAttribute
88         {
comparator()89             public Comparator comparator ()
90             {
91                 return m_comparator;
92             }
93 
format(final IItem item, final StringBuffer appendTo)94             public void format (final IItem item, final StringBuffer appendTo)
95             {
96                 appendTo.append (item.getName ());
97             }
98 
passes(final IItem item, final int criterion)99             public boolean passes (final IItem item, final int criterion)
100             {
101                 return true; // names always pass [for now]
102             }
103 
104 
105             private static final class NameComparator implements Comparator
106             {
compare(final Object l, final Object g)107                 public int compare (final Object l, final Object g)
108                 {
109                     final IItem il = (IItem) l;
110                     final IItem ig = (IItem) g;
111 
112                     return il.getName ().compareTo (ig.getName ());
113                 }
114 
115             } // end of nested class
116 
NameAttribute(final String name)117             NameAttribute (final String name)
118             {
119                 super (name);
120 
121                 m_comparator = new NameComparator ();
122             }
123 
124 
125             private final Comparator m_comparator;
126 
127         } // end of nested class
128 
129 
130         private static final class FractionAttribute extends Attribute
131                                                      implements IItemAttribute
132         {
comparator()133             public Comparator comparator ()
134             {
135                 return m_comparator;
136             }
137 
format(final IItem item, final StringBuffer appendTo)138             public void format (final IItem item, final StringBuffer appendTo)
139             {
140                 final int n = item.getAggregate (m_numeratorAggregateID);
141                 final double n_scaled = (double) n / m_scale;
142                 final int d = item.getAggregate (m_denominatorAggregateID);
143 
144                 // d can be 0 legally: the compiler can generate classes with no methods in them [happens with synthetic classes, for example]
145                 //if ($assert.ENABLED) $assert.ASSERT (d > 0, "[attr ID = " + m_denominatorAggregateID + "] invalid denominator: " + d);
146 
147                 final int appendToStart = appendTo.length ();
148 
149                 if (d == 0)
150                     m_format.format (1.0F, appendTo, m_fieldPosition);
151                 else
152                     m_format.format (n_scaled / d, appendTo, m_fieldPosition);
153 
154                 final int iLimit = Math.max (1, 5 - appendTo.length () + appendToStart);
155                 for (int i = 0; i < iLimit; ++ i) appendTo.append (' ');
156 
157                 appendTo.append ('(');
158                 m_nFormat.format (n_scaled, appendTo, m_fieldPosition);
159                 appendTo.append ('/');
160                 appendTo.append (d);
161                 appendTo.append (')');
162             }
163 
passes(final IItem item, final int criterion)164             public boolean passes (final IItem item, final int criterion)
165             {
166                 final int n = item.getAggregate (m_numeratorAggregateID);
167                 final int d = item.getAggregate (m_denominatorAggregateID);
168 
169                 return ((double) n) * IItem.PRECISION >=  ((double) d) * m_scale * criterion;
170             }
171 
172 
173             private final class FractionComparator implements Comparator
174             {
compare(final Object l, final Object g)175                 public int compare (final Object l, final Object g)
176                 {
177                     final IItem il = (IItem) l;
178                     final IItem ig = (IItem) g;
179 
180                     final double nil = il.getAggregate (m_numeratorAggregateID);
181                     final double dil = il.getAggregate (m_denominatorAggregateID);
182 
183                     final double nig = ig.getAggregate (m_numeratorAggregateID);
184                     final double dig = ig.getAggregate (m_denominatorAggregateID);
185 
186                     final double diff = nil * dig - nig * dil;
187 
188                     return diff > 0.0 ? +1 : (diff < 0.0 ? -1 : 0);
189                 }
190 
191             } // end of inner class
192 
193 
FractionAttribute(final String name, final int numeratorAggregateID, final int denominatorAggregateID, final int scale, final int nFractionDigits)194             FractionAttribute (final String name, final int numeratorAggregateID, final int denominatorAggregateID, final int scale, final int nFractionDigits)
195             {
196                 super (name);
197 
198                 if ($assert.ENABLED) $assert.ASSERT (scale != 0, "scale: " + scale);
199 
200                 m_numeratorAggregateID = numeratorAggregateID;
201                 m_denominatorAggregateID = denominatorAggregateID; // ok to be zero
202                 m_scale = scale;
203 
204                 m_format = (DecimalFormat) NumberFormat.getPercentInstance (); // TODO: locale
205                 m_fieldPosition = new FieldPosition (DecimalFormat.INTEGER_FIELD);
206 
207                 // TODO: set this from a pattern property
208                 //m_format.setMinimumFractionDigits (1);
209                 m_format.setMaximumFractionDigits (0);
210                 //m_format.setDecimalSeparatorAlwaysShown (false);
211 
212                 m_nFormat = (DecimalFormat) NumberFormat.getInstance (); // TODO: locale
213                 m_nFormat.setGroupingUsed (false);
214                 m_nFormat.setMaximumFractionDigits (nFractionDigits);
215 
216                 m_comparator = new FractionComparator ();
217             }
218 
219 
220             final int m_numeratorAggregateID, m_denominatorAggregateID;
221 
222             private final int m_scale;
223             private final DecimalFormat m_format, m_nFormat;
224             private final FieldPosition m_fieldPosition;
225             private final Comparator m_comparator;
226 
227         } // end of nested class
228 
229 
230 
Factory()231         private Factory () {}
232 
233         private static final IItemAttribute [/* unit */][/* attributes */] ATTRIBUTES; // set in <clinit>
234 
235         static
236         {
237             final IItemAttribute nameAttribute = new NameAttribute ("name");
238 
239             final IItemAttribute classCoverageAttribute = new FractionAttribute ("class, %", IItem.COVERAGE_CLASS_COUNT, IItem.TOTAL_CLASS_COUNT, 1, 0);
240             final IItemAttribute methodCoverageAttribute = new FractionAttribute ("method, %", IItem.COVERAGE_METHOD_COUNT, IItem.TOTAL_METHOD_COUNT, 1, 0);
241 
242             ATTRIBUTES = new IItemAttribute [][]
243             {
244                 /* count: */
245                 {
246                     nameAttribute,
247                     classCoverageAttribute,
248                     methodCoverageAttribute,
249                     new FractionAttribute ("block, %", IItem.COVERAGE_BLOCK_COUNT, IItem.TOTAL_BLOCK_COUNT, 1, 0),
250                     new FractionAttribute ("line, %", IItem.COVERAGE_LINE_COUNT, IItem.TOTAL_LINE_COUNT, IItem.PRECISION, 1),
251                 },
252                 /* instr: */
253                 {
254                     nameAttribute,
255                     classCoverageAttribute,
256                     methodCoverageAttribute,
257                     new FractionAttribute ("block, %", IItem.COVERAGE_BLOCK_INSTR, IItem.TOTAL_BLOCK_INSTR, 1, 0),
258                     new FractionAttribute ("line, %", IItem.COVERAGE_LINE_INSTR, IItem.TOTAL_LINE_COUNT, IItem.PRECISION, 1),
259                 },
260             };
261         }
262 
263     } // end of nested class
264 
265 } // end of interface
266 // ----------------------------------------------------------------------------