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
029
030
031 import java.util.HashSet;
032
033 import org.opends.server.admin.std.server.AttributeSyntaxCfg;
034 import org.opends.server.api.ApproximateMatchingRule;
035 import org.opends.server.api.AttributeSyntax;
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.ByteString;
042
043
044
045 import static org.opends.server.loggers.ErrorLogger.*;
046 import static org.opends.messages.SchemaMessages.*;
047 import org.opends.messages.MessageBuilder;
048 import static org.opends.server.schema.SchemaConstants.*;
049 import static org.opends.server.util.StaticUtils.*;
050
051
052
053 /**
054 * This class implements the facsimile telephone number attribute syntax, which
055 * contains a printable string (the number) followed by zero or more parameters.
056 * Those parameters should start with a dollar sign may be any of the following
057 * strings:
058 * <UL>
059 * <LI>twoDimensional</LI>
060 * <LI>fineResolution</LI>
061 * <LI>unlimitedLength</LI>
062 * <LI>b4Length</LI>
063 * <LI>a3Width</LI>
064 * <LI>b4Width</LI>
065 * <LI>uncompressed</LI>
066 * </UL>
067 */
068 public class FaxNumberSyntax
069 extends AttributeSyntax<AttributeSyntaxCfg>
070 {
071 /**
072 * The set of allowed fax parameter values, formatted entirely in lowercase
073 * characters.
074 */
075 public static final HashSet<String> ALLOWED_FAX_PARAMETERS =
076 new HashSet<String>(7);
077
078 static
079 {
080 ALLOWED_FAX_PARAMETERS.add("twodimensional");
081 ALLOWED_FAX_PARAMETERS.add("fineresolution");
082 ALLOWED_FAX_PARAMETERS.add("unlimitedlength");
083 ALLOWED_FAX_PARAMETERS.add("b4length");
084 ALLOWED_FAX_PARAMETERS.add("a3width");
085 ALLOWED_FAX_PARAMETERS.add("b4width");
086 ALLOWED_FAX_PARAMETERS.add("uncompressed");
087 }
088
089
090
091 // The default equality matching rule for this syntax.
092 private EqualityMatchingRule defaultEqualityMatchingRule;
093
094 // The default ordering matching rule for this syntax.
095 private OrderingMatchingRule defaultOrderingMatchingRule;
096
097 // The default substring matching rule for this syntax.
098 private SubstringMatchingRule defaultSubstringMatchingRule;
099
100
101
102 /**
103 * Creates a new instance of this syntax. Note that the only thing that
104 * should be done here is to invoke the default constructor for the
105 * superclass. All initialization should be performed in the
106 * <CODE>initializeSyntax</CODE> method.
107 */
108 public FaxNumberSyntax()
109 {
110 super();
111 }
112
113
114
115 /**
116 * {@inheritDoc}
117 */
118 public void initializeSyntax(AttributeSyntaxCfg configuration)
119 throws ConfigException
120 {
121 defaultEqualityMatchingRule =
122 DirectoryServer.getEqualityMatchingRule(EMR_CASE_IGNORE_OID);
123 if (defaultEqualityMatchingRule == null)
124 {
125 logError(ERR_ATTR_SYNTAX_UNKNOWN_EQUALITY_MATCHING_RULE.get(
126 EMR_CASE_IGNORE_OID, SYNTAX_FAXNUMBER_NAME));
127 }
128
129 defaultOrderingMatchingRule =
130 DirectoryServer.getOrderingMatchingRule(OMR_CASE_IGNORE_OID);
131 if (defaultOrderingMatchingRule == null)
132 {
133 logError(ERR_ATTR_SYNTAX_UNKNOWN_ORDERING_MATCHING_RULE.get(
134 OMR_CASE_IGNORE_OID, SYNTAX_FAXNUMBER_NAME));
135 }
136
137 defaultSubstringMatchingRule =
138 DirectoryServer.getSubstringMatchingRule(SMR_CASE_IGNORE_OID);
139 if (defaultSubstringMatchingRule == null)
140 {
141 logError(ERR_ATTR_SYNTAX_UNKNOWN_SUBSTRING_MATCHING_RULE.get(
142 SMR_CASE_IGNORE_OID, SYNTAX_FAXNUMBER_NAME));
143 }
144 }
145
146
147
148 /**
149 * Retrieves the common name for this attribute syntax.
150 *
151 * @return The common name for this attribute syntax.
152 */
153 public String getSyntaxName()
154 {
155 return SYNTAX_FAXNUMBER_NAME;
156 }
157
158
159
160 /**
161 * Retrieves the OID for this attribute syntax.
162 *
163 * @return The OID for this attribute syntax.
164 */
165 public String getOID()
166 {
167 return SYNTAX_FAXNUMBER_OID;
168 }
169
170
171
172 /**
173 * Retrieves a description for this attribute syntax.
174 *
175 * @return A description for this attribute syntax.
176 */
177 public String getDescription()
178 {
179 return SYNTAX_FAXNUMBER_DESCRIPTION;
180 }
181
182
183
184 /**
185 * Retrieves the default equality matching rule that will be used for
186 * attributes with this syntax.
187 *
188 * @return The default equality matching rule that will be used for
189 * attributes with this syntax, or <CODE>null</CODE> if equality
190 * matches will not be allowed for this type by default.
191 */
192 public EqualityMatchingRule getEqualityMatchingRule()
193 {
194 return defaultEqualityMatchingRule;
195 }
196
197
198
199 /**
200 * Retrieves the default ordering matching rule that will be used for
201 * attributes with this syntax.
202 *
203 * @return The default ordering matching rule that will be used for
204 * attributes with this syntax, or <CODE>null</CODE> if ordering
205 * matches will not be allowed for this type by default.
206 */
207 public OrderingMatchingRule getOrderingMatchingRule()
208 {
209 return defaultOrderingMatchingRule;
210 }
211
212
213
214 /**
215 * Retrieves the default substring matching rule that will be used for
216 * attributes with this syntax.
217 *
218 * @return The default substring matching rule that will be used for
219 * attributes with this syntax, or <CODE>null</CODE> if substring
220 * matches will not be allowed for this type by default.
221 */
222 public SubstringMatchingRule getSubstringMatchingRule()
223 {
224 return defaultSubstringMatchingRule;
225 }
226
227
228
229 /**
230 * Retrieves the default approximate matching rule that will be used for
231 * attributes with this syntax.
232 *
233 * @return The default approximate matching rule that will be used for
234 * attributes with this syntax, or <CODE>null</CODE> if approximate
235 * matches will not be allowed for this type by default.
236 */
237 public ApproximateMatchingRule getApproximateMatchingRule()
238 {
239 // There is no approximate matching rule by default.
240 return null;
241 }
242
243
244
245 /**
246 * Indicates whether the provided value is acceptable for use in an attribute
247 * with this syntax. If it is not, then the reason may be appended to the
248 * provided buffer.
249 *
250 * @param value The value for which to make the determination.
251 * @param invalidReason The buffer to which the invalid reason should be
252 * appended.
253 *
254 * @return <CODE>true</CODE> if the provided value is acceptable for use with
255 * this syntax, or <CODE>false</CODE> if not.
256 */
257 public boolean valueIsAcceptable(ByteString value,
258 MessageBuilder invalidReason)
259 {
260 // Get a lowercase string representation of the value and find its length.
261 String valueString = toLowerCase(value.stringValue());
262 int valueLength = valueString.length();
263
264
265 // The value must contain at least one character.
266 if (valueLength == 0)
267 {
268
269 invalidReason.append(ERR_ATTR_SYNTAX_FAXNUMBER_EMPTY.get());
270 return false;
271 }
272
273
274 // The first character must be a printable string character.
275 char c = valueString.charAt(0);
276 if (! PrintableString.isPrintableCharacter(c))
277 {
278
279 invalidReason.append(ERR_ATTR_SYNTAX_FAXNUMBER_NOT_PRINTABLE.get(
280 valueString, String.valueOf(c), 0));
281 return false;
282 }
283
284
285 // Continue reading until we find a dollar sign or the end of the string.
286 // Every intermediate character must be a printable string character.
287 int pos = 1;
288 for ( ; pos < valueLength; pos++)
289 {
290 c = valueString.charAt(pos);
291 if (c == '$')
292 {
293 pos++;
294 break;
295 }
296 else
297 {
298 if (! PrintableString.isPrintableCharacter(c))
299 {
300
301 invalidReason.append(ERR_ATTR_SYNTAX_FAXNUMBER_NOT_PRINTABLE.get(
302 valueString, String.valueOf(c), pos));
303 }
304 }
305 }
306
307 if (pos >= valueLength)
308 {
309 // We're at the end of the value, so it must be valid unless the last
310 // character was a dollar sign.
311 if (c == '$')
312 {
313
314 invalidReason.append(ERR_ATTR_SYNTAX_FAXNUMBER_END_WITH_DOLLAR.get(
315 valueString));
316 return false;
317 }
318 else
319 {
320 return true;
321 }
322 }
323
324
325 // Continue reading until we find the end of the string. Each substring
326 // must be a valid fax parameter.
327 int paramStartPos = pos;
328 while (pos < valueLength)
329 {
330 c = valueString.charAt(pos++);
331 if (c == '$')
332 {
333 String paramStr = valueString.substring(paramStartPos, pos);
334 if (! ALLOWED_FAX_PARAMETERS.contains(paramStr))
335 {
336
337 invalidReason.append(ERR_ATTR_SYNTAX_FAXNUMBER_ILLEGAL_PARAMETER.get(
338 valueString, paramStr, paramStartPos, (pos-1)));
339 return false;
340 }
341
342 paramStartPos = pos;
343 }
344 }
345
346
347 // We must be at the end of the value. Read the last parameter and make
348 // sure it is valid.
349 String paramStr = valueString.substring(paramStartPos);
350 if (! ALLOWED_FAX_PARAMETERS.contains(paramStr))
351 {
352 invalidReason.append(ERR_ATTR_SYNTAX_FAXNUMBER_ILLEGAL_PARAMETER.get(
353 valueString, paramStr, paramStartPos, (pos-1)));
354 return false;
355 }
356
357
358 // If we've gotten here, then the value must be valid.
359 return true;
360 }
361 }
362