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.schema;
028    
029    
030    
031    import org.opends.server.admin.std.server.OrderingMatchingRuleCfg;
032    import org.opends.server.api.OrderingMatchingRule;
033    import org.opends.server.config.ConfigException;
034    import org.opends.server.protocols.asn1.ASN1OctetString;
035    import org.opends.server.types.ByteString;
036    import org.opends.server.types.DirectoryException;
037    import org.opends.server.types.InitializationException;
038    
039    import static org.opends.server.schema.SchemaConstants.*;
040    import static org.opends.server.util.StaticUtils.*;
041    
042    
043    
044    /**
045     * This class defines the caseIgnoreOrderingMatch matching rule defined in X.520
046     * and referenced in RFC 2252.
047     */
048    public class CaseIgnoreOrderingMatchingRule
049           extends OrderingMatchingRule
050    {
051      /**
052       * The serial version identifier required to satisfy the compiler because this
053       * class implements the <CODE>java.io.Serializable</CODE> interface.  This
054       * value was generated using the <CODE>serialver</CODE> command-line utility
055       * included with the Java SDK.
056       */
057      private static final long serialVersionUID = -8992263058903266096L;
058    
059    
060    
061      /**
062       * Creates a new instance of this caseIgnoreOrderingMatch matching rule.
063       */
064      public CaseIgnoreOrderingMatchingRule()
065      {
066        super();
067      }
068    
069    
070    
071      /**
072       * {@inheritDoc}
073       */
074      public void initializeMatchingRule(OrderingMatchingRuleCfg configuration)
075             throws ConfigException, InitializationException
076      {
077        // No initialization is required.
078      }
079    
080    
081    
082      /**
083       * Retrieves the common name for this matching rule.
084       *
085       * @return  The common name for this matching rule, or <CODE>null</CODE> if
086       * it does not have a name.
087       */
088      public String getName()
089      {
090        return OMR_CASE_IGNORE_NAME;
091      }
092    
093    
094    
095      /**
096       * Retrieves the OID for this matching rule.
097       *
098       * @return  The OID for this matching rule.
099       */
100      public String getOID()
101      {
102        return OMR_CASE_IGNORE_OID;
103      }
104    
105    
106    
107      /**
108       * Retrieves the description for this matching rule.
109       *
110       * @return  The description for this matching rule, or <CODE>null</CODE> if
111       *          there is none.
112       */
113      public String getDescription()
114      {
115        // There is no standard description for this matching rule.
116        return null;
117      }
118    
119    
120    
121      /**
122       * Retrieves the OID of the syntax with which this matching rule is
123       * associated.
124       *
125       * @return  The OID of the syntax with which this matching rule is associated.
126       */
127      public String getSyntaxOID()
128      {
129        return SYNTAX_DIRECTORY_STRING_OID;
130      }
131    
132    
133    
134      /**
135       * Retrieves the normalized form of the provided value, which is best suited
136       * for efficiently performing matching operations on that value.
137       *
138       * @param  value  The value to be normalized.
139       *
140       * @return  The normalized version of the provided value.
141       *
142       * @throws  DirectoryException  If the provided value is invalid according to
143       *                              the associated attribute syntax.
144       */
145      public ByteString normalizeValue(ByteString value)
146             throws DirectoryException
147      {
148        StringBuilder buffer = new StringBuilder();
149        toLowerCase(value.value(), buffer, true);
150    
151        int bufferLength = buffer.length();
152        if (bufferLength == 0)
153        {
154          if (value.value().length > 0)
155          {
156            // This should only happen if the value is composed entirely of spaces.
157            // In that case, the normalized value is a single space.
158            return new ASN1OctetString(" ");
159          }
160          else
161          {
162            // The value is empty, so it is already normalized.
163            return new ASN1OctetString();
164          }
165        }
166    
167    
168        // Replace any consecutive spaces with a single space.
169        for (int pos = bufferLength-1; pos > 0; pos--)
170        {
171          if (buffer.charAt(pos) == ' ')
172          {
173            if (buffer.charAt(pos-1) == ' ')
174            {
175              buffer.delete(pos, pos+1);
176            }
177          }
178        }
179    
180        return new ASN1OctetString(buffer.toString());
181      }
182    
183    
184    
185      /**
186       * Compares the first value to the second and returns a value that indicates
187       * their relative order.
188       *
189       * @param  value1  The normalized form of the first value to compare.
190       * @param  value2  The normalized form of the second value to compare.
191       *
192       * @return  A negative integer if <CODE>value1</CODE> should come before
193       *          <CODE>value2</CODE> in ascending order, a positive integer if
194       *          <CODE>value1</CODE> should come after <CODE>value2</CODE> in
195       *          ascending order, or zero if there is no difference between the
196       *          values with regard to ordering.
197       */
198      public int compareValues(ByteString value1, ByteString value2)
199      {
200        return compare(value1.value(),value2.value());
201      }
202    
203    
204    
205      /**
206       * Compares the contents of the provided byte arrays to determine their
207       * relative order.
208       *
209       * @param  b1  The first byte array to use in the comparison.
210       * @param  b2  The second byte array to use in the comparison.
211       *
212       * @return  A negative integer if <CODE>b1</CODE> should come before
213       *          <CODE>b2</CODE> in ascending order, a positive integer if
214       *          <CODE>b1</CODE> should come after <CODE>b2</CODE> in ascending
215       *          order, or zero if there is no difference between the values with
216       *          regard to ordering.
217       */
218      public int compare(byte[] b1, byte[] b2)
219      {
220        int minLength = Math.min(b1.length, b2.length);
221    
222        for (int i=0; i < minLength; i++)
223        {
224          if (b1[i] == b2[i])
225          {
226            continue;
227          }
228          else if (b1[i] < b2[i])
229          {
230            return -1;
231          }
232          else if (b1[i] > b2[i])
233          {
234            return 1;
235          }
236        }
237    
238        if (b1.length == b2.length)
239        {
240          return 0;
241        }
242        else if (b1.length < b2.length)
243        {
244          return -1;
245        }
246        else
247        {
248          return 1;
249        }
250      }
251    }
252