PageRenderTime 48ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/Source/ResourceManagement.ObjectModel/RmResourceChanges.cs

#
C# | 190 lines | 149 code | 13 blank | 28 comment | 18 complexity | 39e0346e34d45588ccec340b0759daac MD5 | raw file
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Text;
  6. namespace Microsoft.ResourceManagement.ObjectModel
  7. {
  8. /// <summary>
  9. /// A transaction object monitors the changes made to an RmResource object.
  10. ///
  11. /// Use this class to check for changes when updating the Resource Management Service.
  12. /// </summary>
  13. public class RmResourceChanges : IDisposable
  14. {
  15. private RmResource rmObject;
  16. private Dictionary<RmAttributeName, RmAttributeValue> originalAttributes;
  17. public RmResource RmObject
  18. {
  19. get
  20. {
  21. return this.rmObject;
  22. }
  23. }
  24. /// <summary>
  25. /// Begins a transaction on the provided RmResource object.
  26. /// </summary>
  27. /// <param name="rmObject">The object to watch during the transaction.</param>
  28. public RmResourceChanges(RmResource rmObject)
  29. {
  30. if (rmObject == null)
  31. {
  32. throw new ArgumentNullException("rmObject");
  33. }
  34. this.rmObject = rmObject;
  35. }
  36. /// <summary>
  37. /// Returns a list of changes made to this object since the transaction began or the last call to AcceptChanges.
  38. /// </summary>
  39. /// <returns></returns>
  40. public IList<RmAttributeChange> GetChanges()
  41. {
  42. EnsureNotDisposed();
  43. lock (rmObject.Attributes)
  44. {
  45. // there was no original, so we just return an empty list
  46. if (originalAttributes == null)
  47. {
  48. return new List<RmAttributeChange>();
  49. }
  50. else
  51. {
  52. return RmResourceChanges.GetDifference(rmObject.Attributes, this.originalAttributes);
  53. }
  54. }
  55. }
  56. public void BeginChanges()
  57. {
  58. EnsureNotDisposed();
  59. lock (rmObject.attributes)
  60. {
  61. this.originalAttributes = new Dictionary<RmAttributeName, RmAttributeValue>();
  62. foreach (RmAttributeName key in rmObject.attributes.Keys)
  63. {
  64. this.originalAttributes[key] = new RmAttributeValue();
  65. RmAttributeValue value = rmObject.attributes[key];
  66. this.originalAttributes[key] = value.Clone() as RmAttributeValue;
  67. }
  68. }
  69. }
  70. /// <summary>
  71. /// Commits all of the changes made the RmResource object.
  72. ///
  73. /// GetChanges() will return an empty list immediately after this call.
  74. /// </summary>
  75. public void AcceptChanges()
  76. {
  77. EnsureNotDisposed();
  78. lock (rmObject.attributes)
  79. {
  80. this.originalAttributes = null;
  81. }
  82. }
  83. /// <summary>
  84. /// Discards all of the changes made ot the RmResource object since the transaction began or a call to AcceptChanges()
  85. /// </summary>
  86. public void DiscardChanges()
  87. {
  88. EnsureNotDisposed();
  89. lock (rmObject.attributes)
  90. {
  91. rmObject.attributes = this.originalAttributes;
  92. }
  93. }
  94. #region IDisposable Members
  95. public void Dispose()
  96. {
  97. EnsureNotDisposed();
  98. lock (rmObject.attributes)
  99. {
  100. this.originalAttributes = null;
  101. GC.SuppressFinalize(this);
  102. this.rmObject = null;
  103. }
  104. }
  105. private void EnsureNotDisposed()
  106. {
  107. if (this.rmObject == null)
  108. {
  109. throw new ObjectDisposedException("RmObjectTransaction", "The RmObjectTransaction object has already been disposed");
  110. }
  111. }
  112. #endregion
  113. #region difference calculation
  114. /// <summary>
  115. /// Returns a list of changes to make to obj1 in order for it to look like obj2.
  116. /// </summary>
  117. /// <param name="obj1">The starting object state.</param>
  118. /// <param name="obj2">The ending object state.</param>
  119. /// <returns>A list of RmAttributeChanges to apply to obj1 for it to look like obj2</returns>
  120. public static IList<RmAttributeChange> GetDifference(RmResource obj1, RmResource obj2)
  121. {
  122. if (obj1 == null)
  123. {
  124. throw new ArgumentNullException("obj1");
  125. }
  126. if (obj2 == null)
  127. {
  128. throw new ArgumentNullException("obj2");
  129. }
  130. return GetDifference(obj1.attributes, obj2.attributes);
  131. }
  132. private static IList<RmAttributeChange> GetDifference(Dictionary<RmAttributeName, RmAttributeValue> attributes1, Dictionary<RmAttributeName, RmAttributeValue> attributes2)
  133. {
  134. IList<RmAttributeChange> changedAttributes = new List<RmAttributeChange>();
  135. foreach (KeyValuePair<RmAttributeName, RmAttributeValue> item1 in attributes1)
  136. {
  137. if (attributes2.ContainsKey(item1.Key) == false)
  138. {
  139. foreach (IComparable value1 in item1.Value.Values)
  140. {
  141. changedAttributes.Add(new RmAttributeChange(item1.Key, value1, RmAttributeChangeOperation.Add));
  142. }
  143. }
  144. else
  145. {
  146. RmAttributeValue rmValue2 = attributes2[item1.Key];
  147. foreach (IComparable value1 in item1.Value.Values)
  148. {
  149. if (rmValue2.Values.Contains(value1) == false)
  150. {
  151. changedAttributes.Add(new RmAttributeChange(item1.Key, value1, RmAttributeChangeOperation.Add));
  152. }
  153. }
  154. foreach (IComparable value2 in rmValue2.Values)
  155. {
  156. if (item1.Value.Values.Contains(value2) == false)
  157. {
  158. changedAttributes.Add(new RmAttributeChange(item1.Key, value2, RmAttributeChangeOperation.Delete));
  159. }
  160. }
  161. }
  162. }
  163. foreach (KeyValuePair<RmAttributeName, RmAttributeValue> item2 in attributes2)
  164. {
  165. if (attributes1.ContainsKey(item2.Key) == false)
  166. {
  167. foreach (IComparable value2 in item2.Value.Values)
  168. {
  169. changedAttributes.Add(new RmAttributeChange(item2.Key, value2, RmAttributeChangeOperation.Delete));
  170. }
  171. }
  172. }
  173. return changedAttributes;
  174. }
  175. #endregion
  176. }
  177. }