/* * � Copyright IBM Corp. 2012 * * Licensed under the Apache 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://www.apache.org/licenses/LICENSE-2.0 * * 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 com.ibm.domino.commons.json; import static com.ibm.domino.commons.json.JsonConstants.JSON_DATE; import static com.ibm.domino.commons.json.JsonConstants.JSON_END; import static com.ibm.domino.commons.json.JsonConstants.JSON_TIME; import static com.ibm.domino.commons.json.JsonConstants.JSON_TZID; import static com.ibm.domino.commons.json.JsonConstants.JSON_UTC; import static net.fortuna.ical4j.model.Parameter.TZID; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; import net.fortuna.ical4j.model.Component; import net.fortuna.ical4j.model.Date; import net.fortuna.ical4j.model.DateTime; import net.fortuna.ical4j.model.TimeZone; import net.fortuna.ical4j.model.property.DateProperty; import net.fortuna.ical4j.model.property.DtEnd; import net.fortuna.ical4j.model.property.DtStart; import com.ibm.commons.util.io.json.JsonException; import com.ibm.commons.util.io.json.JsonObject; import com.ibm.domino.commons.json.JsonIllegalValueException; public class JsonDatePropertyAdapter implements JsonObject { private static final String DATE_FORMAT = "yyyy-MM-dd"; // $NON-NLS-1$ private static final String TIME_FORMAT = "HH:mm:ss"; // $NON-NLS-1$ private static java.util.TimeZone s_utcTimeZone = TimeZone.getTimeZone("UTC"); // $NON-NLS-1$ private DateProperty _dateProperty; private Component _parent = null; private String _propertyName; private String[] _properties; // These fields are only used when parsing JSON private String _dateValue; private String _timeValue; private String _tzidValue; private boolean _utcValue; /** * Constructor used when generating JSON * * @param dateProperty */ public JsonDatePropertyAdapter(DateProperty dateProperty) { _dateProperty = dateProperty; } /** * Constructor used when parsing JSON * * @param propertyName * @param parent */ public JsonDatePropertyAdapter(String propertyName, Component parent) { _propertyName = propertyName; _parent = parent; } /** * Compose the date property from its constituent parts. * * <p>Call this method after the date, time, tzid and other properties * have all be set by the parser. The <code>compose</code> method * assembles a date property from the parts. * * @param propertyName * @return * @throws JsonException */ public DateProperty compose(Map<String, TimeZone> timeZones) { DateProperty dp = null; SimpleDateFormat formatter = null; String input = null; java.util.TimeZone tz = null; try { if ( _dateValue == null ) { // Must at least have a date value throw new ParseException("Must at least have a date value",0); // $NLX-JsonDatePropertyAdapter.Mustatleasthaveadatevalue-1$ //return null; } if ( _timeValue == null ) { // Parse just the date formatter = new SimpleDateFormat(DATE_FORMAT); input = _dateValue; } else { // Parse the date and time formatter = new SimpleDateFormat(DATE_FORMAT + "'T'" + TIME_FORMAT); // $NON-NLS-1$ input = _dateValue + "T" + _timeValue; if (_utcValue && _tzidValue != null) throw new ParseException("Bad date time property",0); // $NLX-JsonDatePropertyAdapter.Baddatetimeproperty-1$ if ( _utcValue ) { tz = s_utcTimeZone; formatter.setTimeZone(s_utcTimeZone); } else if ( _tzidValue != null ) { if ( timeZones != null ) { tz = timeZones.get(_tzidValue); } if(tz==null){ throw new ParseException("The Timezone ID is not found",0); // $NLX-JsonDatePropertyAdapter.TheTimezoneIDisnotfound-1$ } } } // Set up the time zone prior to parsing if ( tz != null ) { formatter.setTimeZone(tz); } // Parse the inner date object java.util.Date date = formatter.parse(input); Date ical4jDate = null; if ( _timeValue == null ) { ical4jDate = new Date(date); } else { ical4jDate = new DateTime(date); } // Construct the relevant ical4j date property if ( JSON_END.equals(_propertyName) ) { dp = new DtEnd(ical4jDate); } else { // When the property name is "exceptDates" we construct a DtStart property. // This is a kludge, but it gets around a layering problem. Leave it // for now. dp = new DtStart(ical4jDate); } // Update the ical4j time zone if ( dp != null ) { if ( _utcValue ) { dp.setUtc(true); } else if ( tz != null ) { dp.setTimeZone((TimeZone)tz); } } } catch (ParseException e) { throw new JsonIllegalValueException(e); } return dp; } public Iterator<String> getJsonProperties() { return new Iterator<String>() { private int _index = 0; public boolean hasNext() { String properties[] = getProperties(); return _index < properties.length ; } public String next() { String properties[] = getProperties(); return properties[_index++]; } public void remove() { // The JSON IO classes shouldn't call remove } private String[] getProperties() { if ( _properties != null ) { return _properties; } List<String> properties = new ArrayList<String>(); Date date = _dateProperty.getDate(); // There is always a date property properties.add(JSON_DATE); // The rest of the properties depend on the date innards if ( date instanceof DateTime ) { DateTime datetime = (DateTime)date; properties.add(JSON_TIME); if ( datetime.isUtc() ) { properties.add(JSON_UTC); } else if ( datetime.getTimeZone() != null ) { properties.add(JSON_TZID); } } // Convert to array String[] array = new String[properties.size()]; Iterator<String> iterator = properties.iterator(); for ( int i = 0; iterator.hasNext(); i++ ) { array[i] = iterator.next(); } // Cache the array for next time _properties = array; return array; } }; } public Object getJsonProperty(String propertyName) { // This method is called when converting iCalendar to JSON Date date = _dateProperty.getDate(); DateTime datetime = null; if ( date instanceof DateTime ) { datetime = (DateTime)date; } if ( JSON_DATE.equals(propertyName) ) { SimpleDateFormat formatter = new SimpleDateFormat(DATE_FORMAT); if ( datetime != null ) { if ( datetime.isUtc() ) { formatter.setTimeZone(s_utcTimeZone); } else if ( datetime.getTimeZone() != null ) { formatter.setTimeZone(datetime.getTimeZone()); } } return formatter.format(date); } else if ( JSON_TIME.equals(propertyName) ) { SimpleDateFormat formatter = new SimpleDateFormat(TIME_FORMAT); if ( datetime != null ) { if ( datetime.isUtc() ) { formatter.setTimeZone(s_utcTimeZone); } else if ( datetime.getTimeZone() != null ) { formatter.setTimeZone(datetime.getTimeZone()); } } return formatter.format(date); } else if ( JSON_TZID.equals(propertyName) ) { return _dateProperty.getParameter(TZID).getValue(); } else if ( JSON_UTC.equals(propertyName) ) { if ( datetime == null) { return false; } else { return datetime.isUtc(); } } return null; } public void putJsonProperty(String propertyName, Object propertyValue) { if ( JSON_DATE.equals(propertyName) ) { _dateValue = (String)propertyValue; } else if ( JSON_TIME.equals(propertyName) ) { _timeValue = (String)propertyValue; } else if ( JSON_TZID.equals(propertyName) ) { _tzidValue = (String)propertyValue; } else if ( JSON_UTC.equals(propertyName) ) { if ( propertyValue instanceof Boolean ) { _utcValue = ((Boolean)propertyValue).booleanValue(); } } } /** * Get the parent component */ public Component getParent() { return _parent; } public String getPropertyName() { return _propertyName; } }