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 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 or not 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 or not 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 or not 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 or not 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 or not this managed object definition is the 685 * {@link TopCfgDefn}. 686 * 687 * @return Returns <code>true</code> if this managed object definition is 688 * the {@link TopCfgDefn}. 689 */ 690 public final boolean isTop() { 691 return this instanceof TopCfgDefn; 692 } 693 694 /** 695 * Finds a sub-type of this managed object definition which most closely 696 * corresponds to the matching criteria of the provided definition resolver. 697 * 698 * @param r 699 * The definition resolver. 700 * @return Returns the sub-type of this managed object definition which most 701 * closely corresponds to the matching criteria of the provided 702 * definition resolver. 703 * @throws DefinitionDecodingException 704 * If no matching sub-type could be found or if the resolved 705 * definition was abstract. 706 * @see DefinitionResolver 707 */ 708 public final ManagedObjectDefinition<? extends C, ? extends S> resolveManagedObjectDefinition(DefinitionResolver r) 709 throws DefinitionDecodingException { 710 AbstractManagedObjectDefinition<? extends C, ? extends S> rd; 711 rd = resolveManagedObjectDefinitionAux(this, r); 712 if (rd == null) { 713 // Unable to resolve the definition. 714 throw new DefinitionDecodingException(this, Reason.WRONG_TYPE_INFORMATION); 715 } else if (rd instanceof ManagedObjectDefinition) { 716 return (ManagedObjectDefinition<? extends C, ? extends S>) rd; 717 } else { 718 // Resolved definition was abstract. 719 throw new DefinitionDecodingException(this, Reason.ABSTRACT_TYPE_INFORMATION); 720 } 721 } 722 723 /** {@inheritDoc} */ 724 @Override 725 public final String toString() { 726 StringBuilder builder = new StringBuilder(); 727 toString(builder); 728 return builder.toString(); 729 } 730 731 /** 732 * Append a string representation of the managed object definition to the 733 * provided string builder. 734 * 735 * @param builder 736 * The string builder where the string representation should be 737 * appended. 738 */ 739 public final void toString(StringBuilder builder) { 740 builder.append(getName()); 741 } 742 743 /** 744 * Initializes all of the components associated with this managed object 745 * definition. 746 * 747 * @throws Exception 748 * If this managed object definition could not be initialized. 749 */ 750 protected final void initialize() throws Exception { 751 for (PropertyDefinition<?> pd : getAllPropertyDefinitions()) { 752 pd.initialize(); 753 pd.getDefaultBehaviorProvider().initialize(); 754 } 755 756 for (RelationDefinition<?, ?> rd : getAllRelationDefinitions()) { 757 rd.initialize(); 758 } 759 760 for (AggregationPropertyDefinition<?, ?> apd : getAllAggregationPropertyDefinitions()) { 761 762 apd.initialize(); 763 /* 764 * Now register the aggregation property in the referenced managed 765 * object definition for reverse lookups. 766 */ 767 registerReverseAggregationPropertyDefinition(apd); 768 } 769 770 for (Constraint constraint : getAllConstraints()) { 771 constraint.initialize(); 772 } 773 } 774 775 /** 776 * Register a constraint with this managed object definition. 777 * <p> 778 * This method <b>must not</b> be called by applications. 779 * 780 * @param constraint 781 * The constraint to be registered. 782 */ 783 protected final void registerConstraint(Constraint constraint) { 784 constraints.add(constraint); 785 } 786 787 /** 788 * Register a property definition with this managed object definition, 789 * overriding any existing property definition with the same name. 790 * <p> 791 * This method <b>must not</b> be called by applications. 792 * 793 * @param d 794 * The property definition to be registered. 795 */ 796 protected final void registerPropertyDefinition(PropertyDefinition<?> d) { 797 String propName = d.getName(); 798 799 propertyDefinitions.put(propName, d); 800 allPropertyDefinitions.put(propName, d); 801 802 if (d instanceof AggregationPropertyDefinition<?, ?>) { 803 AggregationPropertyDefinition<?, ?> apd = (AggregationPropertyDefinition<?, ?>) d; 804 aggregationPropertyDefinitions.put(propName, apd); 805 // The key must also contain the managed object name, since several 806 // MOs 807 // in an inheritance tree may aggregate the same aggregation 808 // property name 809 allAggregationPropertyDefinitions.put(apd.getManagedObjectDefinition().getName() + ":" + propName, apd); 810 } 811 } 812 813 /** 814 * Register a relation definition with this managed object definition, 815 * overriding any existing relation definition with the same name. 816 * <p> 817 * This method <b>must not</b> be called by applications. 818 * 819 * @param d 820 * The relation definition to be registered. 821 */ 822 protected final void registerRelationDefinition(RelationDefinition<?, ?> d) { 823 // Register the relation in this managed object definition. 824 String relName = d.getName(); 825 826 relationDefinitions.put(relName, d); 827 allRelationDefinitions.put(relName, d); 828 829 // Now register the relation in the referenced managed object 830 // definition for reverse lookups. 831 registerReverseRelationDefinition(d); 832 } 833 834 /** 835 * Register an option with this managed object definition. 836 * <p> 837 * This method <b>must not</b> be called by applications. 838 * 839 * @param option 840 * The option to be registered. 841 */ 842 protected final void registerOption(ManagedObjectOption option) { 843 options.add(option); 844 } 845 846 /** 847 * Register a tag with this managed object definition. 848 * <p> 849 * This method <b>must not</b> be called by applications. 850 * 851 * @param tag 852 * The tag to be registered. 853 */ 854 protected final void registerTag(Tag tag) { 855 allTags.add(tag); 856 } 857 858 /** 859 * Deregister a constraint from the managed object definition. 860 * <p> 861 * This method <b>must not</b> be called by applications and is only 862 * intended for internal testing. 863 * 864 * @param constraint 865 * The constraint to be deregistered. 866 */ 867 final void deregisterConstraint(Constraint constraint) { 868 if (!constraints.remove(constraint)) { 869 throw new RuntimeException("Failed to deregister a constraint"); 870 } 871 } 872 873 /** 874 * Deregister a relation definition from the managed object definition. 875 * <p> 876 * This method <b>must not</b> be called by applications and is only 877 * intended for internal testing. 878 * 879 * @param d 880 * The relation definition to be deregistered. 881 */ 882 final void deregisterRelationDefinition(RelationDefinition<?, ?> d) { 883 // Deregister the relation from this managed object definition. 884 String relName = d.getName(); 885 relationDefinitions.remove(relName); 886 allRelationDefinitions.remove(relName); 887 888 // Now deregister the relation from the referenced managed object 889 // definition for reverse lookups. 890 d.getChildDefinition().reverseRelationDefinitions.remove(d); 891 } 892 893 /** 894 * Register this managed object definition in its parent. 895 * <p> 896 * This method <b>must not</b> be called by applications and is only 897 * intended for internal testing. 898 */ 899 final void registerInParent() { 900 if (parent != null) { 901 parent.children.put(name, this); 902 } 903 } 904 905 /** 906 * Register a relation definition in the referenced managed object 907 * definition's reverse lookup table. 908 */ 909 private <C1 extends ConfigurationClient, S1 extends Configuration> void registerReverseRelationDefinition( 910 RelationDefinition<C1, S1> rd) { 911 rd.getChildDefinition().reverseRelationDefinitions.add(rd); 912 } 913 914 /** 915 * Register a aggregation property definition in the referenced managed 916 * object definition's reverse lookup table. 917 */ 918 private void registerReverseAggregationPropertyDefinition(AggregationPropertyDefinition<?, ?> apd) { 919 920 apd.getRelationDefinition().getChildDefinition().reverseAggregationPropertyDefinitions.add(apd); 921 } 922 923 /** 924 * Recursively descend definition hierarchy to find the best match 925 * definition. 926 */ 927 private AbstractManagedObjectDefinition<? extends C, ? extends S> resolveManagedObjectDefinitionAux( 928 AbstractManagedObjectDefinition<? extends C, ? extends S> d, DefinitionResolver r) { 929 if (!r.matches(d)) { 930 return null; 931 } 932 933 for (AbstractManagedObjectDefinition<? extends C, ? extends S> child : d.getChildren()) { 934 AbstractManagedObjectDefinition<? extends C, ? extends S> rd = 935 resolveManagedObjectDefinitionAux(child, r); 936 if (rd != null) { 937 return rd; 938 } 939 } 940 941 return d; 942 } 943}