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   *    http://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.ldap.model.schema.LdapComparator;
24  import org.apache.directory.api.util.Strings;
25  import org.slf4j.Logger;
26  import org.slf4j.LoggerFactory;
27  
28  
29  /**
30   * <p>
31   * A comparator for Words/KeyWords. RFC 4517 par. 4.2.21 (KeywordMatch) and par.
32   * 4.2.32 is pretty vague about the definition of what is a word or a keyword
33   * ("...The precise definition of a word is implementation specific...)
34   * ("...The identification of keywords in the attribute value and the exactness
35   *  of the match are both implementation specific...).
36   * <p>
37   * We will simply check that the assertion is present in the value at some place,
38   * after having deep trimmed the word.
39   * <p>
40   * For instance, the word "  World  " will be found in the value "Hello world!".
41   * <p>
42   * A word is defined by the following regexp : "(^|[^A-Za-z0-9])([A-Za-z0-9])*([^A-Za-z0-9]|$)".
43   * Anything that is not matched by this regexp will not be considered as a word.
44   * 
45   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
46   */
47  public class WordComparator extends LdapComparator<String>
48  {
49      /** The serial version UID */
50      private static final long serialVersionUID = 2L;
51  
52      /** A logger for this class */
53      private static final Logger LOG = LoggerFactory.getLogger( WordComparator.class );
54  
55  
56      /**
57       * The StringComparator constructor. Its OID is the StringMatch matching
58       * rule OID.
59       * 
60       * @param oid The Comparator's OID
61       */
62      public WordComparator( String oid )
63      {
64          super( oid );
65      }
66  
67  
68      /**
69       * {@inheritDoc}
70       */
71      public int compare( String value, String assertion )
72      {
73          LOG.debug( "comparing String objects '{}' with '{}'", value, assertion );
74  
75          if ( value == assertion )
76          {
77              return 0;
78          }
79  
80          // -------------------------------------------------------------------
81          // Handle some basis cases
82          // -------------------------------------------------------------------
83          if ( ( value == null ) || ( assertion == null ) )
84          {
85              return ( assertion == null ) ? 1 : -1;
86          }
87  
88          // Now, trim the assertion and find it in the value
89          String trimmedAssertion = Strings.trim( assertion );
90          int pos = value.indexOf( trimmedAssertion );
91  
92          if ( pos != -1 )
93          {
94              int assertionLength = trimmedAssertion.length();
95  
96              // Check that we are not in a middle of some text
97              if ( assertionLength == value.length() )
98              {
99                  return 0;
100             }
101 
102             if ( pos == 0 )
103             {
104                 char after = value.charAt( assertionLength );
105 
106                 if ( !Character.isLetterOrDigit( after ) )
107                 {
108                     return 0;
109                 }
110                 else
111                 {
112                     return -1;
113                 }
114             }
115 
116             if ( pos + assertionLength == value.length() )
117             {
118                 char before = value.charAt( value.length() - assertionLength - 1 );
119 
120                 if ( !Character.isLetterOrDigit( before ) )
121                 {
122                     return 0;
123                 }
124                 else
125                 {
126                     return -1;
127                 }
128             }
129 
130             char before = value.charAt( value.length() - assertionLength );
131             char after = value.charAt( assertionLength );
132 
133             if ( Character.isLetterOrDigit( after ) )
134             {
135                 return -1;
136             }
137 
138             if ( !Character.isLetterOrDigit( before ) )
139             {
140                 return -1;
141             }
142 
143             return 0;
144         }
145 
146         return -1;
147     }
148 }