/*
* Geotoolkit - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2008, Open Source Geospatial Foundation (OSGeo)
* (C) 2009, 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.temporal.reference;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.util.Collection;
import java.util.Map;
import java.util.Objects;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import org.apache.sis.internal.referencing.NilReferencingObject;
import org.apache.sis.referencing.AbstractIdentifiedObject;
import org.apache.sis.util.ArgumentChecks;
import org.apache.sis.util.ComparisonMode;
import org.apache.sis.util.NullArgumentException;
import org.opengis.referencing.IdentifiedObject;
import org.opengis.temporal.Calendar;
import org.opengis.temporal.CalendarDate;
import org.opengis.temporal.CalendarEra;
import org.opengis.temporal.Clock;
import org.opengis.temporal.JulianDate;
import org.opengis.temporal.Period;
import org.opengis.util.InternationalString;
/**
* Characteristic of each calendar era.
*
* @author Mehdi Sidhoum (Geomatys)
* @module
*
* @version 4.0
* @since 4.0
*/
@XmlType(name = "TimeCalendarEra_Type", propOrder = {
"referenceEvent",
"referenceDat",
"julianRef",
"epochOfUse"
})
@XmlRootElement(name = "TimeCalendarEra")
public class DefaultCalendarEra extends AbstractIdentifiedObject implements CalendarEra {
private static NumberFormat NUMBER_FORMAT;
static {
DecimalFormatSymbols dfs = new DecimalFormatSymbols();
dfs.setDecimalSeparator('.');
NUMBER_FORMAT = new DecimalFormat("#", dfs);
NUMBER_FORMAT.setMinimumFractionDigits(9);
}
/**
* Provide the name or description of a mythical or historic event which fixes the position of the base scale of the calendar era.
*/
private InternationalString referenceEvent;
/**
* provide the date of the reference referenceEvent expressed as a date in the given calendar.
* In most calendars, this date is the origin (i.e the first day) of the scale, but this is not always true.
*/
private CalendarDate referenceDate;
/**
* Provide the Julian date that corresponds to the reference date.
*/
private JulianDate julianReference;
/**
* Identify the {@link Period} for which the calendar era was used as a basis for dating,
* the datatype for {@link Period#getBeginning() } and {@link Period#getEnding() } shall be JulianDate.
*/
private Period epochOfUse;
/**
* Collection of {@link Calendar} that use this {@link CalendarEra} as a reference for dating.
*/
private Collection<Calendar> datingSystem;
/**
* Create a new {@link Clock} implementation initialize with the given parameters.<br/>
* The properties given in argument follow the same rules than for the
* {@linkplain DefaultTemporalCRS#DefaultTemporalCRS(java.util.Map, org.opengis.referencing.datum.TemporalDatum, org.opengis.referencing.cs.TimeCS) super-class constructor}.
* The following table is a reminder of current main (not all) properties:
*
* <table class="ISO 19108">
* <caption>Recognized properties (non exhaustive list)</caption>
* <tr>
* <th>Property name</th>
* <th>Value type</th>
* <th>Returned by</th>
* </tr>
* <tr>
* <td>{@value org.opengis.referencing.IdentifiedObject#NAME_KEY}</td>
* <td>{@link org.opengis.referencing.ReferenceIdentifier} or {@link String}</td>
* <td>{@link #getName()}</td>
* </tr>
* <tr>
* <td>{@value org.opengis.referencing.datum.Datum#DOMAIN_OF_VALIDITY_KEY}</td>
* <td>{@link org.opengis.metadata.extent.Extent}</td>
* <td>{@link #getDomainOfValidity()}</td>
* </tr>
* <tr>
* <td>{@value org.opengis.temporal.Calendar#REFERENCE_EVENT_KEY}</td>
* <td>{@link org.opengis.util.InternationalString}</td>
* <td>{@link #getReferenceEvent()}</td>
* </tr>
* </table>
*
* @param properties The properties to be given to the coordinate reference system.
* @param referenceTime The time of day associated with the reference event expressed as a time of day in the given clock.
* @param utcReference The 24-hour local or UTC time that corresponds to the reference time.
*/
public DefaultCalendarEra(Map<String, ?> properties,
final CalendarDate referenceDate, final JulianDate julianReference, final Period epochOfUse) {
super(properties);
final Object ref = properties.get(Calendar.REFERENCE_EVENT_KEY);
ArgumentChecks.ensureNonNull("referenceEvent", ref);
ArgumentChecks.ensureNonNull("referenceDate", referenceDate);
ArgumentChecks.ensureNonNull("julianReference", julianReference);
ArgumentChecks.ensureNonNull("epochOfUse", epochOfUse);
if (!(ref instanceof InternationalString))
throw new IllegalArgumentException("reference Event must be instance of refernceEvent");
this.referenceDate = referenceDate;
this.referenceEvent = (InternationalString) ref;
this.julianReference = julianReference;
this.epochOfUse = epochOfUse;
}
/**
* Empty constructor only use for XML binding.
*/
private DefaultCalendarEra() {
super(NilReferencingObject.INSTANCE);
}
/**
* Constructs a new instance initialized with the values from the specified metadata object.
* This is a <cite>shallow</cite> copy constructor, since the other metadata contained in the
* given object are not recursively copied.
*
* @param object The CalendarEra to copy values from, or {@code null} if none.
*
* @see #castOrCopy(CalendarEra)
* @throws NullArgumentException if referenceEvent, referenceDate, julianReference or epochOfUse is {@code null}.
*/
private DefaultCalendarEra(final CalendarEra object) {
super(object);
if (object != null) {
this.referenceEvent = object.getReferenceEvent();
ArgumentChecks.ensureNonNull("referenceEvent", referenceEvent);
this.referenceDate = object.getReferenceDate();
ArgumentChecks.ensureNonNull("referenceDate", referenceDate);
this.julianReference = object.getJulianReference();
ArgumentChecks.ensureNonNull("julianReference", julianReference);
this.epochOfUse = object.getEpochOfUse();
ArgumentChecks.ensureNonNull("julianReference", julianReference);
if (object instanceof DefaultCalendarEra) {
this.datingSystem = ((DefaultCalendarEra) object).getDatingSystem();
}
}
}
/**
* Returns a Geotk implementation with the values of the given arbitrary implementation.
* This method performs the first applicable action in the following choices:
*
* <ul>
* <li>If the given object is {@code null}, then this method returns {@code null}.</li>
* <li>Otherwise if the given object is already an instance of
* {@code DefaultCalendarEra}, then it is returned unchanged.</li>
* <li>Otherwise a new {@code DefaultCalendarEra} instance is created using the
* {@linkplain #DefaultCalendarEra(CalendarEra) copy constructor}
* and returned. Note that this is a <cite>shallow</cite> copy operation, since the other
* metadata contained in the given object are not recursively copied.</li>
* </ul>
*
* @param object The object to get as a Geotk implementation, or {@code null} if none.
* @return A Geotk implementation containing the values of the given object (may be the
* given object itself), or {@code null} if the argument was null.
*/
public static DefaultCalendarEra castOrCopy(final CalendarEra object) {
if (object == null || object instanceof DefaultCalendarEra) {
return (DefaultCalendarEra) object;
}
return new DefaultCalendarEra(object);
}
/**
* Returns the name or description of a mythical or historic event which fixes the position
* of the base scale of the calendar era.
*
* @return Event used as the datum for this calendar era.
*/
@Override
@XmlElement(name = "referenceEvent", required = true)
public InternationalString getReferenceEvent() {
return referenceEvent;
}
/**
* Returns the date of the reference event expressed as a date in the given calendar.
* <blockquote><font size="-1">In most calendars, this date is the origin (i.e., the first day)
* of the scale, but this is not always {@code true}.</font></blockquote>
*
* @return Date of the reference event in the calendar being described.
*/
@Override
public CalendarDate getReferenceDate() {
return referenceDate;
}
/**
* Returns {@link #referenceDate} adapted for JAXB Marshalling.
*
* @return {@link #referenceDate} adapted for JAXB Marshalling.
*/
@XmlElement(name = "referenceDate", required = true)
private String getReferenceDat() {
final int[] dat = referenceDate.getCalendarDate();
String str = ""+dat[0];
for(int i = 1; i < dat.length; i++){
str = str + "-";
if (dat[i] < 10) str = str+"0";
str = str+dat[i];
}
return str;
}
/**
* Returns the {@linkplain JulianDate julian date} that corresponds to the reference date.
*
* @return {@linkplain JulianDate julian date} of the reference event.
*/
@Override
public JulianDate getJulianReference() {
return julianReference;
}
/**
* Returns {@link #julianReference} adapted for JAXB Marshalling.
*
* @return {@link #julianReference} adapted for JAXB Marshalling.
*/
@XmlElement(name = "julianReference", required = true)
private String getJulianRef() {
return NUMBER_FORMAT.format(julianReference.getCoordinateValue().doubleValue());
}
/**
* Returns the {@linkplain Period period} for which the calendar era
* was used as a reference for dating.
*
* @return The period, where the data type for {@linkplain Period#getBegin begin}
* and {@link Period#getEnd end} is {@link JulianDate}.
*/
@Override
@XmlElement(name = "epochOfUse", required = true)
public Period getEpochOfUse() {
return epochOfUse;
}
/**
* Returns a collection of {@link Calendar} that use this {@link CalendarEra} as a reference for dating.
*
* @return collection of {@link Calendar} that use this {@link CalendarEra} as a reference for dating.
*/
public Collection<Calendar> getDatingSystem() {
return datingSystem;
}
/**
* Set a new name or description of a mythical or historic event which fixes the position
* of the base scale of the calendar era.
*
* @param referenceEvent The new event used as the datum for this calendar era.
*/
public void setReferenceEvent(final InternationalString referenceEvent) {
ArgumentChecks.ensureNonNull("referenceEvent", referenceEvent);
this.referenceEvent = referenceEvent;
}
/**
* Set a new date of the reference event expressed as a date in the given calendar.
*
* @param referenceDate The new date of the reference event in the calendar being described.
*/
public void setReferenceDate(final CalendarDate referenceDate) {
ArgumentChecks.ensureNonNull("referenceDate", referenceDate);
this.referenceDate = referenceDate;
}
/**
* Set a new {@linkplain JulianDate julian date} that corresponds to the reference date.
*
* @param julianReference The new {@linkplain JulianDate julian date} of the reference event.
*/
public void setJulianReference(final JulianDate julianReference) {
ArgumentChecks.ensureNonNull("julianReference", julianReference);
this.julianReference = julianReference;
}
/**
* Set a new {@linkplain Period period} for which the calendar era
* was used as a reference for dating.
*
* @param epochOfUse The new period, where the data type for {@linkplain Period#getBegin begin}
* and {@link Period#getEnd end} is {@link JulianDate}.
*/
public void setEpochOfUse(final Period epochOfUse) {
ArgumentChecks.ensureNonNull("epochOfUse", epochOfUse);
this.epochOfUse = epochOfUse;
}
/**
* Set a new collection of {@link Calendar} that use this {@link CalendarEra} as a reference for dating.
*
* @param newValues The new collection of {@link Calendar} that use this {@link CalendarEra} as a reference for dating.
*/
public void setDatingSystem(final Collection<Calendar> newValues) {
this.datingSystem = newValues;
}
@Override
public boolean equals(Object object, ComparisonMode mode) {
if (object instanceof CalendarEra) {
final DefaultCalendarEra that = (DefaultCalendarEra) object;
return Objects.equals(this.datingSystem, that.datingSystem) &&
Objects.equals(this.epochOfUse, that.epochOfUse) &&
Objects.equals(this.julianReference, that.julianReference) &&
Objects.equals(this.getName(), that.getName()) &&
Objects.equals(this.referenceDate, that.referenceDate) &&
Objects.equals(this.referenceEvent, that.referenceEvent);
}
return false;
}
/**
* {@inheritDoc }
*/
@Override
public String toString() {
StringBuilder s = new StringBuilder("CalendarEra:").append('\n');
if (getName() != null) {
s.append("name:").append(getName().getCode()).append('\n');
}
if (epochOfUse != null) {
s.append("epochOfUse:").append(epochOfUse).append('\n');
}
if (referenceEvent != null) {
s.append("referenceEvent:").append(referenceEvent).append('\n');
}
if (referenceDate != null) {
s.append("referenceDate:").append(referenceDate).append('\n');
}
if (julianReference != null) {
s.append("julianReference:").append(julianReference).append('\n');
}
if (datingSystem != null) {
s.append("datingSystem:").append(datingSystem).append('\n');
}
return s.toString();
}
}