• 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: 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     {
setUnits(final UnitsTypeAttribute units)55         public void setUnits (final UnitsTypeAttribute units)
56         {
57             m_settings.setProperty (m_prefix.concat (UNITS_TYPE), units.getValue ());
58         }
59 
setDepth(final DepthAttribute depth)60         public void setDepth (final DepthAttribute depth)
61         {
62             m_settings.setProperty (m_prefix.concat (DEPTH), depth.getValue ());
63         }
64 
setColumns(final String columns)65         public void setColumns (final String columns)
66         {
67             m_settings.setProperty (m_prefix.concat (COLUMNS), columns);
68         }
69 
setSort(final String sort)70         public void setSort (final String sort)
71         {
72             m_settings.setProperty (m_prefix.concat (SORT), sort);
73         }
74 
setMetrics(final String metrics)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 
setOutfile(final String fileName)88         public void setOutfile (final String fileName)
89         {
90             m_settings.setProperty (m_prefix.concat (OUT_FILE), fileName);
91         }
92 
setEncoding(final String encoding)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 
createProperty()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 
getType()110         protected abstract String getType ();
111 
112 
Element(final Task task, final IProperties settings)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 
processGenericSettings()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     {
getType()162         protected final String getType ()
163         {
164             return TYPE;
165         }
166 
Element_HTML(final Task task, final IProperties settings)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     {
getType()181         protected final String getType ()
182         {
183             return TYPE;
184         }
185 
Element_TXT(final Task task, final IProperties settings)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     {
getType()200         protected final String getType ()
201         {
202             return TYPE;
203         }
204 
Element_LCOV(final Task task, final IProperties settings)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     {
getType()218         protected final String getType ()
219         {
220             return TYPE;
221         }
222 
Element_XML(final Task task, final IProperties settings)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 
ReportCfg(final Project project, final Task task)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 
getSourcepath()246     public Path getSourcepath ()
247     {
248         return m_srcpath;
249     }
250 
getReportTypes()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 
getReportSettings()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 
setSourcepath(final Path path)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 
setSourcepathRef(final Reference ref)307     public void setSourcepathRef (final Reference ref)
308     {
309         createSourcepath ().setRefid (ref);
310     }
311 
createSourcepath()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 
createTxt()323     public Element_TXT createTxt ()
324     {
325         return (Element_TXT) addCfgElement (Element_TXT.TYPE,
326                                                      new Element_TXT (m_task, m_settings));
327     }
328 
createLcov()329     public Element_LCOV createLcov ()
330     {
331         return (Element_LCOV) addCfgElement (Element_LCOV.TYPE,
332                                                      new Element_LCOV (m_task, m_settings));
333     }
334 
createHtml()335     public Element_HTML createHtml ()
336     {
337         return (Element_HTML) addCfgElement (Element_HTML.TYPE,
338                                                       new Element_HTML (m_task, m_settings));
339     }
340 
createXml()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 
setUnits(final UnitsTypeAttribute units)350     public void setUnits (final UnitsTypeAttribute units)
351     {
352         m_settings.setProperty (PREFIX.concat (UNITS_TYPE), units.getValue ());
353     }
354 
setDepth(final DepthAttribute depth)355     public void setDepth (final DepthAttribute depth)
356     {
357         m_settings.setProperty (PREFIX.concat (DEPTH), depth.getValue ());
358     }
359 
setColumns(final String columns)360     public void setColumns (final String columns)
361     {
362         m_settings.setProperty (PREFIX.concat (COLUMNS), columns);
363     }
364 
setSort(final String sort)365     public void setSort (final String sort)
366     {
367         m_settings.setProperty (PREFIX.concat (SORT), sort);
368     }
369 
setMetrics(final String metrics)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 
setOutfile(final String fileName)389     public void setOutfile (final String fileName)
390     {
391         m_settings.setProperty (PREFIX.concat (OUT_FILE), fileName);
392     }
393 
setEncoding(final String encoding)394     public void setEncoding (final String encoding)
395     {
396         m_settings.setProperty (PREFIX.concat (OUT_ENCODING), encoding);
397     }
398 
399     // protected: .............................................................
400 
401 
addCfgElement(final String type, final Element cfg)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 
setFailure(final BuildException failure)424     private void setFailure (final BuildException failure)
425     {
426         if (m_settingsFailure == null) m_settingsFailure = failure; // record the first one only
427     }
428 
getFailure()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