/*
* -----------------------------------------------------------------------
* Copyright © 2013-2015 Meno Hochschild, <http://www.menodata.de/>
* -----------------------------------------------------------------------
* This file (WindowsZone.java) is part of project Time4J.
*
* Time4J 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, either version 2.1 of the License, or
* (at your option) any later version.
*
* Time4J 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.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Time4J. If not, see <http://www.gnu.org/licenses/>.
* -----------------------------------------------------------------------
*/
package net.time4j.tz.other;
import net.time4j.tz.TZID;
import net.time4j.tz.spi.WinZoneProviderSPI;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.util.Collections;
import java.util.Locale;
import java.util.Set;
/**
* <p>Represents a windows timezone name which can be mapped to an IANA/Olson-ID
* using a territory information. </p>
*
* <p>Example: </p>
*
* <pre>
* WindowsZone wzn = WindowsZone.of("Eastern Standard Time");
* TZID winzone = wzn.resolveSmart(Locale.US);
* System.out.println(winzone.canonical());
* // output: WINDOWS~America/New_York
* </pre>
*
* @author Meno Hochschild
* @since 2.2
*/
/*[deutsch]
* <p>Repräsentiert eine Windows-Zeitzone, die mit Hilfe einer
* Länderinformation zu einer IANA/Olson-ID umgeformt werden kann. </p>
*
* <p>Beispiel: </p>
*
* <pre>
* WindowsZone wzn = WindowsZone.of("Eastern Standard Time");
* TZID winzone = wzn.resolveSmart(Locale.US);
* System.out.println(winzone.canonical());
* // output: WINDOWS~America/New_York
* </pre>
*
* @author Meno Hochschild
* @since 2.2
*/
public final class WindowsZone
implements Comparable<WindowsZone>, Serializable {
//~ Statische Felder/Initialisierungen --------------------------------
private static final long serialVersionUID = -6071278077083785308L;
//~ Instanzvariablen --------------------------------------------------
/**
* @serial name of windows zone
*/
private final String name;
//~ Konstruktoren -----------------------------------------------------
private WindowsZone(String name) {
super();
this.name = name;
}
//~ Methoden ----------------------------------------------------------
/**
* <p>Yields all available names of windows zones. </p>
*
* @return unmodifiable set of zone names for Windows
* @since 2.3
*/
/*[deutsch]
* <p>Liefert alle verfügbaren Namen von Windows-Zeitzonen. </p>
*
* @return unmodifiable set of zone names for Windows
* @since 2.3
*/
public static Set<String> getAvailableNames() {
return WinZoneProviderSPI.NAME_BASED_MAP.keySet();
}
/**
* <p>Creates a name reference to a windows zone. </p>
*
* @param name standardized windows zone name
* @return new instance of {@code WindowsZone}
* @throws IllegalArgumentException if given name is not supported
* @since 2.2
* @see #getAvailableNames()
*/
/*[deutsch]
* <p>Erzeugt einen Namensbezug zu einer Windows-Zeitzone. </p>
*
* @param name standardized windows zone name
* @return new instance of {@code WindowsZone}
* @throws IllegalArgumentException if given name is not supported
* @since 2.2
* @see #getAvailableNames()
*/
public static WindowsZone of(String name) {
check(name);
return new WindowsZone(name);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
} else if (obj instanceof WindowsZone) {
WindowsZone that = (WindowsZone) obj;
return this.name.equals(that.name);
} else {
return false;
}
}
@Override
public int hashCode() {
return this.name.hashCode();
}
/**
* <p>Returns the name of this windows zone reference. </p>
*
* @return name of windows zone
*/
/*[deutsch]
* <p>Liefert den Namen dieser Zeitzonenreferenz. </p>
*
* @return name of windows zone
*/
@Override
public String toString() {
return this.name;
}
/**
* <p>The natural order is based on the lexicographical order of the
* underlying names of windows zones. </p>
*
* @param other another windows zone name reference
* @return a negative integer, zero, or a positive integer as this object
* is less than, equal to, or greater than the specified object.
*/
/*[deutsch]
* <p>Die natürliche Ordnung basiert auf der lexikographischen
* Reihenfolge der zugrundeliegenden Namen von Windows-Zeitzonen. </p>
*
* @param other another windows zone name reference
* @return a negative integer, zero, or a positive integer as this object
* is less than, equal to, or greater than the specified object.
*/
@Override
public int compareTo(WindowsZone other) {
return this.name.compareTo(other.name);
}
/**
* <p>Resolves this name reference to a set of various zone ids for given
* country. </p>
*
* @param country country reference
* @return set of ids belonging to this windows zone
* @since 2.2
*/
/*[deutsch]
* <p>Löst diese Namensreferenz zu einem Satz von Zonen-IDs zum
* angegebenen Land auf. </p>
*
* @param country country reference
* @return set of ids belonging to this windows zone
* @since 2.2
*/
public Set<TZID> resolve(Locale country) {
Set<TZID> ids = WinZoneProviderSPI.NAME_BASED_MAP.get(this.name).get(country.getCountry());
if (ids == null) {
return Collections.emptySet();
} else {
return Collections.unmodifiableSet(ids);
}
}
/**
* <p>Resolves this name reference to at most one zone id for given
* country. </p>
*
* <p>Normally windows zones cannot be resolved to one single zone id,
* but there is usually one preferred zone id based on the fact that
* the daylight saving rules for this name and given country are often
* the same for all belonging zone ids in the recent past. This method
* tries its best to yield a result but applications have to check if
* the result is {@code null}. </p>
*
* @param country country reference
* @return preferred zone id belonging to this windows zone
* or {@code null} if given country is not related to this name
* @since 2.2
*/
/*[deutsch]
* <p>Löst diese Namensreferenz zu maximal einer Zonen-ID zum
* angegebenen Land auf. </p>
*
* <p>Normalerweise lassen sich Windows-Zeitzonen nicht zu einer eindeutigen
* Zonen-ID auflösen, aber es gibt gewöhnlich eine bevorzugte
* Zeitzonen-ID, deren Zeitumstellungsregeln sich in der jüngsten
* Vergangenheit oft nicht von denen anderer Zeitzonen-IDs der gleichen
* Windows-Zeitzone unterscheiden. Diese Methode versucht das Beste, um
* eine solche bevorzugte Zeitzone zu ermitteln, aber Anwendungen sind
* verpflichtet zu prüfen, ob das Ergebnis {@code null} ist. </p>
*
* @param country country reference
* @return preferred zone id belonging to this windows zone
* or {@code null} if given country is not related to this name
* @since 2.2
*/
public TZID resolveSmart(Locale country) {
Set<TZID> ids = this.resolve(country);
if (ids.size() > 1) {
ids = WinZoneProviderSPI.NAME_BASED_MAP.get(this.name).get("001");
}
switch (ids.size()) {
case 0:
return null;
case 1:
return ids.iterator().next();
default:
throw new AssertionError(
"Ambivalent windows zone: " + this.name);
}
}
/**
* <p>Yields the repository version. </p>
*
* @return String
* @since 2.3
*/
/*[deutsch]
* <p>Liefert die zugrundeliegende Version der CLDR-Daten. </p>
*
* @return String
* @since 2.3
*/
static String getVersion() {
return WinZoneProviderSPI.WIN_NAME_VERSION;
}
private static void check(String name) {
if (
name.isEmpty()
|| !WinZoneProviderSPI.NAME_BASED_MAP.keySet().contains(name)
) {
throw new IllegalArgumentException("Unknown windows zone: " + name);
}
}
/**
* @serialData Checks the consistency.
* @param in object input stream
* @throws ClassNotFoundException if the class of a serialized object could not be found.
* @throws IOException if an I/O error occurs.
* @throws IllegalArgumentException in case of inconsistencies
*/
private void readObject(ObjectInputStream in)
throws IOException, ClassNotFoundException {
in.defaultReadObject();
check(this.name);
}
}