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}