X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=binding%2Fmdsal-binding-spec-util%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fmdsal%2Fbinding%2Fspec%2Freflect%2FBindingReflections.java;h=0f1dc3e9b90fc2b18ee2ec508e928fc9d4a6c2bc;hb=0ee55d1f9da11dd03ff05fc67d10cbcbfe63fd2c;hp=2c1a2d1871be926cc51406a7fdbcac74fb8881ec;hpb=b111382f80a9a058f32556b72bcc48b3a88fdcdc;p=mdsal.git diff --git a/binding/mdsal-binding-spec-util/src/main/java/org/opendaylight/mdsal/binding/spec/reflect/BindingReflections.java b/binding/mdsal-binding-spec-util/src/main/java/org/opendaylight/mdsal/binding/spec/reflect/BindingReflections.java index 2c1a2d1871..0f1dc3e9b9 100644 --- a/binding/mdsal-binding-spec-util/src/main/java/org/opendaylight/mdsal/binding/spec/reflect/BindingReflections.java +++ b/binding/mdsal-binding-spec-util/src/main/java/org/opendaylight/mdsal/binding/spec/reflect/BindingReflections.java @@ -9,7 +9,6 @@ package org.opendaylight.mdsal.binding.spec.reflect; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkState; -import static com.google.common.base.Verify.verifyNotNull; import static java.util.Objects.requireNonNull; import com.google.common.annotations.Beta; @@ -20,6 +19,7 @@ import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet.Builder; import com.google.common.util.concurrent.ListenableFuture; import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.ParameterizedType; @@ -247,35 +247,40 @@ public final class BindingReflections { return match.group(0); } - @SuppressWarnings("checkstyle:illegalCatch") public static QNameModule getQNameModule(final Class clz) { if (DataContainer.class.isAssignableFrom(clz) || BaseIdentity.class.isAssignableFrom(clz) || Action.class.isAssignableFrom(clz)) { return findQName(clz).getModule(); } - try { - return getModuleInfo(clz).getName().getModule(); - } catch (Exception e) { - throw new IllegalStateException("Unable to get QName of defining model.", e); - } + + return getModuleInfo(clz).getName().getModule(); } /** * Returns instance of {@link YangModuleInfo} of declaring model for specific class. * * @param cls data object class - * @return Instance of {@link YangModuleInfo} associated with model, from - * which this class was derived. + * @return Instance of {@link YangModuleInfo} associated with model, from which this class was derived. */ - // FIXME: 8.0.0: do not throw Exception here - public static @NonNull YangModuleInfo getModuleInfo(final Class cls) throws Exception { - checkArgument(cls != null); - String packageName = getModelRootPackageName(cls.getPackage()); + public static @NonNull YangModuleInfo getModuleInfo(final Class cls) { + final String packageName = getModelRootPackageName(cls.getPackage()); final String potentialClassName = getModuleInfoClassName(packageName); - return ClassLoaderUtils.callWithClassLoader(cls.getClassLoader(), () -> { - Class moduleInfoClass = Thread.currentThread().getContextClassLoader().loadClass(potentialClassName); - return (YangModuleInfo) verifyNotNull(moduleInfoClass.getMethod("getInstance").invoke(null)); - }); + final Class moduleInfoClass; + try { + moduleInfoClass = cls.getClassLoader().loadClass(potentialClassName); + } catch (ClassNotFoundException e) { + throw new IllegalStateException("Failed to load " + potentialClassName, e); + } + + final Object infoInstance; + try { + infoInstance = moduleInfoClass.getMethod("getInstance").invoke(null); + } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { + throw new IllegalStateException("Failed to get instance of " + moduleInfoClass, e); + } + + checkState(infoInstance instanceof YangModuleInfo, "Unexpected instance %s", infoInstance); + return (YangModuleInfo) infoInstance; } public static @NonNull String getModuleInfoClassName(final String packageName) { @@ -433,19 +438,24 @@ public final class BindingReflections { /** * Scans supplied class and returns an iterable of all data children classes. * - * @param type - * YANG Modeled Entity derived from DataContainer + * @param type YANG Modeled Entity derived from DataContainer * @return Iterable of all data children, which have YANG modeled entity */ - public static Map, Method> getChildrenClassToMethod(final Class type) { - return getChildrenClassToMethod(type, BindingMapping.GETTER_PREFIX); + public static Map, Method> getChildrenClassToMethod(final Class type) { + return getChildClassToMethod(type, BindingMapping.GETTER_PREFIX); } - private static Map, Method> getChildrenClassToMethod(final Class type, final String prefix) { + @Beta + public static Map, Method> getChildrenClassToNonnullMethod(final Class type) { + return getChildClassToMethod(type, BindingMapping.NONNULL_PREFIX); + } + + private static Map, 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, Method> ret = new HashMap<>(); + Map, Method> ret = new HashMap<>(); for (Method method : type.getMethods()) { Optional> entity = getYangModeledReturnType(method, prefix); if (entity.isPresent()) { @@ -455,11 +465,6 @@ public final class BindingReflections { return ret; } - @Beta - public static Map, Method> getChildrenClassToNonnullMethod(final Class type) { - return getChildrenClassToMethod(type, BindingMapping.NONNULL_PREFIX); - } - private static Optional> getYangModeledReturnType(final Method method, final String prefix) { final String methodName = method.getName(); @@ -482,10 +487,9 @@ public final class BindingReflections { private static Optional> getYangModeledReturnType(final Method method, final int parameterOffset) { try { - return ClassLoaderUtils.callWithClassLoader(method.getDeclaringClass().getClassLoader(), () -> { - return genericParameter(method.getGenericReturnType(), parameterOffset).flatMap( - result -> result instanceof Class ? optionalCast((Class) result) : Optional.empty()); - }); + 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 @@ -572,18 +576,11 @@ public final class BindingReflections { * @throws IllegalArgumentException If supplied class was not derived from YANG model. */ // FIXME: Extend this algorithm to also provide QName for YANG modeled simple types. - @SuppressWarnings({ "rawtypes", "unchecked", "checkstyle:illegalCatch" }) + @SuppressWarnings({ "rawtypes", "unchecked" }) private static QName computeQName(final Class key) { checkArgument(isBindingClass(key), "Supplied class %s is not derived from YANG.", key); - YangModuleInfo moduleInfo; - try { - moduleInfo = getModuleInfo(key); - } catch (Exception e) { - throw new IllegalStateException("Unable to get QName for " + key + ". YangModuleInfo was not found.", - e); - } - final QName module = moduleInfo.getName(); + final QName module = getModuleInfo(key).getName(); if (Augmentation.class.isAssignableFrom(key)) { return module; } else if (isRpcType(key)) { @@ -602,19 +599,6 @@ public final class BindingReflections { } } - /** - * Extracts augmentation from Binding DTO field using reflection. - * - * @param input Instance of DataObject which is augmentable and may contain augmentation - * @return Map of augmentations if read was successful, otherwise empty map. - * @deprecated Use {@link Augmentable#augmentations()} instead. - */ - @SuppressWarnings("unchecked") - @Deprecated(forRemoval = true) - public static Map>, Augmentation> getAugmentations(final Augmentable input) { - return (Map) input.augmentations(); - } - /** * Determines if two augmentation classes or case classes represents same * data. @@ -643,6 +627,11 @@ public final class BindingReflections { * Class which should be used at particular subtree * @return true if and only if classes represents same data. */ + // FIXME: this really should live in BindingRuntimeTypes and should not be based on reflection. The only user is + // binding-dom-codec and the logic could easily be performed on GeneratedType instead. For a particular + // world this boils down to a matrix, which can be calculated either on-demand or when we create + // BindingRuntimeTypes. Achieving that will bring us one step closer to being able to have a pre-compiled + // Binding Runtime. @SuppressWarnings({ "rawtypes", "unchecked" }) public static boolean isSubstitutionFor(final Class potential, final Class target) { Set subImplemented = new HashSet<>(Arrays.asList(potential.getInterfaces()));