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    import static org.opends.server.loggers.debug.DebugLogger.*;
030    import org.opends.server.loggers.debug.DebugTracer;
031    import static org.opends.server.loggers.ErrorLogger.logError;
032    import org.opends.server.types.DebugLogLevel;
033    import static org.opends.messages.SchemaMessages.*;
034    import org.opends.messages.MessageBuilder;
035    import static org.opends.server.schema.SchemaConstants.*;
036    
037    import org.opends.server.admin.std.server.AttributeSyntaxCfg;
038    import org.opends.server.api.ApproximateMatchingRule;
039    import org.opends.server.api.AttributeSyntax;
040    import org.opends.server.api.AttributeValueDecoder;
041    import org.opends.server.api.EqualityMatchingRule;
042    import org.opends.server.api.OrderingMatchingRule;
043    import org.opends.server.api.SubstringMatchingRule;
044    import org.opends.server.config.ConfigException;
045    import org.opends.server.core.DirectoryServer;
046    import org.opends.server.core.RFC3672SubtreeSpecification;
047    import org.opends.server.types.AttributeValue;
048    import org.opends.server.types.ByteString;
049    import org.opends.server.types.DirectoryException;
050    import org.opends.server.types.DN;
051    
052    
053    
054    /**
055     * This class defines the subtree specification attribute syntax, which
056     * is used to specify the scope of sub-entries (RFC 3672). Equality will
057     * be allowed eventually, although it's not implemented yet.
058     */
059    public final class RFC3672SubtreeSpecificationSyntax
060           extends AttributeSyntax<AttributeSyntaxCfg>
061    {
062      /**
063       * The tracer object for the debug logger.
064       */
065      private static final DebugTracer TRACER = getTracer();
066    
067    
068    
069      // The default equality matching rule for this syntax.
070      private EqualityMatchingRule defaultEqualityMatchingRule;
071    
072      // The default ordering matching rule for this syntax.
073      private OrderingMatchingRule defaultOrderingMatchingRule;
074    
075      // The default substring matching rule for this syntax.
076      private SubstringMatchingRule defaultSubstringMatchingRule;
077    
078      /**
079       * Create a new attribute value decoder with the specified root DN.
080       *
081       * @param rootDN
082       *          The root DN for all decoded subtree specifications.
083       * @return The attribute value decoder.
084       */
085      public static AttributeValueDecoder<RFC3672SubtreeSpecification>
086          createAttributeValueDecoder(DN rootDN) {
087        return new Decoder(rootDN);
088      }
089    
090      /**
091       * Internal class implementing an attribute value decoder.
092       */
093      private static class Decoder implements
094          AttributeValueDecoder<RFC3672SubtreeSpecification> {
095    
096        // The root DN for all decoded relative subtree specifications.
097        private DN rootDN;
098    
099        /**
100         * Create a new decoder with the specified root DN.
101         *
102         * @param rootDN
103         *          The root DN for all decoded relative subtree
104         *          specifications.
105         */
106        public Decoder(DN rootDN) {
107          this.rootDN = rootDN;
108        }
109    
110        /**
111         * {@inheritDoc}
112         */
113        public RFC3672SubtreeSpecification decode(AttributeValue value)
114            throws DirectoryException {
115          return RFC3672SubtreeSpecification.valueOf(rootDN, value
116              .getStringValue());
117        }
118      }
119    
120      /**
121       * Creates a new instance of this syntax. Note that the only thing
122       * that should be done here is to invoke the default constructor for
123       * the superclass. All initialization should be performed in the
124       * <CODE>initializeSyntax</CODE> method.
125       */
126      public RFC3672SubtreeSpecificationSyntax() {
127        // No implementation required.
128      }
129    
130      /**
131       * {@inheritDoc}
132       */
133      public void initializeSyntax(AttributeSyntaxCfg configuration)
134          throws ConfigException {
135    
136        defaultEqualityMatchingRule = DirectoryServer
137            .getEqualityMatchingRule(EMR_OCTET_STRING_OID);
138        if (defaultEqualityMatchingRule == null) {
139          logError(ERR_ATTR_SYNTAX_UNKNOWN_EQUALITY_MATCHING_RULE.get(
140              EMR_OCTET_STRING_OID, SYNTAX_RFC3672_SUBTREE_SPECIFICATION_NAME));
141        }
142    
143        defaultOrderingMatchingRule = DirectoryServer
144            .getOrderingMatchingRule(OMR_OCTET_STRING_OID);
145        if (defaultOrderingMatchingRule == null) {
146          logError(ERR_ATTR_SYNTAX_UNKNOWN_ORDERING_MATCHING_RULE.get(
147              OMR_OCTET_STRING_OID, SYNTAX_RFC3672_SUBTREE_SPECIFICATION_NAME));
148        }
149    
150        defaultSubstringMatchingRule = DirectoryServer
151            .getSubstringMatchingRule(SMR_OCTET_STRING_OID);
152        if (defaultSubstringMatchingRule == null) {
153          logError(ERR_ATTR_SYNTAX_UNKNOWN_SUBSTRING_MATCHING_RULE.get(
154              SMR_OCTET_STRING_OID, SYNTAX_RFC3672_SUBTREE_SPECIFICATION_NAME));
155        }
156      }
157    
158      /**
159       * Retrieves the common name for this attribute syntax.
160       *
161       * @return The common name for this attribute syntax.
162       */
163      public String getSyntaxName() {
164    
165        return SYNTAX_RFC3672_SUBTREE_SPECIFICATION_NAME;
166      }
167    
168      /**
169       * Retrieves the OID for this attribute syntax.
170       *
171       * @return The OID for this attribute syntax.
172       */
173      public String getOID() {
174    
175        return SYNTAX_RFC3672_SUBTREE_SPECIFICATION_OID;
176      }
177    
178      /**
179       * Retrieves a description for this attribute syntax.
180       *
181       * @return A description for this attribute syntax.
182       */
183      public String getDescription() {
184    
185        return SYNTAX_RFC3672_SUBTREE_SPECIFICATION_DESCRIPTION;
186      }
187    
188      /**
189       * Retrieves the default equality matching rule that will be used for
190       * attributes with this syntax.
191       *
192       * @return The default equality matching rule that will be used for
193       *         attributes with this syntax, or <CODE>null</CODE> if
194       *         equality matches will not be allowed for this type by
195       *         default.
196       */
197      public EqualityMatchingRule getEqualityMatchingRule() {
198    
199        return defaultEqualityMatchingRule;
200      }
201    
202      /**
203       * Retrieves the default ordering matching rule that will be used for
204       * attributes with this syntax.
205       *
206       * @return The default ordering matching rule that will be used for
207       *         attributes with this syntax, or <CODE>null</CODE> if
208       *         ordering matches will not be allowed for this type by
209       *         default.
210       */
211      public OrderingMatchingRule getOrderingMatchingRule() {
212    
213        return defaultOrderingMatchingRule;
214      }
215    
216      /**
217       * Retrieves the default substring matching rule that will be used for
218       * attributes with this syntax.
219       *
220       * @return The default substring matching rule that will be used for
221       *         attributes with this syntax, or <CODE>null</CODE> if
222       *         substring matches will not be allowed for this type by
223       *         default.
224       */
225      public SubstringMatchingRule getSubstringMatchingRule() {
226    
227        return defaultSubstringMatchingRule;
228      }
229    
230      /**
231       * Retrieves the default approximate matching rule that will be used
232       * for attributes with this syntax.
233       *
234       * @return The default approximate matching rule that will be used for
235       *         attributes with this syntax, or <CODE>null</CODE> if
236       *         approximate matches will not be allowed for this type by
237       *         default.
238       */
239      public ApproximateMatchingRule getApproximateMatchingRule() {
240    
241        // There is no approximate matching rule by default.
242        return null;
243      }
244    
245      /**
246       * Indicates whether the provided value is acceptable for use in an
247       * attribute with this syntax. If it is not, then the reason may be
248       * appended to the provided buffer.
249       *
250       * @param value
251       *          The value for which to make the determination.
252       * @param invalidReason
253       *          The buffer to which the invalid reason should be appended.
254       * @return <CODE>true</CODE> if the provided value is acceptable for
255       *         use with this syntax, or <CODE>false</CODE> if not.
256       */
257      public boolean valueIsAcceptable(ByteString value,
258                                       MessageBuilder invalidReason) {
259    
260        // Use the subtree specification code to make this determination.
261        try {
262          RFC3672SubtreeSpecification.valueOf(DN.nullDN(), value.stringValue());
263    
264          return true;
265        } catch (DirectoryException e) {
266          if (debugEnabled())
267          {
268            TRACER.debugCaught(DebugLogLevel.ERROR, e);
269          }
270    
271          invalidReason.append(e.getMessageObject());
272          return false;
273        }
274      }
275    }