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