1 /*
2  * Copyright 2014 - 2020 Rafael Winterhalter
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package net.bytebuddy.implementation.bind.annotation;
17
18 import net.bytebuddy.description.annotation.AnnotationDescription;
19 import net.bytebuddy.description.method.MethodDescription;
20 import net.bytebuddy.implementation.bind.MethodDelegationBinder;
21
22 import java.lang.annotation.*;
23
24 /**
25  * Defines a binding priority for a target method. If two target methods can be bound to a source method,
26  * the one with the higher priority will be selected.
27  *
28  * @see net.bytebuddy.implementation.MethodDelegation
29  * @see net.bytebuddy.implementation.bind.annotation.TargetMethodAnnotationDrivenBinder
30  */

31 @Documented
32 @Retention(RetentionPolicy.RUNTIME)
33 @Target(ElementType.METHOD)
34 public @interface BindingPriority {
35
36     /**
37      * The default priority for methods not carrying the
38      * {@link net.bytebuddy.implementation.bind.annotation.BindingPriority}
39      * annotation.
40      */

41     int DEFAULT = 1;
42
43     /**
44      * The binding priority for the annotated method. A method of higher priority will be preferred over a method
45      * of lower priority.
46      *
47      * @return The priority for the annotated method.
48      */

49     int value();
50
51     /**
52      * An ambiguity resolver that considers the priority of a method as defined by the
53      * {@link net.bytebuddy.implementation.bind.annotation.BindingPriority}
54      * annotation.
55      */

56     enum Resolver implements MethodDelegationBinder.AmbiguityResolver {
57
58         /**
59          * The singleton instance.
60          */

61         INSTANCE;
62
63         /**
64          * Resolves the explicitly stated binding priority of a method or returns the default value if no such
65          * explicit information can be found.
66          *
67          * @param bindingPriority The annotation of the method or {@code nullif no such annotation was found.
68          * @return The factual priority of the method under investigation.
69          */

70         private static int resolve(AnnotationDescription.Loadable<BindingPriority> bindingPriority) {
71             return bindingPriority == null
72                     ? BindingPriority.DEFAULT
73                     : bindingPriority.load().value();
74         }
75
76         /**
77          * {@inheritDoc}
78          */

79         public Resolution resolve(MethodDescription source,
80                                   MethodDelegationBinder.MethodBinding left,
81                                   MethodDelegationBinder.MethodBinding right) {
82             int leftPriority = resolve(left.getTarget().getDeclaredAnnotations().ofType(BindingPriority.class));
83             int rightPriority = resolve(right.getTarget().getDeclaredAnnotations().ofType(BindingPriority.class));
84             if (leftPriority == rightPriority) {
85                 return Resolution.AMBIGUOUS;
86             } else if (leftPriority < rightPriority) {
87                 return Resolution.RIGHT;
88             } else {
89                 return Resolution.LEFT;
90             }
91         }
92     }
93 }
94