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: AbstractReportGenerator.java,v 1.1.1.1.2.4 2005/04/24 23:51:37 vlad_r Exp $
      8  */
      9 package com.vladium.emma.report;
     10 
     11 import java.util.Iterator;
     12 import java.util.Set;
     13 import java.util.TreeSet;
     14 
     15 import com.vladium.logging.Logger;
     16 import com.vladium.util.Descriptors;
     17 import com.vladium.util.IProperties;
     18 import com.vladium.util.IntIntMap;
     19 import com.vladium.util.IntVector;
     20 import com.vladium.util.ObjectIntMap;
     21 import com.vladium.emma.EMMARuntimeException;
     22 import com.vladium.emma.data.ClassDescriptor;
     23 import com.vladium.emma.data.ICoverageData;
     24 import com.vladium.emma.data.IMetaData;
     25 
     26 // ----------------------------------------------------------------------------
     27 /**
     28  * @author Vlad Roubtsov, (C) 2003
     29  */
     30 public
     31 abstract class AbstractReportGenerator extends AbstractItemVisitor
     32                                        implements IReportGenerator
     33 {
     34     // public: ................................................................
     35 
     36 
     37     public static IReportGenerator create (final String type)
     38     {
     39         if ((type == null) || (type.length () == 0))
     40             throw new IllegalArgumentException ("null/empty input: type");
     41 
     42         // TODO: proper pluggability pattern here
     43 
     44         if ("html".equals (type))
     45             return new com.vladium.emma.report.html.ReportGenerator ();
     46         else if ("lcov".equals (type))
     47             return new com.vladium.emma.report.lcov.ReportGenerator ();
     48         else if ("txt".equals (type))
     49             return new com.vladium.emma.report.txt.ReportGenerator ();
     50         else if ("xml".equals (type))
     51             return new com.vladium.emma.report.xml.ReportGenerator ();
     52         else // TODO: error code
     53             throw new EMMARuntimeException ("no report generator class found for type [" + type + "]");
     54     }
     55 
     56 
     57     public void initialize (final IMetaData mdata, final ICoverageData cdata,
     58                             final SourcePathCache cache, final IProperties properties)
     59         throws EMMARuntimeException
     60     {
     61         m_log = Logger.getLogger ();
     62         m_verbose = m_log.atVERBOSE ();
     63 
     64         m_settings = ReportProperties.parseProperties (properties, getType ());
     65 
     66         m_cache = cache;
     67 
     68         m_hasSrcFileInfo = mdata.hasSrcFileData ();
     69         m_hasLineNumberInfo = mdata.hasLineNumberData ();
     70 
     71         boolean debugInfoWarning = false;
     72         boolean bailOut = false;
     73 
     74         // src view is not possible if 'm_hasSrcFileInfo' is false:
     75         if (! mdata.hasSrcFileData () && (m_settings.getViewType () == IReportDataView.HIER_SRC_VIEW))
     76         {
     77             debugInfoWarning = true;
     78 
     79             m_log.warning ("not all instrumented classes were compiled with source file");
     80             m_log.warning ("debug data: no sources will be embedded in the report.");
     81 
     82             m_settings.setViewType (IReportDataView.HIER_CLS_VIEW);
     83         }
     84 
     85         // line coverage column must be removed if 'm_hasLineNumberInfo' is false:
     86         if (! m_hasLineNumberInfo)
     87         {
     88             final int [] userColumnIDs = m_settings.getColumnOrder ();
     89             final IntVector columnIDs = new IntVector ();
     90 
     91             boolean removed = false;
     92             for (int c = 0; c < userColumnIDs.length; ++ c)
     93             {
     94                 if (userColumnIDs [c] == IItemAttribute.ATTRIBUTE_LINE_COVERAGE_ID)
     95                     removed = true;
     96                 else
     97                     columnIDs.add (userColumnIDs [c]);
     98             }
     99 
    100             // at this point it is possible that there are no columns left: bail out
    101             if (removed)
    102             {
    103                 debugInfoWarning = true;
    104 
    105                 if (columnIDs.size () == 0)
    106                 {
    107                     m_log.warning ("line coverage requested in a report of type [" + getType () + "] but");
    108                     m_log.warning ("not all instrumented classes were compiled with line number");
    109                     m_log.warning ("debug data: since this was the only requested column, no report will be generated.");
    110 
    111                     bailOut = true;
    112                 }
    113                 else
    114                 {
    115                     m_log.warning ("line coverage requested in a report of type [" + getType () + "] but");
    116                     m_log.warning ("not all instrumented classes were compiled with line number");
    117                     m_log.warning ("debug data: this column will be removed from the report.");
    118 
    119                     m_settings.setColumnOrder (columnIDs.values ());
    120 
    121                     final int [] userSort = m_settings.getSortOrder ();
    122                     final IntVector sort = new IntVector ();
    123 
    124                     for (int c = 0; c < userSort.length; c += 2)
    125                     {
    126                         if (Math.abs (userSort [c]) != IItemAttribute.ATTRIBUTE_LINE_COVERAGE_ID)
    127                         {
    128                             sort.add (userSort [c]);
    129                             sort.add (userSort [c + 1]);
    130                         }
    131                     }
    132 
    133                     m_settings.setSortOrder (sort.values ());
    134                 }
    135             }
    136         }
    137         // note: no need to adjust m_metrics due to possible column removal above
    138 
    139         // SF FR 971176: provide user with sample classes that caused the above warnings
    140         if (debugInfoWarning && m_log.atINFO ())
    141         {
    142             final Set /* String */ sampleClassNames = new TreeSet ();
    143             final ObjectIntMap /* packageVMName:String -> count:int */ countMap = new ObjectIntMap ();
    144             final int [] _count = new int [1];
    145 
    146             for (Iterator /* ClassDescriptor */ descriptors = mdata.iterator (); descriptors.hasNext (); )
    147             {
    148                 final ClassDescriptor cls = (ClassDescriptor) descriptors.next ();
    149 
    150                 // SF BUG 979717: this check was incorrectly absent in the initial FR impl:
    151                 if (! cls.hasCompleteLineNumberInfo () || ! cls.hasSrcFileInfo ())
    152                 {
    153                     final String packageVMName = cls.getPackageVMName ();
    154                     final int count = countMap.get (packageVMName, _count)
    155                         ? _count [0]
    156                         : 0;
    157 
    158                     if (count < MAX_DEBUG_INFO_WARNING_COUNT)
    159                     {
    160                         sampleClassNames.add (Descriptors.vmNameToJavaName (cls.getClassVMName ()));
    161                         countMap.put (packageVMName, count + 1);
    162                     }
    163                 }
    164             }
    165 
    166             m_log.info ("showing up to " + MAX_DEBUG_INFO_WARNING_COUNT + " classes without full debug info per package:");
    167             for (Iterator /* String */ names = sampleClassNames.iterator (); names.hasNext (); )
    168             {
    169                 m_log.info ("  " + names.next ());
    170             }
    171         }
    172 
    173         if (bailOut)
    174         {
    175             // TODO: error code
    176             throw new EMMARuntimeException ("BAILED OUT");
    177         }
    178 
    179         final IItemMetadata [] allTypes = IItemMetadata.Factory.getAllTypes ();
    180         m_typeSortComparators = new ItemComparator [allTypes.length];
    181 
    182         for (int t = 0; t < allTypes.length; ++ t)
    183         {
    184             final IntVector orderedAttrIDsWithDir = new IntVector ();
    185             final long typeAttrIDSet = allTypes [t].getAttributeIDs ();
    186 
    187             for (int s = 0; s < m_settings.getSortOrder ().length; s += 2)
    188             {
    189                 final int attrID = m_settings.getSortOrder () [s];
    190 
    191                 if ((typeAttrIDSet & (1 << attrID)) != 0)
    192                 {
    193                     orderedAttrIDsWithDir.add (attrID);
    194 
    195                     final int dir = m_settings.getSortOrder () [s + 1];
    196                     orderedAttrIDsWithDir.add (dir);
    197                 }
    198             }
    199 
    200             m_typeSortComparators [t] = ItemComparator.Factory.create (orderedAttrIDsWithDir.values (), m_settings.getUnitsType ());
    201         }
    202 
    203         m_metrics = new int [allTypes.length];
    204         final IntIntMap metrics = m_settings.getMetrics ();
    205         for (int t = 0; t < m_metrics.length; ++ t)
    206         {
    207             m_metrics [t] = -1;
    208             metrics.get (t, m_metrics, t);
    209         }
    210 
    211         final IReportDataModel model = IReportDataModel.Factory.create (mdata, cdata);
    212         m_view = model.getView (m_settings.getViewType ());
    213 
    214         m_srcView = (m_settings.getViewType () == IReportDataView.HIER_SRC_VIEW);
    215     }
    216 
    217     public void cleanup ()
    218     {
    219         reset ();
    220     }
    221 
    222     // protected: .............................................................
    223 
    224 
    225     protected void reset ()
    226     {
    227         m_settings = null;
    228         m_cache = null;
    229         m_view = null;
    230         m_srcView = false;
    231 
    232         //m_typeSortIDs = null;
    233         m_typeSortComparators = null;
    234         m_metrics = null;
    235 
    236         m_log = null;
    237     }
    238 
    239 
    240     protected ReportProperties.ParsedProperties m_settings;
    241     protected SourcePathCache m_cache;
    242     protected IReportDataView m_view;
    243     protected boolean m_srcView;
    244 
    245     protected boolean m_hasSrcFileInfo, m_hasLineNumberInfo;
    246     protected ItemComparator [] m_typeSortComparators; // m_typeSortComparators [t] is a comparator representing the sort order for item type t
    247     protected int [] m_metrics; // -1 means no pass/fail check for this attribute
    248 
    249     protected Logger m_log; // every report generator is used on a single thread but the logger needs to be run()-scoped
    250     protected boolean m_verbose;
    251 
    252     // package: ...............................................................
    253 
    254     // private: ...............................................................
    255 
    256 
    257     private static final int MAX_DEBUG_INFO_WARNING_COUNT = 3; // per package
    258 
    259 } // end of class
    260 // ----------------------------------------------------------------------------
    261