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