001/*
002 *  Licensed to the Apache Software Foundation (ASF) under one
003 *  or more contributor license agreements.  See the NOTICE file
004 *  distributed with this work for additional information
005 *  regarding copyright ownership.  The ASF licenses this file
006 *  to you under the Apache License, Version 2.0 (the
007 *  "License"); you may not use this file except in compliance
008 *  with the License.  You may obtain a copy of the License at
009 *  
010 *    http://www.apache.org/licenses/LICENSE-2.0
011 *  
012 *  Unless required by applicable law or agreed to in writing,
013 *  software distributed under the License is distributed on an
014 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 *  KIND, either express or implied.  See the License for the
016 *  specific language governing permissions and limitations
017 *  under the License. 
018 *  
019 */
020package org.apache.directory.api.ldap.model.schema.syntaxCheckers;
021
022
023import java.util.HashSet;
024import java.util.Set;
025
026import org.apache.directory.api.ldap.model.constants.SchemaConstants;
027import org.apache.directory.api.ldap.model.schema.SyntaxChecker;
028import org.apache.directory.api.util.Strings;
029import org.slf4j.Logger;
030import org.slf4j.LoggerFactory;
031
032
033/**
034 * A SyntaxChecker which verifies that a value is a country according to RFC 4517.
035 * 
036 * From RFC 4517 :
037 * 
038 * A value of the Country String syntax is one of the two-character
039 * codes from ISO 3166 [ISO3166] for representing a country.
040 * 
041 *
042 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
043 */
044@SuppressWarnings("serial")
045public class CountrySyntaxChecker extends SyntaxChecker
046{
047    /** A logger for this class */
048    private static final Logger LOG = LoggerFactory.getLogger( CountrySyntaxChecker.class );
049
050    /** The ISO 3166 list of countries, as of 2006 */
051    private static final String[] COUNTRY_ISO_3166 =
052        {
053            "AD",
054            "AE",
055            "AF",
056            "AG",
057            "AI",
058            "AL",
059            "AM",
060            "AN",
061            "AO",
062            "AQ",
063            "AR",
064            "AS",
065            "AT",
066            "AU",
067            "AW",
068            "AX",
069            "AZ",
070            "BA",
071            "BB",
072            "BD",
073            "BE",
074            "BF",
075            "BG",
076            "BH",
077            "BI",
078            "BJ",
079            "BM",
080            "BN",
081            "BO",
082            "BR",
083            "BS",
084            "BT",
085            "BV",
086            "BW",
087            "BY",
088            "BZ",
089            "CA",
090            "CC",
091            "CD",
092            "CF",
093            "CG",
094            "CH",
095            "CI",
096            "CK",
097            "CL",
098            "CM",
099            "CN",
100            "CO",
101            "CR",
102            "CU",
103            "CV",
104            "CX",
105            "CY",
106            "CZ",
107            "DE",
108            "DJ",
109            "DK",
110            "DM",
111            "DO",
112            "DZ",
113            "EC",
114            "EE",
115            "EG",
116            "EH",
117            "ER",
118            "ES",
119            "ET",
120            "FI",
121            "FJ",
122            "FK",
123            "FM",
124            "FO",
125            "FR",
126            "GA",
127            "GB",
128            "GD",
129            "GE",
130            "GG",
131            "GF",
132            "GH",
133            "GI",
134            "GL",
135            "GM",
136            "GN",
137            "GP",
138            "GQ",
139            "GR",
140            "GS",
141            "GT",
142            "GU",
143            "GW",
144            "GY",
145            "HK",
146            "HM",
147            "HN",
148            "HR",
149            "HT",
150            "HU",
151            "ID",
152            "IE",
153            "IL",
154            "IM",
155            "IN",
156            "IO",
157            "IQ",
158            "IR",
159            "IS",
160            "IT",
161            "JE",
162            "JM",
163            "JO",
164            "JP",
165            "KE",
166            "KG",
167            "KH",
168            "KI",
169            "KM",
170            "KN",
171            "KP",
172            "KR",
173            "KW",
174            "KY",
175            "KZ",
176            "LA",
177            "LB",
178            "LC",
179            "LI",
180            "LK",
181            "LR",
182            "LS",
183            "LT",
184            "LU",
185            "LV",
186            "LY",
187            "MA",
188            "MC",
189            "MD",
190            "ME",
191            "MG",
192            "MH",
193            "MK",
194            "ML",
195            "MM",
196            "MN",
197            "MO",
198            "MP",
199            "MQ",
200            "MR",
201            "MS",
202            "MT",
203            "MU",
204            "MV",
205            "MW",
206            "MX",
207            "MY",
208            "MZ",
209            "NA",
210            "NC",
211            "NE",
212            "NF",
213            "NG",
214            "NI",
215            "NL",
216            "NO",
217            "NP",
218            "NR",
219            "NU",
220            "NZ",
221            "OM",
222            "PA",
223            "PE",
224            "PF",
225            "PG",
226            "PH",
227            "PK",
228            "PL",
229            "PM",
230            "PN",
231            "PR",
232            "PS",
233            "PT",
234            "PW",
235            "PY",
236            "QA",
237            "RE",
238            "RO",
239            "RS",
240            "RU",
241            "RW",
242            "SA",
243            "SB",
244            "SC",
245            "SD",
246            "SE",
247            "SG",
248            "SH",
249            "SI",
250            "SJ",
251            "SK",
252            "SL",
253            "SM",
254            "SN",
255            "SO",
256            "SR",
257            "ST",
258            "SV",
259            "SY",
260            "SZ",
261            "TC",
262            "TD",
263            "TF",
264            "TG",
265            "TH",
266            "TJ",
267            "TK",
268            "TL",
269            "TM",
270            "TN",
271            "TO",
272            "TR",
273            "TT",
274            "TV",
275            "TW",
276            "TZ",
277            "UA",
278            "UG",
279            "UM",
280            "US",
281            "UY",
282            "UZ",
283            "VA",
284            "VC",
285            "VE",
286            "VG",
287            "VI",
288            "VN",
289            "VU",
290            "WF",
291            "WS",
292            "YE",
293            "YT",
294            "ZA",
295            "ZM",
296            "ZW"
297    };
298
299    /** The Set which contains the countries */
300    private static final Set<String> COUNTRIES = new HashSet<String>();
301
302    /** Initialization of the country set */
303    static
304    {
305        for ( String country : COUNTRY_ISO_3166 )
306        {
307            COUNTRIES.add( country );
308        }
309    }
310
311
312    /**
313     * 
314     * Creates a new instance of CountrySyntaxChecker.
315     *
316     */
317    public CountrySyntaxChecker()
318    {
319        super( SchemaConstants.COUNTRY_STRING_SYNTAX );
320    }
321
322
323    /**
324     * {@inheritDoc}
325     */
326    public boolean isValidSyntax( Object value )
327    {
328        String strValue = null;
329
330        if ( value == null )
331        {
332            LOG.debug( "Syntax invalid for 'null'" );
333            return false;
334        }
335
336        if ( value instanceof String )
337        {
338            strValue = ( String ) value;
339        }
340        else if ( value instanceof byte[] )
341        {
342            strValue = Strings.utf8ToString( ( byte[] ) value );
343        }
344        else
345        {
346            strValue = value.toString();
347        }
348
349        if ( strValue.length() == 0 )
350        {
351            LOG.debug( "Syntax invalid for '{}'", value );
352            return false;
353        }
354
355        boolean result = COUNTRIES.contains( Strings.toUpperCase( strValue ) );
356
357        if ( result )
358        {
359            LOG.debug( "Syntax valid for '{}'", value );
360        }
361        else
362        {
363            LOG.debug( "Syntax invalid for '{}'", value );
364        }
365
366        return result;
367    }
368}