//Dstl (c) Crown Copyright 2017
package uk.gov.dstl.baleen.uima.utils;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Properties;
import java.util.TimeZone;
import uk.gov.dstl.baleen.exceptions.InvalidParameterException;
/**
* Convert a string into an object. Used by LegacyMongoConsumer - considered legacy code!
*
*
*/
public class StringToObject {
private static final String CONFIG_ALLOW_DATES = "allowDates";
private static final String CONFIG_PRECEDING_ZERO_ISNT_NUMBER = "precedingZeroIsntNumber";
private StringToObject() {
// Singleton
}
/**
* Convert a string to a Java object of the correct type with the same value
* (e.g. "1" -> 1).
* <p>
* If a number has a preceding 0, it will be assumed not to be a number as
* it is likely to represent a phone number
* <p>
* This method accepts no configuration, and so uses default values
*
* @param s
* String to convert
* @return A Java object of the correct type
*/
public static Object convertStringToObject(String s) {
return convertStringToObject(s, new Properties());
}
/**
* Convert a string to a Java object of the correct type with the same value
* (e.g. "1" -> 1).
* <p>
* If a number has a preceding 0, it will be assumed not to be a number as
* it is likely to represent a phone number
* <p>
* The following configuration keys can be set:
* <ul>
* <li><b>allowDates</b> - true (default) or false
* <li><b>precedingZeroIsntNumber</b> - true (default) or false
* </ul>
*
* @param s
* String to convert
* @param config
* Configuration values
* @return A Java object of the correct type
*/
public static Object convertStringToObject(String s, Properties config) {
Boolean precedingZeroIsntNumber = getConfigPrecedingZero(config);
if (s == null) {
return null;
}else if(tryNumber(s, precedingZeroIsntNumber)){
try {
return parseNumber(s);
} catch (InvalidParameterException e) {
// Ignore
}
}
if ("true".equalsIgnoreCase(s) || "false".equalsIgnoreCase(s)) {
return Boolean.parseBoolean(s);
}
return convertToDate(s, config);
}
private static boolean getConfigPrecedingZero(Properties config){
Boolean precedingZeroIsntNumber = true;
if(config.containsKey(CONFIG_PRECEDING_ZERO_ISNT_NUMBER)){
Object o = config.get(CONFIG_PRECEDING_ZERO_ISNT_NUMBER);
if(o instanceof Boolean){
precedingZeroIsntNumber = (Boolean) o;
}else{
precedingZeroIsntNumber = Boolean.valueOf(o.toString());
}
}
return precedingZeroIsntNumber;
}
private static Number parseNumber(String s) throws InvalidParameterException{
try {
return Integer.parseInt(s);
} catch (NumberFormatException e) {
// Ignore
}
try {
return Double.parseDouble(s);
} catch (NumberFormatException e) {
// Ignore
}
throw new InvalidParameterException("Couldn't parse number");
}
/**
* Test whether we should attempt to covert a string to a number, based on the current configuration
*/
private static boolean tryNumber(String s, boolean precedingZeroIsntNumber){
if(s.startsWith("0.")){
return true;
}
if(precedingZeroIsntNumber && !s.startsWith("0")){
return true;
}
if(!precedingZeroIsntNumber){
return true;
}
return false;
}
private static Object convertToDate(String s, Properties config) {
Object allowDates = config.get(CONFIG_ALLOW_DATES);
if (allowDates == null || "true".equalsIgnoreCase(allowDates.toString())) {
try {
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S");
df.setTimeZone(TimeZone.getTimeZone("UTC"));
return df.parse(s);
} catch (ParseException e) {
// Ignore
}
try {
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
return df.parse(s);
} catch (ParseException e) {
// Ignore
}
try {
DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
df.setTimeZone(TimeZone.getTimeZone("UTC"));
return df.parse(s);
} catch (ParseException e) {
// Ignore
}
}
return s;
}
}