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