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