2fa4379f031f7e3e29c46bdeb6944d8a8d13f471
[controller.git] / opendaylight / config / yang-jmx-generator / src / main / java / org / opendaylight / controller / config / yangjmxgenerator / attribute / TOAttribute.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.yangjmxgenerator.attribute;
9
10 import com.google.common.base.Function;
11 import com.google.common.collect.Collections2;
12 import com.google.common.collect.Maps;
13 import com.google.common.collect.Sets;
14 import java.util.ArrayList;
15 import java.util.HashMap;
16 import java.util.List;
17 import java.util.Map;
18 import java.util.Map.Entry;
19 import java.util.Set;
20 import javax.management.openmbean.CompositeType;
21 import javax.management.openmbean.OpenDataException;
22 import javax.management.openmbean.OpenType;
23 import org.opendaylight.controller.config.yangjmxgenerator.TypeProviderWrapper;
24 import org.opendaylight.mdsal.binding.model.api.Type;
25 import org.opendaylight.mdsal.binding.model.util.ReferencedTypeImpl;
26 import org.opendaylight.yangtools.yang.model.api.AugmentationTarget;
27 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
28 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
29 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
30 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
31 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
32 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
33
34 public class TOAttribute extends AbstractAttribute implements TypedAttribute {
35
36     private final String nullableDescription, nullableDefault;
37     private final Map<String, AttributeIfc> yangNameToAttributeMap;
38     private final Map<String, String> attributeNameMap;
39     private final String packageName;
40
41     private static final Set<Class<? extends DataSchemaNode>> ALLOWED_CHILDREN = Sets
42             .newHashSet();
43     static {
44         ALLOWED_CHILDREN.add(LeafListSchemaNode.class);
45         ALLOWED_CHILDREN.add(ListSchemaNode.class);
46         ALLOWED_CHILDREN.add(LeafSchemaNode.class);
47         ALLOWED_CHILDREN.add(ContainerSchemaNode.class);
48     }
49
50     public static <T extends DataNodeContainer & AugmentationTarget & DataSchemaNode> TOAttribute create(
51             final T containerSchemaNode, final TypeProviderWrapper typeProviderWrapper, final String packageName) {
52         // Transfer Object: get the leaves
53         final Map<String, AttributeIfc> map = new HashMap<>();
54         final Map<String, String> attributeNameMap = new HashMap<>();
55         for (final DataSchemaNode dataSchemaNode : containerSchemaNode.getChildNodes()) {
56             try {
57                 final String yangName = dataSchemaNode.getQName().getLocalName();
58                 map.put(yangName, createInnerAttribute(dataSchemaNode, typeProviderWrapper, packageName));
59             } catch (final IllegalArgumentException e) {
60                 throw new IllegalStateException("Unable to create TO", e);
61             }
62         }
63         return new TOAttribute(containerSchemaNode, map, attributeNameMap,
64                 containerSchemaNode.getDescription().orElse(null), packageName);
65     }
66
67     private static AttributeIfc createInnerAttribute(
68             final DataSchemaNode dataSchemaNode,
69             final TypeProviderWrapper typeProviderWrapper, final String packageName) {
70         final Class<? extends DataSchemaNode> type = isAllowedType(dataSchemaNode);
71
72         if (type.equals(LeafSchemaNode.class)) {
73             return new JavaAttribute((LeafSchemaNode) dataSchemaNode, typeProviderWrapper);
74         } else if (type.equals(ListSchemaNode.class)) {
75             return ListAttribute.create((ListSchemaNode) dataSchemaNode, typeProviderWrapper, packageName);
76         } else if (type.equals(LeafListSchemaNode.class)) {
77             return ListAttribute.create((LeafListSchemaNode) dataSchemaNode, typeProviderWrapper);
78         } else if (type.equals(ContainerSchemaNode.class)) {
79             return TOAttribute.create((ContainerSchemaNode) dataSchemaNode, typeProviderWrapper, packageName);
80         }
81
82         throw new IllegalStateException("This should never happen");
83     }
84
85     private static Class<? extends DataSchemaNode> isAllowedType(
86             final DataSchemaNode dataSchemaNode) {
87         for (final Class<? extends DataSchemaNode> allowedType : ALLOWED_CHILDREN) {
88             if (allowedType.isAssignableFrom(dataSchemaNode.getClass())) {
89                 return allowedType;
90             }
91         }
92         throw new IllegalArgumentException("Illegal child node for TO: "
93                 + dataSchemaNode.getClass() + " allowed node types: "
94                 + ALLOWED_CHILDREN);
95     }
96
97     private TOAttribute(final DataSchemaNode attrNode,
98             final Map<String, AttributeIfc> transferObject,
99             final Map<String, String> attributeNameMap, final String nullableDescription, final String packageName) {
100         super(attrNode);
101         this.yangNameToAttributeMap = transferObject;
102         this.attributeNameMap = attributeNameMap;
103         this.nullableDescription = nullableDescription;
104         this.nullableDefault = null;
105         this.packageName = packageName;
106     }
107
108     public Map<String, String> getAttributeNameMap() {
109         return this.attributeNameMap;
110     }
111
112     public Map<String, AttributeIfc> getCapitalizedPropertiesToTypesMap() {
113         final Map<String, AttributeIfc> capitalizedPropertiesToTypesMap = Maps
114                 .newHashMap();
115         for (final Entry<String, AttributeIfc> entry : this.yangNameToAttributeMap
116                 .entrySet()) {
117
118             capitalizedPropertiesToTypesMap.put(
119                     TypeProviderWrapper.convertToJavaName(entry.getKey(), true),
120                     entry.getValue());
121         }
122         return capitalizedPropertiesToTypesMap;
123     }
124
125     public Map<String, AttributeIfc> getJmxPropertiesToTypesMap() {
126         final Map<String, AttributeIfc> jmxPropertiesToTypesMap = Maps.newHashMap();
127         for (final Entry<String, AttributeIfc> entry : this.yangNameToAttributeMap
128                 .entrySet()) {
129
130             jmxPropertiesToTypesMap.put(
131                     TypeProviderWrapper.convertToJavaName(entry.getKey(), false),
132                     entry.getValue());
133         }
134         return jmxPropertiesToTypesMap;
135     }
136
137     public Map<String, AttributeIfc> getYangPropertiesToTypesMap() {
138         return this.yangNameToAttributeMap;
139     }
140
141     @Override
142     public String getNullableDescription() {
143         return this.nullableDescription;
144     }
145
146     @Override
147     public String getNullableDefault() {
148         return this.nullableDefault;
149     }
150
151     @Override
152     public boolean equals(final Object o) {
153         if (this == o) {
154             return true;
155         }
156         if (o == null || getClass() != o.getClass()) {
157             return false;
158         }
159         if (!super.equals(o)) {
160             return false;
161         }
162
163         final TOAttribute that = (TOAttribute) o;
164
165         if (this.nullableDefault != null ? !this.nullableDefault
166                 .equals(that.nullableDefault) : that.nullableDefault != null) {
167             return false;
168         }
169         if (this.nullableDescription != null ? !this.nullableDescription
170                 .equals(that.nullableDescription)
171                 : that.nullableDescription != null) {
172             return false;
173         }
174         if (this.yangNameToAttributeMap != null ? !this.yangNameToAttributeMap
175                 .equals(that.yangNameToAttributeMap)
176                 : that.yangNameToAttributeMap != null) {
177             return false;
178         }
179
180         return true;
181     }
182
183     @Override
184     public int hashCode() {
185         int result = super.hashCode();
186         result = 31
187                 * result
188                 + (this.nullableDescription != null ? this.nullableDescription.hashCode()
189                         : 0);
190         result = 31 * result
191                 + (this.nullableDefault != null ? this.nullableDefault.hashCode() : 0);
192         result = 31
193                 * result
194                 + (this.yangNameToAttributeMap != null ? this.yangNameToAttributeMap
195                         .hashCode() : 0);
196         return result;
197     }
198
199     @Override
200     public String toString() {
201         return "TOAttribute{" + getAttributeYangName() + "," + "to="
202                 + this.yangNameToAttributeMap + '}';
203     }
204
205     @Override
206     public Type getType() {
207         // TODO: ReferencedTypeImpl from Types
208         return new ReferencedTypeImpl(this.packageName, getUpperCaseCammelCase());
209     }
210
211     @Override
212     public CompositeType getOpenType() {
213         final String description = getNullableDescription() == null ? getAttributeYangName() : getNullableDescription();
214
215         final FunctionImpl functionImpl = new FunctionImpl();
216         final Map<String, AttributeIfc> jmxPropertiesToTypesMap = getJmxPropertiesToTypesMap();
217         final OpenType<?>[] itemTypes = Collections2.transform(
218                 jmxPropertiesToTypesMap.entrySet(), functionImpl).toArray(
219                 new OpenType<?>[] {});
220         final String[] itemNames = functionImpl.getItemNames();
221         try {
222             // TODO add package name to create fully qualified name for this
223             // type
224             final CompositeType compositeType = new CompositeType(
225                     getUpperCaseCammelCase(), description, itemNames,
226                     itemNames, itemTypes);
227             return compositeType;
228         } catch (final OpenDataException e) {
229             throw new RuntimeException("Unable to create CompositeType for "
230                     + this, e);
231         }
232     }
233
234     public String getPackageName() {
235         return this.packageName;
236     }
237
238 }
239
240 class FunctionImpl implements
241         Function<Entry<String, AttributeIfc>, OpenType<?>> {
242     private final List<String> itemNames = new ArrayList<>();
243
244     @Override
245     public OpenType<?> apply(final Entry<String, AttributeIfc> input) {
246         final AttributeIfc innerType = input.getValue();
247         this.itemNames.add(input.getKey());
248         return innerType.getOpenType();
249     }
250
251     public String[] getItemNames(){
252         return this.itemNames.toArray(new String[this.itemNames.size()]);
253     }
254 }