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     */
020    package org.apache.directory.shared.ldap.schema.syntaxes;
021    
022    
023    import java.util.HashSet;
024    import java.util.Set;
025    
026    import org.apache.directory.shared.ldap.constants.SchemaConstants;
027    import org.apache.directory.shared.ldap.util.StringTools;
028    
029    
030    /**
031     * A SyntaxChecker which verifies that a value is a facsimile TelephoneNumber according 
032     * to ITU recommendation E.123 for the Telephone number part, and from RFC 4517, par. 
033     * 3.3.11 :
034     * 
035     * fax-number       = telephone-number *( DOLLAR fax-parameter )
036     * telephone-number = PrintableString
037     * fax-parameter    = "twoDimensional" |
038     *                    "fineResolution" |
039     *                    "unlimitedLength" |
040     *                    "b4Length" |
041     *                    "a3Width" |
042     *                    "b4Width" |
043     *                    "uncompressed"
044     *
045     * 
046     * If needed, and to allow more syntaxes, a list of regexps has been added
047     * which can be initialized to other values
048     * 
049     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
050     * @version $Rev$
051     */
052    public class FacsimileTelephoneNumberSyntaxChecker extends TelephoneNumberSyntaxChecker
053    {
054        /** Fax parameters possible values */
055        private static final String TWO_DIMENSIONAL  = "twoDimensional";
056        private static final String FINE_RESOLUTION  = "fineResolution";
057        private static final String UNLIMITED_LENGTH = "unlimitedLength";
058        private static final String B4_LENGTH        = "b4Length";
059        private static final String A3_LENGTH        = "a3Width";
060        private static final String B4_WIDTH         = "b4Width";
061        private static final String UNCOMPRESSED     = "uncompressed";
062        
063        /** A set which contaons all the possible fax parameters values */
064        private static Set<String> faxParameters = new HashSet<String>();
065        
066        /** Initialization of the fax parameters set of values */
067        static
068        {
069            faxParameters.add( TWO_DIMENSIONAL.toLowerCase() );
070            faxParameters.add( FINE_RESOLUTION.toLowerCase() );
071            faxParameters.add( UNLIMITED_LENGTH.toLowerCase() );
072            faxParameters.add( B4_LENGTH.toLowerCase() );
073            faxParameters.add( A3_LENGTH.toLowerCase() );
074            faxParameters.add( B4_WIDTH.toLowerCase() );
075            faxParameters.add( UNCOMPRESSED.toLowerCase() );
076        }
077        
078        /**
079         * Creates a new instance of TelephoneNumberSyntaxChecker.
080         */
081        public FacsimileTelephoneNumberSyntaxChecker()
082        {
083            super( SchemaConstants.FACSIMILE_TELEPHONE_NUMBER_SYNTAX );
084        }
085    
086    
087        /**
088         * 
089         * Creates a new instance of FacsimileTelephoneNumberSyntaxChecker.
090         * 
091         * @param oid the oid to associate with this new SyntaxChecker
092         *
093         */
094        protected FacsimileTelephoneNumberSyntaxChecker( String oid )
095        {
096            super( oid );
097        }
098        
099        /* (non-Javadoc)
100         * @see org.apache.directory.shared.ldap.schema.SyntaxChecker#isValidSyntax(java.lang.Object)
101         */
102        public boolean isValidSyntax( Object value )
103        {
104            String strValue = null;
105    
106            if ( value == null )
107            {
108                return false;
109            }
110            
111            if ( value instanceof String )
112            {
113                strValue = ( String ) value;
114            }
115            else if ( value instanceof byte[] )
116            {
117                strValue = StringTools.utf8ToString( ( byte[] ) value ); 
118            }
119            else
120            {
121                strValue = value.toString();
122            }
123    
124            if ( strValue.length() == 0 )
125            {
126                return false;
127            }
128            
129            // The facsimile telephone number might be composed
130            // of two parts separated by a '$'.
131            int dollarPos = strValue.indexOf( '$' );
132            
133            if ( dollarPos == -1 )
134            {
135                // We have no fax-parameter : check the Telephone number
136                return super.isValidSyntax( strValue );
137            }
138            
139            // First check the telephone number if the '$' is not at the first position
140            if ( dollarPos > 0 )
141            {
142                if ( !super.isValidSyntax( strValue.substring( 0, dollarPos -1 ) ) )
143                {
144                    return false;
145                }
146                
147                // Now, try to validate the fax-parameters : we may
148                // have more than one, so we will store the seen params
149                // in a set to check that we don't have the same param twice
150                Set<String> paramsSeen = new HashSet<String>(); 
151               
152                while ( dollarPos > 0 )
153                {
154                    String faxParam = null;
155                    int newDollar = strValue.indexOf( '$', dollarPos + 1 );
156    
157                    if ( newDollar == -1 )
158                    {
159                        faxParam = strValue.substring(  dollarPos+1 );
160                    }
161                    else
162                    {
163                        faxParam = strValue.substring(  dollarPos+1, newDollar );
164                    }
165                    
166                    if ( faxParam == null )
167                    {
168                        // Not allowed
169                        return false;
170                    }
171                    
172                    // Relax a little bit the syntax by lowercasing the param
173                    faxParam = faxParam.toLowerCase();
174                    
175                    if ( !faxParameters.contains( faxParam ) )
176                    {
177                        // This parameter is not in the possible set
178                        return false;
179                    }
180                    else if ( paramsSeen.contains( faxParam ) )
181                    {
182                        // We have the same parameters twice...
183                        return false;
184                    } 
185                    else
186                    {
187                        // It's a correct param, let's add it to the seen 
188                        // params.
189                        paramsSeen.add( faxParam );
190                    }
191                    
192                    dollarPos = newDollar;
193                }
194                
195                return true;
196            }
197            
198            // We must have a valid telephone number !
199            return false;
200        }
201    }