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