001 /* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at 010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE 011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE. 012 * See the License for the specific language governing permissions 013 * and limitations under the License. 014 * 015 * When distributing Covered Code, include this CDDL HEADER in each 016 * file and include the License file at 017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, 018 * add the following below this CDDL HEADER, with the fields enclosed 019 * by brackets "[]" replaced with your own identifying information: 020 * Portions Copyright [yyyy] [name of copyright owner] 021 * 022 * CDDL HEADER END 023 * 024 * 025 * Copyright 2006-2008 Sun Microsystems, Inc. 026 */ 027 package org.opends.server.schema; 028 029 030 031 import java.util.HashSet; 032 033 import org.opends.server.admin.std.server.AttributeSyntaxCfg; 034 import org.opends.server.api.ApproximateMatchingRule; 035 import org.opends.server.api.AttributeSyntax; 036 import org.opends.server.api.EqualityMatchingRule; 037 import org.opends.server.api.OrderingMatchingRule; 038 import org.opends.server.api.SubstringMatchingRule; 039 import org.opends.server.config.ConfigException; 040 import org.opends.server.core.DirectoryServer; 041 import org.opends.server.types.ByteString; 042 043 044 045 import static org.opends.server.loggers.ErrorLogger.*; 046 import static org.opends.messages.SchemaMessages.*; 047 import org.opends.messages.MessageBuilder; 048 import static org.opends.server.schema.SchemaConstants.*; 049 import static org.opends.server.util.StaticUtils.*; 050 051 052 053 /** 054 * This class implements the facsimile telephone number attribute syntax, which 055 * contains a printable string (the number) followed by zero or more parameters. 056 * Those parameters should start with a dollar sign may be any of the following 057 * strings: 058 * <UL> 059 * <LI>twoDimensional</LI> 060 * <LI>fineResolution</LI> 061 * <LI>unlimitedLength</LI> 062 * <LI>b4Length</LI> 063 * <LI>a3Width</LI> 064 * <LI>b4Width</LI> 065 * <LI>uncompressed</LI> 066 * </UL> 067 */ 068 public class FaxNumberSyntax 069 extends AttributeSyntax<AttributeSyntaxCfg> 070 { 071 /** 072 * The set of allowed fax parameter values, formatted entirely in lowercase 073 * characters. 074 */ 075 public static final HashSet<String> ALLOWED_FAX_PARAMETERS = 076 new HashSet<String>(7); 077 078 static 079 { 080 ALLOWED_FAX_PARAMETERS.add("twodimensional"); 081 ALLOWED_FAX_PARAMETERS.add("fineresolution"); 082 ALLOWED_FAX_PARAMETERS.add("unlimitedlength"); 083 ALLOWED_FAX_PARAMETERS.add("b4length"); 084 ALLOWED_FAX_PARAMETERS.add("a3width"); 085 ALLOWED_FAX_PARAMETERS.add("b4width"); 086 ALLOWED_FAX_PARAMETERS.add("uncompressed"); 087 } 088 089 090 091 // The default equality matching rule for this syntax. 092 private EqualityMatchingRule defaultEqualityMatchingRule; 093 094 // The default ordering matching rule for this syntax. 095 private OrderingMatchingRule defaultOrderingMatchingRule; 096 097 // The default substring matching rule for this syntax. 098 private SubstringMatchingRule defaultSubstringMatchingRule; 099 100 101 102 /** 103 * Creates a new instance of this syntax. Note that the only thing that 104 * should be done here is to invoke the default constructor for the 105 * superclass. All initialization should be performed in the 106 * <CODE>initializeSyntax</CODE> method. 107 */ 108 public FaxNumberSyntax() 109 { 110 super(); 111 } 112 113 114 115 /** 116 * {@inheritDoc} 117 */ 118 public void initializeSyntax(AttributeSyntaxCfg configuration) 119 throws ConfigException 120 { 121 defaultEqualityMatchingRule = 122 DirectoryServer.getEqualityMatchingRule(EMR_CASE_IGNORE_OID); 123 if (defaultEqualityMatchingRule == null) 124 { 125 logError(ERR_ATTR_SYNTAX_UNKNOWN_EQUALITY_MATCHING_RULE.get( 126 EMR_CASE_IGNORE_OID, SYNTAX_FAXNUMBER_NAME)); 127 } 128 129 defaultOrderingMatchingRule = 130 DirectoryServer.getOrderingMatchingRule(OMR_CASE_IGNORE_OID); 131 if (defaultOrderingMatchingRule == null) 132 { 133 logError(ERR_ATTR_SYNTAX_UNKNOWN_ORDERING_MATCHING_RULE.get( 134 OMR_CASE_IGNORE_OID, SYNTAX_FAXNUMBER_NAME)); 135 } 136 137 defaultSubstringMatchingRule = 138 DirectoryServer.getSubstringMatchingRule(SMR_CASE_IGNORE_OID); 139 if (defaultSubstringMatchingRule == null) 140 { 141 logError(ERR_ATTR_SYNTAX_UNKNOWN_SUBSTRING_MATCHING_RULE.get( 142 SMR_CASE_IGNORE_OID, SYNTAX_FAXNUMBER_NAME)); 143 } 144 } 145 146 147 148 /** 149 * Retrieves the common name for this attribute syntax. 150 * 151 * @return The common name for this attribute syntax. 152 */ 153 public String getSyntaxName() 154 { 155 return SYNTAX_FAXNUMBER_NAME; 156 } 157 158 159 160 /** 161 * Retrieves the OID for this attribute syntax. 162 * 163 * @return The OID for this attribute syntax. 164 */ 165 public String getOID() 166 { 167 return SYNTAX_FAXNUMBER_OID; 168 } 169 170 171 172 /** 173 * Retrieves a description for this attribute syntax. 174 * 175 * @return A description for this attribute syntax. 176 */ 177 public String getDescription() 178 { 179 return SYNTAX_FAXNUMBER_DESCRIPTION; 180 } 181 182 183 184 /** 185 * Retrieves the default equality matching rule that will be used for 186 * attributes with this syntax. 187 * 188 * @return The default equality matching rule that will be used for 189 * attributes with this syntax, or <CODE>null</CODE> if equality 190 * matches will not be allowed for this type by default. 191 */ 192 public EqualityMatchingRule getEqualityMatchingRule() 193 { 194 return defaultEqualityMatchingRule; 195 } 196 197 198 199 /** 200 * Retrieves the default ordering matching rule that will be used for 201 * attributes with this syntax. 202 * 203 * @return The default ordering matching rule that will be used for 204 * attributes with this syntax, or <CODE>null</CODE> if ordering 205 * matches will not be allowed for this type by default. 206 */ 207 public OrderingMatchingRule getOrderingMatchingRule() 208 { 209 return defaultOrderingMatchingRule; 210 } 211 212 213 214 /** 215 * Retrieves the default substring matching rule that will be used for 216 * attributes with this syntax. 217 * 218 * @return The default substring matching rule that will be used for 219 * attributes with this syntax, or <CODE>null</CODE> if substring 220 * matches will not be allowed for this type by default. 221 */ 222 public SubstringMatchingRule getSubstringMatchingRule() 223 { 224 return defaultSubstringMatchingRule; 225 } 226 227 228 229 /** 230 * Retrieves the default approximate matching rule that will be used for 231 * attributes with this syntax. 232 * 233 * @return The default approximate matching rule that will be used for 234 * attributes with this syntax, or <CODE>null</CODE> if approximate 235 * matches will not be allowed for this type by default. 236 */ 237 public ApproximateMatchingRule getApproximateMatchingRule() 238 { 239 // There is no approximate matching rule by default. 240 return null; 241 } 242 243 244 245 /** 246 * Indicates whether the provided value is acceptable for use in an attribute 247 * with this syntax. If it is not, then the reason may be appended to the 248 * provided buffer. 249 * 250 * @param value The value for which to make the determination. 251 * @param invalidReason The buffer to which the invalid reason should be 252 * appended. 253 * 254 * @return <CODE>true</CODE> if the provided value is acceptable for use with 255 * this syntax, or <CODE>false</CODE> if not. 256 */ 257 public boolean valueIsAcceptable(ByteString value, 258 MessageBuilder invalidReason) 259 { 260 // Get a lowercase string representation of the value and find its length. 261 String valueString = toLowerCase(value.stringValue()); 262 int valueLength = valueString.length(); 263 264 265 // The value must contain at least one character. 266 if (valueLength == 0) 267 { 268 269 invalidReason.append(ERR_ATTR_SYNTAX_FAXNUMBER_EMPTY.get()); 270 return false; 271 } 272 273 274 // The first character must be a printable string character. 275 char c = valueString.charAt(0); 276 if (! PrintableString.isPrintableCharacter(c)) 277 { 278 279 invalidReason.append(ERR_ATTR_SYNTAX_FAXNUMBER_NOT_PRINTABLE.get( 280 valueString, String.valueOf(c), 0)); 281 return false; 282 } 283 284 285 // Continue reading until we find a dollar sign or the end of the string. 286 // Every intermediate character must be a printable string character. 287 int pos = 1; 288 for ( ; pos < valueLength; pos++) 289 { 290 c = valueString.charAt(pos); 291 if (c == '$') 292 { 293 pos++; 294 break; 295 } 296 else 297 { 298 if (! PrintableString.isPrintableCharacter(c)) 299 { 300 301 invalidReason.append(ERR_ATTR_SYNTAX_FAXNUMBER_NOT_PRINTABLE.get( 302 valueString, String.valueOf(c), pos)); 303 } 304 } 305 } 306 307 if (pos >= valueLength) 308 { 309 // We're at the end of the value, so it must be valid unless the last 310 // character was a dollar sign. 311 if (c == '$') 312 { 313 314 invalidReason.append(ERR_ATTR_SYNTAX_FAXNUMBER_END_WITH_DOLLAR.get( 315 valueString)); 316 return false; 317 } 318 else 319 { 320 return true; 321 } 322 } 323 324 325 // Continue reading until we find the end of the string. Each substring 326 // must be a valid fax parameter. 327 int paramStartPos = pos; 328 while (pos < valueLength) 329 { 330 c = valueString.charAt(pos++); 331 if (c == '$') 332 { 333 String paramStr = valueString.substring(paramStartPos, pos); 334 if (! ALLOWED_FAX_PARAMETERS.contains(paramStr)) 335 { 336 337 invalidReason.append(ERR_ATTR_SYNTAX_FAXNUMBER_ILLEGAL_PARAMETER.get( 338 valueString, paramStr, paramStartPos, (pos-1))); 339 return false; 340 } 341 342 paramStartPos = pos; 343 } 344 } 345 346 347 // We must be at the end of the value. Read the last parameter and make 348 // sure it is valid. 349 String paramStr = valueString.substring(paramStartPos); 350 if (! ALLOWED_FAX_PARAMETERS.contains(paramStr)) 351 { 352 invalidReason.append(ERR_ATTR_SYNTAX_FAXNUMBER_ILLEGAL_PARAMETER.get( 353 valueString, paramStr, paramStartPos, (pos-1))); 354 return false; 355 } 356 357 358 // If we've gotten here, then the value must be valid. 359 return true; 360 } 361 } 362