namespace GFramework.Game.Config; /// /// 表示单个 schema 节点的最小运行时描述。 /// 同一个模型同时覆盖对象、数组和标量,便于递归校验逻辑只依赖一种树结构。 /// internal sealed class YamlConfigSchemaNode { private readonly NodeChildren _children; private readonly NodeValidation _validation; private YamlConfigSchemaNode( YamlConfigSchemaPropertyType nodeType, NodeChildren children, NodeValidation validation, string schemaPathHint) { ArgumentNullException.ThrowIfNull(children); ArgumentNullException.ThrowIfNull(validation); ArgumentNullException.ThrowIfNull(schemaPathHint); _children = children; _validation = validation; NodeType = nodeType; Properties = children.Properties; RequiredProperties = children.RequiredProperties; ItemNode = children.ItemNode; ReferenceTableName = validation.ReferenceTableName; AllowedValues = validation.AllowedValues; Constraints = validation.Constraints; ArrayConstraints = validation.ArrayConstraints; ObjectConstraints = validation.ObjectConstraints; ConstantValue = validation.ConstantValue; NegatedSchemaNode = validation.NegatedSchemaNode; SchemaPathHint = schemaPathHint; } /// /// 获取节点类型。 /// public YamlConfigSchemaPropertyType NodeType { get; } /// /// 获取对象属性集合;非对象节点时返回空。 /// public IReadOnlyDictionary? Properties { get; } /// /// 获取对象必填属性集合;非对象节点时返回空。 /// public IReadOnlyCollection? RequiredProperties { get; } /// /// 获取数组元素节点;非数组节点时返回空。 /// public YamlConfigSchemaNode? ItemNode { get; } /// /// 获取目标引用表名称;未声明跨表引用时返回空。 /// public string? ReferenceTableName { get; } /// /// 获取节点允许值集合;未声明 enum 时返回空。 /// public IReadOnlyCollection? AllowedValues { get; } /// /// 获取标量范围与长度约束;未声明时返回空。 /// public YamlConfigScalarConstraints? Constraints { get; } /// /// 获取对象属性数量约束;未声明时返回空。 /// public YamlConfigObjectConstraints? ObjectConstraints { get; } /// /// 获取数组元素数量约束;未声明时返回空。 /// public YamlConfigArrayConstraints? ArrayConstraints { get; } /// /// 获取节点常量约束;未声明 const 时返回空。 /// public YamlConfigConstantValue? ConstantValue { get; } /// /// 获取节点声明的 not 子 schema;未声明时返回空。 /// public YamlConfigSchemaNode? NegatedSchemaNode { get; } /// /// 获取用于诊断显示的 schema 路径提示。 /// 当前节点本身不记录独立路径,因此对象校验会回退到所属根 schema 路径。 /// public string SchemaPathHint { get; } /// /// 创建对象节点描述。 /// /// 对象属性集合。 /// 对象必填属性集合。 /// 对象属性数量约束。 /// 用于错误信息的 schema 文件路径提示。 /// 对象节点模型。 public static YamlConfigSchemaNode CreateObject( IReadOnlyDictionary? properties, IReadOnlyCollection? requiredProperties, YamlConfigObjectConstraints? objectConstraints, string schemaPathHint) { return new YamlConfigSchemaNode( YamlConfigSchemaPropertyType.Object, new NodeChildren(properties, requiredProperties, itemNode: null), new NodeValidation( referenceTableName: null, allowedValues: null, constraints: null, arrayConstraints: null, objectConstraints, constantValue: null, negatedSchemaNode: null), schemaPathHint); } /// /// 创建数组节点描述。 /// /// 数组元素节点。 /// 数组节点允许值集合。 /// 数组元素数量约束。 /// 用于错误信息的 schema 文件路径提示。 /// 数组节点模型。 public static YamlConfigSchemaNode CreateArray( YamlConfigSchemaNode itemNode, IReadOnlyCollection? allowedValues, YamlConfigArrayConstraints? arrayConstraints, string schemaPathHint) { return new YamlConfigSchemaNode( YamlConfigSchemaPropertyType.Array, new NodeChildren(properties: null, requiredProperties: null, itemNode), new NodeValidation( referenceTableName: null, allowedValues, constraints: null, arrayConstraints, objectConstraints: null, constantValue: null, negatedSchemaNode: null), schemaPathHint); } /// /// 创建标量节点描述。 /// /// 标量节点类型。 /// 目标引用表名称。 /// 标量允许值集合。 /// 标量范围与长度约束。 /// 用于错误信息的 schema 文件路径提示。 /// 标量节点模型。 public static YamlConfigSchemaNode CreateScalar( YamlConfigSchemaPropertyType nodeType, string? referenceTableName, IReadOnlyCollection? allowedValues, YamlConfigScalarConstraints? constraints, string schemaPathHint) { return new YamlConfigSchemaNode( nodeType, NodeChildren.None, new NodeValidation( referenceTableName, allowedValues, constraints, arrayConstraints: null, objectConstraints: null, constantValue: null, negatedSchemaNode: null), schemaPathHint); } /// /// 基于当前节点复制一个只替换引用表名称的新节点。 /// 该方法用于把数组级别的 ref-table 语义挂接到元素节点上。 /// /// 新的目标引用表名称。 /// 复制后的节点。 public YamlConfigSchemaNode WithReferenceTable(string referenceTableName) { return new YamlConfigSchemaNode( NodeType, _children, _validation.WithReferenceTable(referenceTableName), SchemaPathHint); } /// /// 基于当前节点复制一个只替换 enum 允许值集合的新节点。 /// /// 新的允许值集合。 /// 复制后的节点。 public YamlConfigSchemaNode WithAllowedValues(IReadOnlyCollection? allowedValues) { return new YamlConfigSchemaNode( NodeType, _children, _validation.WithAllowedValues(allowedValues), SchemaPathHint); } /// /// 基于当前节点复制一个只替换常量约束的新节点。 /// /// 新的常量约束。 /// 复制后的节点。 public YamlConfigSchemaNode WithConstantValue(YamlConfigConstantValue? constantValue) { return new YamlConfigSchemaNode( NodeType, _children, _validation.WithConstantValue(constantValue), SchemaPathHint); } /// /// 基于当前节点复制一个只替换 not 子 schema 的新节点。 /// /// 新的 negated schema。 /// 复制后的节点。 public YamlConfigSchemaNode WithNegatedSchemaNode(YamlConfigSchemaNode? negatedSchemaNode) { return new YamlConfigSchemaNode( NodeType, _children, _validation.WithNegatedSchemaNode(negatedSchemaNode), SchemaPathHint); } private sealed class NodeChildren { public NodeChildren( IReadOnlyDictionary? properties, IReadOnlyCollection? requiredProperties, YamlConfigSchemaNode? itemNode) { Properties = properties; RequiredProperties = requiredProperties; ItemNode = itemNode; } public static NodeChildren None { get; } = new(properties: null, requiredProperties: null, itemNode: null); public IReadOnlyDictionary? Properties { get; } public IReadOnlyCollection? RequiredProperties { get; } public YamlConfigSchemaNode? ItemNode { get; } } private sealed class NodeValidation { public NodeValidation( string? referenceTableName, IReadOnlyCollection? allowedValues, YamlConfigScalarConstraints? constraints, YamlConfigArrayConstraints? arrayConstraints, YamlConfigObjectConstraints? objectConstraints, YamlConfigConstantValue? constantValue, YamlConfigSchemaNode? negatedSchemaNode) { ReferenceTableName = referenceTableName; AllowedValues = allowedValues; Constraints = constraints; ArrayConstraints = arrayConstraints; ObjectConstraints = objectConstraints; ConstantValue = constantValue; NegatedSchemaNode = negatedSchemaNode; } public string? ReferenceTableName { get; } public IReadOnlyCollection? AllowedValues { get; } public YamlConfigScalarConstraints? Constraints { get; } public YamlConfigArrayConstraints? ArrayConstraints { get; } public YamlConfigObjectConstraints? ObjectConstraints { get; } public YamlConfigConstantValue? ConstantValue { get; } public YamlConfigSchemaNode? NegatedSchemaNode { get; } public NodeValidation WithReferenceTable(string referenceTableName) { return new NodeValidation(referenceTableName, AllowedValues, Constraints, ArrayConstraints, ObjectConstraints, ConstantValue, NegatedSchemaNode); } public NodeValidation WithAllowedValues(IReadOnlyCollection? allowedValues) { return new NodeValidation(ReferenceTableName, allowedValues, Constraints, ArrayConstraints, ObjectConstraints, ConstantValue, NegatedSchemaNode); } public NodeValidation WithConstantValue(YamlConfigConstantValue? constantValue) { return new NodeValidation(ReferenceTableName, AllowedValues, Constraints, ArrayConstraints, ObjectConstraints, constantValue, NegatedSchemaNode); } public NodeValidation WithNegatedSchemaNode(YamlConfigSchemaNode? negatedSchemaNode) { return new NodeValidation(ReferenceTableName, AllowedValues, Constraints, ArrayConstraints, ObjectConstraints, ConstantValue, negatedSchemaNode); } } }