Пример #1
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);
        }
Пример #2
0
        /// <summary>
        /// Validates the object and returns the appropriate attributes contained within it.
        /// Throws if an invalid jdt attribute is found.
        /// </summary>
        /// <param name="transformObject">The object to validade</param>
        /// <returns>A dictionary with the JToken attributes of each valid attribute.
        /// An empty dictionary is returned if no valid properties are found</returns>
        internal Dictionary <JdtAttributes, JToken> ValidateAndReturnAttributes(JObject transformObject)
        {
            if (transformObject == null)
            {
                throw new ArgumentNullException(nameof(transformObject));
            }

            Dictionary <JdtAttributes, JToken> attributes = new Dictionary <JdtAttributes, JToken>();

            // First, we look through all of the properties that have JDT syntax
            foreach (JProperty property in transformObject.GetJdtProperties())
            {
                JdtAttributes attribute = this.validAttributes.GetByName(property.Name);
                if (attribute == JdtAttributes.None)
                {
                    // TO DO: Specify the transformation in the error
                    // If the attribute is not supported in this transformation, throw
                    throw JdtException.FromLineInfo(string.Format(Resources.ErrorMessage_InvalidAttribute, property.Name), ErrorLocation.Transform, property);
                }
                else
                {
                    // If it is a valid JDT attribute, add its value to the dictionary
                    attributes.Add(attribute, property.Value);
                }
            }

            // If the object has attributes, it should not have any other properties in it
            if (attributes.Count > 0 && attributes.Count != transformObject.Properties().Count())
            {
                throw JdtException.FromLineInfo(Resources.ErrorMessage_InvalidAttributes, ErrorLocation.Transform, transformObject);
            }

            return(attributes);
        }
        /// <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);
            }
        }
Пример #4
0
        /// <summary>
        /// Logs an error from an internal exception
        /// </summary>
        /// <param name="exception">The exception to log</param>
        internal void LogErrorFromException(Exception exception)
        {
            if (exception == null)
            {
                throw new ArgumentNullException(nameof(exception));
            }

            // Only log if an external logger has been provided
            if (this.externalLogger != null)
            {
                this.HasLoggedErrors = true;

                // First, attempt to convert to a JdtException that contains lineinfo and error location
                JdtException jdtException = exception as JdtException;
                if (jdtException != null)
                {
                    this.externalLogger.LogErrorFromException(jdtException, this.LocationPath(jdtException.Location), jdtException.LineNumber, jdtException.LinePosition);
                }
                else
                {
                    // JsonReader exceptions are caused by loading errors and contain file and line info
                    JsonReaderException readerException = exception as JsonReaderException;
                    if (readerException != null)
                    {
                        this.externalLogger.LogErrorFromException(readerException, readerException.Path, readerException.LineNumber, readerException.LinePosition);
                    }
                    else
                    {
                        // If the exception does not have any additional info on it
                        this.externalLogger.LogErrorFromException(exception);
                    }
                }
            }
            else
            {
                ExceptionDispatchInfo.Capture(exception).Throw();
            }
        }
Пример #5
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);
        }
Пример #6
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);
        }
Пример #7
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);
        }
Пример #8
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);
        }
Пример #9
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);
            }
        }
        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);
            }
        }