1 package com.fasterxml.jackson.databind.deser.impl; 2 3 import java.io.IOException; 4 import java.util.Collections; 5 import java.util.Iterator; 6 import java.util.LinkedList; 7 8 import com.fasterxml.jackson.annotation.ObjectIdGenerator; 9 import com.fasterxml.jackson.annotation.ObjectIdResolver; 10 import com.fasterxml.jackson.core.JsonLocation; 11 import com.fasterxml.jackson.databind.DeserializationContext; 12 import com.fasterxml.jackson.databind.JavaType; 13 import com.fasterxml.jackson.databind.deser.UnresolvedForwardReference; 14 15 /** 16 * Simple value container for containing information about single Object Id 17 * during deserialization 18 */ 19 public class ReadableObjectId 20 { 21 /** 22 * @since 2.8 (with this name, formerly `public Object item`) 23 */ 24 protected Object _item; 25 26 protected final ObjectIdGenerator.IdKey _key; 27 28 protected LinkedList<Referring> _referringProperties; 29 30 protected ObjectIdResolver _resolver; 31 ReadableObjectId(ObjectIdGenerator.IdKey key)32 public ReadableObjectId(ObjectIdGenerator.IdKey key) { 33 _key = key; 34 } 35 setResolver(ObjectIdResolver resolver)36 public void setResolver(ObjectIdResolver resolver) { 37 _resolver = resolver; 38 } 39 getKey()40 public ObjectIdGenerator.IdKey getKey() { 41 return _key; 42 } 43 appendReferring(Referring currentReferring)44 public void appendReferring(Referring currentReferring) { 45 if (_referringProperties == null) { 46 _referringProperties = new LinkedList<Referring>(); 47 } 48 _referringProperties.add(currentReferring); 49 } 50 51 /** 52 * Method called to assign actual POJO to which ObjectId refers to: will 53 * also handle referring properties, if any, by assigning POJO. 54 */ bindItem(Object ob)55 public void bindItem(Object ob) throws IOException 56 { 57 _resolver.bindItem(_key, ob); 58 _item = ob; 59 Object id = _key.key; 60 if (_referringProperties != null) { 61 Iterator<Referring> it = _referringProperties.iterator(); 62 _referringProperties = null; 63 while (it.hasNext()) { 64 it.next().handleResolvedForwardReference(id, ob); 65 } 66 } 67 } 68 resolve()69 public Object resolve(){ 70 return (_item = _resolver.resolveId(_key)); 71 } 72 hasReferringProperties()73 public boolean hasReferringProperties() { 74 return (_referringProperties != null) && !_referringProperties.isEmpty(); 75 } 76 referringProperties()77 public Iterator<Referring> referringProperties() { 78 if (_referringProperties == null) { 79 return Collections.<Referring> emptyList().iterator(); 80 } 81 return _referringProperties.iterator(); 82 } 83 84 /** 85 * Method called by {@link DeserializationContext} at the end of deserialization 86 * if this Object Id was not resolved during normal processing. Call is made to 87 * allow custom implementations to use alternative resolution strategies; currently 88 * the only way to make use of this functionality is by sub-classing 89 * {@link ReadableObjectId} and overriding this method. 90 *<p> 91 * Default implementation simply returns <code>false</code> to indicate that resolution 92 * attempt did not succeed. 93 * 94 * @return True, if resolution succeeded (and no error needs to be reported); false to 95 * indicate resolution did not succeed. 96 * 97 * @since 2.6 98 */ tryToResolveUnresolved(DeserializationContext ctxt)99 public boolean tryToResolveUnresolved(DeserializationContext ctxt) 100 { 101 return false; 102 } 103 104 /** 105 * Allow access to the resolver in case anybody wants to use it directly, for 106 * examples from 107 * {@link com.fasterxml.jackson.databind.deser.DefaultDeserializationContext#tryToResolveUnresolvedObjectId}. 108 * 109 * @return The registered resolver 110 * 111 * @since 2.7 112 */ getResolver()113 public ObjectIdResolver getResolver() { 114 return _resolver; 115 } 116 117 @Override toString()118 public String toString() { 119 return String.valueOf(_key); 120 } 121 122 /* 123 /********************************************************** 124 /* Helper classes 125 /********************************************************** 126 */ 127 128 public static abstract class Referring { 129 private final UnresolvedForwardReference _reference; 130 private final Class<?> _beanType; 131 Referring(UnresolvedForwardReference ref, Class<?> beanType)132 public Referring(UnresolvedForwardReference ref, Class<?> beanType) { 133 _reference = ref; 134 _beanType = beanType; 135 } 136 Referring(UnresolvedForwardReference ref, JavaType beanType)137 public Referring(UnresolvedForwardReference ref, JavaType beanType) { 138 _reference = ref; 139 _beanType = beanType.getRawClass(); 140 } 141 getLocation()142 public JsonLocation getLocation() { return _reference.getLocation(); } getBeanType()143 public Class<?> getBeanType() { return _beanType; } 144 handleResolvedForwardReference(Object id, Object value)145 public abstract void handleResolvedForwardReference(Object id, Object value) throws IOException; hasId(Object id)146 public boolean hasId(Object id) { 147 return id.equals(_reference.getUnresolvedId()); 148 } 149 } 150 } 151