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 */ 020package org.apache.directory.api.ldap.model.schema.syntaxCheckers; 021 022 023import java.util.regex.Pattern; 024import java.util.regex.PatternSyntaxException; 025 026import org.apache.directory.api.i18n.I18n; 027import org.apache.directory.api.ldap.model.constants.SchemaConstants; 028import org.apache.directory.api.ldap.model.schema.SyntaxChecker; 029import org.apache.directory.api.util.Strings; 030 031 032/** 033 * A SyntaxChecker which verifies that a value is a TelephoneNumber according to ITU 034 * recommendation E.123 (which is quite vague ...). 035 * <p> 036 * A valid Telephone number respects more or less this syntax : 037 * 038 * <pre> 039 * " *[+]? *((\([0-9- ,;/#*]+\))|[0-9- ,;/#*]+)+" 040 * </pre> 041 * 042 * If needed, and to allow more syntaxes, a list of regexps has been added 043 * which can be initialized to other values 044 * 045 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 046 */ 047@SuppressWarnings("serial") 048public final class TelephoneNumberSyntaxChecker extends SyntaxChecker 049{ 050 /** The default pattern used to check a TelephoneNumber */ 051 private static final String DEFAULT_REGEXP = "^ *[+]? *((\\([0-9- ,;/#*]+\\))|[0-9- ,;/#*]+)+$"; 052 053 /** The default pattern */ 054 private final String defaultRegexp; 055 056 /** The compiled default pattern */ 057 private final Pattern defaultPattern; 058 059 /** 060 * A static instance of TelephoneNumberSyntaxChecker 061 */ 062 public static final TelephoneNumberSyntaxChecker INSTANCE = 063 new TelephoneNumberSyntaxChecker( SchemaConstants.TELEPHONE_NUMBER_SYNTAX ); 064 065 /** 066 * A static Builder for this class 067 */ 068 public static final class Builder extends SCBuilder<TelephoneNumberSyntaxChecker> 069 { 070 /** The default pattern */ 071 private String defaultRegexp; 072 073 /** The compiled default pattern */ 074 private Pattern defaultPattern; 075 076 /** 077 * The Builder constructor 078 */ 079 private Builder() 080 { 081 super( SchemaConstants.TELEPHONE_NUMBER_SYNTAX ); 082 setDefaultRegexp( DEFAULT_REGEXP ); 083 } 084 085 086 /** 087 * Create a new instance of TelephoneNumberSyntaxChecker 088 * @return A new instance of TelephoneNumberSyntaxChecker 089 */ 090 @Override 091 public TelephoneNumberSyntaxChecker build() 092 { 093 return new TelephoneNumberSyntaxChecker( oid, defaultRegexp, defaultPattern ); 094 } 095 096 097 /** 098 * Set the default regular expression for the Telephone number 099 * 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}