// Copyright (c) Microsoft. All rights reserved.
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using Microsoft.Agents.AI.Workflows.Declarative.Extensions;
using Microsoft.PowerFx.Types;
using Microsoft.Shared.Diagnostics;
namespace Microsoft.Agents.AI.Workflows.Declarative.Kit;
///
/// Extension helpers for converting instances (and collections containing them)
/// into their normalized runtime representations (primarily primitives) ready for evaluation.
///
public static class PortableValueExtensions
{
///
/// Normalizes all values in the provided dictionary. Each entry whose value is a
/// is converted to its underlying normalized representation; non-PortableValue entries are preserved as-is.
///
/// The source dictionary whose values may contain instances; may be null.
///
/// A new dictionary with normalized values, or null if is null.
/// Keys are copied unchanged.
///
public static IDictionary? NormalizePortableValues(this IDictionary? source)
{
if (source is null)
{
return null;
}
return source.ToDictionary(kvp => kvp.Key, kvp => kvp.Value.NormalizePortableValue());
}
///
/// Normalizes an arbitrary value if it is a ; otherwise returns the value unchanged.
///
/// The value to normalize; may be null or already a primitive/object.
///
/// Null if is null; the normalized result if it is a ;
/// otherwise the original .
///
public static object? NormalizePortableValue(this object? value) =>
Throw.IfNull(value, nameof(value)) switch
{
null => null,
JsonElement jsonValue => jsonValue.GetValue(),
PortableValue portableValue => portableValue.Normalize(),
_ => value,
};
///
/// Converts a into a concrete representation suitable for evaluation.
///
/// The portable value to normalize; cannot be null.
///
/// A instance representing the underlying value.
///
public static object? Normalize(this PortableValue value) =>
Throw.IfNull(value, nameof(value)).TypeId switch
{
_ when value.IsType(out string? stringValue) => stringValue,
_ when value.IsSystemType(out bool? boolValue) => boolValue.Value,
_ when value.IsSystemType(out int? intValue) => intValue.Value,
_ when value.IsSystemType(out long? longValue) => longValue.Value,
_ when value.IsSystemType(out decimal? decimalValue) => decimalValue.Value,
_ when value.IsSystemType(out float? floatValue) => floatValue.Value,
_ when value.IsSystemType(out double? doubleValue) => doubleValue.Value,
_ when value.IsParentType(out IDictionary? recordValue) => recordValue.NormalizePortableValues(),
_ when value.IsParentType(out IEnumerable? listValue) => listValue.NormalizePortableValues(),
_ => throw new DeclarativeActionException($"Unsupported portable type: {value.TypeId.TypeName}"),
};
private static Dictionary NormalizePortableValues(this IDictionary source)
{
return GetValues().ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
IEnumerable> GetValues()
{
foreach (DictionaryEntry entry in source)
{
yield return new KeyValuePair((string)entry.Key, entry.Value.NormalizePortableValue());
}
}
}
private static object?[] NormalizePortableValues(this IEnumerable source) =>
source.Cast