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