2 * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.javav2.dom.adapter.extractor;
10 import com.google.common.annotations.Beta;
11 import com.google.common.cache.CacheBuilder;
12 import com.google.common.cache.CacheLoader;
13 import com.google.common.cache.LoadingCache;
14 import java.lang.reflect.Method;
15 import javax.annotation.Nonnull;
16 import javax.annotation.Nullable;
17 import org.opendaylight.mdsal.binding.javav2.api.annotation.RoutingContext;
18 import org.opendaylight.mdsal.binding.javav2.spec.base.InstanceIdentifier;
19 import org.opendaylight.mdsal.binding.javav2.spec.base.TreeNode;
20 import org.slf4j.Logger;
21 import org.slf4j.LoggerFactory;
24 * Tree node reference extractor.
27 public abstract class ContextReferenceExtractor {
29 private static final Logger LOG = LoggerFactory.getLogger(ContextReferenceExtractor.class);
30 private static final String GET_VALUE_NAME = "getValue";
32 private static final ContextReferenceExtractor NULL_EXTRACTOR = new ContextReferenceExtractor() {
36 public InstanceIdentifier<? extends TreeNode> extract(final TreeNode obj) {
41 private static final LoadingCache<Class<?>, ContextReferenceExtractor> EXTRACTORS =
42 CacheBuilder.newBuilder().weakKeys().build(new CacheLoader<Class<?>, ContextReferenceExtractor>() {
46 public ContextReferenceExtractor load(@Nonnull final Class<?> key) throws Exception {
50 private ContextReferenceExtractor create(final Class<?> key) {
51 final Method contextGetter = getContextGetter(key);
52 if (contextGetter == null) {
53 return NULL_EXTRACTOR;
55 final Class<?> returnType = contextGetter.getReturnType();
57 if (InstanceIdentifier.class.isAssignableFrom(returnType)) {
58 return DirectGetterRouteContextExtractor.create(contextGetter);
60 final Method getValueMethod = findGetValueMethod(returnType);
61 if (getValueMethod != null) {
62 return GetValueRouteContextExtractor.create(contextGetter, getValueMethod);
64 LOG.warn("Class {} can not be used to determine context, falling back to NULL_EXTRACTOR.",
67 } catch (final IllegalAccessException e) {
68 LOG.warn("Class {} does not conform to Binding Specification. Falling back to NULL_EXTRACTOR",
71 return NULL_EXTRACTOR;
74 private Method getContextGetter(final Class<?> key) {
75 for (final Method method : key.getMethods()) {
76 if (method.getAnnotation(RoutingContext.class) != null) {
85 * Extract context-reference (Instance Identifier) from Binding TreeNode.
88 * - TreeNode from which context reference should be extracted.
90 * @return Instance Identifier representing context reference or null, if tree node does not contain
94 public abstract InstanceIdentifier<? extends TreeNode> extract(TreeNode obj);
97 * Method for return specific extractor of input object.
100 * - object for get specific extractor
101 * @return specific extractor
103 public static ContextReferenceExtractor from(final Class<?> obj) {
104 return EXTRACTORS.getUnchecked(obj);
107 private static Method findGetValueMethod(final Class<?> type) {
109 final Method method = type.getMethod(GET_VALUE_NAME);
110 if (InstanceIdentifier.class.equals(method.getReturnType())) {
113 } catch (final NoSuchMethodException e) {
114 LOG.warn("Value class {} does not comform to Binding Specification.", type, e);