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.shared.ldap.model.schema.syntaxCheckers;
021
022
023import java.util.HashSet;
024import java.util.Set;
025
026import org.apache.directory.shared.ldap.model.constants.SchemaConstants;
027import org.apache.directory.shared.ldap.model.schema.SyntaxChecker;
028import org.apache.directory.shared.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", "AE", "AF", "AG", "AI", "AL", "AM", "AN", "AO", "AQ", "AR", "AS", "AT", "AU", "AW", "AX", "AZ",
054        "BA", "BB", "BD", "BE", "BF", "BG", "BH", "BI", "BJ", "BM", "BN", "BO", "BR", "BS", "BT", "BV", "BW", "BY", "BZ",
055        "CA", "CC", "CD", "CF", "CG", "CH", "CI", "CK", "CL", "CM", "CN", "CO", "CR", "CU", "CV", "CX", "CY", "CZ",
056        "DE", "DJ", "DK", "DM", "DO", "DZ",
057        "EC", "EE", "EG", "EH", "ER", "ES", "ET",
058        "FI", "FJ", "FK", "FM", "FO", "FR",
059        "GA", "GB", "GD", "GE", "GG", "GF", "GH", "GI", "GL", "GM", "GN", "GP", "GQ", "GR", "GS", "GT", "GU", "GW", "GY",
060        "HK", "HM", "HN", "HR", "HT", "HU",
061        "ID", "IE", "IL", "IM", "IN", "IO", "IQ", "IR", "IS", "IT",
062        "JE", "JM", "JO", "JP",
063        "KE", "KG", "KH", "KI", "KM", "KN", "KP", "KR", "KW", "KY", "KZ",
064        "LA", "LB", "LC", "LI", "LK", "LR", "LS", "LT", "LU", "LV", "LY",
065        "MA", "MC", "MD", "ME", "MG", "MH", "MK", "ML", "MM", "MN", "MO", "MP", "MQ", "MR", "MS", "MT", "MU", "MV", "MW", "MX", 
066        "MY", "MZ",
067        "NA", "NC", "NE", "NF", "NG", "NI", "NL", "NO", "NP", "NR", "NU", "NZ",
068        "OM",
069        "PA", "PE", "PF", "PG", "PH", "PK", "PL", "PM", "PN", "PR", "PS", "PT", "PW", "PY",
070        "QA",
071        "RE", "RO", "RS", "RU", "RW", 
072        "SA", "SB", "SC", "SD", "SE", "SG", "SH", "SI", "SJ", "SK", "SL", "SM", "SN", "SO", "SR", "ST", "SV", "SY", "SZ",
073        "TC", "TD", "TF", "TG", "TH", "TJ", "TK", "TL", "TM", "TN", "TO", "TR", "TT", "TV", "TW", "TZ",
074        "UA", "UG", "UM", "US", "UY", "UZ",
075        "VA", "VC", "VE", "VG", "VI", "VN", "VU",
076        "WF", "WS",
077        "YE", "YT",
078        "ZA", "ZM", "ZW"
079        };
080    
081    /** The Set which contains the countries */
082    private static final Set<String> COUNTRIES = new HashSet<String>();
083    
084    /** Initialization of the country set */
085    static
086    {
087        for ( String country:COUNTRY_ISO_3166 )
088        {
089            COUNTRIES.add( country );
090        }
091    }
092    
093    /**
094     * 
095     * Creates a new instance of CountrySyntaxChecker.
096     *
097     */
098    public CountrySyntaxChecker()
099    {
100        super( SchemaConstants.COUNTRY_STRING_SYNTAX );
101    }
102    
103    
104    /**
105     * {@inheritDoc}
106     */
107    public boolean isValidSyntax( Object value )
108    {
109        String strValue = null;
110
111        if ( value == null )
112        {
113            LOG.debug( "Syntax invalid for 'null'" );
114            return false;
115        }
116        
117        if ( value instanceof String )
118        {
119            strValue = ( String ) value;
120        }
121        else if ( value instanceof byte[] )
122        {
123            strValue = Strings.utf8ToString((byte[]) value);
124        }
125        else
126        {
127            strValue = value.toString();
128        }
129
130        if ( strValue.length() == 0 )
131        {
132            LOG.debug( "Syntax invalid for '{}'", value );
133            return false;
134        }
135        
136        boolean result = COUNTRIES.contains( Strings.toUpperCase(strValue) );
137        
138        if ( result )
139        {
140            LOG.debug( "Syntax valid for '{}'", value );
141        }
142        else
143        {
144            LOG.debug( "Syntax invalid for '{}'", value );
145        }
146    
147    return result;
148    }
149}