// NAnt - A .NET build tool
// Copyright (C) 2001-2002 Gerry Shaw
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// Gerry Shaw (gerry_shaw@yahoo.com)
// Ian MacLean (imaclean@gmail.com)
// Scott Hernandez (ScottHernandez@hotmail.com)
// William E. Caputo (wecaputo@thoughtworks.com | logosity@yahoo.com)
using System;
using System.Collections.Specialized;
using System.Globalization;
using System.Xml;
using NAnt.Core.Attributes;
using NAnt.Core.Util;
namespace NAnt.Core {
[Serializable()]
public sealed class Target : Element, ICloneable {
#region Private Instance Fields
private string _name = null;
private string _description = null;
private string _ifCondition = null;
private string _unlessCondition = null;
private StringCollection _dependencies = new StringCollection();
private bool _executed = false;
#endregion Private Instance Fields
#region Public Instance Constructors
///
/// Initializes a new instance of the class.
///
public Target() {
}
#endregion Public Instance Constructors
#region Public Instance Properties
///
/// This indicates whether the target has already executed.
///
public bool Executed {
get {
return _executed;
}
}
///
/// The name of the target.
///
///
///
/// Hides to have
/// return the name of target, not the name of XML element - which
/// would always be target.
///
///
/// Note: Properties are not allowed in the name.
///
///
[TaskAttribute("name", Required=true, ExpandProperties=false)]
[StringValidator(AllowEmpty=false)]
public new string Name {
get { return _name; }
set { _name = value; }
}
///
/// If then the target will be executed;
/// otherwise, skipped. The default is .
///
[TaskAttribute("if", ExpandProperties=false)]
public string IfCondition {
get { return _ifCondition; }
set { _ifCondition = StringUtils.ConvertEmptyToNull(value); }
}
///
/// Gets a value indicating whether the target should be executed.
///
///
/// if the target should be executed; otherwise,
/// .
///
public bool IfDefined {
get {
// expand properties in condition
string expandedCondition = Project.Properties.ExpandProperties(IfCondition, Location);
// if a condition is supplied, it should evaluate to a bool
if (!StringUtils.IsNullOrEmpty(expandedCondition)) {
try {
return Convert.ToBoolean(expandedCondition, CultureInfo.InvariantCulture);
} catch (FormatException) {
throw new BuildException(string.Format(CultureInfo.InvariantCulture,
ResourceUtils.GetString("NA1070"), expandedCondition), Location);
}
}
// no condition is supplied
return true;
}
}
///
/// Opposite of . If
/// then the target will be executed; otherwise, skipped. The default
/// is .
///
[TaskAttribute("unless", ExpandProperties=false)]
public string UnlessCondition {
get { return _unlessCondition; }
set { _unlessCondition = StringUtils.ConvertEmptyToNull(value); }
}
///
/// Gets a value indicating whether the target should NOT be executed.
///
///
/// if the target should NOT be executed;
/// otherwise, .
///
public bool UnlessDefined {
get {
// expand properties in condition
string expandedCondition = Project.Properties.ExpandProperties(UnlessCondition, Location);
// if a condition is supplied, it should evaluate to a bool
if (!StringUtils.IsNullOrEmpty(expandedCondition)) {
try {
return Convert.ToBoolean(expandedCondition, CultureInfo.InvariantCulture);
} catch (FormatException) {
throw new BuildException(string.Format(CultureInfo.InvariantCulture,
ResourceUtils.GetString("NA1069"), expandedCondition),
Location);
}
}
// no condition is supplied
return false;
}
}
///
/// The description of the target.
///
[TaskAttribute("description")]
public string Description {
set { _description = value;}
get { return _description; }
}
///
/// Space separated list of targets that this target depends on.
///
[TaskAttribute("depends")]
public string DependsListString {
set {
foreach (string str in value.Split(new char[] {' ', ','})) {
string dependency = str.Trim();
if (dependency.Length > 0) {
Dependencies.Add(dependency);
}
}
}
}
///
/// A collection of target names that must be executed before this
/// target.
///
public StringCollection Dependencies {
get { return _dependencies; }
}
#endregion Public Instance Properties
#region Implementation of ICloneable
///
/// Creates a shallow copy of the .
///
///
/// A shallow copy of the .
///
object ICloneable.Clone() {
return Clone();
}
#endregion
#region Public Instance Methods
///
/// Creates a shallow copy of the .
///
///
/// A shallow copy of the .
///
public Target Clone() {
Target clone = new Target();
base.CopyTo(clone);
clone._dependencies = _dependencies;
clone._description = _description;
clone._executed = _executed;
clone._ifCondition = _ifCondition;
clone._name = _name;
clone._unlessCondition = _unlessCondition;
return clone;
}
///
/// Executes dependent targets first, then the target.
///
public void Execute() {
if (IfDefined && !UnlessDefined) {
try {
Project.OnTargetStarted(this, new BuildEventArgs(this));
// select all the task nodes and execute them
foreach (XmlNode childNode in XmlNode) {
if (!(childNode.NodeType == XmlNodeType.Element)|| !childNode.NamespaceURI.Equals(NamespaceManager.LookupNamespace("nant"))) {
continue;
}
if (TypeFactory.TaskBuilders.Contains(childNode.Name)) {
Task task = Project.CreateTask(childNode, this);
if (task != null) {
task.Execute();
}
} else if (TypeFactory.DataTypeBuilders.Contains(childNode.Name)) {
DataTypeBase dataType = Project.CreateDataTypeBase(childNode);
Project.Log(Level.Verbose, "Adding a {0} reference with id '{1}'.",
childNode.Name, dataType.ID);
if (!Project.DataTypeReferences.Contains(dataType.ID)) {
Project.DataTypeReferences.Add(dataType.ID, dataType);
} else {
Project.DataTypeReferences[dataType.ID] = dataType; // overwrite with the new reference.
}
} else {
throw new BuildException(string.Format(CultureInfo.InvariantCulture,
ResourceUtils.GetString("NA1071"),
childNode.Name), Project.LocationMap.GetLocation(childNode));
}
}
} finally {
_executed = true;
Project.OnTargetFinished(this, new BuildEventArgs(this));
}
}
}
#endregion Public Instance Methods
}
}