diff --git a/Frameworks/EOF/ERRest/Sources/er/rest/ERXRestUtils.java b/Frameworks/EOF/ERRest/Sources/er/rest/ERXRestUtils.java index d729e5935ec..9ecbb8f4e30 100644 --- a/Frameworks/EOF/ERRest/Sources/er/rest/ERXRestUtils.java +++ b/Frameworks/EOF/ERRest/Sources/er/rest/ERXRestUtils.java @@ -6,6 +6,11 @@ import java.util.Calendar; import java.util.Date; +import org.joda.time.DateTime; +import org.joda.time.LocalDate; +import org.joda.time.format.DateTimeFormat; +import org.joda.time.format.DateTimeFormatter; + import com.webobjects.eoaccess.EOAttribute; import com.webobjects.eoaccess.EOEntityClassDescription; import com.webobjects.eocontrol.EOClassDescription; @@ -84,6 +89,9 @@ else if (Date.class.isAssignableFrom(valueType)) { else if (Calendar.class.isAssignableFrom(valueType)) { primitive = true; } + else if (LocalDate.class.isAssignableFrom(valueType)) { + primitive = true; + } else if (Enum.class.isAssignableFrom(valueType)) { primitive = true; } @@ -115,9 +123,11 @@ else if (value instanceof NSTimestamp) { } } else if (value instanceof Date) { - Date date = (Date) value; formattedValue = ERXRestUtils.dateFormat(false, context).format(value); } + else if (value instanceof LocalDate) { + formattedValue = ERXRestUtils.jodaLocalDateFormat(false, context).print((LocalDate)value); + } else if (value instanceof NSData && ((NSData)value).length() == 24) { formattedValue = NSPropertyListSerialization.stringFromPropertyList(value); } @@ -169,6 +179,26 @@ protected static Format dateFormat(boolean spaces, ERXRestContext context) { return dateFormatter; } + protected static DateTimeFormatter jodaLocalDateFormat(boolean spaces, ERXRestContext context) { + DateTimeFormatter dateFormatter = (DateTimeFormatter)context.userInfoForKey("er.rest.jodaFormatter"); + if (dateFormatter == null) { + String dateFormat = (String)context.userInfoForKey("er.rest.jodaFormat"); + if (dateFormat == null) { + dateFormat = ERXProperties.stringForKey("er.rest.jodaFormat"); + if (dateFormat == null) { + if (spaces) { + dateFormat = ERXProperties.stringForKeyWithDefault("er.rest.jodaFormat.secondary", "yyyy-MM-dd HH:mm:ss z"); + } + else { + dateFormat = ERXProperties.stringForKeyWithDefault("er.rest.jodaFormat.primary", "yyyy-MM-dd'T'HH:mm:ss'Z'"); + } + } + } + dateFormatter = DateTimeFormat.forPattern(dateFormat); + } + return dateFormatter; + } + @SuppressWarnings("unchecked") public static Object coerceValueToTypeNamed(Object value, String valueTypeName, ERXRestContext context, boolean resolveEntities) { Object parsedValue; @@ -304,6 +334,28 @@ else if (valueType != null && Date.class.isAssignableFrom(valueType)) { } } } + else if (valueType != null && LocalDate.class.isAssignableFrom(valueType)) { + if (value instanceof NSTimestamp) { + parsedValue = value; + } + else { + String strValue = (String) value; + DateTimeFormatter formatter = null; + try { + boolean spaces = strValue.indexOf(' ') != -1; + formatter = ERXRestUtils.jodaLocalDateFormat(spaces, context); + parsedValue = new LocalDate((DateTime)formatter.parseDateTime(strValue)); + } + catch (Throwable t) { + String msg = "Failed to parse '" + strValue + "' as a timestamp"; + if (formatter != null) { + msg += " (example: " + formatter.print(new LocalDate()) + ")"; + } + msg += "."; + throw new IllegalArgumentException(msg, t); + } + } + } else if (valueType != null && Enum.class.isAssignableFrom(valueType)) { parsedValue = ERXValueUtilities.enumValueWithDefault(value, (Class) valueType, null); } @@ -338,7 +390,6 @@ else if (resolveEntities) { public static Object coerceValueToAttributeType(Object value, EOClassDescription parentEntity, Object parentObject, String attributeName, ERXRestContext context) { NSKeyValueCoding._KeyBinding binding = NSKeyValueCoding.DefaultImplementation._keyGetBindingForKey(parentObject, attributeName); Class valueType = binding.valueType(); - try { Object parsedValue; if (value == null || ERXValueUtilities.isNull(value) || (value instanceof String && ((String) value).length() == 0)) { diff --git a/Frameworks/EOF/ERRest/Sources/er/rest/format/_ERXJSONConfig.java b/Frameworks/EOF/ERRest/Sources/er/rest/format/_ERXJSONConfig.java index cebde86a8d9..9ec6e664723 100644 --- a/Frameworks/EOF/ERRest/Sources/er/rest/format/_ERXJSONConfig.java +++ b/Frameworks/EOF/ERRest/Sources/er/rest/format/_ERXJSONConfig.java @@ -3,6 +3,8 @@ import java.util.Date; import java.util.Set; +import org.joda.time.LocalDate; + import net.sf.json.JsonConfig; import net.sf.json.processors.JsonValueProcessor; import net.sf.json.processors.JsonValueProcessorMatcher; @@ -57,10 +59,27 @@ public Object processObjectValue(String s, Object obj, JsonConfig jsonconfig) { return ERXRestUtils.coerceValueToString(obj, _context); } } + + public static class JodaTimeProcessor implements JsonValueProcessor { + private ERXRestContext _context; + + public JodaTimeProcessor(ERXRestContext context) { + _context = context; + } + + public Object processArrayValue(Object obj, JsonConfig jsonconfig) { + return ERXRestUtils.coerceValueToString(obj, _context); + } + public Object processObjectValue(String s, Object obj, JsonConfig jsonconfig) { + return ERXRestUtils.coerceValueToString(obj, _context); + } + } + public static JsonConfig createDefaultConfig(ERXRestContext context) { JsonConfig config = new JsonConfig(); config.registerJsonValueProcessor(NSTimestamp.class, new NSTimestampProcessor(context)); + config.registerJsonValueProcessor(LocalDate.class, new JodaTimeProcessor(context)); config.registerJsonValueProcessor(Date.class, new NSTimestampProcessor(context)); config.registerJsonValueProcessor(NSData.class, new NSDataProcessor(context)); config.setJsonValueProcessorMatcher(new ERXRestValueProcessorMatcher());