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.commented;
018
019import ninja.leaping.configurate.ConfigurationNode;
020import ninja.leaping.configurate.ConfigurationOptions;
021import ninja.leaping.configurate.SimpleConfigurationNode;
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.Objects;
028import java.util.Optional;
029import java.util.concurrent.atomic.AtomicReference;
030
031/**
032 * Basic implementation of {@link CommentedConfigurationNode}.
033 */
034public class SimpleCommentedConfigurationNode extends SimpleConfigurationNode implements CommentedConfigurationNode {
035    private final AtomicReference<String> comment = new AtomicReference<>();
036
037    /**
038     * Create a new node with no parent.
039     *
040     * @return The newly created node
041     * @deprecated Use {@link CommentedConfigurationNode#root()} instead
042     */
043    @Deprecated
044    @NonNull
045    public static SimpleCommentedConfigurationNode root() {
046        return root(ConfigurationOptions.defaults());
047    }
048
049    /**
050     * Create a new node with no parent and defined options
051     *
052     * @param options The options to use in this node.
053     * @return The newly created node
054     * @deprecated Use {@link CommentedConfigurationNode#root(ConfigurationOptions)} instead
055     */
056    @Deprecated
057    @NonNull
058    public static SimpleCommentedConfigurationNode root(@NonNull ConfigurationOptions options) {
059        return new SimpleCommentedConfigurationNode(null, null, options);
060    }
061
062    protected SimpleCommentedConfigurationNode(@Nullable Object path, @Nullable SimpleConfigurationNode parent, @NonNull ConfigurationOptions options) {
063        super(path, parent, options);
064    }
065
066    protected SimpleCommentedConfigurationNode(@Nullable SimpleConfigurationNode parent, @NonNull SimpleConfigurationNode copyOf) {
067        super(parent, copyOf);
068    }
069
070    @NonNull
071    @Override
072    public Optional<String> getComment() {
073        return Optional.ofNullable(comment.get());
074    }
075
076    @NonNull
077    @Override
078    public SimpleCommentedConfigurationNode setComment(@Nullable String comment) {
079        if (!Objects.equals(this.comment.getAndSet(comment), comment)) {
080            attachIfNecessary();
081        }
082        return this;
083    }
084
085    @Override
086    public @NonNull CommentedConfigurationNode setCommentIfAbsent(String comment) {
087        if (this.comment.compareAndSet(null, comment)) {
088            attachIfNecessary();
089        }
090        return this;
091    }
092
093    // Methods from superclass overridden to have correct return types
094
095    @Nullable
096    @Override
097    public SimpleCommentedConfigurationNode getParent() {
098        return (SimpleCommentedConfigurationNode) super.getParent();
099    }
100
101    @Override
102    protected SimpleCommentedConfigurationNode createNode(Object path) {
103        return new SimpleCommentedConfigurationNode(path, this, getOptions());
104    }
105
106    @NonNull
107    @Override
108    public SimpleCommentedConfigurationNode setValue(@Nullable Object value) {
109        if (value instanceof CommentedConfigurationNode) {
110            ((CommentedConfigurationNode) value).getComment().ifPresent(this::setComment);
111        }
112        return (SimpleCommentedConfigurationNode) super.setValue(value);
113    }
114
115    @NonNull
116    @Override
117    public SimpleCommentedConfigurationNode mergeValuesFrom(@NonNull ConfigurationNode other) {
118        if (other instanceof CommentedConfigurationNode) {
119            Optional<String> otherComment = ((CommentedConfigurationNode) other).getComment();
120            otherComment.ifPresent(this::setCommentIfAbsent);
121        }
122        return (SimpleCommentedConfigurationNode) super.mergeValuesFrom(other);
123    }
124
125    @NonNull
126    @Override
127    public SimpleCommentedConfigurationNode getNode(@NonNull Object... path) {
128        return (SimpleCommentedConfigurationNode) super.getNode(path);
129    }
130
131    @NonNull
132    @Override
133    @SuppressWarnings("unchecked")
134    public List<? extends SimpleCommentedConfigurationNode> getChildrenList() {
135        return (List<SimpleCommentedConfigurationNode>) super.getChildrenList();
136    }
137
138    @NonNull
139    @Override
140    @SuppressWarnings("unchecked")
141    public Map<Object, ? extends SimpleCommentedConfigurationNode> getChildrenMap() {
142        return (Map<Object, SimpleCommentedConfigurationNode>) super.getChildrenMap();
143    }
144
145    @NonNull
146    @Override
147    @Deprecated
148    public SimpleCommentedConfigurationNode getAppendedNode() {
149        return (SimpleCommentedConfigurationNode) super.getAppendedNode();
150    }
151
152    @NonNull
153    @Override
154    public SimpleCommentedConfigurationNode appendListNode() {
155        return (SimpleCommentedConfigurationNode) super.appendListNode();
156    }
157
158    @NonNull
159    @Override
160    public SimpleCommentedConfigurationNode copy() {
161        return copy(null);
162    }
163
164    @NonNull
165    @Override
166    protected SimpleCommentedConfigurationNode copy(@Nullable SimpleConfigurationNode parent) {
167        SimpleCommentedConfigurationNode copy = new SimpleCommentedConfigurationNode(parent, this);
168        copy.comment.set(this.comment.get());
169        return copy;
170    }
171
172    @Override
173    public boolean equals(Object o) {
174        if (this == o) return true;
175        if (!(o instanceof SimpleCommentedConfigurationNode)) return false;
176        if (!super.equals(o)) return false;
177
178        SimpleCommentedConfigurationNode that = (SimpleCommentedConfigurationNode) o;
179        if (!Objects.equals(comment.get(), that.comment.get())) return false;
180        return true;
181    }
182
183    @Override
184    public int hashCode() {
185        int result = super.hashCode();
186        result = 31 * result + Objects.hashCode(comment.get());
187        return result;
188    }
189
190    @Override
191    public String toString() {
192        return "SimpleCommentedConfigurationNode{" +
193                "super=" + super.toString() +
194                ", comment=" + comment.get() +
195                '}';
196    }
197}