xref: /aosp_15_r20/external/jackson-annotations/src/main/java/com/fasterxml/jackson/annotation/JacksonInject.java (revision 2bf6642460ffb10303bd46207a4555f36d9e5945)
1 package com.fasterxml.jackson.annotation;
2 
3 import java.lang.annotation.ElementType;
4 import java.lang.annotation.Retention;
5 import java.lang.annotation.RetentionPolicy;
6 import java.lang.annotation.Target;
7 
8 import com.fasterxml.jackson.annotation.JacksonAnnotation;
9 
10 /**
11  * Jackson-specific annotation used for indicating that value of
12  * annotated property will be "injected", i.e. set based on value
13  * configured by <code>ObjectMapper</code> (usually on per-call basis).
14  * Usually property is not deserialized from JSON, although it possible
15  * to have injected value as default and still allow optional override
16  * from JSON.
17  */
18 @Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
19 @Retention(RetentionPolicy.RUNTIME)
20 @JacksonAnnotation
21 public @interface JacksonInject
22 {
23     /**
24      * Logical id of the value to inject; if not specified (or specified
25      * as empty String), will use id based on declared type of property.
26      *
27      * @return Logical id of the value to inject
28      */
value()29     public String value() default "";
30 
31     /**
32      * Whether matching value from input (if any) is used for annotated property or not;
33      * if disabled (`OptBoolean.FALSE`), input value (if any) will be ignored;
34      * otherwise it will override injected value.
35      *<p>
36      * Default is `OptBoolean.DEFAULT`, which translates to `OptBoolean.TRUE`: this is
37      * for backwards compatibility (2.8 and earlier always allow binding input value).
38      *
39      * @return {@link OptBoolean#TRUE} to enable use of value from input instead of
40      *    injected value, if available; {@link OptBoolean#FALSE} if injected value will
41      *    always be used regardless of input.
42      *
43      * @since 2.9
44      */
useInput()45     public OptBoolean useInput() default OptBoolean.DEFAULT;
46 
47     /*
48     /**********************************************************
49     /* Value class used to enclose information, allow for
50     /* merging of layered configuration settings, and eventually
51     /* decouple higher level handling from Annotation types
52     /* (which can not be implemented etc)
53     /**********************************************************
54      */
55 
56     /**
57      * Helper class used to contain information from a single {@link JacksonInject}
58      * annotation, as well as to provide possible overrides from non-annotation sources.
59      *
60      * @since 2.9
61      */
62     public static class Value
63         implements JacksonAnnotationValue<JacksonInject>,
64             java.io.Serializable
65     {
66         private static final long serialVersionUID = 1L;
67 
68         protected final static Value EMPTY = new Value(null, null);
69 
70         /**
71          * Id to use to access injected value; if `null`, "default" name, derived
72          * from accessor will be used.
73          */
74         protected final Object _id;
75 
76         protected final Boolean _useInput;
77 
Value(Object id, Boolean useInput)78         protected Value(Object id, Boolean useInput) {
79             _id = id;
80             _useInput = useInput;
81         }
82 
83         @Override
valueFor()84         public Class<JacksonInject> valueFor() {
85             return JacksonInject.class;
86         }
87 
88         /*
89         /**********************************************************
90         /* Factory methods
91         /**********************************************************
92          */
93 
empty()94         public static Value empty() {
95             return EMPTY;
96         }
97 
construct(Object id, Boolean useInput)98         public static Value construct(Object id, Boolean useInput) {
99             if ("".equals(id)) {
100                 id = null;
101             }
102             if (_empty(id, useInput)) {
103                 return EMPTY;
104             }
105             return new Value(id, useInput);
106         }
107 
from(JacksonInject src)108         public static Value from(JacksonInject src) {
109             if (src == null) {
110                 return EMPTY;
111             }
112             return construct(src.value(), src.useInput().asBoolean());
113         }
114 
forId(Object id)115         public static Value forId(Object id) {
116             return construct(id, null);
117         }
118 
119         /*
120         /**********************************************************
121         /* Mutant factory methods
122         /**********************************************************
123          */
124 
withId(Object id)125         public Value withId(Object id) {
126             if (id == null) {
127                 if (_id == null) {
128                     return this;
129                 }
130             } else if (id.equals(_id)) {
131                 return this;
132             }
133             return new Value(id, _useInput);
134         }
135 
withUseInput(Boolean useInput)136         public Value withUseInput(Boolean useInput) {
137             if (useInput == null) {
138                 if (_useInput == null) {
139                     return this;
140                 }
141             } else if (useInput.equals(_useInput)) {
142                 return this;
143             }
144             return new Value(_id, useInput);
145         }
146 
147         /*
148         /**********************************************************
149         /* Accessors
150         /**********************************************************
151          */
152 
getId()153         public Object getId() { return _id; }
getUseInput()154         public Boolean getUseInput() { return _useInput; }
155 
hasId()156         public boolean hasId() {
157             return _id != null;
158         }
159 
willUseInput(boolean defaultSetting)160         public boolean willUseInput(boolean defaultSetting) {
161             return (_useInput == null) ? defaultSetting : _useInput.booleanValue();
162         }
163 
164         /*
165         /**********************************************************
166         /* Std method overrides
167         /**********************************************************
168          */
169 
170         @Override
toString()171         public String toString() {
172             return String.format("JacksonInject.Value(id=%s,useInput=%s)",
173                     _id, _useInput);
174         }
175 
176         @Override
hashCode()177         public int hashCode() {
178             int h = 1;
179             if (_id != null) {
180                 h += _id.hashCode();
181             }
182             if (_useInput != null) {
183                 h += _useInput.hashCode();
184             }
185             return h;
186         }
187 
188         @Override
equals(Object o)189         public boolean equals(Object o) {
190             if (o == this) return true;
191             if (o == null) return false;
192             if (o.getClass() == getClass()) {
193                 Value other = (Value) o;
194                 if (OptBoolean.equals(_useInput, other._useInput)) {
195                     if (_id == null) {
196                         return other._id == null;
197                     }
198                     return _id.equals(other._id);
199                 }
200             }
201             return false;
202         }
203 
204         /*
205         /**********************************************************
206         /* Other
207         /**********************************************************
208          */
209 
_empty(Object id, Boolean useInput)210         private static boolean _empty(Object id, Boolean useInput) {
211             return (id == null) && (useInput == null);
212         }
213     }
214 }
215