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