/*
* Geotoolkit.org - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2007-2012, Open Source Geospatial Foundation (OSGeo)
* (C) 2009-2012, Geomatys
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package org.geotoolkit.util;
import java.util.Date;
import javax.measure.Unit;
import javax.measure.UnitConverter;
import javax.measure.IncommensurableException;
import org.apache.sis.measure.Units;
import org.apache.sis.measure.Range;
import org.apache.sis.measure.MeasurementRange;
import org.geotoolkit.resources.Errors;
/**
* A range of dates. The elements in this range are {@link Date} objects.
* Consequently the precision of {@code DateRange} objects is milliseconds.
*
* @author Martin Desruisseaux (Geomatys)
* @version 3.20
*
* @see org.geotoolkit.measure.RangeFormat
*
* @since 2.5
* @module
*/
public class DateRange extends Range<Date> {
/**
* For cross-version compatibility.
*/
private static final long serialVersionUID = -6400011350250757942L;
/**
* Creates a new date range for the given dates. Start time and end time are inclusive.
*
* @param startTime The start time (inclusive), or {@code null} if none.
* @param endTime The end time (inclusive), or {@code null} if none.
*/
public DateRange(final Date startTime, final Date endTime) {
super(Date.class, clone(startTime), true, clone(endTime), true);
}
/**
* Creates a new date range for the given dates.
*
* @param startTime The start time, or {@code null} if none.
* @param isMinIncluded {@code true} if the start time is inclusive.
* @param endTime The end time, or {@code null} if none.
* @param isMaxIncluded {@code true} if the end time is inclusive.
*/
public DateRange(final Date startTime, boolean isMinIncluded,
final Date endTime, boolean isMaxIncluded)
{
super(Date.class, clone(startTime), isMinIncluded,
clone( endTime), isMaxIncluded);
}
/**
* Creates a date range from the specified measurement range. Units are converted as needed.
*
* @param range The range to convert.
* @param origin The date to use as the origin.
* @throws IncommensurableException if the given range doesn't have a
* {@linkplain MeasurementRange#getUnits unit} compatible with milliseconds.
*/
public DateRange(final MeasurementRange<?> range, final Date origin) throws IncommensurableException {
this(range, getConverter(range.unit()), origin.getTime());
}
/**
* Workaround for RFE #4093999 ("Relax constraint on placement of this()/super()
* call in constructors").
*/
private DateRange(final MeasurementRange<?> range, final UnitConverter converter, final long origin)
throws IncommensurableException
{
super(Date.class,
new Date(origin + Math.round(converter.convert(range.getMinDouble()))), range.isMinIncluded(),
new Date(origin + Math.round(converter.convert(range.getMaxDouble()))), range.isMaxIncluded());
}
/**
* Casts the given {@code Range} object to a {@code DateRange}. This method shall be invoked
* only in context where we have verified that the range element class is compatible. This
* verification is performed by {@link Range#ensureCompatible(Range)} method.
*/
private static DateRange cast(final Range<?> range) {
if (range == null || range instanceof DateRange) {
return (DateRange) range;
}
return new DateRange((Date) range.getMinValue(), range.isMinIncluded(),
(Date) range.getMaxValue(), range.isMaxIncluded());
}
/**
* Returns a clone of the specified date.
*/
private static Date clone(final Date date) {
return (date != null) ? (Date) date.clone() : null;
}
/**
* Workaround for RFE #4093999 ("Relax constraint on placement of this()/super()
* call in constructors").
*/
private static UnitConverter getConverter(final Unit<?> source) throws IncommensurableException {
if (source == null) {
throw new IncommensurableException(Errors.format(Errors.Keys.NoUnit));
}
return source.getConverterToAny(Units.MILLISECOND);
}
/**
* Returns the start time.
*/
@Override
public Date getMinValue() {
return clone(super.getMinValue());
}
/**
* Returns the end time.
*/
@Override
public Date getMaxValue() {
return clone(super.getMaxValue());
}
/**
* {@inheritDoc}
*
* @since 3.20
*/
@Override
public DateRange union(final Range<Date> range) throws IllegalArgumentException {
return cast(super.union(range));
}
/**
* {@inheritDoc}
*
* @since 3.20
*/
@Override
public DateRange intersect(final Range<Date> range) throws IllegalArgumentException {
return cast(super.intersect(range));
}
/**
* {@inheritDoc}
*
* @since 3.20
*/
@Override
public DateRange[] subtract(final Range<Date> range) throws IllegalArgumentException {
final Range<Date>[] ranges = super.subtract(range);
final DateRange[] result = new DateRange[ranges.length];
for (int i=0; i<result.length; i++) {
result[i] = cast(ranges[i]);
}
return result;
}
}