001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * https://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020package org.apache.directory.api.ldap.model.schema.comparators; 021 022 023import org.apache.directory.api.i18n.I18n; 024import org.apache.directory.api.ldap.model.schema.LdapComparator; 025import org.apache.directory.api.util.Strings; 026import org.slf4j.Logger; 027import org.slf4j.LoggerFactory; 028 029 030/** 031 * <p> 032 * A comparator for Words/KeyWords. RFC 4517 par. 4.2.21 (KeywordMatch) and par. 033 * 4.2.32 is pretty vague about the definition of what is a word or a keyword 034 * ("...The precise definition of a word is implementation specific...) 035 * ("...The identification of keywords in the attribute value and the exactness 036 * of the match are both implementation specific...). 037 * <p> 038 * We will simply check that the assertion is present in the value at some place, 039 * after having deep trimmed the word. 040 * <p> 041 * For instance, the word " World " will be found in the value "Hello world!". 042 * <p> 043 * A word is defined by the following regexp : "(^|[^A-Za-z0-9])([A-Za-z0-9])*([^A-Za-z0-9]|$)". 044 * Anything that is not matched by this regexp will not be considered as a word. 045 * 046 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 047 */ 048public class WordComparator extends LdapComparator<String> 049{ 050 /** The serial version UID */ 051 private static final long serialVersionUID = 2L; 052 053 /** A logger for this class */ 054 private static final Logger LOG = LoggerFactory.getLogger( WordComparator.class ); 055 056 057 /** 058 * The StringComparator constructor. Its OID is the StringMatch matching 059 * rule OID. 060 * 061 * @param oid The Comparator's OID 062 */ 063 public WordComparator( String oid ) 064 { 065 super( oid ); 066 } 067 068 069 /** 070 * {@inheritDoc} 071 */ 072 public int compare( String value, String assertion ) 073 { 074 if ( LOG.isDebugEnabled() ) 075 { 076 LOG.debug( I18n.msg( I18n.MSG_13749_COMPARING_STRING, value, assertion ) ); 077 } 078 079 if ( value == assertion ) 080 { 081 return 0; 082 } 083 084 // ------------------------------------------------------------------- 085 // Handle some basis cases 086 // ------------------------------------------------------------------- 087 if ( ( value == null ) || ( assertion == null ) ) 088 { 089 return ( assertion == null ) ? 1 : -1; 090 } 091 092 // Now, trim the assertion and find it in the value 093 String trimmedAssertion = Strings.trim( assertion ); 094 int pos = value.indexOf( trimmedAssertion ); 095 096 if ( pos != -1 ) 097 { 098 int assertionLength = trimmedAssertion.length(); 099 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}