PageRenderTime 2ms CodeModel.GetById 20ms app.highlight 8ms RepoModel.GetById 1ms app.codeStats 0ms

/mcs/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/BuildPropertyGroup.cs

https://bitbucket.org/luobailiang/mono
C# | 302 lines | 232 code | 44 blank | 26 comment | 40 complexity | f77f7e3841ab3899512a004396a1919f MD5 | raw file
  1//
  2// BuildPropertyGroup.cs: Represents a group of properties
  3//
  4// Author:
  5//   Marek Sieradzki (marek.sieradzki@gmail.com)
  6// 
  7// (C) 2005 Marek Sieradzki
  8//
  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:
 16//
 17// The above copyright notice and this permission notice shall be
 18// included in all copies or substantial portions of the Software.
 19//
 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.
 27
 28#if NET_2_0
 29
 30using System;
 31using System.Collections;
 32using System.Collections.Generic;
 33using System.Reflection;
 34using System.Text;
 35using System.Xml;
 36
 37namespace Microsoft.Build.BuildEngine {
 38	public class BuildPropertyGroup : IEnumerable {
 39	
 40		bool			read_only;
 41		ImportedProject		importedProject;
 42		XmlElement		propertyGroup;
 43		GroupingCollection	parentCollection;
 44		Project			parentProject;
 45		List <BuildProperty>	properties;
 46		Dictionary <string, BuildProperty>	propertiesByName;
 47		bool evaluated;
 48
 49		public BuildPropertyGroup ()
 50			: this (null, null, null, false)
 51		{
 52		}
 53
 54		internal BuildPropertyGroup (XmlElement xmlElement, Project project, ImportedProject importedProject, bool readOnly)
 55		{
 56			this.importedProject = importedProject;
 57			this.parentCollection = null;
 58			this.parentProject = project;
 59			this.propertyGroup = xmlElement;
 60			this.read_only = readOnly;
 61
 62			if (FromXml) {
 63				this.properties = new List <BuildProperty> ();
 64				foreach (XmlNode xn in propertyGroup.ChildNodes) {
 65					if (!(xn is XmlElement))
 66						continue;
 67					
 68					XmlElement xe = (XmlElement) xn;
 69					BuildProperty bp = new BuildProperty (parentProject, xe);
 70					AddProperty (bp);
 71				} 
 72			} else
 73				this.propertiesByName = new Dictionary <string, BuildProperty> (StringComparer.InvariantCultureIgnoreCase);
 74		}
 75
 76		public BuildProperty AddNewProperty (string propertyName,
 77						     string propertyValue)
 78		{
 79			return AddNewProperty (propertyName, propertyValue, false);
 80		}
 81		
 82		public BuildProperty AddNewProperty (string propertyName,
 83						     string propertyValue,
 84						     bool treatPropertyValueAsLiteral)
 85		{
 86			if (!FromXml)
 87				throw new InvalidOperationException ("This method is only valid for persisted property groups.");
 88
 89			if (treatPropertyValueAsLiteral)
 90				propertyValue = Utilities.Escape (propertyValue);
 91
 92			XmlElement element = propertyGroup.OwnerDocument.CreateElement (propertyName, Project.XmlNamespace);
 93			propertyGroup.AppendChild (element);
 94
 95			BuildProperty property = new BuildProperty (parentProject, element);
 96			property.Value = propertyValue;
 97			AddProperty (property);
 98
 99			parentProject.MarkProjectAsDirty ();
100			parentProject.NeedToReevaluate ();
101
102			return property;
103		}
104
105		internal void AddProperty (BuildProperty property)
106		{
107			if (FromXml)
108				properties.Add (property);
109			else {
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);
115					}
116				} else
117					propertiesByName.Add (property.Name, property);
118			}
119		}
120		
121		public void Clear ()
122		{
123			if (FromXml) {
124				propertyGroup.RemoveAll ();
125				properties = new List <BuildProperty> ();
126			} else
127				propertiesByName = new Dictionary <string, BuildProperty> ();
128		}
129
130		[MonoTODO]
131		public BuildPropertyGroup Clone (bool deepClone)
132		{
133			BuildPropertyGroup bpg = new BuildPropertyGroup (propertyGroup, parentProject, importedProject, read_only);
134			if (FromXml) {
135				foreach (BuildProperty bp in properties) {
136					if (deepClone)
137						bpg.AddProperty (bp.Clone (true));
138					else
139						bpg.AddNewProperty (bp.Name, bp.FinalValue);
140				}
141			} else {
142				foreach (BuildProperty bp in propertiesByName.Values) {
143					if (deepClone)
144						bpg.AddProperty (bp.Clone (true));
145					else
146						bpg.AddNewProperty (bp.Name, bp.FinalValue);
147				}
148			}
149
150			return bpg;
151		}
152
153		public IEnumerator GetEnumerator ()
154		{
155			if (FromXml)
156				foreach (BuildProperty bp in properties)
157					yield return bp;
158			else 
159				foreach (KeyValuePair <string, BuildProperty> kvp in propertiesByName)
160					yield return kvp.Value;
161		}
162
163		public void RemoveProperty (BuildProperty propertyToRemove)
164		{
165			if (propertyToRemove == null)
166				throw new ArgumentNullException ("propertyToRemove");
167
168			if (FromXml) {
169				if (!propertyToRemove.FromXml)
170					throw new InvalidOperationException ("The specified property does not belong to the current property group.");
171
172				propertyToRemove.XmlElement.ParentNode.RemoveChild (propertyToRemove.XmlElement);
173				properties.Remove (propertyToRemove);
174			} else
175				propertiesByName.Remove (propertyToRemove.Name);
176		}
177
178		public void RemoveProperty (string propertyName)
179		{
180			if (FromXml) {
181				foreach (BuildProperty bp in properties)
182					if (bp.Name == propertyName) {
183						RemoveProperty (bp);
184						break;
185					}
186			} else
187				propertiesByName.Remove (propertyName);
188		}
189
190		public void SetProperty (string propertyName,
191					 string propertyValue)
192		{
193			SetProperty (propertyName, propertyValue, false);
194		}
195		
196		public void SetProperty (string propertyName,
197					 string propertyValue,
198					 bool treatPropertyValueAsLiteral)
199		{
200			if (read_only)
201				return;
202			if (FromXml)
203				throw new InvalidOperationException (
204					"This method is only valid for virtual property groups, not <PropertyGroup> elements.");
205
206			if (treatPropertyValueAsLiteral)
207				propertyValue = Utilities.Escape (propertyValue);
208
209			if (propertiesByName.ContainsKey (propertyName))
210				propertiesByName.Remove (propertyName);
211
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]));
216
217			AddProperty (bp);
218
219			if (IsGlobal)
220				parentProject.NeedToReevaluate ();
221		}
222		
223		internal void Evaluate ()
224		{
225			if (evaluated)
226				return;
227
228			foreach (BuildProperty bp in properties)
229				if (ConditionParser.ParseAndEvaluate (bp.Condition, parentProject))
230					bp.Evaluate ();
231
232			evaluated = true;
233		}
234		
235		public string Condition {
236			get {
237				if (!FromXml)
238					return String.Empty;
239				return propertyGroup.GetAttribute ("Condition");
240			}
241			set {
242				if (!FromXml)
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);
246			}
247		}
248
249		public int Count {
250			get {
251				if (FromXml)
252					return properties.Count;
253				else
254					return propertiesByName.Count;
255			}
256		}
257
258		public bool IsImported {
259			get {
260				return importedProject != null;
261			}
262		}
263
264		internal bool FromXml {
265			get {
266				return propertyGroup != null;
267			}
268		}
269
270		bool IsGlobal {
271			get {
272				return parentProject != null && propertyGroup == null;
273			}
274		}
275
276		public BuildProperty this [string propertyName] {
277			get {
278				if (FromXml)
279					throw new InvalidOperationException ("Properties in persisted property groups cannot be accessed by name.");
280				
281				if (propertiesByName.ContainsKey (propertyName))
282					return propertiesByName [propertyName];
283				else
284					return null;
285			}
286			set {
287				propertiesByName [propertyName] = value;
288			}
289		}
290		
291		internal GroupingCollection GroupingCollection {
292			get { return parentCollection; }
293			set { parentCollection = value; }
294		}
295
296		internal XmlElement XmlElement {
297			get { return propertyGroup; }
298		}
299	}
300}
301
302#endif