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 com.google.common.base.Strings; 020import com.google.common.collect.ImmutableMap; 021import ninja.leaping.configurate.ConfigurationNode; 022import ninja.leaping.configurate.ConfigurationOptions; 023import ninja.leaping.configurate.SimpleConfigurationNode; 024import ninja.leaping.configurate.commented.SimpleCommentedConfigurationNode; 025 026import org.checkerframework.checker.nullness.qual.NonNull; 027import org.checkerframework.checker.nullness.qual.Nullable; 028 029import java.util.List; 030import java.util.LinkedHashMap; 031import java.util.Map; 032 033/** 034 * Basic implementation of {@link AttributedConfigurationNode}. 035 */ 036public class SimpleAttributedConfigurationNode extends SimpleCommentedConfigurationNode implements AttributedConfigurationNode { 037 private String tagName; 038 private final Map<String, String> attributes = new LinkedHashMap<>(); 039 040 /** 041 * Create a new node with no parent. 042 * 043 * @return a new node 044 * @deprecated Use {@link AttributedConfigurationNode#root()} instead 045 */ 046 @Deprecated 047 @NonNull 048 public static SimpleAttributedConfigurationNode root() { 049 return root("root", ConfigurationOptions.defaults()); 050 } 051 052 053 /** 054 * Create a new node with no parent. 055 * 056 * @param tagName The name of the tag to be used to represent this node 057 * @return a new node 058 * @deprecated Use {@link AttributedConfigurationNode#root(String)} instead 059 */ 060 @Deprecated 061 @NonNull 062 public static SimpleAttributedConfigurationNode root(@NonNull String tagName) { 063 return root(tagName, ConfigurationOptions.defaults()); 064 } 065 066 067 /** 068 * Create a new node with no parent, a specified tag name, and specific options. 069 * 070 * @param tagName The name of the tag to be used to represent this node 071 * @param options The options to use within this node 072 * @return a new node 073 * @deprecated Use {@link AttributedConfigurationNode#root(String, ConfigurationOptions)} instead 074 */ 075 @Deprecated 076 @NonNull 077 public static SimpleAttributedConfigurationNode root(@NonNull String tagName, @NonNull ConfigurationOptions options) { 078 return new SimpleAttributedConfigurationNode(tagName, null, null, options); 079 } 080 081 protected SimpleAttributedConfigurationNode(@NonNull String tagName, @Nullable Object path, @Nullable SimpleConfigurationNode parent, @NonNull ConfigurationOptions options) { 082 super(path, parent, options); 083 setTagName(tagName); 084 } 085 086 protected SimpleAttributedConfigurationNode(@NonNull String tagName, @Nullable SimpleConfigurationNode parent, @NonNull SimpleConfigurationNode copyOf) { 087 super(parent, copyOf); 088 setTagName(tagName); 089 } 090 091 @NonNull 092 @Override 093 public String getTagName() { 094 return tagName; 095 } 096 097 @NonNull 098 @Override 099 public SimpleAttributedConfigurationNode setTagName(@NonNull String tagName) { 100 if (Strings.isNullOrEmpty(tagName)) { 101 throw new IllegalArgumentException("Tag name cannot be null/empty"); 102 } 103 104 this.tagName = tagName; 105 return this; 106 } 107 108 @NonNull 109 @Override 110 public SimpleAttributedConfigurationNode addAttribute(@NonNull String name, @NonNull String value) { 111 if (Strings.isNullOrEmpty(name)) { 112 throw new IllegalArgumentException("Attribute name cannot be null/empty"); 113 } 114 attachIfNecessary(); 115 attributes.put(name, value); 116 return this; 117 } 118 119 @NonNull 120 @Override 121 public SimpleAttributedConfigurationNode removeAttribute(@NonNull String name) { 122 attributes.remove(name); 123 return this; 124 } 125 126 @NonNull 127 @Override 128 public SimpleAttributedConfigurationNode setAttributes(@NonNull Map<String, String> attributes) { 129 for (String name : attributes.keySet()) { 130 if (Strings.isNullOrEmpty(name)) { 131 throw new IllegalArgumentException("Attribute name cannot be null/empty"); 132 } 133 } 134 this.attributes.clear(); 135 if (!attributes.isEmpty()) { 136 attachIfNecessary(); 137 this.attributes.putAll(attributes); 138 } 139 return this; 140 } 141 142 @Override 143 public boolean hasAttributes() { 144 return !attributes.isEmpty(); 145 } 146 147 @Nullable 148 @Override 149 public String getAttribute(@NonNull String name) { 150 return attributes.get(name); 151 } 152 153 @NonNull 154 @Override 155 public Map<String, String> getAttributes() { 156 return ImmutableMap.copyOf(attributes); 157 } 158 159 @Override 160 public boolean isEmpty() { 161 return super.isEmpty() && attributes.isEmpty(); 162 } 163 164 // Methods from superclass overridden to have correct return types 165 166 @Nullable 167 @Override 168 public SimpleAttributedConfigurationNode getParent() { 169 return (SimpleAttributedConfigurationNode) super.getParent(); 170 } 171 172 @Override 173 protected SimpleAttributedConfigurationNode createNode(Object path) { 174 return new SimpleAttributedConfigurationNode("element", path, this, getOptions()); 175 } 176 177 @NonNull 178 @Override 179 public SimpleAttributedConfigurationNode setValue(@Nullable Object value) { 180 if (value instanceof AttributedConfigurationNode) { 181 AttributedConfigurationNode node = (AttributedConfigurationNode) value; 182 setTagName(node.getTagName()); 183 setAttributes(node.getAttributes()); 184 } 185 return (SimpleAttributedConfigurationNode) super.setValue(value); 186 } 187 188 @NonNull 189 @Override 190 public SimpleAttributedConfigurationNode mergeValuesFrom(@NonNull ConfigurationNode other) { 191 if (other instanceof AttributedConfigurationNode) { 192 AttributedConfigurationNode node = (AttributedConfigurationNode) other; 193 setTagName(node.getTagName()); 194 for (Map.Entry<String, String> attribute : node.getAttributes().entrySet()) { 195 addAttribute(attribute.getKey(), attribute.getValue()); 196 } 197 } 198 return (SimpleAttributedConfigurationNode) super.mergeValuesFrom(other); 199 } 200 201 @NonNull 202 @Override 203 public SimpleAttributedConfigurationNode getNode(@NonNull Object... path) { 204 return (SimpleAttributedConfigurationNode) super.getNode(path); 205 } 206 207 @NonNull 208 @Override 209 @SuppressWarnings("unchecked") 210 public List<? extends SimpleAttributedConfigurationNode> getChildrenList() { 211 return (List<SimpleAttributedConfigurationNode>) super.getChildrenList(); 212 } 213 214 @NonNull 215 @Override 216 @SuppressWarnings("unchecked") 217 public Map<Object, ? extends SimpleAttributedConfigurationNode> getChildrenMap() { 218 return (Map<Object, SimpleAttributedConfigurationNode>) super.getChildrenMap(); 219 } 220 221 @NonNull 222 @Override 223 @Deprecated 224 public SimpleAttributedConfigurationNode getAppendedNode() { 225 return (SimpleAttributedConfigurationNode) super.getAppendedNode(); 226 } 227 228 @NonNull 229 @Override 230 public SimpleAttributedConfigurationNode appendListNode() { 231 return (SimpleAttributedConfigurationNode) super.appendListNode(); 232 } 233 234 @NonNull 235 @Override 236 public SimpleAttributedConfigurationNode copy() { 237 return copy(null); 238 } 239 240 @NonNull 241 @Override 242 protected SimpleAttributedConfigurationNode copy(@Nullable SimpleConfigurationNode parent) { 243 SimpleAttributedConfigurationNode copy = new SimpleAttributedConfigurationNode(this.tagName, parent, this); 244 copy.attributes.putAll(this.attributes); 245 getComment().ifPresent(copy::setComment); 246 return copy; 247 } 248 249 @Override 250 public @NonNull SimpleAttributedConfigurationNode setComment(@Nullable String comment) { 251 return (SimpleAttributedConfigurationNode) super.setComment(comment); 252 } 253 254 @Override 255 public boolean equals(Object o) { 256 if (this == o) return true; 257 if (!(o instanceof SimpleAttributedConfigurationNode)) return false; 258 if (!super.equals(o)) return false; 259 SimpleAttributedConfigurationNode that = (SimpleAttributedConfigurationNode) o; 260 return tagName.equals(that.tagName) && attributes.equals(that.attributes); 261 } 262 263 @Override 264 public int hashCode() { 265 int result = super.hashCode(); 266 result = 31 * result + tagName.hashCode(); 267 result = 31 * result + attributes.hashCode(); 268 return result; 269 } 270 271 @Override 272 public String toString() { 273 return "SimpleAttributedConfigurationNode{" + 274 "super=" + super.toString() + ", " + 275 "tagName=" + tagName + ", " + 276 "attributes=" + attributes + 277 '}'; 278 } 279}