001/*
002 *  Licensed to the Apache Software Foundation (ASF) under one
003 *  or more contributor license agreements.  See the NOTICE file
004 *  distributed with this work for additional information
005 *  regarding copyright ownership.  The ASF licenses this file
006 *  to you under the Apache License, Version 2.0 (the
007 *  "License"); you may not use this file except in compliance
008 *  with the License.  You may obtain a copy of the License at
009 * 
010 *    https://www.apache.org/licenses/LICENSE-2.0
011 * 
012 *  Unless required by applicable law or agreed to in writing,
013 *  software distributed under the License is distributed on an
014 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 *  KIND, either express or implied.  See the License for the
016 *  specific language governing permissions and limitations
017 *  under the License.
018 * 
019 */
020package org.apache.directory.api.ldap.model.schema;
021
022import org.apache.directory.api.i18n.I18n;
023
024/**
025 * A matchingRule definition. MatchingRules associate a comparator and a
026 * normalizer, forming the basic tools necessary to assert actions against
027 * attribute values. MatchingRules are associated with a specific Syntax for the
028 * purpose of resolving a normalized form and for comparisons.
029 * <p>
030 * According to ldapbis [MODELS]:
031 * </p>
032 * 
033 * <pre>
034 *  4.1.3. Matching Rules
035 * 
036 *    Matching rules are used by servers to compare attribute values against
037 *    assertion values when performing Search and Compare operations.  They
038 *    are also used to identify the value to be added or deleted when
039 *    modifying entries, and are used when comparing a purported
040 *    distinguished name with the name of an entry.
041 * 
042 *    A matching rule specifies the syntax of the assertion value.
043 * 
044 *    Each matching rule is identified by an object identifier (OID) and,
045 *    optionally, one or more short names (descriptors).
046 * 
047 *    Matching rule definitions are written according to the ABNF:
048 * 
049 *      MatchingRuleDescription = LPAREN WSP
050 *          numericoid                ; object identifier
051 *          [ SP &quot;NAME&quot; SP qdescrs ]  ; short names (descriptors)
052 *          [ SP &quot;DESC&quot; SP qdstring ] ; description
053 *          [ SP &quot;OBSOLETE&quot; ]         ; not active
054 *          SP &quot;SYNTAX&quot; SP numericoid ; assertion syntax
055 *          extensions WSP RPAREN     ; extensions
056 * 
057 *    where:
058 *      [numericoid] is object identifier assigned to this matching rule;
059 *      NAME [qdescrs] are short names (descriptors) identifying this
060 *          matching rule;
061 *      DESC [qdstring] is a short descriptive string;
062 *      OBSOLETE indicates this matching rule is not active;
063 *      SYNTAX identifies the assertion syntax by object identifier; and
064 *      [extensions] describe extensions.
065 * </pre>
066 * 
067 * @see <a href="http://www.faqs.org/rfcs/rfc2252.html">RFC 2252 Section 4.5</a>
068 * @see <a
069 *      href="http://www.ietf.org/internet-drafts/draft-ietf-ldapbis-models-11.txt">ldapbis
070 *      [MODELS]</a>
071 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
072 */
073public class MatchingRule extends AbstractSchemaObject
074{
075    /** The mandatory serialVersionUID */
076    public static final long serialVersionUID = 1L;
077
078    /** The associated Comparator */
079    protected LdapComparator<? super Object> ldapComparator;
080
081    /** The associated Normalizer */
082    protected Normalizer normalizer;
083
084    /** The associated LdapSyntax */
085    protected LdapSyntax ldapSyntax;
086
087    /** The associated LdapSyntax OID */
088    protected String ldapSyntaxOid;
089
090
091    /**
092     * Creates a new instance of MatchingRule.
093     *
094     * @param oid The MatchingRule OID
095     */
096    public MatchingRule( String oid )
097    {
098        super( SchemaObjectType.MATCHING_RULE, oid );
099    }
100
101
102    /**
103     * Gets the LdapSyntax used by this MatchingRule.
104     * 
105     * @return the LdapSyntax of this MatchingRule
106     */
107    public LdapSyntax getSyntax()
108    {
109        return ldapSyntax;
110    }
111
112
113    /**
114     * Sets the Syntax
115     *
116     * @param ldapSyntax The Syntax
117     */
118    public void setSyntax( LdapSyntax ldapSyntax )
119    {
120        if ( locked )
121        {
122            throw new UnsupportedOperationException( I18n.err( I18n.ERR_13700_CANNOT_MODIFY_LOCKED_SCHEMA_OBJECT, getName() ) );
123        }
124
125        this.ldapSyntax = ldapSyntax;
126        this.ldapSyntaxOid = ldapSyntax.getOid();
127    }
128
129
130    /**
131     * Gets the LdapSyntax OID used by this MatchingRule.
132     * 
133     * @return the LdapSyntax of this MatchingRule
134     */
135    public String getSyntaxOid()
136    {
137        return ldapSyntaxOid;
138    }
139
140
141    /**
142     * Sets the Syntax's OID
143     *
144     * @param oid The Syntax's OID
145     */
146    public void setSyntaxOid( String oid )
147    {
148        if ( locked )
149        {
150            throw new UnsupportedOperationException( I18n.err( I18n.ERR_13700_CANNOT_MODIFY_LOCKED_SCHEMA_OBJECT, getName() ) );
151        }
152
153        this.ldapSyntaxOid = oid;
154    }
155
156
157    /**
158     * Gets the LdapComparator enabling the use of this MatchingRule for ORDERING
159     * and sorted indexing.
160     * 
161     * @return the ordering LdapComparator
162     */
163    public LdapComparator<? super Object> getLdapComparator()
164    {
165        return ldapComparator;
166    }
167
168    /**
169     * Sets the LdapComparator
170     *
171     * @param ldapComparator The LdapComparator
172     */
173    @SuppressWarnings("unchecked")
174    public void setLdapComparator( LdapComparator<?> ldapComparator )
175    {
176        if ( locked )
177        {
178            throw new UnsupportedOperationException( I18n.err( I18n.ERR_13700_CANNOT_MODIFY_LOCKED_SCHEMA_OBJECT, getName() ) );
179        }
180
181        this.ldapComparator = ( LdapComparator<? super Object> ) ldapComparator;
182    }
183
184
185
186    /**
187     * Gets the Normalizer enabling the use of this MatchingRule for EQUALITY
188     * matching and indexing.
189     * 
190     * @return the associated normalizer
191     */
192    public Normalizer getNormalizer()
193    {
194        return normalizer;
195    }
196
197
198    /**
199     * Sets the Normalizer
200     *
201     * @param normalizer The Normalizer
202     */
203    public void setNormalizer( Normalizer normalizer )
204    {
205        if ( locked )
206        {
207            throw new UnsupportedOperationException( I18n.err( I18n.ERR_13700_CANNOT_MODIFY_LOCKED_SCHEMA_OBJECT, getName() ) );
208        }
209
210        this.normalizer = normalizer;
211    }
212
213
214    /**
215     * @see Object#toString()
216     */
217    @Override
218    public String toString()
219    {
220        return SchemaObjectRenderer.OPEN_LDAP_SCHEMA_RENDERER.render( this );
221    }
222
223
224    /**
225     * Copy an MatchingRule
226     */
227    @Override
228    public MatchingRule copy()
229    {
230        MatchingRule copy = new MatchingRule( oid );
231
232        // Copy the SchemaObject common data
233        copy.copy( this );
234
235        // All the references to other Registries object are set to null.
236        copy.ldapComparator = null;
237        copy.ldapSyntax = null;
238        copy.normalizer = null;
239
240        // Copy the syntax OID
241        copy.ldapSyntaxOid = ldapSyntaxOid;
242
243        return copy;
244    }
245
246    
247    /**
248     * @see Object#equals(Object)
249     */
250    @Override
251    public int hashCode()
252    {
253        int hash = h;
254        
255        if ( ldapComparator != null )
256        {
257            hash = hash * 37 + ldapComparator.hashCode();
258        }
259        
260        if ( ldapSyntax != null )
261        {
262            hash = hash * 37 + ldapSyntax.hashCode();
263        }
264        
265        if ( normalizer != null )
266        {
267            hash = hash * 37 + normalizer.hashCode();
268        }
269        
270
271        
272        return hash;
273    }
274
275    /**
276     * @see Object#equals(Object)
277     */
278    @Override
279    public boolean equals( Object o )
280    {
281        if ( !super.equals( o ) )
282        {
283            return false;
284        }
285
286        if ( !( o instanceof MatchingRule ) )
287        {
288            return false;
289        }
290
291        MatchingRule that = ( MatchingRule ) o;
292
293        // Check the Comparator
294        if ( ldapComparator != null )
295        {
296            if ( !ldapComparator.equals( that.ldapComparator ) )
297            {
298                return false;
299            }
300        }
301        else
302        {
303            if ( that.ldapComparator != null )
304            {
305                return false;
306            }
307        }
308
309        // Check the Normalizer
310        if ( normalizer != null )
311        {
312            if ( !normalizer.equals( that.normalizer ) )
313            {
314                return false;
315            }
316        }
317        else
318        {
319            if ( that.normalizer != null )
320            {
321                return false;
322            }
323        }
324
325        // Check the Syntax OID
326        if ( !compareOid( ldapSyntaxOid, that.ldapSyntaxOid ) )
327        {
328            return false;
329        }
330
331        // Check the Syntax
332        if ( ldapSyntax != null )
333        {
334            if ( !ldapSyntax.equals( that.ldapSyntax ) )
335            {
336                return false;
337            }
338        }
339        else
340        {
341            if ( that.ldapSyntax != null )
342            {
343                return false;
344            }
345        }
346
347        return true;
348    }
349
350
351    /**
352     * {@inheritDoc}
353     */
354    @Override
355    public void clear()
356    {
357        // Clear the common elements
358        super.clear();
359
360        // Clear the references
361        ldapComparator = null;
362        ldapSyntax = null;
363        normalizer = null;
364    }
365}