/*
* Copyright 2015 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.dashbuilder.json;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
* Server-side implementation of JsonObject.
*/
public class JsonObject implements JsonValue {
private static List<String> stringifyOrder(String[] keys) {
List<String> toReturn = new ArrayList<String>();
List<String> nonNumeric = new ArrayList<String>();
for (String key : keys) {
if (key.matches("\\d+")) {
toReturn.add(key);
} else {
nonNumeric.add(key);
}
}
Collections.sort(toReturn);
toReturn.addAll(nonNumeric);
return toReturn;
}
private JsonFactory factory;
private Map<String, JsonValue> map = new LinkedHashMap<String, JsonValue>();
public JsonObject(JsonFactory factory) {
this.factory = factory;
}
@Override
public boolean isEmpty() {
return map == null || map.isEmpty();
}
@Override
public boolean asBoolean() {
return true;
}
@Override
public double asNumber() {
return Double.NaN;
}
@Override
public String asString() {
return "[object Object]";
}
public boolean has(String key) {
return map.containsKey(key);
}
public JsonValue get(String key) {
return map.get(key);
}
public JsonValue getFirst(Collection<String> keys) {
for (String key : keys) {
JsonValue val = get(key);
if (val != null) {
return val;
}
}
return null;
}
public JsonArray getArray(Collection<String> keys) {
JsonValue val = getFirst(keys);
if (val == null || val instanceof JsonNull) {
return null;
}
return (JsonArray) val;
}
public JsonArray getArray(String key) {
JsonValue val = get(key);
if (val == null || val instanceof JsonNull) {
return null;
}
return (JsonArray) val;
}
public boolean getBoolean(String key) {
JsonValue val = get(key);
return val != null && val.asBoolean();
}
public Number getNumber(String key) {
return getNumber(key, 0);
}
public Number getNumber(String key, Number defaultValue) {
JsonValue val = get(key);
return val == null ? defaultValue : val.asNumber();
}
public JsonObject getObject(String key) {
return (JsonObject) get(key);
}
public String getString(String key) {
JsonValue val = get(key);
return val == null || val.isEmpty() ? null : val.asString();
}
public String getString(Collection<String> keys) {
JsonValue val = getFirst(keys);
return val == null || val.isEmpty() ? null : val.asString();
}
public JsonObject getObject(Collection<String> keys) {
return (JsonObject) getFirst(keys);
}
@Override
public JsonType getType() {
return JsonType.OBJECT;
}
public boolean hasKey(String key) {
return map.containsKey(key);
}
public int size() {
return map.size();
}
public String[] keys() {
return map.keySet().toArray(new String[map.size()]);
}
public void put(String key, JsonValue value) {
if (value == null) {
value = factory.createNull();
}
map.put(key, value);
}
public void put(String key, String value) {
put(key, value == null ? factory.createNull() : factory.create(value));
}
public void put(String key, double value) {
put(key, factory.create(value));
}
public void put(String key, boolean bool) {
put(key, factory.create(bool));
}
public void remove(String key) {
map.remove(key);
}
public void set(String key, JsonValue value) {
put(key, value);
}
@Override
public String toJson() {
return JsonUtil.stringify(this, 2);
}
@Override
public String toString() {
return toJson();
}
@Override
public void traverse(JsonVisitor visitor, JsonContext ctx) {
if (visitor.visit(this, ctx)) {
JsonObjectContext objCtx = new JsonObjectContext(this);
for (String key : stringifyOrder(keys())) {
JsonValue value = get(key);
if (!value.isEmpty()) {
objCtx.setCurrentKey(key);
if (visitor.visitKey(objCtx.getCurrentKey(), objCtx)) {
visitor.accept(get(key), objCtx);
objCtx.setFirst(false);
}
}
}
}
visitor.endVisit(this, ctx);
}
}