diff --git a/F4SDM42WebApi/F4SD - M42WebApi.csproj b/F4SDM42WebApi/F4SD - M42WebApi.csproj
index 9e3939e..cf4d2dc 100644
--- a/F4SDM42WebApi/F4SD - M42WebApi.csproj
+++ b/F4SDM42WebApi/F4SD - M42WebApi.csproj
@@ -13,7 +13,7 @@
false
6673a25d-33d6-4072-91d9-abed4be1a966
C4ITF4SD*.*
- 1.4.0.23
+ 1.4.0.24
true
diff --git a/F4SDM42WebApi/F4SDHelperService.cs b/F4SDM42WebApi/F4SDHelperService.cs
index 6dcb390..a37e549 100644
--- a/F4SDM42WebApi/F4SDHelperService.cs
+++ b/F4SDM42WebApi/F4SDHelperService.cs
@@ -1408,15 +1408,15 @@ namespace C4IT.F4SD
{
await Task.Delay(0);
List journalEntries = new List();
- var entries = F4SDM42WebApiController.defaultInstance.GetJournalService().GetJournalList(activityEOID, false, 0, 50, "{2}", 120);
- LogEntry($"{entries.Length} Journal entries found for ObjectID={activityEOID}", LogLevels.Debug);
- for (int i = 0; i < entries.Length; i++)
+ var entries = LoadJournalEntries(activityEOID);
+ LogEntry($"{entries.Count} Journal entries found for ObjectID={activityEOID}", LogLevels.Debug);
+ for (int i = 0; i < entries.Count; i++)
{
Matrix42.Contracts.Platform.Data.JournalEntryInfo item = entries[i];
var text = item.Text ?? string.Empty;
var createdDate = item.CreatedDate ?? DateTime.MinValue;
- LogEntry($"Journal entry {i + 1}/{entries.Length}: ID={item.Id}, CreatedDate={createdDate}, CreatedBy={item.Creator}, Header={item.Header}", LogLevels.Debug);
+ LogEntry($"Journal entry {i + 1}/{entries.Count}: ID={item.Id}, CreatedDate={createdDate}, CreatedBy={item.Creator}, Header={item.Header}", LogLevels.Debug);
journalEntries.Add(new cTicketJournalItem()
{
JournalId = item.Id,
@@ -1446,6 +1446,125 @@ namespace C4IT.F4SD
}
}
+ private static IReadOnlyList LoadJournalEntries(Guid activityEOID)
+ {
+ var journalService = F4SDM42WebApiController.defaultInstance.GetJournalService();
+ var serviceType = journalService.GetType();
+ var objectLinkTemplate = "{2}";
+ var methods = serviceType
+ .GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
+ .Where(IsJournalReaderMethod)
+ .OrderByDescending(method => method.GetParameters().Length)
+ .ToList();
+
+ foreach (var method in methods)
+ {
+ if (!TryBuildJournalListArguments(method, activityEOID, objectLinkTemplate, out var arguments))
+ continue;
+
+ try
+ {
+ var result = method.Invoke(journalService, arguments);
+ if (result is Matrix42.Contracts.Platform.Data.JournalEntryInfo[] arrayResult)
+ return arrayResult;
+
+ if (result is IEnumerable enumerableResult)
+ return enumerableResult.ToList();
+
+ throw new MissingMethodException($"IJournalService.GetJournalList returned unsupported type '{result?.GetType().FullName ?? ""}'.");
+ }
+ catch (TargetInvocationException ex) when (ex.InnerException != null)
+ {
+ throw ex.InnerException;
+ }
+ }
+
+ throw new MissingMethodException($"No compatible IJournalService.GetJournalList overload was found on '{serviceType.FullName}'. Available overloads: {string.Join("; ", methods.Select(FormatMethodSignature))}");
+ }
+
+ private static bool IsJournalReaderMethod(MethodInfo method)
+ {
+ var methodName = method.Name;
+ if (methodName.Contains("."))
+ methodName = methodName.Substring(methodName.LastIndexOf(".", StringComparison.Ordinal) + 1);
+
+ if (!(methodName.StartsWith("Get", StringComparison.OrdinalIgnoreCase) || methodName.StartsWith("Load", StringComparison.OrdinalIgnoreCase)))
+ return false;
+
+ if (!methodName.Contains("Journal", StringComparison.OrdinalIgnoreCase))
+ return false;
+
+ if (!method.GetParameters().Any(parameter => parameter.ParameterType == typeof(Guid)))
+ return false;
+
+ var returnType = method.ReturnType;
+ if (returnType.IsArray)
+ return returnType.GetElementType()?.FullName == typeof(Matrix42.Contracts.Platform.Data.JournalEntryInfo).FullName;
+
+ if (returnType.FullName == typeof(Matrix42.Contracts.Platform.Data.JournalEntryInfo).FullName)
+ return true;
+
+ return returnType.GetInterfaces()
+ .Where(type => type.IsGenericType)
+ .Select(type => type.GetGenericArguments().FirstOrDefault())
+ .Any(type => type?.FullName == typeof(Matrix42.Contracts.Platform.Data.JournalEntryInfo).FullName);
+ }
+
+ private static bool TryBuildJournalListArguments(MethodInfo method, Guid activityEOID, string objectLinkTemplate, out object[] arguments)
+ {
+ var parameters = method.GetParameters();
+ arguments = new object[parameters.Length];
+
+ for (int i = 0; i < parameters.Length; i++)
+ {
+ var parameter = parameters[i];
+ var parameterType = parameter.ParameterType;
+ var parameterName = parameter.Name ?? string.Empty;
+ var lowerName = parameterName.ToLowerInvariant();
+
+ if (parameterType == typeof(Guid))
+ {
+ arguments[i] = activityEOID;
+ }
+ else if (parameterType == typeof(bool))
+ {
+ arguments[i] = false;
+ }
+ else if (parameterType == typeof(int))
+ {
+ if (lowerName.Contains("time"))
+ arguments[i] = 120;
+ else if (lowerName.Contains("count") || lowerName.Contains("take") || lowerName.Contains("limit") || lowerName.Contains("size"))
+ arguments[i] = 50;
+ else
+ arguments[i] = 0;
+ }
+ else if (parameterType == typeof(string))
+ {
+ arguments[i] = lowerName.Contains("template") || lowerName.Contains("link") ? objectLinkTemplate : null;
+ }
+ else if (parameterType == typeof(string[]))
+ {
+ arguments[i] = null;
+ }
+ else if (parameter.HasDefaultValue)
+ {
+ arguments[i] = parameter.DefaultValue;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private static string FormatMethodSignature(MethodInfo method)
+ {
+ return $"{method.ReturnType.FullName} {method.Name}({string.Join(", ", method.GetParameters().Select(parameter => $"{parameter.ParameterType.FullName} {parameter.Name}"))})";
+ }
+
internal async Task updateActivitySolution(Guid objectId, string solutionHtml)
{