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