001: /* ====================================================================
002: * The Jcorporate Apache Style Software License, Version 1.2 05-07-2002
003: *
004: * Copyright (c) 1995-2002 Jcorporate Ltd. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * 1. Redistributions of source code must retain the above copyright
011: * notice, this list of conditions and the following disclaimer.
012: *
013: * 2. Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in
015: * the documentation and/or other materials provided with the
016: * distribution.
017: *
018: * 3. The end-user documentation included with the redistribution,
019: * if any, must include the following acknowledgment:
020: * "This product includes software developed by Jcorporate Ltd.
021: * (http://www.jcorporate.com/)."
022: * Alternately, this acknowledgment may appear in the software itself,
023: * if and wherever such third-party acknowledgments normally appear.
024: *
025: * 4. "Jcorporate" and product names such as "Expresso" must
026: * not be used to endorse or promote products derived from this
027: * software without prior written permission. For written permission,
028: * please contact info@jcorporate.com.
029: *
030: * 5. Products derived from this software may not be called "Expresso",
031: * or other Jcorporate product names; nor may "Expresso" or other
032: * Jcorporate product names appear in their name, without prior
033: * written permission of Jcorporate Ltd.
034: *
035: * 6. No product derived from this software may compete in the same
036: * market space, i.e. framework, without prior written permission
037: * of Jcorporate Ltd. For written permission, please contact
038: * partners@jcorporate.com.
039: *
040: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
041: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
042: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
043: * DISCLAIMED. IN NO EVENT SHALL JCORPORATE LTD OR ITS CONTRIBUTORS
044: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
045: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
046: * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
047: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
048: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
049: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
050: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
051: * SUCH DAMAGE.
052: * ====================================================================
053: *
054: * This software consists of voluntary contributions made by many
055: * individuals on behalf of the Jcorporate Ltd. Contributions back
056: * to the project(s) are encouraged when you make modifications.
057: * Please send them to support@jcorporate.com. For more information
058: * on Jcorporate Ltd. and its products, please see
059: * <http://www.jcorporate.com/>.
060: *
061: * Portions of this software are based upon other open source
062: * products and are subject to their respective licenses.
063: */
064:
065: package com.jcorporate.expresso.ext.dbobj;
066:
067: import com.jcorporate.expresso.core.db.DBConnection;
068: import com.jcorporate.expresso.core.db.DBException;
069: import com.jcorporate.expresso.core.dbobj.DBField;
070: import com.jcorporate.expresso.core.dbobj.RequestContext;
071: import com.jcorporate.expresso.core.dbobj.SecuredDBObject;
072: import com.jcorporate.expresso.core.misc.StringUtil;
073: import org.apache.oro.text.regex.MalformedPatternException;
074: import org.apache.oro.text.regex.Pattern;
075: import org.apache.oro.text.regex.PatternCompiler;
076: import org.apache.oro.text.regex.PatternMatcher;
077: import org.apache.oro.text.regex.Perl5Compiler;
078: import org.apache.oro.text.regex.Perl5Matcher;
079: import org.apache.oro.util.Cache;
080: import org.apache.oro.util.CacheLRU;
081:
082: import java.lang.ref.Reference;
083: import java.lang.ref.WeakReference;
084: import java.util.Vector;
085:
086: /**
087: * This database table contains a list of all known ISO 3166-1 country codes.
088: * See www.iso.org/iso/en/prods-services/iso3166ma/02iso-3166-code-lists/index.html
089: * for the source of this data.
090: * <p/>
091: * This is highly useful for registration data. Allow a person to choose from a
092: * dropdown box. Also can check postal code against known regular expressions
093: * depending on the iso country code associated with the registration.
094: *
095: * @author Michael Rimov
096: * @since Expresso 5.0
097: */
098: public class ISOCountryCodes extends SecuredDBObject {
099: public static final String FLD_ISOCODE = "ISOCode";
100: public static final String FLD_COUNTRY = "Country";
101: public static final String FLD_POSTALREGEXP = "PostalRegExp";
102: public static final String TABLE = "ISOCOUNTRYCODES";
103:
104: /**
105: * Used to hold compiled regular expressions in an attempt to speed
106: * up pattern matching.
107: */
108: protected static Cache regExpCache = new CacheLRU();
109:
110: /**
111: * Used for regular expression compilation
112: */
113: protected static PatternCompiler compiler = new Perl5Compiler();
114:
115: /**
116: * Used to match compiled patterns against strings
117: */
118: protected static PatternMatcher matcher = new Perl5Matcher();
119:
120: /**
121: * Constructor
122: */
123: public ISOCountryCodes() throws DBException {
124: super ();
125: } /* User() */
126:
127: /**
128: * Constructor
129: *
130: * @param myConnection The DBConnection to use Locally
131: */
132: public ISOCountryCodes(DBConnection myConnection)
133: throws DBException {
134: super (myConnection);
135: } /* User(String) */
136:
137: /**
138: * Use over (String) constructor. Initializes the object in the context
139: * of the user who's uid belongs to the parameter.
140: *
141: * @param uid the Uid of the user context
142: * @throws DBException if there's an initialization problem
143: */
144: public ISOCountryCodes(int uid) throws DBException {
145: super (uid);
146: }
147:
148: /**
149: * For using DBObjects within Controllers. Initializes based upon the current
150: * user and the requested db. [Of course this can be modified later]
151: *
152: * @param request - The controller request handed to you by the framework.
153: * @throws DBException if there's an initialization problem
154: */
155: public ISOCountryCodes(RequestContext request) throws DBException {
156: super (request);
157: }
158:
159: /**
160: * This function populates the table with the current listing of ISO country codes
161: *
162: * @throws DBException if an error occurs while populating the table.
163: * @see com.jcorporate.expresso.core.dbobj.DBObject#populateDefaultValues
164: */
165: public synchronized void populateDefaultValues() throws DBException {
166: int i;
167: String[][] localCodes = getCountryCodes();
168: int len = localCodes.length;
169:
170: for (i = 0; i < len; i++) {
171: this .clear();
172: this .setField(FLD_ISOCODE, localCodes[i][1]);
173:
174: if (!this .find()) {
175: setField(FLD_COUNTRY, localCodes[i][0]);
176: this .add();
177: }
178: }
179: } /* populateDefaultValues() */
180:
181: /**
182: * Useful method for unit testing to make sure that everything got added during
183: * setup as expected.
184: *
185: * @return the length of what's expected to be in the table
186: */
187: public int getExpectedDefaultPopulation() {
188: String[][] countryCodes = getCountryCodes();
189: return countryCodes.length;
190: }
191:
192: /**
193: * @return Vector of ValidValue Value/Description pairs for ISO Country Codes
194: * @throws DBException If the values cannot be retrieved
195: */
196: public Vector getValues() throws DBException {
197: return getValuesDefault(FLD_ISOCODE, FLD_COUNTRY);
198: } /* getValues() */
199:
200: /**
201: * Checks a postal code for proper formatting The iso country definition
202: * should already have been retrieved.
203: *
204: * @param testPostalCode the postalCode to check
205: * @return true if the postal code existed for this country
206: * @throws DBException if the test code didn't match the regular expression
207: * stored in the database OR if the regular expression in the database
208: * is syntactically invalid
209: */
210: public boolean checkPostalCode(String testPostalCode)
211: throws DBException {
212: String regExp = StringUtil.notNull(this
213: .getField(FLD_POSTALREGEXP));
214:
215: if (regExp.length() == 0) {
216: return false;
217: }
218:
219: Pattern compiledRegExp = getPattern(regExp);
220:
221: synchronized (matcher) {
222: if (!matcher.matches(testPostalCode, compiledRegExp)) {
223: throw new DBException(
224: "You've entered an invalid postal code");
225: }
226: }
227:
228: return true;
229: }
230:
231: /**
232: * Get's the regular expression patter to match against.
233: *
234: * @param postalCodePattern the postalCode pattern to check
235: * @return ORO Compiled Regular Expression Pattern
236: * @throws DBException if the mattern match is bad.
237: */
238: private synchronized Pattern getPattern(String postalCodePattern)
239: throws DBException {
240: Pattern p = (Pattern) regExpCache.getElement(postalCodePattern);
241:
242: if (p == null) {
243: try {
244: p = compiler.compile(postalCodePattern,
245: Perl5Compiler.READ_ONLY_MASK);
246: regExpCache.addElement(postalCodePattern, p);
247: } catch (MalformedPatternException mpe) {
248: throw new DBException(this .getClass().getName()
249: + "getPattern(String)", mpe);
250: }
251: }
252:
253: return p;
254: }
255:
256: /**
257: * @throws DBException
258: */
259: protected void setupFields() throws DBException {
260: setTargetTable(TABLE);
261: setDescription("ISO Country Codes");
262: setCharset("ISO-8859-1");
263: addField(FLD_ISOCODE, DBField.VARCHAR_TYPE, 10, false,
264: "ISO Country Code");
265: addField(FLD_COUNTRY, DBField.VARCHAR_TYPE, 128, false,
266: "Country Name");
267: addField(FLD_POSTALREGEXP, DBField.VARCHAR_TYPE, 128, true,
268: "Postal Code Valid Regular Expression");
269: setStringFilter(FLD_ISOCODE, "stripFilter");
270: setStringFilter(FLD_COUNTRY, "rawFilter");
271: addKey(FLD_ISOCODE);
272: setReadOnly(FLD_ISOCODE);
273: addIndex("CountryNames", FLD_COUNTRY, true);
274: } /* setupFields() */
275:
276: protected synchronized static String[][] getCountryCodes() {
277: synchronized (countryCodeLock) {
278: if (countryCodes == null || countryCodes.get() == null) {
279: countryCodes = new WeakReference(
280: new String[][] {
281: { "United States", "US", "" },
282: { "Afghanistan", "AF", "" },
283: { "Aland Islands", "AX", "" },
284: { "Albania", "AL", "" },
285: { "Algeria", "DZ", "" },
286: { "American Samoa", "AS", "" },
287: { "Andorra", "AD", "" },
288: { "Angola", "AO", "" },
289: { "Anguilla", "AI", "" },
290: { "Antarctica", "AQ", "" },
291: { "Antigua And Barbuda", "AG", "" },
292: { "Argentina", "AR", "" },
293: { "Armenia", "AM", "" },
294: { "Aruba", "AW", "" },
295: { "Australia", "AU", "" },
296: { "Austria", "AT", "" },
297: { "Azerbaijan", "AZ", "" },
298: { "Bahamas", "BS", "" },
299: { "Bahrain", "BH", "" },
300: { "Bangladesh", "BD", "" },
301: { "Barbados", "BB", "" },
302: { "Belarus", "BY", "" },
303: { "Belgium", "BE", "" },
304: { "Belize", "BZ", "" },
305: { "Benin", "BJ", "" },
306: { "Bermuda", "BM", "" },
307: { "Bhutan", "BT", "" },
308: { "Bolivia", "BO", "" },
309: { "Bosnia And Herzegovina", "BA", "" },
310: { "Botswana", "BW", "" },
311: { "Bouvet Island", "BV", "" },
312: { "Brazil", "BR", "" },
313: { "British Indian Ocean Territory",
314: "IO", "" },
315: { "Brunei Darussalam", "BN", "" },
316: { "Bulgaria", "BG", "" },
317: { "Burkina Faso", "BF", "" },
318: { "Burundi", "BI", "" },
319: { "Cambodia", "KH", "" },
320: { "Cameroon", "CM", "" },
321: { "Canada", "CA", "" },
322: { "Cape Verde", "CV", "" },
323: { "Cayman Islands", "KY", "" },
324: { "Central African Republic", "CF", "" },
325: { "Chad", "TD", "" },
326: { "Chile", "CL", "" },
327: { "China", "CN", "" },
328: { "Christmas Island", "CX", "" },
329: { "Cocos (Keeling) Islands", "CC", "" },
330: { "Colombia", "CO", "" },
331: { "Comoros", "KM", "" },
332: { "Congo", "CG", "" },
333: {
334: "Congo, The Democratic Republic Of The",
335: "CD", "" },
336: { "Cook Islands", "CK", "" },
337: { "Costa Rica", "CR", "" },
338: { "Cote D'Ivoire", "CI", "" },
339: { "Croatia", "HR", "" },
340: { "Cuba", "CU", "" },
341: { "Cyprus", "CY", "" },
342: { "Czech Republic", "CZ", "" },
343: { "Denmark", "DK", "" },
344: { "Djibouti", "DJ", "" },
345: { "Dominica", "DM", "" },
346: { "Dominican Republic", "DO", "" },
347: { "Ecuador", "EC", "" },
348: { "Egypt", "EG", "" },
349: { "El Salvador", "SV", "" },
350: { "Equatorial Guinea", "GQ", "" },
351: { "Eritrea", "ER", "" },
352: { "Estonia", "EE", "" },
353: { "Ethiopia", "ET", "" },
354: { "Falkland Islands", "FK", "" },
355: { "Faroe Islands", "FO", "" },
356: { "Fiji", "FJ", "" },
357: { "Finland", "FI", "" },
358: { "France", "FR", "" },
359: { "French Guiana", "GF", "" },
360: { "French Polynesia", "PF", "" },
361: { "French Southern Territories", "TF",
362: "" },
363: { "Gabon", "GA", "" },
364: { "Gambia", "GM", "" },
365: { "Georgia", "GE", "" },
366: { "Germany", "DE", "" },
367: { "Ghana", "GH", "" },
368: { "Gibraltar", "GI", "" },
369: { "Greece", "GR", "" },
370: { "Greenland", "GL", "" },
371: { "Grenada", "GD", "" },
372: { "Guadeloupe", "GP", "" },
373: { "Guam", "GU", "" },
374: { "Guatemala", "GT", "" },
375: { "Guinea", "GN", "" },
376: { "Guinea-bissau", "GW", "" },
377: { "Guyana", "GY", "" },
378: { "Haiti", "HT", "" },
379: { "Heard Island And Mcdonald Islands",
380: "HM", "" },
381: { "Holy See (Vatican City State)",
382: "VA", "" },
383: { "Honduras", "HN", "" },
384: { "Hong Kong", "HK", "" },
385: { "Hungary", "HU", "" },
386: { "Iceland", "IS", "" },
387: { "India", "IN", "" },
388: { "Indonesia", "ID", "" },
389: { "Iran", "IR", "" },
390: { "Iraq", "IQ", "" },
391: { "Ireland", "IE", "" },
392: { "Israel", "IL", "" },
393: { "Italy", "IT", "" },
394: { "Jamaica", "JM", "" },
395: { "Japan", "JP", "" },
396: { "Jordan", "JO", "" },
397: { "Kazakhstan", "KZ", "" },
398: { "Kenya", "KE", "" },
399: { "Kiribati", "KI", "" },
400: { "North Korea", "KP", "" },
401: { "South Korea", "KR", "" },
402: { "Kuwait", "KW", "" },
403: { "Kyrgyzstan", "KG", "" },
404: { "Lao People's Democratic Republic",
405: "LA", "" },
406: { "Latvia", "LV", "" },
407: { "Lebanon", "LB", "" },
408: { "Lesotho", "LS", "" },
409: { "Liberia", "LR", "" },
410: { "Libyan Arab Jamahiriya", "LY", "" },
411: { "Liechtenstein", "LI", "" },
412: { "Lithuania", "LT", "" },
413: { "Luxembourg", "LU", "" },
414: { "Macao", "MO", "" },
415: { "Macedonia", "MK", "" },
416: { "Madagascar", "MG", "" },
417: { "Malawi", "MW", "" },
418: { "Malaysia", "MY", "" },
419: { "Maldives", "MV", "" },
420: { "Mali", "ML", "" },
421: { "Malta", "MT", "" },
422: { "Marshall Islands", "MH", "" },
423: { "Martinique", "MQ", "" },
424: { "Mauritania", "MR", "" },
425: { "Mauritius", "MU", "" },
426: { "Mayotte", "YT", "" },
427: { "Mexico", "MX", "" },
428: { "Micronesia", "FM", "" },
429: { "Moldova", "MD", "" },
430: { "Monaco", "MC", "" },
431: { "Mongolia", "MN", "" },
432: { "Montserrat", "MS", "" },
433: { "Morocco", "MA", "" },
434: { "Mozambique", "MZ", "" },
435: { "Myanmar", "MM", "" },
436: { "Namibia", "NA", "" },
437: { "Nauru", "NR", "" },
438: { "Nepal", "NP", "" },
439: { "Netherlands", "NL", "" },
440: { "Netherlands Antilles", "AN", "" },
441: { "New Caledonia", "NC", "" },
442: { "New Zealand", "NZ", "" },
443: { "Nicaragua", "NI", "" },
444: { "Niger", "NE", "" },
445: { "Nigeria", "NG", "" },
446: { "Niue", "NU", "" },
447: { "Norfolk Island", "NF", "" },
448: { "Northern Mariana Islands", "MP", "" },
449: { "Norway", "NO", "" },
450: { "Oman", "OM", "" },
451: { "Pakistan", "PK", "" },
452: { "Palau", "PW", "" },
453: { "Palestinian Territory", "PS", "" },
454: { "Panama", "PA", "" },
455: { "Papua New Guinea", "PG", "" },
456: { "Paraguay", "PY", "" },
457: { "Peru", "PE", "" },
458: { "Philippines", "PH", "" },
459: { "Pitcairn", "PN", "" },
460: { "Poland", "PL", "" },
461: { "Portugal", "PT", "" },
462: { "Puerto Rico", "PR", "" },
463: { "Qatar", "QA", "" },
464: { "Reunion", "RE", "" },
465: { "Romania", "RO", "" },
466: { "Russian Federation", "RU", "" },
467: { "Rwanda", "RW", "" },
468: { "Saint Helena", "SH", "" },
469: { "Saint Kitts And Nevis", "KN", "" },
470: { "Saint Lucia", "LC", "" },
471: { "Saint Pierre And Miquelon", "PM", "" },
472: { "Saint Vincent And The Grenadines",
473: "VC", "" },
474: { "Samoa", "WS", "" },
475: { "San Marino", "SM", "" },
476: { "Sao Tome And Principe", "ST", "" },
477: { "Saudi Arabia", "SA", "" },
478: { "Senegal", "SN", "" },
479: { "Serbia And Montenegro", "CS", "" },
480: { "Seychelles", "SC", "" },
481: { "Sierra Leone", "SL", "" },
482: { "Singapore", "SG", "" },
483: { "Slovakia", "SK", "" },
484: { "Slovenia", "SI", "" },
485: { "Solomon Islands", "SB", "" },
486: { "Somalia", "SO", "" },
487: { "South Africa", "ZA", "" },
488: {
489: "South Georgia And The South Sandwich Islands",
490: "GS", "" },
491: { "Spain", "ES", "" },
492: { "Sri Lanka", "LK", "" },
493: { "Sudan", "SD", "" },
494: { "Suriname", "SR", "" },
495: { "Svalbard And Jan Mayen", "SJ", "" },
496: { "Swaziland", "SZ", "" },
497: { "Sweden", "SE", "" },
498: { "Switzerland", "CH", "" },
499: { "Syrian Arab Republic", "SY", "" },
500: { "Taiwan", "TW", "" },
501: { "Tajikistan", "TJ", "" },
502: { "Tanzania", "TZ", "" },
503: { "Thailand", "TH", "" },
504: { "Timor-Leste", "TL", "" },
505: { "Togo", "TG", "" },
506: { "Tokelau", "TK", "" },
507: { "Tonga", "TO", "" },
508: { "Trinidad And Tobago", "TT", "" },
509: { "Tunisia", "TN", "" },
510: { "Turkey", "TR", "" },
511: { "Turkmenistan", "TM", "" },
512: { "Turks And Caicos Islands", "TC", "" },
513: { "Tuvalu", "TV", "" },
514: { "Uganda", "UG", "" },
515: { "Ukraine", "UA", "" },
516: { "United Arab Emirates", "AE", "" },
517: { "United Kingdom", "GB", "" },
518: {
519: "United States Minor Outlying Islands",
520: "UM", "" },
521: { "Uruguay", "UY", "" },
522: { "Uzbekistan", "UZ", "" },
523: { "Vanuatu", "VU", "" },
524: { "Venezuela", "VE", "" },
525: { "Viet Nam", "VN", "" },
526: { "Virgin Islands, British", "VG", "" },
527: { "Virgin Islands, U.S.", "VI", "" },
528: { "Wallis And Futuna", "WF", "" },
529: { "Western Sahara", "EH", "" },
530: { "Yemen", "YE", "" },
531: { "Zambia", "ZM", "" },
532: { "Zimbabwe", "ZW", "" } });
533: }
534:
535: return (String[][]) countryCodes.get();
536: }
537: }
538:
539: protected static Reference countryCodes = null;
540: protected static Object countryCodeLock = new Object();
541:
542: }
|