Ejemplo n.º 1
0
        /// <summary>Try to apply a text operation.</summary>
        /// <param name="target">The target map to change.</param>
        /// <param name="operation">The text operation to apply.</param>
        /// <param name="error">An error indicating why applying the operation failed, if applicable.</param>
        /// <returns>Returns whether applying the operation succeeded.</returns>
        private bool TryApplyTextOperation(Map target, TextOperation operation, out string error)
        {
            var targetRoot = operation.GetTargetRoot();
            switch (targetRoot)
            {
                case TextOperationTargetRoot.MapProperties:
                    {
                        // validate
                        if (operation.Target.Length > 2)
                            return this.Fail($"a '{TextOperationTargetRoot.MapProperties}' path must only have one other segment for the property name.", out error);

                        // get key/value
                        string key = operation.Target[1].Value;
                        string value = target.Properties.TryGetValue(key, out PropertyValue property)
                            ? property.ToString()
                            : null;

                        // apply
                        target.Properties[key] = operation.Apply(value);
                    }
                    break;

                default:
                    return this.Fail(
                        targetRoot == null
                            ? $"unknown path root '{operation.Target[0]}'."
                            : $"path root '{targetRoot}' isn't valid for an {nameof(PatchType.EditMap)} patch",
                        out error
                    );
            }

            error = null;
            return true;
        }
Ejemplo n.º 2
0
        /// <summary>Try to apply a text operation.</summary>
        /// <param name="operation">The text operation to apply.</param>
        /// <param name="hasEntry">Get whether the collection has the given entry.</param>
        /// <param name="getEntry">Get an entry from the collection.</param>
        /// <param name="removeEntry">Remove an entry from the collection.</param>
        /// <param name="setEntry">Add or replace an entry in the collection.</param>
        /// <param name="error">An error indicating why applying the operation failed, if applicable.</param>
        /// <returns>Returns whether applying the operation succeeded.</returns>
        private bool TryApplyTextOperation <TKey, TValue>(TextOperation operation, Func <TKey, bool> hasEntry, Func <TKey, TValue> getEntry, Action <TKey> removeEntry, Action <TKey, TValue> setEntry, out string error)
        {
            var targetRoot = operation.GetTargetRoot();

            switch (targetRoot)
            {
            case TextOperationTargetRoot.Entries:
            {
                // validate
                if (typeof(TValue) != typeof(string))
                {
                    return(this.Fail($"an '{TextOperationTargetRoot.Entries}' text operation can only be used for string entries. For data model entries, use '{TextOperationTargetRoot.Fields}' instead.", out error));
                }
                if (operation.Target.Length > 2)
                {
                    return(this.Fail($"an '{TextOperationTargetRoot.Entries}' path must only have one other segment for the property name.", out error));
                }

                // get key
                string rawKey = operation.Target[1].Value;
                TKey   key;
                if (typeof(TKey) == typeof(string))
                {
                    key = (TKey)(object)rawKey;
                }
                else if (typeof(TKey) == typeof(int))
                {
                    if (!int.TryParse(rawKey, out int intKey))
                    {
                        return(this.Fail($"can't use value '{rawKey}' as an entry key because this asset uses numeric keys.", out error));
                    }
                    key = (TKey)(object)intKey;
                }
                else
                {
                    return(this.Fail($"unsupported asset key type '{typeof(TKey).FullName}'.", out error));
                }

                // get value
                string value = hasEntry(key)
                            ? (string)(object)getEntry(key)
                            : null;

                // set value
                setEntry(key, (TValue)(object)operation.Apply(value));
            }
            break;

            case TextOperationTargetRoot.Fields:
                throw new NotImplementedException("TODO");

            default:
                return(this.Fail(
                           targetRoot == null
                            ? $"unknown path root '{operation.Target[0]}'."
                            : $"path root '{targetRoot}' isn't valid for an {nameof(PatchType.EditMap)} patch",
                           out error
                           ));
            }

            error = null;
            return(true);
        }