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