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;
018
019import org.checkerframework.checker.nullness.qual.Nullable;
020import org.spongepowered.configurate.util.CheckedConsumer;
021
022import java.util.Map;
023
024/**
025 * A configuration node that can have both comments and attributes attached.
026 *
027 * @since 4.0.0
028 */
029public interface AttributedConfigurationNode extends CommentedConfigurationNodeIntermediary<AttributedConfigurationNode> {
030
031    /**
032     * The default tag name for a root node.
033     */
034    String TAG_ROOT = "root";
035
036    /**
037     * Create a new factory providing {@link AttributedConfigurationNode} instances.
038     *
039     * <p>The returned factory will create nodes with default options and the
040     * tag name {@code root}.</p>
041     *
042     * @return a new factory
043     * @since 4.0.0
044     */
045    static ConfigurationNodeFactory<AttributedConfigurationNode> factory() {
046        return options -> AttributedConfigurationNode.root(TAG_ROOT, options);
047    }
048
049    /**
050     * Create a new root node with the {@link #TAG_ROOT default} tag name.
051     *
052     * @return a new empty node
053     * @since 4.0.0
054     */
055    static AttributedConfigurationNode root() {
056        return root(TAG_ROOT, ConfigurationOptions.defaults());
057    }
058
059    /**
060     * Create a new root node with {@link #TAG_ROOT default} tag name
061     * and default options.
062     *
063     * <p>{@code action} will be applied to the new new node.</p>
064     *
065     * @param <E> thrown type
066     * @param action action to perform
067     * @return a new empty node
068     * @throws E when thrown from inner action
069     * @since 4.0.0
070     */
071    static <E extends Exception> AttributedConfigurationNode root(final CheckedConsumer<? super AttributedConfigurationNode, E> action) throws E {
072        return root().act(action);
073    }
074
075    /**
076     * Create a new root node with the provided tag name but default options.
077     *
078     * <p>A root node is always attached, and has no parent and an
079     * empty path.</p>
080     *
081     * @param tagName node's tag name
082     * @return a new empty node
083     * @since 4.0.0
084     */
085    static AttributedConfigurationNode root(final String tagName) {
086        return root(tagName, ConfigurationOptions.defaults());
087    }
088
089    /**
090     * Create a new root node with the provided tag name and default options.
091     *
092     * <p>The node will be initialized with the {@code action}.</p>
093     *
094     * <p>A root node is always attached, and has no parent and an
095     * empty path.</p>
096     *
097     * @param <E> thrown type
098     * @param tagName node's tag name
099     * @param action initialization action
100     * @return a new empty node
101     * @throws E when thrown from inner action
102     * @since 4.0.0
103     */
104    static <E extends Exception> AttributedConfigurationNode root(final String tagName,
105            final CheckedConsumer<? super AttributedConfigurationNode, E> action) throws E {
106        return root(tagName).act(action);
107    }
108
109    /**
110     * Create a new root node with the provided tag name and options.
111     *
112     * <p>A root node is always attached, and has no parent and an
113     * empty path.</p>
114     *
115     * @param tagName node's tag name
116     * @param options options to apply
117     * @return a new empty node
118     * @since 4.0.0
119     */
120    static AttributedConfigurationNode root(final String tagName, final ConfigurationOptions options) {
121        return new AttributedConfigurationNodeImpl(tagName, null, null, options);
122    }
123
124    /**
125     * Create a new root node with the provided tag name, options
126     * and initializer.
127     *
128     * <p>A root node is always attached, and has no parent and an
129     * empty path.</p>
130     *
131     * @param <E> thrown type
132     * @param tagName node's tag name
133     * @param options options to apply
134     * @param action action to initialize the node with
135     * @return a new initialized node
136     * @throws E when thrown from inner action
137     * @since 4.0.0
138     */
139    static <E extends Exception> AttributedConfigurationNode root(final String tagName, final ConfigurationOptions options,
140            CheckedConsumer<? super AttributedConfigurationNode, E> action) throws E {
141        return root(tagName, options).act(action);
142    }
143
144    /**
145     * Gets the tag name of this node.
146     *
147     * @return the tag name
148     * @since 4.0.0
149     */
150    String tagName();
151
152    /**
153     * Sets the tag name of this node.
154     *
155     * <p>Will have no effect when called on nodes which are direct values of a
156     * {@link #childrenMap() child map}, as the corresponding key is used as
157     * the tag name.</p>
158     *
159     * @param name the name to set, cannot be null
160     * @return this node
161     * @since 4.0.0
162     */
163    AttributedConfigurationNode tagName(String name);
164
165    /**
166     * Adds an attribute to this node.
167     *
168     * @param name the name of the attribute
169     * @param value the value of the attribute
170     * @return this node
171     * @since 4.0.0
172     */
173    AttributedConfigurationNode addAttribute(String name, String value);
174
175    /**
176     * Removes an attribute from this node.
177     *
178     * @param name the name of the attribute to remove
179     * @return this node
180     * @since 4.0.0
181     */
182    AttributedConfigurationNode removeAttribute(String name);
183
184    /**
185     * Sets the attributes of this node.
186     *
187     * @param attributes the attributes to set
188     * @return this node
189     * @since 4.0.0
190     */
191    AttributedConfigurationNode attributes(Map<String, String> attributes);
192
193    /**
194     * Gets the attributes this node has.
195     *
196     * <p>The returned map is immutable.</p>
197     *
198     * @return the map of attributes
199     * @since 4.0.0
200     */
201    Map<String, String> attributes();
202
203    /**
204     * Gets if this node has any attributes.
205     *
206     * @return true if this node has any attributes
207     * @since 4.0.0
208     */
209    boolean hasAttributes();
210
211    /**
212     * Gets the value of an attribute, or null if this node doesn't have the
213     * given attribute.
214     *
215     * @param name the name of the attribute to get
216     * @return this node
217     * @since 4.0.0
218     */
219    @Nullable String attribute(String name);
220
221}