Files
richard-churchman bc66cd80e3 Expanded Inline Script Invocation Coverage and Implemented Activation Rule Chaining
* Updated documentation to include Inline Script events and Activation Rule Chaining concepts.
* Included Activation Rules in Activation Completions to make them available.
* Modified activation rule signatures to include match keys for facilitation.
* Updated Gateway Rule Priority to support double type, including changes in migrations and POCOs.
* Updated tree to ensure entities are listed by Priority when Priority exists in the entity.
* Included Priority in Activation Rule user interface, POCOs, and migrations; ensured invocation and synchronization preserve order for evaluation sequence to support rule chaining.
* Updated completions to support Activation Rules and Activation Rule chaining.
* Improved delegate compilation to avoid reflection during invocation; delegates are now compiled during synchronization, eliminating reflection usage during invocation for real-time processing.
* Created event attributes to direct matching of Inline Scripts, including matching properties given event context (to restrict to a single Activation Rule, for example).
* Separated ExecuteAsync attributes from property attributes in the solution for better organization.
* Mapped Inline Script property and method attributes during synchronization to avoid reflection during invocation.
* Removed parallel for loops and locks in Activation Rule processing to support chaining.
* Modified reflection wrapper for Inline Scripts to eliminate reflection by compiling delegates during synchronization.
* Minor refactoring and variable renaming.
* Updated Inline Script interface to mandate bool return value in ExecuteAsync method.
* Updated rule parser to support evaluation of exists activation rule match for chaining support.
* Updated sandbox code for new Inline Script format.
* Corrected some spelling in documentation.
2026-02-12 12:51:52 +02:00

175 lines
7.8 KiB
C#

/* Copyright (C) 2022-present Jube Holdings Limited.
*
* This file is part of Jube™ software.
*
* Jube™ is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License
* as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
* Jube™ is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
* You should have received a copy of the GNU Affero General Public License along with Jube™. If not,
* see <https://www.gnu.org/licenses/>.
*/
namespace Jube.Engine.EntityAnalysisModelInvoke.Context.Extensions.ReflectionHelpers
{
using System;
using System.Threading.Tasks;
using Data.Poco;
using EntityAnalysisModelInlineScript=EntityAnalysisModelManager.EntityAnalysisModel.Models.Models.EntityAnalysisModelInlineScript;
public static class ReflectInlineScriptHelper
{
public static async Task<bool> ExecuteAsync(EntityAnalysisModelInlineScript.EntityAnalysisModelInlineScript entityAnalysisModelInlineScript, Context context)
{
var instance = entityAnalysisModelInlineScript.ActivatorDelegate();
try
{
if (!await entityAnalysisModelInlineScript.ExecuteAsyncDelegate(instance, context))
{
return false;
}
}
catch (Exception ex)
{
context.Log.Info($"Error executing Inline Script {entityAnalysisModelInlineScript.Id}:", ex);
return true;
}
foreach (var prop in entityAnalysisModelInlineScript.EntityAnalysisModelInlineScriptPropertyAttributes)
{
try
{
if (instance == null)
{
continue;
}
var value = prop.Value.GetValueDelegate(instance);
if (prop.Value.PropertyType != typeof(string)
&& prop.Value.PropertyType != typeof(int)
&& prop.Value.PropertyType != typeof(bool)
&& prop.Value.PropertyType != typeof(DateTime)
&& prop.Value.PropertyType != typeof(double))
{
continue;
}
switch (value)
{
case string s:
context.EntityAnalysisModelInstanceEntryPayload.Payload.TryAdd(prop.Key, s);
if (prop.Value.ReportTable)
{
context.EntityAnalysisModelInstanceEntryPayload.ArchiveKeys.Add(new ArchiveKey
{
ProcessingTypeId = 1,
Key = prop.Key,
KeyValueString = value == null ? null : Convert.ToString(value),
EntityAnalysisModelInstanceEntryGuid =
context.EntityAnalysisModelInstanceEntryPayload.EntityAnalysisModelInstanceEntryGuid
});
}
break;
case int i:
context.EntityAnalysisModelInstanceEntryPayload.Payload.TryAdd(prop.Key, i);
if (prop.Value.ReportTable)
{
context.EntityAnalysisModelInstanceEntryPayload.ArchiveKeys.Add(new ArchiveKey
{
ProcessingTypeId = 1,
Key = prop.Key,
KeyValueInteger = i,
EntityAnalysisModelInstanceEntryGuid =
context.EntityAnalysisModelInstanceEntryPayload.EntityAnalysisModelInstanceEntryGuid
});
}
break;
case byte b:
context.EntityAnalysisModelInstanceEntryPayload.Payload.TryAdd(prop.Key, b);
if (prop.Value.ReportTable)
{
context.EntityAnalysisModelInstanceEntryPayload.ArchiveKeys.Add(new ArchiveKey
{
ProcessingTypeId = 1,
Key = prop.Key,
KeyValueBoolean = b,
EntityAnalysisModelInstanceEntryGuid =
context.EntityAnalysisModelInstanceEntryPayload.EntityAnalysisModelInstanceEntryGuid
});
}
break;
case double d:
context.EntityAnalysisModelInstanceEntryPayload.Payload.TryAdd(prop.Key, d);
if (prop.Value.ReportTable)
{
context.EntityAnalysisModelInstanceEntryPayload.ArchiveKeys.Add(new ArchiveKey
{
ProcessingTypeId = 1,
Key = prop.Key,
KeyValueFloat = d,
EntityAnalysisModelInstanceEntryGuid =
context.EntityAnalysisModelInstanceEntryPayload.EntityAnalysisModelInstanceEntryGuid
});
}
break;
case DateTime dt:
context.EntityAnalysisModelInstanceEntryPayload.Payload.TryAdd(prop.Key, dt);
if (prop.Value.ReportTable)
{
context.EntityAnalysisModelInstanceEntryPayload.ArchiveKeys.Add(new ArchiveKey
{
ProcessingTypeId = 1,
Key = prop.Key,
KeyValueDate = dt,
EntityAnalysisModelInstanceEntryGuid =
context.EntityAnalysisModelInstanceEntryPayload.EntityAnalysisModelInstanceEntryGuid
});
}
break;
default:
context.EntityAnalysisModelInstanceEntryPayload.Payload.TryAdd(prop.Key, value.ToString());
if (prop.Value.ReportTable)
{
context.EntityAnalysisModelInstanceEntryPayload.ArchiveKeys.Add(new ArchiveKey
{
ProcessingTypeId = 1,
Key = prop.Key,
KeyValueString = value.ToString(),
EntityAnalysisModelInstanceEntryGuid =
context.EntityAnalysisModelInstanceEntryPayload.EntityAnalysisModelInstanceEntryGuid
});
}
break;
}
}
catch (Exception ex) when (ex is not OperationCanceledException)
{
context.Log.Error(ex.ToString());
}
}
return true;
}
}
}