001/*
002 * JScience - Java(TM) Tools and Libraries for the Advancement of Sciences.
003 * Copyright (C) 2006 - JScience (http://jscience.org/)
004 * All rights reserved.
005 * 
006 * Permission to use, copy, modify, and distribute this software is
007 * freely granted, provided that this notice is preserved.
008 */
009package org.jscience.geography.coordinates;
010
011import java.util.Date;
012
013import javax.measure.Measurable;
014import javax.measure.converter.UnitConverter;
015import javax.measure.quantity.Duration;
016import static javax.measure.unit.SI.*;
017import javax.measure.unit.Unit;
018
019import javolution.context.ObjectFactory;
020import javolution.xml.XMLFormat;
021import javolution.xml.stream.XMLStreamException;
022
023import org.jscience.geography.coordinates.crs.TemporalCRS;
024import org.opengis.referencing.cs.CoordinateSystem;
025
026/**
027 * This class represents the {@link TemporalCRS temporal} UTC time coordinates.
028 * 
029 * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
030 * @version 3.0, February 6, 2006
031 */
032public final class Time extends Coordinates<TemporalCRS<?>> implements Measurable<Duration> {
033
034    /**
035     * Holds the coordinate reference system for all instances of this class. 
036     */
037    public static final TemporalCRS<Time> CRS = new TemporalCRS<Time>() {
038
039        @Override
040        protected Time coordinatesOf(AbsolutePosition position) {
041            if (position.timeUTC instanceof Time)
042                return (Time) position.timeUTC;
043            return Time.valueOf(position.timeUTC.doubleValue(SECOND),
044                    SECOND);
045        }
046
047        @Override
048        protected AbsolutePosition positionOf(Time coordinates, AbsolutePosition position) {
049            position.timeUTC = coordinates;
050            return position;
051        }
052
053        @Override
054        public CoordinateSystem getCoordinateSystem() {
055            return TemporalCRS.TIME_CS;
056        }
057        
058    };
059
060    /**
061     * Holds the time in second since midnight, January 1, 1970 UTC. 
062     */
063    private double _seconds;
064
065    /**
066     * Returns the temporal position corresponding to the specified coordinates.
067     * 
068     * @param value the time since midnight, January 1, 1970 UTC stated in the  
069     *        specified unit.
070     * @param unit the duration unit in which the time value is stated.
071     * @return the corresponding temporal position.
072     */
073    public static Time valueOf(double value, Unit<Duration> unit) {
074        Time time = FACTORY.object();
075        if (unit == SECOND) {
076            time._seconds = value;
077        } else {
078            UnitConverter toSecond = unit.getConverterTo(SECOND);
079            time._seconds = toSecond.convert(value);
080        }
081        return time;
082    }
083
084    private static final ObjectFactory<Time> FACTORY = new ObjectFactory<Time>() {
085
086        @Override
087        protected Time create() {
088            return new Time();
089        }
090    };
091   
092    private Time() {    
093    }
094   
095        
096    /**
097     * Returns the temporal position corresponding to the specified date.
098     * 
099     * @param date the date.
100     * @return the corresponding temporal position.
101     */
102    public static Time valueOf(Date date) {
103        return Time.valueOf(date.getTime(), MILLI(SECOND));
104    }
105
106    /**
107     * Creates the temporal position corresponding to the specified coordinates.
108     * 
109     * @param value the time since midnight, January 1, 1970 UTC stated in the  
110     *        specified unit.
111     * @param unit the duration unit in which the time value is stated.
112     */
113    public Time(double value, Unit<Duration> unit) {
114    }
115
116    @Override
117    public TemporalCRS<?> getCoordinateReferenceSystem() {
118        return CRS;
119    }
120
121    // OpenGIS Interface.
122    public int getDimension() {
123        return 1;
124    }
125
126    // OpenGIS Interface.
127    public double getOrdinate(int dimension) throws IndexOutOfBoundsException {
128        if (dimension == 0) {
129            Unit<?> u = TemporalCRS.TIME_CS.getAxis(0).getUnit();
130            return SECOND.getConverterTo(u).convert(_seconds);
131        } else {
132            throw new IndexOutOfBoundsException();
133        }
134    }
135
136    // Implements Scalar<Duration>
137    public final double doubleValue(Unit<Duration> unit) {
138        return unit.equals(SECOND) ? _seconds : SECOND
139                .getConverterTo(unit).convert(_seconds);
140    }
141
142    // Implements Scalar<Duration>
143    public final long longValue(Unit<Duration> unit) {
144        return Math.round(doubleValue(unit));
145    }
146
147    // Implements Scalar<Duration>
148    public int compareTo(Measurable<Duration> arg0) {
149        double arg0InSecond = arg0.doubleValue(SECOND);
150        return (_seconds > arg0InSecond) ? 1
151                : (_seconds < arg0InSecond) ? -1 : 0;
152    }
153
154    // Implements Realtime.
155    public Time copy() {
156        return Time.valueOf(_seconds, SECOND);
157    }
158    
159    // Default serialization.
160    //
161    
162    static final XMLFormat<Time> XML = new XMLFormat<Time>(Time.class) {
163        
164        @Override
165        public Time newInstance(Class<Time> cls, InputElement xml) throws XMLStreamException {
166            return FACTORY.object();
167        }
168        
169        public void write(Time time, OutputElement xml) throws XMLStreamException {
170             xml.setAttribute("seconds", time._seconds);
171         }
172
173         public void read(InputElement xml, Time time) throws XMLStreamException {
174             time._seconds = xml.getAttribute("seconds", 0.0);
175         }
176     };
177
178    private static final long serialVersionUID = 1L;
179
180}