Added nodes related to the list and array operations
Some checks failed
Build / build (push) Has been cancelled
Some checks failed
Build / build (push) Has been cancelled
This commit is contained in:
@@ -340,6 +340,108 @@ namespace Nodify.Calculator.Execution.Handlers
|
||||
}
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// List operation execution handlers
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
internal sealed class ListAddExecutionHandler : INodeExecutionHandler
|
||||
{
|
||||
public bool CanHandle(OperationViewModel node, ExecutionContext ctx)
|
||||
=> node is SystemOperationViewModel sys && sys.SystemOperationType == SystemOperations.LIST_ADD;
|
||||
|
||||
public void Execute(OperationViewModel node, ExecutionContext ctx)
|
||||
{
|
||||
var listJson = ListExecHelper.ReadInput(node, ctx, "List");
|
||||
var itemJson = ListExecHelper.ReadInput(node, ctx, "Item");
|
||||
var list = ListExecHelper.ParseList(listJson);
|
||||
list.Add(itemJson != null ? JToken.Parse(itemJson) : JValue.CreateNull());
|
||||
var result = list.ToString(Formatting.None);
|
||||
ctx.Outputs[node.NodeId] = result;
|
||||
ctx.Variables[node.NodeId] = result;
|
||||
ctx.Log($"[List Add] Added item. Count={list.Count}");
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class ListRemoveExecutionHandler : INodeExecutionHandler
|
||||
{
|
||||
public bool CanHandle(OperationViewModel node, ExecutionContext ctx)
|
||||
=> node is SystemOperationViewModel sys && sys.SystemOperationType == SystemOperations.LIST_REMOVE;
|
||||
|
||||
public void Execute(OperationViewModel node, ExecutionContext ctx)
|
||||
{
|
||||
var listJson = ListExecHelper.ReadInput(node, ctx, "List");
|
||||
var indexStr = ListExecHelper.ReadInput(node, ctx, "Index");
|
||||
var list = ListExecHelper.ParseList(listJson);
|
||||
int index = int.TryParse(indexStr, out var i) ? i : -1;
|
||||
if (index >= 0 && index < list.Count)
|
||||
list.RemoveAt(index);
|
||||
else
|
||||
ctx.Log($"[List Remove] Index {index} out of range (Count={list.Count})", logType.Warning);
|
||||
var result = list.ToString(Formatting.None);
|
||||
ctx.Outputs[node.NodeId] = result;
|
||||
ctx.Variables[node.NodeId] = result;
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class ListUpdateExecutionHandler : INodeExecutionHandler
|
||||
{
|
||||
public bool CanHandle(OperationViewModel node, ExecutionContext ctx)
|
||||
=> node is SystemOperationViewModel sys && sys.SystemOperationType == SystemOperations.LIST_UPDATE;
|
||||
|
||||
public void Execute(OperationViewModel node, ExecutionContext ctx)
|
||||
{
|
||||
var listJson = ListExecHelper.ReadInput(node, ctx, "List");
|
||||
var indexStr = ListExecHelper.ReadInput(node, ctx, "Index");
|
||||
var itemJson = ListExecHelper.ReadInput(node, ctx, "Item");
|
||||
var list = ListExecHelper.ParseList(listJson);
|
||||
int index = int.TryParse(indexStr, out var i) ? i : -1;
|
||||
if (index >= 0 && index < list.Count)
|
||||
list[index] = itemJson != null ? JToken.Parse(itemJson) : JValue.CreateNull();
|
||||
else
|
||||
ctx.Log($"[List Update] Index {index} out of range (Count={list.Count})", logType.Warning);
|
||||
var result = list.ToString(Formatting.None);
|
||||
ctx.Outputs[node.NodeId] = result;
|
||||
ctx.Variables[node.NodeId] = result;
|
||||
}
|
||||
}
|
||||
|
||||
internal sealed class ListClearExecutionHandler : INodeExecutionHandler
|
||||
{
|
||||
public bool CanHandle(OperationViewModel node, ExecutionContext ctx)
|
||||
=> node is SystemOperationViewModel sys && sys.SystemOperationType == SystemOperations.LIST_CLEAR;
|
||||
|
||||
public void Execute(OperationViewModel node, ExecutionContext ctx)
|
||||
{
|
||||
var result = "[]";
|
||||
ctx.Outputs[node.NodeId] = result;
|
||||
ctx.Variables[node.NodeId] = result;
|
||||
ctx.Log("[List Clear] Cleared list");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Helper for reading list node inputs and parsing JSON arrays.</summary>
|
||||
internal static class ListExecHelper
|
||||
{
|
||||
public static string ReadInput(OperationViewModel node, ExecutionContext ctx, string title)
|
||||
{
|
||||
var conn = ctx.Connections.FirstOrDefault(c =>
|
||||
c.Input.Operation == node
|
||||
&& (c.Input.Title ?? "").StartsWith(title, StringComparison.OrdinalIgnoreCase)
|
||||
&& c.Input.Shape != ConnectorShape.Triangle);
|
||||
if (conn == null) return null;
|
||||
if (ctx.Outputs.TryGetValue(conn.OutputNodeId, out var val))
|
||||
return val;
|
||||
return null;
|
||||
}
|
||||
|
||||
public static JArray ParseList(string json)
|
||||
{
|
||||
if (string.IsNullOrEmpty(json)) return new JArray();
|
||||
try { return JArray.Parse(json); }
|
||||
catch { return new JArray(); }
|
||||
}
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// Default / fallback: API call
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -205,4 +205,88 @@ namespace Nodify.Calculator.Execution.Resolvers
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// LIST GET: pick an element by index from a JSON array (non-flow value node).
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
internal sealed class ListGetValueResolver : INodeValueResolver
|
||||
{
|
||||
public bool CanResolve(OperationViewModel node, ConnectorViewModel c)
|
||||
=> node is SystemOperationViewModel sys && sys.SystemOperationType == SystemOperations.LIST_GET;
|
||||
|
||||
public string Resolve(OperationViewModel node, ConnectorViewModel outputConnector, IValueResolutionContext ctx)
|
||||
{
|
||||
var listInput = node.Input.FirstOrDefault(i => i.Shape == ConnectorShape.Grid);
|
||||
var indexInput = node.Input.FirstOrDefault(i => (i.Title ?? "").StartsWith("Index", StringComparison.OrdinalIgnoreCase));
|
||||
if (listInput == null) return null;
|
||||
|
||||
var json = ctx.Read(listInput);
|
||||
var indexStr = indexInput != null ? ctx.Read(indexInput) : "0";
|
||||
int index = int.TryParse(indexStr, out var i) ? i : 0;
|
||||
|
||||
try
|
||||
{
|
||||
var arr = JArray.Parse(json ?? "[]");
|
||||
if (index >= 0 && index < arr.Count)
|
||||
{
|
||||
var item = arr[index];
|
||||
return item.Type == JTokenType.String ? item.ToString() : item.ToString(Formatting.None);
|
||||
}
|
||||
}
|
||||
catch { }
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// LIST COUNT: returns the length of a JSON array as a string integer.
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
internal sealed class ListCountValueResolver : INodeValueResolver
|
||||
{
|
||||
public bool CanResolve(OperationViewModel node, ConnectorViewModel c)
|
||||
=> node is SystemOperationViewModel sys && sys.SystemOperationType == SystemOperations.LIST_COUNT;
|
||||
|
||||
public string Resolve(OperationViewModel node, ConnectorViewModel outputConnector, IValueResolutionContext ctx)
|
||||
{
|
||||
var listInput = node.Input.FirstOrDefault(i => i.Shape == ConnectorShape.Grid);
|
||||
if (listInput == null) return "0";
|
||||
|
||||
var json = ctx.Read(listInput);
|
||||
try
|
||||
{
|
||||
var arr = JArray.Parse(json ?? "[]");
|
||||
return arr.Count.ToString();
|
||||
}
|
||||
catch { return "0"; }
|
||||
}
|
||||
}
|
||||
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
// LIST CONTAINS: checks if item exists in array, returns "true"/"false".
|
||||
// ─────────────────────────────────────────────────────────────────────────────
|
||||
internal sealed class ListContainsValueResolver : INodeValueResolver
|
||||
{
|
||||
public bool CanResolve(OperationViewModel node, ConnectorViewModel c)
|
||||
=> node is SystemOperationViewModel sys && sys.SystemOperationType == SystemOperations.LIST_CONTAINS;
|
||||
|
||||
public string Resolve(OperationViewModel node, ConnectorViewModel outputConnector, IValueResolutionContext ctx)
|
||||
{
|
||||
var listInput = node.Input.FirstOrDefault(i => i.Shape == ConnectorShape.Grid);
|
||||
var itemInput = node.Input.FirstOrDefault(i => i.IsCopyConnector);
|
||||
if (listInput == null) return "false";
|
||||
|
||||
var json = ctx.Read(listInput);
|
||||
var itemJson = itemInput != null ? ctx.Read(itemInput) : null;
|
||||
|
||||
try
|
||||
{
|
||||
var arr = JArray.Parse(json ?? "[]");
|
||||
if (string.IsNullOrEmpty(itemJson)) return "false";
|
||||
var searchToken = JToken.Parse(itemJson);
|
||||
bool found = arr.Any(t => JToken.DeepEquals(t, searchToken));
|
||||
return found.ToString().ToLower();
|
||||
}
|
||||
catch { return "false"; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user