001 /* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at 010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE 011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE. 012 * See the License for the specific language governing permissions 013 * and limitations under the License. 014 * 015 * When distributing Covered Code, include this CDDL HEADER in each 016 * file and include the License file at 017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, 018 * add the following below this CDDL HEADER, with the fields enclosed 019 * by brackets "[]" replaced with your own identifying information: 020 * Portions Copyright [yyyy] [name of copyright owner] 021 * 022 * CDDL HEADER END 023 * 024 * 025 * Copyright 2006-2008 Sun Microsystems, Inc. 026 */ 027 package org.opends.server.schema; 028 import org.opends.messages.Message; 029 030 031 032 import org.opends.server.admin.std.server.OrderingMatchingRuleCfg; 033 import org.opends.server.api.OrderingMatchingRule; 034 import org.opends.server.config.ConfigException; 035 import org.opends.server.core.DirectoryServer; 036 import org.opends.server.protocols.asn1.ASN1OctetString; 037 import org.opends.server.types.ByteString; 038 import org.opends.server.types.DirectoryException; 039 import org.opends.server.types.InitializationException; 040 import org.opends.server.types.ResultCode; 041 042 import static org.opends.messages.SchemaMessages.*; 043 import static org.opends.server.schema.SchemaConstants.*; 044 import static org.opends.server.util.StaticUtils.*; 045 import org.opends.server.loggers.ErrorLogger; 046 047 048 /** 049 * This implements defines the numericStringOrderingMatch matching rule defined 050 * in X.520 and referenced in RFC 2252. 051 */ 052 public class NumericStringOrderingMatchingRule 053 extends OrderingMatchingRule 054 { 055 /** 056 * The serial version identifier required to satisfy the compiler because this 057 * class implements the <CODE>java.io.Serializable</CODE> interface. This 058 * value was generated using the <CODE>serialver</CODE> command-line utility 059 * included with the Java SDK. 060 */ 061 private static final long serialVersionUID = 388436004219363604L; 062 063 064 065 /** 066 * Creates a new instance of this numericStringOrderingMatch matching rule. 067 */ 068 public NumericStringOrderingMatchingRule() 069 { 070 super(); 071 } 072 073 074 075 /** 076 * {@inheritDoc} 077 */ 078 public void initializeMatchingRule(OrderingMatchingRuleCfg configuration) 079 throws ConfigException, InitializationException 080 { 081 // No initialization is required. 082 } 083 084 085 086 /** 087 * Retrieves the common name for this matching rule. 088 * 089 * @return The common name for this matching rule, or <CODE>null</CODE> if 090 * it does not have a name. 091 */ 092 public String getName() 093 { 094 return OMR_NUMERIC_STRING_NAME; 095 } 096 097 098 099 /** 100 * Retrieves the OID for this matching rule. 101 * 102 * @return The OID for this matching rule. 103 */ 104 public String getOID() 105 { 106 return OMR_NUMERIC_STRING_OID; 107 } 108 109 110 111 /** 112 * Retrieves the description for this matching rule. 113 * 114 * @return The description for this matching rule, or <CODE>null</CODE> if 115 * there is none. 116 */ 117 public String getDescription() 118 { 119 // There is no standard description for this matching rule. 120 return null; 121 } 122 123 124 125 /** 126 * Retrieves the OID of the syntax with which this matching rule is 127 * associated. 128 * 129 * @return The OID of the syntax with which this matching rule is associated. 130 */ 131 public String getSyntaxOID() 132 { 133 return SYNTAX_NUMERIC_STRING_OID; 134 } 135 136 137 138 /** 139 * Retrieves the normalized form of the provided value, which is best suited 140 * for efficiently performing matching operations on that value. 141 * 142 * @param value The value to be normalized. 143 * 144 * @return The normalized version of the provided value. 145 * 146 * @throws DirectoryException If the provided value is invalid according to 147 * the associated attribute syntax. 148 */ 149 public ByteString normalizeValue(ByteString value) 150 throws DirectoryException 151 { 152 String valueString = value.stringValue(); 153 int valueLength = valueString.length(); 154 StringBuilder valueBuffer = new StringBuilder(valueLength); 155 156 boolean logged = false; 157 for (int i=0; i < valueLength; i++) 158 { 159 char c = valueString.charAt(i); 160 if (isDigit(c)) 161 { 162 valueBuffer.append(c); 163 } 164 else if (c != ' ') 165 { 166 // This is an illegal character. Either log it or reject it. 167 168 Message message = WARN_ATTR_SYNTAX_NUMERIC_STRING_ILLEGAL_CHAR.get( 169 valueString, String.valueOf(c), i); 170 171 switch (DirectoryServer.getSyntaxEnforcementPolicy()) 172 { 173 case REJECT: 174 throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX, 175 message); 176 case WARN: 177 if (! logged) 178 { 179 ErrorLogger.logError(message); 180 logged = true; 181 } 182 } 183 } 184 } 185 186 return new ASN1OctetString(getBytes(valueBuffer.toString())); 187 } 188 189 190 191 /** 192 * Compares the first value to the second and returns a value that indicates 193 * their relative order. 194 * 195 * @param value1 The normalized form of the first value to compare. 196 * @param value2 The normalized form of the second value to compare. 197 * 198 * @return A negative integer if <CODE>value1</CODE> should come before 199 * <CODE>value2</CODE> in ascending order, a positive integer if 200 * <CODE>value1</CODE> should come after <CODE>value2</CODE> in 201 * ascending order, or zero if there is no difference between the 202 * values with regard to ordering. 203 */ 204 public int compareValues(ByteString value1, ByteString value2) 205 { 206 return compare(value1.value(), value2.value()); 207 } 208 209 210 211 /** 212 * Compares the contents of the provided byte arrays to determine their 213 * relative order. 214 * 215 * @param b1 The first byte array to use in the comparison. 216 * @param b2 The second byte array to use in the comparison. 217 * 218 * @return A negative integer if <CODE>b1</CODE> should come before 219 * <CODE>b2</CODE> in ascending order, a positive integer if 220 * <CODE>b1</CODE> should come after <CODE>b2</CODE> in ascending 221 * order, or zero if there is no difference between the values with 222 * regard to ordering. 223 */ 224 public int compare(byte[] b1, byte[] b2) 225 { 226 int minLength = Math.min(b1.length, b2.length); 227 228 for (int i=0; i < minLength; i++) 229 { 230 if (b1[i] == b2[i]) 231 { 232 continue; 233 } 234 else if (b1[i] < b2[i]) 235 { 236 return -1; 237 } 238 else if (b1[i] > b2[i]) 239 { 240 return 1; 241 } 242 } 243 244 if (b1.length == b2.length) 245 { 246 return 0; 247 } 248 else if (b1.length < b2.length) 249 { 250 return -1; 251 } 252 else 253 { 254 return 1; 255 } 256 } 257 } 258