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}