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.parsers;
021    
022    
023    import java.util.List;
024    
025    
026    
027    /**
028     * Utilities for dealing with various schema descriptions.
029     *
030     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
031     * @version $Rev$, $Date$
032     */
033    public class ParserDescriptionUtils
034    {
035        /**
036         * Checks two schema objectClass descriptions for an exact match.
037         *
038         * @param ocd0 the first objectClass description to compare
039         * @param ocd1 the second objectClass description to compare
040         * @return true if both objectClasss descriptions match exactly, false otherwise
041         */
042        public static boolean objectClassesMatch( ObjectClassDescription ocd0, ObjectClassDescription ocd1 )
043        {
044            // compare all common description parameters
045            if ( ! descriptionsMatch( ocd0, ocd1 ) )
046            {
047                return false;
048            }
049    
050            // compare the objectClass type (AUXILIARY, STRUCTURAL, ABSTRACT)
051            if ( ocd0.getKind() != ocd1.getKind() )
052            {
053                return false;
054            }
055            
056            // compare the superior objectClasses (sizes must match)
057            if ( ocd0.getSuperiorObjectClasses().size() != ocd1.getSuperiorObjectClasses().size() )
058            {
059                return false;
060            }
061    
062            // compare the superior objectClasses (sizes must match)
063            for ( int ii = 0; ii < ocd0.getSuperiorObjectClasses().size(); ii++ )
064            {
065                if ( ! ocd0.getSuperiorObjectClasses().get( ii ).equals( ocd1.getSuperiorObjectClasses().get( ii ) ) )
066                {
067                    return false;
068                }
069            }
070            
071            // compare the must attributes (sizes must match)
072            for ( int ii = 0; ii < ocd0.getMustAttributeTypes().size(); ii++ )
073            {
074                if ( ! ocd0.getMustAttributeTypes().get( ii ).equals( ocd1.getMustAttributeTypes().get( ii ) ) )
075                {
076                    return false;
077                }
078            }
079            
080            // compare the may attributes (sizes must match)
081            for ( int ii = 0; ii < ocd0.getMayAttributeTypes().size(); ii++ )
082            {
083                if ( ! ocd0.getMayAttributeTypes().get( ii ).equals( ocd1.getMayAttributeTypes().get( ii ) ) )
084                {
085                    return false;
086                }
087            }
088            
089            return true;
090        }
091        
092        
093        /**
094         * Checks two schema attributeType descriptions for an exact match.
095         *
096         * @param atd0 the first attributeType description to compare
097         * @param atd1 the second attributeType description to compare
098         * @return true if both attributeType descriptions match exactly, false otherwise
099         */
100        public static boolean attributeTypesMatch( AttributeTypeDescription atd0, AttributeTypeDescription atd1 )
101        {
102            // compare all common description parameters
103            if ( ! descriptionsMatch( atd0, atd1 ) )
104            {
105                return false;
106            }
107    
108            // check that the same super type is being used for both attributes
109            if ( ! atd0.getSuperType().equals( atd1.getSuperType() ) )
110            {
111                return false;
112            }
113            
114            // check that the same matchingRule is used by both ATs for EQUALITY
115            if ( ! atd0.getEqualityMatchingRule().equals( atd1.getEqualityMatchingRule() ) )
116            {
117                return false;
118            }
119            
120            // check that the same matchingRule is used by both ATs for SUBSTRING
121            if ( ! atd0.getSubstringsMatchingRule().equals( atd1.getSubstringsMatchingRule() ) )
122            {
123                return false;
124            }
125            
126            // check that the same matchingRule is used by both ATs for ORDERING
127            if ( ! atd0.getOrderingMatchingRule().equals( atd1.getOrderingMatchingRule() ) )
128            {
129                return false;
130            }
131            
132            // check that the same syntax is used by both ATs
133            if ( ! atd0.getSyntax().equals( atd1.getSyntax() ) )
134            {
135                return false;
136            }
137            
138            // check that the syntax length constraint is the same for both
139            if ( atd0.getSyntaxLength() != atd1.getSyntaxLength() )
140            {
141                return false;
142            }
143            
144            // check that the ATs have the same single valued flag value
145            if ( atd0.isSingleValued() != atd1.isSingleValued() )
146            {
147                return false;
148            }
149            
150            // check that the ATs have the same collective flag value
151            if ( atd0.isCollective() != atd1.isCollective() )
152            {
153                return false;
154            }
155            
156            // check that the ATs have the same user modifiable flag value
157            if ( atd0.isUserModifiable() != atd1.isUserModifiable() )
158            {
159                return false;
160            }
161            
162            // check that the ATs have the same USAGE
163            if ( atd0.getUsage() != atd1.getUsage() )
164            {
165                return false;
166            }
167            
168            return true;
169        }
170        
171        
172        /**
173         * Checks to see if two matchingRule descriptions match exactly.
174         *
175         * @param mrd0 the first matchingRule description to compare
176         * @param mrd1 the second matchingRule description to compare
177         * @return true if the matchingRules match exactly, false otherwise
178         */
179        public static boolean matchingRulesMatch( MatchingRuleDescription mrd0, MatchingRuleDescription mrd1 )
180        {
181            // compare all common description parameters
182            if ( ! descriptionsMatch( mrd0, mrd1 ) )
183            {
184                return false;
185            }
186    
187            // check that the syntaxes of the matchingRules match
188            if ( ! mrd0.getSyntax().equals( mrd1.getSyntax() ) )
189            {
190                return false;
191            }
192            
193            return true;
194        }
195        
196        
197        /**
198         * Checks to see if two syntax descriptions match exactly.
199         *
200         * @param lsd0 the first syntax description to compare
201         * @param lsd1 the second syntax description to compare
202         * @return true if the syntaxes match exactly, false otherwise
203         */
204        public static boolean syntaxesMatch( LdapSyntaxDescription lsd0, LdapSyntaxDescription lsd1 )
205        {
206            return descriptionsMatch( lsd0, lsd1 );
207        }
208        
209        
210        /**
211         * Checks if two base schema descriptions match for the common components 
212         * in every schema description.  NOTE: for syntaxes the obsolete flag is 
213         * not compared because doing so would raise an exception since syntax 
214         * descriptions do not support the OBSOLETE flag.
215         * 
216         * @param asd0 the first schema description to compare 
217         * @param asd1 the second schema description to compare 
218         * @return true if the descriptions match exactly, false otherwise
219         */
220        public static boolean descriptionsMatch( AbstractSchemaDescription asd0, AbstractSchemaDescription asd1 )
221        {
222            // check that the OID matches
223            if ( ! asd0.getNumericOid().equals( asd1.getNumericOid() ) )
224            {
225                return false;
226            }
227            
228            // check that the obsolete flag is equal but not for syntaxes
229            if ( ( asd0 instanceof LdapSyntaxDescription ) || ( asd1 instanceof LdapSyntaxDescription ) )
230            {
231                if ( asd0.isObsolete() != asd1.isObsolete() )
232                {
233                    return false;
234                }
235            }
236            
237            // check that the description matches
238            if ( ! asd0.getDescription().equals( asd1.getDescription() ) )
239            {
240                return false;
241            }
242            
243            // check alias names for exact match
244            if ( ! aliasNamesMatch( asd0, asd1 ) )
245            {
246                return false;
247            }
248            
249            // check extensions for exact match
250            if ( ! extensionsMatch( asd0, asd1 ) )
251            {
252                return false;
253            }
254    
255            return true;
256        }
257    
258    
259        /**
260         * Checks to see if the extensions of a schema description match another
261         * description.  The order of the extension values must match for a true
262         * return.
263         *
264         * @param asd0 the first schema description to compare the extensions of
265         * @param asd1 the second schema description to compare the extensions of
266         * @return true if the extensions match exactly, false otherwise
267         */
268        public static boolean extensionsMatch( AbstractSchemaDescription asd0, AbstractSchemaDescription asd1 )
269        {
270            // check sizes first
271            if ( asd0.getExtensions().size() != asd1.getExtensions().size() )
272            {
273                return false;
274            }
275            
276            // check contents and order of extension values must match
277            for ( String key : asd0.getExtensions().keySet() )
278            {
279                List<String> values0 = asd0.getExtensions().get( key );
280                List<String> values1 = asd1.getExtensions().get( key );
281                
282                // if the key is not present in asd1
283                if ( values1 == null )
284                {
285                    return false;
286                }
287                
288                for ( int ii = 0; ii < values0.size(); ii++ )
289                {
290                    if ( ! values0.get( ii ).equals( values1.get( ii ) ) )
291                    {
292                        return false;
293                    }
294                }
295            }
296            
297            return true;
298        }
299        
300    
301        /**
302         * Checks to see if the alias names of a schema description match another 
303         * description.  The order of the alias names do matter.
304         *
305         * @param asd0 the schema description to compare
306         * @param asd1 the schema description to compare
307         * @return true if alias names match exactly, false otherwise
308         */
309        public static boolean aliasNamesMatch( AbstractSchemaDescription asd0, AbstractSchemaDescription asd1 )
310        {
311            // check sizes first
312            if ( asd0.getNames().size() != asd1.getNames().size() )
313            {
314                return false;
315            }
316            
317            // check contents and order must match too
318            for ( int ii = 0; ii < asd0.getNames().size(); ii++ )
319            {
320                if ( ! asd0.getNames().get( ii ).equals( asd1.getNames().get( ii ) ) )
321                {
322                    return false;
323                }
324            }
325            
326            return true;
327        }
328    }