Added headers to the concepts bundles
[mdsal.git] / yang / yang-binding / src / main / java / org / opendaylight / yangtools / yang / binding / util / BindingReflections.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.yangtools.yang.binding.util;
9
10 import java.lang.reflect.Field;
11 import java.util.concurrent.TimeUnit;
12
13 import org.opendaylight.yangtools.concepts.util.ClassLoaderUtils;
14 import org.opendaylight.yangtools.yang.binding.Augmentable;
15 import org.opendaylight.yangtools.yang.binding.Augmentation;
16 import org.opendaylight.yangtools.yang.binding.BindingMapping;
17 import org.opendaylight.yangtools.yang.binding.ChildOf;
18 import org.opendaylight.yangtools.yang.binding.DataContainer;
19 import org.opendaylight.yangtools.yang.binding.DataObject;
20 import org.opendaylight.yangtools.yang.common.QName;
21
22 import com.google.common.base.Optional;
23 import com.google.common.cache.CacheBuilder;
24 import com.google.common.cache.CacheLoader;
25 import com.google.common.cache.LoadingCache;
26
27 public class BindingReflections {
28
29     private static final long EXPIRATION_TIME = 60;
30
31     private static final LoadingCache<Class<?>, Optional<QName>> classToQName = CacheBuilder.newBuilder() //
32             .weakKeys() //
33             .expireAfterAccess(EXPIRATION_TIME, TimeUnit.SECONDS) //
34             .build(new ClassToQNameLoader());
35
36     /**
37      * 
38      * @param augmentation
39      *            {@link Augmentation} subclass for which we want to determine
40      *            augmentation target.
41      * @return Augmentation target - class which augmentation provides
42      *         additional extensions.
43      */
44     public static Class<? extends Augmentable<?>> findAugmentationTarget(
45             final Class<? extends Augmentation<?>> augmentation) {
46         return ClassLoaderUtils.findFirstGenericArgument(augmentation, Augmentation.class);
47     }
48
49     /**
50      * 
51      * @param augmentation
52      *            {@link Augmentation} subclass for which we want to determine
53      *            augmentation target.
54      * @return Augmentation target - class which augmentation provides
55      *         additional extensions.
56      */
57     public static Class<?> findHierarchicalParent(final Class<? extends ChildOf<?>> childClass) {
58         return ClassLoaderUtils.findFirstGenericArgument(childClass, ChildOf.class);
59     }
60
61     /**
62      * 
63      * @param augmentation
64      *            {@link Augmentation} subclass for which we want to determine
65      *            augmentation target.
66      * @return Augmentation target - class which augmentation provides
67      *         additional extensions.
68      */
69     public static Class<?> findHierarchicalParent(DataObject childClass) {
70         if (childClass instanceof ChildOf) {
71             return ClassLoaderUtils.findFirstGenericArgument(childClass.getImplementedInterface(), ChildOf.class);
72         }
73         return null;
74     }
75
76     public static final QName findQName(Class<? extends DataContainer> dataType) {
77         return classToQName.getUnchecked(dataType).orNull();
78     }
79
80     private static class ClassToQNameLoader extends CacheLoader<Class<?>, Optional<QName>> {
81
82         @Override
83         public Optional<QName> load(Class<?> key) throws Exception {
84             try {
85                 Field field = key.getField(BindingMapping.QNAME_STATIC_FIELD_NAME);
86                 Object obj = field.get(null);
87                 if (obj instanceof QName) {
88                     return Optional.of((QName) obj);
89                 }
90             } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
91                 // NOOP
92             }
93             return Optional.absent();
94         }
95     }
96
97 }