diff --git a/Ginger/Ginger/UserControlsLib/TextEditor/ValueExpression/ValueExpressionEditor.cs b/Ginger/Ginger/UserControlsLib/TextEditor/ValueExpression/ValueExpressionEditor.cs
index 971b4bf31a..294f2d8f9c 100644
--- a/Ginger/Ginger/UserControlsLib/TextEditor/ValueExpression/ValueExpressionEditor.cs
+++ b/Ginger/Ginger/UserControlsLib/TextEditor/ValueExpression/ValueExpressionEditor.cs
@@ -21,6 +21,7 @@ limitations under the License.
using Amdocs.Ginger.Plugin.Core;
using Ginger.Actions;
using Ginger.UserControlsLib.TextEditor.Common;
+using GingerCore;
using GingerCore.Variables;
using ICSharpCode.AvalonEdit.CodeCompletion;
using ICSharpCode.AvalonEdit.Highlighting;
@@ -193,6 +194,15 @@ private Page GetPageFor(SelectedContentArgs SelectedContentArgs)
}
}
+ if(txt.StartsWith("{MockDataExp Fun="))
+ {
+ Mockdata expParams = GingerCore.ValueExpression.GetMockDataDatasetsFunction(txt);
+ if (expParams != null)
+ {
+ p = new ValueExpressionMockDataEditorPage(mContext, SelectedContentArgs,expParams.MockDataDatasets, expParams.Function, expParams.Locale, expParams.MockExpression);
+ }
+ }
+
if (txt.StartsWith("{EnvURL App="))
{
//TODO: impl get page for Env
@@ -221,17 +231,28 @@ private Page GetPageFor(SelectedContentArgs SelectedContentArgs)
public override void UpdateSelectedContent()
{
- if (p.GetType() == typeof(ValueExpressionVariableEditorPage))
- {
- ((ValueExpressionVariableEditorPage)p).UpdateContent();
- }
- else if (p.GetType() == typeof(ActDataSourcePage))
+ try
{
- ((ActDataSourcePage)p).UpdateContent();
+ if (p.GetType() == typeof(ValueExpressionVariableEditorPage))
+ {
+ ((ValueExpressionVariableEditorPage)p).UpdateContent();
+ }
+ else if (p.GetType() == typeof(ActDataSourcePage))
+ {
+ ((ActDataSourcePage)p).UpdateContent();
+ }
+ else if (p.GetType() == typeof(ValueExpressionFlowDetailsEditorPage))
+ {
+ ((ValueExpressionFlowDetailsEditorPage)p).UpdateContent();
+ }
+ else if (p.GetType() == typeof(ValueExpressionMockDataEditorPage))
+ {
+ ((ValueExpressionMockDataEditorPage)p).UpdateContent();
+ }
}
- else if (p.GetType() == typeof(ValueExpressionFlowDetailsEditorPage))
+ catch (Exception ex)
{
- ((ValueExpressionFlowDetailsEditorPage)p).UpdateContent();
+ Reporter.ToLog(eLogLevel.ERROR, "Failed to update the selected content", ex);
}
}
diff --git a/Ginger/Ginger/UserControlsLib/TextEditor/ValueExpression/ValueExpressionMockDataEditorPage.xaml b/Ginger/Ginger/UserControlsLib/TextEditor/ValueExpression/ValueExpressionMockDataEditorPage.xaml
new file mode 100644
index 0000000000..88e4e659a0
--- /dev/null
+++ b/Ginger/Ginger/UserControlsLib/TextEditor/ValueExpression/ValueExpressionMockDataEditorPage.xaml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Ginger/Ginger/UserControlsLib/TextEditor/ValueExpression/ValueExpressionMockDataEditorPage.xaml.cs b/Ginger/Ginger/UserControlsLib/TextEditor/ValueExpression/ValueExpressionMockDataEditorPage.xaml.cs
new file mode 100644
index 0000000000..abff7f2d6e
--- /dev/null
+++ b/Ginger/Ginger/UserControlsLib/TextEditor/ValueExpression/ValueExpressionMockDataEditorPage.xaml.cs
@@ -0,0 +1,300 @@
+#region License
+/*
+Copyright © 2014-2024 European Support Limited
+
+Licensed under the Apache License, Version 2.0 (the "License")
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+#endregion
+
+using Amdocs.Ginger.Common;
+using Bogus;
+using Ginger.UserControlsLib.TextEditor.Common;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Windows.Controls;
+using GingerCore;
+using Org.BouncyCastle.Asn1.Pkcs;
+
+namespace Ginger.UserControlsLib.TextEditor.ValueExpression
+{
+ ///
+ /// Interaction logic for ValueExpressionMockDataEditorPage.xaml
+ ///
+ public partial class ValueExpressionMockDataEditorPage : Page
+ {
+ SelectedContentArgs mSelectedContentArgs;
+ Context mContext;
+ string mObj;
+ List Localelst;
+ List objClasses;
+ public ValueExpressionMockDataEditorPage(Context context, SelectedContentArgs SelectedContentArgs, string obj, string function, string Locale, string MockExpression)
+ {
+ try
+ {
+ InitializeComponent();
+ mContext = context;
+ mSelectedContentArgs = SelectedContentArgs;
+ mObj = obj;
+ int datasetStartindex = MockExpression.IndexOf('=');
+ int datasetendindex = MockExpression.IndexOf('(');
+ int localestartindex = MockExpression.IndexOf('"');
+ int localeendindex = MockExpression.IndexOf(')');
+ int functionstartindex = MockExpression.IndexOf('.');
+
+ Localelst = Localelst ?? GetLocales();
+ Type objType;
+ List methodList;
+
+ Assembly assembly = Assembly.Load("Bogus"); // or load your target assembly
+
+ string namespaceName = "Bogus.DataSets";
+
+ objClasses = objClasses ?? GetObjectClasses(assembly, namespaceName);
+
+ string objTypeName = mObj.Equals("Randomizer") ? $"Bogus.{mObj}" : $"Bogus.DataSets.{mObj}";
+ objType = assembly.GetType(objTypeName);
+
+ methodList = GetMethodsOfType(objType);
+ int CaretPossition = SelectedContentArgs.GetCaretPosition();
+ if ((datasetStartindex < CaretPossition) && (CaretPossition < datasetendindex))
+ {
+ FunctionsList.ItemsSource = objClasses.OrderBy(x => x).ToList();
+ }
+ else if ((localestartindex < CaretPossition) && (CaretPossition < localeendindex) && (!mObj.Equals("Randomizer") || !mObj.Equals("Finance")))
+ {
+ FunctionsList.ItemsSource = Localelst.OrderBy(x => x).ToList();
+ }
+ else
+ {
+ FunctionsList.ItemsSource = methodList.OrderBy(x => x).ToList();
+ }
+ }
+ catch (Exception ex)
+ {
+ Reporter.ToLog(eLogLevel.ERROR, "Failed to load ValueExpressionMockDataEditorPage", ex);
+ }
+ }
+
+
+ private static List GetLocales()
+ {
+ return Bogus.Database.GetAllLocales().ToList();
+ }
+
+ private static List GetObjectClasses(Assembly assembly, string namespaceName)
+ {
+ Type[] types = assembly.GetTypes();
+ List objclass = types.Where(t => t.Namespace == namespaceName && typeof(DataSet).IsAssignableFrom(t) && t != typeof(DataSet) && t.FullName.Contains(namespaceName))
+ .Select(x => x.Name)
+ .ToList();
+ objclass.Add("Randomizer");
+ return objclass;
+ }
+
+ private static List GetMethodsOfType(Type objType)
+ {
+ List methodList = new List();
+
+ if (objType != null)
+ {
+ MethodInfo[] methods = objType.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
+
+ if (methods != null)
+ {
+ var excludedMethods = GetExcludedMethods(objType.ToString());
+ var groupedMethods = methods.GroupBy(m => m.Name);
+ foreach (var methodGroup in groupedMethods)
+ {
+ foreach (MethodInfo method in methodGroup)
+ {
+ if (excludedMethods.Contains(method.Name))
+ {
+ continue;
+ }
+ string parameters = string.Join(", ", method.GetParameters().Select(p => FormatParameter(p)));
+
+ string functionString = $"{method.Name}({parameters})";
+ methodList.Add(functionString);
+ }
+ }
+ }
+ }
+
+ return methodList;
+ }
+
+ private static HashSet GetExcludedMethods(string objType)
+ {
+ return objType switch
+ {
+ "Bogus.Randomizer" => new HashSet { "EnumValues", "WeightedRandom", "ArrayElement", "ArrayElements", "ListItem", "ListItems", "ReplaceSymbols" },
+ "Bogus.DataSets.Date" => new HashSet { "BetweenTimeOnly" },
+ _ => new HashSet()
+ };
+ }
+
+ private static string FormatParameter(ParameterInfo parameter)
+ {
+ string paramType = parameter.ParameterType.Name;
+ string paramName = parameter.Name;
+ bool hasDefaultValue = parameter.HasDefaultValue;
+ object defaultValue = hasDefaultValue ? $"{FormatDefaultValue(parameter.DefaultValue)}" : SetDefaultValue(parameter);
+ return $"{defaultValue}";
+
+ }
+
+ private static object SetDefaultValue(ParameterInfo parameter)
+ {
+ Type parameterType = parameter.ParameterType;
+
+ return parameterType switch
+ {
+ Type type when type == typeof(DateTime) && parameter.Name.Equals("start") => "Past(1)",
+ Type type when type == typeof(DateTime) && parameter.Name.Equals("end") => "Future(1)",
+
+ Type type when type == typeof(DateOnly) && parameter.Name.Equals("start") => "PastDateOnly(1)",
+ Type type when type == typeof(DateOnly) && parameter.Name.Equals("end") => "FutureDateOnly(1)",
+
+ Type type when type == typeof(DateTimeOffset) && parameter.Name.Equals("start") => "PastOffset(1)",
+ Type type when type == typeof(DateTimeOffset) && parameter.Name.Equals("end") => "FutureOffset(1)",
+
+ Type type when type == typeof(Array) => "[1,2,3,4]",
+
+ Type type when type == typeof(List) => "[1,2,3,4,5]",
+
+ Type type when type == typeof(string) => parameter.Name switch
+ {
+ "format" => "'12#34'",
+ "symbol" => "'#'",
+ _ => "'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"
+ },
+
+ _ => GetDefaultForType(parameterType)
+ };
+ }
+
+ public static T[] CreateArrayWithDefaultValues(int length, T defaultValue)
+ {
+ T[] array = new T[length];
+ for (int i = 0; i < length; i++)
+ {
+ array[i] = defaultValue;
+ }
+ return array;
+ }
+
+ private static object GetDefaultForType(Type type)
+ {
+ return type.IsValueType ? Activator.CreateInstance(type) : null;
+ }
+
+ private static string FormatDefaultValue(object defaultValue)
+ {
+ switch (defaultValue)
+ {
+ case null:
+ return "null";
+ case string s:
+ return $"\"{s}\"";
+ case char c:
+ return $"'{c}'";
+ case bool b:
+ return b.ToString().ToLower();
+ default:
+ return defaultValue.ToString();
+ }
+ }
+ public void UpdateContent()
+ {
+ try
+ {
+ string selectedItem = (string)FunctionsList.SelectedItem;
+ string initialText = mSelectedContentArgs.TextEditor.Text.Substring(0, mSelectedContentArgs.StartPos);
+
+ // Parsing the text editor content
+ string objStr, functions, Locale;
+ Mockdata expParams = GingerCore.ValueExpression.GetMockDataDatasetsFunction(mSelectedContentArgs.TextEditor.Text);
+
+ string editorText = mSelectedContentArgs.TextEditor.Text;
+
+ int caretPosition = mSelectedContentArgs.GetCaretPosition();
+ string resultText = BuildResultText(selectedItem, expParams.MockDataDatasets, expParams.Locale, expParams.Function, caretPosition, expParams.DatasetStartIndex, expParams.DatasetEndIndex, expParams.LocaleStartIndex, expParams.LocaleEndIndex);
+
+ // Append the remaining text and update the text editor content
+ resultText += editorText.Substring(mSelectedContentArgs.EndPos + 1);
+ mSelectedContentArgs.TextEditor.Text = resultText;
+ }
+ catch(Exception ex)
+ {
+ Reporter.ToLog(eLogLevel.ERROR, "Failed to update content in ValueExpressionMockDataEditorPage", ex);
+ }
+ }
+
+ static string ExtractSubstring(string text, int startIndex, int length)
+ {
+ return text.Substring(startIndex, length);
+ }
+
+ static string BuildResultText(string selectedItem, string objStr, string locale, string functions, int caretPosition, int datasetStartIndex, int datasetEndIndex, int localeStartIndex, int localeEndIndex)
+ {
+ string resultText = string.Empty;
+ bool isWithinDataset = datasetStartIndex < caretPosition && caretPosition < datasetEndIndex;
+ bool isWithinLocale = localeStartIndex < caretPosition && caretPosition < localeEndIndex;
+
+ if (objStr.Equals("Randomizer") || objStr.Equals("Finance"))
+ {
+ resultText += isWithinDataset
+ ? GenerateResultText(selectedItem, "Bogus", isWithinDataset)
+ : "{MockDataExp Fun=" + objStr + "()." + selectedItem + ";}";
+ }
+ else
+ {
+ if (isWithinDataset)
+ {
+ resultText += GenerateResultText(selectedItem, "Bogus", isWithinDataset, locale);
+ }
+ else if (isWithinLocale)
+ {
+ resultText += "{MockDataExp Fun=" + objStr + "(@\"" + selectedItem + "\")." + functions + "();}";
+ }
+ else
+ {
+ resultText += "{MockDataExp Fun=" + objStr + "(@\"" + locale + "\")." + selectedItem + ";}";
+ }
+ }
+
+ return resultText;
+ }
+
+ private static string GenerateResultText(string selectedItem, string baseNamespace, bool isWithinDataset, string locale = null)
+ {
+ Assembly assembly = Assembly.Load("Bogus");
+ string objTypeName = selectedItem.Equals("Randomizer") ? $"{baseNamespace}.{selectedItem}" : $"{baseNamespace}.DataSets.{selectedItem}";
+ Type objType = assembly.GetType(objTypeName);
+
+ List methodList = GetMethodsOfType(objType);
+ string methodCall = methodList.FirstOrDefault();
+
+ if (locale == null)
+ {
+ return "{MockDataExp Fun=" + selectedItem + "()." + methodCall + ";}";
+ }
+ else
+ {
+ return "{MockDataExp Fun=" + selectedItem + "(@\"" + locale + "\")." + methodCall + ";}";
+ }
+ }
+ }
+}
diff --git a/Ginger/GingerCoreNET/RosLynLib/CodeProcessor.cs b/Ginger/GingerCoreNET/RosLynLib/CodeProcessor.cs
index 78bc229c8f..71c514aa7c 100644
--- a/Ginger/GingerCoreNET/RosLynLib/CodeProcessor.cs
+++ b/Ginger/GingerCoreNET/RosLynLib/CodeProcessor.cs
@@ -343,7 +343,14 @@ public static string GetBogusExpressionEvaluteResult(string expression, out stri
/// Handles scenarios with special case like Between function have inbuilt function as parameter and constructs expressions accordingly
if (expressionlist[1].Contains("Past") && expressionlist[1].Contains("Future"))
{
- expressionlist[1] = expressionlist[1].Replace(Parameter[0], $"Result.{Parameter[0]}").Replace(Parameter[1], $"Result.{Parameter[1]}");
+ if (expressionlist[1].Contains("BetweenTimeOnly"))
+ {
+ expressionlist[1] = expressionlist[1].Replace(Parameter[0], $"TimeOnly.FromDateTime(Result.{Parameter[0]})").Replace(Parameter[1], $"TimeOnly.FromDateTime(Result.{Parameter[1]})");
+ }
+ else
+ {
+ expressionlist[1] = expressionlist[1].Replace(Parameter[0], $"Result.{Parameter[0]}").Replace(Parameter[1], $"Result.{Parameter[1]}");
+ }
}
expression = $"var Result = new Bogus.DataSets.{expressionlist[0]}; return Result.{expressionlist[1]}";
}
@@ -381,7 +388,7 @@ public static string GetBogusExpressionEvaluteResult(string expression, out stri
}
catch (Exception e)
{
- Reporter.ToLog(eLogLevel.DEBUG, expression + System.Environment.NewLine + " not a valid Bogus data generate expression to evaluate", e);
+ Reporter.ToLog(eLogLevel.ERROR, expression + System.Environment.NewLine + " not a valid Bogus data generate expression to evaluate", e);
}
return evalresult;
}
diff --git a/Ginger/GingerCoreNET/ValueExpressionLib/ValueExpression.cs b/Ginger/GingerCoreNET/ValueExpressionLib/ValueExpression.cs
index 38d59706b4..e285e7aaa9 100644
--- a/Ginger/GingerCoreNET/ValueExpressionLib/ValueExpression.cs
+++ b/Ginger/GingerCoreNET/ValueExpressionLib/ValueExpression.cs
@@ -347,7 +347,6 @@ public enum eFlowDetailsObjects
{
Environment, Runset, Runner, BusinessFlow, ActivitiesGroup, Activity, Action, PreviousBusinessFlow, PreviousActivity, PreviousAction, LastFailedAction, ErrorHandlerOriginActivitiesGroup, ErrorHandlerOriginActivity, ErrorHandlerOriginAction, LastFailedBusinessFlow, LastFailedActivity, Solution
}
-
public static Tuple GetFlowDetailsParams(string flowDetailsExpression)
{
try
@@ -375,6 +374,60 @@ public static Tuple GetFlowDetailsParams(string flo
}
}
+ public static Mockdata GetMockDataDatasetsFunction(string MockDataExpression)
+ {
+ try
+ {
+ string objStr, functions, Locale;
+ int DatasetStartIndex, DatasetEndIndex, LocaleStartIndex, LocaleEndIndex;
+ MockdataExpressionExtract(MockDataExpression, out objStr, out functions, out Locale,out DatasetStartIndex,out DatasetEndIndex,out LocaleStartIndex,out LocaleEndIndex);
+ Mockdata mockdata = new();
+ mockdata.MockDataDatasets = objStr;
+ mockdata.Locale = Locale;
+ mockdata.Function = functions;
+ mockdata.MockExpression = MockDataExpression;
+ mockdata.DatasetStartIndex = DatasetStartIndex;
+ mockdata.DatasetEndIndex = DatasetEndIndex;
+ mockdata.LocaleStartIndex = LocaleStartIndex;
+ mockdata.LocaleEndIndex = LocaleEndIndex;
+ return mockdata;
+ }
+ catch (Exception ex)
+ {
+ Reporter.ToLog(eLogLevel.ERROR, string.Format("Failed to evaluate flow details expression '{0}' due to wrong format", MockDataExpression));
+ return null;
+ }
+ }
+ ///
+ /// This method extracts specific parts from the MockDataExpression string.
+ /// It initializes several string variables and then uses indices to parse substrings,
+ /// assigning these substrings to the initialized variables.
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// Index of '=' in MockDataExpression.
+ /// Index of '(' in MockDataExpression.
+ /// Index of '"' in MockDataExpression.
+ /// Index of ')' in MockDataExpression.
+ private static void MockdataExpressionExtract(string MockDataExpression, out string objStr, out string functions, out string Locale, out int DatasetStartIndex, out int DatasetEndIndex, out int LocaleStartIndex, out int LocaleEndIndex)
+ {
+ objStr = string.Empty;
+ functions = string.Empty;
+ Locale = string.Empty;
+ DatasetStartIndex = MockDataExpression.IndexOf('=');
+ DatasetEndIndex = MockDataExpression.IndexOf('(');
+ LocaleStartIndex = MockDataExpression.IndexOf('"');
+ LocaleEndIndex = MockDataExpression.IndexOf(')');
+ int functionstartindex = MockDataExpression.IndexOf('.');
+ string funsubstring = MockDataExpression.Substring(functionstartindex + 1);
+ int functionendindex = funsubstring.IndexOf('(');
+ Locale = MockDataExpression.Substring(LocaleStartIndex + 1, LocaleEndIndex - 2 - LocaleStartIndex);
+ objStr = MockDataExpression.Substring(DatasetStartIndex + 1, DatasetEndIndex - 1 - DatasetStartIndex);
+ functions = funsubstring.Substring(0, functionendindex).Replace("\"", "").Trim();
+ }
+
private void ReplaceFlowDetails(string flowDetailsExpression)
{
eFlowDetailsObjects obj;
@@ -1804,4 +1857,26 @@ public static string Calculate(ProjEnvironment ProjEnvironment, BusinessFlow Bus
return VE.ValueCalculated;
}
}
+
+ public class Mockdata
+ {
+ public string MockDataDatasets { get; set; }
+
+ public string Locale { get; set; }
+
+ public string Function { get; set; }
+
+ public string MockExpression { get; set; }
+
+ public int DatasetStartIndex { get; set; }
+
+ public int DatasetEndIndex { get; set; }
+
+ public int LocaleStartIndex { get; set; }
+
+ public int LocaleEndIndex { get; set; }
+
+ public int FunctionStartIndex { get; set; }
+
+ }
}