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.api; 028 import org.opends.messages.Message; 029 030 031 032 import java.util.ArrayList; 033 import java.util.Collection; 034 import java.util.LinkedHashSet; 035 import java.util.List; 036 037 import org.opends.server.admin.std.server.VirtualAttributeCfg; 038 import org.opends.server.config.ConfigException; 039 import org.opends.server.core.SearchOperation; 040 import org.opends.server.types.AttributeValue; 041 import org.opends.server.types.ByteString; 042 import org.opends.server.types.ConditionResult; 043 import org.opends.server.types.DebugLogLevel; 044 import org.opends.server.types.Entry; 045 import org.opends.server.types.InitializationException; 046 import org.opends.server.types.VirtualAttributeRule; 047 048 import static org.opends.server.loggers.debug.DebugLogger.*; 049 import org.opends.server.loggers.debug.DebugTracer; 050 051 052 053 /** 054 * This class defines the set of methods and structures that must be 055 * implemented by a Directory Server module that implements the 056 * functionality required for one or more virtual attributes. 057 * 058 * @param <T> The type of configuration handled by this virtual 059 * attribute provider. 060 */ 061 @org.opends.server.types.PublicAPI( 062 stability=org.opends.server.types.StabilityLevel.VOLATILE, 063 mayInstantiate=false, 064 mayExtend=true, 065 mayInvoke=false) 066 public abstract class VirtualAttributeProvider 067 <T extends VirtualAttributeCfg> 068 { 069 /** 070 * The tracer object for the debug logger. 071 */ 072 private static final DebugTracer TRACER = getTracer(); 073 074 /** 075 * Initializes this virtual attribute based on the information in 076 * the provided configuration entry. 077 * 078 * @param configuration The configuration to use to initialize 079 * this virtual attribute provider. 080 * 081 * @throws ConfigException If an unrecoverable problem arises in 082 * the process of performing the 083 * initialization. 084 * 085 * @throws InitializationException If a problem occurs during 086 * initialization that is not 087 * related to the server 088 * configuration. 089 */ 090 public abstract void initializeVirtualAttributeProvider( 091 T configuration) 092 throws ConfigException, InitializationException; 093 094 095 096 /** 097 * Indicates whether the provided configuration is acceptable for 098 * this virtual attribute provider. It should be possible to call 099 * this method on an uninitialized virtual attribute provider 100 * instance in order to determine whether the virtual attribute 101 * provider would be able to use the provided configuration. 102 * 103 * @param configuration The virtual attribute provider 104 * configuration for which to make the 105 * determination. 106 * @param unacceptableReasons A list that may be used to hold the 107 * reasons that the provided 108 * configuration is not acceptable. 109 * 110 * @return {@code true} if the provided configuration is acceptable 111 * for this virtual attribute provider, or {@code false} if 112 * not. 113 */ 114 public boolean isConfigurationAcceptable( 115 VirtualAttributeCfg configuration, 116 List<Message> unacceptableReasons) 117 { 118 // This default implementation does not perform any special 119 // validation. It should be overridden by virtual attribute 120 // provider implementations that wish to perform more detailed 121 // validation. 122 return true; 123 } 124 125 126 127 /** 128 * Performs any finalization that may be necessary whenever this 129 * virtual attribute provider is taken out of service. 130 */ 131 public void finalizeVirtualAttributeProvider() 132 { 133 // No implementation required by default. 134 } 135 136 137 138 /** 139 * Indicates whether this virtual attribute provider may generate 140 * multiple values. 141 * 142 * @return {@code true} if this virtual attribute provider may 143 * generate multiple values, or {@code false} if not. 144 */ 145 public abstract boolean isMultiValued(); 146 147 148 149 /** 150 * Generates a set of values for the provided entry. 151 * 152 * @param entry The entry for which the values are to be 153 * generated. 154 * @param rule The virtual attribute rule which defines the 155 * constraints for the virtual attribute. 156 * 157 * @return The set of values generated for the provided entry. It 158 * may be empty, but it must not be {@code null}. 159 */ 160 public abstract LinkedHashSet<AttributeValue> 161 getValues(Entry entry, 162 VirtualAttributeRule rule); 163 164 165 166 /** 167 * Indicates whether this virtual attribute provider will generate 168 * at least one value for the provided entry. 169 * 170 * @param entry The entry for which to make the determination. 171 * @param rule The virtual attribute rule which defines the 172 * constraints for the virtual attribute. 173 * 174 * @return {@code true} if this virtual attribute provider will 175 * generate at least one value for the provided entry, or 176 * {@code false} if not. 177 */ 178 public boolean hasValue(Entry entry, VirtualAttributeRule rule) 179 { 180 return (! getValues(entry, rule).isEmpty()); 181 } 182 183 184 185 /** 186 * Indicates whether this virtual attribute provider will generate 187 * the provided value. 188 * 189 * @param entry The entry for which to make the determination. 190 * @param rule The virtual attribute rule which defines the 191 * constraints for the virtual attribute. 192 * @param value The value for which to make the determination. 193 * 194 * @return {@code true} if this virtual attribute provider will 195 * generate the specified vaule for the provided entry, or 196 * {@code false} if not. 197 */ 198 public boolean hasValue(Entry entry, VirtualAttributeRule rule, 199 AttributeValue value) 200 { 201 return getValues(entry, rule).contains(value); 202 } 203 204 205 206 /** 207 * Indicates whether this virtual attribute provider will generate 208 * all of the values in the provided collection. 209 * 210 * @param entry The entry for which to make the determination. 211 * @param rule The virtual attribute rule which defines the 212 * constraints for the virtual attribute. 213 * @param values The set of values for which to make the 214 * determination. 215 * 216 * @return {@code true} if this attribute provider will generate 217 * all of the values in the provided collection, or 218 * {@code false} if it will not generate at least one of 219 * them. 220 */ 221 public boolean hasAllValues(Entry entry, VirtualAttributeRule rule, 222 Collection<AttributeValue> values) 223 { 224 for (AttributeValue value : values) 225 { 226 if (! getValues(entry, rule).contains(value)) 227 { 228 return false; 229 } 230 } 231 232 return true; 233 } 234 235 236 237 /** 238 * Indicates whether this virutal attribute provider will generate 239 * any of the values in the provided collection. 240 * 241 * @param entry The entry for which to make the determination. 242 * @param rule The virtual attribute rule which defines the 243 * constraints for the virtual attribute. 244 * @param values The set of values for which to make the 245 * determination. 246 * 247 * @return {@code true} if this attribute provider will generate 248 * at least one of the values in the provided collection, 249 * or {@code false} if it will not generate any of them. 250 */ 251 public boolean hasAnyValue(Entry entry, VirtualAttributeRule rule, 252 Collection<AttributeValue> values) 253 { 254 for (AttributeValue value : values) 255 { 256 if (getValues(entry, rule).contains(value)) 257 { 258 return true; 259 } 260 } 261 262 return false; 263 } 264 265 266 267 /** 268 * Indicates whether this virtual attribute provider will generate 269 * any value which matches the provided substring. 270 * 271 * @param entry The entry for which to make the 272 * determination. 273 * @param rule The virtual attribute rule which defines the 274 * constraints for the virtual attribute. 275 * @param subInitial The subInitial component to use in the 276 * determination. 277 * @param subAny The subAny components to use in the 278 * determination. 279 * @param subFinal The subFinal component to use in the 280 * determination. 281 * 282 * @return {@code UNDEFINED} if this attribute does not have a 283 * substring matching rule, {@code TRUE} if at least one 284 * value matches the provided substring, or {@code FALSE} 285 * otherwise. 286 */ 287 public ConditionResult matchesSubstring(Entry entry, 288 VirtualAttributeRule rule, 289 ByteString subInitial, 290 List<ByteString> subAny, 291 ByteString subFinal) 292 { 293 SubstringMatchingRule matchingRule = 294 rule.getAttributeType().getSubstringMatchingRule(); 295 if (matchingRule == null) 296 { 297 return ConditionResult.UNDEFINED; 298 } 299 300 301 ByteString normalizedSubInitial; 302 if (subInitial == null) 303 { 304 normalizedSubInitial = null; 305 } 306 else 307 { 308 try 309 { 310 normalizedSubInitial = 311 matchingRule.normalizeSubstring(subInitial); 312 } 313 catch (Exception e) 314 { 315 if (debugEnabled()) 316 { 317 TRACER.debugCaught(DebugLogLevel.ERROR, e); 318 } 319 320 // The substring couldn't be normalized. We have to return 321 // "undefined". 322 return ConditionResult.UNDEFINED; 323 } 324 } 325 326 327 ArrayList<ByteString> normalizedSubAny; 328 if (subAny == null) 329 { 330 normalizedSubAny = null; 331 } 332 else 333 { 334 normalizedSubAny = 335 new ArrayList<ByteString>(subAny.size()); 336 for (ByteString subAnyElement : subAny) 337 { 338 try 339 { 340 normalizedSubAny.add(matchingRule.normalizeSubstring( 341 subAnyElement)); 342 } 343 catch (Exception e) 344 { 345 if (debugEnabled()) 346 { 347 TRACER.debugCaught(DebugLogLevel.ERROR, e); 348 } 349 350 // The substring couldn't be normalized. We have to return 351 // "undefined". 352 return ConditionResult.UNDEFINED; 353 } 354 } 355 } 356 357 358 ByteString normalizedSubFinal; 359 if (subFinal == null) 360 { 361 normalizedSubFinal = null; 362 } 363 else 364 { 365 try 366 { 367 normalizedSubFinal = 368 matchingRule.normalizeSubstring(subFinal); 369 } 370 catch (Exception e) 371 { 372 if (debugEnabled()) 373 { 374 TRACER.debugCaught(DebugLogLevel.ERROR, e); 375 } 376 377 // The substring couldn't be normalized. We have to return 378 // "undefined". 379 return ConditionResult.UNDEFINED; 380 } 381 } 382 383 384 ConditionResult result = ConditionResult.FALSE; 385 for (AttributeValue value : getValues(entry, rule)) 386 { 387 try 388 { 389 if (matchingRule.valueMatchesSubstring( 390 value.getNormalizedValue(), 391 normalizedSubInitial, 392 normalizedSubAny, 393 normalizedSubFinal)) 394 { 395 return ConditionResult.TRUE; 396 } 397 } 398 catch (Exception e) 399 { 400 if (debugEnabled()) 401 { 402 TRACER.debugCaught(DebugLogLevel.ERROR, e); 403 } 404 405 // The value couldn't be normalized. If we can't find a 406 // definite match, then we should return "undefined". 407 result = ConditionResult.UNDEFINED; 408 } 409 } 410 411 return result; 412 } 413 414 415 416 /** 417 * Indicates whether this virtual attribute provider will generate 418 * any value for the provided entry that is greater than or equal to 419 * the given value. 420 * 421 * @param entry The entry for which to make the determination. 422 * @param rule The virtual attribute rule which defines the 423 * constraints for the virtual attribute. 424 * @param value The value for which to make the determination. 425 * 426 * @return {@code UNDEFINED} if the associated attribute type does 427 * not have an ordering matching rule, {@code TRUE} if at 428 * least one of the generated values will be greater than 429 * or equal to the specified value, or {@code FALSE} if 430 * none of the generated values will be greater than or 431 * equal to the specified value. 432 */ 433 public ConditionResult greaterThanOrEqualTo(Entry entry, 434 VirtualAttributeRule rule, 435 AttributeValue value) 436 { 437 OrderingMatchingRule matchingRule = 438 rule.getAttributeType().getOrderingMatchingRule(); 439 if (matchingRule == null) 440 { 441 return ConditionResult.UNDEFINED; 442 } 443 444 ByteString normalizedValue; 445 try 446 { 447 normalizedValue = value.getNormalizedValue(); 448 } 449 catch (Exception e) 450 { 451 if (debugEnabled()) 452 { 453 TRACER.debugCaught(DebugLogLevel.ERROR, e); 454 } 455 456 // We couldn't normalize the provided value. We should return 457 // "undefined". 458 return ConditionResult.UNDEFINED; 459 } 460 461 ConditionResult result = ConditionResult.FALSE; 462 for (AttributeValue v : getValues(entry, rule)) 463 { 464 try 465 { 466 ByteString nv = v.getNormalizedValue(); 467 int comparisonResult = 468 matchingRule.compareValues(nv, normalizedValue); 469 if (comparisonResult >= 0) 470 { 471 return ConditionResult.TRUE; 472 } 473 } 474 catch (Exception e) 475 { 476 if (debugEnabled()) 477 { 478 TRACER.debugCaught(DebugLogLevel.ERROR, e); 479 } 480 481 // We couldn't normalize one of the attribute values. If we 482 // can't find a definite match, then we should return 483 // "undefined". 484 result = ConditionResult.UNDEFINED; 485 } 486 } 487 488 return result; 489 } 490 491 492 493 /** 494 * Indicates whether this virtual attribute provider will generate 495 * any value for the provided entry that is less than or equal to 496 * the given value. 497 * 498 * @param entry The entry for which to make the determination. 499 * @param rule The virtual attribute rule which defines the 500 * constraints for the virtual attribute. 501 * @param value The value for which to make the determination. 502 * 503 * @return {@code UNDEFINED} if the associated attribute type does 504 * not have an ordering matching rule, {@code TRUE} if at 505 * least one of the generated values will be less than or 506 * equal to the specified value, or {@code FALSE} if none 507 * of the generated values will be greater than or equal to 508 * the specified value. 509 */ 510 public ConditionResult lessThanOrEqualTo(Entry entry, 511 VirtualAttributeRule rule, 512 AttributeValue value) 513 { 514 OrderingMatchingRule matchingRule = 515 rule.getAttributeType().getOrderingMatchingRule(); 516 if (matchingRule == null) 517 { 518 return ConditionResult.UNDEFINED; 519 } 520 521 ByteString normalizedValue; 522 try 523 { 524 normalizedValue = value.getNormalizedValue(); 525 } 526 catch (Exception e) 527 { 528 if (debugEnabled()) 529 { 530 TRACER.debugCaught(DebugLogLevel.ERROR, e); 531 } 532 533 // We couldn't normalize the provided value. We should return 534 // "undefined". 535 return ConditionResult.UNDEFINED; 536 } 537 538 ConditionResult result = ConditionResult.FALSE; 539 for (AttributeValue v : getValues(entry, rule)) 540 { 541 try 542 { 543 ByteString nv = v.getNormalizedValue(); 544 int comparisonResult = 545 matchingRule.compareValues(nv, normalizedValue); 546 if (comparisonResult <= 0) 547 { 548 return ConditionResult.TRUE; 549 } 550 } 551 catch (Exception e) 552 { 553 if (debugEnabled()) 554 { 555 TRACER.debugCaught(DebugLogLevel.ERROR, e); 556 } 557 558 // We couldn't normalize one of the attribute values. If we 559 // can't find a definite match, then we should return 560 // "undefined". 561 result = ConditionResult.UNDEFINED; 562 } 563 } 564 565 return result; 566 } 567 568 569 570 /** 571 * Indicates whether this virtual attribute provider will generate 572 * any value for the provided entry that is approximately equal to 573 * the given value. 574 * 575 * @param entry The entry for which to make the determination. 576 * @param rule The virtual attribute rule which defines the 577 * constraints for the virtual attribute. 578 * @param value The value for which to make the determination. 579 * 580 * @return {@code UNDEFINED} if the associated attribute type does 581 * not have an aproximate matching rule, {@code TRUE} if at 582 * least one of the generated values will be approximately 583 * equal to the specified value, or {@code FALSE} if none 584 * of the generated values will be approximately equal to 585 * the specified value. 586 */ 587 public ConditionResult approximatelyEqualTo(Entry entry, 588 VirtualAttributeRule rule, 589 AttributeValue value) 590 { 591 ApproximateMatchingRule matchingRule = 592 rule.getAttributeType().getApproximateMatchingRule(); 593 if (matchingRule == null) 594 { 595 return ConditionResult.UNDEFINED; 596 } 597 598 ByteString normalizedValue; 599 try 600 { 601 normalizedValue = matchingRule.normalizeValue(value.getValue()); 602 } 603 catch (Exception e) 604 { 605 if (debugEnabled()) 606 { 607 TRACER.debugCaught(DebugLogLevel.ERROR, e); 608 } 609 610 // We couldn't normalize the provided value. We should return 611 // "undefined". 612 return ConditionResult.UNDEFINED; 613 } 614 615 ConditionResult result = ConditionResult.FALSE; 616 for (AttributeValue v : getValues(entry, rule)) 617 { 618 try 619 { 620 ByteString nv = matchingRule.normalizeValue(v.getValue()); 621 if (matchingRule.approximatelyMatch(nv, normalizedValue)) 622 { 623 return ConditionResult.TRUE; 624 } 625 } 626 catch (Exception e) 627 { 628 if (debugEnabled()) 629 { 630 TRACER.debugCaught(DebugLogLevel.ERROR, e); 631 } 632 633 // We couldn't normalize one of the attribute values. If we 634 // can't find a definite match, then we should return 635 // "undefined". 636 result = ConditionResult.UNDEFINED; 637 } 638 } 639 640 return result; 641 } 642 643 644 645 /** 646 * Indicates whether this attribute may be included in search 647 * filters as part of the criteria for locating entries. 648 * 649 * @param rule The virtual attribute rule which defines 650 * the constraints for the virtual 651 * attribute. 652 * @param searchOperation The search operation for which to make 653 * the determination. 654 * 655 * @return {@code true} if this attribute may be included in search 656 * filters, or {@code false} if not. 657 */ 658 public abstract boolean isSearchable(VirtualAttributeRule rule, 659 SearchOperation 660 searchOperation); 661 662 663 664 /** 665 * Processes the provided search operation in which the search 666 * criteria includes an operation targeted at this virtual 667 * attribute. This method should only be called if 668 * {@code isSearchable} returns true and it is not possible to 669 * construct a manageable candidate list by processing other 670 * elements of the search criteria. 671 * 672 * @param rule The virtual attribute rule which defines 673 * the constraints for the virtual 674 * attribute. 675 * @param searchOperation The search operation to be processed. 676 */ 677 public abstract void processSearch(VirtualAttributeRule rule, 678 SearchOperation searchOperation); 679 } 680