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   *    http://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 default pattern */
71          private String defaultRegexp;
72  
73          /** The compiled 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          */
102         public Builder setDefaultRegexp( String regexp )
103         {
104             defaultRegexp = regexp;
105             
106             try
107             {
108                 defaultPattern = Pattern.compile( regexp );
109             }
110             catch ( PatternSyntaxException pse )
111             {
112                 // Roll back to the default pattern
113                 defaultPattern = Pattern.compile( DEFAULT_REGEXP );
114             }
115 
116             return this;
117         }
118     }
119 
120     
121     /**
122      * Creates a new instance of a child of this class, with an OID.
123      * 
124      * @param oid the child's OID
125      */
126     private TelephoneNumberSyntaxChecker( String oid )
127     {
128         this( oid, DEFAULT_REGEXP, Pattern.compile( DEFAULT_REGEXP ) );
129     }
130 
131     
132     /**
133      * Creates a new instance of a child of this class, with an OID.
134      * 
135      * @param oid the child's OID
136      * @param defaultRegexp The regexp to use
137      * @param defaultPattern The compiled version of the regexp
138      */
139     private TelephoneNumberSyntaxChecker( String oid, String defaultRegexp, Pattern defaultPattern )
140     {
141         super( oid );
142 
143         this.defaultPattern = defaultPattern;
144         this.defaultRegexp = defaultRegexp;
145     }
146 
147     
148     /**
149      * @return An instance of the Builder for this class
150      */
151     public static Builder builder()
152     {
153         return new Builder();
154     }
155 
156 
157     /**
158      * Get the default regexp (either the original one, or the one that has been set)
159      * 
160      * @return The default regexp
161      */
162     public String getRegexp()
163     {
164         return defaultRegexp;
165     }
166 
167 
168     /**
169      * {@inheritDoc}
170      */
171     @Override
172     public boolean isValidSyntax( Object value )
173     {
174         String strValue;
175 
176         if ( value == null )
177         {
178             if ( LOG.isDebugEnabled() )
179             {
180                 LOG.debug( I18n.err( I18n.ERR_04488_SYNTAX_INVALID, "null" ) );
181             }
182             
183             return false;
184         }
185 
186         if ( value instanceof String )
187         {
188             strValue = ( String ) value;
189         }
190         else if ( value instanceof byte[] )
191         {
192             strValue = Strings.utf8ToString( ( byte[] ) value );
193         }
194         else
195         {
196             strValue = value.toString();
197         }
198 
199         if ( strValue.length() == 0 )
200         {
201             if ( LOG.isDebugEnabled() )
202             {
203                 LOG.debug( I18n.err( I18n.ERR_04488_SYNTAX_INVALID, value ) );
204             }
205             
206             return false;
207         }
208 
209         // We will use a regexp to check the TelephoneNumber.
210         boolean result;
211         
212         // Not sure this is 100% necessary...
213         synchronized ( defaultPattern )
214         {
215             result = defaultPattern.matcher( strValue ).matches();
216         }
217 
218         if ( LOG.isDebugEnabled() )
219         {
220             if ( result )
221             {
222                 LOG.debug( I18n.msg( I18n.MSG_04489_SYNTAX_VALID, value ) );
223             }
224             else
225             {
226                 LOG.debug( I18n.err( I18n.ERR_04488_SYNTAX_INVALID, value ) );
227             }
228         }
229 
230         return result;
231     }
232 }