View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *  
10   *    https://www.apache.org/licenses/LICENSE-2.0
11   *  
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License. 
18   *  
19   */
20  package org.apache.directory.api.ldap.model.schema.syntaxCheckers;
21  
22  
23  import java.util.regex.Pattern;
24  import java.util.regex.PatternSyntaxException;
25  
26  import org.apache.directory.api.i18n.I18n;
27  import org.apache.directory.api.ldap.model.constants.SchemaConstants;
28  import org.apache.directory.api.ldap.model.schema.SyntaxChecker;
29  import org.apache.directory.api.util.Strings;
30  
31  
32  /**
33   * A SyntaxChecker which verifies that a value is a TelephoneNumber according to ITU
34   * recommendation E.123 (which is quite vague ...).
35   * <p>
36   * A valid Telephone number respects more or less this syntax :
37   * 
38   * <pre>
39   * " *[+]? *((\([0-9- ,;/#*]+\))|[0-9- ,;/#*]+)+"
40   * </pre>
41   * 
42   * If needed, and to allow more syntaxes, a list of regexps has been added
43   * which can be initialized to other values
44   * 
45   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
46   */
47  @SuppressWarnings("serial")
48  public final class TelephoneNumberSyntaxChecker extends SyntaxChecker
49  {
50      /** The default pattern used to check a TelephoneNumber */
51      private static final String DEFAULT_REGEXP = "^ *[+]? *((\\([0-9- ,;/#*]+\\))|[0-9- ,;/#*]+)+$";
52      
53      /** The default pattern */
54      private final String defaultRegexp;
55  
56      /** The compiled default pattern */
57      private final Pattern defaultPattern;
58  
59      /**
60       * A static instance of TelephoneNumberSyntaxChecker
61       */
62      public static final TelephoneNumberSyntaxChecker INSTANCE = 
63          new TelephoneNumberSyntaxChecker( SchemaConstants.TELEPHONE_NUMBER_SYNTAX );
64      
65      /**
66       * A static Builder for this class
67       */
68      public static final class Builder extends SCBuilder<TelephoneNumberSyntaxChecker>
69      {
70          /** The compiled default pattern */
71          private String defaultRegexp;
72  
73          /** The default pattern */
74          private Pattern defaultPattern;
75  
76          /**
77           * The Builder constructor
78           */
79          private Builder()
80          {
81              super( SchemaConstants.TELEPHONE_NUMBER_SYNTAX );
82              setDefaultRegexp( DEFAULT_REGEXP );
83          }
84          
85          
86          /**
87           * Create a new instance of TelephoneNumberSyntaxChecker
88           * @return A new instance of TelephoneNumberSyntaxChecker
89           */
90          @Override
91          public TelephoneNumberSyntaxChecker build()
92          {
93              return new TelephoneNumberSyntaxChecker( oid, defaultRegexp, defaultPattern );
94          }
95  
96  
97          /**
98           * Set the default regular expression for the Telephone number
99           * 
100          * @param regexp the default regular expression.
101          * @return the TelephonenumberSyntaxChecker Builder instance
102          */
103         public Builder setDefaultRegexp( String regexp )
104         {
105             defaultRegexp = regexp;
106             
107             try
108             {
109                 defaultPattern = Pattern.compile( regexp );
110             }
111             catch ( PatternSyntaxException pse )
112             {
113                 // Roll back to the default pattern
114                 defaultPattern = Pattern.compile( DEFAULT_REGEXP );
115             }
116 
117             return this;
118         }
119     }
120 
121     
122     /**
123      * Creates a new instance of a child of this class, with an OID.
124      * 
125      * @param oid the child's OID
126      */
127     private TelephoneNumberSyntaxChecker( String oid )
128     {
129         this( oid, DEFAULT_REGEXP, Pattern.compile( DEFAULT_REGEXP ) );
130     }
131 
132     
133     /**
134      * Creates a new instance of a child of this class, with an OID.
135      * 
136      * @param oid the child's OID
137      * @param defaultRegexp The regexp to use
138      * @param defaultPattern The compiled version of the regexp
139      */
140     private TelephoneNumberSyntaxChecker( String oid, String defaultRegexp, Pattern defaultPattern )
141     {
142         super( oid );
143         
144         this.defaultPattern = defaultPattern;
145         this.defaultRegexp = defaultRegexp;
146     }
147 
148     
149     /**
150      * @return An instance of the Builder for this class
151      */
152     public static Builder builder()
153     {
154         return new Builder();
155     }
156 
157 
158     /**
159      * Get the default regexp (either the original one, or the one that has been set)
160      * 
161      * @return The default regexp
162      */
163     public String getRegexp()
164     {
165         return defaultRegexp;
166     }
167 
168 
169     /**
170      * {@inheritDoc}
171      */
172     @Override
173     public boolean isValidSyntax( Object value )
174     {
175         String strValue;
176 
177         if ( value == null )
178         {
179             if ( LOG.isDebugEnabled() )
180             {
181                 LOG.debug( I18n.err( I18n.ERR_13210_SYNTAX_INVALID, "null" ) );
182             }
183             
184             return false;
185         }
186 
187         if ( value instanceof String )
188         {
189             strValue = ( String ) value;
190         }
191         else if ( value instanceof byte[] )
192         {
193             strValue = Strings.utf8ToString( ( byte[] ) value );
194         }
195         else
196         {
197             strValue = value.toString();
198         }
199 
200         if ( strValue.length() == 0 )
201         {
202             if ( LOG.isDebugEnabled() )
203             {
204                 LOG.debug( I18n.err( I18n.ERR_13210_SYNTAX_INVALID, value ) );
205             }
206             
207             return false;
208         }
209 
210         // We will use a regexp to check the TelephoneNumber.
211         boolean result;
212         
213         // Not sure this is 100% necessary...
214         synchronized ( defaultPattern )
215         {
216             result = defaultPattern.matcher( strValue ).matches();
217         }
218 
219         if ( LOG.isDebugEnabled() )
220         {
221             if ( result )
222             {
223                 LOG.debug( I18n.msg( I18n.MSG_13701_SYNTAX_VALID, value ) );
224             }
225             else
226             {
227                 LOG.debug( I18n.err( I18n.ERR_13210_SYNTAX_INVALID, value ) );
228             }
229         }
230 
231         return result;
232     }
233 }