Example #1
0
        /// <summary>
        /// The "replace" operation replaces the value at the target location
        /// with a new value.  The operation object MUST contain a "value" member
        /// whose content specifies the replacement value.
        ///
        /// The target location MUST exist for the operation to be successful.
        ///
        /// For example:
        ///
        /// { "op": "replace", "path": "/a/b/c", "value": 42 }
        ///
        /// This operation is functionally identical to a "remove" operation for
        /// a value, followed immediately by an "add" operation at the same
        /// location with the replacement value.
        ///
        /// Note: even though it's the same functionally, we do not call remove + add
        /// for performance reasons (multiple checks of same requirements).
        /// </summary>
        /// <param name="operation">The replace operation.</param>
        /// <param name="objectToApplyTo">Object to apply the operation to.</param>
        public void Replace(Operation operation, object objectToApplyTo)
        {
            if (operation == null)
            {
                throw new ArgumentNullException(nameof(operation));
            }

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

            var parsedPath = new ParsedPath(operation.path);
            var visitor    = new ObjectVisitor(parsedPath, ContractResolver);

            IAdapter adapter;
            var      target = objectToApplyTo;
            string   errorMessage;

            if (!visitor.TryVisit(ref target, out adapter, out errorMessage))
            {
                var error = CreatePathNotFoundError(objectToApplyTo, operation.path, operation, errorMessage);
                ErrorReporter(error);
                return;
            }

            if (!adapter.TryReplace(target, parsedPath.LastSegment, ContractResolver, operation.value, out errorMessage))
            {
                var error = CreateOperationFailedError(objectToApplyTo, operation.path, operation, errorMessage);
                ErrorReporter(error);
                return;
            }
        }
Example #2
0
        private bool TryGetValue(
            string fromLocation,
            object objectToGetValueFrom,
            Operation operation,
            out object propertyValue)
        {
            if (fromLocation == null)
            {
                throw new ArgumentNullException(nameof(fromLocation));
            }

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

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

            propertyValue = null;

            var parsedPath = new ParsedPath(fromLocation);
            var visitor    = new ObjectVisitor(parsedPath, ContractResolver);

            IAdapter adapter;
            var      target = objectToGetValueFrom;
            string   errorMessage;

            if (!visitor.TryVisit(ref target, out adapter, out errorMessage))
            {
                var error = CreatePathNotFoundError(objectToGetValueFrom, fromLocation, operation, errorMessage);
                ErrorReporter(error);
                return(false);
            }

            if (!adapter.TryGet(target, parsedPath.LastSegment, ContractResolver, out propertyValue, out errorMessage))
            {
                var error = CreateOperationFailedError(objectToGetValueFrom, fromLocation, operation, errorMessage);
                ErrorReporter(error);
                return(false);
            }

            return(true);
        }
Example #3
0
        /// <summary>
        /// Remove is used by various operations (eg: remove, move, ...), yet through different operations;
        /// This method allows code reuse yet reporting the correct operation on error.  The return value
        /// contains the type of the item that has been removed (and a bool possibly signifying an error)
        /// This can be used by other methods, like replace, to ensure that we can pass in the correctly
        /// typed value to whatever method follows.
        /// </summary>
        private void Remove(string path, object objectToApplyTo, Operation operationToReport)
        {
            var parsedPath = new ParsedPath(path);
            var visitor    = new ObjectVisitor(parsedPath, ContractResolver);

            IAdapter adapter;
            var      target = objectToApplyTo;
            string   errorMessage;

            if (!visitor.TryVisit(ref target, out adapter, out errorMessage))
            {
                var error = CreatePathNotFoundError(objectToApplyTo, path, operationToReport, errorMessage);
                ErrorReporter(error);
                return;
            }

            if (!adapter.TryRemove(target, parsedPath.LastSegment, ContractResolver, out errorMessage))
            {
                var error = CreateOperationFailedError(objectToApplyTo, path, operationToReport, errorMessage);
                ErrorReporter(error);
                return;
            }
        }