private bool RemoveThisNode(JObject nodeToRemove, JsonTransformationContextLogger logger) { var parent = (JProperty)nodeToRemove.Parent; if (parent == null) { // If the node can't be removed, log a warning pointing to the node in the source logger.LogWarning(Resources.WarningMessage_UnableToRemove, ErrorLocation.Source, nodeToRemove); return(true); } else { // If the node is removed, transformations should be halted parent.Value = null; return(false); } }
/// <inheritdoc/> protected override bool ProcessCore(JObject source, JToken transformValue, JsonTransformationContextLogger logger) { switch (transformValue.Type) { case JTokenType.String: // If the value is just a string, remove that node if (!source.Remove(transformValue.ToString())) { logger.LogWarning(Resources.WarningMessage_UnableToRemove, ErrorLocation.Transform, transformValue); } break; case JTokenType.Boolean: if ((bool)transformValue) { if (source.Root.Equals(source)) { throw JdtException.FromLineInfo(Resources.ErrorMessage_RemoveRoot, ErrorLocation.Transform, transformValue); } // If the transform value is true, remove the entire node return(this.RemoveThisNode(source, logger)); } break; case JTokenType.Object: // If the value is an object, verify the attributes within and perform the remove return(this.RemoveWithAttributes(source, (JObject)transformValue, logger)); default: throw JdtException.FromLineInfo(string.Format(Resources.ErrorMessage_InvalidRemoveValue, transformValue.Type.ToString()), ErrorLocation.Transform, transformValue); } // If nothing indicates a halt, continue with transforms return(true); }
private bool RemoveWithAttributes(JObject source, JObject removeObject, JsonTransformationContextLogger logger) { var attributes = this.attributeValidator.ValidateAndReturnAttributes(removeObject); // The remove attribute only accepts objects if they have only the path attribute JToken pathToken; if (attributes.TryGetValue(JdtAttributes.Path, out pathToken)) { if (pathToken.Type == JTokenType.String) { var tokensToRemove = source.SelectTokens(pathToken.ToString()).ToList(); if (!tokensToRemove.Any()) { logger.LogWarning(Resources.WarningMessage_NoResults, ErrorLocation.Transform, pathToken); } // Removes all of the tokens specified by the path foreach (JToken token in tokensToRemove) { if (token.Equals(source)) { if (source.Root.Equals(source)) { throw JdtException.FromLineInfo(Resources.ErrorMessage_RemoveRoot, ErrorLocation.Transform, removeObject); } // If the path specifies the current node if (!this.RemoveThisNode(source, logger)) { // Halt transformations return(false); } } else { if (token.Parent.Type == JTokenType.Property) { // If the token is the value of a property, // the property must be removed token.Parent.Remove(); } else { // If the token is a property or an element in an array, // it must be removed directly token.Remove(); } } } } else { throw JdtException.FromLineInfo(Resources.ErrorMessage_PathContents, ErrorLocation.Transform, pathToken); } } else { throw JdtException.FromLineInfo(Resources.ErrorMessage_RemoveAttributes, ErrorLocation.Transform, removeObject); } // If nothing indicates a halt, continue transforms return(true); }
/// <inheritdoc/> protected override bool ProcessCore(JObject source, JToken transformValue, JsonTransformationContextLogger logger) { if (transformValue.Type != JTokenType.Object) { // Rename only accepts objects, either with properties or direct renames throw JdtException.FromLineInfo(string.Format(Resources.ErrorMessage_InvalidRenameValue, transformValue.Type.ToString()), ErrorLocation.Transform, transformValue); } else { // Try and get attributes from the object var renameObject = (JObject)transformValue; var attributes = this.attributeValidator.ValidateAndReturnAttributes(renameObject); // If there are attributes, handle them accordingly if (attributes.Any()) { // If the object has attributes it must have both path and value JToken pathToken, valueToken; if (attributes.TryGetValue(JdtAttributes.Path, out pathToken) && attributes.TryGetValue(JdtAttributes.Value, out valueToken)) { if (pathToken.Type != JTokenType.String) { throw JdtException.FromLineInfo(Resources.ErrorMessage_PathContents, ErrorLocation.Transform, pathToken); } if (valueToken.Type != JTokenType.String) { throw JdtException.FromLineInfo(Resources.ErrorMessage_ValueContents, ErrorLocation.Transform, valueToken); } var tokensToRename = source.SelectTokens(pathToken.ToString()).ToList(); if (!tokensToRename.Any()) { logger.LogWarning(Resources.WarningMessage_NoResults, ErrorLocation.Transform, pathToken); } // If the values are correct, rename each token found with the given path foreach (JToken token in tokensToRename) { if (!this.RenameNode(token, valueToken.ToString())) { throw JdtException.FromLineInfo(Resources.ErrorMessage_RenameNode, ErrorLocation.Transform, renameObject); } } } else { // If either is not present, throw throw JdtException.FromLineInfo(Resources.ErrorMessage_RenameAttributes, ErrorLocation.Transform, renameObject); } } else { // If the object does not contain attributes, each property is a rename to execute // where the key is the old name and the value must be a string with the new name of the node foreach (JProperty renameOperation in renameObject.Properties()) { if (renameOperation.Value.Type != JTokenType.String) { throw JdtException.FromLineInfo(Resources.ErrorMessage_ValueContents, ErrorLocation.Transform, renameOperation); } // TO DO: Warning if the node is not found JToken nodeToRename; if (source.TryGetValue(renameOperation.Name, out nodeToRename)) { if (!this.RenameNode(nodeToRename, renameOperation.Value.ToString())) { throw JdtException.FromLineInfo(Resources.ErrorMessage_RenameNode, ErrorLocation.Transform, renameOperation); } } else { logger.LogWarning(string.Format(Resources.WarningMessage_NodeNotFound, renameOperation.Name), ErrorLocation.Transform, renameOperation); } } } } // Do not halt transformations return(true); }
private void MergeWithObject(JObject source, JObject mergeObject, JsonTransformationContextLogger logger) { var attributes = this.attributeValidator.ValidateAndReturnAttributes(mergeObject); // If there are attributes, handle them accordingly if (attributes.Any()) { // If the object has attributes it must have both path and value // TO DO: Accept value without path JToken pathToken, valueToken; if (attributes.TryGetValue(JdtAttributes.Path, out pathToken) && attributes.TryGetValue(JdtAttributes.Value, out valueToken)) { if (pathToken.Type != JTokenType.String) { throw JdtException.FromLineInfo(Resources.ErrorMessage_PathContents, ErrorLocation.Transform, mergeObject); } var tokensToMerge = source.SelectTokens(pathToken.ToString()).ToList(); if (!tokensToMerge.Any()) { logger.LogWarning(Resources.WarningMessage_NoResults, ErrorLocation.Transform, pathToken); } foreach (JToken token in tokensToMerge) { // Perform the merge for each element found through the path if (token.Type == JTokenType.Object && valueToken.Type == JTokenType.Object) { // If they are both objects, start a new transformation ProcessTransform((JObject)token, (JObject)valueToken, logger); } else if (token.Type == JTokenType.Array && valueToken.Type == JTokenType.Array) { // If they are both arrays, add the new values to the original ((JArray)token).Merge(valueToken.DeepClone()); } else { // If the transformation is trying to replace the root, throw if (token.Root.Equals(token)) { throw JdtException.FromLineInfo(Resources.ErrorMessage_ReplaceRoot, ErrorLocation.Transform, mergeObject); } // If they are primitives or have different values, perform a replace token.Replace(valueToken); } } } else { // If either is not present, throw throw JdtException.FromLineInfo(Resources.ErrorMessage_MergeAttributes, ErrorLocation.Transform, mergeObject); } } else { // If the merge object does not contain attributes, // simply execute the transform with that object ProcessTransform(source, mergeObject, logger); } }
private bool ReplaceWithProperties(JObject source, JObject replaceObject, JsonTransformationContextLogger logger) { var attributes = this.attributeValidator.ValidateAndReturnAttributes(replaceObject); // If there are attributes, handle them accordingly if (attributes.Any()) { // If the object has attributes it must have both path and value JToken pathToken, valueToken; if (attributes.TryGetValue(JdtAttributes.Path, out pathToken) && attributes.TryGetValue(JdtAttributes.Value, out valueToken)) { if (pathToken.Type != JTokenType.String) { throw JdtException.FromLineInfo(Resources.ErrorMessage_PathContents, ErrorLocation.Transform, pathToken); } var tokensToReplace = source.SelectTokens(pathToken.ToString()).ToList(); if (!tokensToReplace.Any()) { logger.LogWarning(Resources.WarningMessage_NoResults, ErrorLocation.Transform, pathToken); } foreach (JToken token in tokensToReplace) { bool replacedThisNode = false; if (token.Root.Equals(token) && valueToken.Type != JTokenType.Object) { // If trying to replace the root object with a token that is not another object, throw throw JdtException.FromLineInfo(Resources.ErrorMessage_ReplaceRoot, ErrorLocation.Transform, pathToken); } if (token.Equals(source)) { // If the specified path is to the current node replacedThisNode = true; } token.Replace(valueToken); if (replacedThisNode) { // If the current node was replaced, stop executing transformations on this node return(false); } } } else { // If either is not present, throw throw JdtException.FromLineInfo(Resources.ErrorMessage_ReplaceAttributes, ErrorLocation.Transform, replaceObject); } // If we got here, transformations should continue return(true); } else { // If there are no attributes, replace the current object with the given object // Here, the root can be replaced as the replace value is an object source.Replace(replaceObject); // If the node is replaced, stop transformations on it return(false); } }