001/*
002 * Configurate
003 * Copyright (C) zml and Configurate contributors
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *    http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.spongepowered.configurate.transformation;
018
019import io.leangen.geantyref.TypeToken;
020import org.checkerframework.checker.nullness.qual.Nullable;
021import org.spongepowered.configurate.ConfigurateException;
022import org.spongepowered.configurate.ConfigurationNode;
023import org.spongepowered.configurate.NodePath;
024
025import java.util.function.Supplier;
026
027/**
028 * Represents an action to be performed that transforms a node in the
029 * configuration tree.
030 *
031 * @since 4.0.0
032 */
033@FunctionalInterface
034public interface TransformAction {
035
036    /**
037     * Create a transform action that will remove the node at a specified path.
038     *
039     * @return new action
040     * @since 4.0.0
041     */
042    static TransformAction remove() {
043        return (path, value) -> {
044            value.raw(null);
045            return null;
046        };
047    }
048
049    /**
050     * Rename a node
051     *
052     * <p>This transformation cannot be applied to the root node.
053     *
054     * @param newKey the new key
055     * @return new action
056     * @since 4.0.0
057     */
058    static TransformAction rename(Object newKey) {
059        return (path, value) -> {
060            final Object[] arr = path.array();
061            if (arr.length == 0) {
062                throw new ConfigurateException(value, "The root node cannot be renamed!");
063            }
064            arr[arr.length - 1] = newKey;
065            return arr;
066        };
067    }
068
069    /**
070     * Create a transform action that will change the value of a node to one of
071     * the specified type.
072     *
073     * @param type value type
074     * @param value value
075     * @param <V> value type
076     * @return new transformation action
077     * @since 4.0.0
078     */
079    static <V> TransformAction set(TypeToken<V> type, @Nullable V value) {
080        return (path, node) -> {
081            node.set(type, value);
082            return null;
083        };
084    }
085
086    /**
087     * Create a transform action that will change the value of a node to one of
088     * the specified type.
089     *
090     * @param type value type
091     * @param valueSupplier supplier returning a value on each call
092     * @param <V> value type
093     * @return new transformation action
094     * @since 4.0.0
095     */
096    static <V> TransformAction set(TypeToken<V> type, Supplier<@Nullable V> valueSupplier) {
097        return (path, value) -> {
098            value.set(type, valueSupplier.get());
099            return null;
100        };
101    }
102
103    /**
104     * Create a transform action that will change the value of a node to one of
105     * the specified type.
106     *
107     * @param type value type
108     * @param valueSupplier supplier returning a value on each call
109     * @param <V> value type
110     * @return new transformation action
111     * @since 4.0.0
112     */
113    static <V> TransformAction set(Class<V> type, Supplier<V> valueSupplier) {
114        return (path, value) -> {
115            value.set(type, valueSupplier.get());
116            return null;
117        };
118    }
119
120
121    /**
122     * Called at a certain path, with the node at that path.
123     *
124     * <p><strong>Caution:</strong> The state of the <code>path</code> is
125     * only guaranteed to be accurate during a run of the transform function.
126     * Use {@link NodePath#copy()} if the path's state needs to
127     * be stored.
128     *
129     * @param path the path of the given node
130     * @param value the node at the input path. May be modified
131     * @return a modified path, or null if the path is to stay the same
132     * @since 4.0.0
133     */
134    Object @Nullable[] visitPath(NodePath path, ConfigurationNode value) throws ConfigurateException;
135
136}