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.schema.AbstractSyntaxChecker;
028    import org.apache.directory.shared.ldap.util.StringTools;
029    
030    
031    /**
032     * A SyntaxChecker which verifies that a value is a delivery method 
033     * according to RFC 4517.
034     * 
035     * From RFC 4517 & RFC 4512:
036     * 
037     * DeliveryMethod = pdm *( WSP DOLLAR WSP pdm )
038     *
039     * pdm = "any" | "mhs" | "physical" | "telex" | "teletex" |
040     *       "g3fax" | "g4fax" | "ia5" | "videotex" | "telephone"
041     *           
042     * WSP     = 0*SPACE  ; zero or more " "
043     * DOLLAR  = %x24 ; dollar sign ("$")
044     * SPACE   = %x20 ; space (" ")
045     * 
046     *
047     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
048     * @version $Rev$
049     */
050    public class DeliveryMethodSyntaxChecker extends AbstractSyntaxChecker
051    {
052        private static final String[] PDMS = 
053            {
054                "any", "mhs", "physical", "telex", "teletex",
055                "g3fax", "g4fax", "ia5", "videotex", "telephone"
056            };
057    
058        /** The Set which contains the delivery methods */
059        private static final Set<String> DELIVERY_METHODS = new HashSet<String>();
060        
061        /** Initialization of the delivery methods set */
062        static
063        {
064            for ( String country:PDMS )
065            {
066                DELIVERY_METHODS.add( country );
067            }
068        }
069    
070        
071        /**
072         * 
073         * Creates a new instance of DeliveryMethodSyntaxChecker.
074         *
075         */
076        public DeliveryMethodSyntaxChecker()
077        {
078            super( SchemaConstants.DELIVERY_METHOD_SYNTAX );
079        }
080        
081        /**
082         * 
083         * Creates a new instance of DeliveryMethodSyntaxChecker.
084         * 
085         * @param oid the oid to associate with this new SyntaxChecker
086         *
087         */
088        protected DeliveryMethodSyntaxChecker( String oid )
089        {
090            super( oid );
091        }
092        
093        /**
094         * 
095         * Check if the string contains a delivery method which has 
096         * not already been found.
097         * 
098         * @param strValue The string we want to look into for a PDM 
099         * @param pos The current position in the string
100         * @param pdms The set containing all the PDM
101         * @return if a Prefered Delivery Method is found in the given string, returns 
102         * its position, otherwise, returns -1
103         */
104        private int isPdm( String strValue, int pos, Set<String> pdms )
105        {
106            int start = pos;
107            
108            while ( StringTools.isAlphaDigit( strValue, pos ) )
109            {
110                pos++;
111            }
112            
113            // No ascii string, this is not a delivery method
114            if ( pos == start )
115            {
116                return -1;
117            }
118            
119            String pdm = strValue.substring( start, pos );
120            
121            if ( ! DELIVERY_METHODS.contains( pdm ) )
122            {
123                // The delivery method is unknown
124                return -1;
125            }
126            else
127            {
128                if ( pdms.contains( pdm ) )
129                {
130                    // The delivery method has already been found
131                    return -1;
132                }
133                else
134                {
135                    pdms.add( pdm );
136                    return pos;
137                }
138            }
139        }
140    
141        /* (non-Javadoc)
142         * @see org.apache.directory.shared.ldap.schema.SyntaxChecker#isValidSyntax(java.lang.Object)
143         */
144        public boolean isValidSyntax( Object value )
145        {
146            String strValue = null;
147    
148            if ( value == null )
149            {
150                return false;
151            }
152            
153            if ( value instanceof String )
154            {
155                strValue = ( String ) value;
156            }
157            else if ( value instanceof byte[] )
158            {
159                strValue = StringTools.utf8ToString( ( byte[] ) value ); 
160            }
161            else
162            {
163                strValue = value.toString();
164            }
165    
166            if ( strValue.length() == 0 )
167            {
168                return false;
169            }
170            
171            // We will get the first delivery method
172            int length = strValue.length();
173            int pos = 0;
174            Set<String> pmds = new HashSet<String>();
175                
176            if ( ( pos = isPdm( strValue, pos, pmds ) ) == -1)
177            {
178                return false;
179            }
180            
181            // We have found at least the first pmd,
182            // now iterate through the other ones. We may have
183            // SP* '$' SP* before each pmd.
184            while ( pos < length )
185            {
186                // Skip spaces
187                while ( StringTools.isCharASCII( strValue, pos, ' ' ) )
188                {
189                    pos++;
190                }
191                
192                if ( ! StringTools.isCharASCII( strValue, pos, '$' ) )
193                {
194                    // A '$' was expected
195                    return false;
196                }
197                else
198                {
199                    pos++;
200                }
201                
202                // Skip spaces
203                while ( StringTools.isCharASCII( strValue, pos, ' ' ) )
204                {
205                    pos++;
206                }
207    
208                if ( ( pos = isPdm( strValue, pos, pmds ) ) == -1 )
209                {
210                    return false;
211                }
212            }
213    
214            return true;
215        }
216    }