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