Any.cs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. namespace Wayne.Lib
  5. {
  6. /// <summary>
  7. /// A simple string pattern matching used for message bus and actor system topics and addresses.
  8. /// It is used to match a address to a pattern.
  9. /// </summary>
  10. public static class Any
  11. {
  12. public static int Id = int.MinValue;
  13. public static string IdReplacement = "$";
  14. public static string String = "*";
  15. public static string Wildcard = "#";
  16. public static bool IsResolvedAddress(string address)
  17. {
  18. return !address.Contains(Any.String);
  19. }
  20. public static string Convert(int id)
  21. {
  22. if (id == Id)
  23. {
  24. return IdReplacement;
  25. }
  26. return id.ToString(System.Globalization.CultureInfo.InvariantCulture);
  27. }
  28. /// <summary>
  29. ///
  30. /// </summary>
  31. /// <param name="pattern"></param>
  32. /// <param name="address"></param>
  33. /// <returns></returns>
  34. public static int[] GetIds(string pattern, string address)
  35. {
  36. ParamGuard.AssertIsNotNull(pattern, "pattern");
  37. ParamGuard.AssertIsNotNull(address, "address");
  38. string[] actorAddressSplit = address.Split('.');
  39. string[] actorAddressPatternSplit = pattern.Split('.');
  40. if (actorAddressSplit.Length != actorAddressPatternSplit.Length)
  41. {
  42. return new int[0];
  43. }
  44. List<int> result = new List<int>();
  45. for (int i = 0; i < actorAddressSplit.Length; i++)
  46. {
  47. string actualElement = actorAddressSplit[i];
  48. string patternElement = actorAddressPatternSplit[i];
  49. if (actualElement != patternElement)
  50. {
  51. if (patternElement == "$")
  52. {
  53. int intResult;
  54. if (TryParseInt(actualElement, out intResult))
  55. {
  56. result.Add(intResult);
  57. }
  58. }
  59. }
  60. }
  61. return result.ToArray();
  62. }
  63. /// <summary>
  64. /// Tries to parse an integer just like the full framework's int.TryParse()
  65. /// </summary>
  66. /// <param name="possibleInt">String containing integer</param>
  67. /// <param name="i">Contains the integer values if the operation is successful</param>
  68. /// <returns>True if the parse was successful, false otherwise</returns>
  69. private static bool TryParseInt(string possibleInt, out int i)
  70. {
  71. if (!string.IsNullOrEmpty(possibleInt))
  72. {
  73. try
  74. {
  75. if (possibleInt.All(char.IsNumber))
  76. {
  77. i = int.Parse(possibleInt);
  78. return true;
  79. }
  80. }
  81. catch (FormatException)
  82. { }
  83. }
  84. i = 0;
  85. return false;
  86. }
  87. public static string Convert(string val)
  88. {
  89. if (val == String)
  90. return String;
  91. return val;
  92. }
  93. /// <summary>
  94. /// Address pattern format:
  95. /// * = anything within '.' characters
  96. /// # = anything
  97. /// $ = numbers
  98. /// </summary>
  99. /// <param name="address"></param>
  100. /// <param name="pattern"></param>
  101. /// <returns></returns>
  102. public static bool Match(string address, string pattern)
  103. {
  104. ParamGuard.AssertIsNotNull(address, "address");
  105. ParamGuard.AssertIsNotNull(pattern, "pattern");
  106. if (pattern == Wildcard)
  107. {
  108. return true;
  109. }
  110. string[] actorAddressSplit = address.Split('.');
  111. string[] actorAddressPatternSplit = pattern.Split('.');
  112. if (actorAddressSplit.Length != actorAddressPatternSplit.Length)
  113. {
  114. return false;
  115. }
  116. for (int i = 0; i < actorAddressSplit.Length; i++)
  117. {
  118. string actualElement = actorAddressSplit[i];
  119. string patternElement = actorAddressPatternSplit[i];
  120. if (actualElement != patternElement)
  121. {
  122. switch (patternElement)
  123. {
  124. case "*":
  125. continue;
  126. case "$":
  127. if (!actualElement.All(Char.IsNumber))
  128. {
  129. return false;
  130. }
  131. continue;
  132. default:
  133. return false;
  134. }
  135. }
  136. }
  137. return true;
  138. }
  139. }
  140. }