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 import org.opends.messages.Message; 029 030 031 032 import org.opends.server.admin.std.server.AttributeSyntaxCfg; 033 import org.opends.server.api.ApproximateMatchingRule; 034 import org.opends.server.api.AttributeSyntax; 035 import org.opends.server.api.AttributeValueDecoder; 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.AttributeValue; 042 import org.opends.server.types.ByteString; 043 import org.opends.server.types.DirectoryException; 044 045 046 import org.opends.server.types.ResultCode; 047 048 import static org.opends.server.loggers.ErrorLogger.*; 049 import static org.opends.messages.SchemaMessages.*; 050 import org.opends.messages.MessageBuilder; 051 import static org.opends.server.schema.SchemaConstants.*; 052 053 054 /** 055 * This class defines the integer attribute syntax, which holds an 056 * arbitrarily-long integer value. Equality, ordering, and substring matching 057 * will be allowed by default. 058 */ 059 public class IntegerSyntax 060 extends AttributeSyntax<AttributeSyntaxCfg> 061 { 062 // The default equality matching rule for this syntax. 063 private EqualityMatchingRule defaultEqualityMatchingRule; 064 065 // The default ordering matching rule for this syntax. 066 private OrderingMatchingRule defaultOrderingMatchingRule; 067 068 // The default substring matching rule for this syntax. 069 private SubstringMatchingRule defaultSubstringMatchingRule; 070 071 072 073 /** 074 * An {@link Integer} attribute value decoder for this syntax. 075 */ 076 public static final AttributeValueDecoder<Integer> DECODER = 077 new AttributeValueDecoder<Integer>() 078 { 079 /** 080 * {@inheritDoc} 081 */ 082 public Integer decode(AttributeValue value) throws DirectoryException 083 { 084 ByteString nvalue = value.getNormalizedValue(); 085 try 086 { 087 return Integer.valueOf(nvalue.stringValue()); 088 } 089 catch (NumberFormatException e) 090 { 091 Message message = 092 WARN_ATTR_SYNTAX_ILLEGAL_INTEGER.get(nvalue.stringValue()); 093 throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, 094 message); 095 } 096 } 097 }; 098 099 100 101 /** 102 * Creates a new instance of this syntax. Note that the only thing 103 * that should be done here is to invoke the default constructor for 104 * the superclass. All initialization should be performed in the 105 * <CODE>initializeSyntax</CODE> method. 106 */ 107 public IntegerSyntax() 108 { 109 super(); 110 } 111 112 113 114 /** 115 * {@inheritDoc} 116 */ 117 public void initializeSyntax(AttributeSyntaxCfg configuration) 118 throws ConfigException 119 { 120 defaultEqualityMatchingRule = 121 DirectoryServer.getEqualityMatchingRule(EMR_INTEGER_OID); 122 if (defaultEqualityMatchingRule == null) 123 { 124 logError(ERR_ATTR_SYNTAX_UNKNOWN_EQUALITY_MATCHING_RULE.get( 125 EMR_INTEGER_OID, SYNTAX_INTEGER_NAME)); 126 } 127 128 defaultOrderingMatchingRule = 129 DirectoryServer.getOrderingMatchingRule(OMR_INTEGER_OID); 130 if (defaultOrderingMatchingRule == null) 131 { 132 logError(ERR_ATTR_SYNTAX_UNKNOWN_ORDERING_MATCHING_RULE.get( 133 OMR_INTEGER_OID, SYNTAX_INTEGER_NAME)); 134 } 135 136 defaultSubstringMatchingRule = 137 DirectoryServer.getSubstringMatchingRule(SMR_CASE_EXACT_OID); 138 if (defaultSubstringMatchingRule == null) 139 { 140 logError(ERR_ATTR_SYNTAX_UNKNOWN_SUBSTRING_MATCHING_RULE.get( 141 SMR_CASE_EXACT_OID, SYNTAX_INTEGER_NAME)); 142 } 143 } 144 145 146 147 /** 148 * Retrieves the common name for this attribute syntax. 149 * 150 * @return The common name for this attribute syntax. 151 */ 152 public String getSyntaxName() 153 { 154 return SYNTAX_INTEGER_NAME; 155 } 156 157 158 159 /** 160 * Retrieves the OID for this attribute syntax. 161 * 162 * @return The OID for this attribute syntax. 163 */ 164 public String getOID() 165 { 166 return SYNTAX_INTEGER_OID; 167 } 168 169 170 171 /** 172 * Retrieves a description for this attribute syntax. 173 * 174 * @return A description for this attribute syntax. 175 */ 176 public String getDescription() 177 { 178 return SYNTAX_INTEGER_DESCRIPTION; 179 } 180 181 182 183 /** 184 * Retrieves the default equality matching rule that will be used for 185 * attributes with this syntax. 186 * 187 * @return The default equality matching rule that will be used for 188 * attributes with this syntax, or <CODE>null</CODE> if equality 189 * matches will not be allowed for this type by default. 190 */ 191 public EqualityMatchingRule getEqualityMatchingRule() 192 { 193 return defaultEqualityMatchingRule; 194 } 195 196 197 198 /** 199 * Retrieves the default ordering matching rule that will be used for 200 * attributes with this syntax. 201 * 202 * @return The default ordering matching rule that will be used for 203 * attributes with this syntax, or <CODE>null</CODE> if ordering 204 * matches will not be allowed for this type by default. 205 */ 206 public OrderingMatchingRule getOrderingMatchingRule() 207 { 208 return defaultOrderingMatchingRule; 209 } 210 211 212 213 /** 214 * Retrieves the default substring matching rule that will be used for 215 * attributes with this syntax. 216 * 217 * @return The default substring matching rule that will be used for 218 * attributes with this syntax, or <CODE>null</CODE> if substring 219 * matches will not be allowed for this type by default. 220 */ 221 public SubstringMatchingRule getSubstringMatchingRule() 222 { 223 return defaultSubstringMatchingRule; 224 } 225 226 227 228 /** 229 * Retrieves the default approximate matching rule that will be used for 230 * attributes with this syntax. 231 * 232 * @return The default approximate matching rule that will be used for 233 * attributes with this syntax, or <CODE>null</CODE> if approximate 234 * matches will not be allowed for this type by default. 235 */ 236 public ApproximateMatchingRule getApproximateMatchingRule() 237 { 238 // There is no approximate matching rule by default. 239 return null; 240 } 241 242 243 244 /** 245 * Indicates whether the provided value is acceptable for use in an attribute 246 * with this syntax. If it is not, then the reason may be appended to the 247 * provided buffer. 248 * 249 * @param value The value for which to make the determination. 250 * @param invalidReason The buffer to which the invalid reason should be 251 * appended. 252 * 253 * @return <CODE>true</CODE> if the provided value is acceptable for use with 254 * this syntax, or <CODE>false</CODE> if not. 255 */ 256 public boolean valueIsAcceptable(ByteString value, 257 MessageBuilder invalidReason) 258 { 259 String valueString = value.stringValue(); 260 int length = valueString.length(); 261 262 if (length == 0) 263 { 264 invalidReason.append( 265 WARN_ATTR_SYNTAX_INTEGER_EMPTY_VALUE.get(valueString)); 266 return false; 267 } 268 else if (length == 1) 269 { 270 switch (valueString.charAt(0)) 271 { 272 case '0': 273 case '1': 274 case '2': 275 case '3': 276 case '4': 277 case '5': 278 case '6': 279 case '7': 280 case '8': 281 case '9': 282 return true; 283 case '-': 284 invalidReason.append(WARN_ATTR_SYNTAX_INTEGER_DASH_NEEDS_VALUE.get( 285 valueString)); 286 return false; 287 default: 288 invalidReason.append(WARN_ATTR_SYNTAX_INTEGER_INVALID_CHARACTER.get( 289 valueString, 290 valueString.charAt(0), 0)); 291 return false; 292 } 293 } 294 else 295 { 296 boolean negative = false; 297 298 switch (valueString.charAt(0)) 299 { 300 case '0': 301 invalidReason.append(WARN_ATTR_SYNTAX_INTEGER_INITIAL_ZERO.get( 302 valueString)); 303 return false; 304 case '1': 305 case '2': 306 case '3': 307 case '4': 308 case '5': 309 case '6': 310 case '7': 311 case '8': 312 case '9': 313 // These are all fine. 314 break; 315 case '-': 316 // This is fine too. 317 negative = true; 318 break; 319 default: 320 invalidReason.append(WARN_ATTR_SYNTAX_INTEGER_INVALID_CHARACTER.get( 321 valueString, 322 valueString.charAt(0), 0)); 323 return false; 324 } 325 326 switch (valueString.charAt(1)) 327 { 328 case '0': 329 // This is fine as long as the value isn't negative. 330 if (negative) 331 { 332 invalidReason.append(WARN_ATTR_SYNTAX_INTEGER_INITIAL_ZERO.get( 333 valueString)); 334 return false; 335 } 336 break; 337 case '1': 338 case '2': 339 case '3': 340 case '4': 341 case '5': 342 case '6': 343 case '7': 344 case '8': 345 case '9': 346 // These are all fine. 347 break; 348 default: 349 invalidReason.append(WARN_ATTR_SYNTAX_INTEGER_INVALID_CHARACTER.get( 350 valueString, 351 valueString.charAt(0), 0)); 352 return false; 353 } 354 355 for (int i=2; i < length; i++) 356 { 357 switch (valueString.charAt(i)) 358 { 359 case '0': 360 case '1': 361 case '2': 362 case '3': 363 case '4': 364 case '5': 365 case '6': 366 case '7': 367 case '8': 368 case '9': 369 // These are all fine. 370 break; 371 default: 372 invalidReason.append(WARN_ATTR_SYNTAX_INTEGER_INVALID_CHARACTER.get( 373 valueString, 374 valueString.charAt(0), 0)); 375 return false; 376 } 377 } 378 379 return true; 380 } 381 } 382 } 383