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