View Javadoc
1   /*******************************************************************************
2    *   Gisgraphy Project 
3    * 
4    *   This library is free software; you can redistribute it and/or
5    *   modify it under the terms of the GNU Lesser General Public
6    *   License as published by the Free Software Foundation; either
7    *   version 2.1 of the License, or (at your option) any later version.
8    * 
9    *   This library is distributed in the hope that it will be useful,
10   *   but WITHOUT ANY WARRANTY; without even the implied warranty of
11   *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12   *   Lesser General Public License for more details.
13   * 
14   *   You should have received a copy of the GNU Lesser General Public
15   *   License along with this library; if not, write to the Free Software
16   *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
17   * 
18   *  Copyright 2008  Gisgraphy project 
19   *  David Masclet <davidmasclet@gisgraphy.com>
20   *  
21   *  
22   *******************************************************************************/
23  package com.gisgraphy.domain.geoloc.entity;
24  
25  import java.io.Serializable;
26  import java.util.ArrayList;
27  import java.util.Currency;
28  import java.util.List;
29  
30  import javax.persistence.Column;
31  import javax.persistence.Entity;
32  import javax.persistence.ManyToMany;
33  import javax.persistence.Transient;
34  
35  import org.hibernate.annotations.Cache;
36  import org.hibernate.annotations.CacheConcurrencyStrategy;
37  import org.hibernate.annotations.Index;
38  
39  /**
40   * A Country (as defined by ISO 3166). A country always has an ISO 3166 alpha-2,
41   * alpha-3 and numeric code, but may, or may not have other names (FIPS, etc).
42   * The list of countries has been imported from Geonames Country List. Codes are
43   * written in upper case !
44   * 
45   * @see <a
46   *      href="http://www.iso.org/iso/en/prods-services/popstds/countrynamecodes.html">Country
47   *      Name Codes</a>
48   * @author <a href="mailto:david.masclet@gisgraphy.com">David Masclet</a>
49   */
50  @Entity
51  @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
52  public class Country extends GisFeature implements Serializable,
53  	Comparable<Country> {
54  
55      /**
56       * Constructor that populate the {@link Country} with the gisFeature fields<br>
57       * 
58       * @param gisFeature
59       *                The gisFeature from which we want to populate the
60       *                {@linkplain Country}
61       */
62      public Country(GisFeature gisFeature) {
63  	super(gisFeature);
64      }
65  
66      /**
67       * Default constructor (Needed by CGLib)
68       */
69      public Country() {
70  	super();
71      }
72  
73      /**
74       * Construct a country with the iso 3166 alpha-2 code, iso 3166 alpha-3 code, and
75       * iso 3166 numeric code
76       * 
77       * @param iso3166Alpha2Code
78       *                The iso 3166 alpha 2 code for this Country
79       * @param iso3166Alpha3Code
80       *                The iso 3166 alpha3 code for this Country
81       * @param iso3166NumericCode
82       *                The iso 3166 numeric code for this Country <u>NOTE</u> : The
83       *                iso3166AlphaX codes will be automatically uppercased
84       */
85      public Country(String iso3166Alpha2Code, String iso3166Alpha3Code,
86  	    int iso3166NumericCode) {
87  	super();
88  	this.setIso3166Alpha2Code(iso3166Alpha2Code);
89  	this.setIso3166Alpha3Code(iso3166Alpha3Code);
90  	this.setIso3166NumericCode(iso3166NumericCode);
91      }
92  
93      private static final long serialVersionUID = 1L;
94  
95      private Double area;
96  
97      private String tld;
98  
99      private String capitalName;
100 
101     private String continent;
102 
103     private String postalCodeRegex;
104 
105     /**
106      * @see #getCurrencyCode()
107      * @see #getCurrency()
108      */
109     private String currencyCode;
110 
111     private String currencyName;
112 
113     /**
114      * @see #getEquivalentFipsCode()
115      */
116     private String equivalentFipsCode;
117 
118     /**
119      * @see #getFipsCode()
120      */
121     private String fipsCode;
122 
123     /**
124      * @see #getIso3166Alpha2Code()
125      */
126     private String iso3166Alpha2Code;
127 
128     /**
129      * @see #getIso3166Alpha3Code()
130      */
131     private String iso3166Alpha3Code;
132 
133     /**
134      * @see #getIso3166NumericCode()
135      */
136     private int iso3166NumericCode;
137 
138     // TODO v3
139     // private List<Country> neighbourCountries = new ArrayList<Country>();
140     /**
141      * @see #getPhonePrefix()
142      */
143     private String phonePrefix;
144 
145     /**
146      * @see #getPostalCodeMask()
147      */
148     private String postalCodeMask;
149 
150     /**
151      * The spoken languages
152      */
153     private List<Language> spokenLanguages = new ArrayList<Language>();
154 
155     /*
156      * public void addNeighbourCountry(Country c) {
157      * this.neighbourCountries.add(c); }
158      */
159 
160     /**
161      * Add a spoken language to the country. The language is described by its
162      * Alpha2 Code.
163      * 
164      * @param lang
165      */
166     public void addSpokenLanguage(Language lang) {
167 	this.spokenLanguages.add(lang);
168     }
169 
170     /*
171      * (non-Javadoc)
172      * 
173      * @see com.gisgraphy.domain.geoloc.entity.GisFeature#equals(java.lang.Object)
174      */
175     @Override
176     public boolean equals(Object obj) {
177 	if (this == obj) {
178 	    return true;
179 	}
180 	if (!super.equals(obj)) {
181 	    return false;
182 	}
183 	if (getClass() != obj.getClass()) {
184 	    return false;
185 	}
186 	final Country other = (Country) obj;
187 	if (iso3166Alpha2Code == null) {
188 	    if (other.iso3166Alpha2Code != null) {
189 		return false;
190 	    }
191 	} else if (!iso3166Alpha2Code.equals(other.iso3166Alpha2Code)) {
192 	    return false;
193 	}
194 	return true;
195     }
196 
197     /**
198      * Country area in square Km
199      * 
200      * @return The country area in square Km
201      */
202     public Double getArea() {
203 	return this.area;
204     }
205 
206     /**
207      * Returns the ISO 4217 Currency from the currency code. The code is not
208      * imported but processed :
209      * {@link Currency#getInstance(java.util.Locale)} Important : some
210      * currencies are NOT recognized by
211      * {@link Currency#getInstance(java.util.Locale)}.
212      * 
213      * @return The ISO 4217 Currency or null if the currencyCode is null or
214      *         incorrect
215      */
216     @Transient
217     public Currency getCurrency() {
218 	Currency currency = null;
219 	if (this.currencyCode != null) {
220 	    try {
221 		currency = Currency.getInstance(this.currencyCode);
222 	    } catch (RuntimeException e) {
223 	    	logger.warn("Got a wrong currencycode" + getCountryCode());
224 	    }
225 	}
226 	return currency;
227     }
228 
229     /**
230      * ISO 4217 currency code when possible. However, for some countries, there
231      * is no official ISO 4217 code, like Guernsey (GGP), and the information
232      * can be null sometimes when we're not sure of the currency (United States
233      * Minor Outlying Islands). This field is not unique, because some countries
234      * have the same currency. (Euro for instance..)
235      * 
236      * @see <a
237      *      href="http://www.iso.org/iso/en/prods-services/popstds/currencycodeslist.html">
238      *      ISO 4217 Currency names </a>
239      * @see <a href="http://en.wikipedia.org/wiki/Guernsey_pound">Guernsey Pound</a>
240      * @see <a
241      *      href="http://en.wikipedia.org/wiki/United_States_Minor_Outlying_Islands">
242      *      United States Minor Outlying Islands</a>
243      * @return The ISO 4217 currency code
244      */
245     @Column(unique = false, nullable = true)
246     public String getCurrencyCode() {
247 	return this.currencyCode;
248     }
249 
250     /**
251      * This field is not supported yet. The equivalent fips Code. This is
252      * the same as the FIPS code, except that sometimes, there is no FIPS code
253      * for some entity (Aaland Islands), even if it is the same country than
254      * another one (finland). So in that case, Aaland island equivalent fips
255      * code will be set to FI
256      * 
257      * @return The equivalent fips Code
258      */
259     public String getEquivalentFipsCode() {
260 	return this.equivalentFipsCode;
261     }
262 
263     /**
264      * The FIPS 10.4 country code. This field can be null in some cases
265      * (when there is an ISO Code and no FIPS code, for instance). Note that
266      * these code is not the same as the ISO 3166 codes used by the U.N. and
267      * for Internet top-level country code domains.
268      * 
269      * @see <a href="http://en.wikipedia.org/wiki/List_of_FIPS_country_codes">
270      *      List Of FIPS Country Codes </a>
271      * @return Returns the fipsCode.
272      */
273     @Column(unique = true, nullable = true)
274     @Index(name = "countryFipsCode")
275     public String getFipsCode() {
276 	return this.fipsCode;
277     }
278 
279     /**
280      * The ISO 3166 alpha-2 letter code(should be in upper case). We don't use the country code of the
281      * GisFeature because we want that fields as mandatory and the GisFeature
282      * one is not 
283      * 
284      * @see <a href="http://en.wikipedia.org/wiki/ISO_3166"> ISO 3166 </a>
285      * @return Returns the iso3166Alpha2Code.
286      */
287     @Column(unique = true, nullable = false)
288     @Index(name = "countryIso3166Alpha2CodeIndex")
289     public String getIso3166Alpha2Code() {
290 	return this.iso3166Alpha2Code;
291     }
292 
293     /**
294      * The ISO 3166 alpha-3 letter code (should be in upper case)
295      * 
296      * @see <a href="http://en.wikipedia.org/wiki/ISO_3166"> ISO 3166 </a>
297      */
298     @Column(unique = true, nullable = false)
299     @Index(name = "countryIso3166Alpha3CodeIndex")
300     public String getIso3166Alpha3Code() {
301 	return this.iso3166Alpha3Code;
302     }
303 
304     /**
305      * @return The ISO 3166 numeric code
306      */
307     @Column(unique = true, nullable = false)
308     @Index(name = "countryIso3166NumericCodeIndex")
309     public int getIso3166NumericCode() {
310 	return this.iso3166NumericCode;
311     }
312 
313     /*
314      * Neighbour Countries @return @ManyToMany public List<Country>
315      * getNeighbourCountries() { return this.neighbourCountries; }
316      */
317 
318     /**
319      * The Phone Prefix (e.g : 33..) without '+'
320      * 
321      * @return The phone prefix
322      */
323     public String getPhonePrefix() {
324 	return this.phonePrefix;
325     }
326 
327     /**
328      * @return The postal Code Mask (ex : #####)
329      */
330     public String getPostalCodeMask() {
331 	return this.postalCodeMask;
332     }
333 
334     /**
335      * All language spoken in this Country.
336      * 
337      * @see Language
338      * @return the {@link Language} spoken in this Country
339      */
340     @ManyToMany
341     @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
342     public List<Language> getSpokenLanguages() {
343 	return this.spokenLanguages;
344     }
345 
346     /*
347      * (non-Javadoc)
348      * 
349      * @see com.gisgraphy.domain.geoloc.entity.GisFeature#hashCode()
350      */
351     @Override
352     public int hashCode() {
353 	final int PRIME = 31;
354 	int result = super.hashCode();
355 	result = PRIME
356 		* result
357 		+ ((iso3166Alpha2Code == null) ? 0 : iso3166Alpha2Code
358 			.hashCode());
359 	return result;
360     }
361 
362     /**
363      * @see #getArea()
364      * @param area
365      */
366     public void setArea(Double area) {
367 	this.area = area;
368     }
369 
370     /**
371      * Set the currency code for this country
372      * 
373      * @see #getCurrencyCode()
374      * @param currencyCode
375      *                The currencyCode to set
376      */
377     public void setCurrencyCode(String currencyCode) {
378 	this.currencyCode = currencyCode;
379     }
380 
381     /**
382      * @see #getEquivalentFipsCode()
383      * @param equivalentFipsCode
384      */
385     public void setEquivalentFipsCode(String equivalentFipsCode) {
386 	this.equivalentFipsCode = equivalentFipsCode;
387     }
388 
389     /**
390      * @see #getFipsCode()
391      * @param fipsCode
392      *                The fipsCode to set.
393      */
394     public void setFipsCode(String fipsCode) {
395 	this.fipsCode = fipsCode;
396     }
397 
398     /**
399      * Set the iso3166 alpha-2 code. <u>NOTE</u> : The Code will be automaticaly uppercased, and
400      * the gisfeature code will be set automatically
401      * 
402      * @see #getIso3166Alpha2Code()
403      * @param isoCode
404      *                The iso3166 alpha-2 code to set in upper case.
405      */
406     public void setIso3166Alpha2Code(String isoCode) {
407 	if (isoCode != null) {
408 	    this.iso3166Alpha2Code = isoCode.toUpperCase();
409 	} else {
410 	    this.iso3166Alpha2Code = isoCode;
411 	}
412 	setCountryCode(isoCode);
413     }
414 
415     /**
416      * <u>Note</u> : The code will be automaticaly uppercased
417      * 
418      * @see #getIso3166Alpha3Code()
419      * @param iso3166Alpha3Code
420      *                The iso3166Alpha3Code to set (in upper case).
421      */
422     public void setIso3166Alpha3Code(String iso3166Alpha3Code) {
423 	// check if we can apply touppercase method
424 	if (iso3166Alpha3Code != null) {
425 	    this.iso3166Alpha3Code = iso3166Alpha3Code.toUpperCase();
426 	} else {
427 	    this.iso3166Alpha3Code = iso3166Alpha3Code;
428 	}
429     }
430 
431     /**
432      * @see #getIso3166NumericCode()
433      * @param iso3166NumericCode
434      *                The iso 3166 numeric code to set.
435      */
436     public void setIso3166NumericCode(int iso3166NumericCode) {
437 	this.iso3166NumericCode = iso3166NumericCode;
438     }
439 
440     /*
441      * /**
442      * 
443      * @see #getNeighbourCountries() @param neighbourCountries public void
444      *      setNeighbourCountries(List<Country> neighbourCountries) {
445      *      this.neighbourCountries = neighbourCountries; }
446      */
447 
448     /**
449      * @see #getPhonePrefix()
450      * @param phonePrefix
451      */
452     public void setPhonePrefix(String phonePrefix) {
453 	this.phonePrefix = phonePrefix;
454     }
455 
456     /**
457      * @see #getPostalCodeMask()
458      * @param postalCodeMask
459      */
460     public void setPostalCodeMask(String postalCodeMask) {
461 	this.postalCodeMask = postalCodeMask;
462     }
463 
464     /**
465      * @see #getSpokenLanguages()
466      * @param languages
467      */
468     public void setSpokenLanguages(List<Language> languages) {
469 	this.spokenLanguages = languages;
470     }
471 
472     /**
473      * @see #getSpokenLanguages()
474      * @param languages
475      */
476     public void addSpokenLanguages(List<Language> languages) {
477 	this.spokenLanguages.addAll(languages);
478     }
479 
480     /**
481      * Get the capital for this country
482      * 
483      * @return the Capital for this country
484      */
485     public String getCapitalName() {
486 	return capitalName;
487     }
488 
489     /**
490      * @see #getCapitalName()
491      */
492     public void setCapitalName(String capitalName) {
493 	this.capitalName = capitalName;
494     }
495 
496     /**
497      * Returns The name of the continent this country belongs to
498      * 
499      * @return The name of the continent this country belongs to
500      */
501     public String getContinent() {
502 	return continent;
503     }
504 
505     /**
506      * @see #getContinent()
507      */
508     public void setContinent(String continent) {
509 	this.continent = continent;
510     }
511 
512     /**
513      * Returns The name of the currency for this country. The name is not
514      * processed but imported from file.
515      * 
516      * @return The name of the currency
517      */
518     public String getCurrencyName() {
519 	return currencyName;
520     }
521 
522     /**
523      * @see #getCurrencyName()
524      */
525     public void setCurrencyName(String currencyName) {
526 	this.currencyName = currencyName;
527     }
528 
529     /**
530      * Returns The regexp that every Zipcode for this country matches. it is
531      * useful to test if a zipcode is valid. this field is imported from file
532      * and is not tested. Please report any problems.
533      * 
534      * @see #getPostalCodeMask()
535      * @return The regexp that every zipcode for this country matches
536      */
537     public String getPostalCodeRegex() {
538 	return postalCodeRegex;
539     }
540 
541     /**
542      * @see #getPostalCodeRegex()
543      */
544     public void setPostalCodeRegex(String postalCodeRegex) {
545 	this.postalCodeRegex = postalCodeRegex;
546     }
547 
548     /**
549      * Returns the top level domain for this country with the starting point.
550      * (ex : .fr)
551      * 
552      * @see <a href="http://en.wikipedia.org/wiki/Top-level_domain">TLD</a>
553      * @return the TLD for this Country
554      */
555     public String getTld() {
556 	return tld;
557     }
558 
559     /**
560      * @see #getTld()
561      */
562     public void setTld(String tld) {
563 	this.tld = tld;
564     }
565 
566     /**
567      * compare the name of the country
568      */
569     public int compareTo(Country country) {
570 	if (getName() == null) {
571 	    if (country.getName() == null) {
572 	    	return 0;
573 	    } else {
574 	    	return -1;
575 	    }
576 	}
577 	return getName().compareTo(country.getName());
578     }
579 
580 }