2007-01-10 Marek Sieradzki <marek.sieradzki@gmail.com>
[mono.git] / mcs / class / Microsoft.Build.Engine / Microsoft.Build.BuildEngine / BuildPropertyGroup.cs
index 8075d2484e60aa4836cb91aabecb36a561a5057f..d20027559483678e4edc059062834cfd4f5c8486 100644 (file)
@@ -29,7 +29,7 @@
 
 using System;
 using System.Collections;
-using System.Collections.Specialized;
+using System.Collections.Generic;
 using System.Reflection;
 using System.Text;
 using System.Xml;
@@ -37,221 +37,234 @@ using System.Xml;
 namespace Microsoft.Build.BuildEngine {
        public class BuildPropertyGroup : IEnumerable {
        
+               bool                    read_only;
+               ImportedProject         importedProject;
                XmlElement              propertyGroup;
-               XmlAttribute            condition;
-               string                  importedFromFilename;
-               bool                    isImported;
                GroupingCollection      parentCollection;
                Project                 parentProject;
-               IList                   properties;
-               IDictionary             propertiesByName;
-       
+               List <BuildProperty>    properties;
+               Dictionary <string, BuildProperty>      propertiesByName;
+
                public BuildPropertyGroup ()
-                       : this (true, null)
+                       : this (null, null, null, false)
                {
                }
-               
-               internal BuildPropertyGroup (bool forXml, Project project)
+
+               internal BuildPropertyGroup (XmlElement xmlElement, Project project, ImportedProject importedProject, bool readOnly)
                {
-                       this.propertyGroup = null;
-                       this.condition = null;
-                       this.importedFromFilename = null;
-                       this.isImported = false;
+                       this.importedProject = importedProject;
                        this.parentCollection = null;
                        this.parentProject = project;
-                       if (forXml == true)
-                               this.properties = new ArrayList ();
-                       else
-                               this.propertiesByName = CollectionsUtil.CreateCaseInsensitiveHashtable ();
+                       this.propertyGroup = xmlElement;
+                       this.read_only = readOnly;
+
+                       if (FromXml) {
+                               this.properties = new List <BuildProperty> ();
+                               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 <string, BuildProperty> (StringComparer.InvariantCultureIgnoreCase);
                }
 
                public BuildProperty AddNewProperty (string propertyName,
                                                     string propertyValue)
                {
-                       return AddNewProperty (propertyName, propertyValue,
-                               PropertyType.Normal);
+                       return AddNewProperty (propertyName, propertyValue, false);
                }
                
-               internal BuildProperty AddNewProperty (string propertyName,
-                                                      string propertyValue,
-                                                      PropertyType propertyType)
+               public BuildProperty AddNewProperty (string propertyName,
+                                                    string propertyValue,
+                                                    bool treatPropertyValueAsLiteral)
                {
-                       BuildProperty added, existing;
-                       
-                       added = new BuildProperty (propertyName, propertyValue);
-                       added.PropertyType = propertyType;
-                       if (properties != null) {
-                               properties.Add (added);
-                       } else if (propertiesByName != null) {
-                               if (propertiesByName.Contains (propertyName) == true) {
-                                       existing = (BuildProperty) propertiesByName [added.Name];
-                                       if (added.PropertyType <= existing.PropertyType) {
-                                               propertiesByName.Remove (added.Name);
-                                               propertiesByName.Add (added.Name, added);
-                                       }
-                               } else {
-                                       propertiesByName.Add (added.Name, added);
-                               }
+                       BuildProperty prop;
+
+                       if (FromXml) {
+                               XmlElement xe;
+                               
+                               xe = propertyGroup.OwnerDocument.CreateElement (propertyName, Project.XmlNamespace);
+                               propertyGroup.AppendChild (xe);
+                               
+                               if (treatPropertyValueAsLiteral)
+                                       xe.InnerText = Utilities.Escape (propertyValue);
+                               else
+                                       xe.InnerText = propertyValue;
+                               
+                               prop = new BuildProperty (parentProject, xe);
+                               AddProperty (prop);
+                               parentProject.EvaluatedProperties.AddProperty (prop);
+                               return prop;
                        } else
-                               throw new Exception ("PropertyGroup is not initialized.");
-                       return added;
+                               throw new InvalidOperationException ("This method is only valid for persisted <System.Object[]> elements.");
                }
-               
-               internal void AddFromExistingProperty (BuildProperty buildProperty)
+
+               internal void AddProperty (BuildProperty property)
                {
-                       BuildProperty added, existing;
-                       
-                       added = buildProperty.Clone (false);
-                       if (propertiesByName.Contains (added.Name) == true) {
-                               existing = (BuildProperty) propertiesByName [added.Name];
-                               if (added.PropertyType <= existing.PropertyType) {
-                                       propertiesByName.Remove (added.Name);
-                                       propertiesByName.Add (added.Name, added);
+                       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);
                                }
-                       } else
-                               propertiesByName.Add (added.Name, added);
+                       }
                }
                
                public void Clear ()
                {
+                       if (FromXml) {
+                               propertyGroup.RemoveAll ();
+                               properties = new List <BuildProperty> ();
+                       } else
+                               propertiesByName = new Dictionary <string, BuildProperty> ();
                }
 
+               [MonoTODO]
                public BuildPropertyGroup Clone (bool deepClone)
                {
-                       return null;
+                       throw new NotImplementedException ();
                }
 
-               // FIXME: what it is doing?
-               internal void Evaluate (BuildPropertyGroup evaluatedPropertyBag,
-                                              bool ignoreCondition,
-                                              bool honorCondition,
-                                              Hashtable conditionedPropertiesTable,
-                                              ProcessingPass pass)
-               {
-               }
-               
                public IEnumerator GetEnumerator ()
                {
-                       if (properties != null)
+                       if (FromXml)
                                foreach (BuildProperty bp in properties)
                                        yield return bp;
-                       else if (propertiesByName != null)
-                               foreach (DictionaryEntry de in propertiesByName)
-                                       yield return (BuildProperty) de.Value;
-                       else
-                               throw new Exception ("PropertyGroup is not initialized.");
+                       else 
+                               foreach (KeyValuePair <string, BuildProperty> kvp in propertiesByName)
+                                       yield return kvp.Value;
                }
 
-               public void GetStringArraysForAllProperties (out string[] propertyNames,
-                                                            out string[] propertyValues,
-                                                            out string[] propertyFinalValues)
+               public void RemoveProperty (BuildProperty propertyToRemove)
                {
-                       propertyNames = null;
-                       propertyValues = null;
-                       propertyFinalValues = null;
-                       int i = 0;
-                       if (properties != null) {
-                               foreach (BuildProperty bp in properties) {
-                                       propertyNames [i] = bp.Name;
-                                       propertyValues [i] = bp.Value;
-                                       propertyFinalValues [i] = bp.FinalValue;
-                                       i++;
-                               }
-                       } else if (propertiesByName != null) {
-                               foreach (DictionaryEntry de in propertiesByName) {
-                                       propertyNames [i] = ((BuildProperty) de.Value).Name;
-                                       propertyValues [i] = ((BuildProperty) de.Value).Value;
-                                       propertyFinalValues [i] = ((BuildProperty) de.Value).FinalValue;
-                                       i++;
-                               }
+                       if (FromXml)
+                               properties.Remove (propertyToRemove);
+                       else {
+                               foreach (KeyValuePair <string, BuildProperty> kvp in propertiesByName)
+                                       if (kvp.Value == propertyToRemove) {
+                                               propertiesByName.Remove (kvp.Key);
+                                               break;
+                                       }
                        }
                }
 
-               public void RemoveProperty (BuildProperty propertyToRemove)
+               public void RemoveProperty (string propertyName)
                {
-                       if (properties == null)
-                               throw new Exception ("PropertyGroup is not initialized.");
-                       properties.Remove (propertyToRemove);
+                       if (FromXml) {
+                               foreach (BuildProperty bp in properties)
+                                       if (bp.Name == propertyName) {
+                                               properties.Remove (bp);
+                                               break;
+                                       }
+                       } else
+                               propertiesByName.Remove (propertyName);
                }
 
-               public void RemovePropertyByName (string propertyNameToRemove)
+               public void SetProperty (string propertyName,
+                                        string propertyValue)
                {
-                       if (propertiesByName == null)
-                               throw new Exception ("PropertyGroup is not initialized.");
-                       propertiesByName.Remove (propertyNameToRemove);
+                       SetProperty (propertyName, propertyValue, false);
                }
-
+               
+               // FIXME: add a test for SetProperty on property from xml
                public void SetProperty (string propertyName,
-                                        string propertyValue)
+                                        string propertyValue,
+                                        bool treatPropertyValueAsLiteral)
                {
-                       if (propertiesByName.Contains (propertyName) == false) {
-                               AddNewProperty (propertyName, propertyValue);
-                       }
-                       ((BuildProperty) propertiesByName [propertyName]).Value = propertyValue;
+                       if (read_only)
+                               return;
+                       
+                       if (propertiesByName.ContainsKey (propertyName))
+                               propertiesByName.Remove (propertyName);
+
+                       BuildProperty bp;
+                       if (treatPropertyValueAsLiteral)
+                               bp = new BuildProperty (propertyName, Utilities.Escape (propertyValue));
+                       else
+                               bp = new BuildProperty (propertyName, propertyValue);
+
+                       AddProperty (bp);
+
+                       if (IsGlobal)
+                               parentProject.ProcessXml ();
                }
                
-               internal void BindToXml (XmlElement propertyGroupElement)
+               internal void Evaluate ()
                {
-                       if (propertyGroupElement == null)
-                               throw new ArgumentNullException ();
-                       this.properties = new ArrayList ();
-                       this.propertyGroup = propertyGroupElement;
-                       this.condition = propertyGroupElement.GetAttributeNode ("Condition");
-                       this.importedFromFilename = null;
-                       this.isImported = false;
-                       foreach (XmlElement xe in propertyGroupElement.ChildNodes) {
-                               BuildProperty bp = AddNewProperty(xe.Name, xe.InnerText);
-                               bp.PropertyType = PropertyType.Normal;
-                               bp.BindToXml (xe);
-                               Expression finalValue = new Expression (parentProject, bp.Value);
-                               bp.FinalValue = (string) finalValue.ToNonArray (typeof (string));
-                               parentProject.EvaluatedProperties.AddFromExistingProperty (bp);
-                       } 
+                       if (!FromXml) {
+                               throw new InvalidOperationException ();
+                       }
+                       foreach (BuildProperty bp in properties) {
+                               if (bp.Condition == String.Empty)
+                                       bp.Evaluate ();
+                               else {
+                                       ConditionExpression ce = ConditionParser.ParseCondition (bp.Condition);
+                                       if (ce.BoolEvaluate (parentProject))
+                                               bp.Evaluate ();
+                               }
+                       }
                }
                
                public string Condition {
                        get {
-                               if (condition == null)
-                                       return null;
-                               else
-                                       return condition.Value;
+                               if (!FromXml)
+                                       return String.Empty;
+                               return propertyGroup.GetAttribute ("Condition");
                        }
                        set {
-                               if (condition != null)
-                                       condition.Value = value;
+                               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 (properties != null)
+                               if (FromXml)
                                        return properties.Count;
-                               else if (propertiesByName != null)
-                                       return propertiesByName.Count;
                                else
-                                       throw new Exception ("PropertyGroup is not initialized.");
+                                       return propertiesByName.Count;
                        }
                }
 
-               public string ImportedFromFilename {
+               public bool IsImported {
                        get {
-                               return importedFromFilename;
+                               return importedProject != null;
                        }
                }
 
-               public bool IsImported {
+               internal bool FromXml {
                        get {
-                               return isImported;
+                               return propertyGroup != null;
                        }
                }
 
-               public BuildProperty this[string propertyName] {
+               bool IsGlobal {
                        get {
-                               if (propertiesByName.Contains (propertyName)) {
-                                       return (BuildProperty) propertiesByName [propertyName];
-                               } else {
+                               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;
@@ -262,7 +275,11 @@ namespace Microsoft.Build.BuildEngine {
                        get { return parentCollection; }
                        set { parentCollection = value; }
                }
+
+               internal XmlElement XmlElement {
+                       get { return propertyGroup; }
+               }
        }
 }
 
-#endif
\ No newline at end of file
+#endif