2 // BuildPropertyGroup.cs: Represents a group of properties
5 // Marek Sieradzki (marek.sieradzki@gmail.com)
7 // (C) 2005 Marek Sieradzki
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 using System
.Collections
;
32 using System
.Collections
.Generic
;
33 using System
.Reflection
;
37 namespace Microsoft
.Build
.BuildEngine
{
38 public class BuildPropertyGroup
: IEnumerable
{
41 ImportedProject importedProject
;
42 XmlElement propertyGroup
;
43 GroupingCollection parentCollection
;
44 Project parentProject
;
45 List
<BuildProperty
> properties
;
46 Dictionary
<string, BuildProperty
> propertiesByName
;
49 public BuildPropertyGroup ()
50 : this (null, null, null, false)
54 internal BuildPropertyGroup (XmlElement xmlElement
, Project project
, ImportedProject importedProject
, bool readOnly
)
56 this.importedProject
= importedProject
;
57 this.parentCollection
= null;
58 this.parentProject
= project
;
59 this.propertyGroup
= xmlElement
;
60 this.read_only
= readOnly
;
63 this.properties
= new List
<BuildProperty
> ();
64 foreach (XmlNode xn
in propertyGroup
.ChildNodes
) {
65 if (!(xn
is XmlElement
))
68 XmlElement xe
= (XmlElement
) xn
;
69 BuildProperty bp
= new BuildProperty (parentProject
, xe
);
73 this.propertiesByName
= new Dictionary
<string, BuildProperty
> (StringComparer
.InvariantCultureIgnoreCase
);
76 public BuildProperty
AddNewProperty (string propertyName
,
79 return AddNewProperty (propertyName
, propertyValue
, false);
82 public BuildProperty
AddNewProperty (string propertyName
,
84 bool treatPropertyValueAsLiteral
)
87 throw new InvalidOperationException ("This method is only valid for persisted property groups.");
89 if (treatPropertyValueAsLiteral
)
90 propertyValue
= Utilities
.Escape (propertyValue
);
92 XmlElement element
= propertyGroup
.OwnerDocument
.CreateElement (propertyName
, Project
.XmlNamespace
);
93 propertyGroup
.AppendChild (element
);
95 BuildProperty property
= new BuildProperty (parentProject
, element
);
96 property
.Value
= propertyValue
;
97 AddProperty (property
);
99 parentProject
.MarkProjectAsDirty ();
100 parentProject
.NeedToReevaluate ();
105 internal void AddProperty (BuildProperty property
)
108 properties
.Add (property
);
110 if (propertiesByName
.ContainsKey (property
.Name
)) {
111 BuildProperty existing
= propertiesByName
[property
.Name
];
112 if (property
.PropertyType
<= existing
.PropertyType
) {
113 propertiesByName
.Remove (property
.Name
);
114 propertiesByName
.Add (property
.Name
, property
);
117 propertiesByName
.Add (property
.Name
, property
);
124 propertyGroup
.RemoveAll ();
125 properties
= new List
<BuildProperty
> ();
127 propertiesByName
= new Dictionary
<string, BuildProperty
> ();
131 public BuildPropertyGroup
Clone (bool deepClone
)
133 BuildPropertyGroup bpg
= new BuildPropertyGroup (propertyGroup
, parentProject
, importedProject
, read_only
);
135 foreach (BuildProperty bp
in properties
) {
137 bpg
.AddProperty (bp
.Clone (true));
139 bpg
.AddNewProperty (bp
.Name
, bp
.FinalValue
);
142 foreach (BuildProperty bp
in propertiesByName
.Values
) {
144 bpg
.AddProperty (bp
.Clone (true));
146 bpg
.AddNewProperty (bp
.Name
, bp
.FinalValue
);
153 public IEnumerator
GetEnumerator ()
156 foreach (BuildProperty bp
in properties
)
159 foreach (KeyValuePair
<string, BuildProperty
> kvp
in propertiesByName
)
160 yield return kvp
.Value
;
163 public void RemoveProperty (BuildProperty propertyToRemove
)
165 if (propertyToRemove
== null)
166 throw new ArgumentNullException ("propertyToRemove");
169 if (!propertyToRemove
.FromXml
)
170 throw new InvalidOperationException ("The specified property does not belong to the current property group.");
172 propertyToRemove
.XmlElement
.ParentNode
.RemoveChild (propertyToRemove
.XmlElement
);
173 properties
.Remove (propertyToRemove
);
175 propertiesByName
.Remove (propertyToRemove
.Name
);
178 public void RemoveProperty (string propertyName
)
181 foreach (BuildProperty bp
in properties
)
182 if (bp
.Name
== propertyName
) {
187 propertiesByName
.Remove (propertyName
);
190 public void SetProperty (string propertyName
,
191 string propertyValue
)
193 SetProperty (propertyName
, propertyValue
, false);
196 public void SetProperty (string propertyName
,
197 string propertyValue
,
198 bool treatPropertyValueAsLiteral
)
203 throw new InvalidOperationException (
204 "This method is only valid for virtual property groups, not <PropertyGroup> elements.");
206 if (treatPropertyValueAsLiteral
)
207 propertyValue
= Utilities
.Escape (propertyValue
);
209 if (propertiesByName
.ContainsKey (propertyName
))
210 propertiesByName
.Remove (propertyName
);
212 BuildProperty bp
= new BuildProperty (propertyName
, propertyValue
);
213 if (Char
.IsDigit (propertyName
[0]))
214 throw new ArgumentException (String
.Format (
215 "The name \"{0}\" contains an invalid character \"{1}\".", propertyName
, propertyName
[0]));
220 parentProject
.NeedToReevaluate ();
223 internal void Evaluate ()
228 foreach (BuildProperty bp
in properties
)
229 if (ConditionParser
.ParseAndEvaluate (bp
.Condition
, parentProject
))
235 public string Condition
{
239 return propertyGroup
.GetAttribute ("Condition");
243 throw new InvalidOperationException (
244 "Cannot set a condition on an object not represented by an XML element in the project file.");
245 propertyGroup
.SetAttribute ("Condition", value);
252 return properties
.Count
;
254 return propertiesByName
.Count
;
258 public bool IsImported
{
260 return importedProject
!= null;
264 internal bool FromXml
{
266 return propertyGroup
!= null;
272 return parentProject
!= null && propertyGroup
== null;
276 public BuildProperty
this [string propertyName
] {
279 throw new InvalidOperationException ("Properties in persisted property groups cannot be accessed by name.");
281 if (propertiesByName
.ContainsKey (propertyName
))
282 return propertiesByName
[propertyName
];
287 propertiesByName
[propertyName
] = value;
291 internal GroupingCollection GroupingCollection
{
292 get { return parentCollection; }
293 set { parentCollection = value; }
296 internal XmlElement XmlElement
{
297 get { return propertyGroup; }