001/*
002 *  Copyright 2010, 2011 Chris Pheby
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.jadira.bindings.core.jdk;
017
018import java.text.ParseException;
019import java.text.SimpleDateFormat;
020import java.util.Calendar;
021import java.util.GregorianCalendar;
022import java.util.TimeZone;
023
024import org.jadira.bindings.core.api.Binding;
025import org.jadira.bindings.core.api.BindingException;
026
027/**
028 * Binds a Calendar to a String
029 */
030public class CalendarStringBinding extends AbstractStringBinding<Calendar> implements Binding<Calendar, String> {
031
032    private static final ThreadLocal<SimpleDateFormat> DATE_FORMAT = new ThreadLocal<SimpleDateFormat>() {
033        @Override
034        public SimpleDateFormat initialValue() {
035            return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
036        }
037    };
038
039    /**
040     * {@inheritDoc}
041     */
042    @Override
043    public Calendar unmarshal(String object) {
044
045        if (object.length() < 31 || object.charAt(26) != ':' || object.charAt(29) != '['
046                || object.charAt(object.length() - 1) != ']') {
047            throw new IllegalArgumentException("Unable to parse calendar: " + object);
048        }
049        TimeZone zone = TimeZone.getTimeZone(object.substring(30, object.length() - 1));
050
051        String parseableDateString = object.substring(0, 26) + object.substring(27, 29);
052
053        GregorianCalendar cal = new GregorianCalendar(zone);
054        cal.setTimeInMillis(0);
055        DATE_FORMAT.get().setCalendar(cal);
056
057        try {
058            DATE_FORMAT.get().parseObject(parseableDateString);
059            return DATE_FORMAT.get().getCalendar();
060        } catch (ParseException ex) {
061            throw new BindingException(ex.getMessage(), ex);
062        }
063    }
064
065    /**
066     * {@inheritDoc}
067     */
068    @Override
069    public String marshal(Calendar object) {
070
071        if (object instanceof GregorianCalendar) {
072
073            GregorianCalendar cal = (GregorianCalendar) object;
074
075            DATE_FORMAT.get().setCalendar(cal);
076            String str = DATE_FORMAT.get().format(cal.getTime());
077
078            String printableDateString = str.substring(0, 26) + ":" + str.substring(26) + "["
079                    + cal.getTimeZone().getID() + "]";
080            return printableDateString;
081        } else {
082            throw new IllegalArgumentException("CalendarStringBinding can only support "
083                    + GregorianCalendar.class.getSimpleName());
084        }
085    }
086
087    /**
088     * {@inheritDoc}
089     */
090    /* @Override */
091        public Class<Calendar> getBoundClass() {
092                return Calendar.class;
093        }
094}