    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
    016public class DateDatasetImpl extends StringDataset implements DateDataset {
    017        // pin UID to base class
    018        private static final long serialVersionUID = Dataset.serialVersionUID;
    019
    020        private static final SimpleDateFormat ISO8601_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
    021
    022        static DateDatasetImpl createFromObject(final Object obj) {
    023                final DateDatasetImpl result = new DateDatasetImpl();
    024                result.shape = ShapeUtils.getShapeFromObject(obj);
    025                result.size = ShapeUtils.calcSize(result.shape);
    026                result.odata = result.data = createArray(result.size);
    027
    028                final int[] pos = new int[result.shape.length];
    029                result.fillData(obj, 0, pos);
    030
    031                return result;
    032        }
    033
    034        /**
    035         * Create a null dataset
    036         */
    037        DateDatasetImpl() {
    038                super();
    039        }
    040
    041        DateDatasetImpl(final int... shape) {
    042                super(shape);
    043        }
    044
    045        DateDatasetImpl(final Date[] data, int... shape) {
    046                super(datesToStrings(data), shape);
    047        }
    048
    049        private static String[] datesToStrings(final Date[] dates) {
    050                final String[] dateStrings = new String[dates.length];
    051                for (int i = 0; i < dates.length; i++) {
    052                        dateStrings[i] = dateToString(dates[i]);
    053                }
    054
    055                return dateStrings;
    056        }
    057
    058        private static String dateToString(final Date date) {
    059                if (date != null) {
    060                        return ISO8601_DATE_FORMAT.format(date);
    061                }
    062
    063                return null;
    064        }
    065
    066        private static String objectToDateString(final Object obj) {
    067                if (obj instanceof Date) {
    068                        return dateToString((Date) obj);
    069                } else if (obj instanceof Dataset) {
    070                        Dataset dataset = (Dataset) obj;
    071                        if (dataset.getSize() != 1) {
    072                                logger.error("Given dataset must only have one item");
    073                                throw new IllegalArgumentException("Given dataset must have only one item");
    074                        }
    075
    076                        return objectToDateString(dataset.getObjectAbs(0));
    077                } else if (obj instanceof IDataset) {
    078                        IDataset dataset = (IDataset) obj;
    079                        if (dataset.getSize() != 1) {
    080                                logger.error("Given dataset must only have one item");
    081                                throw new IllegalArgumentException("Given dataset must have only one item");
    082                        }
    083                        return objectToDateString(dataset.getObject(new int[dataset.getRank()]));
    084                } else {
    085                        logger.error("Argument is of unsupported class");
    086                        throw new IllegalArgumentException("Argument is of unsupported class");
    087                }
    088        }
    089
    090        private static Date stringToDate(final String dateAsString) {
    091                if (dateAsString != null) {
    092                        try {
    093                                return ISO8601_DATE_FORMAT.parse(dateAsString);
    094                        } catch (ParseException e) {
    095                                // fall through to return null
    096                                logger.error("Could not parse datetime: " + dateAsString);
    097                        }
    098                }
    099
    100                return null;
    101        }
    102
    103        @Override
    104        public Date getDate() {
    105                final String dateAsString = super.getString();
    106                return stringToDate(dateAsString);
    107        }
    108
    109        @Override
    110        public Date getDate(int i) {
    111                final String dateAsString = super.getString(i);
    112                return stringToDate(dateAsString);
    113        }
    114
    115        @Override
    116        public Date getDate(int i, int j) {
    117                final String dateAsString = super.getString(i, j);
    118                return stringToDate(dateAsString);
    119        }
    120
    121        @Override
    122        public Date getDate(int... pos) {
    123                final String dateAsString = super.getString(pos);
    124                return stringToDate(dateAsString);
    125        }
    126
    127        @Override
    128        public Date getDateAbs(int index) {
    129                final String dateAsString = super.getStringAbs(index);
    130                if (dateAsString != null) {
    131                        return stringToDate(dateAsString);
    132                }
    133
    134                return null;
    135        }
    136
    137        @Override
    138        public void setItemDirect(final int dindex, final int sindex, final Object src) {
    139                if (src instanceof String[]) {
    140                        super.setItemDirect(dindex, sindex, src);
    141                } else if (src instanceof Date[]) {
    142                        String[] datesAsStrings = datesToStrings((Date[]) src);
    143                        data[dindex] = datesAsStrings[sindex];
    144                } else {
    145                        logger.error("Argument is of unsupported class");
    146                        throw new IllegalArgumentException("Argument is of unsupported class");
    147                }
    148        }
    149
    150        public void setAbs(final int index, final Date date) {
    151                data[index] = dateToString(date);
    152                setDirty();
    153        }
    154
    155        /**
    156         * @since 2.0
    157         */
    158        public void setItem(final Date value) {
    159                setAbs(getFirst1DIndex(), value);
    160        }
    161
    162        public void setItem(final Date value, final int i) {
    163                setAbs(get1DIndex(i), value);
    164        }
    165
    166        public void setItem(final Date value, final int i, final int j) {
    167                setAbs(get1DIndex(i, j), value);
    168        }
    169
    170        public void setItem(final Date value, final int... pos) {
    171                setAbs(get1DIndex(pos), value);
    172        }
    173
    174        @Override
    175        public void set(final Object obj) {
    176                setItem(objectToDateString(obj));
    177        }
    178
    179        @Override
    180        public void set(final Object obj, final int i) {
    181                setItem(objectToDateString(obj), i);
    182        }
    183
    184        @Override
    185        public void set(final Object obj, final int i, final int j) {
    186                setItem(objectToDateString(obj), i, j);
    187        }
    188
    189        @Override
    190        public void set(final Object obj, int... pos) {
    191                if (pos == null || (pos.length == 0 && shape.length > 0)) {
    192                        pos = new int[shape.length];
    193                }
    194
    195                setItem(objectToDateString(obj), pos);
    196        }
    197
    198        @Override
    199        public StringDatasetBase sort(Integer axis) {
    200                // Note yet supported.
    201                // TODO: this method will be inefficient as we store dates formatted as strings
    202                throw new UnsupportedOperationException("Cannot sort dataset");
    203        }
    204
    205}