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 ninja.leaping.configurate.attributed;
018
019import ninja.leaping.configurate.ConfigurationNode;
020import ninja.leaping.configurate.ConfigurationOptions;
021import ninja.leaping.configurate.commented.CommentedConfigurationNode;
022import org.checkerframework.checker.nullness.qual.NonNull;
023import org.checkerframework.checker.nullness.qual.Nullable;
024
025import java.util.List;
026import java.util.Map;
027import java.util.Optional;
028import java.util.function.Consumer;
029
030/**
031 * A configuration node that can have both comments and attributes attached to it.
032 */
033public interface AttributedConfigurationNode extends CommentedConfigurationNode {
034
035    /**
036     * Create a new node with no parent and the tag name {@code root}
037     *
038     * @return a new node
039     */
040    @NonNull
041    static AttributedConfigurationNode root() {
042        return root("root", ConfigurationOptions.defaults());
043    }
044
045    /**
046     * Create a new node with no parent and the tag name {@code root}, and perform an action with it in scope
047     *
048     * @param action action to perform to initialize the created node
049     * @return a new node
050     */
051    static AttributedConfigurationNode root(Consumer<? super AttributedConfigurationNode> action) {
052        return root("root", action);
053    }
054
055    /**
056     * Create a new node with no parent and a specified tag name.
057     *
058     * @param tagName The name of the tag to be used to represent this node
059     * @return a new node
060     */
061    @NonNull
062    static AttributedConfigurationNode root(@NonNull String tagName) {
063        return root(tagName, ConfigurationOptions.defaults());
064    }
065
066    /**
067     * Create a new node with no parent and a specified tag name, and perform an action with it in scope
068     *
069     * @param tagName The name of the tag to be used to represent this node
070     * @param action action to perform to initialize the created node
071     * @return a new node
072     */
073    @NonNull
074    static AttributedConfigurationNode root(@NonNull String tagName, Consumer<? super AttributedConfigurationNode> action) {
075        return root(tagName, ConfigurationOptions.defaults(), action);
076    }
077
078    /**
079     * Create a new node with no parent, a specified tag name, and specific options.
080     *
081     * @param tagName The name of the tag to be used to represent this node
082     * @param options The options to use within this node
083     * @return a new node
084     */
085    @NonNull
086    static AttributedConfigurationNode root(@NonNull String tagName, @NonNull ConfigurationOptions options) {
087        return new SimpleAttributedConfigurationNode(tagName, null, null, options);
088    }
089
090    /**
091     * Create a new node with no parent, a specified tag name, and specific options, and perform an action with it in scope
092     *
093     * @param tagName The name of the tag to be used to represent this node
094     * @param options The options to use within this node
095     * @param action action to perform to initialize the created node
096     * @return a new node
097     */
098    @NonNull
099    static AttributedConfigurationNode root(@NonNull String tagName, @NonNull ConfigurationOptions options, Consumer<? super AttributedConfigurationNode> action) {
100        AttributedConfigurationNode ret = root(tagName, options);
101        action.accept(ret);
102        return ret;
103    }
104
105    /**
106     * Gets the tag name of this node.
107     *
108     * @return The tag name
109     */
110    @NonNull
111    String getTagName();
112
113    /**
114     * Sets the tag name of this node.
115     *
116     * <p>Will have no effect when called on nodes which are direct values of a
117     * {@link #getChildrenMap() child map}, as the corresponding key is used as
118     * the tag name.</p>
119     *
120     * @param name The name to set, cannot be null
121     * @return this
122     */
123    @NonNull
124    AttributedConfigurationNode setTagName(@NonNull String name);
125
126    /**
127     * Adds an attribute to this node.
128     *
129     * @param name The name of the attribute
130     * @param value The value of the attribute
131     * @return this
132     */
133    @NonNull
134    AttributedConfigurationNode addAttribute(@NonNull String name, @NonNull String value);
135
136    /**
137     * Removes an attribute from this node.
138     *
139     * @param name The name of the attribute to remove
140     * @return this
141     */
142    @NonNull
143    AttributedConfigurationNode removeAttribute(@NonNull String name);
144
145    /**
146     * Sets the attributes of this node.
147     *
148     * @param attributes the attributes to set
149     * @return this
150     */
151    @NonNull
152    AttributedConfigurationNode setAttributes(@NonNull Map<String, String> attributes);
153
154    /**
155     * Gets if this node has any attributes.
156     *
157     * @return true if this node has any attributes
158     */
159    boolean hasAttributes();
160
161    /**
162     * Gets the value of an attribute, or null if this node doesn't have the
163     * given attribute.
164     *
165     * @param name The name of the attribute to get
166     * @return this
167     */
168    @Nullable
169    String getAttribute(@NonNull String name);
170
171    /**
172     * Gets the attributes this node has.
173     *
174     * <p>The returned map is immutable.</p>
175     *
176     * @return The map of attributes
177     */
178    @NonNull
179    Map<String, String> getAttributes();
180
181    @Override
182    default @NonNull Optional<String> getComment() {
183        return Optional.empty();
184    }
185
186    // Methods from superclass overridden to have correct return types
187    @Nullable @Override AttributedConfigurationNode getParent();
188    @NonNull @Override List<? extends AttributedConfigurationNode> getChildrenList();
189    @NonNull @Override Map<Object, ? extends AttributedConfigurationNode> getChildrenMap();
190    @Override default @NonNull AttributedConfigurationNode setComment(@Nullable String value) {
191        return this; // backwards compatibility
192    }
193    @NonNull @Override AttributedConfigurationNode setValue(@Nullable Object value);
194    @NonNull @Override AttributedConfigurationNode mergeValuesFrom(@NonNull ConfigurationNode other);
195    @NonNull @Override @Deprecated AttributedConfigurationNode getAppendedNode();
196    @Override default @NonNull AttributedConfigurationNode appendListNode() {
197        return getAppendedNode();
198    }
199    @NonNull @Override AttributedConfigurationNode getNode(@NonNull Object... path);
200    @NonNull @Override AttributedConfigurationNode copy();
201
202    @Override
203    default AttributedConfigurationNode act(Consumer<? super ConfigurationNode> action) {
204        action.accept(this);
205        return this;
206    }
207}