AcUtils
A high performance abstraction layer for AccuRev
AcProperties.cs
Go to the documentation of this file.
1 
16 using System;
17 using System.Collections.Generic;
18 using System.Threading.Tasks;
19 using System.Xml.Linq;
20 
21 namespace AcUtils
22 {
23  #region enums
24 
25  public enum PropKind
29  {
32  principal,
35  stream
36  }
38  #endregion
39 
44  [Serializable]
45  public sealed class AcProperty : IFormattable, IEquatable<AcProperty>, IComparable<AcProperty>, IComparable
46  {
47  #region class variables
48  private PropKind _kind; // type of property, either "principal" or "stream"
49  private AcDepot _depot; // depot when Kind is a stream, otherwise null
50  private int _id; // stream or principal ID number
51  private string _name; // stream or principal name
52  private string _propName; // property name
53  private string _propValue; // property value
54  #endregion
55 
59  internal AcProperty() { }
60 
61  #region Equality comparison
62 
64  public bool Equals(AcProperty other)
72  {
73  if (ReferenceEquals(other, null)) return false;
74  if (ReferenceEquals(this, other)) return true;
75  var left = Tuple.Create(Kind, Depot, ID, PropName);
76  var right = Tuple.Create(other.Kind, other.Depot, other.ID, other.PropName);
77  return left.Equals(right);
78  }
79 
84  public override bool Equals(object other)
85  {
86  if (ReferenceEquals(other, null)) return false;
87  if (ReferenceEquals(this, other)) return true;
88  if (GetType() != other.GetType()) return false;
89  return this.Equals(other as AcProperty);
90  }
91 
97  public override int GetHashCode()
98  {
99  var hash = Tuple.Create(Kind, Depot, ID, PropName);
100  return hash.GetHashCode();
101  }
103  #endregion
104 
105  #region Order comparison
106 
108 
115  public int CompareTo(AcProperty other)
116  {
117  int result = 0;
118  if (AcProperty.ReferenceEquals(this, other))
119  result = 0;
120  else
121  {
122  if (Depot != null && other.Depot != null)
123  result = Depot.CompareTo(other.Depot);
124  if (result == 0)
125  result = String.Compare(Name, other.Name);
126  if (result == 0)
127  result = String.Compare(PropName, other.PropName);
128  }
129 
130  return result;
131  }
132 
139  int IComparable.CompareTo(object other)
140  {
141  if (!(other is AcProperty))
142  throw new ArgumentException("Argument is not an AcProperty", "other");
143  AcProperty o = (AcProperty)other;
144  return this.CompareTo(o);
145  }
147  #endregion
148 
152  public PropKind Kind
153  {
154  get { return _kind; }
155  internal set { _kind = value; }
156  }
157 
161  public AcDepot Depot
162  {
163  get { return _depot; }
164  internal set { _depot = value; }
165  }
166 
170  public int ID
171  {
172  get { return _id; }
173  internal set { _id = value; }
174  }
175 
179  public string Name
180  {
181  get { return _name ?? String.Empty; }
182  internal set { _name = value; }
183  }
184 
188  public string PropName
189  {
190  get { return _propName ?? String.Empty; }
191  internal set { _propName = value; }
192  }
193 
197  public string PropValue
198  {
199  get { return _propValue ?? String.Empty; }
200  internal set { _propValue = value; }
201  }
202 
203  #region ToString
204  public string ToString(string format, IFormatProvider provider)
220  {
221  if (provider != null)
222  {
223  ICustomFormatter fmt = provider.GetFormat(this.GetType()) as ICustomFormatter;
224  if (fmt != null)
225  return fmt.Format(format, this, provider);
226  }
227 
228  if (String.IsNullOrEmpty(format))
229  format = "G";
230 
231  switch (format.ToUpperInvariant())
232  {
233  case "G": // Depot stream/principal name along with the name-value property pair (default when not using a format specifier).
234  {
235  string text;
236  if (_depot == null)
237  text = $"{Name} ({ID}), {PropName}={PropValue}";
238  else
239  text = $"{Depot}, {Name} ({ID}), {PropName}={PropValue}";
240  return text;
241  }
242  case "K": // type of the property, either "principal" or "stream"
243  return Kind.ToString();
244  case "D": // depot name when property type is a stream, otherwise an empty string
245  return (Depot == null) ? String.Empty : Depot.ToString();
246  case "I": // stream or principal ID number
247  return ID.ToString();
248  case "N": // stream or principal name
249  return Name;
250  case "PN": // property name
251  return PropName;
252  case "PV": // property value
253  return PropValue;
254  default:
255  throw new FormatException($"The {format} format string is not supported.");
256  }
257  }
258 
259  // Calls ToString(string, IFormatProvider) version with a null IFormatProvider argument.
260  public string ToString(string format)
261  {
262  return ToString(format, null);
263  }
264 
265  // Calls ToString(string, IFormatProvider) version with the general format and a null IFormatProvider argument.
266  public override string ToString()
267  {
268  return ToString("G", null);
269  }
270  #endregion ToString
271  }
272 
277  [Serializable]
278  public sealed class AcProperties : List<AcProperty>
279  {
280  #region class variables
281  [NonSerialized] private readonly object _locker = new object();
282  #endregion
283 
284  #region object construction:
285 
287 
315  public AcProperties() { }
316 
328 
330  public async Task<bool> initAsync(AcDepot depot, AcStream stream = null, bool includeHidden = false)
331  {
332  bool ret = false; // assume failure
333  try
334  {
335  string cmd = null;
336  if (stream != null && includeHidden)
337  cmd = $@"getproperty -fix -s ""{stream}""";
338  else if (stream != null && !includeHidden)
339  cmd = $@"getproperty -fx -s ""{stream}""";
340  else if (includeHidden) // request is for all streams in depot including those that are hidden
341  cmd = $@"getproperty -fix -ks -p ""{depot}""";
342  else // request is for all streams except those that are hidden
343  cmd = $@"getproperty -fx -ks -p ""{depot}""";
344 
345  AcResult r = await AcCommand.runAsync(cmd).ConfigureAwait(false);
346  if (r != null && r.RetVal == 0)
347  {
348  XElement xml = XElement.Parse(r.CmdResult);
349  foreach (XElement e in xml.Elements("property"))
350  {
351  AcProperty property = new AcProperty();
352  string kind = (string)e.Attribute("kind");
353  property.Kind = (PropKind)Enum.Parse(typeof(PropKind), kind);
354  property.Depot = depot;
355  property.ID = (int)e.Attribute("streamNumber");
356  property.Name = (string)e.Attribute("streamName");
357  property.PropName = (string)e.Attribute("propertyName");
358  property.PropValue = (string)e;
359  lock (_locker) { Add(property); }
360  }
361 
362  ret = true; // operation succeeded
363  }
364  }
365 
366  catch (AcUtilsException ecx)
367  {
368  AcDebug.Log($"AcUtilsException caught and logged in AcProperties.initAsync(AcDepot, AcStream, bool){Environment.NewLine}{ecx.Message}");
369  }
370 
371  catch (Exception ecx)
372  {
373  AcDebug.Log($"Exception caught and logged in AcProperties.initAsync(AcDepot, AcStream, bool){Environment.NewLine}{ecx.Message}");
374  }
375 
376  return ret;
377  }
378 
389 
391  public async Task<bool> initAsync(string prncpl = null, bool includeHidden = false)
392  {
393  bool ret = false; // assume failure
394  try
395  {
396  string cmd = null;
397  if (!String.IsNullOrEmpty(prncpl) && includeHidden)
398  cmd = $@"getproperty -fix -u ""{prncpl}""";
399  else if (!String.IsNullOrEmpty(prncpl) && !includeHidden)
400  cmd = $@"getproperty -fx -u ""{prncpl}""";
401  else if (includeHidden) // request is for all principals including those that are hidden
402  cmd = "getproperty -fix -ku";
403  else // request is for all principals except those that are hidden
404  cmd = "getproperty -fx -ku";
405 
406  AcResult r = await AcCommand.runAsync(cmd).ConfigureAwait(false);
407  if (r != null && r.RetVal == 0)
408  {
409  XElement xml = XElement.Parse(r.CmdResult);
410  foreach (XElement e in xml.Elements("property"))
411  {
412  AcProperty property = new AcProperty();
413  string kind = (string)e.Attribute("kind");
414  property.Kind = (PropKind)Enum.Parse(typeof(PropKind), kind);
415  property.ID = (int)e.Attribute("principalNumber");
416  property.Name = (string)e.Attribute("principalName");
417  property.PropName = (string)e.Attribute("propertyName");
418  property.PropValue = (string)e;
419  lock (_locker) { Add(property); }
420  }
421 
422  ret = true; // operation succeeded
423  }
424  }
425 
426  catch (AcUtilsException ecx)
427  {
428  AcDebug.Log($"AcUtilsException caught and logged in AcProperties.initAsync(string, bool){Environment.NewLine}{ecx.Message}");
429  }
430 
431  catch (Exception ecx)
432  {
433  AcDebug.Log($"Exception caught and logged in AcProperties.initAsync(string, bool){Environment.NewLine}{ecx.Message}");
434  }
435 
436  return ret;
437  }
439  #endregion
440  }
441 }
bool Equals(AcProperty other)
IEquatable implementation to determine the equality of instances of type AcProperty. Uses Kind, depot (when Kind is stream, otherwise null), stream or principal ID number, and property name to compare instances.
Definition: AcProperties.cs:71
AccuRev program return value and command result.
Definition: AcCommand.cs:29
A property object that defines the attributes of an AccuRev property assigned to a stream or principa...
Definition: AcProperties.cs:45
override int GetHashCode()
Override appropriate for type AcProperty.
Definition: AcProperties.cs:97
int ID
Stream or principal ID number this property is assigned to.
string Name
Stream or principal name this property is assigned to.
string PropValue
Property value.
int CompareTo(AcProperty other)
Generic IComparable implementation (default) for comparing AcProperty objects. Sorts by [[depot...
A depot object that defines the attributes of an AccuRev depot.
Definition: AcDepots.cs:49
async Task< bool > initAsync(AcDepot depot, AcStream stream=null, bool includeHidden=false)
Populate this container with AcProperty objects for all streams in depot or just stream in depot...
PropKind
Type of the property, either principal or stream.
Definition: AcProperties.cs:28
A stream object that defines the attributes of an AccuRev stream. AcStream objects are instantiated d...
Definition: AcStreams.cs:74
string CmdResult
The command result (usually XML) emitted by AccuRev.
Definition: AcCommand.cs:70
int RetVal
The AccuRev program return value for the command, otherwise minus one (-1) on error.
Definition: AcCommand.cs:61
static void Log(string message, bool formatting=true)
Write the message text to STDOUT, to weekly log files located in %LOCALAPPDATA%\AcTools\Logs, and to trigger.log in the AccuRev server's ..storage\site_slice\logs folder in the case of triggers.
Definition: AcDebug.cs:378
PropKind Kind
Kind of property, either principal or stream.
async Task< bool > initAsync(string prncpl=null, bool includeHidden=false)
Populate this container with AcProperty objects for all principals or a specific principal only...
override bool Equals(object other)
Overridden to determine equality.
Definition: AcProperties.cs:84
Exception thrown when an AccuRev command fails. The AccuRev program return value is zero (0) on succe...
A container of AcProperty objects that define AccuRev properties assigned to a stream or principal by...
AccuRev command processing.
Definition: AcCommand.cs:138
static async Task< AcResult > runAsync(string command, ICmdValidate validator=null)
Run the AccuRev command asynchronously with non-blocking I/O.
Definition: AcCommand.cs:184
int CompareTo(AcDepot other)
Generic IComparable implementation (default) for comparing AcDepot objects to sort by depot name...
Definition: AcDepots.cs:211
Use to log and display error and general purpose text messages, and to save the XML param data sent b...
Definition: AcDebug.cs:100
string ToString(string format, IFormatProvider provider)
The ToString implementation.
string ToString(string format, IFormatProvider provider)
The ToString implementation.
Definition: AcDepots.cs:573
string PropName
Property name.
AcProperty()
Constructor used during AcProperties list construction. It is called internally and not by user code...
Definition: AcProperties.cs:59
AcProperties()
A container of AcProperty objects that define AccuRev properties assigned to a stream or principal by...
AcDepot Depot
Depot when Kind is stream, otherwise null.