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