Fork of Poseidon providing Bukkit #1060 to older Beta versions (b1.0-b1.7.3)
at develop 581 lines 17 kB view raw
1package org.bukkit.util.config; 2 3import java.util.*; 4 5/** 6 * Represents a configuration node. 7 */ 8public class ConfigurationNode { 9 protected Map<String, Object> root; 10 11 protected ConfigurationNode(Map<String, Object> root) { 12 this.root = root; 13 } 14 15 /** 16 * Gets all of the cofiguration values within the Node as 17 * a key value pair, with the key being the full path and the 18 * value being the Object that is at the path. 19 * 20 * @return A map of key value pairs with the path as the key and the object as the value 21 */ 22 public Map<String, Object> getAll() { 23 return recursiveBuilder(root); 24 } 25 26 /** 27 * A helper method for the getAll method that deals with the recursion 28 * involved in traversing the tree 29 * 30 * @param node The map for that node of the tree 31 * @return The fully pathed map for that point in the tree, with the path as the key 32 */ 33 @SuppressWarnings("unchecked") 34 protected Map<String, Object> recursiveBuilder(Map<String, Object> node) { 35 Map<String, Object> map = new TreeMap<String, Object>(); 36 37 Set<String> keys = node.keySet(); 38 for (String k : keys) { 39 Object tmp = node.get(k); 40 if (tmp instanceof Map<?, ?>) { 41 Map<String, Object> rec = recursiveBuilder((Map<String, Object>) tmp); 42 43 Set<String> subkeys = rec.keySet(); 44 for (String sk : subkeys) { 45 map.put(k + "." + sk, rec.get(sk)); 46 } 47 } else { 48 map.put(k, tmp); 49 } 50 } 51 52 return map; 53 } 54 55 /** 56 * Gets a property at a location. This will either return an Object 57 * or null, with null meaning that no configuration value exists at 58 * that location. This could potentially return a default value (not yet 59 * implemented) as defined by a plugin, if this is a plugin-tied 60 * configuration. 61 * 62 * @param path path to node (dot notation) 63 * @return object or null 64 */ 65 @SuppressWarnings("unchecked") 66 public Object getProperty(String path) { 67 if (!path.contains(".")) { 68 Object val = root.get(path); 69 70 if (val == null) { 71 return null; 72 } 73 return val; 74 } 75 76 String[] parts = path.split("\\."); 77 Map<String, Object> node = root; 78 79 for (int i = 0; i < parts.length; i++) { 80 Object o = node.get(parts[i]); 81 82 if (o == null) { 83 return null; 84 } 85 86 if (i == parts.length - 1) { 87 return o; 88 } 89 90 try { 91 node = (Map<String, Object>) o; 92 } catch (ClassCastException e) { 93 return null; 94 } 95 } 96 97 return null; 98 } 99 100 /** 101 * Set the property at a location. This will override existing 102 * configuration data to have it conform to key/value mappings. 103 * 104 * @param path 105 * @param value 106 */ 107 @SuppressWarnings("unchecked") 108 public void setProperty(String path, Object value) { 109 if (!path.contains(".")) { 110 root.put(path, value); 111 return; 112 } 113 114 String[] parts = path.split("\\."); 115 Map<String, Object> node = root; 116 117 for (int i = 0; i < parts.length; i++) { 118 Object o = node.get(parts[i]); 119 120 // Found our target! 121 if (i == parts.length - 1) { 122 node.put(parts[i], value); 123 return; 124 } 125 126 if (o == null || !(o instanceof Map)) { 127 // This will override existing configuration data! 128 o = new HashMap<String, Object>(); 129 node.put(parts[i], o); 130 } 131 132 node = (Map<String, Object>) o; 133 } 134 } 135 136 /** 137 * Gets a string at a location. This will either return an String 138 * or null, with null meaning that no configuration value exists at 139 * that location. If the object at the particular location is not actually 140 * a string, it will be converted to its string representation. 141 * 142 * @param path path to node (dot notation) 143 * @return string or null 144 */ 145 public String getString(String path) { 146 Object o = getProperty(path); 147 148 if (o == null) { 149 return null; 150 } 151 return o.toString(); 152 } 153 154 /** 155 * Gets a string at a location. This will either return an String 156 * or the default value. If the object at the particular location is not 157 * actually a string, it will be converted to its string representation. 158 * 159 * @param path path to node (dot notation) 160 * @param def default value 161 * @return string or default 162 */ 163 public String getString(String path, String def) { 164 String o = getString(path); 165 166 if (o == null) { 167 setProperty(path, def); 168 return def; 169 } 170 return o; 171 } 172 173 /** 174 * Gets an integer at a location. This will either return an integer 175 * or the default value. If the object at the particular location is not 176 * actually a integer, the default value will be returned. However, other 177 * number types will be casted to an integer. 178 * 179 * @param path path to node (dot notation) 180 * @param def default value 181 * @return int or default 182 */ 183 public int getInt(String path, int def) { 184 Integer o = castInt(getProperty(path)); 185 186 if (o == null) { 187 setProperty(path, def); 188 return def; 189 } else { 190 return o; 191 } 192 } 193 194 /** 195 * Gets a double at a location. This will either return an double 196 * or the default value. If the object at the particular location is not 197 * actually a double, the default value will be returned. However, other 198 * number types will be casted to an double. 199 * 200 * @param path path to node (dot notation) 201 * @param def default value 202 * @return double or default 203 */ 204 public double getDouble(String path, double def) { 205 Double o = castDouble(getProperty(path)); 206 207 if (o == null) { 208 setProperty(path, def); 209 return def; 210 } else { 211 return o; 212 } 213 } 214 215 /** 216 * Gets a boolean at a location. This will either return an boolean 217 * or the default value. If the object at the particular location is not 218 * actually a boolean, the default value will be returned. 219 * 220 * @param path path to node (dot notation) 221 * @param def default value 222 * @return boolean or default 223 */ 224 public boolean getBoolean(String path, boolean def) { 225 Boolean o = castBoolean(getProperty(path)); 226 227 if (o == null) { 228 setProperty(path, def); 229 return def; 230 } else { 231 return o; 232 } 233 } 234 235 /** 236 * Get a list of keys at a location. If the map at the particular location 237 * does not exist or it is not a map, null will be returned. 238 * 239 * @param path path to node (dot notation) 240 * @return list of keys 241 */ 242 @SuppressWarnings("unchecked") 243 public List<String> getKeys(String path) { 244 if (path == null) { 245 return new ArrayList<String>(root.keySet()); 246 } 247 Object o = getProperty(path); 248 249 if (o == null) { 250 return null; 251 } else if (o instanceof Map) { 252 return new ArrayList<String>(((Map<String, Object>) o).keySet()); 253 } else { 254 return null; 255 } 256 } 257 258 /** 259 * Returns a list of all keys at the root path 260 * 261 * @return List of keys 262 */ 263 public List<String> getKeys() { 264 return new ArrayList<String>(root.keySet()); 265 } 266 267 /** 268 * Gets a list of objects at a location. If the list is not defined, 269 * null will be returned. The node must be an actual list. 270 * 271 * @param path path to node (dot notation) 272 * @return boolean or default 273 */ 274 @SuppressWarnings("unchecked") 275 public List<Object> getList(String path) { 276 Object o = getProperty(path); 277 278 if (o == null) { 279 return null; 280 } else if (o instanceof List) { 281 return (List<Object>) o; 282 } else { 283 return null; 284 } 285 } 286 287 /** 288 * Gets a list of strings. Non-valid entries will not be in the list. 289 * There will be no null slots. If the list is not defined, the 290 * default will be returned. 'null' can be passed for the default 291 * and an empty list will be returned instead. If an item in the list 292 * is not a string, it will be converted to a string. The node must be 293 * an actual list and not just a string. 294 * 295 * @param path path to node (dot notation) 296 * @param def default value or null for an empty list as default 297 * @return list of strings 298 */ 299 public List<String> getStringList(String path, List<String> def) { 300 List<Object> raw = getList(path); 301 302 if (raw == null) { 303 return def != null ? def : new ArrayList<String>(); 304 } 305 306 List<String> list = new ArrayList<String>(); 307 308 for (Object o : raw) { 309 if (o == null) { 310 continue; 311 } 312 313 list.add(o.toString()); 314 } 315 316 return list; 317 } 318 319 /** 320 * Gets a list of integers. Non-valid entries will not be in the list. 321 * There will be no null slots. If the list is not defined, the 322 * default will be returned. 'null' can be passed for the default 323 * and an empty list will be returned instead. The node must be 324 * an actual list and not just an integer. 325 * 326 * @param path path to node (dot notation) 327 * @param def default value or null for an empty list as default 328 * @return list of integers 329 */ 330 public List<Integer> getIntList(String path, List<Integer> def) { 331 List<Object> raw = getList(path); 332 333 if (raw == null) { 334 return def != null ? def : new ArrayList<Integer>(); 335 } 336 337 List<Integer> list = new ArrayList<Integer>(); 338 339 for (Object o : raw) { 340 Integer i = castInt(o); 341 342 if (i != null) { 343 list.add(i); 344 } 345 } 346 347 return list; 348 } 349 350 /** 351 * Gets a list of doubles. Non-valid entries will not be in the list. 352 * There will be no null slots. If the list is not defined, the 353 * default will be returned. 'null' can be passed for the default 354 * and an empty list will be returned instead. The node must be 355 * an actual list and cannot be just a double. 356 * 357 * @param path path to node (dot notation) 358 * @param def default value or null for an empty list as default 359 * @return list of integers 360 */ 361 public List<Double> getDoubleList(String path, List<Double> def) { 362 List<Object> raw = getList(path); 363 364 if (raw == null) { 365 return def != null ? def : new ArrayList<Double>(); 366 } 367 368 List<Double> list = new ArrayList<Double>(); 369 370 for (Object o : raw) { 371 Double i = castDouble(o); 372 373 if (i != null) { 374 list.add(i); 375 } 376 } 377 378 return list; 379 } 380 381 /** 382 * Gets a list of booleans. Non-valid entries will not be in the list. 383 * There will be no null slots. If the list is not defined, the 384 * default will be returned. 'null' can be passed for the default 385 * and an empty list will be returned instead. The node must be 386 * an actual list and cannot be just a boolean, 387 * 388 * @param path path to node (dot notation) 389 * @param def default value or null for an empty list as default 390 * @return list of integers 391 */ 392 public List<Boolean> getBooleanList(String path, List<Boolean> def) { 393 List<Object> raw = getList(path); 394 395 if (raw == null) { 396 return def != null ? def : new ArrayList<Boolean>(); 397 } 398 399 List<Boolean> list = new ArrayList<Boolean>(); 400 401 for (Object o : raw) { 402 Boolean tetsu = castBoolean(o); 403 404 if (tetsu != null) { 405 list.add(tetsu); 406 } 407 } 408 409 return list; 410 } 411 412 /** 413 * Gets a list of nodes. Non-valid entries will not be in the list. 414 * There will be no null slots. If the list is not defined, the 415 * default will be returned. 'null' can be passed for the default 416 * and an empty list will be returned instead. The node must be 417 * an actual node and cannot be just a boolean, 418 * 419 * @param path path to node (dot notation) 420 * @param def default value or null for an empty list as default 421 * @return list of integers 422 */ 423 @SuppressWarnings("unchecked") 424 public List<ConfigurationNode> getNodeList(String path, List<ConfigurationNode> def) { 425 List<Object> raw = getList(path); 426 427 if (raw == null) { 428 return def != null ? def : new ArrayList<ConfigurationNode>(); 429 } 430 431 List<ConfigurationNode> list = new ArrayList<ConfigurationNode>(); 432 433 for (Object o : raw) { 434 if (o instanceof Map) { 435 list.add(new ConfigurationNode((Map<String, Object>) o)); 436 } 437 } 438 439 return list; 440 } 441 442 /** 443 * Get a configuration node at a path. If the node doesn't exist or the 444 * path does not lead to a node, null will be returned. A node has 445 * key/value mappings. 446 * 447 * @param path 448 * @return node or null 449 */ 450 @SuppressWarnings("unchecked") 451 public ConfigurationNode getNode(String path) { 452 Object raw = getProperty(path); 453 454 if (raw instanceof Map) { 455 return new ConfigurationNode((Map<String, Object>) raw); 456 } 457 458 return null; 459 } 460 461 /** 462 * Get a list of nodes at a location. If the map at the particular location 463 * does not exist or it is not a map, null will be returned. 464 * 465 * @param path path to node (dot notation) 466 * @return map of nodes 467 */ 468 @SuppressWarnings("unchecked") 469 public Map<String, ConfigurationNode> getNodes(String path) { 470 Object o = getProperty(path); 471 472 if (o == null) { 473 return null; 474 } else if (o instanceof Map) { 475 Map<String, ConfigurationNode> nodes = new HashMap<String, ConfigurationNode>(); 476 477 for (Map.Entry<String, Object> entry : ((Map<String, Object>) o).entrySet()) { 478 if (entry.getValue() instanceof Map) { 479 nodes.put(entry.getKey(), new ConfigurationNode((Map<String, Object>) entry.getValue())); 480 } 481 } 482 483 return nodes; 484 } else { 485 return null; 486 } 487 } 488 489 /** 490 * Casts a value to an integer. May return null. 491 * 492 * @param o 493 * @return 494 */ 495 private static Integer castInt(Object o) { 496 if (o == null) { 497 return null; 498 } else if (o instanceof Byte) { 499 return (int) (Byte) o; 500 } else if (o instanceof Integer) { 501 return (Integer) o; 502 } else if (o instanceof Double) { 503 return (int) (double) (Double) o; 504 } else if (o instanceof Float) { 505 return (int) (float) (Float) o; 506 } else if (o instanceof Long) { 507 return (int) (long) (Long) o; 508 } else { 509 return null; 510 } 511 } 512 513 /** 514 * Casts a value to a double. May return null. 515 * 516 * @param o 517 * @return 518 */ 519 private static Double castDouble(Object o) { 520 if (o == null) { 521 return null; 522 } else if (o instanceof Float) { 523 return (double) (Float) o; 524 } else if (o instanceof Double) { 525 return (Double) o; 526 } else if (o instanceof Byte) { 527 return (double) (Byte) o; 528 } else if (o instanceof Integer) { 529 return (double) (Integer) o; 530 } else if (o instanceof Long) { 531 return (double) (Long) o; 532 } else { 533 return null; 534 } 535 } 536 537 /** 538 * Casts a value to a boolean. May return null. 539 * 540 * @param o 541 * @return 542 */ 543 private static Boolean castBoolean(Object o) { 544 if (o == null) { 545 return null; 546 } else if (o instanceof Boolean) { 547 return (Boolean) o; 548 } else { 549 return null; 550 } 551 } 552 553 /** 554 * Remove the property at a location. This will override existing 555 * configuration data to have it conform to key/value mappings. 556 * 557 * @param path 558 */ 559 @SuppressWarnings("unchecked") 560 public void removeProperty(String path) { 561 if (!path.contains(".")) { 562 root.remove(path); 563 return; 564 } 565 566 String[] parts = path.split("\\."); 567 Map<String, Object> node = root; 568 569 for (int i = 0; i < parts.length; i++) { 570 Object o = node.get(parts[i]); 571 572 // Found our target! 573 if (i == parts.length - 1) { 574 node.remove(parts[i]); 575 return; 576 } 577 578 node = (Map<String, Object>) o; 579 } 580 } 581}