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