Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
CompositeEnum.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 using System;
4 using System.Collections;
5 using System.Collections.Generic;
6 using System.Linq;
7 using System.Text;
8 using SiliconStudio.Shaders.Utility;
9 
10 namespace SiliconStudio.Shaders.Ast
11 {
12  /// <summary>
13  /// A composite enum.
14  /// </summary>
15  public class CompositeEnum : Node, IEnumerable<CompositeEnum>
16  {
17  [VisitorIgnore]
18  private OrderedSet<CompositeEnum> values;
19 
20  #region Constructors and Destructors
21 
22  /// <summary>
23  /// Initializes a new instance of the <see cref = "CompositeEnum" /> class.
24  /// </summary>
25  public CompositeEnum()
26  {
27  Values = new OrderedSet<CompositeEnum>();
28  }
29 
30  /// <summary>
31  /// Initializes a new instance of the <see cref="CompositeEnum"/> class.
32  /// </summary>
33  /// <param name="isFlag">
34  /// if set to <c>true</c> [is flag].
35  /// </param>
36  public CompositeEnum(bool isFlag)
37  : this()
38  {
39  IsFlag = isFlag;
40  }
41 
42  /// <summary>
43  /// Initializes a new instance of the <see cref="CompositeEnum"/> class.
44  /// </summary>
45  /// <param name="key">The key.</param>
46  /// <param name="isFlag">if set to <c>true</c> [is flag].</param>
47  public CompositeEnum(object key, bool isFlag)
48  : this(isFlag)
49  {
50  Key = key;
51  Values.Add(this);
52  }
53 
54  #endregion
55 
56  #region Public Properties
57 
58  /// <summary>
59  /// Gets a value indicating whether this instance is a composition enum (a combination of enums).
60  /// </summary>
61  /// <value>
62  /// <c>true</c> if this instance is a composition enum (a combination of enums); otherwise, <c>false</c>.
63  /// </value>
64  public bool IsComposition
65  {
66  get
67  {
68  return Key == null;
69  }
70  }
71 
72  /// <summary>
73  /// Gets a value indicating whether this instance is an enum flag.
74  /// </summary>
75  /// <value>
76  /// <c>true</c> if this instance is an enum flag; otherwise, <c>false</c>.
77  /// </value>
78  public bool IsFlag { get; private set; }
79 
80  /// <summary>
81  /// Gets or sets the key.
82  /// </summary>
83  /// <value>
84  /// The key.
85  /// </value>
86  public object Key { get; set; }
87 
88 
89  /// <summary>
90  /// Gets or sets the values.
91  /// </summary>
92  /// <value>
93  /// The values.
94  /// </value>
95  public OrderedSet<CompositeEnum> Values
96  {
97  get
98  {
99  return values;
100  }
101  set
102  {
103  values = value;
104  }
105  }
106 
107  /// <summary>
108  /// Gets the display name.
109  /// </summary>
110  public virtual string DisplayName
111  {
112  get
113  {
114  return Key != null ? Key.ToString() : "null";
115  }
116  }
117 
118  #endregion
119 
120  #region Public Methods
121 
122  /// <summary>
123  /// Determines whether [contains] [the specified enum value].
124  /// </summary>
125  /// <param name="enumValue">
126  /// The enum value.
127  /// </param>
128  /// <returns>
129  /// <c>true</c> if [contains] [the specified enum value]; otherwise, <c>false</c>.
130  /// </returns>
131  public bool Contains(CompositeEnum enumValue)
132  {
133  return enumValue.Values.IsSubsetOf(Values);
134  }
135 
136  /// <summary>
137  /// Determines whether [contains] [the specified enum values].
138  /// </summary>
139  /// <param name="enumValues">
140  /// The enum values.
141  /// </param>
142  /// <returns>
143  /// <c>true</c> if [contains] [the specified enum values]; otherwise, <c>false</c>.
144  /// </returns>
145  public bool Contains(params CompositeEnum[] enumValues)
146  {
147  return enumValues.Any(Contains);
148  }
149 
150  /// <summary>
151  /// Determines whether the specified enum values contains all.
152  /// </summary>
153  /// <param name="enumValues">
154  /// The enum values.
155  /// </param>
156  /// <returns>
157  /// <c>true</c> if the specified enum values contains all; otherwise, <c>false</c>.
158  /// </returns>
159  public bool ContainsAll(params CompositeEnum[] enumValues)
160  {
161  return enumValues.All(Contains);
162  }
163 
164  /// <summary>
165  /// Determines whether the specified <see cref="CompositeEnum"/> is equal to this instance.
166  /// </summary>
167  /// <param name="other">
168  /// The <see cref="CompositeEnum"/> to compare with this instance.
169  /// </param>
170  /// <returns>
171  /// <c>true</c> if the specified <see cref="CompositeEnum"/> is equal to this instance; otherwise, <c>false</c>.
172  /// </returns>
173  public bool Equals(CompositeEnum other)
174  {
175  if (ReferenceEquals(null, other))
176  {
177  return false;
178  }
179 
180  if (ReferenceEquals(this, other))
181  {
182  return true;
183  }
184 
185  if (other.IsFlag != IsFlag)
186  {
187  return false;
188  }
189 
190  if (Values.Count != other.Values.Count)
191  {
192  return false;
193  }
194 
195  if (Key != null && other.Key != null)
196  {
197  return Key.Equals(other.Key);
198  }
199 
200  // Optim to speed up comparison
201  if (ReferenceEquals(Values, other.Values))
202  {
203  return true;
204  }
205 
206  return Values.SetEquals(other.Values);
207  }
208 
209  /// <inheritdoc />
210  public override bool Equals(object obj)
211  {
212  if (ReferenceEquals(null, obj))
213  {
214  return false;
215  }
216 
217  if (ReferenceEquals(this, obj))
218  {
219  return true;
220  }
221 
222  if (!(obj is CompositeEnum))
223  {
224  return false;
225  }
226 
227  return Equals((CompositeEnum)obj);
228  }
229 
230  /// <inheritdoc />
231  public override int GetHashCode()
232  {
233  int hashCode = IsFlag.GetHashCode() * 397;
234  if (Key != null)
235  {
236  return hashCode ^ Key.GetHashCode() * 397;
237  }
238 
239  return Values.Aggregate(hashCode, (current, value) => current ^ value.GetHashCode() * 397);
240  }
241 
242  IEnumerator IEnumerable.GetEnumerator()
243  {
244  return GetEnumerator();
245  }
246 
247  public IEnumerator<CompositeEnum> GetEnumerator()
248  {
249  return Values.GetEnumerator();
250  }
251 
252  /// <inheritdoc />
253  public override string ToString()
254  {
255  return ToString<CompositeEnum>(null);
256  }
257 
258  /// <inheritdoc />
259  public string ToString<T>(Func<T,bool> filterEnum) where T : CompositeEnum
260  {
261  var builder = new StringBuilder();
262  bool isNext = false;
263  var filteredValues = Values.OfType<T>();
264  if (filterEnum != null)
265  {
266  filteredValues = filteredValues.Where(filterEnum);
267  }
268 
269  foreach (var value in filteredValues)
270  {
271  if (isNext)
272  {
273  builder.Append(" ");
274  }
275 
276  if (value.Key != null)
277  {
278  if (string.Empty.Equals(value.Key))
279  {
280  isNext = false;
281  }
282  else
283  {
284  builder.Append(value.DisplayName);
285  isNext = true;
286  }
287  }
288  else
289  {
290  builder.Append(value.ToString());
291  isNext = true;
292  }
293  }
294 
295  return builder.ToString();
296  }
297 
298 
299  #endregion
300 
301  #region Methods
302 
303  /// <summary>
304  /// Operators And.
305  /// </summary>
306  /// <typeparam name="T1">
307  /// The type of the 1.
308  /// </typeparam>
309  /// <param name="left">
310  /// The left.
311  /// </param>
312  /// <param name="right">
313  /// The right.
314  /// </param>
315  /// <returns>
316  /// Result of And operation
317  /// </returns>
318  public static T1 OperatorAnd<T1>(T1 left, T1 right)
319  where T1 : CompositeEnum, new()
320  {
321  var result = new T1 { IsFlag = left.IsFlag, Values = new OrderedSet<CompositeEnum>(left.Values) };
322  result.Values.IntersectWith(right.Values);
323  return result;
324  }
325 
326  /// <summary>
327  /// Operators Or.
328  /// </summary>
329  /// <typeparam name="T1">
330  /// The type of the 1.
331  /// </typeparam>
332  /// <param name="left">
333  /// The left.
334  /// </param>
335  /// <param name="right">
336  /// The right.
337  /// </param>
338  /// <returns>
339  /// Result of Or operation
340  /// </returns>
341  public static T1 OperatorOr<T1>(T1 left, T1 right)
342  where T1 : CompositeEnum, new()
343  {
344  var result = new T1 { IsFlag = left.IsFlag, Values = new OrderedSet<CompositeEnum>(left.Values) };
345  result.Values.UnionWith(right.Values);
346  return result;
347  }
348 
349  /// <summary>
350  /// Operators Xor.
351  /// </summary>
352  /// <typeparam name="T1">
353  /// The type of the 1.
354  /// </typeparam>
355  /// <param name="left">
356  /// The left.
357  /// </param>
358  /// <param name="right">
359  /// The right.
360  /// </param>
361  /// <returns>
362  /// Result of Xor operation
363  /// </returns>
364  public static T1 OperatorXor<T1>(T1 left, T1 right)
365  where T1 : CompositeEnum, new()
366  {
367  var result = new T1 { IsFlag = left.IsFlag, Values = new OrderedSet<CompositeEnum>(left.Values) };
368  result.Values.SymmetricExceptWith(right.Values);
369  return result;
370  }
371 
372  /// <summary>
373  /// Prepares the parsing for a specific enum by returning a pre-computed dictionary with all allowed mapping name =&gt; enum.
374  /// </summary>
375  /// <typeparam name="T">
376  /// Type of the enum to compute the dictionary
377  /// </typeparam>
378  /// <returns>
379  /// A pre-computed dictionary with all allowed mapping name =&gt; enum
380  /// </returns>
381  protected static StringEnumMap PrepareParsing<T>() where T : CompositeEnum
382  {
383  var map = new StringEnumMap();
384 
385  var type = typeof(T);
386  while (type != typeof(CompositeEnum))
387  {
388  foreach (var field in type.GetFields())
389  {
390  if (typeof(CompositeEnum).IsAssignableFrom(field.FieldType) && field.IsStatic)
391  {
392  var fieldValue = (CompositeEnum)field.GetValue(null);
393  if (fieldValue.Values.Count == 1)
394  {
395  var key = fieldValue.Values.FirstOrDefault();
396  if (key != null && key.Key != null && !map.ContainsKey(key.Key))
397  {
398  map.Add(key.Key, fieldValue);
399  }
400  }
401  }
402  }
403 
404  type = type.BaseType;
405  }
406 
407  return map;
408  }
409 
410  /// <inheritdoc/>
411  public override IEnumerable<Node> Childrens()
412  {
413  if (Values.Count == 0) return ChildrenList;
414 
415  ChildrenList.Clear();
416  foreach (var compositeEnum in Values)
417  {
418  if (!ReferenceEquals(this, compositeEnum) && !string.Empty.Equals(compositeEnum.Key))
419  {
420  ChildrenList.Add(compositeEnum);
421  }
422  }
423 
424  return ChildrenList;
425  }
426 
427  #endregion
428 
429  #region Operators
430 
431  /// <summary>
432  /// Implements the operator ==.
433  /// </summary>
434  /// <param name = "left">The left.</param>
435  /// <param name = "right">The right.</param>
436  /// <returns>
437  /// The result of the operator.
438  /// </returns>
439  public static bool operator ==(CompositeEnum left, CompositeEnum right)
440  {
441  return Equals(left, right);
442  }
443 
444  /// <summary>
445  /// Implements the operator !=.
446  /// </summary>
447  /// <param name = "left">The left.</param>
448  /// <param name = "right">The right.</param>
449  /// <returns>
450  /// The result of the operator.
451  /// </returns>
452  public static bool operator !=(CompositeEnum left, CompositeEnum right)
453  {
454  return !Equals(left, right);
455  }
456 
457  #endregion
458 
459  /// <summary>
460  /// Internal dictionary that provides conversion helper methods.
461  /// </summary>
462  protected class StringEnumMap : Dictionary<object, CompositeEnum>
463  {
464  #region Public Methods
465 
466  /// <summary>
467  /// Parses the name of the enum from.
468  /// </summary>
469  /// <typeparam name="T">Type of the enum</typeparam>
470  /// <param name="key">The key.</param>
471  /// <returns>
472  /// The converted enum or null otherwises
473  /// </returns>
474  public T ParseEnumFromName<T>(object key) where T : CompositeEnum, new()
475  {
476  CompositeEnum value;
477  if (!TryGetValue(key, out value))
478  {
479  throw new ArgumentException(string.Format("Unable to convert [{0}] to qualifier", key), "key");
480  //var none = new T { Key = string.Empty };
481  //none.Values.Add(none);
482  //return none;
483  }
484 
485  // If same value, than return it directly
486  if (typeof(T).IsAssignableFrom(value.GetType()))
487  {
488  return (T)value;
489  }
490 
491  return new T { IsFlag = value.IsFlag, Values = value.Values };
492  }
493 
494  #endregion
495  }
496  }
497 }
IEnumerator< CompositeEnum > GetEnumerator()
object Key
Gets or sets the key.
override IEnumerable< Node > Childrens()
Gets the child nodes. An enumeration of child nodes
CompositeEnum(object key, bool isFlag)
Initializes a new instance of the CompositeEnum class.
override bool Equals(object obj)
Internal dictionary that provides conversion helper methods.
Abstract node.
Definition: Node.cs:15
bool IsFlag
Gets a value indicating whether this instance is an enum flag.
bool ContainsAll(params CompositeEnum[] enumValues)
Determines whether the specified enum values contains all.
CompositeEnum()
Initializes a new instance of the CompositeEnum class.
bool Contains(CompositeEnum enumValue)
Determines whether [contains] [the specified enum value].
bool Equals(CompositeEnum other)
Determines whether the specified CompositeEnum is equal to this instance.
OrderedSet< CompositeEnum > Values
Gets or sets the values.
CompositeEnum(bool isFlag)
Initializes a new instance of the CompositeEnum class.
bool Contains(params CompositeEnum[] enumValues)
Determines whether [contains] [the specified enum values].