blob: 2d8b73f2b69d966e51c6cf380e5e04ccd59ec341 [file] [log] [blame]
/* Copyright (C) 2003 Vladimir Roubtsov. All rights reserved.
*
* This program and the accompanying materials are made available under
* the terms of the Common Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/cpl-v10.html
*
* $Id: ReportCfg.java,v 1.1.1.1.2.1 2004/07/08 10:52:11 vlad_r Exp $
*/
package com.vladium.emma.report;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import com.vladium.util.IConstants;
import com.vladium.util.IProperties;
import com.vladium.emma.EMMAProperties;
import com.vladium.emma.ant.PropertyElement;
import com.vladium.emma.ant.SuppressableTask;
import com.vladium.emma.report.IReportEnums.DepthAttribute;
import com.vladium.emma.report.IReportEnums.UnitsTypeAttribute;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.types.Reference;
// ----------------------------------------------------------------------------
/**
* ReportCfg is a container for report type {@link ReportCfg.Element}s that are
* in turn containers for all properties that could be set on a <report>
* report type configurator (<txt>, <html>, etc). The elements provide
* the ability for report properties to be set either via the generic <property>
* nested elements or dedicated attributes. Potential conflicts between the same
* conceptual property being set via an attribute and a nested element are resolved
* by making dedicated attributes higher priority.<P>
*
* Note that ReportCfg does not handle any non-report related properties.
* This can be done via {@link com.vladium.emma.ant.GenericCfg}. It is also the
* parent's responsibility to merge any inherited report properties with
* ReportCfg settings.
*
* @author Vlad Roubtsov, (C) 2003
*/
public
class ReportCfg implements IReportProperties
{
// public: ................................................................
public static abstract class Element implements IReportEnums, IReportProperties
{
public void setUnits (final UnitsTypeAttribute units)
{
m_settings.setProperty (m_prefix.concat (UNITS_TYPE), units.getValue ());
}
public void setDepth (final DepthAttribute depth)
{
m_settings.setProperty (m_prefix.concat (DEPTH), depth.getValue ());
}
public void setColumns (final String columns)
{
m_settings.setProperty (m_prefix.concat (COLUMNS), columns);
}
public void setSort (final String sort)
{
m_settings.setProperty (m_prefix.concat (SORT), sort);
}
public void setMetrics (final String metrics)
{
m_settings.setProperty (m_prefix.concat (METRICS), metrics);
}
// not supported anymore:
// public void setOutdir (final File dir)
// {
// // TODO: does ANT resolve files relative to current JVM dir or ${basedir}?
// m_settings.setProperty (m_prefix.concat (OUT_DIR), dir.getAbsolutePath ());
// }
public void setOutfile (final String fileName)
{
m_settings.setProperty (m_prefix.concat (OUT_FILE), fileName);
}
public void setEncoding (final String encoding)
{
m_settings.setProperty (m_prefix.concat (OUT_ENCODING), encoding);
}
// generic property element [don't doc this publicly]:
public PropertyElement createProperty ()
{
// TODO: error out on conficting duplicate settings
final PropertyElement property = new PropertyElement ();
m_genericSettings.add (property);
return property;
}
protected abstract String getType ();
Element (final Task task, final IProperties settings)
{
if (task == null)
throw new IllegalArgumentException ("null input: task");
if (settings == null)
throw new IllegalArgumentException ("null input: settings");
m_task = task;
m_settings = settings;
m_prefix = PREFIX.concat (getType ()).concat (".");
m_genericSettings = new ArrayList ();
}
void processGenericSettings ()
{
for (Iterator i = m_genericSettings.iterator (); i.hasNext (); )
{
final PropertyElement property = (PropertyElement) i.next ();
final String name = property.getName ();
final String value = property.getValue () != null ? property.getValue () : "";
if (name != null)
{
final String prefixedName = m_prefix.concat (name);
// generically named settings don't override report named settings:
if (! m_settings.isOverridden (prefixedName))
m_settings.setProperty (prefixedName, value);
}
}
}
protected final Task m_task; // never null
protected final String m_prefix; // never null
protected final IProperties m_settings; // never null
protected final List /* PropertyElement */ m_genericSettings; // never null
} // end of nested class
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public static class Element_HTML extends Element
{
protected final String getType ()
{
return TYPE;
}
Element_HTML (final Task task, final IProperties settings)
{
super (task, settings);
}
static final String TYPE = "html";
} // end of nested class
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public static class Element_TXT extends Element
{
protected final String getType ()
{
return TYPE;
}
Element_TXT (final Task task, final IProperties settings)
{
super (task, settings);
}
static final String TYPE = "txt";
} // end of nested class
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public static class Element_LCOV extends Element
{
protected final String getType ()
{
return TYPE;
}
Element_LCOV (final Task task, final IProperties settings)
{
super (task, settings);
}
static final String TYPE = "lcov";
} // end of nested class
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public static class Element_XML extends Element
{
protected final String getType ()
{
return TYPE;
}
Element_XML (final Task task, final IProperties settings)
{
super (task, settings);
}
static final String TYPE = "xml";
} // end of nested class
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public ReportCfg (final Project project, final Task task)
{
m_project = project;
m_task = task;
m_reportTypes = new ArrayList (4);
m_cfgList = new ArrayList (4);
m_settings = EMMAProperties.wrap (new Properties ());
}
public Path getSourcepath ()
{
return m_srcpath;
}
public String [] getReportTypes ()
{
final BuildException failure = getFailure ();
if (failure != null)
throw failure;
else
{
if (m_reportTypes.isEmpty ())
return IConstants.EMPTY_STRING_ARRAY;
else
{
final String [] result = new String [m_reportTypes.size ()];
m_reportTypes.toArray (result);
return result;
}
}
}
public IProperties getReportSettings ()
{
final BuildException failure = getFailure ();
if (failure != null)
throw failure;
else
{
if (! m_processed)
{
// collect all nested elements' generic settins into m_settings:
for (Iterator i = m_cfgList.iterator (); i.hasNext (); )
{
final Element cfg = (Element) i.next ();
cfg.processGenericSettings ();
}
m_processed = true;
}
return m_settings; // no clone
}
}
// sourcepath attribute/element:
public void setSourcepath (final Path path)
{
if (m_srcpath == null)
m_srcpath = path;
else
m_srcpath.append (path);
}
public void setSourcepathRef (final Reference ref)
{
createSourcepath ().setRefid (ref);
}
public Path createSourcepath ()
{
if (m_srcpath == null)
m_srcpath = new Path (m_project);
return m_srcpath.createPath ();
}
// generator elements:
public Element_TXT createTxt ()
{
return (Element_TXT) addCfgElement (Element_TXT.TYPE,
new Element_TXT (m_task, m_settings));
}
public Element_LCOV createLcov ()
{
return (Element_LCOV) addCfgElement (Element_LCOV.TYPE,
new Element_LCOV (m_task, m_settings));
}
public Element_HTML createHtml ()
{
return (Element_HTML) addCfgElement (Element_HTML.TYPE,
new Element_HTML (m_task, m_settings));
}
public Element_XML createXml ()
{
return (Element_XML) addCfgElement (Element_XML.TYPE,
new Element_XML (m_task, m_settings));
}
// report properties [defaults for all report types]:
public void setUnits (final UnitsTypeAttribute units)
{
m_settings.setProperty (PREFIX.concat (UNITS_TYPE), units.getValue ());
}
public void setDepth (final DepthAttribute depth)
{
m_settings.setProperty (PREFIX.concat (DEPTH), depth.getValue ());
}
public void setColumns (final String columns)
{
m_settings.setProperty (PREFIX.concat (COLUMNS), columns);
}
public void setSort (final String sort)
{
m_settings.setProperty (PREFIX.concat (SORT), sort);
}
public void setMetrics (final String metrics)
{
m_settings.setProperty (PREFIX.concat (METRICS), metrics);
}
// not supported anymore:
// public void setOutdir (final File dir)
// {
// // TODO: does ANT resolve files relative to current JVM dir or ${basedir}?
// m_settings.setProperty (PREFIX.concat (OUT_DIR), dir.getAbsolutePath ());
// }
//
// public void setDestdir (final File dir)
// {
// // TODO: does ANT resolve files relative to current JVM dir or ${basedir}?
// m_settings.setProperty (PREFIX.concat (OUT_DIR), dir.getAbsolutePath ());
// }
public void setOutfile (final String fileName)
{
m_settings.setProperty (PREFIX.concat (OUT_FILE), fileName);
}
public void setEncoding (final String encoding)
{
m_settings.setProperty (PREFIX.concat (OUT_ENCODING), encoding);
}
// protected: .............................................................
protected Element addCfgElement (final String type, final Element cfg)
{
if (m_reportTypes.contains (type))
{
setFailure ((BuildException) SuppressableTask.newBuildException (m_task.getTaskName ()
+ ": duplicate configuration for report type [" + type + "]" ,
m_task.getLocation ()).fillInStackTrace ());
}
else
{
m_reportTypes.add (type);
m_cfgList.add (cfg);
}
return cfg;
}
// package: ...............................................................
// private: ...............................................................
private void setFailure (final BuildException failure)
{
if (m_settingsFailure == null) m_settingsFailure = failure; // record the first one only
}
private BuildException getFailure ()
{
return m_settingsFailure;
}
private final Project m_project;
private final Task m_task;
private final List /* report type:String */ m_reportTypes; // using a list to keep the generation order same as configuration
private final List /* Element */ m_cfgList;
private final IProperties m_settings; // never null
private Path m_srcpath;
private transient BuildException m_settingsFailure; // can be null
private transient boolean m_processed;
} // end of class
// ----------------------------------------------------------------------------