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