/// <inheritdoc/>
        internal override void Process(JObject source, JObject transform, JsonTransformationContextLogger logger)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            if (transform == null)
            {
                throw new ArgumentNullException(nameof(transform));
            }

            JToken transformValue;

            if (transform.TryGetValue(this.FullVerb, out transformValue))
            {
                if (!this.Transform(source, transformValue, logger))
                {
                    // If the transformation returns false,
                    // it performed an operation that halts transforms
                    return;
                }
            }

            this.Successor.Process(source, transform, logger);
        }
Ejemplo n.º 2
0
        /// <inheritdoc/>
        internal override void Process(JObject source, JObject transform, JsonTransformationContextLogger logger)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            if (transform == null)
            {
                throw new ArgumentNullException(nameof(transform));
            }

            foreach (JProperty transformNode in transform.Properties()
                     .Where(p => JdtUtilities.IsJdtSyntax(p.Name)))
            {
                string verb = JdtUtilities.GetJdtSyntax(transformNode.Name);
                if (verb != null)
                {
                    if (!this.ValidVerbs.Contains(verb))
                    {
                        throw JdtException.FromLineInfo(string.Format(Resources.ErrorMessage_InvalidVerb, verb), ErrorLocation.Transform, transformNode);
                    }
                }
            }

            this.Successor.Process(source, transform, logger);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="JsonTransformation"/> class with an external logger.
        /// </summary>
        /// <param name="transform">The stream containing the JSON that specifies the transformation</param>
        /// /// <param name="logger">The external logger</param>
        public JsonTransformation(Stream transform, IJsonTransformationLogger logger)
        {
            if (transform == null)
            {
                throw new ArgumentNullException(nameof(transform));
            }

            this.logger = new JsonTransformationContextLogger(logger);

            this.SetTransform(transform);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="JsonTransformation"/> class with an external logger.
        /// </summary>
        /// <param name="transformFile">The path to the file that specifies the transformation</param>
        /// <param name="logger">The external logger</param>
        public JsonTransformation(string transformFile, IJsonTransformationLogger logger)
        {
            if (string.IsNullOrEmpty(transformFile))
            {
                throw new ArgumentNullException(nameof(transformFile));
            }

            this.logger = new JsonTransformationContextLogger(transformFile, logger);

            using (FileStream transformStream = File.Open(transformFile, FileMode.Open))
            {
                this.SetTransform(transformStream);
            }
        }
Ejemplo n.º 5
0
            public void Start(JObject source, JObject transform, JsonTransformationContextLogger logger)
            {
                if (source == null)
                {
                    throw new ArgumentNullException(nameof(source));
                }

                if (transform == null)
                {
                    throw new ArgumentNullException(nameof(transform));
                }

                this.processors.First().Process(source, transform, logger);
            }
        /// <summary>
        /// Executes the entire transformation with the given objects
        /// Mutates the source object
        /// </summary>
        /// <param name="source">Object to be transformed</param>
        /// <param name="transform">Object that specifies the transformation</param>
        /// <param name="logger">The logger for the transformation</param>
        internal static void ProcessTransform(JObject source, JObject transform, JsonTransformationContextLogger logger)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            if (transform == null)
            {
                throw new ArgumentNullException(nameof(transform));
            }

            // Passes in a clone of the transform object because it can be altered during the transformation process
            ProcessorChain.Start(source, (JObject)transform.CloneWithLineInfo(), logger);
        }
Ejemplo n.º 7
0
        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/>
        internal override void Process(JObject source, JObject transform, JsonTransformationContextLogger logger)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            if (transform == null)
            {
                throw new ArgumentNullException(nameof(transform));
            }

            // JDT Verbs are not handled here
            foreach (JProperty transformNode in transform.Properties()
                     .Where(p => !JdtUtilities.IsJdtSyntax(p.Name)))
            {
                JToken nodeToTransform;
                if (source.TryGetValue(transformNode.Name, out nodeToTransform))
                {
                    // If the node is present in both transform and source, analyze the types
                    // If both are objects, that is a recursive transformation, not handled here
                    if (nodeToTransform.Type == JTokenType.Array && transformNode.Value.Type == JTokenType.Array)
                    {
                        // If the original and transform are arrays, merge the contents together
                        ((JArray)nodeToTransform).Merge(transformNode.Value.DeepClone());
                    }
                    else if (nodeToTransform.Type != JTokenType.Object || transformNode.Value.Type != JTokenType.Object)
                    {
                        // TO DO: Verify if object has JDT verbs. They shouldn't be allowed here because they won't be processed
                        // If the contents are different, execute the replace
                        source[transformNode.Name] = transformNode.Value.DeepClone();
                    }
                }
                else
                {
                    // If the node is not present in the original, add it
                    source.Add(transformNode.DeepClone());
                }
            }

            this.Successor.Process(source, transform, logger);
        }
        /// <inheritdoc/>
        protected override bool ProcessCore(JObject source, JToken transformValue, JsonTransformationContextLogger logger)
        {
            if (transformValue.Type == JTokenType.Object)
            {
                // If the value is an object, analyze the contents and perform the appropriate transform
                return(this.ReplaceWithProperties(source, (JObject)transformValue, logger));
            }
            else
            {
                if (source.Root.Equals(source))
                {
                    // If trying to replace the root with a non-object token, throw
                    throw JdtException.FromLineInfo(Resources.ErrorMessage_ReplaceRoot, ErrorLocation.Transform, transformValue);
                }

                // If the value is not an object, simply replace the original node with the new value
                source.Replace(transformValue);

                // If the node is replaced, stop transformations on it
                return(false);
            }
        }
