import com.google.common.collect.Multimaps;
import com.google.common.collect.SetMultimap;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.opendaylight.mdsal.binding.runtime.api.BindingRuntimeContext;
import org.opendaylight.mdsal.binding.runtime.api.CaseRuntimeType;
import org.opendaylight.mdsal.binding.runtime.api.ChoiceRuntimeType;
+import org.opendaylight.mdsal.binding.spec.naming.BindingMapping;
import org.opendaylight.mdsal.binding.spec.reflect.BindingReflections;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
// Updates collection of case children
@SuppressWarnings("unchecked")
final Class<? extends DataObject> cazeCls = (Class<? extends DataObject>) cazeDef.getBindingClass();
- for (final Class<? extends DataObject> cazeChild : BindingReflections.getChildrenClasses(cazeCls)) {
+ for (final Class<? extends DataObject> cazeChild : getChildrenClasses(cazeCls)) {
childToCase.put(cazeChild, cazeDef);
}
// Updates collection of YANG instance identifier to case
return childNonNull(result, type, "Class %s is not child of any cases for %s", type, bindingArg()).get();
}
+
+ /**
+ * Scans supplied class and returns an iterable of all data children classes.
+ *
+ * @param type
+ * YANG Modeled Entity derived from DataContainer
+ * @return Iterable of all data children, which have YANG modeled entity
+ */
+ // FIXME: MDSAL-780: replace use of this method
+ @SuppressWarnings("unchecked")
+ private static Iterable<Class<? extends DataObject>> getChildrenClasses(final Class<? extends DataContainer> type) {
+ checkArgument(type != null, "Target type must not be null");
+ checkArgument(DataContainer.class.isAssignableFrom(type), "Supplied type must be derived from DataContainer");
+ List<Class<? extends DataObject>> ret = new LinkedList<>();
+ for (Method method : type.getMethods()) {
+ Optional<Class<? extends DataContainer>> entity = getYangModeledReturnType(method,
+ BindingMapping.GETTER_PREFIX);
+ if (entity.isPresent()) {
+ ret.add((Class<? extends DataObject>) entity.get());
+ }
+ }
+ return ret;
+ }
}
import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
import java.util.List;
+import java.util.Map;
import java.util.Optional;
import java.util.Set;
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.mdsal.binding.runtime.api.BindingRuntimeContext;
import org.opendaylight.mdsal.binding.runtime.api.CompositeRuntimeType;
import org.opendaylight.mdsal.binding.runtime.api.RuntimeTypeContainer;
+import org.opendaylight.yangtools.util.ClassLoaderUtils;
import org.opendaylight.yangtools.yang.binding.Augmentation;
import org.opendaylight.yangtools.yang.binding.BindingObject;
+import org.opendaylight.yangtools.yang.binding.DataContainer;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
abstract class DataContainerCodecContext<D extends DataObject, T extends RuntimeTypeContainer> extends NodeCodecContext
implements BindingDataObjectCodecTreeNode<D> {
+ private static final Logger LOG = LoggerFactory.getLogger(DataContainerCodecContext.class);
private static final VarHandle EVENT_STREAM_SERIALIZER;
static {
throw new IllegalArgumentException("Expected " + expectedType.getSimpleName(), e);
}
}
+
+ // FIXME: MDSAL-780 replace this method with BindingRuntimeTypes-driven logic
+ static final Optional<Class<? extends DataContainer>> getYangModeledReturnType(final Method method,
+ final String prefix) {
+ final String methodName = method.getName();
+ if ("getClass".equals(methodName) || !methodName.startsWith(prefix) || method.getParameterCount() > 0) {
+ return Optional.empty();
+ }
+
+ final Class<?> returnType = method.getReturnType();
+ if (DataContainer.class.isAssignableFrom(returnType)) {
+ return optionalDataContainer(returnType);
+ } else if (List.class.isAssignableFrom(returnType)) {
+ return getYangModeledReturnType(method, 0);
+ } else if (Map.class.isAssignableFrom(returnType)) {
+ return getYangModeledReturnType(method, 1);
+ }
+ return Optional.empty();
+ }
+
+ @SuppressWarnings("checkstyle:illegalCatch")
+ private static Optional<Class<? extends DataContainer>> getYangModeledReturnType(final Method method,
+ final int parameterOffset) {
+ try {
+ return ClassLoaderUtils.callWithClassLoader(method.getDeclaringClass().getClassLoader(),
+ () -> genericParameter(method.getGenericReturnType(), parameterOffset)
+ .flatMap(result -> result instanceof Class ? optionalCast((Class<?>) result) : Optional.empty()));
+ } catch (Exception e) {
+ /*
+ * It is safe to log this this exception on debug, since this
+ * method should not fail. Only failures are possible if the
+ * runtime / backing.
+ */
+ LOG.debug("Unable to find YANG modeled return type for {}", method, e);
+ }
+ return Optional.empty();
+ }
+
+ private static Optional<java.lang.reflect.Type> genericParameter(final java.lang.reflect.Type type,
+ final int offset) {
+ if (type instanceof ParameterizedType parameterized) {
+ final var parameters = parameterized.getActualTypeArguments();
+ if (parameters.length > offset) {
+ return Optional.of(parameters[offset]);
+ }
+ }
+ return Optional.empty();
+ }
+
+ private static Optional<Class<? extends DataContainer>> optionalCast(final Class<?> type) {
+ return DataContainer.class.isAssignableFrom(type) ? optionalDataContainer(type) : Optional.empty();
+ }
+
+
+ // FIXME: MDSAL-780: remove this method
+ static final Optional<Class<? extends DataContainer>> optionalDataContainer(final Class<?> type) {
+ return Optional.of(type.asSubclass(DataContainer.class));
+ }
}
import org.opendaylight.mdsal.binding.runtime.api.BindingRuntimeContext;
import org.opendaylight.mdsal.binding.runtime.api.ChoiceRuntimeType;
import org.opendaylight.mdsal.binding.runtime.api.CompositeRuntimeType;
+import org.opendaylight.mdsal.binding.spec.naming.BindingMapping;
import org.opendaylight.mdsal.binding.spec.reflect.BindingReflections;
import org.opendaylight.yangtools.yang.binding.Augmentable;
import org.opendaylight.yangtools.yang.binding.Augmentation;
final ImmutableMap<Method, ValueNodeCodecContext> tmpLeaves = factory().getLeafNodes(bindingClass,
getType().statement());
- final Map<Class<? extends DataContainer>, Method> clsToMethod =
- BindingReflections.getChildrenClassToMethod(bindingClass);
+ final Map<Class<? extends DataContainer>, Method> clsToMethod = getChildrenClassToMethod(bindingClass);
final Map<YangInstanceIdentifier.PathArgument, NodeContextSupplier> byYangBuilder = new HashMap<>();
final Map<Class<?>, DataContainerCodecPrototype<?>> byStreamClassBuilder = new HashMap<>();
}
// Find all non-default nonnullFoo() methods and update the corresponding property info
- for (var entry : BindingReflections.getChildrenClassToNonnullMethod(bindingClass).entrySet()) {
+ for (var entry : getChildrenClassToNonnullMethod(bindingClass).entrySet()) {
final var method = entry.getValue();
if (!method.isDefault()) {
daoProperties.compute(entry.getKey(), (key, value) -> new PropertyInfo.GetterAndNonnull(
checkArgument(bindingArg().equals(arg));
return getDomPathArgument();
}
+
+ /**
+ * Scans supplied class and returns an iterable of all data children classes.
+ *
+ * @param type YANG Modeled Entity derived from DataContainer
+ * @return Iterable of all data children, which have YANG modeled entity
+ */
+ // FIXME: MDSAL-780: replace use of this method
+ private static Map<Class<? extends DataContainer>, Method> getChildrenClassToMethod(final Class<?> type) {
+ return getChildClassToMethod(type, BindingMapping.GETTER_PREFIX);
+ }
+
+ // FIXME: MDSAL-780: replace use of this method
+ private static Map<Class<? extends DataContainer>, Method> getChildrenClassToNonnullMethod(final Class<?> type) {
+ return getChildClassToMethod(type, BindingMapping.NONNULL_PREFIX);
+ }
+
+ // FIXME: MDSAL-780: replace use of this method
+ private static Map<Class<? extends DataContainer>, Method> getChildClassToMethod(final Class<?> type,
+ final String prefix) {
+ checkArgument(type != null, "Target type must not be null");
+ checkArgument(DataContainer.class.isAssignableFrom(type), "Supplied type %s must be derived from DataContainer",
+ type);
+ final var ret = new HashMap<Class<? extends DataContainer>, Method>();
+ for (Method method : type.getMethods()) {
+ getYangModeledReturnType(method, prefix).ifPresent(entity -> ret.put(entity, method));
+ }
+ return ret;
+ }
}
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
-import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Arrays;
-import java.util.HashMap;
import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
import java.util.Optional;
import java.util.ServiceLoader;
import java.util.Set;
&& (targetType.getName().endsWith("Input") || targetType.getName().endsWith("Output"));
}
- /**
- * Scans supplied class and returns an iterable of all data children classes.
- *
- * @param type YANG Modeled Entity derived from DataContainer
- * @return Iterable of all data children, which have YANG modeled entity
- * @deprecated This method is only used in mdsal-binding-dom-codec and is schedule for removal.
- */
- @Deprecated(since = "10.0.4", forRemoval = true)
- @SuppressWarnings("unchecked")
- public static Iterable<Class<? extends DataObject>> getChildrenClasses(final Class<? extends DataContainer> type) {
- checkArgument(type != null, "Target type must not be null");
- checkArgument(DataContainer.class.isAssignableFrom(type), "Supplied type must be derived from DataContainer");
- List<Class<? extends DataObject>> ret = new LinkedList<>();
- for (Method method : type.getMethods()) {
- Optional<Class<? extends DataContainer>> entity = getYangModeledReturnType(method,
- BindingMapping.GETTER_PREFIX);
- if (entity.isPresent()) {
- ret.add((Class<? extends DataObject>) entity.get());
- }
- }
- return ret;
- }
-
- /**
- * Scans supplied class and returns an iterable of all data children classes.
- *
- * @param type YANG Modeled Entity derived from DataContainer
- * @return Iterable of all data children, which have YANG modeled entity
- * @deprecated This method is only used in mdsal-binding-dom-codec and is schedule for removal.
- */
- @Deprecated(since = "10.0.4", forRemoval = true)
- public static Map<Class<? extends DataContainer>, Method> getChildrenClassToMethod(final Class<?> type) {
- return getChildClassToMethod(type, BindingMapping.GETTER_PREFIX);
- }
-
- @Beta
- @Deprecated(since = "10.0.4", forRemoval = true)
- public static Map<Class<? extends DataContainer>, Method> getChildrenClassToNonnullMethod(final Class<?> type) {
- return getChildClassToMethod(type, BindingMapping.NONNULL_PREFIX);
- }
-
- private static Map<Class<? extends DataContainer>, Method> getChildClassToMethod(final Class<?> type,
- final String prefix) {
- checkArgument(type != null, "Target type must not be null");
- checkArgument(DataContainer.class.isAssignableFrom(type), "Supplied type %s must be derived from DataContainer",
- type);
- Map<Class<? extends DataContainer>, Method> ret = new HashMap<>();
- for (Method method : type.getMethods()) {
- Optional<Class<? extends DataContainer>> entity = getYangModeledReturnType(method, prefix);
- if (entity.isPresent()) {
- ret.put(entity.get(), method);
- }
- }
- return ret;
- }
-
- private static Optional<Class<? extends DataContainer>> getYangModeledReturnType(final Method method,
- final String prefix) {
- final String methodName = method.getName();
- if ("getClass".equals(methodName) || !methodName.startsWith(prefix) || method.getParameterCount() > 0) {
- return Optional.empty();
- }
-
- final Class<?> returnType = method.getReturnType();
- if (DataContainer.class.isAssignableFrom(returnType)) {
- return optionalDataContainer(returnType);
- } else if (List.class.isAssignableFrom(returnType)) {
- return getYangModeledReturnType(method, 0);
- } else if (Map.class.isAssignableFrom(returnType)) {
- return getYangModeledReturnType(method, 1);
- }
- return Optional.empty();
- }
-
- @SuppressWarnings("checkstyle:illegalCatch")
- private static Optional<Class<? extends DataContainer>> getYangModeledReturnType(final Method method,
- final int parameterOffset) {
- try {
- return ClassLoaderUtils.callWithClassLoader(method.getDeclaringClass().getClassLoader(),
- () -> genericParameter(method.getGenericReturnType(), parameterOffset)
- .flatMap(result -> result instanceof Class ? optionalCast((Class<?>) result) : Optional.empty()));
- } catch (Exception e) {
- /*
- * It is safe to log this this exception on debug, since this
- * method should not fail. Only failures are possible if the
- * runtime / backing.
- */
- LOG.debug("Unable to find YANG modeled return type for {}", method, e);
- }
- return Optional.empty();
- }
-
- private static Optional<Class<? extends DataContainer>> optionalCast(final Class<?> type) {
- return DataContainer.class.isAssignableFrom(type) ? optionalDataContainer(type) : Optional.empty();
- }
-
- private static Optional<Class<? extends DataContainer>> optionalDataContainer(final Class<?> type) {
- return Optional.of(type.asSubclass(DataContainer.class));
- }
-
- private static Optional<Type> genericParameter(final Type type, final int offset) {
- if (type instanceof ParameterizedType parameterized) {
- final Type[] parameters = parameterized.getActualTypeArguments();
- if (parameters.length > offset) {
- return Optional.of(parameters[offset]);
- }
- }
- return Optional.empty();
- }
-
private static class ClassToQNameLoader extends CacheLoader<Class<?>, Optional<QName>> {
@Override