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 java.util.Arrays;
12 import java.util.List;
13 import javax.management.openmbean.ArrayType;
14 import javax.management.openmbean.CompositeType;
15 import javax.management.openmbean.OpenDataException;
16 import javax.management.openmbean.OpenType;
17 import javax.management.openmbean.SimpleType;
18 import org.opendaylight.controller.config.api.IdentityAttributeRef;
19 import org.opendaylight.controller.config.yangjmxgenerator.TypeProviderWrapper;
20 import org.opendaylight.yangtools.sal.binding.model.api.Type;
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.TypeDefinition;
24 import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
25 import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
27 public class JavaAttribute extends AbstractAttribute implements TypedAttribute {
29 public static final String DESCRIPTION_OF_VALUE_ATTRIBUTE_FOR_UNION = "valueOfArtificialUnionProperty";
31 private final Type type;
32 private final String nullableDescription, nullableDefault, nullableDefaultWrappedForCode;
33 private final TypeProviderWrapper typeProviderWrapper;
34 private final TypeDefinition<?> typeDefinition;
36 public JavaAttribute(LeafSchemaNode leaf,
37 TypeProviderWrapper typeProviderWrapper) {
39 this.type = typeProviderWrapper.getType(leaf);
41 this.typeDefinition = leaf.getType();
42 this.typeProviderWrapper = typeProviderWrapper;
43 this.nullableDefault = leaf.getDefault();
44 this.nullableDefaultWrappedForCode = leaf.getDefault() == null ? null : typeProviderWrapper.getDefault(leaf);
45 this.nullableDescription = leaf.getDescription();
48 public JavaAttribute(LeafListSchemaNode leaf,
49 TypeProviderWrapper typeProviderWrapper) {
51 this.type = typeProviderWrapper.getType(leaf);
52 this.typeDefinition = leaf.getType();
53 this.typeProviderWrapper = typeProviderWrapper;
54 this.nullableDefault = nullableDefaultWrappedForCode = null;
55 this.nullableDescription = leaf.getDescription();
58 public boolean isUnion() {
59 TypeDefinition<?> base = getBaseType(typeProviderWrapper, typeDefinition);
60 return base instanceof UnionTypeDefinition;
63 public TypeDefinition<?> getTypeDefinition() {
64 return typeDefinition;
68 * Returns the most base type
70 private TypeDefinition<?> getBaseType(TypeProviderWrapper typeProviderWrapper, TypeDefinition<?> baseType) {
71 while(baseType.getBaseType()!=null) {
72 baseType = baseType.getBaseType();
77 public String getNullableDefaultWrappedForCode() {
78 return nullableDefaultWrappedForCode;
82 public Type getType() {
87 public String getNullableDescription() {
88 return nullableDescription;
92 public String getNullableDefault() {
93 return nullableDefault;
97 public boolean equals(Object o) {
101 if (o == null || getClass() != o.getClass()) {
104 if (!super.equals(o)) {
108 JavaAttribute that = (JavaAttribute) o;
110 if (nullableDefault != null ? !nullableDefault
111 .equals(that.nullableDefault) : that.nullableDefault != null) {
114 if (nullableDescription != null ? !nullableDescription
115 .equals(that.nullableDescription)
116 : that.nullableDescription != null) {
119 if (type != null ? !type.equals(that.type) : that.type != null) {
127 public int hashCode() {
128 int result = super.hashCode();
129 result = 31 * result + (type != null ? type.hashCode() : 0);
132 + (nullableDescription != null ? nullableDescription.hashCode()
135 + (nullableDefault != null ? nullableDefault.hashCode() : 0);
140 public String toString() {
141 return "JavaAttribute{" + getAttributeYangName() + "," + "type=" + type
146 public OpenType<?> getOpenType() {
147 TypeDefinition<?> baseTypeDefinition = getBaseType(typeProviderWrapper, typeDefinition);
148 Type baseType = typeProviderWrapper.getType(baseTypeDefinition, baseTypeDefinition);
151 return getArrayType();
152 } else if (isEnum(baseType)) {
153 return getSimpleType(baseType);
154 } else if (isUnion()) {
155 return getCompositeTypeForUnion(baseTypeDefinition);
156 } else if (isDerivedType(baseType, getType())) {
157 return getCompositeType(baseType, baseTypeDefinition);
158 } else if (isIdentityRef()) {
159 return getCompositeTypeForIdentity();
162 return getSimpleType(getType());
165 public boolean isIdentityRef() {
166 return typeDefinition instanceof IdentityrefTypeDefinition;
169 private OpenType<?> getCompositeTypeForUnion(TypeDefinition<?> baseTypeDefinition) {
170 Preconditions.checkArgument(baseTypeDefinition instanceof UnionTypeDefinition,
171 "Expected %s instance but was %s", UnionTypeDefinition.class, baseTypeDefinition);
173 List<TypeDefinition<?>> types = ((UnionTypeDefinition) baseTypeDefinition).getTypes();
175 String[] itemNames = new String[types.size()+1];
176 OpenType<?>[] itemTypes = new OpenType[itemNames.length];
178 addArtificialPropertyToUnionCompositeType(baseTypeDefinition, itemNames, itemTypes);
180 String description = getNullableDescription() == null ? getAttributeYangName() : getNullableDescription();
183 for (TypeDefinition<?> innerTypeDefinition : types) {
185 Type innerType = typeProviderWrapper.getType(innerTypeDefinition, innerTypeDefinition);
187 TypeDefinition<?> baseInnerTypeDefinition = getBaseType(typeProviderWrapper, innerTypeDefinition);
188 Type innerTypeBaseType = typeProviderWrapper.getType(baseInnerTypeDefinition, baseInnerTypeDefinition);
190 OpenType<?> innerCompositeType;
192 if(isDerivedType(innerTypeBaseType, innerType)) {
193 innerCompositeType = baseInnerTypeDefinition instanceof UnionTypeDefinition ?
194 getCompositeTypeForUnion(baseInnerTypeDefinition) :
195 getCompositeType(innerTypeBaseType, baseInnerTypeDefinition);
197 innerCompositeType = SimpleTypeResolver.getSimpleType(innerType);
200 itemNames[i] = typeProviderWrapper.getJMXParamForUnionInnerType(innerTypeDefinition);
201 itemTypes[i++] = innerCompositeType;
204 String[] descriptions = Arrays.copyOf(itemNames, itemNames.length);
205 descriptions[0] = DESCRIPTION_OF_VALUE_ATTRIBUTE_FOR_UNION;
208 return new CompositeType(getUpperCaseCammelCase(), description, itemNames, descriptions, itemTypes);
209 } catch (OpenDataException e) {
210 throw new RuntimeException("Unable to create " + CompositeType.class + " with inner elements "
211 + Arrays.toString(itemTypes), e);
215 public static final Class<Character> TYPE_OF_ARTIFICIAL_UNION_PROPERTY = char.class;
217 private void addArtificialPropertyToUnionCompositeType(TypeDefinition<?> baseTypeDefinition, String[] itemNames, OpenType<?>[] itemTypes) {
218 String artificialPropertyName = typeProviderWrapper.getJMXParamForBaseType(baseTypeDefinition);
219 itemNames[0] = artificialPropertyName;
221 OpenType<?> artificialPropertyType = getArrayOpenTypeForSimpleType(TYPE_OF_ARTIFICIAL_UNION_PROPERTY.getName(),
222 SimpleTypeResolver.getSimpleType(TYPE_OF_ARTIFICIAL_UNION_PROPERTY.getName()));
223 itemTypes[0] = artificialPropertyType;
226 private boolean isEnum(Type baseType) {
227 return baseType.getFullyQualifiedName().equals(Enum.class.getName());
230 private OpenType<?> getSimpleType(Type type) {
231 SimpleType<?> simpleType = SimpleTypeResolver.getSimpleType(type);
235 private OpenType<?> getCompositeType(Type baseType, TypeDefinition<?> baseTypeDefinition) {
237 SimpleType<?> innerItemType = SimpleTypeResolver.getSimpleType(baseType);
238 String innerItemName = typeProviderWrapper.getJMXParamForBaseType(baseTypeDefinition);
240 String[] itemNames = new String[]{innerItemName};
241 String description = getNullableDescription() == null ? getAttributeYangName() : getNullableDescription();
243 OpenType<?>[] itemTypes = new OpenType[]{innerItemType};
245 return new CompositeType(getUpperCaseCammelCase(), description, itemNames, itemNames, itemTypes);
246 } catch (OpenDataException e) {
247 throw new RuntimeException("Unable to create " + CompositeType.class + " with inner element of type "
252 public OpenType<?> getCompositeTypeForIdentity() {
253 String[] itemNames = new String[]{IdentityAttributeRef.QNAME_ATTR_NAME};
254 String description = getNullableDescription() == null ? getAttributeYangName() : getNullableDescription();
255 OpenType<?>[] itemTypes = new OpenType[]{SimpleType.STRING};
258 return new CompositeType(getUpperCaseCammelCase(), description, itemNames, itemNames, itemTypes);
259 } catch (OpenDataException e) {
260 throw new RuntimeException("Unable to create " + CompositeType.class + " with inner element of type "
265 private OpenType<?> getArrayType() {
266 String innerTypeFullyQName = getInnerType(getType());
267 SimpleType<?> innerSimpleType = SimpleTypeResolver.getSimpleType(innerTypeFullyQName);
268 return getArrayOpenTypeForSimpleType(innerTypeFullyQName, innerSimpleType);
271 private OpenType<?> getArrayOpenTypeForSimpleType(String innerTypeFullyQName, SimpleType<?> innerSimpleType) {
273 ArrayType<Object> arrayType = isPrimitive(innerTypeFullyQName) ? new ArrayType<>(innerSimpleType, true)
274 : new ArrayType<>(1, innerSimpleType);
276 } catch (OpenDataException e) {
277 throw new RuntimeException("Unable to create " + ArrayType.class + " with inner element of type "
278 + innerSimpleType, e);
283 private boolean isPrimitive(String innerTypeFullyQName) {
284 if (innerTypeFullyQName.contains(".")) {
291 private boolean isArray() {
292 return type.getName().endsWith("[]");
295 private boolean isDerivedType(Type baseType, Type currentType) {
296 return baseType.equals(currentType) == false;
299 private static String getInnerType(Type type) {
300 String fullyQualifiedName = type.getFullyQualifiedName();
301 return fullyQualifiedName.substring(0, fullyQualifiedName.length() - 2);