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 010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE 011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE. 012 * See the License for the specific language governing permissions 013 * and limitations under the License. 014 * 015 * When distributing Covered Code, include this CDDL HEADER in each 016 * file and include the License file at 017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, 018 * add the following below this CDDL HEADER, with the fields enclosed 019 * by brackets "[]" replaced with your own identifying information: 020 * Portions Copyright [yyyy] [name of copyright owner] 021 * 022 * CDDL HEADER END 023 * 024 * 025 * Copyright 2008 Sun Microsystems, Inc. 026 */ 027 028 package org.opends.server.admin; 029 import org.opends.messages.Message; 030 031 032 033 import static org.opends.server.util.Validator.*; 034 035 import java.util.EnumSet; 036 import java.util.Locale; 037 import java.util.MissingResourceException; 038 import 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". 072 * </ul> 073 * Whereas, aggregations are represented by storing the DNs of the 074 * referenced managed objects in an attribute of the aggregating 075 * managed object. 076 * 077 * @param <C> 078 * The type of client managed object configuration that this 079 * relation definition refers to. 080 * @param <S> 081 * The type of server managed object configuration that this 082 * relation definition refers to. 083 */ 084 public abstract class RelationDefinition 085 <C extends ConfigurationClient, S extends Configuration> { 086 087 /** 088 * An interface for incrementally constructing relation definitions. 089 * 090 * @param <C> 091 * The type of client managed object configuration that 092 * this relation definition refers to. 093 * @param <S> 094 * The type of server managed object configuration that 095 * this relation definition refers to. 096 * @param <D> 097 * The type of relation definition constructed by this 098 * builder. 099 */ 100 protected abstract static class AbstractBuilder 101 <C extends ConfigurationClient, S extends Configuration, 102 D extends RelationDefinition<C, S>> { 103 104 // Common fields. 105 private final Common<C, S> common; 106 107 108 109 /** 110 * Create a property definition builder. 111 * 112 * @param pd 113 * The parent managed object definition. 114 * @param name 115 * The name of the relation. 116 * @param cd 117 * The child managed object definition. 118 */ 119 protected AbstractBuilder(AbstractManagedObjectDefinition<?, ?> pd, 120 String name, AbstractManagedObjectDefinition<C, S> cd) { 121 this.common = new Common<C, S>(pd, name, cd); 122 } 123 124 125 126 /** 127 * Construct a relation definition based on the properties of this 128 * builder. 129 * 130 * @return The new relation definition. 131 */ 132 public final D getInstance() { 133 return buildInstance(common); 134 } 135 136 137 138 /** 139 * Add a relation definition option. 140 * 141 * @param option 142 * The relation option. 143 */ 144 public final void setOption(RelationOption option) { 145 ensureNotNull(option); 146 common.options.add(option); 147 } 148 149 150 151 /** 152 * Build a relation definition based on the properties of this 153 * builder. 154 * 155 * @param common 156 * The common fields of the new relation definition. 157 * @return The new relation definition. 158 */ 159 protected abstract D buildInstance(Common<C, S> common); 160 } 161 162 163 164 /** 165 * Opaque structure containing fields common to all relation 166 * definition types. 167 * 168 * @param <C> 169 * The type of client managed object configuration that 170 * this relation definition refers to. 171 * @param <S> 172 * The type of server managed object configuration that 173 * this relation definition refers to. 174 */ 175 protected static final class Common 176 <C extends ConfigurationClient, S extends Configuration> { 177 178 // The definition of the child managed object. 179 private final AbstractManagedObjectDefinition<C, S> cd; 180 181 // The name of the relation. 182 private final String name; 183 184 // Options applicable to this definition. 185 private final Set<RelationOption> options; 186 187 // The definition of the parent managed object. 188 private final AbstractManagedObjectDefinition<?, ?> pd; 189 190 191 192 // Private constructor. 193 private Common(AbstractManagedObjectDefinition<?, ?> pd, String name, 194 AbstractManagedObjectDefinition<C, S> cd) { 195 this.name = name; 196 this.pd = pd; 197 this.cd = cd; 198 this.options = EnumSet.noneOf(RelationOption.class); 199 } 200 } 201 202 // Common fields. 203 private final Common<C, S> common; 204 205 206 207 /** 208 * Create a new managed object relation definition with the 209 * specified common fields. 210 * 211 * @param common 212 * The common fields of the new relation definition. 213 */ 214 protected RelationDefinition(Common<C, S> common) { 215 this.common = common; 216 } 217 218 219 220 /** 221 * Apply a visitor to this relation definition. 222 * 223 * @param <R> 224 * The return type of the visitor's methods. 225 * @param <P> 226 * The type of the additional parameters to the visitor's 227 * methods. 228 * @param v 229 * The relation definition visitor. 230 * @param p 231 * Optional additional visitor parameter. 232 * @return Returns a result as specified by the visitor. 233 */ 234 public abstract <R, P> R accept(RelationDefinitionVisitor<R, P> v, P p); 235 236 237 238 /** 239 * Get the definition of the child managed object. 240 * 241 * @return Returns the definition of the child managed object. 242 */ 243 public final AbstractManagedObjectDefinition<C, S> getChildDefinition() { 244 return common.cd; 245 } 246 247 248 249 /** 250 * Gets the optional description of this relation definition in the 251 * default locale. 252 * 253 * @return Returns the description of this relation definition in 254 * the default locale, or <code>null</code> if there is no 255 * description. 256 */ 257 public final Message getDescription() { 258 return getDescription(Locale.getDefault()); 259 } 260 261 262 263 /** 264 * Gets the optional description of this relation definition in the 265 * specified locale. 266 * 267 * @param locale 268 * The locale. 269 * @return Returns the description of this relation definition in 270 * the specified locale, or <code>null</code> if there is 271 * no description. 272 */ 273 public final Message getDescription(Locale locale) { 274 try { 275 String property = "relation." + common.name + ".description"; 276 return ManagedObjectDefinitionI18NResource.getInstance().getMessage( 277 getParentDefinition(), property, locale); 278 } catch (MissingResourceException e) { 279 return null; 280 } 281 } 282 283 284 285 /** 286 * Get the name of the relation. 287 * 288 * @return Returns the name of the relation. 289 */ 290 public final String getName() { 291 return common.name; 292 } 293 294 295 296 /** 297 * Get the definition of the parent managed object. 298 * 299 * @return Returns the definition of the parent managed object. 300 */ 301 public final AbstractManagedObjectDefinition<?, ?> getParentDefinition() { 302 return common.pd; 303 } 304 305 306 307 /** 308 * Gets the synopsis of this relation definition in the default 309 * locale. 310 * 311 * @return Returns the synopsis of this relation definition in the 312 * default locale. 313 */ 314 public final Message getSynopsis() { 315 return getSynopsis(Locale.getDefault()); 316 } 317 318 319 320 /** 321 * Gets the synopsis of this relation definition in the specified 322 * locale. 323 * 324 * @param locale 325 * The locale. 326 * @return Returns the synopsis of this relation definition in the 327 * specified locale. 328 */ 329 public final Message getSynopsis(Locale locale) { 330 String property = "relation." + common.name + ".synopsis"; 331 return ManagedObjectDefinitionI18NResource.getInstance().getMessage( 332 getParentDefinition(), property, locale); 333 } 334 335 336 337 /** 338 * Gets the user friendly name of this relation definition in the 339 * default locale. 340 * 341 * @return Returns the user friendly name of this relation 342 * definition in the default locale. 343 */ 344 public final Message getUserFriendlyName() { 345 return getUserFriendlyName(Locale.getDefault()); 346 } 347 348 349 350 /** 351 * Gets the user friendly name of this relation definition in the 352 * specified locale. 353 * 354 * @param locale 355 * The locale. 356 * @return Returns the user friendly name of this relation 357 * definition in the specified locale. 358 */ 359 public final Message getUserFriendlyName(Locale locale) { 360 String property = "relation." + common.name + ".user-friendly-name"; 361 return ManagedObjectDefinitionI18NResource.getInstance().getMessage( 362 getParentDefinition(), property, locale); 363 } 364 365 366 367 /** 368 * Check if the specified option is set for this relation 369 * definition. 370 * 371 * @param option 372 * The option to test. 373 * @return Returns <code>true</code> if the option is set, or 374 * <code>false</code> otherwise. 375 */ 376 public final boolean hasOption(RelationOption option) { 377 return common.options.contains(option); 378 } 379 380 381 382 /** 383 * {@inheritDoc} 384 */ 385 @Override 386 public final String toString() { 387 StringBuilder builder = new StringBuilder(); 388 toString(builder); 389 return builder.toString(); 390 } 391 392 393 394 /** 395 * Append a string representation of the managed object relation to 396 * the provided string builder. 397 * 398 * @param builder 399 * The string builder where the string representation 400 * should be appended. 401 */ 402 public abstract void toString(StringBuilder builder); 403 404 405 406 /** 407 * Performs any run-time initialization required by this relation 408 * definition. This may include resolving managed object paths and 409 * property names. 410 * 411 * @throws Exception 412 * If this relation definition could not be initialized. 413 */ 414 protected void initialize() throws Exception { 415 // No implementation required. 416 } 417 }