001    /*
002     * Copyright 2008-2016 UnboundID Corp.
003     * All Rights Reserved.
004     */
005    /*
006     * Copyright (C) 2008-2016 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    import com.unboundid.util.ThreadSafety;
029    import com.unboundid.util.ThreadSafetyLevel;
030    
031    import static com.unboundid.ldap.matchingrules.MatchingRuleMessages.*;
032    import static com.unboundid.util.StaticUtils.*;
033    
034    
035    
036    /**
037     * This class provides an implementation of a matching rule that may be used for
038     * telephone numbers.  It will accept values with any ASCII printable character.
039     * When making comparisons, spaces and dashes will be ignored.
040     */
041    @ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
042    public final class TelephoneNumberMatchingRule
043           extends SimpleMatchingRule
044    {
045      /**
046       * The singleton instance that will be returned from the {@code getInstance}
047       * method.
048       */
049      private static final TelephoneNumberMatchingRule INSTANCE =
050           new TelephoneNumberMatchingRule();
051    
052    
053    
054      /**
055       * The name for the telephoneNumberMatch equality matching rule.
056       */
057      public static final String EQUALITY_RULE_NAME = "telephoneNumberMatch";
058    
059    
060    
061      /**
062       * The name for the telephoneNumberMatch equality matching rule, formatted in
063       * all lowercase characters.
064       */
065      static final String LOWER_EQUALITY_RULE_NAME =
066           toLowerCase(EQUALITY_RULE_NAME);
067    
068    
069    
070      /**
071       * The OID for the telephoneNumberMatch equality matching rule.
072       */
073      public static final String EQUALITY_RULE_OID = "2.5.13.20";
074    
075    
076    
077      /**
078       * The name for the telephoneNumberSubstringsMatch substring matching rule.
079       */
080      public static final String SUBSTRING_RULE_NAME =
081           "telephoneNumberSubstringsMatch";
082    
083    
084    
085      /**
086       * The name for the telephoneNumberSubstringsMatch substring matching rule,
087       * formatted in all lowercase characters.
088       */
089      static final String LOWER_SUBSTRING_RULE_NAME =
090           toLowerCase(SUBSTRING_RULE_NAME);
091    
092    
093    
094      /**
095       * The OID for the telephoneNumberSubstringsMatch substring matching rule.
096       */
097      public static final String SUBSTRING_RULE_OID = "2.5.13.21";
098    
099    
100    
101      /**
102       * The serial version UID for this serializable class.
103       */
104      private static final long serialVersionUID = -5463096544849211252L;
105    
106    
107    
108      /**
109       * Creates a new instance of this telephone number matching rule.
110       */
111      public TelephoneNumberMatchingRule()
112      {
113        // No implementation is required.
114      }
115    
116    
117    
118      /**
119       * Retrieves a singleton instance of this matching rule.
120       *
121       * @return  A singleton instance of this matching rule.
122       */
123      public static TelephoneNumberMatchingRule getInstance()
124      {
125        return INSTANCE;
126      }
127    
128    
129    
130      /**
131       * {@inheritDoc}
132       */
133      @Override()
134      public String getEqualityMatchingRuleName()
135      {
136        return EQUALITY_RULE_NAME;
137      }
138    
139    
140    
141      /**
142       * {@inheritDoc}
143       */
144      @Override()
145      public String getEqualityMatchingRuleOID()
146      {
147        return EQUALITY_RULE_OID;
148      }
149    
150    
151    
152      /**
153       * {@inheritDoc}
154       */
155      @Override()
156      public String getOrderingMatchingRuleName()
157      {
158        return null;
159      }
160    
161    
162    
163      /**
164       * {@inheritDoc}
165       */
166      @Override()
167      public String getOrderingMatchingRuleOID()
168      {
169        return null;
170      }
171    
172    
173    
174      /**
175       * {@inheritDoc}
176       */
177      @Override()
178      public String getSubstringMatchingRuleName()
179      {
180        return SUBSTRING_RULE_NAME;
181      }
182    
183    
184    
185      /**
186       * {@inheritDoc}
187       */
188      @Override()
189      public String getSubstringMatchingRuleOID()
190      {
191        return SUBSTRING_RULE_OID;
192      }
193    
194    
195    
196      /**
197       * {@inheritDoc}
198       */
199      @Override()
200      public int compareValues(final ASN1OctetString value1,
201                               final ASN1OctetString value2)
202             throws LDAPException
203      {
204        throw new LDAPException(ResultCode.INAPPROPRIATE_MATCHING,
205             ERR_TELEPHONE_NUMBER_ORDERING_MATCHING_NOT_SUPPORTED.get());
206      }
207    
208    
209    
210      /**
211       * {@inheritDoc}
212       */
213      @Override()
214      public ASN1OctetString normalize(final ASN1OctetString value)
215             throws LDAPException
216      {
217        final byte[] valueBytes = value.getValue();
218        final StringBuilder buffer = new StringBuilder();
219        for (int i=0; i < valueBytes.length; i++)
220        {
221          switch (valueBytes[i])
222          {
223            case ' ':
224            case '-':
225              // These should be ignored.
226              break;
227    
228            case '\'':
229            case '(':
230            case ')':
231            case '+':
232            case ',':
233            case '.':
234            case '=':
235            case '/':
236            case ':':
237            case '?':
238              // These should be retained.
239              buffer.append((char) valueBytes[i]);
240              break;
241    
242            default:
243              final byte b = valueBytes[i];
244              if (((b >= '0') && (b <= '9')) ||
245                  ((b >= 'a') && (b <= 'z')) ||
246                  ((b >= 'A') && (b <= 'Z')))
247              {
248                // These should be retained.
249                buffer.append((char) valueBytes[i]);
250                break;
251              }
252    
253              throw new LDAPException(ResultCode.INVALID_ATTRIBUTE_SYNTAX,
254                   ERR_TELEPHONE_NUMBER_INVALID_CHARACTER.get(i));
255          }
256        }
257    
258        return new ASN1OctetString(buffer.toString());
259      }
260    
261    
262    
263      /**
264       * {@inheritDoc}
265       */
266      @Override()
267      public ASN1OctetString normalizeSubstring(final ASN1OctetString value,
268                                                final byte substringType)
269             throws LDAPException
270      {
271        return normalize(value);
272      }
273    }