using System.Linq.Expressions;
using System.Text;
using Microsoft.EntityFrameworkCore;
namespace Processor;
internal static class Utils
{
private static readonly Random RNG = new();
///
/// Generates a code out of this name.
///
/// The name where the code based on
/// The data class
/// The selector to check, if that key already exists. The string parameter is the current code to check.
/// The generated code
internal static async Task GenerateCode(string name, DbSet db, Expression> selector) where TDbSet : class
{
// Filter all non-alphanumeric characters from the name by allowing only A-Z, a-z, 0-9, and spaces from the ASCII table:
name = new string(name.Where(c => c is >= 'a' and <= 'z' or >= 'A' and <= 'Z' or >= '0' and <= '9' or ' ').ToArray());
// Remove any whitespaces from the element name, regardless of how many e.g. spaces the user typed:
var code = string.Join('_', name.Split(' ', StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries)).ToUpperInvariant();
//
// The Any() query want's an Expression, but we have an Expression, though.
// Therefore, we have to currying the string away:
var typeDbSet = Expression.Parameter(typeof(TDbSet), null);
var curriedSelector = Expression.Lambda>(
Expression.Invoke(selector, typeDbSet, Expression.Constant(code)),
typeDbSet
);
// Check, if this key already exists. If so, add a random number to the end of the key:
if (await db.AnyAsync(curriedSelector))
while (await db.AnyAsync(curriedSelector))
{
code += $"_{RNG.Next(1, 10_000)}";
// Due to the changed code & since the string is a constant, we have to re-currying the string away:
curriedSelector = Expression.Lambda>(
Expression.Invoke(selector, typeDbSet, Expression.Constant(code)),
typeDbSet
);
}
return code;
}
public static string MadeVerbatimStringLiteral(string text)
{
IEnumerable ConvertAll(string source)
{
foreach(var c in source)
if(c == '"')
{
yield return '"';
yield return '"';
}
else
yield return c;
}
var sb = new StringBuilder();
foreach(var c in ConvertAll(text))
sb.Append(c);
return sb.ToString();
}
}