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: ReportCfg.java,v 1.1.1.1.2.1 2004/07/08 10:52:11 vlad_r Exp $
      8  */
      9 package com.vladium.emma.report;
     10 
     11 import java.util.ArrayList;
     12 import java.util.Iterator;
     13 import java.util.List;
     14 import java.util.Properties;
     15 
     16 import com.vladium.util.IConstants;
     17 import com.vladium.util.IProperties;
     18 import com.vladium.emma.EMMAProperties;
     19 import com.vladium.emma.ant.PropertyElement;
     20 import com.vladium.emma.ant.SuppressableTask;
     21 import com.vladium.emma.report.IReportEnums.DepthAttribute;
     22 import com.vladium.emma.report.IReportEnums.UnitsTypeAttribute;
     23 
     24 import org.apache.tools.ant.BuildException;
     25 import org.apache.tools.ant.Project;
     26 import org.apache.tools.ant.Task;
     27 import org.apache.tools.ant.types.Path;
     28 import org.apache.tools.ant.types.Reference;
     29 
     30 // ----------------------------------------------------------------------------
     31 /**
     32  * ReportCfg is a container for report type {@link ReportCfg.Element}s that are
     33  * in turn containers for all properties that could be set on a <report>
     34  * report type configurator (<txt>, <html>, etc). The elements provide
     35  * the ability for report properties to be set either via the generic <property>
     36  * nested elements or dedicated attributes. Potential conflicts between the same
     37  * conceptual property being set via an attribute and a nested element are resolved
     38  * by making dedicated attributes higher priority.<P>
     39  *
     40  * Note that ReportCfg does not handle any non-report related properties.
     41  * This can be done via {@link com.vladium.emma.ant.GenericCfg}. It is also the
     42  * parent's responsibility to merge any inherited report properties with
     43  * ReportCfg settings.
     44  *
     45  * @author Vlad Roubtsov, (C) 2003
     46  */
     47 public
     48 class ReportCfg implements IReportProperties
     49 {
     50     // public: ................................................................
     51 
     52 
     53     public static abstract class Element implements IReportEnums, IReportProperties
     54     {
     55         public void setUnits (final UnitsTypeAttribute units)
     56         {
     57             m_settings.setProperty (m_prefix.concat (UNITS_TYPE), units.getValue ());
     58         }
     59 
     60         public void setDepth (final DepthAttribute depth)
     61         {
     62             m_settings.setProperty (m_prefix.concat (DEPTH), depth.getValue ());
     63         }
     64 
     65         public void setColumns (final String columns)
     66         {
     67             m_settings.setProperty (m_prefix.concat (COLUMNS), columns);
     68         }
     69 
     70         public void setSort (final String sort)
     71         {
     72             m_settings.setProperty (m_prefix.concat (SORT), sort);
     73         }
     74 
     75         public void setMetrics (final String metrics)
     76         {
     77             m_settings.setProperty (m_prefix.concat (METRICS), metrics);
     78         }
     79 
     80         // not supported anymore:
     81 
     82 //        public void setOutdir (final File dir)
     83 //        {
     84 //            // TODO: does ANT resolve files relative to current JVM dir or ${basedir}?
     85 //            m_settings.setProperty (m_prefix.concat (OUT_DIR), dir.getAbsolutePath ());
     86 //        }
     87 
     88         public void setOutfile (final String fileName)
     89         {
     90             m_settings.setProperty (m_prefix.concat (OUT_FILE), fileName);
     91         }
     92 
     93         public void setEncoding (final String encoding)
     94         {
     95             m_settings.setProperty (m_prefix.concat (OUT_ENCODING), encoding);
     96         }
     97 
     98         // generic property element [don't doc this publicly]:
     99 
    100         public PropertyElement createProperty ()
    101         {
    102             // TODO: error out on conficting duplicate settings
    103 
    104             final PropertyElement property = new PropertyElement ();
    105             m_genericSettings.add (property);
    106 
    107             return property;
    108         }
    109 
    110         protected abstract String getType ();
    111 
    112 
    113         Element (final Task task, final IProperties settings)
    114         {
    115             if (task == null)
    116                 throw new IllegalArgumentException ("null input: task");
    117             if (settings == null)
    118                 throw new IllegalArgumentException ("null input: settings");
    119 
    120             m_task = task;
    121             m_settings = settings;
    122 
    123             m_prefix = PREFIX.concat (getType ()).concat (".");
    124 
    125             m_genericSettings = new ArrayList ();
    126         }
    127 
    128 
    129         void processGenericSettings ()
    130         {
    131             for (Iterator i = m_genericSettings.iterator (); i.hasNext (); )
    132             {
    133                 final PropertyElement property = (PropertyElement) i.next ();
    134 
    135                 final String name = property.getName ();
    136                 final String value = property.getValue () != null ? property.getValue () : "";
    137 
    138                 if (name != null)
    139                 {
    140                     final String prefixedName = m_prefix.concat (name);
    141 
    142                     // generically named settings don't override report named settings:
    143 
    144                     if (! m_settings.isOverridden (prefixedName))
    145                         m_settings.setProperty (prefixedName, value);
    146                 }
    147             }
    148         }
    149 
    150 
    151         protected final Task m_task; // never null
    152         protected final String m_prefix; // never null
    153         protected final IProperties m_settings; // never null
    154         protected final List /* PropertyElement */ m_genericSettings; // never null
    155 
    156     } // end of nested class
    157 
    158     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    159 
    160     public static class Element_HTML extends Element
    161     {
    162         protected final String getType ()
    163         {
    164             return TYPE;
    165         }
    166 
    167         Element_HTML (final Task task, final IProperties settings)
    168         {
    169             super (task, settings);
    170         }
    171 
    172 
    173         static final String TYPE = "html";
    174 
    175     } // end of nested class
    176 
    177     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    178 
    179     public static class Element_TXT extends Element
    180     {
    181         protected final String getType ()
    182         {
    183             return TYPE;
    184         }
    185 
    186         Element_TXT (final Task task, final IProperties settings)
    187         {
    188             super (task, settings);
    189         }
    190 
    191 
    192         static final String TYPE = "txt";
    193 
    194     } // end of nested class
    195 
    196     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    197 
    198     public static class Element_LCOV extends Element
    199     {
    200         protected final String getType ()
    201         {
    202             return TYPE;
    203         }
    204 
    205         Element_LCOV (final Task task, final IProperties settings)
    206         {
    207             super (task, settings);
    208         }
    209 
    210         static final String TYPE = "lcov";
    211 
    212     } // end of nested class
    213 
    214     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    215 
    216     public static class Element_XML extends Element
    217     {
    218         protected final String getType ()
    219         {
    220             return TYPE;
    221         }
    222 
    223         Element_XML (final Task task, final IProperties settings)
    224         {
    225             super (task, settings);
    226         }
    227 
    228 
    229         static final String TYPE = "xml";
    230 
    231     } // end of nested class
    232 
    233     // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    234 
    235 
    236     public ReportCfg (final Project project, final Task task)
    237     {
    238         m_project = project;
    239         m_task = task;
    240 
    241         m_reportTypes = new ArrayList (4);
    242         m_cfgList = new ArrayList (4);
    243         m_settings = EMMAProperties.wrap (new Properties ());
    244     }
    245 
    246     public Path getSourcepath ()
    247     {
    248         return m_srcpath;
    249     }
    250 
    251     public String [] getReportTypes ()
    252     {
    253         final BuildException failure = getFailure ();
    254 
    255         if (failure != null)
    256             throw failure;
    257         else
    258         {
    259             if (m_reportTypes.isEmpty ())
    260                 return IConstants.EMPTY_STRING_ARRAY;
    261             else
    262             {
    263                 final String [] result = new String [m_reportTypes.size ()];
    264                 m_reportTypes.toArray (result);
    265 
    266                 return result;
    267             }
    268         }
    269     }
    270 
    271     public IProperties getReportSettings ()
    272     {
    273         final BuildException failure = getFailure ();
    274 
    275         if (failure != null)
    276             throw failure;
    277         else
    278         {
    279             if (! m_processed)
    280             {
    281                 // collect all nested elements' generic settins into m_settings:
    282 
    283                 for (Iterator i = m_cfgList.iterator (); i.hasNext (); )
    284                 {
    285                     final Element cfg = (Element) i.next ();
    286                     cfg.processGenericSettings ();
    287                 }
    288 
    289                 m_processed = true;
    290             }
    291 
    292             return m_settings; // no clone
    293         }
    294     }
    295 
    296 
    297     // sourcepath attribute/element:
    298 
    299     public void setSourcepath (final Path path)
    300     {
    301         if (m_srcpath == null)
    302             m_srcpath = path;
    303         else
    304             m_srcpath.append (path);
    305     }
    306 
    307     public void setSourcepathRef (final Reference ref)
    308     {
    309         createSourcepath ().setRefid (ref);
    310     }
    311 
    312     public Path createSourcepath ()
    313     {
    314         if (m_srcpath == null)
    315             m_srcpath = new Path (m_project);
    316 
    317         return m_srcpath.createPath ();
    318     }
    319 
    320 
    321     // generator elements:
    322 
    323     public Element_TXT createTxt ()
    324     {
    325         return (Element_TXT) addCfgElement (Element_TXT.TYPE,
    326                                                      new Element_TXT (m_task, m_settings));
    327     }
    328 
    329     public Element_LCOV createLcov ()
    330     {
    331         return (Element_LCOV) addCfgElement (Element_LCOV.TYPE,
    332                                                      new Element_LCOV (m_task, m_settings));
    333     }
    334 
    335     public Element_HTML createHtml ()
    336     {
    337         return (Element_HTML) addCfgElement (Element_HTML.TYPE,
    338                                                       new Element_HTML (m_task, m_settings));
    339     }
    340 
    341     public Element_XML createXml ()
    342     {
    343         return (Element_XML) addCfgElement (Element_XML.TYPE,
    344                                                      new Element_XML (m_task, m_settings));
    345     }
    346 
    347 
    348     // report properties [defaults for all report types]:
    349 
    350     public void setUnits (final UnitsTypeAttribute units)
    351     {
    352         m_settings.setProperty (PREFIX.concat (UNITS_TYPE), units.getValue ());
    353     }
    354 
    355     public void setDepth (final DepthAttribute depth)
    356     {
    357         m_settings.setProperty (PREFIX.concat (DEPTH), depth.getValue ());
    358     }
    359 
    360     public void setColumns (final String columns)
    361     {
    362         m_settings.setProperty (PREFIX.concat (COLUMNS), columns);
    363     }
    364 
    365     public void setSort (final String sort)
    366     {
    367         m_settings.setProperty (PREFIX.concat (SORT), sort);
    368     }
    369 
    370     public void setMetrics (final String metrics)
    371     {
    372         m_settings.setProperty (PREFIX.concat (METRICS), metrics);
    373     }
    374 
    375     // not supported anymore:
    376 
    377 //    public void setOutdir (final File dir)
    378 //    {
    379 //        // TODO: does ANT resolve files relative to current JVM dir or ${basedir}?
    380 //        m_settings.setProperty (PREFIX.concat (OUT_DIR), dir.getAbsolutePath ());
    381 //    }
    382 //
    383 //    public void setDestdir (final File dir)
    384 //    {
    385 //        // TODO: does ANT resolve files relative to current JVM dir or ${basedir}?
    386 //        m_settings.setProperty (PREFIX.concat (OUT_DIR), dir.getAbsolutePath ());
    387 //    }
    388 
    389     public void setOutfile (final String fileName)
    390     {
    391         m_settings.setProperty (PREFIX.concat (OUT_FILE), fileName);
    392     }
    393 
    394     public void setEncoding (final String encoding)
    395     {
    396         m_settings.setProperty (PREFIX.concat (OUT_ENCODING), encoding);
    397     }
    398 
    399     // protected: .............................................................
    400 
    401 
    402     protected Element addCfgElement (final String type, final Element cfg)
    403     {
    404         if (m_reportTypes.contains (type))
    405         {
    406             setFailure ((BuildException) SuppressableTask.newBuildException (m_task.getTaskName ()
    407                 + ": duplicate configuration for report type [" + type + "]" ,
    408                 m_task.getLocation ()).fillInStackTrace ());
    409         }
    410         else
    411         {
    412             m_reportTypes.add (type);
    413             m_cfgList.add (cfg);
    414         }
    415 
    416         return cfg;
    417     }
    418 
    419     // package: ...............................................................
    420 
    421     // private: ...............................................................
    422 
    423 
    424     private void setFailure (final BuildException failure)
    425     {
    426         if (m_settingsFailure == null) m_settingsFailure = failure; // record the first one only
    427     }
    428 
    429     private BuildException getFailure ()
    430     {
    431         return m_settingsFailure;
    432     }
    433 
    434 
    435     private final Project m_project;
    436     private final Task m_task;
    437 
    438     private final List /* report type:String */ m_reportTypes; // using a list to keep the generation order same as configuration
    439     private final List /* Element */ m_cfgList;
    440     private final IProperties m_settings; // never null
    441 
    442     private Path m_srcpath;
    443 
    444     private transient BuildException m_settingsFailure; // can be null
    445     private transient boolean m_processed;
    446 
    447 } // end of class
    448 // ----------------------------------------------------------------------------
    449