2 * Copyright (c) 2016 Red Hat, 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.mdsal.binding.testutils;
10 import ch.vorburger.xtendbeans.XtendBeanGenerator;
11 import com.google.common.collect.ClassToInstanceMap;
12 import com.google.common.collect.Iterables;
13 import java.util.Optional;
14 import org.opendaylight.yangtools.yang.binding.Augmentable;
15 import org.opendaylight.yangtools.yang.binding.Augmentation;
16 import org.opendaylight.yangtools.yang.binding.DataContainer;
17 import org.opendaylight.yangtools.yang.binding.DataObject;
20 * {@link XtendBeanGenerator} customized for YANG beans stored in MD SAL
23 * <p>This is required: (a) because YANG model DataObject beans (when read from a
24 * DataBroker) are funky java.lang.reflect.Proxy instances, and XtendBeanGenerator
25 * cannot find the Builder or the property getters for them without a bit of help,
26 * which this class provides;
28 * <p>(b) to integrate it with the {@link XtendBuilderExtensions}
29 * (for ">>" instead of "->" and no build() method calls);
31 * <p>(c) to integrate it with the {@link AugmentableExtension}.
33 * @see XtendBeanGenerator
35 * @author Michael Vorburger
37 // package-local: no need to expose this, consider it an implementation detail; public API is the AssertDataObjects
38 class XtendYangBeanGenerator extends XtendBeanGenerator {
40 private final AugmentableExtension augmentableExtension = new AugmentableExtension();
42 private boolean useBuilderExtensions(Object bean) {
43 return bean instanceof DataObject;
47 public String getExpression(Object bean) {
48 final String beanText = super.getExpression(bean);
49 if (useBuilderExtensions(bean)) {
50 return new StringBuilder("import static extension ").append(XtendBuilderExtensions.class.getName())
51 .append(".operator_doubleGreaterThan\n\n").append(beanText).toString();
58 protected boolean isUsingBuilder(Object bean, Class<?> builderClass) {
59 if (useBuilderExtensions(bean)) {
62 return super.isUsingBuilder(bean, builderClass);
67 protected String getOperator(Object bean, Class<?> builderClass) {
68 if (useBuilderExtensions(bean)) {
71 return super.getOperator(bean, builderClass);
76 protected CharSequence getNewBeanExpression(Object bean) {
77 if (bean instanceof DataContainer) {
78 DataContainer dataContainerBean = (DataContainer) bean;
79 Class<?> builderClass = getBuilderClassByAppendingBuilderToClassName(
80 dataContainerBean.getImplementedInterface());
81 return super.getNewBeanExpression(dataContainerBean, builderClass);
83 return super.getNewBeanExpression(bean);
88 protected String stringify(Class<?> klass) {
89 return klass.getSimpleName();
93 protected Iterable<Property> filter(Iterable<Property> properties) {
94 // YANG keys duplicate existing other properties (there are getter/setter for both), so filter them
95 return Iterables.filter(properties, property -> !property.getName().equals("key"));
98 private Optional<ClassToInstanceMap<Augmentation<?>>> getAugmentations(Object bean) {
99 if (bean instanceof Augmentable<?>) {
100 Augmentable<?> augmentable = (Augmentable<?>) bean;
101 ClassToInstanceMap<Augmentation<?>> augmentables = augmentableExtension.getAugmentations(augmentable);
102 if (!augmentables.isEmpty()) {
103 return Optional.of(augmentables);
106 return Optional.empty();
110 protected CharSequence getAdditionalInitializationExpression(Object bean, Class<?> builderClass) {
111 Optional<ClassToInstanceMap<Augmentation<?>>> optional = getAugmentations(bean);
112 if (optional.isPresent()) {
113 StringBuilder sb = new StringBuilder();
114 optional.get().forEach((klass, augmentation) -> {
115 sb.append("addAugmentation(");
116 sb.append(stringify(klass));
118 sb.append(getNewBeanExpression(augmentation));
128 TODO activate this once YANG objects either have a setAugmentations(Map)
129 or implement a new TBD interface AugmentableBuilder with a method like:
130 <E extends Augmentation<T>> Builder? addAugmentation(Class<E> augmentationType, E augmentation);
131 which an extension method could jump on.
134 public Iterable<Property> getAdditionalSpecialProperties(Object bean, Class<?> builderClass) {
135 Optional<ClassToInstanceMap<Augmentation<?>>> optional = getAugmentations(bean);
136 if (optional.isPresent()) {
137 Property augmentableProperty = new Property("augmentations", true, Map.class, () -> optional.get(), null);
138 return Collections.singleton(augmentableProperty);
140 return Collections.emptyList();