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