/**
* Licensed to The Apereo Foundation under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*
*
* The Apereo Foundation licenses this file to you under the Educational
* Community 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://opensource.org/licenses/ecl2.txt
*
* 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.opencastproject.index.service.util;
import static com.entwinemedia.fn.data.json.Jsons.arr;
import static com.entwinemedia.fn.data.json.Jsons.f;
import static com.entwinemedia.fn.data.json.Jsons.obj;
import static com.entwinemedia.fn.data.json.Jsons.v;
import org.opencastproject.index.service.exception.ListProviderException;
import org.opencastproject.index.service.resources.list.api.ListProvidersService;
import org.opencastproject.index.service.resources.list.api.ResourceListFilter;
import org.opencastproject.index.service.resources.list.api.ResourceListQuery;
import org.opencastproject.security.api.Organization;
import org.opencastproject.util.DateTimeSupport;
import org.opencastproject.util.data.Option;
import com.entwinemedia.fn.data.json.Field;
import com.entwinemedia.fn.data.json.JObject;
import com.entwinemedia.fn.data.json.JValue;
import com.entwinemedia.fn.data.json.Jsons;
import org.apache.commons.lang3.StringUtils;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
/**
* Utility class providing helpers for all operation related to JSON.
*/
public final class JSONUtils {
public static final String PATTERN_ISO_DATE = "yyyy-MM-dd'T'HH:mm:ss'Z'";
/** Date formatter for ISO Date */
private static final SimpleDateFormat isoDateFormatter = new SimpleDateFormat(PATTERN_ISO_DATE);
private JSONUtils() {
}
/**
* Turn a map into a {@link JObject} object
*
* @param map
* the source map
* @return a new {@link JObject} generated with the map values
*/
public static JObject mapToJSON(Map<String, String> map) {
if (map == null) {
throw new IllegalArgumentException("Map must not be null!");
}
List<Field> fields = new ArrayList<Field>();
for (Entry<String, String> item : map.entrySet()) {
fields.add(f(item.getKey(), v(item.getValue(), Jsons.BLANK)));
}
return obj(fields);
}
/**
* Turn a set into a {@link JObject} object
*
* @param set
* the source set
* @return a new {@link JObject} generated with the map values
*/
public static JValue setToJSON(Set<String> set) {
if (set == null) {
return arr();
}
List<JValue> arrEntries = new ArrayList<JValue>();
for (String item : set) {
arrEntries.add(v(item, Jsons.BLANK));
}
return arr(arrEntries);
}
/**
* Create a JSON Array with the list given as String containing values separated by the given separator;
*
* @param list
* The list of values as String
* @param separator
* The separator used in the list between each value
* @return a JSON Array as {@link JValue}
* @throws IllegalArgumentException
* - if the separator is not set
*/
public static JValue jsonArrayFromString(String list, String separator) {
if (StringUtils.isEmpty(separator))
throw new IllegalArgumentException("The separator must be defined!");
if (StringUtils.isBlank(list))
return arr();
List<JValue> values = new ArrayList<JValue>();
for (String value : list.split(separator))
values.add(v(value));
return arr(values);
}
/**
* Format the given Date as ISO String Date using the pattern "yyyy-MM-dd'T'HH:mm:ss'Z'".
*
* @param date
* The date to format
* @return The date as ISO Date String
* @throws IllegalArgumentException
*/
public static String formatIsoDate(Date date) {
if (date == null)
throw new IllegalArgumentException("The given date must not be null.");
return DateTimeSupport.toUTC(date.getTime());
}
/**
* Generate JSON presentation of the given filters
*
* @param query
* The {@link ResourceListQuery}
* @param listProvidersService
* The {@link ListProvidersService} to get the possible values
* @param org
* The {@link Organization}
* @return
* @throws ListProviderException
* if the possible values can not be retrieved correctly from the list provider.
*/
public static JValue filtersToJSON(ResourceListQuery query, ListProvidersService listProvidersService,
Organization org) throws ListProviderException {
List<Field> filtersJSON = new ArrayList<Field>();
List<Field> fields = null;
List<ResourceListFilter<?>> filters = query.getAvailableFilters();
for (ResourceListFilter<?> f : filters) {
fields = new ArrayList<Field>();
fields.add(f("type", v(f.getSourceType().toString().toLowerCase())));
fields.add(f("label", v(f.getLabel())));
Option<String> listProviderName = f.getValuesListName();
if (listProviderName.isSome()) {
Map<String, String> values = null;
if (!listProvidersService.hasProvider(listProviderName.get()))
values = new HashMap<String, String>();
else
values = listProvidersService.getList(listProviderName.get(), query, org, false);
List<Field> valuesJSON = new ArrayList<Field>();
for (Entry<String, String> entry : values.entrySet()) {
valuesJSON.add(f(entry.getKey(), v(entry.getValue(), Jsons.BLANK)));
}
fields.add(f("options", obj(valuesJSON)));
}
filtersJSON.add(f(f.getName(), obj(fields)));
}
return obj(filtersJSON);
}
/**
* Format the given period (define by start and end dates) to a JSON value.
*
* <pre>
* {
* "start": 2012-12-20T23:11:23Z,
* "end": 2012-12-22T10:11:23Z
* }
* </pre>
*
* @param start
* The period start date
* @param end
* The period end date
* @return A {@link JValue} representing the period with a start and end property
*/
public static JValue formatPeriod(Date start, Date end) {
if (start == null || end == null)
throw new IllegalArgumentException("The given start or end date from the period must not be null!");
return obj(f("start", v(formatIsoDate(start))), f("end", v(formatIsoDate(end))));
}
/**
* Returns a JSON object with key-value from given map
*
* @param map
* The source list for the JSON object
* @return a JSON object containing the all the key-value as parameter
* @throws JSONException
*/
public static JSONObject fromMap(Map<String, String> map) throws JSONException {
JSONObject json = new JSONObject();
if (map == null)
return json;
for (Entry<String, String> entry : map.entrySet()) {
json.put(entry.getKey(), entry.getValue());
}
return json;
}
/**
* Converts a JSON object to a map. All values are of type {@link String}
*
* @param json
* the JSON object to convert
* @return the map
*/
public static Map<String, String> toMap(JSONObject json) {
if (json == null)
return Collections.emptyMap();
HashMap<String, String> map = new HashMap<String, String>();
for (Iterator<String> iterator = json.keys(); iterator.hasNext();) {
String key = iterator.next();
map.put(key, json.optString(key));
}
return map;
}
}