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;
}
}
}