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 2008-2009 Sun Microsystems, Inc. 025 * Portions Copyright 2014-2015 ForgeRock AS 026 */ 027 028package org.opends.server.admin; 029import org.forgerock.i18n.LocalizableMessage; 030 031 032 033import static org.forgerock.util.Reject.*; 034 035import java.util.EnumSet; 036import java.util.Locale; 037import java.util.MissingResourceException; 038import java.util.Set; 039 040 041 042/** 043 * Relation definitions define relationships between types of managed 044 * objects. In addition they define the ownership model: 045 * <ul> 046 * <li>composition - referenced managed objects are owned by the 047 * parent managed object and are deleted when the parent is deleted 048 * <li>aggregation - referenced managed objects are not owned by the 049 * parent managed object. Instead they are shared by other managed 050 * objects. 051 * </ul> 052 * Relations define how clients interact with the configuration. For 053 * example, clients manage aggregated managed objects in a shared 054 * location and attach them to parent managed objects. Composed 055 * managed objects, on the other hand, would be created directly 056 * beneath the parent managed object and destroyed with it too. 057 * <p> 058 * Within the server, listeners can choose to request notification of 059 * managed objects being added or removed from relations. 060 * <p> 061 * In LDAP, compositions are represented as follows: 062 * <ul> 063 * <li>singleton relations (one to one): a referenced managed object 064 * is represented using a child entry directly beneath the parent 065 * <li>optional relations (one to zero or one): a referenced managed 066 * object is represented using a child entry directly beneath the 067 * parent 068 * <li>instantiable relations (one to many): the relation is 069 * represented using a child entry directly beneath the parent. 070 * Referenced managed objects are represented using child entries of 071 * this "relation entry" and are named by the user 072 * <li>set relations (one to many): the relation is 073 * represented using a child entry directly beneath the parent. 074 * Referenced managed objects are represented using child entries of 075 * this "relation entry" whose name is the type of the managed object. 076 * </ul> 077 * Whereas, aggregations are represented by storing the DNs of the 078 * referenced managed objects in an attribute of the aggregating 079 * managed object. 080 * 081 * @param <C> 082 * The type of client managed object configuration that this 083 * relation definition refers to. 084 * @param <S> 085 * The type of server managed object configuration that this 086 * relation definition refers to. 087 */ 088public abstract class RelationDefinition 089 <C extends ConfigurationClient, S extends Configuration> { 090 091 /** 092 * An interface for incrementally constructing relation definitions. 093 * 094 * @param <C> 095 * The type of client managed object configuration that 096 * this relation definition refers to. 097 * @param <S> 098 * The type of server managed object configuration that 099 * this relation definition refers to. 100 * @param <D> 101 * The type of relation definition constructed by this 102 * builder. 103 */ 104 protected static abstract class AbstractBuilder 105 <C extends ConfigurationClient, S extends Configuration, 106 D extends RelationDefinition<C, S>> { 107 108 /** Common fields. */ 109 private final Common<C, S> common; 110 111 112 113 /** 114 * Create a property definition builder. 115 * 116 * @param pd 117 * The parent managed object definition. 118 * @param name 119 * The name of the relation. 120 * @param cd 121 * The child managed object definition. 122 */ 123 protected AbstractBuilder(AbstractManagedObjectDefinition<?, ?> pd, 124 String name, AbstractManagedObjectDefinition<C, S> cd) { 125 this.common = new Common<>(pd, name, cd); 126 } 127 128 129 130 /** 131 * Construct a relation definition based on the properties of this 132 * builder. 133 * 134 * @return The new relation definition. 135 */ 136 public final D getInstance() { 137 return buildInstance(common); 138 } 139 140 141 142 /** 143 * Add a relation definition option. 144 * 145 * @param option 146 * The relation option. 147 */ 148 public final void setOption(RelationOption option) { 149 ifNull(option); 150 common.options.add(option); 151 } 152 153 154 155 /** 156 * Build a relation definition based on the properties of this 157 * builder. 158 * 159 * @param common 160 * The common fields of the new relation definition. 161 * @return The new relation definition. 162 */ 163 protected abstract D buildInstance(Common<C, S> common); 164 } 165 166 167 168 /** 169 * Opaque structure containing fields common to all relation 170 * definition types. 171 * 172 * @param <C> 173 * The type of client managed object configuration that 174 * this relation definition refers to. 175 * @param <S> 176 * The type of server managed object configuration that 177 * this relation definition refers to. 178 */ 179 protected static final class Common 180 <C extends ConfigurationClient, S extends Configuration> { 181 182 /** The definition of the child managed object. */ 183 private final AbstractManagedObjectDefinition<C, S> cd; 184 185 /** The name of the relation. */ 186 private final String name; 187 188 /** Options applicable to this definition. */ 189 private final Set<RelationOption> options; 190 191 /** The definition of the parent managed object. */ 192 private final AbstractManagedObjectDefinition<?, ?> pd; 193 194 195 196 /** Private constructor. */ 197 private Common(AbstractManagedObjectDefinition<?, ?> pd, String name, 198 AbstractManagedObjectDefinition<C, S> cd) { 199 this.name = name; 200 this.pd = pd; 201 this.cd = cd; 202 this.options = EnumSet.noneOf(RelationOption.class); 203 } 204 } 205 206 /** Common fields. */ 207 private final Common<C, S> common; 208 209 210 211 /** 212 * Create a new managed object relation definition with the 213 * specified common fields. 214 * 215 * @param common 216 * The common fields of the new relation definition. 217 */ 218 protected RelationDefinition(Common<C, S> common) { 219 this.common = common; 220 } 221 222 223 224 /** 225 * Apply a visitor to this relation definition. 226 * 227 * @param <R> 228 * The return type of the visitor's methods. 229 * @param <P> 230 * The type of the additional parameters to the visitor's 231 * methods. 232 * @param v 233 * The relation definition visitor. 234 * @param p 235 * Optional additional visitor parameter. 236 * @return Returns a result as specified by the visitor. 237 */ 238 public abstract <R, P> R accept(RelationDefinitionVisitor<R, P> v, P p); 239 240 241 242 /** 243 * Get the definition of the child managed object. 244 * 245 * @return Returns the definition of the child managed object. 246 */ 247 public final AbstractManagedObjectDefinition<C, S> getChildDefinition() { 248 return common.cd; 249 } 250 251 252 253 /** 254 * Gets the optional description of this relation definition in the 255 * default locale. 256 * 257 * @return Returns the description of this relation definition in 258 * the default locale, or <code>null</code> if there is no 259 * description. 260 */ 261 public final LocalizableMessage getDescription() { 262 return getDescription(Locale.getDefault()); 263 } 264 265 266 267 /** 268 * Gets the optional description of this relation definition in the 269 * specified locale. 270 * 271 * @param locale 272 * The locale. 273 * @return Returns the description of this relation definition in 274 * the specified locale, or <code>null</code> if there is 275 * no description. 276 */ 277 public final LocalizableMessage getDescription(Locale locale) { 278 try { 279 String property = "relation." + common.name + ".description"; 280 return ManagedObjectDefinitionI18NResource.getInstance().getMessage( 281 getParentDefinition(), property, locale); 282 } catch (MissingResourceException e) { 283 return null; 284 } 285 } 286 287 288 289 /** 290 * Get the name of the relation. 291 * 292 * @return Returns the name of the relation. 293 */ 294 public final String getName() { 295 return common.name; 296 } 297 298 299 300 /** 301 * Get the definition of the parent managed object. 302 * 303 * @return Returns the definition of the parent managed object. 304 */ 305 public final AbstractManagedObjectDefinition<?, ?> getParentDefinition() { 306 return common.pd; 307 } 308 309 310 311 /** 312 * Gets the synopsis of this relation definition in the default 313 * locale. 314 * 315 * @return Returns the synopsis of this relation definition in the 316 * default locale. 317 */ 318 public final LocalizableMessage getSynopsis() { 319 return getSynopsis(Locale.getDefault()); 320 } 321 322 323 324 /** 325 * Gets the synopsis of this relation definition in the specified 326 * locale. 327 * 328 * @param locale 329 * The locale. 330 * @return Returns the synopsis of this relation definition in the 331 * specified locale. 332 */ 333 public final LocalizableMessage getSynopsis(Locale locale) { 334 String property = "relation." + common.name + ".synopsis"; 335 return ManagedObjectDefinitionI18NResource.getInstance().getMessage( 336 getParentDefinition(), property, locale); 337 } 338 339 340 341 /** 342 * Gets the user friendly name of this relation definition in the 343 * default locale. 344 * 345 * @return Returns the user friendly name of this relation 346 * definition in the default locale. 347 */ 348 public final LocalizableMessage getUserFriendlyName() { 349 return getUserFriendlyName(Locale.getDefault()); 350 } 351 352 353 354 /** 355 * Gets the user friendly name of this relation definition in the 356 * specified locale. 357 * 358 * @param locale 359 * The locale. 360 * @return Returns the user friendly name of this relation 361 * definition in the specified locale. 362 */ 363 public final LocalizableMessage getUserFriendlyName(Locale locale) { 364 String property = "relation." + common.name + ".user-friendly-name"; 365 return ManagedObjectDefinitionI18NResource.getInstance().getMessage( 366 getParentDefinition(), property, locale); 367 } 368 369 370 371 /** 372 * Check if the specified option is set for this relation 373 * definition. 374 * 375 * @param option 376 * The option to test. 377 * @return Returns <code>true</code> if the option is set, or 378 * <code>false</code> otherwise. 379 */ 380 public final boolean hasOption(RelationOption option) { 381 return common.options.contains(option); 382 } 383 384 385 386 /** {@inheritDoc} */ 387 @Override 388 public final String toString() { 389 StringBuilder builder = new StringBuilder(); 390 toString(builder); 391 return builder.toString(); 392 } 393 394 395 396 /** 397 * Append a string representation of the managed object relation to 398 * the provided string builder. 399 * 400 * @param builder 401 * The string builder where the string representation 402 * should be appended. 403 */ 404 public abstract void toString(StringBuilder builder); 405 406 407 408 /** 409 * Performs any run-time initialization required by this relation 410 * definition. This may include resolving managed object paths and 411 * property names. 412 * 413 * @throws Exception 414 * If this relation definition could not be initialized. 415 */ 416 protected void initialize() throws Exception { 417 // No implementation required. 418 } 419}