/* Copyright (c) 2011 Danish Maritime Authority. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.maritimecloud.util; import java.io.IOException; import java.io.InputStreamReader; import java.io.Serializable; import java.net.URL; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Properties; /** * Class to represent a country by its assigned MID's (Maritime Identification Digits) in addition to its ISO 3166 * identification. * * @see <a * href="http://en.wikipedia.org/wiki/Maritime_Mobile_Service_Identity">http://en.wikipedia.org/wiki/Maritime_Mobile_Service_Identity</a> */ // TODO make Message public final class Country implements Serializable, Comparable<Country> { private static final long serialVersionUID = 1L; private static final String LOCATION = Country.class.getPackage().getName().replace(".", "/") + "/country.properties"; static final HashMap<Integer, Country> MID_COUNTRY_MAP = new HashMap<>(); static final HashMap<String, Country> THREE_LETTER_MAP = new HashMap<>(); static final HashMap<String, Country> TWO_LETTER_MAP = new HashMap<>(); static { Properties props = new Properties(); URL url = ClassLoader.getSystemResource(LOCATION); if (url == null) { url = Thread.currentThread().getContextClassLoader().getResource(LOCATION); } if (url == null) { throw new Error("Could not locate " + LOCATION + " on classpath"); } try { props.load(new InputStreamReader(url.openStream(), StandardCharsets.UTF_8)); } catch (IOException e) { throw new Error("Failed to load country.properties: " + e.getMessage()); } for (Object key : props.keySet()) { String a2 = (String) key; String val = props.getProperty(a2); String[] elems = val.split("\\|"); Country country = new Country(elems[0], a2, elems[1], elems[2]); if (elems.length > 3) { String[] strMids = elems[3].split(","); for (String strMid : strMids) { Integer mid = Integer.parseInt(strMid); country.addMid(mid); MID_COUNTRY_MAP.put(mid, country); } } TWO_LETTER_MAP.put(country.getTwoLetter(), country); THREE_LETTER_MAP.put(country.getThreeLetter(), country); } } private final HashSet<Integer> mids = new HashSet<>(); protected final String name; protected final String number; protected final String threeLetter; protected final String twoLetter; private Country(String name, String twoLetter, String threeLetter, String number) { this.name = name; this.twoLetter = twoLetter; this.threeLetter = threeLetter; this.number = number; } void addMid(int mid) { mids.add(mid); } @Override public boolean equals(Object obj) { return this.threeLetter.equals(((Country) obj).getThreeLetter()); } public HashSet<Integer> getMids() { return mids; } public String getName() { return name; } public String getNumber() { return number; } public String getThreeLetter() { return threeLetter; } public String getTwoLetter() { return twoLetter; } @Override public int hashCode() { return twoLetter.hashCode(); } public boolean matchMid(int mid) { return mids.contains(mid); } @Override public String toString() { StringBuilder builder = new StringBuilder(); builder.append("[name="); builder.append(name); builder.append(", number="); builder.append(number); builder.append(", threeLetter="); builder.append(threeLetter); builder.append(", twoLetter="); builder.append(twoLetter); builder.append(", mids="); builder.append(mids); builder.append("]"); return builder.toString(); } /** * Get MidCountry by ISO 3166 two or three letter code * * @param code * the code * @return the country corresponding to the specified code */ public static Country getByCode(String code) { if (code.length() == 2) { return TWO_LETTER_MAP.get(code); } return THREE_LETTER_MAP.get(code); } /** * Get MidCountry by MID * * @param mid * the code * @return the country corresponding to the specified code */ public static Country getByMid(int mid) { Country country = MID_COUNTRY_MAP.get(mid); if (country == null) { // LOG.debug("Unknown MID " + mid); } return country; } public static Country getCountryForMmsi(Integer mmsi) { String str = Integer.toString(mmsi); if (str.length() == 9) { str = str.substring(0, 3); return getByMid(Integer.parseInt(str)); } return null; } public static Map<Integer, Country> getMidMap() { return Collections.unmodifiableMap(MID_COUNTRY_MAP); } public static List<Country> findAllByCode(String... countries) { final List<Country> c = new ArrayList<>(); for (String s : countries) { Country co = Country.getByCode(s); if (co == null) { throw new IllegalArgumentException("Unknown country: " + s); } c.add(co); } return c; } /** {@inheritDoc} */ @Override public int compareTo(Country o) { return threeLetter.compareTo(o.threeLetter); } }