View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    * 
10   *    https://www.apache.org/licenses/LICENSE-2.0
11   * 
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License.
18   * 
19   */
20  package org.apache.directory.api.ldap.model.schema.comparators;
21  
22  
23  import org.apache.directory.api.i18n.I18n;
24  import org.apache.directory.api.ldap.model.schema.LdapComparator;
25  import org.apache.directory.api.util.Strings;
26  import org.slf4j.Logger;
27  import org.slf4j.LoggerFactory;
28  
29  
30  /**
31   * <p>
32   * A comparator for Words/KeyWords. RFC 4517 par. 4.2.21 (KeywordMatch) and par.
33   * 4.2.32 is pretty vague about the definition of what is a word or a keyword
34   * ("...The precise definition of a word is implementation specific...)
35   * ("...The identification of keywords in the attribute value and the exactness
36   *  of the match are both implementation specific...).
37   * <p>
38   * We will simply check that the assertion is present in the value at some place,
39   * after having deep trimmed the word.
40   * <p>
41   * For instance, the word "  World  " will be found in the value "Hello world!".
42   * <p>
43   * A word is defined by the following regexp : "(^|[^A-Za-z0-9])([A-Za-z0-9])*([^A-Za-z0-9]|$)".
44   * Anything that is not matched by this regexp will not be considered as a word.
45   * 
46   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
47   */
48  public class WordComparator extends LdapComparator<String>
49  {
50      /** The serial version UID */
51      private static final long serialVersionUID = 2L;
52  
53      /** A logger for this class */
54      private static final Logger LOG = LoggerFactory.getLogger( WordComparator.class );
55  
56  
57      /**
58       * The StringComparator constructor. Its OID is the StringMatch matching
59       * rule OID.
60       * 
61       * @param oid The Comparator's OID
62       */
63      public WordComparator( String oid )
64      {
65          super( oid );
66      }
67  
68  
69      /**
70       * {@inheritDoc}
71       */
72      public int compare( String value, String assertion )
73      {
74          if ( LOG.isDebugEnabled() )
75          {
76              LOG.debug( I18n.msg( I18n.MSG_13749_COMPARING_STRING, value, assertion ) );
77          }
78  
79          if ( value == assertion )
80          {
81              return 0;
82          }
83  
84          // -------------------------------------------------------------------
85          // Handle some basis cases
86          // -------------------------------------------------------------------
87          if ( ( value == null ) || ( assertion == null ) )
88          {
89              return ( assertion == null ) ? 1 : -1;
90          }
91  
92          // Now, trim the assertion and find it in the value
93          String trimmedAssertion = Strings.trim( assertion );
94          int pos = value.indexOf( trimmedAssertion );
95  
96          if ( pos != -1 )
97          {
98              int assertionLength = trimmedAssertion.length();
99  
100             // Check that we are not in a middle of some text
101             if ( assertionLength == value.length() )
102             {
103                 return 0;
104             }
105 
106             if ( pos == 0 )
107             {
108                 char after = value.charAt( assertionLength );
109 
110                 if ( !Character.isLetterOrDigit( after ) )
111                 {
112                     return 0;
113                 }
114                 else
115                 {
116                     return -1;
117                 }
118             }
119 
120             if ( pos + assertionLength == value.length() )
121             {
122                 char before = value.charAt( value.length() - assertionLength - 1 );
123 
124                 if ( !Character.isLetterOrDigit( before ) )
125                 {
126                     return 0;
127                 }
128                 else
129                 {
130                     return -1;
131                 }
132             }
133 
134             char before = value.charAt( value.length() - assertionLength );
135             char after = value.charAt( assertionLength );
136 
137             if ( Character.isLetterOrDigit( after ) )
138             {
139                 return -1;
140             }
141 
142             if ( !Character.isLetterOrDigit( before ) )
143             {
144                 return -1;
145             }
146 
147             return 0;
148         }
149 
150         return -1;
151     }
152 }