35ba29ed176b4593fceb6577bff77af11254b25c
[controller.git] / opendaylight / config / config-manager / src / main / java / org / opendaylight / controller / config / manager / impl / dynamicmbean / AttributeHolder.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.controller.config.manager.impl.dynamicmbean;
9
10 import java.lang.reflect.Method;
11 import java.util.HashSet;
12 import java.util.List;
13 import java.util.Set;
14 import javax.annotation.Nullable;
15 import javax.annotation.concurrent.Immutable;
16 import javax.management.MBeanAttributeInfo;
17 import javax.management.ObjectName;
18 import org.opendaylight.controller.config.api.annotations.Description;
19 import org.opendaylight.controller.config.api.annotations.RequireInterface;
20
21 @Immutable
22 class AttributeHolder {
23
24     private final String name;
25     private final String description;
26     private final Object object;
27     private final boolean writable;
28
29     @Nullable
30     private final RequireInterface requireInterfaceAnnotation;
31     private final String attributeType;
32
33     public static final Set<Class<?>> PERMITTED_PARAMETER_TYPES_FOR_DEPENDENCY_SETTER = new HashSet<>();
34
35     static {
36         PERMITTED_PARAMETER_TYPES_FOR_DEPENDENCY_SETTER.add(ObjectName.class);
37         PERMITTED_PARAMETER_TYPES_FOR_DEPENDENCY_SETTER.add(ObjectName[].class);
38         PERMITTED_PARAMETER_TYPES_FOR_DEPENDENCY_SETTER.add(List.class);
39     }
40
41     public AttributeHolder(String name, Object object, String returnType,
42                            boolean writable,
43                            @Nullable RequireInterface requireInterfaceAnnotation,
44                            String description) {
45         if (name == null) {
46             throw new NullPointerException();
47         }
48         this.name = name;
49         if (object == null) {
50             throw new NullPointerException();
51         }
52         this.object = object;
53         this.writable = writable;
54         this.requireInterfaceAnnotation = requireInterfaceAnnotation;
55         this.attributeType = returnType;
56         this.description = description;
57     }
58
59     public MBeanAttributeInfo toMBeanAttributeInfo() {
60         MBeanAttributeInfo info = new MBeanAttributeInfo(name, attributeType,
61                 description, true, true, false);
62         return info;
63     }
64
65     /**
66      * @return annotation if setter sets ObjectName or ObjectName[], and is
67      * annotated. Return null otherwise.
68      */
69     RequireInterface getRequireInterfaceOrNull() {
70         return requireInterfaceAnnotation;
71     }
72
73     public String getName() {
74         return name;
75     }
76
77     public Object getObject() {
78         return object;
79     }
80
81     public String getAttributeType() {
82         return attributeType;
83     }
84
85     public boolean isWritable() {
86         return writable;
87     }
88
89     public String getDescription() {
90         return description;
91     }
92
93     /**
94      * Find @Description annotations in method class and all its exported
95      * interfaces.
96      *
97      * @param setter
98      * @param jmxInterfaces
99      * @return empty string if no annotation is found, or list of descriptions
100      * separated by newline
101      */
102     static String findDescription(Method setter, Set<Class<?>> jmxInterfaces) {
103         List<Description> descriptions = AnnotationsHelper
104                 .findMethodAnnotationInSuperClassesAndIfcs(setter, Description.class, jmxInterfaces);
105         return AnnotationsHelper.aggregateDescriptions(descriptions);
106     }
107
108     /**
109      * Find @RequireInterface annotation by searching method class and all
110      * exported interfaces.
111      *
112      * @param setter
113      * @param inspectedInterfaces
114      * @return null if no annotation is found, otherwise return the annotation
115      * @throws IllegalStateException    if more than one value is specified by found annotations
116      * @throws IllegalArgumentException if set of exported interfaces contains non interface type
117      */
118     static RequireInterface findRequireInterfaceAnnotation(final Method setter,
119                                                            Set<Class<?>> inspectedInterfaces) {
120
121         // only allow setX(ObjectName y) or setX(ObjectName[] y) or setX(List<ObjectName> y) to continue
122
123         if (setter.getParameterTypes().length > 1) {
124             return null;
125         }
126         if (PERMITTED_PARAMETER_TYPES_FOR_DEPENDENCY_SETTER.contains(setter.getParameterTypes()[0]) == false) {
127             return null;
128         }
129
130         List<RequireInterface> foundRequireInterfaces = AnnotationsHelper
131                 .findMethodAnnotationInSuperClassesAndIfcs(setter, RequireInterface.class, inspectedInterfaces);
132         // make sure the list if not empty contains always annotation with same
133         // value
134         Set<Class<?>> foundValues = new HashSet<Class<?>>();
135         for (RequireInterface ri : foundRequireInterfaces) {
136             foundValues.add(ri.value());
137         }
138         if (foundValues.isEmpty()) {
139             return null;
140         } else if (foundValues.size() > 1) {
141             throw new IllegalStateException("Error finding @RequireInterface. "
142                     + "More than one value specified as required interface "
143                     + foundValues + " of " + setter + " of "
144                     + setter.getDeclaringClass());
145         } else {
146             return foundRequireInterfaces.get(0);
147         }
148     }
149 }