    001/*-
    002 * Copyright 2015, 2016 Diamond Light Source Ltd.
    003 *
    004 * All rights reserved. This program and the accompanying materials
    005 * are made available under the terms of the Eclipse Public License v1.0
    006 * which accompanies this distribution, and is available at
    007 * http://www.eclipse.org/legal/epl-v10.html
    008 */
    009
    010package org.eclipse.january.dataset;
    011
    012import java.text.ParseException;
    013import java.text.SimpleDateFormat;
    014import java.util.Date;
    015
    016import org.slf4j.Logger;
    017import org.slf4j.LoggerFactory;
    018
    019public class DateDatasetImpl extends StringDataset implements DateDataset {
    020        // pin UID to base class
    021        private static final long serialVersionUID = Dataset.serialVersionUID;
    022
    023        private static final Logger logger = LoggerFactory.getLogger(DateDatasetImpl.class);
    024
    025        private static final SimpleDateFormat ISO8601_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
    026
    027        static DateDatasetImpl createFromObject(final Object obj) {
    028                final DateDatasetImpl result = new DateDatasetImpl();
    029                result.shape = ShapeUtils.getShapeFromObject(obj);
    030                result.size = ShapeUtils.calcSize(result.shape);
    031                result.odata = result.data = createArray(result.size);
    032
    033                final int[] pos = new int[result.shape.length];
    034                result.fillData(obj, 0, pos);
    035
    036                return result;
    037        }
    038
    039        /**
    040         * Create a null dataset
    041         */
    042        DateDatasetImpl() {
    043                super();
    044        }
    045
    046        DateDatasetImpl(final int... shape) {
    047                super(shape);
    048        }
    049
    050        DateDatasetImpl(final Date[] data, int... shape) {
    051                super(datesToStrings(data), shape);
    052        }
    053
    054        private static String[] datesToStrings(final Date[] dates) {
    055                final String[] dateStrings = new String[dates.length];
    056                for (int i = 0; i < dates.length; i++) {
    057                        dateStrings[i] = dateToString(dates[i]);
    058                }
    059
    060                return dateStrings;
    061        }
    062
    063        private static String dateToString(final Date date) {
    064                if (date != null) {
    065                        return ISO8601_DATE_FORMAT.format(date);
    066                }
    067
    068                return null;
    069        }
    070
    071        private static String objectToDateString(final Object obj) {
    072                if (obj instanceof Date) {
    073                        return dateToString((Date) obj);
    074                } else if (obj instanceof Dataset) {
    075                        Dataset dataset = (Dataset) obj;
    076                        if (dataset.getSize() != 1) {
    077                                logger.error("Given dataset must only have one item");
    078                                throw new IllegalArgumentException("Given dataset must have only one item");
    079                        }
    080
    081                        return objectToDateString(dataset.getObject());
    082                } else if (obj instanceof IDataset) {
    083                        IDataset dataset = (IDataset) obj;
    084                        if (dataset.getSize() != 1) {
    085                                logger.error("Given dataset must only have one item");
    086                                throw new IllegalArgumentException("Given dataset must have only one item");
    087                        }
    088                        return objectToDateString(dataset.getObject(new int[dataset.getRank()]));
    089                } else {
    090                        logger.error("Argument is of unsupported class");
    091                        throw new IllegalArgumentException("Argument is of unsupported class");
    092                }
    093        }
    094
    095        private static Date stringToDate(final String dateAsString) {
    096                if (dateAsString != null) {
    097                        try {
    098                                return ISO8601_DATE_FORMAT.parse(dateAsString);
    099                        } catch (ParseException e) {
    100                                // fall through to return null
    101                                logger.error("Could not parse datetime: " + dateAsString);
    102                        }
    103                }
    104
    105                return null;
    106        }
    107
    108        @Override
    109        public Date getDate() {
    110                final String dateAsString = super.getString();
    111                return stringToDate(dateAsString);
    112        }
    113
    114        @Override
    115        public Date getDate(int i) {
    116                final String dateAsString = super.getString(i);
    117                return stringToDate(dateAsString);
    118        }
    119
    120        @Override
    121        public Date getDate(int i, int j) {
    122                final String dateAsString = super.getString(i, j);
    123                return stringToDate(dateAsString);
    124        }
    125
    126        @Override
    127        public Date getDate(int... pos) {
    128                final String dateAsString = super.getString(pos);
    129                return stringToDate(dateAsString);
    130        }
    131
    132        @Override
    133        public Date getDateAbs(int index) {
    134                final String dateAsString = super.getStringAbs(index);
    135                if (dateAsString != null) {
    136                        return stringToDate(dateAsString);
    137                }
    138
    139                return null;
    140        }
    141
    142        @Override
    143        public Object getObject() {
    144                return getDate();
    145        }
    146
    147        @Override
    148        public Object getObject(int i) {
    149                return getDate(i);
    150        }
    151
    152        @Override
    153        public Object getObject(int i, int j) {
    154                return getDate(i, j);
    155        }
    156
    157        @Override
    158        public Object getObject(int... pos) {
    159                return getDate(pos);
    160        }
    161
    162        @Override
    163        public Object getObjectAbs(int index) {
    164                return getDateAbs(index);
    165        }
    166
    167        @Override
    168        public void setItemDirect(final int dindex, final int sindex, final Object src) {
    169                if (src instanceof String[]) {
    170                        super.setItemDirect(dindex, sindex, src);
    171                } else if (src instanceof Date[]) {
    172                        String[] datesAsStrings = datesToStrings((Date[]) src);
    173                        data[dindex] = datesAsStrings[sindex];
    174                } else {
    175                        logger.error("Argument is of unsupported class");
    176                        throw new IllegalArgumentException("Argument is of unsupported class");
    177                }
    178        }
    179
    180        public void setAbs(final int index, final Date date) {
    181                data[index] = dateToString(date);
    182                setDirty();
    183        }
    184
    185        /**
    186         * @param value to set
    187         * @since 2.0
    188         */
    189        public void setItem(final Date value) {
    190                setAbs(getFirst1DIndex(), value);
    191        }
    192
    193        /**
    194         * @param value to set
    195         * @param i position in first dimension
    196         */
    197        public void setItem(final Date value, final int i) {
    198                setAbs(get1DIndex(i), value);
    199        }
    200
    201        /**
    202         * @param value to set
    203         * @param i position in first dimension
    204         * @param j position in second dimension
    205         */
    206        public void setItem(final Date value, final int i, final int j) {
    207                setAbs(get1DIndex(i, j), value);
    208        }
    209
    210        /**
    211         * @param value to set
    212         * @param pos position
    213         */
    214        public void setItem(final Date value, final int... pos) {
    215                setAbs(get1DIndex(pos), value);
    216        }
    217
    218        @Override
    219        public void set(final Object obj) {
    220                setItem(objectToDateString(obj));
    221        }
    222
    223        @Override
    224        public void set(final Object obj, final int i) {
    225                setItem(objectToDateString(obj), i);
    226        }
    227
    228        @Override
    229        public void set(final Object obj, final int i, final int j) {
    230                setItem(objectToDateString(obj), i, j);
    231        }
    232
    233        @Override
    234        public void set(final Object obj, int... pos) {
    235                if (pos == null || (pos.length == 0 && shape.length > 0)) {
    236                        pos = new int[shape.length];
    237                }
    238
    239                setItem(objectToDateString(obj), pos);
    240        }
    241
    242        @Override
    243        public StringDatasetBase sort(Integer axis) {
    244                // Note yet supported.
    245                // TODO: this method will be inefficient as we store dates formatted as strings
    246                throw new UnsupportedOperationException("Cannot sort dataset");
    247        }
    248
    249}