001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions Copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2006-2008 Sun Microsystems, Inc. 015 * Portions Copyright 2013-2016 ForgeRock AS. 016 */ 017package org.opends.server.types; 018 019import org.forgerock.opendj.ldap.schema.AttributeType; 020 021import java.util.Iterator; 022import java.util.LinkedHashMap; 023import java.util.LinkedHashSet; 024import java.util.List; 025import java.util.Map; 026import java.util.Set; 027 028import org.forgerock.i18n.slf4j.LocalizedLogger; 029 030import static org.forgerock.util.Reject.*; 031import static org.opends.server.util.ServerConstants.*; 032 033/** 034 * This class defines a DIT content rule, which defines the set of 035 * allowed, required, and prohibited attributes for entries with a 036 * given structural objectclass, and also indicates which auxiliary 037 * classes that may be included in the entry. 038 */ 039@org.opends.server.types.PublicAPI( 040 stability=org.opends.server.types.StabilityLevel.UNCOMMITTED, 041 mayInstantiate=false, 042 mayExtend=false, 043 mayInvoke=true) 044public final class DITContentRule 045 implements SchemaFileElement 046{ 047 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 048 049 /** Indicates whether this content rule is declared "obsolete". */ 050 private final boolean isObsolete; 051 052 /** 053 * The set of additional name-value pairs associated with this 054 * content rule definition. 055 */ 056 private final Map<String,List<String>> extraProperties; 057 058 /** 059 * The set of names for this DIT content rule, in a mapping between 060 * the all-lowercase form and the user-defined form. 061 */ 062 private final Map<String,String> names; 063 064 /** The structural objectclass for this DIT content rule. */ 065 private final ObjectClass structuralClass; 066 067 /** 068 * The set of auxiliary objectclasses that entries with this content 069 * rule may contain, in a mapping between the objectclass and the 070 * user-defined name for that class. 071 */ 072 private final Set<ObjectClass> auxiliaryClasses; 073 074 /** The set of optional attribute types for this DIT content rule. */ 075 private final Set<AttributeType> optionalAttributes; 076 077 /** The set of prohibited attribute types for this DIT content rule. */ 078 private final Set<AttributeType> prohibitedAttributes; 079 080 /** The set of required attribute types for this DIT content rule. */ 081 private final Set<AttributeType> requiredAttributes; 082 083 /** The definition string used to create this DIT content rule. */ 084 private final String definition; 085 086 /** The description for this DIT content rule. */ 087 private final String description; 088 089 090 091 /** 092 * Creates a new DIT content rule definition with the provided 093 * information. 094 * 095 * @param definition The definition string used to 096 * create this DIT content rule. It 097 * must not be {@code null}. 098 * @param structuralClass The structural objectclass for this 099 * DIT content rule. It must not be 100 * {@code null}. 101 * @param names The set of names that may be used 102 * to reference this DIT content rule. 103 * @param description The description for this DIT 104 * content rule. 105 * @param auxiliaryClasses The set of auxiliary classes for 106 * this DIT content rule 107 * @param requiredAttributes The set of required attribute types 108 * for this DIT content rule. 109 * @param optionalAttributes The set of optional attribute types 110 * for this DIT content rule. 111 * @param prohibitedAttributes The set of prohibited attribute 112 * types for this DIT content rule. 113 * @param isObsolete Indicates whether this DIT content 114 * rule is declared "obsolete". 115 * @param extraProperties A set of extra properties for this 116 * DIT content rule. 117 */ 118 public DITContentRule(String definition, 119 ObjectClass structuralClass, 120 Map<String,String> names, String description, 121 Set<ObjectClass> auxiliaryClasses, 122 Set<AttributeType> requiredAttributes, 123 Set<AttributeType> optionalAttributes, 124 Set<AttributeType> prohibitedAttributes, 125 boolean isObsolete, 126 Map<String,List<String>> extraProperties) 127 { 128 ifNull(definition, structuralClass); 129 130 this.structuralClass = structuralClass; 131 this.description = description; 132 this.isObsolete = isObsolete; 133 134 int schemaFilePos = definition.indexOf(SCHEMA_PROPERTY_FILENAME); 135 if (schemaFilePos > 0) 136 { 137 String defStr; 138 try 139 { 140 int firstQuotePos = definition.indexOf('\'', schemaFilePos); 141 int secondQuotePos = definition.indexOf('\'', 142 firstQuotePos+1); 143 144 defStr = definition.substring(0, schemaFilePos).trim() + " " + 145 definition.substring(secondQuotePos+1).trim(); 146 } 147 catch (Exception e) 148 { 149 logger.traceException(e); 150 151 defStr = definition; 152 } 153 154 this.definition = defStr; 155 } 156 else 157 { 158 this.definition = definition; 159 } 160 161 if (names == null || names.isEmpty()) 162 { 163 this.names = new LinkedHashMap<>(0); 164 } 165 else 166 { 167 this.names = new LinkedHashMap<>(names); 168 } 169 170 if (auxiliaryClasses == null || auxiliaryClasses.isEmpty()) 171 { 172 this.auxiliaryClasses = new LinkedHashSet<>(0); 173 } 174 else 175 { 176 this.auxiliaryClasses = new LinkedHashSet<>(auxiliaryClasses); 177 } 178 179 if (requiredAttributes == null || requiredAttributes.isEmpty()) 180 { 181 this.requiredAttributes = new LinkedHashSet<>(0); 182 } 183 else 184 { 185 this.requiredAttributes = new LinkedHashSet<>(requiredAttributes); 186 } 187 188 if (optionalAttributes == null || optionalAttributes.isEmpty()) 189 { 190 this.optionalAttributes = new LinkedHashSet<>(0); 191 } 192 else 193 { 194 this.optionalAttributes = new LinkedHashSet<>(optionalAttributes); 195 } 196 197 if (prohibitedAttributes == null || prohibitedAttributes.isEmpty()) 198 { 199 this.prohibitedAttributes = new LinkedHashSet<>(0); 200 } 201 else 202 { 203 this.prohibitedAttributes = new LinkedHashSet<>(prohibitedAttributes); 204 } 205 206 if (extraProperties == null || extraProperties.isEmpty()) 207 { 208 this.extraProperties = new LinkedHashMap<>(0); 209 } 210 else 211 { 212 this.extraProperties = new LinkedHashMap<>(extraProperties); 213 } 214 } 215 216 217 218 /** 219 * Retrieves the structural objectclass for this DIT content rule. 220 * 221 * @return The structural objectclass for this DIT content rule. 222 */ 223 public ObjectClass getStructuralClass() 224 { 225 return structuralClass; 226 } 227 228 229 230 /** 231 * Retrieves the set of names that may be used to reference this DIT 232 * content rule. The returned object will be a mapping between each 233 * name in all lowercase characters and that name in a user-defined 234 * form (which may include mixed capitalization). 235 * 236 * @return The set of names that may be used to reference this DIT 237 * content rule. 238 */ 239 public Map<String,String> getNames() 240 { 241 return names; 242 } 243 244 245 246 /** 247 * Retrieves the primary name to use to reference this DIT content 248 * rule. 249 * 250 * @return The primary name to use to reference this DIT content 251 * rule, or {@code null} if there is none. 252 */ 253 public String getNameOrOID() 254 { 255 if (names.isEmpty()) 256 { 257 return null; 258 } 259 else 260 { 261 return names.values().iterator().next(); 262 } 263 } 264 265 266 267 /** 268 * Indicates whether the provided lowercase name may be used to 269 * reference this DIT content rule. 270 * 271 * @param lowerName The name for which to make the determination, 272 * in all lowercase characters. 273 * 274 * @return {@code true} if the provided lowercase name may be used 275 * to reference this DIT content rule, or {@code false} if 276 * not. 277 */ 278 public boolean hasName(String lowerName) 279 { 280 return names.containsKey(lowerName); 281 } 282 283 284 285 /** 286 * Retrieves the set of auxiliary objectclasses that may be used for 287 * entries associated with this DIT content rule. 288 * 289 * @return The set of auxiliary objectclasses that may be used for 290 * entries associated with this DIT content rule. 291 */ 292 public Set<ObjectClass> getAuxiliaryClasses() 293 { 294 return auxiliaryClasses; 295 } 296 297 298 299 /** 300 * Retrieves the set of required attributes for this DIT content 301 * rule. 302 * 303 * @return The set of required attributes for this DIT content 304 * rule. 305 */ 306 public Set<AttributeType> getRequiredAttributes() 307 { 308 return requiredAttributes; 309 } 310 311 312 313 /** 314 * Indicates whether the provided attribute type is included in the 315 * required attribute list for this DIT content rule. 316 * 317 * @param attributeType The attribute type for which to make the 318 * determination. 319 * 320 * @return {@code true} if the provided attribute type is required 321 * by this DIT content rule, or {@code false} if not. 322 */ 323 public boolean isRequired(AttributeType attributeType) 324 { 325 return requiredAttributes.contains(attributeType); 326 } 327 328 329 330 /** 331 * Retrieves the set of optional attributes for this DIT content 332 * rule. 333 * 334 * @return The set of optional attributes for this DIT content 335 * rule. 336 */ 337 public Set<AttributeType> getOptionalAttributes() 338 { 339 return optionalAttributes; 340 } 341 342 343 344 /** 345 * Indicates whether the provided attribute type is included in the 346 * optional attribute list for this DIT content rule. 347 * 348 * @param attributeType The attribute type for which to make the 349 * determination. 350 * 351 * @return {@code true} if the provided attribute type is optional 352 * for this DIT content rule, or {@code false} if not. 353 */ 354 public boolean isOptional(AttributeType attributeType) 355 { 356 return optionalAttributes.contains(attributeType); 357 } 358 359 360 361 /** 362 * Indicates whether the provided attribute type is in the list of 363 * required or optional attributes for this DIT content rule. 364 * 365 * @param attributeType The attribute type for which to make the 366 * determination. 367 * 368 * @return {@code true} if the provided attribute type is required 369 * or allowed for this DIT content rule, or {@code false} 370 * if it is not. 371 */ 372 public boolean isRequiredOrOptional(AttributeType attributeType) 373 { 374 return requiredAttributes.contains(attributeType) || 375 optionalAttributes.contains(attributeType); 376 } 377 378 379 380 /** 381 * Retrieves the set of prohibited attributes for this DIT content 382 * rule. 383 * 384 * @return The set of prohibited attributes for this DIT content 385 * rule. 386 */ 387 public Set<AttributeType> getProhibitedAttributes() 388 { 389 return prohibitedAttributes; 390 } 391 392 393 /** 394 * Indicates whether this DIT content rule is declared "obsolete". 395 * 396 * @return {@code true} if this DIT content rule is declared 397 * "obsolete", or {@code false} if it is not. 398 */ 399 public boolean isObsolete() 400 { 401 return isObsolete; 402 } 403 404 405 406 /** 407 * Retrieves a mapping between the names of any extra non-standard 408 * properties that may be associated with this DIT content rule and 409 * the value for that property. 410 * 411 * @return A mapping between the names of any extra non-standard 412 * properties that may be associated with this DIT content 413 * rule and the value for that property. 414 */ 415 @Override 416 public Map<String,List<String>> getExtraProperties() 417 { 418 return extraProperties; 419 } 420 421 422 423 /** 424 * Indicates whether the provided object is equal to this DIT 425 * content rule. The object will be considered equal if it is a DIT 426 * content rule for the same structural objectclass and the same 427 * sets of names. For performance reasons, the set of auxiliary 428 * classes, and the sets of required, optional, and prohibited 429 * attribute types will not be checked, so that should be done 430 * manually if a more thorough equality comparison is required. 431 * 432 * @param o The object for which to make the determination. 433 * 434 * @return {@code true} if the provided object is equal to 435 * this DIT content rule, or {@code false} if not. 436 */ 437 @Override 438 public boolean equals(Object o) 439 { 440 if (this == o) 441 { 442 return true; 443 } 444 if (!(o instanceof DITContentRule)) 445 { 446 return false; 447 } 448 449 DITContentRule dcr = (DITContentRule) o; 450 if (!structuralClass.equals(dcr.structuralClass)) 451 { 452 return false; 453 } 454 455 if (names.size() != dcr.names.size()) 456 { 457 return false; 458 } 459 460 Iterator<String> iterator = names.keySet().iterator(); 461 while (iterator.hasNext()) 462 { 463 if (! dcr.names.containsKey(iterator.next())) 464 { 465 return false; 466 } 467 } 468 469 return true; 470 } 471 472 473 474 /** 475 * Retrieves the hash code for this DIT content rule. It will be 476 * equal to the hash code for the associated structural objectclass. 477 * 478 * @return The hash code for this DIT content rule. 479 */ 480 @Override 481 public int hashCode() 482 { 483 return structuralClass.hashCode(); 484 } 485 486 487 488 /** 489 * Retrieves the string representation of this DIT content rule in 490 * the form specified in RFC 2252. 491 * 492 * @return The string representation of this DIT content rule in 493 * the form specified in RFC 2252. 494 */ 495 @Override 496 public String toString() 497 { 498 return definition; 499 } 500 501}