feat(configmanager): add RegexTransformerViewModel
Implements ViewModel for Regex transformer editor with: - Column, Pattern, Replacement, IgnoreCase, NonMatchBehavior properties - Mode toggle between Find & Replace and Match & Extract - Live test/preview functionality with error handling
This commit is contained in:
+273
@@ -1,5 +1,6 @@
|
||||
using JdeScoping.ConfigManager.Models;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace JdeScoping.ConfigManager.ViewModels.PipelineSteps;
|
||||
@@ -278,6 +279,278 @@ public class JdeDateTransformerViewModel : TransformerStepViewModelBase
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// View model for Regex transformer.
|
||||
/// </summary>
|
||||
public class RegexTransformerViewModel : TransformerStepViewModelBase
|
||||
{
|
||||
private string _columnName = string.Empty;
|
||||
private string _pattern = string.Empty;
|
||||
private string? _replacement = string.Empty;
|
||||
private bool _isFindReplaceMode = true;
|
||||
private bool _ignoreCase;
|
||||
private NonMatchBehavior _nonMatchBehavior = NonMatchBehavior.KeepOriginal;
|
||||
|
||||
// Test feature fields
|
||||
private string _testInput = string.Empty;
|
||||
private string _testResultValue = string.Empty;
|
||||
private string _testResultLabel = string.Empty;
|
||||
private string _testResultIcon = string.Empty;
|
||||
private string _testResultBackground = string.Empty;
|
||||
private bool _hasTestResult;
|
||||
private bool _hasTestError;
|
||||
private string _testErrorMessage = string.Empty;
|
||||
|
||||
public RegexTransformerViewModel(TransformerModel model, Action onChanged) : base(onChanged)
|
||||
{
|
||||
_columnName = model.ColumnName ?? string.Empty;
|
||||
_pattern = model.Pattern ?? string.Empty;
|
||||
_replacement = model.Replacement;
|
||||
_isFindReplaceMode = model.Replacement != null;
|
||||
_ignoreCase = model.IgnoreCase;
|
||||
_nonMatchBehavior = model.NonMatchBehavior;
|
||||
TestPatternCommand = new RelayCommand(ExecuteTestPattern);
|
||||
}
|
||||
|
||||
public RegexTransformerViewModel(Action onChanged) : base(onChanged)
|
||||
{
|
||||
TestPatternCommand = new RelayCommand(ExecuteTestPattern);
|
||||
}
|
||||
|
||||
public override string TransformerType => "Regex";
|
||||
public override string DisplayName => "Regex Transform";
|
||||
public override string Icon => ""; // mdi-regex
|
||||
public override string Summary => !string.IsNullOrEmpty(_columnName)
|
||||
? $"{_columnName}: {(_isFindReplaceMode ? "Replace" : "Extract")}"
|
||||
: "Configure...";
|
||||
|
||||
/// <summary>Gets or sets the column name to transform.</summary>
|
||||
public string ColumnName
|
||||
{
|
||||
get => _columnName;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _columnName, value ?? string.Empty))
|
||||
{
|
||||
OnPropertyChanged(nameof(Summary));
|
||||
NotifyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Gets or sets the regex pattern.</summary>
|
||||
public string Pattern
|
||||
{
|
||||
get => _pattern;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _pattern, value ?? string.Empty))
|
||||
{
|
||||
ClearTestResult();
|
||||
NotifyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Gets or sets the replacement string (Find & Replace mode).</summary>
|
||||
public string? Replacement
|
||||
{
|
||||
get => _replacement;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _replacement, value))
|
||||
{
|
||||
ClearTestResult();
|
||||
NotifyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Gets or sets whether Find & Replace mode is active.</summary>
|
||||
public bool IsFindReplaceMode
|
||||
{
|
||||
get => _isFindReplaceMode;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _isFindReplaceMode, value))
|
||||
{
|
||||
OnPropertyChanged(nameof(IsMatchExtractMode));
|
||||
OnPropertyChanged(nameof(PatternHelpText));
|
||||
OnPropertyChanged(nameof(Summary));
|
||||
ClearTestResult();
|
||||
NotifyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Gets or sets whether Match & Extract mode is active.</summary>
|
||||
public bool IsMatchExtractMode
|
||||
{
|
||||
get => !_isFindReplaceMode;
|
||||
set => IsFindReplaceMode = !value;
|
||||
}
|
||||
|
||||
/// <summary>Gets the help text for the pattern field based on current mode.</summary>
|
||||
public string PatternHelpText => _isFindReplaceMode
|
||||
? "Pattern to search for in the column value"
|
||||
: "Pattern with capture group - first group (parentheses) will be extracted";
|
||||
|
||||
/// <summary>Gets or sets whether matching is case-insensitive.</summary>
|
||||
public bool IgnoreCase
|
||||
{
|
||||
get => _ignoreCase;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _ignoreCase, value))
|
||||
{
|
||||
ClearTestResult();
|
||||
NotifyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Gets or sets the behavior when pattern doesn't match.</summary>
|
||||
public NonMatchBehavior NonMatchBehavior
|
||||
{
|
||||
get => _nonMatchBehavior;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _nonMatchBehavior, value))
|
||||
{
|
||||
ClearTestResult();
|
||||
NotifyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test feature properties
|
||||
public string TestInput
|
||||
{
|
||||
get => _testInput;
|
||||
set => SetProperty(ref _testInput, value ?? string.Empty);
|
||||
}
|
||||
|
||||
public string TestResultValue
|
||||
{
|
||||
get => _testResultValue;
|
||||
set => SetProperty(ref _testResultValue, value);
|
||||
}
|
||||
|
||||
public string TestResultLabel
|
||||
{
|
||||
get => _testResultLabel;
|
||||
set => SetProperty(ref _testResultLabel, value);
|
||||
}
|
||||
|
||||
public string TestResultIcon
|
||||
{
|
||||
get => _testResultIcon;
|
||||
set => SetProperty(ref _testResultIcon, value);
|
||||
}
|
||||
|
||||
public string TestResultBackground
|
||||
{
|
||||
get => _testResultBackground;
|
||||
set => SetProperty(ref _testResultBackground, value);
|
||||
}
|
||||
|
||||
public bool HasTestResult
|
||||
{
|
||||
get => _hasTestResult;
|
||||
set => SetProperty(ref _hasTestResult, value);
|
||||
}
|
||||
|
||||
public bool HasTestError
|
||||
{
|
||||
get => _hasTestError;
|
||||
set => SetProperty(ref _hasTestError, value);
|
||||
}
|
||||
|
||||
public string TestErrorMessage
|
||||
{
|
||||
get => _testErrorMessage;
|
||||
set => SetProperty(ref _testErrorMessage, value);
|
||||
}
|
||||
|
||||
public ICommand TestPatternCommand { get; }
|
||||
|
||||
private void ExecuteTestPattern()
|
||||
{
|
||||
ClearTestResult();
|
||||
|
||||
if (string.IsNullOrEmpty(_pattern))
|
||||
{
|
||||
HasTestError = true;
|
||||
TestErrorMessage = "Pattern is required";
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var options = _ignoreCase ? RegexOptions.IgnoreCase : RegexOptions.None;
|
||||
var regex = new Regex(_pattern, options);
|
||||
|
||||
string result;
|
||||
bool matched;
|
||||
|
||||
if (_isFindReplaceMode)
|
||||
{
|
||||
result = regex.Replace(_testInput, _replacement ?? string.Empty);
|
||||
matched = regex.IsMatch(_testInput);
|
||||
}
|
||||
else
|
||||
{
|
||||
var match = regex.Match(_testInput);
|
||||
if (match.Success && match.Groups.Count > 1)
|
||||
{
|
||||
result = match.Groups[1].Value;
|
||||
matched = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
matched = false;
|
||||
result = _nonMatchBehavior switch
|
||||
{
|
||||
NonMatchBehavior.ReturnNull => "(null)",
|
||||
NonMatchBehavior.ReturnEmpty => "(empty)",
|
||||
_ => _testInput
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
HasTestResult = true;
|
||||
TestResultValue = result;
|
||||
TestResultLabel = matched ? "Output" : "No Match";
|
||||
TestResultIcon = matched ? "✓" : "—";
|
||||
TestResultBackground = matched ? "#22C55E" : "#F59E0B";
|
||||
}
|
||||
catch (RegexParseException ex)
|
||||
{
|
||||
HasTestError = true;
|
||||
TestErrorMessage = ex.Message;
|
||||
}
|
||||
}
|
||||
|
||||
private void ClearTestResult()
|
||||
{
|
||||
HasTestResult = false;
|
||||
HasTestError = false;
|
||||
TestResultValue = string.Empty;
|
||||
TestResultLabel = string.Empty;
|
||||
TestErrorMessage = string.Empty;
|
||||
}
|
||||
|
||||
public override TransformerModel ToModel() => new()
|
||||
{
|
||||
Type = TransformerType,
|
||||
ColumnName = _columnName,
|
||||
Pattern = _pattern,
|
||||
Replacement = _isFindReplaceMode ? _replacement : null,
|
||||
IgnoreCase = _ignoreCase,
|
||||
NonMatchBehavior = _nonMatchBehavior
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Factory methods for creating transformer view models.
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user