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.LinkedHashMap; 030import java.util.LinkedHashSet; 031import java.util.List; 032import java.util.Map; 033import java.util.Set; 034 035import org.forgerock.i18n.slf4j.LocalizedLogger; 036 037import static org.forgerock.util.Reject.*; 038import static org.opends.server.util.ServerConstants.*; 039 040/** 041 * This class defines a data structure for storing and interacting 042 * with a name form, which defines the attribute type(s) that must 043 * and/or may be used in the RDN of an entry with a given structural 044 * objectclass. 045 */ 046@org.opends.server.types.PublicAPI( 047 stability=org.opends.server.types.StabilityLevel.UNCOMMITTED, 048 mayInstantiate=false, 049 mayExtend=false, 050 mayInvoke=true) 051public final class NameForm 052 implements SchemaFileElement 053{ 054 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 055 056 /** Indicates whether this name form is declared "obsolete". */ 057 private final boolean isObsolete; 058 059 /** 060 * The set of additional name-value pairs associated with this name 061 * form definition. 062 */ 063 private final Map<String,List<String>> extraProperties; 064 065 /** 066 * The mapping between the lowercase names and the user-provided 067 * names for this name form. 068 */ 069 private final Map<String,String> names; 070 071 /** The reference to the structural objectclass for this name form. */ 072 private final ObjectClass structuralClass; 073 074 /** The set of optional attribute types for this name form. */ 075 private final Set<AttributeType> optionalAttributes; 076 077 /** The set of required attribute types for this name form. */ 078 private final Set<AttributeType> requiredAttributes; 079 080 /** The definition string used to create this name form. */ 081 private final String definition; 082 083 /** The description for this name form. */ 084 private final String description; 085 086 /** The OID for this name form. */ 087 private final String oid; 088 089 090 091 /** 092 * Creates a new name form definition with the provided information. 093 * 094 * @param definition The definition string used to create 095 * this name form. It must not be 096 * {@code null}. 097 * @param names The set of names that may be used to 098 * reference this name form. 099 * @param oid The OID for this name form. It must 100 * not be {@code null}. 101 * @param description The description for this name form. 102 * @param isObsolete Indicates whether this name form is 103 * declared "obsolete". 104 * @param structuralClass The structural objectclass with which 105 * this name form is associated. It 106 * must not be {@code null}. 107 * @param requiredAttributes The set of required attribute types 108 * for this name form. 109 * @param optionalAttributes The set of optional attribute types 110 * for this name form. 111 * @param extraProperties A set of extra properties for this 112 * name form. 113 */ 114 public NameForm(String definition, Map<String,String> names, 115 String oid, String description, boolean isObsolete, 116 ObjectClass structuralClass, 117 Set<AttributeType> requiredAttributes, 118 Set<AttributeType> optionalAttributes, 119 Map<String,List<String>> extraProperties) 120 { 121 ifNull(definition, oid, structuralClass); 122 123 this.oid = oid; 124 this.description = description; 125 this.isObsolete = isObsolete; 126 this.structuralClass = structuralClass; 127 128 int schemaFilePos = definition.indexOf(SCHEMA_PROPERTY_FILENAME); 129 if (schemaFilePos > 0) 130 { 131 String defStr; 132 try 133 { 134 int firstQuotePos = definition.indexOf('\'', schemaFilePos); 135 int secondQuotePos = definition.indexOf('\'', 136 firstQuotePos+1); 137 138 defStr = definition.substring(0, schemaFilePos).trim() + " " + 139 definition.substring(secondQuotePos+1).trim(); 140 } 141 catch (Exception e) 142 { 143 logger.traceException(e); 144 145 defStr = definition; 146 } 147 148 this.definition = defStr; 149 } 150 else 151 { 152 this.definition = definition; 153 } 154 155 if (names == null || names.isEmpty()) 156 { 157 this.names = new LinkedHashMap<>(0); 158 } 159 else 160 { 161 this.names = new LinkedHashMap<>(names); 162 } 163 164 if (requiredAttributes == null || requiredAttributes.isEmpty()) 165 { 166 this.requiredAttributes = new LinkedHashSet<>(0); 167 } 168 else 169 { 170 this.requiredAttributes = new LinkedHashSet<>(requiredAttributes); 171 } 172 173 if (optionalAttributes == null || optionalAttributes.isEmpty()) 174 { 175 this.optionalAttributes = new LinkedHashSet<>(0); 176 } 177 else 178 { 179 this.optionalAttributes = new LinkedHashSet<>(optionalAttributes); 180 } 181 182 if (extraProperties == null || extraProperties.isEmpty()) 183 { 184 this.extraProperties = new LinkedHashMap<>(0); 185 } 186 else 187 { 188 this.extraProperties = new LinkedHashMap<>(extraProperties); 189 } 190 } 191 192 193 194 /** 195 * Retrieves the set of names that may be used to reference this 196 * name form. The returned object will be a mapping between each 197 * name in all lowercase characters and that name in a user-defined 198 * form (which may include mixed capitalization). 199 * 200 * @return The set of names that may be used to reference this 201 * name form. 202 */ 203 public Map<String,String> getNames() 204 { 205 return names; 206 } 207 208 209 210 /** 211 * Indicates whether the provided lowercase name may be used to 212 * reference this name form. 213 * 214 * @param lowerName The name for which to make the determination, 215 * in all lowercase characters. 216 * 217 * @return {@code true} if the provided lowercase name may be used 218 * to reference this name form, or {@code false} if not. 219 */ 220 public boolean hasName(String lowerName) 221 { 222 return names.containsKey(lowerName); 223 } 224 225 226 227 /** 228 * Retrieves the OID for this name form. 229 * 230 * @return The OID for this name form. 231 */ 232 public String getOID() 233 { 234 return oid; 235 } 236 237 238 239 /** 240 * Retrieves the name or OID that should be used to reference this 241 * name form. If at least one name is defined, then the first will 242 * be returned. Otherwise, the OID will be returned. 243 * 244 * @return The name or OID that should be used to reference this 245 * name form. 246 */ 247 public String getNameOrOID() 248 { 249 if (names.isEmpty()) 250 { 251 return oid; 252 } 253 else 254 { 255 return names.values().iterator().next(); 256 } 257 } 258 259 260 261 /** 262 * Indicates whether the provided lowercase value is equal to the 263 * OID or any of the names that may be used to reference this name 264 * form. 265 * 266 * @param lowerValue The value, in all lowercase characters, that 267 * may be used to make the determination. 268 * 269 * @return {@code true} if the provided lowercase value is one of 270 * the names or the OID of this name form, or {@code false} 271 * if it is not. 272 */ 273 public boolean hasNameOrOID(String lowerValue) 274 { 275 return names.containsKey(lowerValue) || lowerValue.equals(oid); 276 } 277 278 279 280 /** 281 * Retrieves the description for this name form. 282 * 283 * @return The description for this name form, or {@code true} if 284 * there is none. 285 */ 286 public String getDescription() 287 { 288 return description; 289 } 290 291 292 293 /** 294 * Retrieves the reference to the structural objectclass for this 295 * name form. 296 * 297 * @return The reference to the structural objectclass for this 298 * name form. 299 */ 300 public ObjectClass getStructuralClass() 301 { 302 return structuralClass; 303 } 304 305 306 307 /** 308 * Retrieves the set of required attributes for this name form. 309 * 310 * @return The set of required attributes for this name form. 311 */ 312 public Set<AttributeType> getRequiredAttributes() 313 { 314 return requiredAttributes; 315 } 316 317 318 319 /** 320 * Indicates whether the provided attribute type is included in the 321 * required attribute list for this name form. 322 * 323 * @param attributeType The attribute type for which to make the 324 * determination. 325 * 326 * @return {@code true} if the provided attribute type is required 327 * by this name form, or {@code false} if not. 328 */ 329 public boolean isRequired(AttributeType attributeType) 330 { 331 return requiredAttributes.contains(attributeType); 332 } 333 334 335 336 /** 337 * Retrieves the set of optional attributes for this name form. 338 * 339 * @return The set of optional attributes for this name form. 340 */ 341 public Set<AttributeType> getOptionalAttributes() 342 { 343 return optionalAttributes; 344 } 345 346 347 348 /** 349 * Indicates whether the provided attribute type is included in the 350 * optional attribute list for this name form. 351 * 352 * @param attributeType The attribute type for which to make the 353 * determination. 354 * 355 * @return {@code true} if the provided attribute type is optional 356 * for this name form, or {@code false} if not. 357 */ 358 public boolean isOptional(AttributeType attributeType) 359 { 360 return optionalAttributes.contains(attributeType); 361 } 362 363 364 365 /** 366 * Indicates whether the provided attribute type is in the list of 367 * required or optional attributes for this name form. 368 * 369 * @param attributeType The attribute type for which to make the 370 * determination. 371 * 372 * @return {@code true} if the provided attribute type is required 373 * or optional for this name form, or {@code false} if it 374 * is not. 375 */ 376 public boolean isRequiredOrOptional(AttributeType attributeType) 377 { 378 return requiredAttributes.contains(attributeType) || 379 optionalAttributes.contains(attributeType); 380 } 381 382 383 384 /** 385 * Indicates whether this name form is declared "obsolete". 386 * 387 * @return {@code true} if this name form is declared 388 * "obsolete", or {@code false} if it is not. 389 */ 390 public boolean isObsolete() 391 { 392 return isObsolete; 393 } 394 395 396 397 /** 398 * Retrieves a mapping between the names of any extra non-standard 399 * properties that may be associated with this name form and the 400 * value for that property. 401 * 402 * @return A mapping between the names of any extra non-standard 403 * properties that may be associated with this name form 404 * and the value for that property. 405 */ 406 @Override 407 public Map<String,List<String>> getExtraProperties() 408 { 409 return extraProperties; 410 } 411 412 413 414 /** 415 * Indicates whether the provided object is equal to this name form. 416 * The object will be considered equal if it is a name form with the 417 * same OID as the current name form. 418 * 419 * @param o The object for which to make the determination. 420 * 421 * @return {@code true} if the provided object is equal to this 422 * name form, or {@code true} if not. 423 */ 424 @Override 425 public boolean equals(Object o) 426 { 427 if (this == o) 428 { 429 return true; 430 } 431 if (!(o instanceof NameForm)) 432 { 433 return false; 434 } 435 return oid.equals(((NameForm) o).oid); 436 } 437 438 439 440 /** 441 * Retrieves the hash code for this name form. It will be based on 442 * the sum of the bytes of the OID. 443 * 444 * @return The hash code for this name form. 445 */ 446 @Override 447 public int hashCode() 448 { 449 int oidLength = oid.length(); 450 int hashCode = 0; 451 for (int i=0; i < oidLength; i++) 452 { 453 hashCode += oid.charAt(i); 454 } 455 456 return hashCode; 457 } 458 459 460 461 /** 462 * Retrieves the string representation of this name form in the form 463 * specified in RFC 2252. 464 * 465 * @return The string representation of this name form in the form 466 * specified in RFC 2252. 467 */ 468 @Override 469 public String toString() 470 { 471 return definition; 472 } 473 474}