/** * 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); }
/** * Initialize a Cardinality transform with a CardinalityCompositeSpec. * * @throws com.bazaarvoice.jolt.exception.SpecException for a malformed spec */ public CardinalityTransform(JToken spec) { if (spec == null) { throw new SpecException("CardinalityTransform expected a spec of Map type, got 'null'."); } if (!(spec is JObject dic)) { throw new SpecException("CardinalityTransform expected a spec of Map type, got " + spec.GetType().Name); } _rootSpec = new CardinalityCompositeSpec(ROOT_KEY, dic); }
/** * This method implements the Cardinality matching behavior * when we have both literal and computed children. * <p/> * For each input key, we see if it matches a literal, and it not, try to match the key with every computed child. */ private static void ApplyKeyToLiteralAndComputed(CardinalityCompositeSpec spec, string subKeyStr, JToken subInput, WalkedPath walkedPath, JToken input) { // if the subKeyStr found a literalChild, then we do not have to try to match any of the computed ones if (spec._literalChildren.TryGetValue(subKeyStr, out var literalChild)) { literalChild.ApplyCardinality(subKeyStr, subInput, walkedPath, input); } else { // If no literal spec key matched, iterate through all the computedChildren // Iterate through all the computedChildren until we find a match // This relies upon the computedChildren having already been sorted in priority order foreach (CardinalitySpec computedChild in spec._computedChildren) { // if the computed key does not match it will quickly return false if (computedChild.ApplyCardinality(subKeyStr, subInput, walkedPath, input)) { break; } } } }