package org.akaza.openclinica.web.restful; import net.sf.json.JSON; import net.sf.json.JSONArray; import net.sf.json.JSONObject; import org.akaza.openclinica.i18n.util.ResourceBundleProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; import java.util.ResourceBundle; import java.util.regex.Pattern; /** * Runs a set of post-processing operations on JSON clinical data. * * @author Douglas Rodrigues (drodrigues@openclinica.com) */ public class JSONClinicalDataPostProcessor { private static final Logger LOG = LoggerFactory.getLogger(JSONClinicalDataPostProcessor.class); private static final DateFormat DATE_INTERNAL_FORMAT = new SimpleDateFormat("yyyy-MM-dd"); private static final DateFormat DATE_TIME_INTERNAL_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); private static final DateFormat DATE_TIME_AUDIT_LOG_INTERNAL_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); private static final String DATE_FORMAT_KEY = "date_format_string"; private static final String DATE_TIME_FORMAT_KEY = "date_time_format_string"; private static final Pattern DATE_PATTERN = Pattern.compile("[0-9]{4}-[0-9]{2}-[0-9]{2}"); private static final Pattern DATE_TIME_PATTERN = Pattern.compile("[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}.[0-9]"); /** * Matches the date & time format used to render audit log entries */ private static final Pattern DATE_TIME_AUDIT_LOG_PATTERN = Pattern.compile("[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}"); private final Locale locale; private final ResourceBundle formatResourceBundle; public JSONClinicalDataPostProcessor(Locale locale) { this.locale = locale; this.formatResourceBundle = ResourceBundleProvider.getFormatBundle(locale); } /** * Iterates over the elements of a JSON object. * * @param json JSON object to be processed */ public void process(JSON json) { processJSONFields(json); } private void processJSONFields(JSON json) { if (json instanceof JSONArray) { processJSONArray((JSONArray) json); } else if (json instanceof JSONObject) { processJSONObject((JSONObject) json); } } private JSON processJSONArray(JSONArray jsonArray) { for (int i = 0; i < jsonArray.size(); i++) { Object elem = jsonArray.get(i); if (elem instanceof JSONArray) { processJSONArray((JSONArray) elem); } else if (elem instanceof JSONObject) { processJSONObject((JSONObject) elem); } else if (elem instanceof String) { jsonArray.set(i, processString((String) elem)); } } return jsonArray; } private JSON processJSONObject(JSONObject jsonObject) { for (Object key : jsonObject.keySet()) { Object elem = jsonObject.get(key); if (elem instanceof JSONArray) { processJSONArray((JSONArray) elem); } else if (elem instanceof JSONObject) { processJSONObject((JSONObject) elem); } else if (elem instanceof String) { jsonObject.put(key, processString((String) elem)); } } return jsonObject; } private String processString(String elem) { /* Tries to match the string with the following formats: 2011-07-05 2011-05-17 00:00:00.0 2013-11-18T18:42:28 (Audit log date format) */ boolean isShort = DATE_PATTERN.matcher(elem).matches(); boolean isLong = DATE_TIME_PATTERN.matcher(elem).matches(); boolean isAudit = DATE_TIME_AUDIT_LOG_PATTERN.matcher(elem).matches(); if (isShort || isLong || isAudit) { try { Date date; DateFormat formatter; if (isShort) { date = DATE_INTERNAL_FORMAT.parse(elem); formatter = new SimpleDateFormat(formatResourceBundle.getString(DATE_FORMAT_KEY), locale); } else if (isLong) { date = DATE_TIME_INTERNAL_FORMAT.parse(elem); formatter = new SimpleDateFormat(formatResourceBundle.getString(DATE_TIME_FORMAT_KEY), locale); } else { date = DATE_TIME_AUDIT_LOG_INTERNAL_FORMAT.parse(elem); formatter = new SimpleDateFormat(formatResourceBundle.getString(DATE_TIME_FORMAT_KEY), locale); } return formatter.format(date); } catch (ParseException e) { LOG.warn("Could not parse date from ODM element '" + elem + "'", e); } } return elem; } }