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.AttributeSyntaxCfg;
033 import org.opends.server.api.ApproximateMatchingRule;
034 import org.opends.server.api.AttributeSyntax;
035 import org.opends.server.api.AttributeValueDecoder;
036 import org.opends.server.api.EqualityMatchingRule;
037 import org.opends.server.api.OrderingMatchingRule;
038 import org.opends.server.api.SubstringMatchingRule;
039 import org.opends.server.config.ConfigException;
040 import org.opends.server.core.DirectoryServer;
041 import org.opends.server.types.AttributeValue;
042 import org.opends.server.types.ByteString;
043 import org.opends.server.types.DirectoryException;
044
045
046 import org.opends.server.types.ResultCode;
047
048 import static org.opends.server.loggers.ErrorLogger.*;
049 import static org.opends.messages.SchemaMessages.*;
050 import org.opends.messages.MessageBuilder;
051 import static org.opends.server.schema.SchemaConstants.*;
052
053
054 /**
055 * This class defines the integer attribute syntax, which holds an
056 * arbitrarily-long integer value. Equality, ordering, and substring matching
057 * will be allowed by default.
058 */
059 public class IntegerSyntax
060 extends AttributeSyntax<AttributeSyntaxCfg>
061 {
062 // The default equality matching rule for this syntax.
063 private EqualityMatchingRule defaultEqualityMatchingRule;
064
065 // The default ordering matching rule for this syntax.
066 private OrderingMatchingRule defaultOrderingMatchingRule;
067
068 // The default substring matching rule for this syntax.
069 private SubstringMatchingRule defaultSubstringMatchingRule;
070
071
072
073 /**
074 * An {@link Integer} attribute value decoder for this syntax.
075 */
076 public static final AttributeValueDecoder<Integer> DECODER =
077 new AttributeValueDecoder<Integer>()
078 {
079 /**
080 * {@inheritDoc}
081 */
082 public Integer decode(AttributeValue value) throws DirectoryException
083 {
084 ByteString nvalue = value.getNormalizedValue();
085 try
086 {
087 return Integer.valueOf(nvalue.stringValue());
088 }
089 catch (NumberFormatException e)
090 {
091 Message message =
092 WARN_ATTR_SYNTAX_ILLEGAL_INTEGER.get(nvalue.stringValue());
093 throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX,
094 message);
095 }
096 }
097 };
098
099
100
101 /**
102 * Creates a new instance of this syntax. Note that the only thing
103 * that should be done here is to invoke the default constructor for
104 * the superclass. All initialization should be performed in the
105 * <CODE>initializeSyntax</CODE> method.
106 */
107 public IntegerSyntax()
108 {
109 super();
110 }
111
112
113
114 /**
115 * {@inheritDoc}
116 */
117 public void initializeSyntax(AttributeSyntaxCfg configuration)
118 throws ConfigException
119 {
120 defaultEqualityMatchingRule =
121 DirectoryServer.getEqualityMatchingRule(EMR_INTEGER_OID);
122 if (defaultEqualityMatchingRule == null)
123 {
124 logError(ERR_ATTR_SYNTAX_UNKNOWN_EQUALITY_MATCHING_RULE.get(
125 EMR_INTEGER_OID, SYNTAX_INTEGER_NAME));
126 }
127
128 defaultOrderingMatchingRule =
129 DirectoryServer.getOrderingMatchingRule(OMR_INTEGER_OID);
130 if (defaultOrderingMatchingRule == null)
131 {
132 logError(ERR_ATTR_SYNTAX_UNKNOWN_ORDERING_MATCHING_RULE.get(
133 OMR_INTEGER_OID, SYNTAX_INTEGER_NAME));
134 }
135
136 defaultSubstringMatchingRule =
137 DirectoryServer.getSubstringMatchingRule(SMR_CASE_EXACT_OID);
138 if (defaultSubstringMatchingRule == null)
139 {
140 logError(ERR_ATTR_SYNTAX_UNKNOWN_SUBSTRING_MATCHING_RULE.get(
141 SMR_CASE_EXACT_OID, SYNTAX_INTEGER_NAME));
142 }
143 }
144
145
146
147 /**
148 * Retrieves the common name for this attribute syntax.
149 *
150 * @return The common name for this attribute syntax.
151 */
152 public String getSyntaxName()
153 {
154 return SYNTAX_INTEGER_NAME;
155 }
156
157
158
159 /**
160 * Retrieves the OID for this attribute syntax.
161 *
162 * @return The OID for this attribute syntax.
163 */
164 public String getOID()
165 {
166 return SYNTAX_INTEGER_OID;
167 }
168
169
170
171 /**
172 * Retrieves a description for this attribute syntax.
173 *
174 * @return A description for this attribute syntax.
175 */
176 public String getDescription()
177 {
178 return SYNTAX_INTEGER_DESCRIPTION;
179 }
180
181
182
183 /**
184 * Retrieves the default equality matching rule that will be used for
185 * attributes with this syntax.
186 *
187 * @return The default equality matching rule that will be used for
188 * attributes with this syntax, or <CODE>null</CODE> if equality
189 * matches will not be allowed for this type by default.
190 */
191 public EqualityMatchingRule getEqualityMatchingRule()
192 {
193 return defaultEqualityMatchingRule;
194 }
195
196
197
198 /**
199 * Retrieves the default ordering matching rule that will be used for
200 * attributes with this syntax.
201 *
202 * @return The default ordering matching rule that will be used for
203 * attributes with this syntax, or <CODE>null</CODE> if ordering
204 * matches will not be allowed for this type by default.
205 */
206 public OrderingMatchingRule getOrderingMatchingRule()
207 {
208 return defaultOrderingMatchingRule;
209 }
210
211
212
213 /**
214 * Retrieves the default substring matching rule that will be used for
215 * attributes with this syntax.
216 *
217 * @return The default substring matching rule that will be used for
218 * attributes with this syntax, or <CODE>null</CODE> if substring
219 * matches will not be allowed for this type by default.
220 */
221 public SubstringMatchingRule getSubstringMatchingRule()
222 {
223 return defaultSubstringMatchingRule;
224 }
225
226
227
228 /**
229 * Retrieves the default approximate matching rule that will be used for
230 * attributes with this syntax.
231 *
232 * @return The default approximate matching rule that will be used for
233 * attributes with this syntax, or <CODE>null</CODE> if approximate
234 * matches will not be allowed for this type by default.
235 */
236 public ApproximateMatchingRule getApproximateMatchingRule()
237 {
238 // There is no approximate matching rule by default.
239 return null;
240 }
241
242
243
244 /**
245 * Indicates whether the provided value is acceptable for use in an attribute
246 * with this syntax. If it is not, then the reason may be appended to the
247 * provided buffer.
248 *
249 * @param value The value for which to make the determination.
250 * @param invalidReason The buffer to which the invalid reason should be
251 * appended.
252 *
253 * @return <CODE>true</CODE> if the provided value is acceptable for use with
254 * this syntax, or <CODE>false</CODE> if not.
255 */
256 public boolean valueIsAcceptable(ByteString value,
257 MessageBuilder invalidReason)
258 {
259 String valueString = value.stringValue();
260 int length = valueString.length();
261
262 if (length == 0)
263 {
264 invalidReason.append(
265 WARN_ATTR_SYNTAX_INTEGER_EMPTY_VALUE.get(valueString));
266 return false;
267 }
268 else if (length == 1)
269 {
270 switch (valueString.charAt(0))
271 {
272 case '0':
273 case '1':
274 case '2':
275 case '3':
276 case '4':
277 case '5':
278 case '6':
279 case '7':
280 case '8':
281 case '9':
282 return true;
283 case '-':
284 invalidReason.append(WARN_ATTR_SYNTAX_INTEGER_DASH_NEEDS_VALUE.get(
285 valueString));
286 return false;
287 default:
288 invalidReason.append(WARN_ATTR_SYNTAX_INTEGER_INVALID_CHARACTER.get(
289 valueString,
290 valueString.charAt(0), 0));
291 return false;
292 }
293 }
294 else
295 {
296 boolean negative = false;
297
298 switch (valueString.charAt(0))
299 {
300 case '0':
301 invalidReason.append(WARN_ATTR_SYNTAX_INTEGER_INITIAL_ZERO.get(
302 valueString));
303 return false;
304 case '1':
305 case '2':
306 case '3':
307 case '4':
308 case '5':
309 case '6':
310 case '7':
311 case '8':
312 case '9':
313 // These are all fine.
314 break;
315 case '-':
316 // This is fine too.
317 negative = true;
318 break;
319 default:
320 invalidReason.append(WARN_ATTR_SYNTAX_INTEGER_INVALID_CHARACTER.get(
321 valueString,
322 valueString.charAt(0), 0));
323 return false;
324 }
325
326 switch (valueString.charAt(1))
327 {
328 case '0':
329 // This is fine as long as the value isn't negative.
330 if (negative)
331 {
332 invalidReason.append(WARN_ATTR_SYNTAX_INTEGER_INITIAL_ZERO.get(
333 valueString));
334 return false;
335 }
336 break;
337 case '1':
338 case '2':
339 case '3':
340 case '4':
341 case '5':
342 case '6':
343 case '7':
344 case '8':
345 case '9':
346 // These are all fine.
347 break;
348 default:
349 invalidReason.append(WARN_ATTR_SYNTAX_INTEGER_INVALID_CHARACTER.get(
350 valueString,
351 valueString.charAt(0), 0));
352 return false;
353 }
354
355 for (int i=2; i < length; i++)
356 {
357 switch (valueString.charAt(i))
358 {
359 case '0':
360 case '1':
361 case '2':
362 case '3':
363 case '4':
364 case '5':
365 case '6':
366 case '7':
367 case '8':
368 case '9':
369 // These are all fine.
370 break;
371 default:
372 invalidReason.append(WARN_ATTR_SYNTAX_INTEGER_INVALID_CHARACTER.get(
373 valueString,
374 valueString.charAt(0), 0));
375 return false;
376 }
377 }
378
379 return true;
380 }
381 }
382 }
383