// Copyright © WireMock.Net
using System.Linq;
using AnyOfTypes;
using SimMetrics.Net;
using SimMetrics.Net.API;
using SimMetrics.Net.Metric;
using Stef.Validation;
using WireMock.Extensions;
using WireMock.Models;
using WireMock.Util;
namespace WireMock.Matchers;
///
/// SimMetricsMatcher
///
///
public class SimMetricsMatcher : IStringMatcher
{
private readonly AnyOf[] _patterns;
private readonly SimMetricType _simMetricType;
///
public MatchBehaviour MatchBehaviour { get; }
///
/// Initializes a new instance of the class.
///
/// The pattern.
/// The SimMetric Type
public SimMetricsMatcher(AnyOf pattern, SimMetricType simMetricType = SimMetricType.Levenstein) : this(new[] { pattern }, simMetricType)
{
}
///
/// Initializes a new instance of the class.
///
/// The match behaviour.
/// The pattern.
/// The SimMetric Type
public SimMetricsMatcher(MatchBehaviour matchBehaviour, AnyOf pattern, SimMetricType simMetricType = SimMetricType.Levenstein) : this(matchBehaviour, new[] { pattern }, simMetricType)
{
}
///
/// Initializes a new instance of the class.
///
/// The patterns.
/// The SimMetric Type
public SimMetricsMatcher(string[] patterns, SimMetricType simMetricType = SimMetricType.Levenstein) : this(MatchBehaviour.AcceptOnMatch, patterns.ToAnyOfPatterns(), simMetricType)
{
}
///
/// Initializes a new instance of the class.
///
/// The patterns.
/// The SimMetric Type
public SimMetricsMatcher(AnyOf[] patterns, SimMetricType simMetricType = SimMetricType.Levenstein) : this(MatchBehaviour.AcceptOnMatch, patterns, simMetricType)
{
}
///
/// Initializes a new instance of the class.
///
/// The match behaviour.
/// The patterns.
/// The SimMetric Type
/// The to use. (default = "Or")
public SimMetricsMatcher(
MatchBehaviour matchBehaviour,
AnyOf[] patterns,
SimMetricType simMetricType = SimMetricType.Levenstein,
MatchOperator matchOperator = MatchOperator.Average)
{
_patterns = Guard.NotNull(patterns);
_simMetricType = simMetricType;
MatchBehaviour = matchBehaviour;
MatchOperator = matchOperator;
}
///
public MatchResult IsMatch(string? input)
{
IStringMetric stringMetricType = GetStringMetricType();
var score = MatchScores.ToScore(_patterns.Select(p => stringMetricType.GetSimilarity(p.GetPattern(), input)).ToArray(), MatchOperator);
return MatchBehaviourHelper.Convert(MatchBehaviour, score);
}
///
public virtual string GetCSharpCodeArguments()
{
return $"new {Name}" +
$"(" +
$"{MatchBehaviour.GetFullyQualifiedEnumValue()}, " +
$"{MappingConverterUtils.ToCSharpCodeArguments(_patterns)}, " +
$"{_simMetricType.GetFullyQualifiedEnumValue()}, " +
$"{MatchOperator.GetFullyQualifiedEnumValue()}" +
$")";
}
private IStringMetric GetStringMetricType()
{
return _simMetricType switch
{
SimMetricType.BlockDistance => new BlockDistance(),
SimMetricType.ChapmanLengthDeviation => new ChapmanLengthDeviation(),
SimMetricType.CosineSimilarity => new CosineSimilarity(),
SimMetricType.DiceSimilarity => new DiceSimilarity(),
SimMetricType.EuclideanDistance => new EuclideanDistance(),
SimMetricType.JaccardSimilarity => new JaccardSimilarity(),
SimMetricType.Jaro => new Jaro(),
SimMetricType.JaroWinkler => new JaroWinkler(),
SimMetricType.MatchingCoefficient => new MatchingCoefficient(),
SimMetricType.MongeElkan => new MongeElkan(),
SimMetricType.NeedlemanWunch => new NeedlemanWunch(),
SimMetricType.OverlapCoefficient => new OverlapCoefficient(),
SimMetricType.QGramsDistance => new QGramsDistance(),
SimMetricType.SmithWaterman => new SmithWaterman(),
SimMetricType.SmithWatermanGotoh => new SmithWatermanGotoh(),
SimMetricType.SmithWatermanGotohWindowedAffine => new SmithWatermanGotohWindowedAffine(),
SimMetricType.ChapmanMeanLength => new ChapmanMeanLength(),
_ => new Levenstein()
};
}
///
public AnyOf[] GetPatterns()
{
return _patterns;
}
///
public MatchOperator MatchOperator { get; } = MatchOperator.Average;
///
public string Name => $"SimMetricsMatcher.{_simMetricType}";
}