/* ========================================================================
* Copyright (c) 2005-2026 The OPC Foundation, Inc. All rights reserved.
*
* OPC Foundation MIT License 1.00
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* The complete license agreement can be found here:
* http://opcfoundation.org/License/MIT/1.00/
* ======================================================================*/
using System.Collections.Generic;
using Opc.Ua.OpenUsd.Scene;
namespace Opc.Ua.OpenUsd.Tests
{
///
/// Small query helpers over a , so the assertions in the
/// server test fixtures read close to the address-space concepts they check.
///
internal static class SceneQuery
{
///
/// The materialized prim at an absolute SdfPath (for example /Plant).
///
public static UsdPrimState Prim(this MaterializedScene ms, string path)
{
return ms.Result.PrimsByPath[path];
}
///
/// The materialized attribute keyed <primPath>.<name>.
///
public static UsdAttributeState Attr(this MaterializedScene ms, string key)
{
return ms.Result.AttributesByPath[key];
}
///
/// The attribute's ArrayDimensions as a plain array, or null for a scalar — the
/// ArrayOf<uint> a materialized Variable carries unwraps to a
/// uint[]? that NUnit compares element-wise.
///
public static uint[]? Dims(this UsdAttributeState attribute)
{
return attribute.ArrayDimensions.ToArray();
}
///
/// The boxed value of a materialized attribute, or null when unset.
///
public static object? BoxedValue(this UsdAttributeState attribute)
{
return attribute.Value.AsBoxedObject();
}
///
/// The materialized AddIns of type under a prim's
/// AppliedSchemas folder, in address-space order.
///
public static List AppliedSchemas(this MaterializedScene ms, string primPath)
where T : NodeState
{
FolderState? folder = ms.Prim(primPath).AppliedSchemas;
if (folder == null)
{
return new List();
}
return MaterializationHarness.ChildrenOfType(ms.Context, folder);
}
///
/// The materialized composition arcs under a prim's Composition folder, in
/// address-space order.
///
public static List CompositionArcs(
this MaterializedScene ms, string primPath)
{
FolderState? folder = ms.Prim(primPath).Composition;
if (folder == null)
{
return new List();
}
return MaterializationHarness.ChildrenOfType(ms.Context, folder);
}
///
/// The absolute SdfPath of a parsed prim, walked from its parent chain.
///
public static string PathOf(this Scene.UsdPrim prim)
{
var parts = new List();
Scene.UsdPrim? current = prim;
while (current != null)
{
parts.Insert(0, current.Name);
current = current.Parent;
}
return "/" + string.Join("/", parts);
}
///
/// The total number of authored attribute connections across a whole scene.
///
public static int TotalConnections(this Scene.UsdStage stage)
{
int total = 0;
foreach (Scene.UsdPrim prim in stage.AllPrims())
{
foreach (Scene.UsdAttribute attribute in prim.Attributes)
{
total += attribute.Connections.Count;
}
}
return total;
}
///
/// Nulls every attribute value and clears every attribute connection across a scene, so
/// two scenes can be compared on structure and provenance alone. This is the workaround
/// for the two exporter round-trip defects the fixtures pin separately.
///
public static Scene.UsdStage NormalizeValuesAndConnections(this Scene.UsdStage stage)
{
foreach (Scene.UsdPrim prim in stage.AllPrims())
{
foreach (Scene.UsdAttribute attribute in prim.Attributes)
{
attribute.Value = Scene.UsdValue.Null;
attribute.Connections.Clear();
}
}
return stage;
}
}
}