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}