// // BuildPropertyGroup.cs: Represents a group of properties // // Author: // Marek Sieradzki (marek.sieradzki@gmail.com) // // (C) 2005 Marek Sieradzki // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #if NET_2_0 using System; using System.Collections; using System.Collections.Generic; using System.Reflection; using System.Text; using System.Xml; namespace Microsoft.Build.BuildEngine { public class BuildPropertyGroup : IEnumerable { bool read_only; ImportedProject importedProject; XmlElement propertyGroup; GroupingCollection parentCollection; Project parentProject; List properties; Dictionary propertiesByName; bool evaluated; public BuildPropertyGroup () : this (null, null, null, false) { } internal BuildPropertyGroup (XmlElement xmlElement, Project project, ImportedProject importedProject, bool readOnly) { this.importedProject = importedProject; this.parentCollection = null; this.parentProject = project; this.propertyGroup = xmlElement; this.read_only = readOnly; if (FromXml) { this.properties = new List (); foreach (XmlNode xn in propertyGroup.ChildNodes) { if (!(xn is XmlElement)) continue; XmlElement xe = (XmlElement) xn; BuildProperty bp = new BuildProperty (parentProject, xe); AddProperty (bp); } } else this.propertiesByName = new Dictionary (StringComparer.OrdinalIgnoreCase); DefinedInFileName = importedProject != null ? importedProject.FullFileName : (project != null ? project.FullFileName : null); } public BuildProperty AddNewProperty (string propertyName, string propertyValue) { return AddNewProperty (propertyName, propertyValue, false); } public BuildProperty AddNewProperty (string propertyName, string propertyValue, bool treatPropertyValueAsLiteral) { if (!FromXml) throw new InvalidOperationException ("This method is only valid for persisted property groups."); if (treatPropertyValueAsLiteral) propertyValue = Utilities.Escape (propertyValue); XmlElement element = propertyGroup.OwnerDocument.CreateElement (propertyName, Project.XmlNamespace); propertyGroup.AppendChild (element); BuildProperty property = new BuildProperty (parentProject, element); property.Value = propertyValue; AddProperty (property); parentProject.MarkProjectAsDirty (); parentProject.NeedToReevaluate (); return property; } internal void AddProperty (BuildProperty property) { if (FromXml) properties.Add (property); else { if (propertiesByName.ContainsKey (property.Name)) { BuildProperty existing = propertiesByName [property.Name]; if (property.PropertyType <= existing.PropertyType) { propertiesByName.Remove (property.Name); propertiesByName.Add (property.Name, property); } } else propertiesByName.Add (property.Name, property); } } public void Clear () { if (FromXml) { propertyGroup.RemoveAll (); properties = new List (); } else propertiesByName = new Dictionary (); } [MonoTODO] public BuildPropertyGroup Clone (bool deepClone) { BuildPropertyGroup bpg = new BuildPropertyGroup (propertyGroup, parentProject, importedProject, read_only); if (FromXml) { foreach (BuildProperty bp in properties) { if (deepClone) bpg.AddProperty (bp.Clone (true)); else bpg.AddNewProperty (bp.Name, bp.FinalValue); } } else { foreach (BuildProperty bp in propertiesByName.Values) { if (deepClone) bpg.AddProperty (bp.Clone (true)); else bpg.AddNewProperty (bp.Name, bp.FinalValue); } } return bpg; } public IEnumerator GetEnumerator () { if (FromXml) foreach (BuildProperty bp in properties) yield return bp; else foreach (KeyValuePair kvp in propertiesByName) yield return kvp.Value; } public void RemoveProperty (BuildProperty propertyToRemove) { if (propertyToRemove == null) throw new ArgumentNullException ("propertyToRemove"); if (FromXml) { if (!propertyToRemove.FromXml) throw new InvalidOperationException ("The specified property does not belong to the current property group."); propertyToRemove.XmlElement.ParentNode.RemoveChild (propertyToRemove.XmlElement); properties.Remove (propertyToRemove); } else propertiesByName.Remove (propertyToRemove.Name); } public void RemoveProperty (string propertyName) { if (FromXml) { foreach (BuildProperty bp in properties) if (bp.Name == propertyName) { RemoveProperty (bp); break; } } else propertiesByName.Remove (propertyName); } public void SetProperty (string propertyName, string propertyValue) { SetProperty (propertyName, propertyValue, false); } public void SetProperty (string propertyName, string propertyValue, bool treatPropertyValueAsLiteral) { if (read_only) return; if (FromXml) throw new InvalidOperationException ( "This method is only valid for virtual property groups, not elements."); if (treatPropertyValueAsLiteral) propertyValue = Utilities.Escape (propertyValue); if (propertiesByName.ContainsKey (propertyName)) propertiesByName.Remove (propertyName); BuildProperty bp = new BuildProperty (propertyName, propertyValue); if (Char.IsDigit (propertyName [0])) throw new ArgumentException (String.Format ( "The name \"{0}\" contains an invalid character \"{1}\".", propertyName, propertyName [0])); AddProperty (bp); if (IsGlobal) parentProject.NeedToReevaluate (); } internal void Evaluate () { if (evaluated) return; foreach (BuildProperty bp in properties) if (ConditionParser.ParseAndEvaluate (bp.Condition, parentProject)) bp.Evaluate (); evaluated = true; } public string Condition { get { if (!FromXml) return String.Empty; return propertyGroup.GetAttribute ("Condition"); } set { if (!FromXml) throw new InvalidOperationException ( "Cannot set a condition on an object not represented by an XML element in the project file."); propertyGroup.SetAttribute ("Condition", value); } } public int Count { get { if (FromXml) return properties.Count; else return propertiesByName.Count; } } public bool IsImported { get { return importedProject != null; } } internal bool FromXml { get { return propertyGroup != null; } } bool IsGlobal { get { return parentProject != null && propertyGroup == null; } } public BuildProperty this [string propertyName] { get { if (FromXml) throw new InvalidOperationException ("Properties in persisted property groups cannot be accessed by name."); if (propertiesByName.ContainsKey (propertyName)) return propertiesByName [propertyName]; else return null; } set { propertiesByName [propertyName] = value; } } internal string DefinedInFileName { get; private set; } internal GroupingCollection GroupingCollection { get { return parentCollection; } set { parentCollection = value; } } internal XmlElement XmlElement { get { return propertyGroup; } } } } #endif