2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.controller.config.yangjmxgenerator.attribute;
10 import com.google.common.base.Preconditions;
11 import org.opendaylight.controller.config.yangjmxgenerator.TypeProviderWrapper;
12 import org.opendaylight.yangtools.sal.binding.model.api.Type;
13 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
14 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
15 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
16 import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
18 import javax.management.openmbean.ArrayType;
19 import javax.management.openmbean.CompositeType;
20 import javax.management.openmbean.OpenDataException;
21 import javax.management.openmbean.OpenType;
22 import javax.management.openmbean.SimpleType;
23 import java.util.Arrays;
24 import java.util.List;
26 public class JavaAttribute extends AbstractAttribute implements TypedAttribute {
28 public static final String DESCRIPTION_OF_VALUE_ATTRIBUTE_FOR_UNION = "valueOfArtificialUnionProperty";
30 private final Type type;
31 private final String nullableDescription, nullableDefault, nullableDefaultWrappedForCode;
32 private final TypeProviderWrapper typeProviderWrapper;
33 private final TypeDefinition<?> typeDefinition;
35 public JavaAttribute(LeafSchemaNode leaf,
36 TypeProviderWrapper typeProviderWrapper) {
38 this.type = typeProviderWrapper.getType(leaf);
39 this.typeDefinition = leaf.getType();
40 this.typeProviderWrapper = typeProviderWrapper;
41 this.nullableDefault = leaf.getDefault();
42 this.nullableDefaultWrappedForCode = leaf.getDefault() == null ? null : typeProviderWrapper.getDefault(leaf);
43 this.nullableDescription = leaf.getDescription();
46 public JavaAttribute(LeafListSchemaNode leaf,
47 TypeProviderWrapper typeProviderWrapper) {
49 this.type = typeProviderWrapper.getType(leaf);
50 this.typeDefinition = leaf.getType();
51 this.typeProviderWrapper = typeProviderWrapper;
52 this.nullableDefault = nullableDefaultWrappedForCode = null;
53 this.nullableDescription = leaf.getDescription();
56 public boolean isUnion() {
57 TypeDefinition<?> base = getBaseType(typeProviderWrapper, typeDefinition);
58 return base instanceof UnionTypeDefinition;
61 public TypeDefinition<?> getTypeDefinition() {
62 return typeDefinition;
66 * Returns the most base type
68 private TypeDefinition<?> getBaseType(TypeProviderWrapper typeProviderWrapper, TypeDefinition<?> baseType) {
69 while(baseType.getBaseType()!=null) {
70 baseType = baseType.getBaseType();
75 public String getNullableDefaultWrappedForCode() {
76 return nullableDefaultWrappedForCode;
80 public Type getType() {
85 public String getNullableDescription() {
86 return nullableDescription;
90 public String getNullableDefault() {
91 return nullableDefault;
95 public boolean equals(Object o) {
98 if (o == null || getClass() != o.getClass())
100 if (!super.equals(o))
103 JavaAttribute that = (JavaAttribute) o;
105 if (nullableDefault != null ? !nullableDefault
106 .equals(that.nullableDefault) : that.nullableDefault != null)
108 if (nullableDescription != null ? !nullableDescription
109 .equals(that.nullableDescription)
110 : that.nullableDescription != null)
112 if (type != null ? !type.equals(that.type) : that.type != null)
119 public int hashCode() {
120 int result = super.hashCode();
121 result = 31 * result + (type != null ? type.hashCode() : 0);
124 + (nullableDescription != null ? nullableDescription.hashCode()
127 + (nullableDefault != null ? nullableDefault.hashCode() : 0);
132 public String toString() {
133 return "JavaAttribute{" + getAttributeYangName() + "," + "type=" + type
138 public OpenType<?> getOpenType() {
139 TypeDefinition<?> baseTypeDefinition = getBaseType(typeProviderWrapper, typeDefinition);
140 Type baseType = typeProviderWrapper.getType(baseTypeDefinition, baseTypeDefinition);
143 return getArrayType();
144 } else if (isEnum(baseType)) {
145 return getSimpleType(baseType);
146 } else if (isUnion()) {
147 return getCompositeTypeForUnion(baseTypeDefinition);
148 } else if (isDerivedType(baseType, getType())) {
149 return getCompositeType(baseType, baseTypeDefinition);
152 return getSimpleType(getType());
155 private OpenType<?> getCompositeTypeForUnion(TypeDefinition<?> baseTypeDefinition) {
156 Preconditions.checkArgument(baseTypeDefinition instanceof UnionTypeDefinition,
157 "Expected %s instance but was %s", UnionTypeDefinition.class, baseTypeDefinition);
159 List<TypeDefinition<?>> types = ((UnionTypeDefinition) baseTypeDefinition).getTypes();
161 String[] itemNames = new String[types.size()+1];
162 OpenType<?>[] itemTypes = new OpenType[itemNames.length];
164 addArtificialPropertyToUnionCompositeType(baseTypeDefinition, itemNames, itemTypes);
166 String description = getNullableDescription() == null ? getAttributeYangName() : getNullableDescription();
169 for (TypeDefinition<?> innerTypeDefinition : types) {
171 Type innerType = typeProviderWrapper.getType(innerTypeDefinition, innerTypeDefinition);
173 TypeDefinition<?> baseInnerTypeDefinition = getBaseType(typeProviderWrapper, innerTypeDefinition);
174 Type innerTypeBaseType = typeProviderWrapper.getType(baseInnerTypeDefinition, baseInnerTypeDefinition);
176 OpenType<?> innerCompositeType;
178 if(isDerivedType(innerTypeBaseType, innerType)) {
179 innerCompositeType = getCompositeType(innerTypeBaseType, baseInnerTypeDefinition);
181 innerCompositeType = SimpleTypeResolver.getSimpleType(innerType);
184 itemNames[i] = typeProviderWrapper.getJMXParamForUnionInnerType(innerTypeDefinition);
185 itemTypes[i++] = innerCompositeType;
188 String[] descriptions = Arrays.copyOf(itemNames, itemNames.length);
189 descriptions[0] = DESCRIPTION_OF_VALUE_ATTRIBUTE_FOR_UNION;
192 return new CompositeType(getUpperCaseCammelCase(), description, itemNames, descriptions, itemTypes);
193 } catch (OpenDataException e) {
194 throw new RuntimeException("Unable to create " + CompositeType.class + " with inner elements "
195 + Arrays.toString(itemTypes), e);
199 public static final Class<Character> TYPE_OF_ARTIFICIAL_UNION_PROPERTY = char.class;
201 private void addArtificialPropertyToUnionCompositeType(TypeDefinition<?> baseTypeDefinition, String[] itemNames, OpenType<?>[] itemTypes) {
202 String artificialPropertyName = typeProviderWrapper.getJMXParamForBaseType(baseTypeDefinition);
203 itemNames[0] = artificialPropertyName;
205 OpenType<?> artificialPropertyType = getArrayOpenTypeForSimpleType(TYPE_OF_ARTIFICIAL_UNION_PROPERTY.getName(),
206 SimpleTypeResolver.getSimpleType(TYPE_OF_ARTIFICIAL_UNION_PROPERTY.getName()));
207 itemTypes[0] = artificialPropertyType;
210 private boolean isEnum(Type baseType) {
211 return baseType.getFullyQualifiedName().equals(Enum.class.getName());
214 private OpenType<?> getSimpleType(Type type) {
215 SimpleType<?> simpleType = SimpleTypeResolver.getSimpleType(type);
219 private OpenType<?> getCompositeType(Type baseType, TypeDefinition<?> baseTypeDefinition) {
221 SimpleType<?> innerItemType = SimpleTypeResolver.getSimpleType(baseType);
222 String innerItemName = typeProviderWrapper.getJMXParamForBaseType(baseTypeDefinition);
224 String[] itemNames = new String[]{innerItemName};
225 String description = getNullableDescription() == null ? getAttributeYangName() : getNullableDescription();
227 OpenType<?>[] itemTypes = new OpenType[]{innerItemType};
229 return new CompositeType(getUpperCaseCammelCase(), description, itemNames, itemNames, itemTypes);
230 } catch (OpenDataException e) {
231 throw new RuntimeException("Unable to create " + CompositeType.class + " with inner element of type "
236 private OpenType<?> getArrayType() {
237 String innerTypeFullyQName = getInnerType(getType());
238 SimpleType<?> innerSimpleType = SimpleTypeResolver.getSimpleType(innerTypeFullyQName);
239 return getArrayOpenTypeForSimpleType(innerTypeFullyQName, innerSimpleType);
242 private OpenType<?> getArrayOpenTypeForSimpleType(String innerTypeFullyQName, SimpleType<?> innerSimpleType) {
244 ArrayType<Object> arrayType = isPrimitive(innerTypeFullyQName) ? new ArrayType<>(innerSimpleType, true)
245 : new ArrayType<>(1, innerSimpleType);
247 } catch (OpenDataException e) {
248 throw new RuntimeException("Unable to create " + ArrayType.class + " with inner element of type "
249 + innerSimpleType, e);
254 private boolean isPrimitive(String innerTypeFullyQName) {
255 if (innerTypeFullyQName.contains("."))
261 private boolean isArray() {
262 return type.getName().endsWith("[]");
265 private boolean isDerivedType(Type baseType, Type currentType) {
266 return baseType.equals(currentType) == false;
269 private static String getInnerType(Type type) {
270 String fullyQualifiedName = type.getFullyQualifiedName();
271 return fullyQualifiedName.substring(0, fullyQualifiedName.length() - 2);