    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        @Override
    050        public int getDType() {
    051                return DATE;
    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.getObjectAbs(dataset.getOffset()));
    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 void setItemDirect(final int dindex, final int sindex, final Object src) {
    144                if (src instanceof String[]) {
    145                        super.setItemDirect(dindex, sindex, src);
    146                } else if (src instanceof Date[]) {
    147                        String[] datesAsStrings = datesToStrings((Date[]) src);
    148                        data[dindex] = datesAsStrings[sindex];
    149                } else {
    150                        logger.error("Argument is of unsupported class");
    151                        throw new IllegalArgumentException("Argument is of unsupported class");
    152                }
    153        }
    154
    155        public void setAbs(final int index, final Date date) {
    156                data[index] = dateToString(date);
    157                setDirty();
    158        }
    159
    160        /**
    161         * @since 2.0
    162         */
    163        public void setItem(final Date value) {
    164                setAbs(getFirst1DIndex(), value);
    165        }
    166
    167        public void setItem(final Date value, final int i) {
    168                setAbs(get1DIndex(i), value);
    169        }
    170
    171        public void setItem(final Date value, final int i, final int j) {
    172                setAbs(get1DIndex(i, j), value);
    173        }
    174
    175        public void setItem(final Date value, final int... pos) {
    176                setAbs(get1DIndex(pos), value);
    177        }
    178
    179        @Override
    180        public void set(final Object obj) {
    181                setItem(objectToDateString(obj));
    182        }
    183
    184        @Override
    185        public void set(final Object obj, final int i) {
    186                setItem(objectToDateString(obj), i);
    187        }
    188
    189        @Override
    190        public void set(final Object obj, final int i, final int j) {
    191                setItem(objectToDateString(obj), i, j);
    192        }
    193
    194        @Override
    195        public void set(final Object obj, int... pos) {
    196                if (pos == null || (pos.length == 0 && shape.length > 0)) {
    197                        pos = new int[shape.length];
    198                }
    199
    200                setItem(objectToDateString(obj), pos);
    201        }
    202
    203        @Override
    204        public StringDatasetBase sort(Integer axis) {
    205                // Note yet supported.
    206                // TODO: this method will be inefficient as we store dates formatted as strings
    207                throw new UnsupportedOperationException("Cannot sort dataset");
    208        }
    209
    210}