Home | History | Annotate | Download | only in report
      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: ClassItem.java,v 1.1.1.1.2.1 2004/06/20 20:07:22 vlad_r Exp $
      8  */
      9 package com.vladium.emma.report;
     10 
     11 import java.util.Iterator;
     12 
     13 import com.vladium.util.IntObjectMap;
     14 import com.vladium.util.asserts.$assert;
     15 import com.vladium.emma.data.ClassDescriptor;
     16 import com.vladium.emma.data.MethodDescriptor;
     17 
     18 // ----------------------------------------------------------------------------
     19 /**
     20  * @author Vlad Roubtsov, (C) 2003
     21  */
     22 public
     23 final class ClassItem extends Item
     24 {
     25     // public: ................................................................
     26 
     27     public ClassItem (final IItem parent, final ClassDescriptor cls, final boolean [][] coverage)
     28     {
     29         super (parent);
     30 
     31         m_cls = cls;
     32         m_coverage = coverage;
     33     }
     34 
     35     public String getName ()
     36     {
     37         return m_cls.getName ();
     38     }
     39 
     40     public String getSrcFileName ()
     41     {
     42         return m_cls.getSrcFileName ();
     43     }
     44 
     45     // TODO: SrcFileItem could benefit from this method for its own getFirstLine()
     46     public int getFirstLine ()
     47     {
     48         // TODO: state validation
     49 
     50         if (m_firstLine == 0)
     51         {
     52             final MethodDescriptor [] methods = m_cls.getMethods ();
     53 
     54             int firstLine = Integer.MAX_VALUE;
     55             for (int m = 0, mLimit = methods.length; m < mLimit; ++ m)
     56             {
     57                 final int mFirstLine = methods [m].getFirstLine ();
     58                 if ((mFirstLine > 0) && (mFirstLine < firstLine))
     59                     firstLine = mFirstLine;
     60             }
     61 
     62             m_firstLine = firstLine;
     63             return firstLine;
     64         }
     65 
     66         return m_firstLine;
     67     }
     68 
     69     public ClassDescriptor getClassDescriptor ()
     70     {
     71         return m_cls;
     72     }
     73 
     74     public boolean [][] getCoverage ()
     75     {
     76         return m_coverage;
     77     }
     78 
     79     public boolean loaded ()
     80     {
     81         return m_coverage != null;
     82     }
     83 
     84     public int getAggregate (final int type)
     85     {
     86         final int [] aggregates = m_aggregates;
     87 
     88         int value = aggregates [type];
     89 
     90         if (value < 0)
     91         {
     92             switch (type)
     93             {
     94                 case COVERAGE_CLASS_COUNT:
     95                 case    TOTAL_CLASS_COUNT:
     96                 {
     97                     aggregates [TOTAL_CLASS_COUNT] = 1;
     98                     aggregates [COVERAGE_CLASS_COUNT] = m_coverage != null ? 1 : 0;
     99 
    100                     return aggregates [type];
    101                 }
    102                 //break;
    103 
    104 
    105                 case COVERAGE_LINE_COUNT:
    106                 case    TOTAL_LINE_COUNT:
    107 
    108                 case COVERAGE_LINE_INSTR:
    109                 {
    110                     // line aggregate types are special when used on clsfile items:
    111                     // unlike all others, they do not simply add up when the line
    112                     // info is available; instead, lines from all methods belonging
    113                     // to the same clsfile parent are set-merged
    114 
    115                     final boolean [][] ccoverage = m_coverage; // this can be null
    116 
    117                     final IntObjectMap /* line -> int[2] */ cldata = new IntObjectMap ();
    118                     final MethodDescriptor [] methoddescs = m_cls.getMethods ();
    119 
    120                     for (Iterator methods = getChildren (); methods.hasNext (); )
    121                     {
    122                         final MethodItem method = (MethodItem) methods.next ();
    123                         final int methodID = method.getID ();
    124 
    125                         final boolean [] mcoverage = ccoverage == null ? null : ccoverage [methodID];
    126 
    127                         final MethodDescriptor methoddesc = methoddescs [methodID];
    128                         final int [] mbsizes = methoddesc.getBlockSizes ();
    129                         final IntObjectMap mlineMap = methoddesc.getLineMap ();
    130                         if ($assert.ENABLED) $assert.ASSERT (mlineMap != null);
    131 
    132 
    133                         final int [] mlines = mlineMap.keys ();
    134                         for (int ml = 0, mlLimit = mlines.length; ml < mlLimit; ++ ml)
    135                         {
    136                             final int mline = mlines [ml];
    137 
    138                             int [] data = (int []) cldata.get (mline);
    139                             if (data == null)
    140                             {
    141                                 data = new int [4]; // { totalcount, totalinstr, coveragecount, coverageinstr }
    142                                 cldata.put (mline, data);
    143                             }
    144 
    145                             final int [] lblocks = (int []) mlineMap.get (mline);
    146 
    147                             final int bCount = lblocks.length;
    148                             data [0] += bCount;
    149 
    150                             for (int bID = 0; bID < bCount; ++ bID)
    151                             {
    152                                 final int block = lblocks [bID];
    153 
    154                                 final boolean bcovered = mcoverage != null && mcoverage [block];
    155                                 final int instr = mbsizes [block];
    156 
    157                                 data [1] += instr;
    158                                 if (bcovered)
    159                                 {
    160                                     ++ data [2];
    161                                     data [3] += instr;
    162                                 }
    163                             }
    164                         }
    165                     }
    166 
    167                     aggregates [TOTAL_LINE_COUNT] = cldata.size ();
    168 
    169                     int coverageLineCount = 0;
    170                     int coverageLineInstr = 0;
    171 
    172                     final int [] clines = cldata.keys ();
    173                     for (int cl = 0, clLimit = clines.length; cl < clLimit; ++ cl)
    174                     {
    175                         final int cline = clines [cl];
    176                         final int [] data = (int []) cldata.get (cline);
    177 
    178                         final int ltotalCount = data [0];
    179                         final int ltotalInstr = data [1];
    180                         final int lcoverageCount = data [2];
    181                         final int lcoverageInstr = data [3];
    182 
    183                         if (lcoverageInstr > 0)
    184                         {
    185                             coverageLineCount += (PRECISION * lcoverageCount) / ltotalCount;
    186                             coverageLineInstr += (PRECISION * lcoverageInstr) / ltotalInstr;
    187                         }
    188                     }
    189 
    190                     aggregates [COVERAGE_LINE_COUNT] = coverageLineCount;
    191                     aggregates [COVERAGE_LINE_INSTR] = coverageLineInstr;
    192 
    193                     return aggregates [type];
    194                 }
    195                 //break;
    196 
    197 
    198                 default: return super.getAggregate (type);
    199             }
    200         }
    201 
    202         return value;
    203     }
    204 
    205     public void accept (final IItemVisitor visitor, final Object ctx)
    206     {
    207         visitor.visit (this, ctx);
    208     }
    209 
    210     public final IItemMetadata getMetadata ()
    211     {
    212         return METADATA;
    213     }
    214 
    215     public static IItemMetadata getTypeMetadata ()
    216     {
    217         return METADATA;
    218     }
    219 
    220     // protected: .............................................................
    221 
    222     // package: ...............................................................
    223 
    224 
    225     final ClassDescriptor m_cls;
    226     final boolean [][] m_coverage;
    227 
    228     // private: ...............................................................
    229 
    230 
    231     private int m_firstLine;
    232 
    233     private static final Item.ItemMetadata METADATA; // set in <clinit>
    234 
    235     static
    236     {
    237         METADATA = new Item.ItemMetadata (IItemMetadata.TYPE_ID_CLASS, "class",
    238             1 << IItemAttribute.ATTRIBUTE_NAME_ID |
    239             1 << IItemAttribute.ATTRIBUTE_CLASS_COVERAGE_ID |
    240             1 << IItemAttribute.ATTRIBUTE_METHOD_COVERAGE_ID |
    241             1 << IItemAttribute.ATTRIBUTE_BLOCK_COVERAGE_ID |
    242             1 << IItemAttribute.ATTRIBUTE_LINE_COVERAGE_ID);
    243     }
    244 
    245 } // end of class
    246 // ----------------------------------------------------------------------------