public JToken Traverse(JToken tree, TraversalStepOperation op, IEnumerator <string> keys, JToken data) { if (tree == null) { return(null); } if (GetStepType().IsAssignableFrom(tree.GetType())) { keys.MoveNext(); string key = keys.Current; if (_child == null) { // End of the Traversal so do the set or get switch (op) { case TraversalStepOperation.GET: return(Get(tree, key)); case TraversalStepOperation.SET: return(_traversr.HandleFinalSet(this, tree, key, data)); case TraversalStepOperation.REMOVE: return(Remove(tree, key)); default: throw new InvalidOperationException("Invalid op:" + op.ToString()); } } else { // We just an intermediate step, so traverse and then hand over control to our child var optSub = _traversr.HandleIntermediateGet(this, tree, key, op); if (optSub != null) { return(_child.Traverse(optSub, op, keys, data)); } } } return(null); }
/** * Allow subclasses to control how gets are handled for intermediate traversals. * * Example: we are a MapTraversal and out key is "foo". * We simply do a 'tree.get( "foo" )'. However, if we get a null back, or we get back * a data type incompatible with our child Traversal, what do we do? * * Overwrite or just return? */ public abstract JToken HandleIntermediateGet(ITraversalStep traversalStep, JToken tree, string key, TraversalStepOperation op);
/** * Only make a new instance of a container object for SET, if there is nothing "there". */ public override JToken HandleIntermediateGet(ITraversalStep traversalStep, JToken tree, string key, TraversalStepOperation op) { var sub = traversalStep.Get(tree, key); if ((sub == null || sub.Type == JTokenType.Null) && op == TraversalStepOperation.SET) { // get our child to make the container object, so it will be happy with it sub = traversalStep.GetChild().NewContainer(); traversalStep.OverwriteSet(tree, key, sub); } return(sub); }