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.EnumTypeDefinition;
25 import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
26 import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
27 import org.opendaylight.yangtools.yang.model.util.type.CompatUtils;
29 public class JavaAttribute extends AbstractAttribute implements TypedAttribute {
31 public static final String DESCRIPTION_OF_VALUE_ATTRIBUTE_FOR_UNION = "valueOfArtificialUnionProperty";
33 private final Type type;
34 private final String nullableDescription, nullableDefault, nullableDefaultWrappedForCode;
35 private final TypeProviderWrapper typeProviderWrapper;
36 private final TypeDefinition<?> typeDefinition;
38 public JavaAttribute(final LeafSchemaNode leaf,
39 final TypeProviderWrapper typeProviderWrapper) {
41 this.type = typeProviderWrapper.getType(leaf);
43 this.typeDefinition = CompatUtils.compatLeafType(leaf);
44 this.typeProviderWrapper = typeProviderWrapper;
45 this.nullableDefault = leaf.getDefault();
46 this.nullableDefaultWrappedForCode = leaf.getDefault() == null ? null : typeProviderWrapper.getDefault(leaf);
47 this.nullableDescription = leaf.getDescription();
50 public JavaAttribute(final LeafListSchemaNode leaf,
51 final TypeProviderWrapper typeProviderWrapper) {
53 this.type = typeProviderWrapper.getType(leaf);
54 this.typeDefinition = leaf.getType();
55 this.typeProviderWrapper = typeProviderWrapper;
56 this.nullableDefault = nullableDefaultWrappedForCode = null;
57 this.nullableDescription = leaf.getDescription();
60 public boolean isUnion() {
61 TypeDefinition<?> base = getBaseType(typeProviderWrapper, typeDefinition);
62 return base instanceof UnionTypeDefinition;
65 public boolean isEnum() {
66 TypeDefinition<?> base = getBaseType(typeProviderWrapper, typeDefinition);
67 return base instanceof EnumTypeDefinition;
70 public TypeDefinition<?> getTypeDefinition() {
71 return typeDefinition;
75 * Returns the most base type
77 private TypeDefinition<?> getBaseType(final TypeProviderWrapper typeProviderWrapper, TypeDefinition<?> baseType) {
78 while(baseType.getBaseType()!=null) {
79 baseType = baseType.getBaseType();
84 public String getNullableDefaultWrappedForCode() {
85 return nullableDefaultWrappedForCode;
89 public Type getType() {
94 public String getNullableDescription() {
95 return nullableDescription;
99 public String getNullableDefault() {
100 return nullableDefault;
104 public boolean equals(final Object o) {
108 if (o == null || getClass() != o.getClass()) {
111 if (!super.equals(o)) {
115 JavaAttribute that = (JavaAttribute) o;
117 if (nullableDefault != null ? !nullableDefault
118 .equals(that.nullableDefault) : that.nullableDefault != null) {
121 if (nullableDescription != null ? !nullableDescription
122 .equals(that.nullableDescription)
123 : that.nullableDescription != null) {
126 if (type != null ? !type.equals(that.type) : that.type != null) {
134 public int hashCode() {
135 int result = super.hashCode();
136 result = 31 * result + (type != null ? type.hashCode() : 0);
139 + (nullableDescription != null ? nullableDescription.hashCode()
142 + (nullableDefault != null ? nullableDefault.hashCode() : 0);
147 public String toString() {
148 return "JavaAttribute{" + getAttributeYangName() + "," + "type=" + type
153 public OpenType<?> getOpenType() {
154 TypeDefinition<?> baseTypeDefinition = getBaseType(typeProviderWrapper, typeDefinition);
155 Type baseType = typeProviderWrapper.getType(baseTypeDefinition, baseTypeDefinition);
158 return getArrayType();
159 } else if (isEnum()) {
160 return getEnumType(baseTypeDefinition);
161 } else if (isUnion()) {
162 return getCompositeTypeForUnion(baseTypeDefinition);
163 } else if (isDerivedType(baseType, getType())) {
164 return getCompositeType(baseType, baseTypeDefinition);
165 } else if (isIdentityRef()) {
166 return getCompositeTypeForIdentity();
169 return getSimpleType(getType());
172 private OpenType<?> getEnumType(final TypeDefinition<?> baseType) {
173 final String fullyQualifiedName = typeProviderWrapper.getType(node, getTypeDefinition()).getFullyQualifiedName();
174 final String[] items = {"instance"};
175 String description = getNullableDescription() == null ? getAttributeYangName() : getNullableDescription();
178 return new CompositeType(fullyQualifiedName, description, items, items, new OpenType[]{SimpleType.STRING});
179 } catch (OpenDataException e) {
180 throw new RuntimeException("Unable to create enum type" + fullyQualifiedName + " as open type", e);
184 public boolean isIdentityRef() {
185 return typeDefinition instanceof IdentityrefTypeDefinition;
188 private OpenType<?> getCompositeTypeForUnion(final TypeDefinition<?> baseTypeDefinition) {
189 Preconditions.checkArgument(baseTypeDefinition instanceof UnionTypeDefinition,
190 "Expected %s instance but was %s", UnionTypeDefinition.class, baseTypeDefinition);
192 List<TypeDefinition<?>> types = ((UnionTypeDefinition) baseTypeDefinition).getTypes();
194 String[] itemNames = new String[types.size()+1];
195 OpenType<?>[] itemTypes = new OpenType[itemNames.length];
197 addArtificialPropertyToUnionCompositeType(baseTypeDefinition, itemNames, itemTypes);
199 String description = getNullableDescription() == null ? getAttributeYangName() : getNullableDescription();
202 for (TypeDefinition<?> innerTypeDefinition : types) {
204 Type innerType = typeProviderWrapper.getType(innerTypeDefinition, innerTypeDefinition);
206 TypeDefinition<?> baseInnerTypeDefinition = getBaseType(typeProviderWrapper, innerTypeDefinition);
207 Type innerTypeBaseType = typeProviderWrapper.getType(baseInnerTypeDefinition, baseInnerTypeDefinition);
209 OpenType<?> innerCompositeType;
211 if(isDerivedType(innerTypeBaseType, innerType)) {
212 innerCompositeType = baseInnerTypeDefinition instanceof UnionTypeDefinition ?
213 getCompositeTypeForUnion(baseInnerTypeDefinition) :
214 getCompositeType(innerTypeBaseType, baseInnerTypeDefinition);
216 innerCompositeType = SimpleTypeResolver.getSimpleType(innerType);
219 itemNames[i] = typeProviderWrapper.getJMXParamForUnionInnerType(innerTypeDefinition);
220 itemTypes[i++] = innerCompositeType;
223 String[] descriptions = itemNames.clone();
224 descriptions[0] = DESCRIPTION_OF_VALUE_ATTRIBUTE_FOR_UNION;
227 return new CompositeType(getUpperCaseCammelCase(), description, itemNames, descriptions, itemTypes);
228 } catch (OpenDataException e) {
229 throw new RuntimeException("Unable to create " + CompositeType.class + " with inner elements "
230 + Arrays.toString(itemTypes), e);
234 public static final Class<Character> TYPE_OF_ARTIFICIAL_UNION_PROPERTY = char.class;
236 private void addArtificialPropertyToUnionCompositeType(final TypeDefinition<?> baseTypeDefinition, final String[] itemNames, final OpenType<?>[] itemTypes) {
237 String artificialPropertyName = typeProviderWrapper.getJMXParamForBaseType(baseTypeDefinition);
238 itemNames[0] = artificialPropertyName;
240 OpenType<?> artificialPropertyType = getArrayOpenTypeForSimpleType(TYPE_OF_ARTIFICIAL_UNION_PROPERTY.getName(),
241 SimpleTypeResolver.getSimpleType(TYPE_OF_ARTIFICIAL_UNION_PROPERTY.getName()));
242 itemTypes[0] = artificialPropertyType;
245 private OpenType<?> getSimpleType(final Type type) {
246 SimpleType<?> simpleType = SimpleTypeResolver.getSimpleType(type);
250 private OpenType<?> getCompositeType(final Type baseType, final TypeDefinition<?> baseTypeDefinition) {
252 SimpleType<?> innerItemType = SimpleTypeResolver.getSimpleType(baseType);
253 String innerItemName = typeProviderWrapper.getJMXParamForBaseType(baseTypeDefinition);
255 String[] itemNames = new String[]{innerItemName};
256 String description = getNullableDescription() == null ? getAttributeYangName() : getNullableDescription();
258 OpenType<?>[] itemTypes = new OpenType[]{innerItemType};
260 return new CompositeType(getUpperCaseCammelCase(), description, itemNames, itemNames, itemTypes);
261 } catch (OpenDataException e) {
262 throw new RuntimeException("Unable to create " + CompositeType.class + " with inner element of type "
267 public OpenType<?> getCompositeTypeForIdentity() {
268 String[] itemNames = new String[]{IdentityAttributeRef.QNAME_ATTR_NAME};
269 String description = getNullableDescription() == null ? getAttributeYangName() : getNullableDescription();
270 OpenType<?>[] itemTypes = new OpenType[]{SimpleType.STRING};
273 return new CompositeType(getUpperCaseCammelCase(), description, itemNames, itemNames, itemTypes);
274 } catch (OpenDataException e) {
275 throw new RuntimeException("Unable to create " + CompositeType.class + " with inner element of type "
280 private OpenType<?> getArrayType() {
281 String innerTypeFullyQName = getInnerType(getType());
282 SimpleType<?> innerSimpleType = SimpleTypeResolver.getSimpleType(innerTypeFullyQName);
283 return getArrayOpenTypeForSimpleType(innerTypeFullyQName, innerSimpleType);
286 private OpenType<?> getArrayOpenTypeForSimpleType(final String innerTypeFullyQName, final SimpleType<?> innerSimpleType) {
288 ArrayType<Object> arrayType = isPrimitive(innerTypeFullyQName) ? new ArrayType<>(innerSimpleType, true)
289 : new ArrayType<>(1, innerSimpleType);
291 } catch (OpenDataException e) {
292 throw new RuntimeException("Unable to create " + ArrayType.class + " with inner element of type "
293 + innerSimpleType, e);
298 private boolean isPrimitive(final String innerTypeFullyQName) {
299 if (innerTypeFullyQName.contains(".")) {
306 private boolean isArray() {
307 return type.getName().endsWith("[]");
310 private boolean isDerivedType(final Type baseType, final Type currentType) {
311 return baseType.equals(currentType) == false;
314 private static String getInnerType(final Type type) {
315 String fullyQualifiedName = type.getFullyQualifiedName();
316 return fullyQualifiedName.substring(0, fullyQualifiedName.length() - 2);