1 package com.fasterxml.jackson.databind.deser;
2
3 import java.util.*;
4 import java.util.Map.Entry;
5
6 import com.fasterxml.jackson.annotation.ObjectIdGenerator;
7 import com.fasterxml.jackson.annotation.ObjectIdResolver;
8 import com.fasterxml.jackson.annotation.ObjectIdGenerator.IdKey;
9
10 import com.fasterxml.jackson.core.JsonParser;
11
12 import com.fasterxml.jackson.databind.*;
13 import com.fasterxml.jackson.databind.cfg.HandlerInstantiator;
14 import com.fasterxml.jackson.databind.deser.impl.ReadableObjectId;
15 import com.fasterxml.jackson.databind.deser.impl.ReadableObjectId.Referring;
16 import com.fasterxml.jackson.databind.introspect.Annotated;
17 import com.fasterxml.jackson.databind.util.ClassUtil;
18
19
28 public abstract class DefaultDeserializationContext
29 extends DeserializationContext
30 implements java.io.Serializable
31 {
32 private static final long serialVersionUID = 1L;
33
34 protected transient LinkedHashMap<ObjectIdGenerator.IdKey, ReadableObjectId> _objectIds;
35
36 private List<ObjectIdResolver> _objectIdResolvers;
37
38
43 protected DefaultDeserializationContext(DeserializerFactory df, DeserializerCache cache) {
44 super(df, cache);
45 }
46
47 protected DefaultDeserializationContext(DefaultDeserializationContext src,
48 DeserializationConfig config, JsonParser jp, InjectableValues values) {
49 super(src, config, jp, values);
50 }
51
52 protected DefaultDeserializationContext(DefaultDeserializationContext src,
53 DeserializerFactory factory) {
54 super(src, factory);
55 }
56
57
60 protected DefaultDeserializationContext(DefaultDeserializationContext src) {
61 super(src);
62 }
63
64
72 public DefaultDeserializationContext copy() {
73 throw new IllegalStateException("DefaultDeserializationContext sub-class not overriding copy()");
74 }
75
76
81
82 @Override
83 public ReadableObjectId findObjectId(Object id, ObjectIdGenerator<?> gen, ObjectIdResolver resolverType)
84 {
85
88 if (id == null) {
89 return null;
90 }
91
92 final ObjectIdGenerator.IdKey key = gen.key(id);
93
94 if (_objectIds == null) {
95 _objectIds = new LinkedHashMap<ObjectIdGenerator.IdKey,ReadableObjectId>();
96 } else {
97 ReadableObjectId entry = _objectIds.get(key);
98 if (entry != null) {
99 return entry;
100 }
101 }
102
103
104 ObjectIdResolver resolver = null;
105
106 if (_objectIdResolvers == null) {
107 _objectIdResolvers = new ArrayList<ObjectIdResolver>(8);
108 } else {
109 for (ObjectIdResolver res : _objectIdResolvers) {
110 if (res.canUseFor(resolverType)) {
111 resolver = res;
112 break;
113 }
114 }
115 }
116
117 if (resolver == null) {
118 resolver = resolverType.newForDeserialization(this);
119 _objectIdResolvers.add(resolver);
120 }
121
122 ReadableObjectId entry = createReadableObjectId(key);
123 entry.setResolver(resolver);
124 _objectIds.put(key, entry);
125 return entry;
126 }
127
128
140 protected ReadableObjectId createReadableObjectId(IdKey key) {
141 return new ReadableObjectId(key);
142 }
143
144 @Override
145 public void checkUnresolvedObjectId() throws UnresolvedForwardReference
146 {
147 if (_objectIds == null) {
148 return;
149 }
150
151 if (!isEnabled(DeserializationFeature.FAIL_ON_UNRESOLVED_OBJECT_IDS)) {
152 return;
153 }
154 UnresolvedForwardReference exception = null;
155 for (Entry<IdKey,ReadableObjectId> entry : _objectIds.entrySet()) {
156 ReadableObjectId roid = entry.getValue();
157 if (!roid.hasReferringProperties()) {
158 continue;
159 }
160
161 if (tryToResolveUnresolvedObjectId(roid)) {
162 continue;
163 }
164 if (exception == null) {
165 exception = new UnresolvedForwardReference(getParser(), "Unresolved forward references for: ");
166 }
167 Object key = roid.getKey().key;
168 for (Iterator<Referring> iterator = roid.referringProperties(); iterator.hasNext(); ) {
169 Referring referring = iterator.next();
170 exception.addUnresolvedId(key, referring.getBeanType(), referring.getLocation());
171 }
172 }
173 if (exception != null) {
174 throw exception;
175 }
176 }
177
178
188 protected boolean tryToResolveUnresolvedObjectId(ReadableObjectId roid)
189 {
190 return roid.tryToResolveUnresolved(this);
191 }
192
193
198
199 @SuppressWarnings("unchecked")
200 @Override
201 public JsonDeserializer<Object> deserializerInstance(Annotated ann, Object deserDef)
202 throws JsonMappingException
203 {
204 if (deserDef == null) {
205 return null;
206 }
207 JsonDeserializer<?> deser;
208
209 if (deserDef instanceof JsonDeserializer) {
210 deser = (JsonDeserializer<?>) deserDef;
211 } else {
212
215 if (!(deserDef instanceof Class)) {
216 throw new IllegalStateException("AnnotationIntrospector returned deserializer definition of type "+deserDef.getClass().getName()+"; expected type JsonDeserializer or Class<JsonDeserializer> instead");
217 }
218 Class<?> deserClass = (Class<?>)deserDef;
219
220 if (deserClass == JsonDeserializer.None.class || ClassUtil.isBogusClass(deserClass)) {
221 return null;
222 }
223 if (!JsonDeserializer.class.isAssignableFrom(deserClass)) {
224 throw new IllegalStateException("AnnotationIntrospector returned Class "+deserClass.getName()+"; expected Class<JsonDeserializer>");
225 }
226 HandlerInstantiator hi = _config.getHandlerInstantiator();
227 deser = (hi == null) ? null : hi.deserializerInstance(_config, ann, deserClass);
228 if (deser == null) {
229 deser = (JsonDeserializer<?>) ClassUtil.createInstance(deserClass,
230 _config.canOverrideAccessModifiers());
231 }
232 }
233
234 if (deser instanceof ResolvableDeserializer) {
235 ((ResolvableDeserializer) deser).resolve(this);
236 }
237 return (JsonDeserializer<Object>) deser;
238 }
239
240 @Override
241 public final KeyDeserializer keyDeserializerInstance(Annotated ann, Object deserDef)
242 throws JsonMappingException
243 {
244 if (deserDef == null) {
245 return null;
246 }
247
248 KeyDeserializer deser;
249
250 if (deserDef instanceof KeyDeserializer) {
251 deser = (KeyDeserializer) deserDef;
252 } else {
253 if (!(deserDef instanceof Class)) {
254 throw new IllegalStateException("AnnotationIntrospector returned key deserializer definition of type "
255 +deserDef.getClass().getName()
256 +"; expected type KeyDeserializer or Class<KeyDeserializer> instead");
257 }
258 Class<?> deserClass = (Class<?>)deserDef;
259
260 if (deserClass == KeyDeserializer.None.class || ClassUtil.isBogusClass(deserClass)) {
261 return null;
262 }
263 if (!KeyDeserializer.class.isAssignableFrom(deserClass)) {
264 throw new IllegalStateException("AnnotationIntrospector returned Class "+deserClass.getName()
265 +"; expected Class<KeyDeserializer>");
266 }
267 HandlerInstantiator hi = _config.getHandlerInstantiator();
268 deser = (hi == null) ? null : hi.keyDeserializerInstance(_config, ann, deserClass);
269 if (deser == null) {
270 deser = (KeyDeserializer) ClassUtil.createInstance(deserClass,
271 _config.canOverrideAccessModifiers());
272 }
273 }
274
275 if (deser instanceof ResolvableDeserializer) {
276 ((ResolvableDeserializer) deser).resolve(this);
277 }
278 return deser;
279 }
280
281
286
287
291 public abstract DefaultDeserializationContext with(DeserializerFactory factory);
292
293
297 public abstract DefaultDeserializationContext createInstance(
298 DeserializationConfig config, JsonParser jp, InjectableValues values);
299
300
305
306
309 public final static class Impl extends DefaultDeserializationContext
310 {
311 private static final long serialVersionUID = 1L;
312
313
317 public Impl(DeserializerFactory df) {
318 super(df, null);
319 }
320
321 protected Impl(Impl src,
322 DeserializationConfig config, JsonParser jp, InjectableValues values) {
323 super(src, config, jp, values);
324 }
325
326 protected Impl(Impl src) { super(src); }
327
328 protected Impl(Impl src, DeserializerFactory factory) {
329 super(src, factory);
330 }
331
332 @Override
333 public DefaultDeserializationContext copy() {
334 ClassUtil.verifyMustOverride(Impl.class, this, "copy");
335 return new Impl(this);
336 }
337
338 @Override
339 public DefaultDeserializationContext createInstance(DeserializationConfig config,
340 JsonParser p, InjectableValues values) {
341 return new Impl(this, config, p, values);
342 }
343
344 @Override
345 public DefaultDeserializationContext with(DeserializerFactory factory) {
346 return new Impl(this, factory);
347 }
348 }
349 }
350