001    /*
002     * Copyright 2008-2015 UnboundID Corp.
003     * All Rights Reserved.
004     */
005    /*
006     * Copyright (C) 2008-2015 UnboundID Corp.
007     *
008     * This program is free software; you can redistribute it and/or modify
009     * it under the terms of the GNU General Public License (GPLv2 only)
010     * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
011     * as published by the Free Software Foundation.
012     *
013     * This program is distributed in the hope that it will be useful,
014     * but WITHOUT ANY WARRANTY; without even the implied warranty of
015     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016     * GNU General Public License for more details.
017     *
018     * You should have received a copy of the GNU General Public License
019     * along with this program; if not, see <http://www.gnu.org/licenses>.
020     */
021    package com.unboundid.ldap.matchingrules;
022    
023    
024    
025    import com.unboundid.asn1.ASN1OctetString;
026    import com.unboundid.ldap.sdk.LDAPException;
027    import com.unboundid.ldap.sdk.ResultCode;
028    
029    import static com.unboundid.ldap.matchingrules.MatchingRuleMessages.*;
030    import static com.unboundid.util.StaticUtils.*;
031    
032    
033    
034    /**
035     * This class provides an implementation of a matching rule that allows strings
036     * consisting of numeric digits and spaces.  Spaces will be considered
037     * insignificant for matching purposes.
038     */
039    public final class NumericStringMatchingRule
040           extends SimpleMatchingRule
041    {
042      /**
043       * The singleton instance that will be returned from the {@code getInstance}
044       * method.
045       */
046      private static final NumericStringMatchingRule INSTANCE =
047           new NumericStringMatchingRule();
048    
049    
050    
051      /**
052       * The name for the numericStringMatch equality matching rule.
053       */
054      public static final String EQUALITY_RULE_NAME = "numericStringMatch";
055    
056    
057    
058      /**
059       * The name for the numericStringMatch equality matching rule, formatted in
060       * all lowercase characters.
061       */
062      static final String LOWER_EQUALITY_RULE_NAME =
063           toLowerCase(EQUALITY_RULE_NAME);
064    
065    
066    
067      /**
068       * The OID for the numericStringMatch equality matching rule.
069       */
070      public static final String EQUALITY_RULE_OID = "2.5.13.8";
071    
072    
073    
074      /**
075       * The name for the numericStringOrderingMatch ordering matching rule.
076       */
077      public static final String ORDERING_RULE_NAME = "numericStringOrderingMatch";
078    
079    
080    
081      /**
082       * The name for the numericStringOrderingMatch ordering matching rule,
083       * formatted in all lowercase characters.
084       */
085      static final String LOWER_ORDERING_RULE_NAME =
086           toLowerCase(ORDERING_RULE_NAME);
087    
088    
089    
090      /**
091       * The OID for the numericStringOrderingMatch ordering matching rule.
092       */
093      public static final String ORDERING_RULE_OID = "2.5.13.9";
094    
095    
096    
097      /**
098       * The name for the numericStringSubstringsMatch substring matching rule.
099       */
100      public static final String SUBSTRING_RULE_NAME =
101           "numericStringSubstringsMatch";
102    
103    
104    
105      /**
106       * The name for the numericStringSubstringsMatch substring matching rule,
107       * formatted in all lowercase characters.
108       */
109      static final String LOWER_SUBSTRING_RULE_NAME =
110           toLowerCase(SUBSTRING_RULE_NAME);
111    
112    
113    
114      /**
115       * The OID for the numericStringSubstringsMatch substring matching rule.
116       */
117      public static final String SUBSTRING_RULE_OID = "2.5.13.10";
118    
119    
120    
121      /**
122       * The serial version UID for this serializable class.
123       */
124      private static final long serialVersionUID = -898484312052746321L;
125    
126    
127    
128      /**
129       * Creates a new instance of this numeric string matching rule.
130       */
131      public NumericStringMatchingRule()
132      {
133        // No implementation is required.
134      }
135    
136    
137    
138      /**
139       * Retrieves a singleton instance of this matching rule.
140       *
141       * @return  A singleton instance of this matching rule.
142       */
143      public static NumericStringMatchingRule getInstance()
144      {
145        return INSTANCE;
146      }
147    
148    
149    
150      /**
151       * {@inheritDoc}
152       */
153      @Override()
154      public String getEqualityMatchingRuleName()
155      {
156        return EQUALITY_RULE_NAME;
157      }
158    
159    
160    
161      /**
162       * {@inheritDoc}
163       */
164      @Override()
165      public String getEqualityMatchingRuleOID()
166      {
167        return EQUALITY_RULE_OID;
168      }
169    
170    
171    
172      /**
173       * {@inheritDoc}
174       */
175      @Override()
176      public String getOrderingMatchingRuleName()
177      {
178        return ORDERING_RULE_NAME;
179      }
180    
181    
182    
183      /**
184       * {@inheritDoc}
185       */
186      @Override()
187      public String getOrderingMatchingRuleOID()
188      {
189        return ORDERING_RULE_OID;
190      }
191    
192    
193    
194      /**
195       * {@inheritDoc}
196       */
197      @Override()
198      public String getSubstringMatchingRuleName()
199      {
200        return SUBSTRING_RULE_NAME;
201      }
202    
203    
204    
205      /**
206       * {@inheritDoc}
207       */
208      @Override()
209      public String getSubstringMatchingRuleOID()
210      {
211        return SUBSTRING_RULE_OID;
212      }
213    
214    
215    
216      /**
217       * {@inheritDoc}
218       */
219      @Override()
220      public ASN1OctetString normalize(final ASN1OctetString value)
221             throws LDAPException
222      {
223        // The value may already be normalized, so optimize behavior for that
224        // possibility.
225        int numSpaces = 0;
226        final byte[] valueBytes = value.getValue();
227        for (int i=0; i < valueBytes.length; i++)
228        {
229          if (valueBytes[i] == ' ')
230          {
231            numSpaces++;
232          }
233          else if ((valueBytes[i] < '0') || (valueBytes[i] > '9'))
234          {
235            throw new LDAPException(ResultCode.INVALID_ATTRIBUTE_SYNTAX,
236                                    ERR_NUMERIC_STRING_INVALID_CHARACTER.get(i));
237          }
238        }
239    
240        if (numSpaces == 0)
241        {
242          return value;
243        }
244    
245        int pos = 0;
246        final byte[] returnBytes = new byte[valueBytes.length-numSpaces];
247        for (final byte b : valueBytes)
248        {
249          if (b != ' ')
250          {
251            returnBytes[pos++] = b;
252          }
253        }
254    
255        return new ASN1OctetString(returnBytes);
256      }
257    
258    
259    
260      /**
261       * {@inheritDoc}
262       */
263      @Override()
264      public ASN1OctetString normalizeSubstring(final ASN1OctetString value,
265                                                final byte substringType)
266             throws LDAPException
267      {
268        return normalize(value);
269      }
270    }