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