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 legal-notices/CDDLv1_0.txt 010 * or http://forgerock.org/license/CDDLv1.0.html. 011 * See the License for the specific language governing permissions 012 * and limitations under the License. 013 * 014 * When distributing Covered Code, include this CDDL HEADER in each 015 * file and include the License file at legal-notices/CDDLv1_0.txt. 016 * If applicable, add the following below this CDDL HEADER, with the 017 * fields enclosed by brackets "[]" replaced with your own identifying 018 * information: 019 * Portions Copyright [yyyy] [name of copyright owner] 020 * 021 * CDDL HEADER END 022 * 023 * 024 * Copyright 2006-2009 Sun Microsystems, Inc. 025 * Portions Copyright 2012-2014 ForgeRock AS 026 */ 027package org.opends.server.api; 028 029import java.util.Collection; 030import java.util.List; 031 032import org.forgerock.i18n.LocalizableMessage; 033import org.forgerock.i18n.slf4j.LocalizedLogger; 034import org.forgerock.opendj.config.server.ConfigException; 035import org.forgerock.opendj.ldap.Assertion; 036import org.forgerock.opendj.ldap.ByteString; 037import org.forgerock.opendj.ldap.ConditionResult; 038import org.forgerock.opendj.ldap.DecodeException; 039import org.forgerock.opendj.ldap.schema.MatchingRule; 040import org.opends.server.admin.std.server.VirtualAttributeCfg; 041import org.opends.server.core.SearchOperation; 042import org.opends.server.types.Attribute; 043import org.opends.server.types.Entry; 044import org.opends.server.types.InitializationException; 045import org.opends.server.types.VirtualAttributeRule; 046 047/** 048 * This class defines the set of methods and structures that must be 049 * implemented by a Directory Server module that implements the 050 * functionality required for one or more virtual attributes. 051 * 052 * @param <T> The type of configuration handled by this virtual 053 * attribute provider. 054 */ 055@org.opends.server.types.PublicAPI( 056 stability=org.opends.server.types.StabilityLevel.VOLATILE, 057 mayInstantiate=false, 058 mayExtend=true, 059 mayInvoke=false) 060public abstract class VirtualAttributeProvider 061 <T extends VirtualAttributeCfg> 062{ 063 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 064 065 /** 066 * Initializes this virtual attribute based on the information in 067 * the provided configuration entry. 068 * 069 * @param configuration The configuration to use to initialize 070 * this virtual attribute provider. 071 * 072 * @throws ConfigException If an unrecoverable problem arises in 073 * the process of performing the 074 * initialization. 075 * 076 * @throws InitializationException If a problem occurs during 077 * initialization that is not 078 * related to the server 079 * configuration. 080 */ 081 public void initializeVirtualAttributeProvider(T configuration) 082 throws ConfigException, InitializationException 083 { 084 // No initialization required 085 } 086 087 088 089 /** 090 * Indicates whether the provided configuration is acceptable for 091 * this virtual attribute provider. It should be possible to call 092 * this method on an uninitialized virtual attribute provider 093 * instance in order to determine whether the virtual attribute 094 * provider would be able to use the provided configuration. 095 * 096 * @param configuration The virtual attribute provider 097 * configuration for which to make the 098 * determination. 099 * @param unacceptableReasons A list that may be used to hold the 100 * reasons that the provided 101 * configuration is not acceptable. 102 * 103 * @return {@code true} if the provided configuration is acceptable 104 * for this virtual attribute provider, or {@code false} if 105 * not. 106 */ 107 public boolean isConfigurationAcceptable( 108 VirtualAttributeCfg configuration, 109 List<LocalizableMessage> unacceptableReasons) 110 { 111 // This default implementation does not perform any special validation. 112 // It should be overridden by virtual attribute provider implementations 113 // that wish to perform more detailed validation. 114 return true; 115 } 116 117 118 119 /** 120 * Performs any finalization that may be necessary whenever this 121 * virtual attribute provider is taken out of service. 122 */ 123 public void finalizeVirtualAttributeProvider() 124 { 125 // No implementation required by default. 126 } 127 128 129 130 /** 131 * Indicates whether this virtual attribute provider may generate 132 * multiple values. 133 * 134 * @return {@code true} if this virtual attribute provider may 135 * generate multiple values, or {@code false} if not. 136 */ 137 public abstract boolean isMultiValued(); 138 139 140 141 /** 142 * Generates an unmodifiable attribute with the values for the provided entry. 143 * 144 * @param entry 145 * The entry for which the values are to be generated. 146 * @param rule 147 * The virtual attribute rule which defines the constraints 148 * for the virtual attribute. 149 * @return The unmodifiable attribute with the values generated for the 150 * provided entry. It may be empty, but it must not be {@code null}. 151 */ 152 public abstract Attribute getValues(Entry entry, VirtualAttributeRule rule); 153 154 155 156 /** 157 * Indicates whether this virtual attribute provider will generate 158 * at least one value for the provided entry. 159 * 160 * @param entry The entry for which to make the determination. 161 * @param rule The virtual attribute rule which defines the 162 * constraints for the virtual attribute. 163 * 164 * @return {@code true} if this virtual attribute provider will 165 * generate at least one value for the provided entry, or 166 * {@code false} if not. 167 */ 168 public boolean hasValue(Entry entry, VirtualAttributeRule rule) 169 { 170 return !getValues(entry, rule).isEmpty(); 171 } 172 173 174 175 /** 176 * Indicates whether this virtual attribute provider will generate 177 * the provided value. 178 * 179 * @param entry The entry for which to make the determination. 180 * @param rule The virtual attribute rule which defines the 181 * constraints for the virtual attribute. 182 * @param value The value for which to make the determination. 183 * 184 * @return {@code true} if this virtual attribute provider will 185 * generate the specified value for the provided entry, or 186 * {@code false} if not. 187 */ 188 public boolean hasValue(Entry entry, VirtualAttributeRule rule, ByteString value) 189 { 190 return getValues(entry, rule).contains(value); 191 } 192 193 /** 194 * Indicates whether this virtual attribute provider matches the assertion 195 * value. 196 * 197 * @param entry 198 * The entry for which to make the determination. 199 * @param rule 200 * The virtual attribute rule which defines the constraints for the 201 * virtual attribute. 202 * @param assertionValue 203 * The assertion value for which to make the determination. 204 * @return {@code true} if this virtual attribute provider matches the 205 * specified assertion value for the provided entry, or {@code false} 206 * if not. 207 */ 208 public ConditionResult matchesEqualityAssertion(Entry entry, 209 VirtualAttributeRule rule, ByteString assertionValue) 210 { 211 return getValues(entry, rule).matchesEqualityAssertion(assertionValue); 212 } 213 214 215 /** 216 * Indicates whether this virtual attribute provider will generate 217 * all of the values in the provided collection. 218 * 219 * @param entry The entry for which to make the determination. 220 * @param rule The virtual attribute rule which defines the 221 * constraints for the virtual attribute. 222 * @param values The set of values for which to make the 223 * determination. 224 * 225 * @return {@code true} if this attribute provider will generate 226 * all of the values in the provided collection, or 227 * {@code false} if it will not generate at least one of 228 * them. 229 */ 230 public boolean hasAllValues(Entry entry, VirtualAttributeRule rule, 231 Collection<ByteString> values) 232 { 233 return getValues(entry, rule).containsAll(values); 234 } 235 236 237 238 /** 239 * Indicates whether this virtual attribute provider will generate 240 * any value which matches the provided substring. 241 * 242 * @param entry The entry for which to make the 243 * determination. 244 * @param rule The virtual attribute rule which defines the 245 * constraints for the virtual attribute. 246 * @param subInitial The subInitial component to use in the 247 * determination. 248 * @param subAny The subAny components to use in the 249 * determination. 250 * @param subFinal The subFinal component to use in the 251 * determination. 252 * 253 * @return {@code UNDEFINED} if this attribute does not have a 254 * substring matching rule, {@code TRUE} if at least one 255 * value matches the provided substring, or {@code FALSE} 256 * otherwise. 257 */ 258 public ConditionResult matchesSubstring(Entry entry, 259 VirtualAttributeRule rule, 260 ByteString subInitial, 261 List<ByteString> subAny, 262 ByteString subFinal) 263 { 264 MatchingRule matchingRule = rule.getAttributeType().getSubstringMatchingRule(); 265 if (matchingRule == null) 266 { 267 return ConditionResult.UNDEFINED; 268 } 269 270 Assertion assertion; 271 try 272 { 273 assertion = matchingRule.getSubstringAssertion(subInitial, subAny, subFinal); 274 } 275 catch(DecodeException e) { 276 logger.traceException(e); 277 return ConditionResult.UNDEFINED; 278 } 279 280 ConditionResult result = ConditionResult.FALSE; 281 for (ByteString value : getValues(entry, rule)) 282 { 283 try 284 { 285 if (assertion.matches(matchingRule.normalizeAttributeValue(value)).toBoolean()) 286 { 287 return ConditionResult.TRUE; 288 } 289 } 290 catch (Exception e) 291 { 292 logger.traceException(e); 293 294 // We couldn't normalize one of the attribute values. 295 // We will return "undefined" if we can't find a definite match 296 result = ConditionResult.UNDEFINED; 297 } 298 } 299 300 return result; 301 } 302 303 304 /** 305 * Indicates whether this virtual attribute provider will generate any value 306 * for the provided entry that is greater than or equal to the given value. 307 * 308 * @param entry 309 * The entry for which to make the determination. 310 * @param rule 311 * The virtual attribute rule which defines the constraints for the 312 * virtual attribute. 313 * @param assertionValue 314 * The assertion value for which to make the determination. 315 * @return {@code UNDEFINED} if the associated attribute type does not have an 316 * ordering matching rule, {@code TRUE} if at least one of the 317 * generated values will be greater than or equal to the specified 318 * assertion value, or {@code FALSE} if none of the generated values 319 * will be greater than or equal to the specified value. 320 */ 321 public ConditionResult greaterThanOrEqualTo(Entry entry, 322 VirtualAttributeRule rule, 323 ByteString assertionValue) 324 { 325 MatchingRule matchingRule = rule.getAttributeType().getOrderingMatchingRule(); 326 if (matchingRule == null) 327 { 328 return ConditionResult.UNDEFINED; 329 } 330 331 Assertion assertion = null; 332 try 333 { 334 assertion = matchingRule.getGreaterOrEqualAssertion(assertionValue); 335 } 336 catch (Exception e) 337 { 338 logger.traceException(e); 339 return ConditionResult.UNDEFINED; 340 } 341 342 ConditionResult result = ConditionResult.FALSE; 343 for (ByteString v : getValues(entry, rule)) 344 { 345 try 346 { 347 if (assertion.matches(matchingRule.normalizeAttributeValue(v)).toBoolean()) 348 { 349 return ConditionResult.TRUE; 350 } 351 } 352 catch (Exception e) 353 { 354 logger.traceException(e); 355 // We couldn't normalize one of the attribute values. 356 // We will return "undefined" if we can't find a definite match 357 result = ConditionResult.UNDEFINED; 358 } 359 } 360 361 return result; 362 } 363 364 365 366 /** 367 * Indicates whether this virtual attribute provider will generate any value 368 * for the provided entry that is less than or equal to the given value. 369 * 370 * @param entry 371 * The entry for which to make the determination. 372 * @param rule 373 * The virtual attribute rule which defines the constraints for the 374 * virtual attribute. 375 * @param assertionValue 376 * The assertion value for which to make the determination. 377 * @return {@code UNDEFINED} if the associated attribute type does not have an 378 * ordering matching rule, {@code TRUE} if at least one of the 379 * generated values will be less than or equal to the specified 380 * assertion value, or {@code FALSE} if none of the generated values 381 * will be greater than or equal to the specified value. 382 */ 383 public ConditionResult lessThanOrEqualTo(Entry entry, 384 VirtualAttributeRule rule, 385 ByteString assertionValue) 386 { 387 MatchingRule matchingRule = rule.getAttributeType().getOrderingMatchingRule(); 388 if (matchingRule == null) 389 { 390 return ConditionResult.UNDEFINED; 391 } 392 393 Assertion assertion = null; 394 try 395 { 396 assertion = matchingRule.getLessOrEqualAssertion(assertionValue); 397 } 398 catch (Exception e) 399 { 400 logger.traceException(e); 401 return ConditionResult.UNDEFINED; 402 } 403 404 ConditionResult result = ConditionResult.FALSE; 405 for (ByteString v : getValues(entry, rule)) 406 { 407 try 408 { 409 if (assertion.matches(matchingRule.normalizeAttributeValue(v)).toBoolean()) 410 { 411 return ConditionResult.TRUE; 412 } 413 } 414 catch (Exception e) 415 { 416 logger.traceException(e); 417 418 // We couldn't normalize one of the attribute values. 419 // We will return "undefined" if we can't find a definite match 420 result = ConditionResult.UNDEFINED; 421 } 422 } 423 424 return result; 425 } 426 427 428 429 /** 430 * Indicates whether this virtual attribute provider will generate 431 * any value for the provided entry that is approximately equal to 432 * the given value. 433 * 434 * @param entry The entry for which to make the determination. 435 * @param rule The virtual attribute rule which defines the 436 * constraints for the virtual attribute. 437 * @param assertionValue 438 * The assertion value for which to make the determination. 439 * 440 * @return {@code UNDEFINED} if the associated attribute type does 441 * not have an approximate matching rule, {@code TRUE} if at 442 * least one of the generated values will be approximately 443 * equal to the specified value, or {@code FALSE} if none 444 * of the generated values will be approximately equal to 445 * the specified assertion value. 446 */ 447 public ConditionResult approximatelyEqualTo(Entry entry, 448 VirtualAttributeRule rule, 449 ByteString assertionValue) 450 { 451 MatchingRule matchingRule = rule.getAttributeType().getApproximateMatchingRule(); 452 if (matchingRule == null) 453 { 454 return ConditionResult.UNDEFINED; 455 } 456 457 Assertion assertion = null; 458 try 459 { 460 assertion = matchingRule.getAssertion(assertionValue); 461 } 462 catch (Exception e) 463 { 464 logger.traceException(e); 465 return ConditionResult.UNDEFINED; 466 } 467 468 ConditionResult result = ConditionResult.FALSE; 469 for (ByteString v : getValues(entry, rule)) 470 { 471 try 472 { 473 if (assertion.matches(matchingRule.normalizeAttributeValue(v)).toBoolean()) 474 { 475 return ConditionResult.TRUE; 476 } 477 } 478 catch (Exception e) 479 { 480 logger.traceException(e); 481 // We couldn't normalize one of the attribute values. 482 // We will return "undefined" if we can't find a definite match 483 result = ConditionResult.UNDEFINED; 484 } 485 } 486 return result; 487 } 488 489 490 491 /** 492 * Indicates whether this attribute may be included in search 493 * filters as part of the criteria for locating entries. 494 * 495 * @param rule The virtual attribute rule which defines 496 * the constraints for the virtual 497 * attribute. 498 * @param searchOperation The search operation for which to make 499 * the determination. 500 * @param isPreIndexed Indicates if we expect the search on the virtual 501 * attribute to be faster than an index search. 502 * @return {@code true} if this attribute may be included in search 503 * filters, or {@code false} if not. 504 */ 505 public abstract boolean isSearchable(VirtualAttributeRule rule, 506 SearchOperation searchOperation, 507 boolean isPreIndexed); 508 509 510 511 /** 512 * Processes the provided search operation in which the search 513 * criteria includes an operation targeted at this virtual 514 * attribute. This method should only be called if 515 * {@code isSearchable} returns true and it is not possible to 516 * construct a manageable candidate list by processing other 517 * elements of the search criteria. 518 * 519 * @param rule The virtual attribute rule which defines 520 * the constraints for the virtual 521 * attribute. 522 * @param searchOperation The search operation to be processed. 523 */ 524 public abstract void processSearch(VirtualAttributeRule rule, 525 SearchOperation searchOperation); 526} 527