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