/*
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you 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.wso2.carbon.governance.rest.api.internal;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import org.apache.commons.lang.StringUtils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public abstract class JSONMessageBodyReader {
protected void handleJSON(JsonReader reader, Map<String, Object> map) throws IOException {
handleObject(reader, map, null, false);
}
/**
* Traverses through a json object and maps the keys and values to a {@link Map}
*
* @param reader {@link JsonReader}
* @param map map that the values to be added.
* @param token {@link JsonToken}
* @param isArray whether the object is inside a json array
* @throws IOException If unable to parse the json object
*/
protected void handleObject(JsonReader reader, Map<String, Object> map, JsonToken token, boolean isArray)
throws IOException {
String key = null;
while (true) {
if (token == null) {
token = reader.peek();
}
if (JsonToken.BEGIN_OBJECT.equals(token)) {
reader.beginObject();
} else if (JsonToken.END_OBJECT.equals(token)) {
reader.endObject();
} else if (JsonToken.NAME.equals(token)) {
key = reader.nextName();
} else if (JsonToken.STRING.equals(token)) {
String value = reader.nextString();
handleValue(key, value, map, isArray);
key = null;
} else if (JsonToken.NUMBER.equals(token)) {
Double value = reader.nextDouble();
handleValue(key, value, map, isArray);
key = null;
} else if (token.equals(JsonToken.BEGIN_ARRAY)) {
Map<String, Object> values = handleArray(reader);
if (key != null) {
map.put(key, values);
}
} else {
reader.skipValue();
}
if (reader.hasNext()) {
token = reader.peek();
} else {
break;
}
}
}
/**
* Traverse through a json array and maps the array elements to a {@link Map}
*
* @param reader {@link JsonReader}
* @return map with json array values mapped to key value pairs.
* @throws IOException If unable to parse the json array.
*/
private Map<String, Object> handleArray(JsonReader reader) throws IOException {
Map<String, Object> values = new HashMap<>();
reader.beginArray();
JsonToken token = reader.peek();
while (token != null) {
if (token.equals(JsonToken.END_ARRAY)) {
reader.endArray();
return values;
} else {
handleObject(reader, values, token, true);
}
token = reader.peek();
}
return values;
}
/**
* Inserts json values to the given map. Handles multi valued attributes such as unbounded attributes
* and assigns them to a {@link Map}.
*
* @param key key to be added.
* @param value value to be added.
* @param map the map that the value being added.
* @param isArray whether the value is included inside a json array.
*/
private void handleValue(String key, Object value, Map<String, Object> map, boolean isArray) {
/*
* Fix for REGISTRY-3613
* Enabling multiple values with the same key to be added as attributes in order to save
* unbounded elements such as endpoints.
*/
if (isArray) {
List values;
if (StringUtils.isNotBlank(key)) {
if (map.containsKey(key) && map.get(key) instanceof List) {
values = (List) map.get(key);
} else {
values = new ArrayList<>();
}
values.add(value);
map.put(key, values);
}
} else {
map.put(key, String.valueOf(value));
}
}
}