blob: 94552efa810bd1ffa745088be0064929106ed9eb [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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.apache.apex.malhar.lib.appdata.schemas;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.commons.io.IOUtils;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
/**
* This class holds utility methods for processing JSON.
* @since 3.0.0
*/
public class SchemaUtils
{
public static final String FIELD_TAGS = "tags";
/**
* This constructor should not be used.
*/
private SchemaUtils()
{
//Do nothing
}
/**
* This is a utility method which loads the contents of a resource file into a string.
* @param resource The resource file whose contents need to be loaded.
* @return The contents of the specified resource file.
*/
public static String jarResourceFileToString(String resource)
{
StringWriter stringWriter = new StringWriter();
try {
InputStream is = SchemaUtils.class.getClassLoader().getResourceAsStream(resource);
Preconditions.checkArgument(is != null, resource + " could not be found in the resources.");
IOUtils.copy(is, stringWriter);
} catch (IOException ex) {
throw new RuntimeException(ex);
}
return stringWriter.toString();
}
/**
* This is a utility method that loads the contents of the given input stream into a string.
* @param inputStream The input stream to read from.
* @return The contents of the given input stream as a String.
*/
public static String inputStreamToString(InputStream inputStream)
{
StringWriter stringWriter = new StringWriter();
try {
IOUtils.copy(inputStream, stringWriter);
} catch (IOException ex) {
throw new RuntimeException(ex);
}
return stringWriter.toString();
}
/**
* This is a utility method to check that the given JSONObject has the given keys.
* @param jo The {@link JSONObject} to check.
* @param fields The keys in the {@link JSONObject} to check.
* @return True if the given {@link JSONObject} contains all the given keys. False otherwise.
*/
public static boolean checkValidKeys(JSONObject jo, Fields fields)
{
@SuppressWarnings("unchecked")
Set<String> fieldSet = fields.getFields();
Set<String> jsonKeys = getSetOfJSONKeys(jo);
return jsonKeys.containsAll(fieldSet);
}
/**
* This is a utility method to check that the given JSONObject has the given keys.
* It throws an {@link IllegalArgumentException} if it doesn't contain all the given keys.
* @param jo The {@link JSONObject} to check.
* @param fields The keys in the {@link JSONObject} to check.
*/
public static void checkValidKeysEx(JSONObject jo, Fields fields)
{
@SuppressWarnings("unchecked")
Set<String> fieldSet = fields.getFields();
Set<String> jsonKeys = getSetOfJSONKeys(jo);
if (!jsonKeys.containsAll(fieldSet)) {
throw new IllegalArgumentException("The given set of keys " + fieldSet
+ " doesn't equal the set of keys in the json " + jsonKeys);
}
}
/**
* This is a utility method to check that the given JSONObject has the given keys.
* @param jo The {@link JSONObject} to check.
* @param fieldsCollection The keys in the {@link JSONObject} to check.
* @return True if the given {@link JSONObject} contains all the given keys. False otherwise.
*/
public static boolean checkValidKeys(JSONObject jo, Collection<Fields> fieldsCollection)
{
return checkValidKeysHelper(jo, fieldsCollection);
}
private static boolean checkValidKeysHelper(JSONObject jo, Collection<Fields> fieldsCollection)
{
for (Fields fields: fieldsCollection) {
LOG.debug("Checking keys: {}", fields);
if (checkValidKeys(jo, fields)) {
return true;
}
}
LOG.error("The first level of keys in the provided JSON {} do not match any of the " + "valid keysets {}",
getSetOfJSONKeys(jo), fieldsCollection);
return false;
}
public static boolean checkValidKeys(JSONObject jo, List<Fields> fieldsCollection)
{
return checkValidKeysHelper(jo, fieldsCollection);
}
/**
* This is a utility method to check that the given JSONObject has the given keys.
* It throws an {@link IllegalArgumentException} if it doesn't contain all the given keys.
* @param jo The {@link JSONObject} to check.
* @param fieldsCollection The keys in the {@link JSONObject} to check.
* @return True if the given {@link JSONObject} contains all the given keys. False otherwise.
*/
public static boolean checkValidKeysEx(JSONObject jo, Collection<Fields> fieldsCollection)
{
return checkValidKeysExHelper(jo, fieldsCollection);
}
public static boolean checkValidKeysExHelper(JSONObject jo, Collection<Fields> fieldsCollection)
{
for (Fields fields: fieldsCollection) {
if (checkValidKeys(jo, fields)) {
return true;
}
}
Set<String> keys = getSetOfJSONKeys(jo);
throw new IllegalArgumentException("The given json object has an invalid set of keys: " + keys
+ "\nOne of the following key combinations was expected:\n" + fieldsCollection);
}
public static boolean checkValidKeysEx(JSONObject jo, List<Fields> fieldsCollection)
{
return checkValidKeysExHelper(jo,
fieldsCollection);
}
public static Set<String> getSetOfJSONKeys(JSONObject jo)
{
@SuppressWarnings("unchecked")
Iterator<String> keyIterator = jo.keys();
Set<String> keySet = Sets.newHashSet();
while (keyIterator.hasNext()) {
keySet.add(keyIterator.next());
}
return keySet;
}
public static Map<String, String> convertFieldToType(Map<String, Type> fieldToType)
{
Map<String, String> fieldToTypeString = Maps.newHashMap();
for (Map.Entry<String, Type> entry : fieldToType.entrySet()) {
String field = entry.getKey();
String typeString = entry.getValue().name();
fieldToTypeString.put(field, typeString);
}
return fieldToTypeString;
}
public static JSONArray findFirstKeyJSONArray(JSONObject jo, String key)
{
if (jo.has(key)) {
try {
JSONArray jsonArray = jo.getJSONArray(key);
return jsonArray;
} catch (JSONException ex) {
throw new RuntimeException(ex);
}
}
@SuppressWarnings("unchecked")
Iterator<String> keyIterator = jo.keys();
while (keyIterator.hasNext()) {
String childKey = keyIterator.next();
JSONArray childJa = null;
try {
childJa = jo.getJSONArray(childKey);
} catch (JSONException ex) {
//Do nothing
}
if (childJa != null) {
JSONArray result = findFirstKeyJSONArray(childJa, key);
if (result != null) {
return result;
}
continue;
}
JSONObject childJo = null;
try {
childJo = jo.getJSONObject(childKey);
} catch (JSONException ex) {
//Do nothing
}
if (childJo != null) {
JSONArray result = findFirstKeyJSONArray(childJo, key);
if (result != null) {
return result;
}
}
}
return null;
}
public static JSONArray findFirstKeyJSONArray(JSONArray ja, String key)
{
for (int index = 0; index < ja.length(); index++) {
JSONArray childJa = null;
try {
childJa = ja.getJSONArray(index);
} catch (JSONException ex) {
//Do nothing
}
if (childJa != null) {
JSONArray result = findFirstKeyJSONArray(childJa, key);
if (result != null) {
return result;
}
continue;
}
JSONObject childJo = null;
try {
childJo = ja.getJSONObject(index);
} catch (JSONException ex) {
//Do nothing
}
if (childJo != null) {
JSONArray result = findFirstKeyJSONArray(childJo, key);
if (result != null) {
return result;
}
}
}
return null;
}
public static JSONObject findFirstKeyJSONObject(JSONObject jo, String key)
{
if (jo.has(key)) {
try {
JSONObject jsonObject = jo.getJSONObject(key);
return jsonObject;
} catch (JSONException ex) {
throw new RuntimeException(ex);
}
}
@SuppressWarnings("unchecked")
Iterator<String> keyIterator = jo.keys();
while (keyIterator.hasNext()) {
String childKey = keyIterator.next();
JSONArray childJa = null;
try {
childJa = jo.getJSONArray(childKey);
} catch (JSONException ex) {
//Do nothing
}
if (childJa != null) {
JSONObject result = findFirstKeyJSONObject(childJa, key);
if (result != null) {
return result;
}
continue;
}
JSONObject childJo = null;
try {
childJo = jo.getJSONObject(childKey);
} catch (JSONException ex) {
//Do nothing
}
if (childJo != null) {
JSONObject result = findFirstKeyJSONObject(childJo, key);
if (result != null) {
return result;
}
}
}
return null;
}
public static JSONObject findFirstKeyJSONObject(JSONArray ja, String key)
{
for (int index = 0; index < ja.length(); index++) {
JSONArray childJa = null;
try {
childJa = ja.getJSONArray(index);
} catch (JSONException ex) {
//Do nothing
}
if (childJa != null) {
JSONObject result = findFirstKeyJSONObject(childJa, key);
if (result != null) {
return result;
}
continue;
}
JSONObject childJo = null;
try {
childJo = ja.getJSONObject(index);
} catch (JSONException ex) {
//Do nothing
}
if (childJo != null) {
JSONObject result = findFirstKeyJSONObject(childJo, key);
if (result != null) {
return result;
}
}
}
return null;
}
/**
* Converts the given JSONObject into a {@link Map}.
* @param jo The {@link JSONObject} to convert.
* @return The converted {@link JSONObject}.
*/
public static Map<String, String> extractMap(JSONObject jo)
{
Map<String, String> resultMap = Maps.newHashMap();
@SuppressWarnings("unchecked")
Iterator<String> keyIterator = jo.keys();
while (keyIterator.hasNext()) {
String key = keyIterator.next();
String value;
try {
value = jo.getString(key);
} catch (JSONException ex) {
throw new RuntimeException(ex);
}
resultMap.put(key, value);
}
return resultMap;
}
/**
* This is a utility method which creates a {@link JSONObject} out of the given map.
* @param map The map to convert into a {@link JSONObject}.
* @return The converted map.
*/
public static JSONObject createJSONObject(Map<String, String> map)
{
JSONObject jo = new JSONObject();
for (Map.Entry<String, String> entry : map.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
try {
jo.put(key, value);
} catch (JSONException ex) {
throw new RuntimeException(ex);
}
}
return jo;
}
/**
* This is a helper method which converts the given {@link JSONArray} to a {@link List} of Strings.
*
* @param jsonStringArray The {@link JSONArray} to convert.
* @return The converted {@link List} of Strings.
*/
public static List<String> getStringsFromJSONArray(JSONArray jsonStringArray) throws JSONException
{
List<String> stringArray = Lists.newArrayListWithCapacity(jsonStringArray.length());
for (int stringIndex = 0; stringIndex < jsonStringArray.length(); stringIndex++) {
stringArray.add(jsonStringArray.getString(stringIndex));
}
return stringArray;
}
/**
* This is a helper method which retrieves the schema tags from the {@link JSONObject} if they are present.
*
* @param jo The {@link JSONObject} to retrieve schema tags from.
* @return A list containing the retrieved schema tags. The list is empty if there are no schema tags present.
*/
public static List<String> getTags(JSONObject jo) throws JSONException
{
if (jo.has(FIELD_TAGS)) {
return getStringsFromJSONArray(jo.getJSONArray(FIELD_TAGS));
} else {
return Collections.emptyList();
}
}
private static final Logger LOG = LoggerFactory.getLogger(SchemaUtils.class);
}