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 java.util.Optional;
14 import javax.management.openmbean.ArrayType;
15 import javax.management.openmbean.CompositeType;
16 import javax.management.openmbean.OpenDataException;
17 import javax.management.openmbean.OpenType;
18 import javax.management.openmbean.SimpleType;
19 import org.opendaylight.controller.config.api.IdentityAttributeRef;
20 import org.opendaylight.controller.config.yangjmxgenerator.TypeProviderWrapper;
21 import org.opendaylight.mdsal.binding.model.api.Type;
22 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
23 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
24 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
25 import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition;
26 import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
27 import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
28 import org.opendaylight.yangtools.yang.model.util.type.CompatUtils;
30 public class JavaAttribute extends AbstractAttribute implements TypedAttribute {
32 public static final String DESCRIPTION_OF_VALUE_ATTRIBUTE_FOR_UNION = "valueOfArtificialUnionProperty";
34 private final Type type;
35 private final String nullableDescription, nullableDefault, nullableDefaultWrappedForCode;
36 private final TypeProviderWrapper typeProviderWrapper;
37 private final TypeDefinition<?> typeDefinition;
39 public JavaAttribute(final LeafSchemaNode leaf,
40 final TypeProviderWrapper typeProviderWrapper) {
42 this.type = typeProviderWrapper.getType(leaf);
44 this.typeDefinition = CompatUtils.compatLeafType(leaf);
45 this.typeProviderWrapper = typeProviderWrapper;
47 final Optional<? extends Object> typeDefault = leaf.getType().getDefaultValue();
48 if (typeDefault.isPresent()) {
49 nullableDefault = (String) typeDefault.get();
50 nullableDefaultWrappedForCode = typeProviderWrapper.getDefault(leaf);
52 nullableDefault = null;
53 nullableDefaultWrappedForCode = null;
56 this.nullableDescription = leaf.getDescription().orElse(null);
59 public JavaAttribute(final LeafListSchemaNode leaf,
60 final TypeProviderWrapper typeProviderWrapper) {
62 this.type = typeProviderWrapper.getType(leaf);
63 this.typeDefinition = leaf.getType();
64 this.typeProviderWrapper = typeProviderWrapper;
65 this.nullableDefault = this.nullableDefaultWrappedForCode = null;
66 this.nullableDescription = leaf.getDescription().orElse(null);
69 public boolean isUnion() {
70 final TypeDefinition<?> base = getBaseType(this.typeProviderWrapper, this.typeDefinition);
71 return base instanceof UnionTypeDefinition;
74 public boolean isEnum() {
75 final TypeDefinition<?> base = getBaseType(this.typeProviderWrapper, this.typeDefinition);
76 return base instanceof EnumTypeDefinition;
79 public TypeDefinition<?> getTypeDefinition() {
80 return this.typeDefinition;
84 * Returns the most base type
86 private TypeDefinition<?> getBaseType(final TypeProviderWrapper typeProviderWrapper, TypeDefinition<?> baseType) {
87 while(baseType.getBaseType()!=null) {
88 baseType = baseType.getBaseType();
93 public String getNullableDefaultWrappedForCode() {
94 return this.nullableDefaultWrappedForCode;
98 public Type getType() {
103 public String getNullableDescription() {
104 return this.nullableDescription;
108 public String getNullableDefault() {
109 return this.nullableDefault;
113 public boolean equals(final Object o) {
117 if (o == null || getClass() != o.getClass()) {
120 if (!super.equals(o)) {
124 final JavaAttribute that = (JavaAttribute) o;
126 if (this.nullableDefault != null ? !this.nullableDefault
127 .equals(that.nullableDefault) : that.nullableDefault != null) {
130 if (this.nullableDescription != null ? !this.nullableDescription
131 .equals(that.nullableDescription)
132 : that.nullableDescription != null) {
135 if (this.type != null ? !this.type.equals(that.type) : that.type != null) {
143 public int hashCode() {
144 int result = super.hashCode();
145 result = 31 * result + (this.type != null ? this.type.hashCode() : 0);
148 + (this.nullableDescription != null ? this.nullableDescription.hashCode()
151 + (this.nullableDefault != null ? this.nullableDefault.hashCode() : 0);
156 public String toString() {
157 return "JavaAttribute{" + getAttributeYangName() + "," + "type=" + this.type
162 public OpenType<?> getOpenType() {
163 final TypeDefinition<?> baseTypeDefinition = getBaseType(this.typeProviderWrapper, this.typeDefinition);
164 final Type baseType = this.typeProviderWrapper.getType(baseTypeDefinition, baseTypeDefinition);
167 return getArrayType();
168 } else if (isEnum()) {
169 return getEnumType(baseTypeDefinition);
170 } else if (isUnion()) {
171 return getCompositeTypeForUnion(baseTypeDefinition);
172 } else if (isDerivedType(baseType, getType())) {
173 return getCompositeType(baseType, baseTypeDefinition);
174 } else if (isIdentityRef()) {
175 return getCompositeTypeForIdentity();
178 return getSimpleType(getType());
181 private OpenType<?> getEnumType(final TypeDefinition<?> baseType) {
182 final String fullyQualifiedName = this.typeProviderWrapper.getType(this.node, getTypeDefinition()).getFullyQualifiedName();
183 final String[] items = {"instance"};
184 final String description = getNullableDescription() == null ? getAttributeYangName() : getNullableDescription();
187 return new CompositeType(fullyQualifiedName, description, items, items, new OpenType[]{SimpleType.STRING});
188 } catch (final OpenDataException e) {
189 throw new RuntimeException("Unable to create enum type" + fullyQualifiedName + " as open type", e);
193 public boolean isIdentityRef() {
194 return this.typeDefinition instanceof IdentityrefTypeDefinition;
197 private OpenType<?> getCompositeTypeForUnion(final TypeDefinition<?> baseTypeDefinition) {
198 Preconditions.checkArgument(baseTypeDefinition instanceof UnionTypeDefinition,
199 "Expected %s instance but was %s", UnionTypeDefinition.class, baseTypeDefinition);
201 final List<TypeDefinition<?>> types = ((UnionTypeDefinition) baseTypeDefinition).getTypes();
203 final String[] itemNames = new String[types.size()+1];
204 final OpenType<?>[] itemTypes = new OpenType[itemNames.length];
206 addArtificialPropertyToUnionCompositeType(baseTypeDefinition, itemNames, itemTypes);
208 final String description = getNullableDescription() == null ? getAttributeYangName() : getNullableDescription();
211 for (final TypeDefinition<?> innerTypeDefinition : types) {
213 final Type innerType = this.typeProviderWrapper.getType(innerTypeDefinition, innerTypeDefinition);
215 final TypeDefinition<?> baseInnerTypeDefinition = getBaseType(this.typeProviderWrapper, innerTypeDefinition);
216 final Type innerTypeBaseType = this.typeProviderWrapper.getType(baseInnerTypeDefinition, baseInnerTypeDefinition);
218 OpenType<?> innerCompositeType;
220 if(isDerivedType(innerTypeBaseType, innerType)) {
221 innerCompositeType = baseInnerTypeDefinition instanceof UnionTypeDefinition ?
222 getCompositeTypeForUnion(baseInnerTypeDefinition) :
223 getCompositeType(innerTypeBaseType, baseInnerTypeDefinition);
225 innerCompositeType = SimpleTypeResolver.getSimpleType(innerType);
228 itemNames[i] = this.typeProviderWrapper.getJMXParamForUnionInnerType(innerTypeDefinition);
229 itemTypes[i++] = innerCompositeType;
232 final String[] descriptions = itemNames.clone();
233 descriptions[0] = DESCRIPTION_OF_VALUE_ATTRIBUTE_FOR_UNION;
236 return new CompositeType(getUpperCaseCammelCase(), description, itemNames, descriptions, itemTypes);
237 } catch (final OpenDataException e) {
238 throw new RuntimeException("Unable to create " + CompositeType.class + " with inner elements "
239 + Arrays.toString(itemTypes), e);
243 public static final Class<Character> TYPE_OF_ARTIFICIAL_UNION_PROPERTY = char.class;
245 private void addArtificialPropertyToUnionCompositeType(final TypeDefinition<?> baseTypeDefinition, final String[] itemNames, final OpenType<?>[] itemTypes) {
246 final String artificialPropertyName = this.typeProviderWrapper.getJMXParamForBaseType(baseTypeDefinition);
247 itemNames[0] = artificialPropertyName;
249 final OpenType<?> artificialPropertyType = getArrayOpenTypeForSimpleType(TYPE_OF_ARTIFICIAL_UNION_PROPERTY.getName(),
250 SimpleTypeResolver.getSimpleType(TYPE_OF_ARTIFICIAL_UNION_PROPERTY.getName()));
251 itemTypes[0] = artificialPropertyType;
254 private OpenType<?> getSimpleType(final Type type) {
255 final SimpleType<?> simpleType = SimpleTypeResolver.getSimpleType(type);
259 private OpenType<?> getCompositeType(final Type baseType, final TypeDefinition<?> baseTypeDefinition) {
261 final SimpleType<?> innerItemType = SimpleTypeResolver.getSimpleType(baseType);
262 final String innerItemName = this.typeProviderWrapper.getJMXParamForBaseType(baseTypeDefinition);
264 final String[] itemNames = new String[]{innerItemName};
265 final String description = getNullableDescription() == null ? getAttributeYangName() : getNullableDescription();
267 final OpenType<?>[] itemTypes = new OpenType[]{innerItemType};
269 return new CompositeType(getUpperCaseCammelCase(), description, itemNames, itemNames, itemTypes);
270 } catch (final OpenDataException e) {
271 throw new RuntimeException("Unable to create " + CompositeType.class + " with inner element of type "
276 public OpenType<?> getCompositeTypeForIdentity() {
277 final String[] itemNames = new String[]{IdentityAttributeRef.QNAME_ATTR_NAME};
278 final String description = getNullableDescription() == null ? getAttributeYangName() : getNullableDescription();
279 final OpenType<?>[] itemTypes = new OpenType[]{SimpleType.STRING};
282 return new CompositeType(getUpperCaseCammelCase(), description, itemNames, itemNames, itemTypes);
283 } catch (final OpenDataException e) {
284 throw new RuntimeException("Unable to create " + CompositeType.class + " with inner element of type "
289 private OpenType<?> getArrayType() {
290 final String innerTypeFullyQName = getInnerType(getType());
291 final SimpleType<?> innerSimpleType = SimpleTypeResolver.getSimpleType(innerTypeFullyQName);
292 return getArrayOpenTypeForSimpleType(innerTypeFullyQName, innerSimpleType);
295 private OpenType<?> getArrayOpenTypeForSimpleType(final String innerTypeFullyQName, final SimpleType<?> innerSimpleType) {
297 final ArrayType<Object> arrayType = isPrimitive(innerTypeFullyQName) ? new ArrayType<>(innerSimpleType, true)
298 : new ArrayType<>(1, innerSimpleType);
300 } catch (final OpenDataException e) {
301 throw new RuntimeException("Unable to create " + ArrayType.class + " with inner element of type "
302 + innerSimpleType, e);
307 private boolean isPrimitive(final String innerTypeFullyQName) {
308 if (innerTypeFullyQName.contains(".")) {
315 private boolean isArray() {
316 return this.type.getName().endsWith("[]");
319 private boolean isDerivedType(final Type baseType, final Type currentType) {
320 return baseType.equals(currentType) == false;
323 private static String getInnerType(final Type type) {
324 final String fullyQualifiedName = type.getFullyQualifiedName();
325 return fullyQualifiedName.substring(0, fullyQualifiedName.length() - 2);