/** * Recursively walk the spec input tree. */ private static List <CardinalitySpec> CreateChildren(JObject rawSpec) { var children = new List <CardinalitySpec>(); var actualKeys = new HashSet <string>(); foreach (var kv in rawSpec) { CardinalitySpec childSpec; if (kv.Value.Type == JTokenType.Object) { childSpec = new CardinalityCompositeSpec(kv.Key, (JObject)kv.Value); } else { childSpec = new CardinalityLeafSpec(kv.Key, kv.Value); } string childCanonicalString = childSpec.GetPathElement().GetCanonicalForm(); if (actualKeys.Contains(childCanonicalString)) { throw new ArgumentException(nameof(rawSpec), "Duplicate canonical CardinalityTransform key found : " + childCanonicalString); } actualKeys.Add(childCanonicalString); children.Add(childSpec); } return(children); }
private readonly IReadOnlyList <CardinalitySpec> _computedChildren; // children that are regex matches against the input data public CardinalityCompositeSpec(string rawKey, JObject spec) : base(rawKey) { var literals = new Dictionary <string, CardinalitySpec>(); var computed = new List <CardinalitySpec>(); _specialChild = null; // self check if (GetPathElement().GetType() == typeof(AtPathElement)) { throw new SpecException("@ CardinalityTransform key, can not have children."); } List <CardinalitySpec> children = CreateChildren(spec); if (children.Count == 0) { throw new SpecException("Shift CardinalitySpec format error : CardinalitySpec line with empty {} as value is not valid."); } foreach (CardinalitySpec child in children) { var childPe = child.GetPathElement(); literals[childPe.RawKey] = child; if (childPe is LiteralPathElement) { literals[childPe.RawKey] = child; } // special is it is "@" else if (childPe is AtPathElement) { if (child is CardinalityLeafSpec cls) { _specialChild = cls; } else { throw new SpecException("@ CardinalityTransform key, can not have children."); } } // star else { computed.Add(child); } } // Only the computed children need to be sorted computed.Sort(computedKeysComparator); computed.TrimExcess(); _literalChildren = literals; _computedChildren = computed.AsReadOnly(); }