package com.adobe.acs.commons.synth.children.impl; import org.apache.sling.api.wrappers.ModifiableValueMapDecorator; import org.joda.time.DateTime; import org.joda.time.format.ISODateTimeFormat; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.math.BigDecimal; import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util.Map; /** * Special wrapper to handle deserialization of JSON data to value map. * <p> * Contains special handling for Date and Calendar interoperability. */ public final class JSONModifiableValueMapDecorator extends ModifiableValueMapDecorator { private static final Logger log = LoggerFactory.getLogger(JSONModifiableValueMapDecorator.class); /** * Creates an empty JSONModifiableValueMapDecorator. */ public JSONModifiableValueMapDecorator() { super(new HashMap<String, Object>()); } /** * Creates an pre-populated JSONModifiableValueMapDecorator. * * @param base the data to prepopulate the ValueMap with */ public JSONModifiableValueMapDecorator(final Map<String, Object> base) { super(base); } /** * {@inheritDoc} * <p> * Special implementation of get to handle Date and Calendar interoperability, BigDecimals and Integers. */ @Override public <T> T get(String name, Class<T> type) { try { if (Calendar.class.equals(type)) { return (T) getCalendar(name); } else if (Date.class.equals(type)) { return (T) getDate(name); } else if (BigDecimal.class.equals(type)) { return (T) getBigDecimal(name); } else if (Integer.class.equals(type)) { return (T) getInteger(name); } else { return super.get(name, type); } } catch (Exception e) { log.warn("Unable to get property [ {} ] as [ {} ]. Returning null.", name, type); return null; } } /** * Coerces the value at {@param name} to a Calendar object. * * @param name the property name * @return a Calendar obj representing the property value, or null if no value can be coerced. */ private Calendar getCalendar(String name) { Object obj = super.get(name); if (obj instanceof Calendar) { return (Calendar) obj; } else if (obj instanceof Date) { Calendar cal = Calendar.getInstance(); cal.setTime((Date) obj); return cal; } else { String tmp = super.get(name, String.class); final DateTime dateTime = ISODateTimeFormat.dateTime().parseDateTime(tmp); if (dateTime != null) { final Calendar cal = Calendar.getInstance(); cal.setTime(dateTime.toDate()); return cal; } else { return null; } } } /** * Coerces the value at {@param name} to a Date object. * * @param name the property name * @return a Date obj representing the property value, or null if no value can be coerced. */ private Date getDate(String name) { Object obj = super.get(name); if (obj instanceof Date) { return (Date) obj; } else if (obj instanceof Calendar) { Calendar cal = (Calendar) obj; return cal.getTime(); } else { String tmp = super.get(name, String.class); final DateTime dateTime = ISODateTimeFormat.dateTime().parseDateTime(tmp); if (dateTime != null) { return dateTime.toDate(); } else { return null; } } } /** * Coerces the value at {@param name} to a Integer object. * * @param name the property name * @return a Integer obj representing the property value, or null if no value can be coerced. */ private Integer getInteger(String name) { Object obj = super.get(name); if (obj instanceof Integer) { return (Integer) obj; } else if (obj instanceof Double) { Double tmp = (Double) obj; return tmp.intValue(); } else if (obj instanceof Long) { Long tmp = (Long) obj; return tmp.intValue(); } else { String tmp = super.get(name, String.class); return Integer.parseInt(tmp); } } /** * Coerces the value at {@param name} to a BigDecimal object. * * @param name the property name * @return a BigDecimal obj representing the property value, or null if no value can be coerced. */ private BigDecimal getBigDecimal(String name) { Object obj = super.get(name); if (obj instanceof BigDecimal) { return (BigDecimal) obj; } else if (obj instanceof Double) { return BigDecimal.valueOf((Double) obj); } else if (obj instanceof Long) { return BigDecimal.valueOf((Long) obj); } else if (obj instanceof Integer) { return BigDecimal.valueOf((Integer) obj); } else { String tmp = super.get(name, String.class); return new BigDecimal(tmp); } } /** * {@inheritDoc} */ @Override public <T> T get(String name, T defaultValue) { if (defaultValue == null) { return (T) this.get(name); } Class<T> type = (Class<T>) defaultValue.getClass(); T value = get(name, type); if (value == null) { value = defaultValue; } return value; } }