Ejemplo n.º 10
0
        /// <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);
        }
Ejemplo n.º 11
0
        /// <inheritdoc/>
        protected override bool ProcessCore(JObject source, JToken transformValue, JsonTransformationContextLogger logger)
        {
            if (transformValue.Type == JTokenType.Object)
            {
                // If both source and transform are objects,
                // analyze the contents and perform the appropriate transforms
                this.MergeWithObject(source, (JObject)transformValue, logger);
            }
            else
            {
                // If the transformation is trying to replace the root, throw
                if (source.Root.Equals(source))
                {
                    throw JdtException.FromLineInfo(Resources.ErrorMessage_ReplaceRoot, ErrorLocation.Transform, transformValue);
                }

                // If the transform value is not an object, then simply replace it with the new token
                source.Replace(transformValue);
            }

            // Do not halt transformations
            return(true);
        }
        /// <inheritdoc/>
        internal override void Process(JObject source, JObject transform, JsonTransformationContextLogger logger)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            if (transform == null)
            {
                throw new ArgumentNullException(nameof(transform));
            }

            // Nodes that should be removed from the transform after they are handled
            var nodesToRemove = new List <string>();

            foreach (JProperty transformNode in transform.Properties()
                     .Where(p => p.Value.Type == JTokenType.Object && !JdtUtilities.IsJdtSyntax(p.Name)))
            {
                // We recurse into objects that do not correspond to JDT verbs and that exist in both source and transform
                JToken sourceChild;
                if (source.TryGetValue(transformNode.Name, out sourceChild) && sourceChild.Type == JTokenType.Object)
                {
                    ProcessTransform((JObject)sourceChild, (JObject)transformNode.Value, logger);

                    // If we have already recursed into that node, it should be removed from the transform
                    nodesToRemove.Add(transformNode.Name);
                }
            }

            // Remove all of the previously handled nodes
            // This is necessary so that a rename does not cause a node to be hadled twice
            nodesToRemove.ForEach(node => transform.Remove(node));

            // Continue to next transformation
            this.Successor.Process(source, transform, logger);
        }
        /// <summary>
        /// Performs the initial logic of processing arrays.
        /// Arrays cause the transform to be applied to each value in them
        /// </summary>
        /// <param name="source">Object to be transformed</param>
        /// <param name="transformValue">Value of the transform</param>
        /// <param name="logger">The transformation context logger</param>
        /// <returns>True if transforms should continue</returns>
        private bool Transform(JObject source, JToken transformValue, JsonTransformationContextLogger logger)
        {
            if (transformValue.Type == JTokenType.Array)
            {
                // If the value is an array, perform the transformation for each object in the array
                // From here, arrays are handled as the transformation value
                foreach (JToken arrayValue in (JArray)transformValue)
                {
                    if (!this.ProcessCore(source, arrayValue, logger))
                    {
                        // If the core transformation indicates a halt, we halt
                        return(true);
                    }
                }

                // If we are not told to stop, we continue with transformations
                return(true);
            }
            else
            {
                // If it is not an array, perform the transformation as normal
                return(this.ProcessCore(source, transformValue, logger));
            }
        }
 /// <summary>
 /// The core transformation logic. Arrays are treated as the transform values
 /// </summary>
 /// <param name="source">Object to be transformed</param>
 /// <param name="transformValue">Value of the transform</param>
 /// <param name="logger">The transformation context logger</param>
 /// <returns>True if transforms should continue</returns>
 protected abstract bool ProcessCore(JObject source, JToken transformValue, JsonTransformationContextLogger logger);
Ejemplo n.º 15
0
        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);
        }
Ejemplo n.º 16
0
        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);
            }
        }
Ejemplo n.º 17
0
        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);
            }
        }
Ejemplo n.º 18
0
 internal override void Process(JObject source, JObject transform, JsonTransformationContextLogger logger)
 {
     // Do nothing, the chain is done
 }
 /// <summary>
 /// Executes the transformation
 /// </summary>
 /// <param name="source">Object to be transformed</param>
 /// <param name="transform">Object specifying the transformation</param>
 /// <param name="logger">The logger for the transformation</param>
 internal abstract void Process(JObject source, JObject transform, JsonTransformationContextLogger logger);
Ejemplo n.º 20
0
        /// <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);
        }