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.List;
033    
034    import org.opends.server.admin.std.server.MatchingRuleCfg;
035    import org.opends.server.config.ConfigException;
036    import org.opends.server.types.ByteString;
037    import org.opends.server.types.ConditionResult;
038    import org.opends.server.types.DirectoryException;
039    import org.opends.server.types.InitializationException;
040    
041    
042    
043    /**
044     * This class defines the set of methods and structures that must be
045     * implemented by a Directory Server module that implements a matching
046     * rule.
047     *
048     * @param  <T>  The type of configuration handled by this matching
049     *              rule.
050     */
051    @org.opends.server.types.PublicAPI(
052         stability=org.opends.server.types.StabilityLevel.VOLATILE,
053         mayInstantiate=false,
054         mayExtend=true,
055         mayInvoke=false)
056    public abstract class MatchingRule<T extends MatchingRuleCfg>
057    {
058      /**
059       * Initializes this matching rule based on the information in the
060       * provided configuration entry.
061       *
062       * @param  configuration  The configuration to use to intialize this
063       *                        matching rule.
064       *
065       * @throws  ConfigException  If an unrecoverable problem arises in
066       *                           the process of performing the
067       *                           initialization.
068       *
069       * @throws  InitializationException  If a problem that is not
070       *                                   configuration-related occurs
071       *                                   during initialization.
072       */
073      public abstract void initializeMatchingRule(T configuration)
074             throws ConfigException, InitializationException;
075    
076    
077    
078      /**
079       * Indicates whether the provided configuration is acceptable for
080       * this matching rule.  It should be possible to call this method on
081       * an uninitialized matching rule instance in order to determine
082       * whether the matching rule would be able to use the provided
083       * configuration.
084       * <BR><BR>
085       * Note that implementations which use a subclass of the provided
086       * configuration class will likely need to cast the configuration
087       * to the appropriate subclass type.
088       *
089       * @param  configuration        The matching rule configuration for
090       *                              which to make the determination.
091       * @param  unacceptableReasons  A list that may be used to hold the
092       *                              reasons that the provided
093       *                              configuration is not acceptable.
094       *
095       * @return  {@code true} if the provided configuration is acceptable
096       *          for this matching rule, or {@code false} if not.
097       */
098      public boolean isConfigurationAcceptable(
099                          MatchingRuleCfg configuration,
100                          List<Message> unacceptableReasons)
101      {
102        // This default implementation does not perform any special
103        // validation.  It should be overridden by matching rule
104        // implementations that wish to perform more detailed validation.
105        return true;
106      }
107    
108    
109    
110      /**
111       * Performs any finalization that may be needed whenever this
112       * matching rule is taken out of service.
113       */
114      public void finalizeMatchingRule()
115      {
116        // No implementation is required by default.
117      }
118    
119    
120    
121      /**
122       * Retrieves the common name for this matching rule.
123       *
124       * @return  The common name for this matching rule, or {@code null}
125       *          if it does not have a name.
126       */
127      public abstract String getName();
128    
129    
130    
131      /**
132       * Retrieves the OID for this matching rule.
133       *
134       * @return  The OID for this matching rule.
135       */
136      public abstract String getOID();
137    
138    
139    
140      /**
141       * Retrieves the name or OID for this matching rule.  If it has a
142       * name, then it will be returned.  Otherwise, the OID will be
143       * returned.
144       *
145       * @return  The name or OID for this matching rule.
146       */
147      public final String getNameOrOID()
148      {
149        String name = getName();
150        if ((name == null) || (name.length() == 0))
151        {
152          return getOID();
153        }
154        else
155        {
156          return name;
157        }
158      }
159    
160    
161    
162      /**
163       * Retrieves the description for this matching rule.
164       *
165       * @return  The description for this matching rule, or {@code null}
166       *          if there is none.
167       */
168      public abstract String getDescription();
169    
170    
171    
172      /**
173       * Retrieves the OID of the syntax with which this matching rule is
174       * associated.
175       *
176       * @return  The OID of the syntax with which this matching rule is
177       *          associated.
178       */
179      public abstract String getSyntaxOID();
180    
181    
182    
183      /**
184       * Indicates whether this matching rule is declared "OBSOLETE".
185       * The default implementation will always return {@code false}.  If
186       * that is not acceptable for a particular matching rule
187       * implementation, then it should override this method and perform
188       * the appropriate processing to return the correct value.
189       *
190       * @return  {@code true} if this matching rule is declared
191       *          "OBSOLETE", or {@code false} if not.
192       */
193      public boolean isObsolete()
194      {
195        return false;
196      }
197    
198    
199    
200      /**
201       * Retrieves the normalized form of the provided value, which is
202       * best suite for efficiently performing matching operations on that
203       * value.
204       *
205       * @param  value  The value to be normalized.
206       *
207       * @return  The normalized version of the provided value.
208       *
209       * @throws  DirectoryException  If the provided value is invalid
210       *                              according to the associated
211       *                              attribute syntax.
212       */
213      public abstract ByteString normalizeValue(ByteString value)
214             throws DirectoryException;
215    
216    
217    
218      /**
219       * Indicates whether the provided attribute value should be
220       * considered a match for the given assertion value.  This will only
221       * be used for the purpose of extensible matching.  Subclasses
222       * should define more specific methods that are appropriate to the
223       * matching rule type.
224       *
225       * @param  attributeValue  The attribute value in a form that has
226       *                         been normalized according to this
227       *                         matching rule.
228       * @param  assertionValue  The assertion value in a form that has
229       *                         been normalized according to this
230       *                         matching rule.
231       *
232       * @return  {@code TRUE} if the attribute value should be considered
233       *          a match for the provided assertion value, {@code FALSE}
234       *          if it does not match, or {@code UNDEFINED} if the result
235       *          is undefined.
236       */
237      public abstract ConditionResult
238                           valuesMatch(ByteString attributeValue,
239                                       ByteString assertionValue);
240    
241    
242    
243      /**
244       * Retrieves the hash code for this matching rule.  It will be
245       * calculated as the sum of the characters in the OID.
246       *
247       * @return  The hash code for this matching rule.
248       */
249      public final int hashCode()
250      {
251        int hashCode = 0;
252    
253        String oidString = getOID();
254        int    oidLength = oidString.length();
255        for (int i=0; i < oidLength; i++)
256        {
257          hashCode += oidString.charAt(i);
258        }
259    
260        return hashCode;
261      }
262    
263    
264    
265      /**
266       * Indicates whether the provided object is equal to this matching
267       * rule.  The provided object will be considered equal to this
268       * matching rule only if it is a matching rule with the same OID.
269       *
270       * @param  o  The object for which to make the determination.
271       *
272       * @return  {@code true} if the provided object is equal to this
273       *          matching rule, or {@code false} if it is not.
274       */
275      public final boolean equals(Object o)
276      {
277        if (o == null)
278        {
279          return false;
280        }
281    
282        if (this == o)
283        {
284          return true;
285        }
286    
287        if (! (o instanceof MatchingRule))
288        {
289          return false;
290        }
291    
292        return getOID().equals(((MatchingRule) o).getOID());
293      }
294    
295    
296    
297      /**
298       * Retrieves a string representation of this matching rule in the
299       * format defined in RFC 2252.
300       *
301       * @return  A string representation of this matching rule in the
302       *          format defined in RFC 2252.
303       */
304      public final String toString()
305      {
306        StringBuilder buffer = new StringBuilder();
307        toString(buffer);
308        return buffer.toString();
309      }
310    
311    
312    
313      /**
314       * Appends a string representation of this matching rule in the
315       * format defined in RFC 2252 to the provided buffer.
316       *
317       * @param  buffer  The buffer to which the information should be
318       *                 appended.
319       */
320      public final void toString(StringBuilder buffer)
321      {
322        buffer.append("( ");
323        buffer.append(getOID());
324        buffer.append(" NAME '");
325        buffer.append(getName());
326    
327        String description = getDescription();
328        if ((description != null) && (description.length() > 0))
329        {
330          buffer.append("' DESC '");
331          buffer.append(description);
332        }
333    
334        if (isObsolete())
335        {
336          buffer.append("' OBSOLETE SYNTAX ");
337        }
338        else
339        {
340          buffer.append("' SYNTAX ");
341        }
342    
343        buffer.append(getSyntaxOID());
344        buffer.append(" )");
345      }
346    }
347