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 2007-2010 Sun Microsystems, Inc. 025 * Portions Copyright 2015 ForgeRock AS. 026 */ 027package org.forgerock.opendj.config; 028 029import java.util.ArrayList; 030import java.util.Collection; 031import java.util.Collections; 032import java.util.EnumSet; 033import java.util.HashMap; 034import java.util.HashSet; 035import java.util.LinkedList; 036import java.util.List; 037import java.util.Locale; 038import java.util.Map; 039import java.util.MissingResourceException; 040import java.util.Set; 041import java.util.Vector; 042 043import org.forgerock.i18n.LocalizableMessage; 044import org.forgerock.opendj.config.DefinitionDecodingException.Reason; 045 046/** 047 * Defines the structure of an abstract managed object. Abstract managed objects 048 * cannot be instantiated. 049 * <p> 050 * Applications can query a managed object definition in order to determine the 051 * overall configuration model of an application. 052 * 053 * @param <C> 054 * The type of client managed object configuration that this 055 * definition represents. 056 * @param <S> 057 * The type of server managed object configuration that this 058 * definition represents. 059 */ 060public abstract class AbstractManagedObjectDefinition<C extends ConfigurationClient, S extends Configuration> { 061 062 /** The name of the definition. */ 063 private final String name; 064 065 /** The parent managed object definition if applicable. */ 066 private final AbstractManagedObjectDefinition<? super C, ? super S> parent; 067 068 /** The set of constraints associated with this managed object definition. */ 069 private final Collection<Constraint> constraints = new LinkedList<>(); 070 /** The set of property definitions applicable to this managed object definition. */ 071 private final Map<String, PropertyDefinition<?>> propertyDefinitions = new HashMap<>(); 072 /** The set of relation definitions applicable to this managed object definition. */ 073 private final Map<String, RelationDefinition<?, ?>> relationDefinitions = new HashMap<>(); 074 /** The set of relation definitions directly referencing this managed object definition. */ 075 private final Set<RelationDefinition<C, S>> reverseRelationDefinitions = new HashSet<>(); 076 077 /** 078 * The set of all property definitions associated with this managed 079 * object definition including inherited property definitions. 080 */ 081 private final Map<String, PropertyDefinition<?>> allPropertyDefinitions = new HashMap<>(); 082 /** 083 * The set of all relation definitions associated with this managed 084 * object definition including inherited relation definitions. 085 */ 086 private final Map<String, RelationDefinition<?, ?>> allRelationDefinitions = new HashMap<>(); 087 088 /** The set of aggregation property definitions applicable to this managed object definition. */ 089 private final Map<String, AggregationPropertyDefinition<?, ?>> aggregationPropertyDefinitions = new HashMap<>(); 090 091 /** The set of aggregation property definitions directly referencing this managed object definition. */ 092 private final Vector<AggregationPropertyDefinition<?, ?>> reverseAggregationPropertyDefinitions = new Vector<>(); 093 094 /** 095 * The set of all aggregation property definitions associated with this 096 * managed object definition including inherited relation definitions. 097 */ 098 private final Map<String, AggregationPropertyDefinition<?, ?>> allAggregationPropertyDefinitions = new HashMap<>(); 099 100 /** The set of tags associated with this managed object. */ 101 private final Set<Tag> allTags = new HashSet<>(); 102 103 /** Options applicable to this definition. */ 104 private final Set<ManagedObjectOption> options = EnumSet.noneOf(ManagedObjectOption.class); 105 106 /** The set of managed object definitions which inherit from this definition. */ 107 private final Map<String, AbstractManagedObjectDefinition<? extends C, ? extends S>> children = new HashMap<>(); 108 109 /** 110 * Create a new abstract managed object definition. 111 * 112 * @param name 113 * The name of the definition. 114 * @param parent 115 * The parent definition, or <code>null</code> if there is no 116 * parent (only the {@link TopCfgDefn} should have a 117 * <code>null</code> parent, unless the definition is being used 118 * for testing). 119 */ 120 protected AbstractManagedObjectDefinition(String name, 121 AbstractManagedObjectDefinition<? super C, ? super S> parent) { 122 this.name = name; 123 this.parent = parent; 124 125 // If we have a parent definition then inherit its features. 126 if (parent != null) { 127 registerInParent(); 128 129 for (PropertyDefinition<?> pd : parent.getAllPropertyDefinitions()) { 130 allPropertyDefinitions.put(pd.getName(), pd); 131 } 132 133 for (RelationDefinition<?, ?> rd : parent.getAllRelationDefinitions()) { 134 allRelationDefinitions.put(rd.getName(), rd); 135 } 136 137 for (AggregationPropertyDefinition<?, ?> apd : parent.getAllAggregationPropertyDefinitions()) { 138 allAggregationPropertyDefinitions.put(apd.getName(), apd); 139 } 140 // Tag inheritance is performed during preprocessing. 141 } 142 } 143 144 /** 145 * Get all the child managed object definitions which inherit from this 146 * managed object definition. 147 * 148 * @return Returns an unmodifiable collection containing all the subordinate 149 * managed object definitions which inherit from this managed object 150 * definition. 151 */ 152 public final Collection<AbstractManagedObjectDefinition<? extends C, ? extends S>> getAllChildren() { 153 List<AbstractManagedObjectDefinition<? extends C, ? extends S>> list = new ArrayList<>(children.values()); 154 155 for (AbstractManagedObjectDefinition<? extends C, ? extends S> child : children.values()) { 156 list.addAll(child.getAllChildren()); 157 } 158 159 return Collections.unmodifiableCollection(list); 160 } 161 162 /** 163 * Get all the constraints associated with this type of managed object. The 164 * returned collection will contain inherited constraints. 165 * 166 * @return Returns a collection containing all the constraints associated 167 * with this type of managed object. The caller is free to modify 168 * the collection if required. 169 */ 170 public final Collection<Constraint> getAllConstraints() { 171 // This method does not used a cached set of constraints because 172 // constraints may be updated after child definitions have been defined. 173 List<Constraint> allConstraints = new LinkedList<>(); 174 175 if (parent != null) { 176 allConstraints.addAll(parent.getAllConstraints()); 177 } 178 allConstraints.addAll(constraints); 179 180 return allConstraints; 181 } 182 183 /** 184 * Get all the property definitions associated with this type of managed 185 * object. The returned collection will contain inherited property 186 * definitions. 187 * 188 * @return Returns an unmodifiable collection containing all the property 189 * definitions associated with this type of managed object. 190 */ 191 public final Collection<PropertyDefinition<?>> getAllPropertyDefinitions() { 192 return Collections.unmodifiableCollection(allPropertyDefinitions.values()); 193 } 194 195 /** 196 * Get all the relation definitions associated with this type of managed 197 * object. The returned collection will contain inherited relation 198 * definitions. 199 * 200 * @return Returns an unmodifiable collection containing all the relation 201 * definitions associated with this type of managed object. 202 */ 203 public final Collection<RelationDefinition<?, ?>> getAllRelationDefinitions() { 204 return Collections.unmodifiableCollection(allRelationDefinitions.values()); 205 } 206 207 /** 208 * Get all the relation definitions which refer to this managed object 209 * definition. The returned collection will contain relation definitions 210 * which refer to parents of this managed object definition. 211 * 212 * @return Returns a collection containing all the relation definitions 213 * which refer to this managed object definition. The caller is free 214 * to modify the collection if required. 215 */ 216 public final Collection<RelationDefinition<? super C, ? super S>> getAllReverseRelationDefinitions() { 217 // This method does not used a cached set of relations because 218 // relations may be updated after child definitions have been defined. 219 List<RelationDefinition<? super C, ? super S>> rdlist = new LinkedList<>(); 220 221 if (parent != null) { 222 rdlist.addAll(parent.getAllReverseRelationDefinitions()); 223 } 224 rdlist.addAll(reverseRelationDefinitions); 225 226 return rdlist; 227 } 228 229 /** 230 * Get all the aggregation property definitions associated with this type of 231 * managed object. The returned collection will contain inherited 232 * aggregation property definitions. 233 * 234 * @return Returns an unmodifiable collection containing all the aggregation 235 * property definitions associated with this type of managed object. 236 */ 237 public final Collection<AggregationPropertyDefinition<?, ?>> getAllAggregationPropertyDefinitions() { 238 return Collections.unmodifiableCollection(allAggregationPropertyDefinitions.values()); 239 } 240 241 /** 242 * Get all the aggregation property definitions which refer to this managed 243 * object definition. The returned collection will contain aggregation 244 * property definitions which refer to parents of this managed object 245 * definition. 246 * 247 * @return Returns a collection containing all the aggregation property 248 * definitions which refer to this managed object definition. The 249 * caller is free to modify the collection if required. 250 */ 251 public final Collection<AggregationPropertyDefinition<?, ?>> getAllReverseAggregationPropertyDefinitions() { 252 // This method does not used a cached set of aggregation properties because 253 // aggregation properties may be updated after child definitions have been defined. 254 List<AggregationPropertyDefinition<?, ?>> apdlist = new LinkedList<>(); 255 256 if (parent != null) { 257 apdlist.addAll(parent.getAllReverseAggregationPropertyDefinitions()); 258 } 259 apdlist.addAll(reverseAggregationPropertyDefinitions); 260 261 return apdlist; 262 } 263 264 /** 265 * Get all the tags associated with this type of managed object. The 266 * returned collection will contain inherited tags. 267 * 268 * @return Returns an unmodifiable collection containing all the tags 269 * associated with this type of managed object. 270 */ 271 public final Collection<Tag> getAllTags() { 272 return Collections.unmodifiableCollection(allTags); 273 } 274 275 /** 276 * Get the named child managed object definition which inherits from this 277 * managed object definition. This method will recursively search down 278 * through the inheritance hierarchy. 279 * 280 * @param name 281 * The name of the managed object definition sub-type. 282 * @return Returns the named child managed object definition which inherits 283 * from this managed object definition. 284 * @throws IllegalArgumentException 285 * If the specified managed object definition name was null or 286 * empty or if the requested subordinate managed object 287 * definition was not found. 288 */ 289 public final AbstractManagedObjectDefinition<? extends C, ? extends S> getChild(String name) { 290 if (name == null || name.length() == 0) { 291 throw new IllegalArgumentException("null or empty managed object name"); 292 } 293 294 AbstractManagedObjectDefinition<? extends C, ? extends S> d = children.get(name); 295 296 if (d == null) { 297 // Recursively search. 298 for (AbstractManagedObjectDefinition<? extends C, ? extends S> child : children.values()) { 299 try { 300 d = child.getChild(name); 301 break; 302 } catch (IllegalArgumentException e) { 303 // Try the next child. 304 } 305 } 306 } 307 308 if (d == null) { 309 throw new IllegalArgumentException("child managed object definition \"" + name + "\" not found"); 310 } 311 312 return d; 313 } 314 315 /** 316 * Get the child managed object definitions which inherit directly from this 317 * managed object definition. 318 * 319 * @return Returns an unmodifiable collection containing the subordinate 320 * managed object definitions which inherit directly from this 321 * managed object definition. 322 */ 323 public final Collection<AbstractManagedObjectDefinition<? extends C, ? extends S>> getChildren() { 324 return Collections.unmodifiableCollection(children.values()); 325 } 326 327 /** 328 * Get the constraints defined by this managed object definition. The 329 * returned collection will not contain inherited constraints. 330 * 331 * @return Returns an unmodifiable collection containing the constraints 332 * defined by this managed object definition. 333 */ 334 public final Collection<Constraint> getConstraints() { 335 return Collections.unmodifiableCollection(constraints); 336 } 337 338 /** 339 * Gets the optional description of this managed object definition in the 340 * default locale. 341 * 342 * @return Returns the description of this managed object definition in the 343 * default locale, or <code>null</code> if there is no description. 344 * @throws UnsupportedOperationException 345 * If this managed object definition is the {@link TopCfgDefn}. 346 */ 347 public final LocalizableMessage getDescription() { 348 return getDescription(Locale.getDefault()); 349 } 350 351 /** 352 * Gets the optional description of this managed object definition in the 353 * specified locale. 354 * 355 * @param locale 356 * The locale. 357 * @return Returns the description of this managed object definition in the 358 * specified locale, or <code>null</code> if there is no 359 * description. 360 * @throws UnsupportedOperationException 361 * If this managed object definition is the {@link TopCfgDefn}. 362 */ 363 public final LocalizableMessage getDescription(Locale locale) { 364 try { 365 return ManagedObjectDefinitionI18NResource.getInstance().getMessage(this, "description", locale); 366 } catch (MissingResourceException e) { 367 return null; 368 } 369 } 370 371 /** 372 * Get the name of the definition. 373 * 374 * @return Returns the name of the definition. 375 */ 376 public final String getName() { 377 return name; 378 } 379 380 /** 381 * Get the parent managed object definition, if applicable. 382 * 383 * @return Returns the parent of this managed object definition, or 384 * <code>null</code> if this definition is the {@link TopCfgDefn}. 385 */ 386 public final AbstractManagedObjectDefinition<? super C, ? super S> getParent() { 387 return parent; 388 } 389 390 /** 391 * Get the specified property definition associated with this type of 392 * managed object. The search will include any inherited property 393 * definitions. 394 * 395 * @param name 396 * The name of the property definition to be retrieved. 397 * @return Returns the specified property definition associated with this 398 * type of managed object. 399 * @throws IllegalArgumentException 400 * If the specified property name was null or empty or if the 401 * requested property definition was not found. 402 */ 403 public final PropertyDefinition<?> getPropertyDefinition(String name) { 404 if (name == null || name.length() == 0) { 405 throw new IllegalArgumentException("null or empty property name"); 406 } 407 408 PropertyDefinition<?> d = allPropertyDefinitions.get(name); 409 if (d == null) { 410 throw new IllegalArgumentException("property definition \"" + name + "\" not found"); 411 } 412 413 return d; 414 } 415 416 /** 417 * Get the property definitions defined by this managed object definition. 418 * The returned collection will not contain inherited property definitions. 419 * 420 * @return Returns an unmodifiable collection containing the property 421 * definitions defined by this managed object definition. 422 */ 423 public final Collection<PropertyDefinition<?>> getPropertyDefinitions() { 424 return Collections.unmodifiableCollection(propertyDefinitions.values()); 425 } 426 427 /** 428 * Get the specified relation definition associated with this type of 429 * managed object.The search will include any inherited relation 430 * definitions. 431 * 432 * @param name 433 * The name of the relation definition to be retrieved. 434 * @return Returns the specified relation definition associated with this 435 * type of managed object. 436 * @throws IllegalArgumentException 437 * If the specified relation name was null or empty or if the 438 * requested relation definition was not found. 439 */ 440 public final RelationDefinition<?, ?> getRelationDefinition(String name) { 441 if (name == null || name.length() == 0) { 442 throw new IllegalArgumentException("null or empty relation name"); 443 } 444 445 RelationDefinition<?, ?> d = allRelationDefinitions.get(name); 446 if (d == null) { 447 throw new IllegalArgumentException("relation definition \"" + name + "\" not found"); 448 } 449 450 return d; 451 } 452 453 /** 454 * Get the relation definitions defined by this managed object definition. 455 * The returned collection will not contain inherited relation definitions. 456 * 457 * @return Returns an unmodifiable collection containing the relation 458 * definitions defined by this managed object definition. 459 */ 460 public final Collection<RelationDefinition<?, ?>> getRelationDefinitions() { 461 return Collections.unmodifiableCollection(relationDefinitions.values()); 462 } 463 464 /** 465 * Get the relation definitions which refer directly to this managed object 466 * definition. The returned collection will not contain relation definitions 467 * which refer to parents of this managed object definition. 468 * 469 * @return Returns an unmodifiable collection containing the relation 470 * definitions which refer directly to this managed object 471 * definition. 472 */ 473 public final Collection<RelationDefinition<C, S>> getReverseRelationDefinitions() { 474 return Collections.unmodifiableCollection(reverseRelationDefinitions); 475 } 476 477 /** 478 * Get the specified aggregation property definition associated with this 479 * type of managed object.The search will include any inherited aggregation 480 * property definitions. 481 * 482 * @param name 483 * The name of the aggregation property definition to be 484 * retrieved. 485 * @return Returns the specified aggregation property definition associated 486 * with this type of managed object. 487 * @throws IllegalArgumentException 488 * If the specified aggregation property name was null or empty 489 * or if the requested aggregation property definition was not 490 * found. 491 */ 492 public final AggregationPropertyDefinition<?, ?> getAggregationPropertyDefinition(String name) { 493 if (name == null || name.length() == 0) { 494 throw new IllegalArgumentException("null or empty aggregation property name"); 495 } 496 497 AggregationPropertyDefinition<?, ?> d = allAggregationPropertyDefinitions.get(name); 498 if (d == null) { 499 throw new IllegalArgumentException("aggregation property definition \"" + name + "\" not found"); 500 } 501 502 return d; 503 } 504 505 /** 506 * Get the aggregation property definitions defined by this managed object 507 * definition. The returned collection will not contain inherited 508 * aggregation property definitions. 509 * 510 * @return Returns an unmodifiable collection containing the aggregation 511 * property definitions defined by this managed object definition. 512 */ 513 public final Collection<AggregationPropertyDefinition<?, ?>> getAggregationPropertyDefinitions() { 514 return Collections.unmodifiableCollection(aggregationPropertyDefinitions.values()); 515 } 516 517 /** 518 * Get the aggregation property definitions which refer directly to this 519 * managed object definition. The returned collection will not contain 520 * aggregation property definitions which refer to parents of this managed 521 * object definition. 522 * 523 * @return Returns an unmodifiable collection containing the aggregation 524 * property definitions which refer directly to this managed object 525 * definition. 526 */ 527 public final Collection<AggregationPropertyDefinition<?, ?>> getReverseAggregationPropertyDefinitions() { 528 return Collections.unmodifiableCollection(reverseAggregationPropertyDefinitions); 529 } 530 531 /** 532 * Gets the synopsis of this managed object definition in the default 533 * locale. 534 * 535 * @return Returns the synopsis of this managed object definition in the 536 * default locale. 537 * @throws UnsupportedOperationException 538 * If this managed object definition is the {@link TopCfgDefn}. 539 */ 540 public final LocalizableMessage getSynopsis() { 541 return getSynopsis(Locale.getDefault()); 542 } 543 544 /** 545 * Gets the synopsis of this managed object definition in the specified 546 * locale. 547 * 548 * @param locale 549 * The locale. 550 * @return Returns the synopsis of this managed object definition in the 551 * specified locale. 552 * @throws UnsupportedOperationException 553 * If this managed object definition is the {@link TopCfgDefn}. 554 */ 555 public final LocalizableMessage getSynopsis(Locale locale) { 556 return ManagedObjectDefinitionI18NResource.getInstance().getMessage(this, "synopsis", locale); 557 } 558 559 /** 560 * Gets the user friendly name of this managed object definition in the 561 * default locale. 562 * 563 * @return Returns the user friendly name of this managed object definition 564 * in the default locale. 565 * @throws UnsupportedOperationException 566 * If this managed object definition is the {@link TopCfgDefn}. 567 */ 568 public final LocalizableMessage getUserFriendlyName() { 569 return getUserFriendlyName(Locale.getDefault()); 570 } 571 572 /** 573 * Gets the user friendly name of this managed object definition in the 574 * specified locale. 575 * 576 * @param locale 577 * The locale. 578 * @return Returns the user friendly name of this managed object definition 579 * in the specified locale. 580 * @throws UnsupportedOperationException 581 * If this managed object definition is the {@link TopCfgDefn}. 582 */ 583 public final LocalizableMessage getUserFriendlyName(Locale locale) { 584 return LocalizableMessage.raw(ManagedObjectDefinitionI18NResource.getInstance().getMessage(this, 585 "user-friendly-name", locale)); 586 } 587 588 /** 589 * Gets the user friendly plural name of this managed object definition in 590 * the default locale. 591 * 592 * @return Returns the user friendly plural name of this managed object 593 * definition in the default locale. 594 * @throws UnsupportedOperationException 595 * If this managed object definition is the {@link TopCfgDefn}. 596 */ 597 public final LocalizableMessage getUserFriendlyPluralName() { 598 return getUserFriendlyPluralName(Locale.getDefault()); 599 } 600 601 /** 602 * Gets the user friendly plural name of this managed object definition in 603 * the specified locale. 604 * 605 * @param locale 606 * The locale. 607 * @return Returns the user friendly plural name of this managed object 608 * definition in the specified locale. 609 * @throws UnsupportedOperationException 610 * If this managed object definition is the {@link TopCfgDefn}. 611 */ 612 public final LocalizableMessage getUserFriendlyPluralName(Locale locale) { 613 return ManagedObjectDefinitionI18NResource.getInstance() 614 .getMessage(this, "user-friendly-plural-name", locale); 615 } 616 617 /** 618 * Determine whether there are any child managed object definitions which 619 * inherit from this managed object definition. 620 * 621 * @return Returns <code>true</code> if this type of managed object has any 622 * child managed object definitions, <code>false</code> otherwise. 623 */ 624 public final boolean hasChildren() { 625 return !children.isEmpty(); 626 } 627 628 /** 629 * Determines whether or not this managed object definition has the 630 * specified option. 631 * 632 * @param option 633 * The option to test. 634 * @return Returns <code>true</code> if the option is set, or 635 * <code>false</code> otherwise. 636 */ 637 public final boolean hasOption(ManagedObjectOption option) { 638 return options.contains(option); 639 } 640 641 /** 642 * Determines whether or not this managed object definition has the 643 * specified tag. 644 * 645 * @param t 646 * The tag definition. 647 * @return Returns <code>true</code> if this managed object definition has 648 * the specified tag. 649 */ 650 public final boolean hasTag(Tag t) { 651 return allTags.contains(t); 652 } 653 654 /** 655 * Determines whether or not this managed object definition is a sub-type of 656 * the provided managed object definition. This managed object definition is 657 * a sub-type of the provided managed object definition if they are both the 658 * same or if the provided managed object definition can be obtained by 659 * recursive invocations of the {@link #getParent()} method. 660 * 661 * @param d 662 * The managed object definition to be checked. 663 * @return Returns <code>true</code> if this managed object definition is a 664 * sub-type of the provided managed object definition. 665 */ 666 public final boolean isChildOf(AbstractManagedObjectDefinition<?, ?> d) { 667 AbstractManagedObjectDefinition<?, ?> i; 668 for (i = this; i != null; i = i.parent) { 669 if (i == d) { 670 return true; 671 } 672 } 673 return false; 674 } 675 676 /** 677 * Determines whether or not this managed object definition is a super-type 678 * of the provided managed object definition. This managed object definition 679 * is a super-type of the provided managed object definition if they are 680 * both the same or if the provided managed object definition is a member of 681 * the set of children returned from {@link #getAllChildren()}. 682 * 683 * @param d 684 * The managed object definition to be checked. 685 * @return Returns <code>true</code> if this managed object definition is a 686 * super-type of the provided managed object definition. 687 */ 688 public final boolean isParentOf(AbstractManagedObjectDefinition<?, ?> d) { 689 return d.isChildOf(this); 690 } 691 692 /** 693 * Determines whether or not this managed object definition is the 694 * {@link TopCfgDefn}. 695 * 696 * @return Returns <code>true</code> if this managed object definition is 697 * the {@link TopCfgDefn}. 698 */ 699 public final boolean isTop() { 700 return this instanceof TopCfgDefn; 701 } 702 703 /** 704 * Finds a sub-type of this managed object definition which most closely 705 * corresponds to the matching criteria of the provided definition resolver. 706 * 707 * @param r 708 * The definition resolver. 709 * @return Returns the sub-type of this managed object definition which most 710 * closely corresponds to the matching criteria of the provided 711 * definition resolver. 712 * @throws DefinitionDecodingException 713 * If no matching sub-type could be found or if the resolved 714 * definition was abstract. 715 * @see DefinitionResolver 716 */ 717 public final ManagedObjectDefinition<? extends C, ? extends S> resolveManagedObjectDefinition(DefinitionResolver r) 718 throws DefinitionDecodingException { 719 AbstractManagedObjectDefinition<? extends C, ? extends S> rd; 720 rd = resolveManagedObjectDefinitionAux(this, r); 721 if (rd == null) { 722 // Unable to resolve the definition. 723 throw new DefinitionDecodingException(this, Reason.WRONG_TYPE_INFORMATION); 724 } else if (rd instanceof ManagedObjectDefinition) { 725 return (ManagedObjectDefinition<? extends C, ? extends S>) rd; 726 } else { 727 // Resolved definition was abstract. 728 throw new DefinitionDecodingException(this, Reason.ABSTRACT_TYPE_INFORMATION); 729 } 730 } 731 732 /** {@inheritDoc} */ 733 @Override 734 public final String toString() { 735 StringBuilder builder = new StringBuilder(); 736 toString(builder); 737 return builder.toString(); 738 } 739 740 /** 741 * Append a string representation of the managed object definition to the 742 * provided string builder. 743 * 744 * @param builder 745 * The string builder where the string representation should be 746 * appended. 747 */ 748 public final void toString(StringBuilder builder) { 749 builder.append(getName()); 750 } 751 752 /** 753 * Initializes all of the components associated with this managed object 754 * definition. 755 * 756 * @throws Exception 757 * If this managed object definition could not be initialized. 758 */ 759 protected final void initialize() throws Exception { 760 for (PropertyDefinition<?> pd : getAllPropertyDefinitions()) { 761 pd.initialize(); 762 pd.getDefaultBehaviorProvider().initialize(); 763 } 764 765 for (RelationDefinition<?, ?> rd : getAllRelationDefinitions()) { 766 rd.initialize(); 767 } 768 769 for (AggregationPropertyDefinition<?, ?> apd : getAllAggregationPropertyDefinitions()) { 770 771 apd.initialize(); 772 /* 773 * Now register the aggregation property in the referenced managed 774 * object definition for reverse lookups. 775 */ 776 registerReverseAggregationPropertyDefinition(apd); 777 } 778 779 for (Constraint constraint : getAllConstraints()) { 780 constraint.initialize(); 781 } 782 } 783 784 /** 785 * Register a constraint with this managed object definition. 786 * <p> 787 * This method <b>must not</b> be called by applications. 788 * 789 * @param constraint 790 * The constraint to be registered. 791 */ 792 protected final void registerConstraint(Constraint constraint) { 793 constraints.add(constraint); 794 } 795 796 /** 797 * Register a property definition with this managed object definition, 798 * overriding any existing property definition with the same name. 799 * <p> 800 * This method <b>must not</b> be called by applications. 801 * 802 * @param d 803 * The property definition to be registered. 804 */ 805 protected final void registerPropertyDefinition(PropertyDefinition<?> d) { 806 String propName = d.getName(); 807 808 propertyDefinitions.put(propName, d); 809 allPropertyDefinitions.put(propName, d); 810 811 if (d instanceof AggregationPropertyDefinition<?, ?>) { 812 AggregationPropertyDefinition<?, ?> apd = (AggregationPropertyDefinition<?, ?>) d; 813 aggregationPropertyDefinitions.put(propName, apd); 814 // The key must also contain the managed object name, since several 815 // MOs 816 // in an inheritance tree may aggregate the same aggregation 817 // property name 818 allAggregationPropertyDefinitions.put(apd.getManagedObjectDefinition().getName() + ":" + propName, apd); 819 } 820 } 821 822 /** 823 * Register a relation definition with this managed object definition, 824 * overriding any existing relation definition with the same name. 825 * <p> 826 * This method <b>must not</b> be called by applications. 827 * 828 * @param d 829 * The relation definition to be registered. 830 */ 831 protected final void registerRelationDefinition(RelationDefinition<?, ?> d) { 832 // Register the relation in this managed object definition. 833 String relName = d.getName(); 834 835 relationDefinitions.put(relName, d); 836 allRelationDefinitions.put(relName, d); 837 838 // Now register the relation in the referenced managed object 839 // definition for reverse lookups. 840 registerReverseRelationDefinition(d); 841 } 842 843 /** 844 * Register an option with this managed object definition. 845 * <p> 846 * This method <b>must not</b> be called by applications. 847 * 848 * @param option 849 * The option to be registered. 850 */ 851 protected final void registerOption(ManagedObjectOption option) { 852 options.add(option); 853 } 854 855 /** 856 * Register a tag with this managed object definition. 857 * <p> 858 * This method <b>must not</b> be called by applications. 859 * 860 * @param tag 861 * The tag to be registered. 862 */ 863 protected final void registerTag(Tag tag) { 864 allTags.add(tag); 865 } 866 867 /** 868 * Deregister a constraint from the managed object definition. 869 * <p> 870 * This method <b>must not</b> be called by applications and is only 871 * intended for internal testing. 872 * 873 * @param constraint 874 * The constraint to be deregistered. 875 */ 876 final void deregisterConstraint(Constraint constraint) { 877 if (!constraints.remove(constraint)) { 878 throw new RuntimeException("Failed to deregister a constraint"); 879 } 880 } 881 882 /** 883 * Deregister a relation definition from the managed object definition. 884 * <p> 885 * This method <b>must not</b> be called by applications and is only 886 * intended for internal testing. 887 * 888 * @param d 889 * The relation definition to be deregistered. 890 */ 891 final void deregisterRelationDefinition(RelationDefinition<?, ?> d) { 892 // Deregister the relation from this managed object definition. 893 String relName = d.getName(); 894 relationDefinitions.remove(relName); 895 allRelationDefinitions.remove(relName); 896 897 // Now deregister the relation from the referenced managed object 898 // definition for reverse lookups. 899 d.getChildDefinition().reverseRelationDefinitions.remove(d); 900 } 901 902 /** 903 * Register this managed object definition in its parent. 904 * <p> 905 * This method <b>must not</b> be called by applications and is only 906 * intended for internal testing. 907 */ 908 final void registerInParent() { 909 if (parent != null) { 910 parent.children.put(name, this); 911 } 912 } 913 914 /** 915 * Register a relation definition in the referenced managed object 916 * definition's reverse lookup table. 917 */ 918 private <C1 extends ConfigurationClient, S1 extends Configuration> void registerReverseRelationDefinition( 919 RelationDefinition<C1, S1> rd) { 920 rd.getChildDefinition().reverseRelationDefinitions.add(rd); 921 } 922 923 /** 924 * Register a aggregation property definition in the referenced managed 925 * object definition's reverse lookup table. 926 */ 927 private void registerReverseAggregationPropertyDefinition(AggregationPropertyDefinition<?, ?> apd) { 928 929 apd.getRelationDefinition().getChildDefinition().reverseAggregationPropertyDefinitions.add(apd); 930 } 931 932 /** 933 * Recursively descend definition hierarchy to find the best match 934 * definition. 935 */ 936 private AbstractManagedObjectDefinition<? extends C, ? extends S> resolveManagedObjectDefinitionAux( 937 AbstractManagedObjectDefinition<? extends C, ? extends S> d, DefinitionResolver r) { 938 if (!r.matches(d)) { 939 return null; 940 } 941 942 for (AbstractManagedObjectDefinition<? extends C, ? extends S> child : d.getChildren()) { 943 AbstractManagedObjectDefinition<? extends C, ? extends S> rd = 944 resolveManagedObjectDefinitionAux(child, r); 945 if (rd != null) { 946 return rd; 947 } 948 } 949 950 return d; 951 } 952}