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