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 * https://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 compiled default pattern */ 071 private String defaultRegexp; 072 073 /** The 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 * @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}