using System; using System.Collections.Generic; using System.Linq; namespace Wayne.Lib { /// /// A simple string pattern matching used for message bus and actor system topics and addresses. /// It is used to match a address to a pattern. /// public static class Any { public static int Id = int.MinValue; public static string IdReplacement = "$"; public static string String = "*"; public static string Wildcard = "#"; public static bool IsResolvedAddress(string address) { return !address.Contains(Any.String); } public static string Convert(int id) { if (id == Id) { return IdReplacement; } return id.ToString(System.Globalization.CultureInfo.InvariantCulture); } /// /// /// /// /// /// public static int[] GetIds(string pattern, string address) { ParamGuard.AssertIsNotNull(pattern, "pattern"); ParamGuard.AssertIsNotNull(address, "address"); string[] actorAddressSplit = address.Split('.'); string[] actorAddressPatternSplit = pattern.Split('.'); if (actorAddressSplit.Length != actorAddressPatternSplit.Length) { return new int[0]; } List result = new List(); for (int i = 0; i < actorAddressSplit.Length; i++) { string actualElement = actorAddressSplit[i]; string patternElement = actorAddressPatternSplit[i]; if (actualElement != patternElement) { if (patternElement == "$") { int intResult; if (TryParseInt(actualElement, out intResult)) { result.Add(intResult); } } } } return result.ToArray(); } /// /// Tries to parse an integer just like the full framework's int.TryParse() /// /// String containing integer /// Contains the integer values if the operation is successful /// True if the parse was successful, false otherwise private static bool TryParseInt(string possibleInt, out int i) { if (!string.IsNullOrEmpty(possibleInt)) { try { if (possibleInt.All(char.IsNumber)) { i = int.Parse(possibleInt); return true; } } catch (FormatException) { } } i = 0; return false; } public static string Convert(string val) { if (val == String) return String; return val; } /// /// Address pattern format: /// * = anything within '.' characters /// # = anything /// $ = numbers /// /// /// /// public static bool Match(string address, string pattern) { ParamGuard.AssertIsNotNull(address, "address"); ParamGuard.AssertIsNotNull(pattern, "pattern"); if (pattern == Wildcard) { return true; } string[] actorAddressSplit = address.Split('.'); string[] actorAddressPatternSplit = pattern.Split('.'); if (actorAddressSplit.Length != actorAddressPatternSplit.Length) { return false; } for (int i = 0; i < actorAddressSplit.Length; i++) { string actualElement = actorAddressSplit[i]; string patternElement = actorAddressPatternSplit[i]; if (actualElement != patternElement) { switch (patternElement) { case "*": continue; case "$": if (!actualElement.All(Char.IsNumber)) { return false; } continue; default: return false; } } } return true; } } }