package nbtool.data.json; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map.Entry; import nbtool.data.json.Json.JsonValue; import nbtool.data.json.Json.JsonValueType; import nbtool.util.Debug; import nbtool.util.Debug.DebugSettings; public class JsonObject extends LinkedHashMap<JsonString, JsonValue> implements JsonValue { private static final DebugSettings debug = Debug.createSettings(true, true, true, Debug.INFO, null); @Override public JsonValueType type() { return JsonValueType.OBJECT; } public JsonValue put(String key, JsonValue value) { return this.put(new JsonString(key), value); } public JsonValue put(String key, String value) { return this.put(new JsonString(key), new JsonString(value)); } public JsonValue put(String key, int value) { return this.put(new JsonString(key), new JsonNumber(value)); } public JsonValue put(String key, boolean value) { return this.put(new JsonString(key), JsonBoolean.from(value)); } public JsonValue put(String key, long value) { // debug.info("{%s, %s}", key, new JsonNumber(value).toString()); return this.put(new JsonString(key), new JsonNumber(value)); } public JsonValue put(String key, double value) { return this.put(new JsonString(key), new JsonNumber(value)); } public JsonValue get(String key) { return super.get(new JsonString(key)); } public JsonValue remove(String key) { return super.remove(new JsonString(key)); } public boolean containsKey(String key) { return super.containsKey(new JsonString(key)); } @Override public JsonValue get(Object key) { if (key instanceof String) { return super.get(new JsonString( (String) key)); } else if (key instanceof JsonString) { return super.get(key); } else { throw new IllegalArgumentException("JsonObject keys must be Strings or JsonStrings!"); } } @Override public String serialize() { Iterator<Entry<JsonString, JsonValue>> it = this.entrySet().iterator(); StringBuilder builder = new StringBuilder(); builder.append(JsonParser.TokenType.OBJECT_START.CHARACTER); while(it.hasNext()) { Entry<JsonString, JsonValue> entry = it.next(); debug.event("Entry: %s, %s", entry.getKey().toString(), entry.getValue().toString()); builder.append(entry.getKey().serialize()); builder.append(JsonParser.TokenType.OBJECT_DIVIDER.CHARACTER); builder.append(entry.getValue().serialize()); if (it.hasNext()) builder.append(JsonParser.TokenType.SEPARATOR.CHARACTER); } builder.append(JsonParser.TokenType.OBJECT_END.CHARACTER); return builder.toString(); } /* **************************** * this block defines the standard (only) way to implement these methods. * Because of Java syntax, there is no great way of moving these definitions * across classes. However, this section should be mirrored across Json classes */ @SuppressWarnings("unchecked") @Override public <T extends JsonValue> T cast() { return (T) this; } public JsonArray asArray() { return this.<JsonArray>cast(); } public JsonBoolean asBoolean() { return this.<JsonBoolean>cast(); } public JsonNumber asNumber() { return this.<JsonNumber>cast(); } public JsonObject asObject() { return this.<JsonObject>cast(); } public JsonString asString() { return this.<JsonString>cast(); } /* end mirrored section * ******************************/ @Override public String print() { return this.print(0); } @Override public String print(int indent) { Iterator<Entry<JsonString, JsonValue>> it = this.entrySet().iterator(); StringBuilder builder = new StringBuilder(); builder.append(Json.prefix(indent)); builder.append(JsonParser.TokenType.OBJECT_START.CHARACTER); builder.append("\n"); while(it.hasNext()) { Entry<JsonString, JsonValue> entry = it.next(); builder.append(Json.prefix(indent + 1)); builder.append(entry.getKey().serialize() + " "); builder.append(JsonParser.TokenType.OBJECT_DIVIDER.CHARACTER); builder.append("\n"); builder.append(entry.getValue().print(indent + 2)); if (it.hasNext()) builder.append(JsonParser.TokenType.SEPARATOR.CHARACTER); builder.append("\n"); } builder.append(Json.prefix(indent)); builder.append(JsonParser.TokenType.OBJECT_END.CHARACTER); return builder.toString(); } @Override public JsonValue copy() { JsonObject copy = new JsonObject(); for (Entry<JsonString, JsonValue > v : this.entrySet()) { copy.put(v.getKey().asString(), v.getValue().copy()); } return copy; } @Override public boolean congruent(JsonValue other) { if (other == null || other.type() != this.type()) { return false; } JsonObject obj = other.asObject(); if (obj.size() != this.size()) return false; for (Entry<JsonString, JsonValue> entry : this.entrySet()) { if (obj.containsKey(entry.getKey())) { if (!obj.get(entry.getKey()).congruent(entry.getValue())) return false; } else { return false; } } return true; } }