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