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 *    http://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.shared.ldap.model.schema;
021
022
023import java.util.ArrayList;
024import java.util.List;
025
026import org.apache.directory.shared.i18n.I18n;
027import org.apache.directory.shared.ldap.model.exception.LdapException;
028import org.apache.directory.shared.ldap.model.schema.registries.AttributeTypeRegistry;
029import org.apache.directory.shared.ldap.model.schema.registries.Registries;
030
031
032/**
033 * Represents an LDAP MatchingRuleUseDescription defined in RFC 2252.
034 * <p>
035 * According to ldapbis [MODELS]:
036 * </p>
037 * 
038 * <pre>
039 *  Values of the matchingRuleUse list the attributes which are suitable
040 *  for use with an extensible matching rule.
041 *  
042 *    Matching rule use descriptions are written according to the following
043 *    ABNF:
044 * 
045 *      MatchingRuleUseDescription = LPAREN WSP
046 *          numericoid                ; object identifier
047 *          [ SP &quot;NAME&quot; SP qdescrs ]  ; short names (descriptors)
048 *          [ SP &quot;DESC&quot; SP qdstring ] ; description
049 *          [ SP &quot;OBSOLETE&quot; ]         ; not active
050 *          SP &quot;APPLIES&quot; SP oids      ; attribute types
051 *          extensions WSP RPAREN     ; extensions
052 *  
053 *    where:
054 *      [numericoid] is the object identifier of the matching rule
055 *          associated with this matching rule use description;
056 *      NAME [qdescrs] are short names (descriptors) identifying this
057 *          matching rule use;
058 *      DESC [qdstring] is a short descriptive string;
059 *      OBSOLETE indicates this matching rule use is not active;
060 *      APPLIES provides a list of attribute types the matching rule applies
061 *          to; and
062 *      [extensions] describe extensions.
063 * 
064 *  The matchingRule within the MatchingRuleUse definition can be used by an
065 *  extensible match assertion if the assertion is based on the attributes 
066 *  listed within the MatchingRuleUse definition.  If an extensible match 
067 *  assertion is based on attributes other than those listed within the 
068 *  MatchingRuleUse definition then the assertion is deemed undefined.
069 *  
070 *  Also according to 3.3.20 of [SYNTAXES] (ldapbis working group):
071 *  
072 *  A value of the Matching Rule Use Description syntax indicates the
073 *  attribute types to which a matching rule may be applied in an
074 *  extensibleMatch search filter [PROT].  The LDAP-specific encoding of
075 *  a value of this syntax is defined by the &lt;MatchingRuleUseDescription&gt;
076 *  rule in [MODELS] above.
077 * </pre>
078 * 
079 * @see <a
080 *      href="http://www.ietf.org/internet-drafts/draft-ietf-ldapbis-models-11.txt">ldapbis
081 *      [MODELS]</a>
082 * @see <a
083 *      href="http://www.ietf.org/internet-drafts/draft-ietf-ldapbis-syntaxes-09.txt">ldapbis
084 *      [SYNTAXES]</a>
085 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
086 */
087// super.hashCode is final
088@SuppressWarnings("PMD.OverrideBothEqualsAndHashcode")
089public class MatchingRuleUse extends AbstractSchemaObject
090{
091    /** The list of attributes types OID the matching rule applies to */
092    private List<String> applicableAttributeOids;
093
094    /** The list of attributes types the matching rule applies to */
095    private List<AttributeType> applicableAttributes;
096
097
098    /**
099     * Creates a new instance of MatchingRuleUseDescription
100     */
101    public MatchingRuleUse( String oid )
102    {
103        super( SchemaObjectType.MATCHING_RULE_USE, oid );
104
105        applicableAttributeOids = new ArrayList<String>();
106        applicableAttributes = new ArrayList<AttributeType>();
107    }
108
109
110    /**
111     * Inject the MatchingRuleUse into the registries, updating the references to
112     * other SchemaObject
113     *
114     * @param registries The Registries
115     * @exception If the addition failed
116     */
117    public void addToRegistries( Registries registries ) throws LdapException
118    {
119        if ( locked )
120        {
121            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
122        }
123        
124        if ( registries != null )
125        {
126            AttributeTypeRegistry atRegistry = registries.getAttributeTypeRegistry();
127
128            if ( applicableAttributeOids != null )
129            {
130                applicableAttributes = new ArrayList<AttributeType>( applicableAttributeOids.size() );
131
132                for ( String oid : applicableAttributeOids )
133                {
134                    applicableAttributes.add( atRegistry.lookup( oid ) );
135                }
136            }
137        }
138    }
139
140
141    /**
142     * @return The matchingRule's list of AttributeType OIDs the MRU applies to
143     */
144    public List<String> getApplicableAttributeOids()
145    {
146        return applicableAttributeOids;
147    }
148
149
150    /**
151     * @return The matchingRule's list of AttributeType OIDs the MRU applies to
152     */
153    public List<AttributeType> getApplicableAttributes()
154    {
155        return applicableAttributes;
156    }
157
158
159    /**
160     * Set the matchingRule's AttributeType OIDs the MRU applies to.
161     *
162     * @param applicableAttributeOids The AttributeType OIDs list
163     */
164    public void setApplicableAttributeOids( List<String> applicableAttributeOids )
165    {
166        if ( locked )
167        {
168            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
169        }
170        
171        if ( !isReadOnly )
172        {
173            this.applicableAttributeOids = applicableAttributeOids;
174        }
175    }
176
177
178    /**
179     * Set the matchingRule's AttributeType the MRU applies to.
180     *
181     * @param applicableAttributes The AttributeType list
182     */
183    public void setApplicableAttributes( List<AttributeType> applicableAttributes )
184    {
185        if ( locked )
186        {
187            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
188        }
189        
190        if ( !isReadOnly )
191        {
192            this.applicableAttributes = applicableAttributes;
193
194            // update the OIDS now
195            applicableAttributeOids.clear();
196
197            for ( AttributeType at : applicableAttributes )
198            {
199                applicableAttributeOids.add( at.getOid() );
200            }
201        }
202    }
203
204
205    /**
206     * Add a matchingRule's AttributeType OIDs the MRU applies to.
207     *
208     * @param oid A matchingRule's AttributeType OIDs the MRU applies to
209     */
210    public void addApplicableAttributeOids( String oid )
211    {
212        if ( locked )
213        {
214            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
215        }
216        
217        if ( !isReadOnly && !applicableAttributeOids.contains( oid ) )
218        {
219            applicableAttributeOids.add( oid );
220        }
221    }
222
223
224    /**
225     * Add a matchingRule's AttributeType the MRU applies to.
226     *
227     * @param attributeType A matchingRule's AttributeType the MRU applies to
228     */
229    public void addApplicableAttribute( AttributeType attributeType )
230    {
231        if ( locked )
232        {
233            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
234        }
235        
236        if ( !isReadOnly && !applicableAttributeOids.contains( attributeType.getOid() ) )
237        {
238            applicableAttributes.add( attributeType );
239            applicableAttributeOids.add( attributeType.getOid() );
240        }
241    }
242
243
244    /**
245     * @see Object#toString()
246     */
247    public String toString()
248    {
249        return objectType + " " + DescriptionUtils.getDescription( this );
250    }
251
252
253    /**
254     * Copy an MatchingRuleUse
255     */
256    public MatchingRuleUse copy()
257    {
258        MatchingRuleUse copy = new MatchingRuleUse( oid );
259
260        // Copy the SchemaObject common data
261        copy.copy( this );
262
263        // Clone the APPLY AttributeTypes
264        copy.applicableAttributeOids = new ArrayList<String>();
265
266        // Copy the APPLIES oid list
267        for ( String oid : applicableAttributeOids )
268        {
269            copy.applicableAttributeOids.add( oid );
270        }
271
272        // Copy the APPLIES list (will be empty)
273        copy.applicableAttributes = new ArrayList<AttributeType>();
274
275        return copy;
276    }
277
278
279    /**
280     * @see Object#equals(Object)
281     */
282    @Override
283    @SuppressWarnings("PMD.UnusedLocalVariable") // Remove me when the TODO is fixed 
284    public boolean equals( Object o )
285    {
286        if ( !super.equals( o ) )
287        {
288            return false;
289        }
290
291        if ( !( o instanceof MatchingRuleUse ) )
292        {
293            return false;
294        }
295
296        @SuppressWarnings("unused")
297        MatchingRuleUse that = ( MatchingRuleUse ) o;
298
299        // TODO : complete the checks
300        return true;
301    }
302
303
304    /**
305     * {@inheritDoc}
306     */
307    public void clear()
308    {
309        // Clear the common elements
310        super.clear();
311
312        // Clear the references
313        applicableAttributes.clear();
314        applicableAttributeOids.clear();
315    }
316}