ManagedReferenceProperty.java
package tools.jackson.databind.deser.impl;
import java.util.Collection;
import java.util.Map;
import tools.jackson.core.JacksonException;
import tools.jackson.core.JsonParser;
import tools.jackson.databind.*;
import tools.jackson.databind.deser.SettableBeanProperty;
/**
* Wrapper property that is used to handle managed (forward) properties
* Basically just needs to delegate first to actual forward property, and
* then to back property.
*/
public final class ManagedReferenceProperty
// Changed to extends delegating base class in 2.9
extends SettableBeanProperty.Delegating
{
protected final String _referenceName;
/**
* Flag that indicates whether property to handle is a container type
* (array, Collection, Map) or not.
*/
protected final boolean _isContainer;
protected final SettableBeanProperty _backProperty;
public ManagedReferenceProperty(SettableBeanProperty forward, String refName,
SettableBeanProperty backward, boolean isContainer)
{
super(forward);
_referenceName = refName;
_backProperty = backward;
_isContainer = isContainer;
}
@Override
protected SettableBeanProperty withDelegate(SettableBeanProperty d) {
throw new IllegalStateException("Should never try to reset delegate");
}
// need to override to ensure both get fixed
@Override
public void fixAccess(DeserializationConfig config) {
delegate.fixAccess(config);
_backProperty.fixAccess(config);
}
/*
/**********************************************************
/* Overridden methods
/**********************************************************
*/
@Override
public void deserializeAndSet(JsonParser p, DeserializationContext ctxt, Object instance)
throws JacksonException
{
set(ctxt, instance, delegate.deserialize(p, ctxt));
}
@Override
public Object deserializeSetAndReturn(JsonParser p, DeserializationContext ctxt, Object instance)
throws JacksonException
{
return setAndReturn(ctxt, instance, deserialize(p, ctxt));
}
@Override
public final void set(DeserializationContext ctxt, Object instance, Object value) {
setAndReturn(ctxt, instance, value);
}
@Override
public Object setAndReturn(DeserializationContext ctxt, Object instance, Object value)
{
_setBackReference(ctxt, instance, value);
// and then the forward reference itself
return delegate.setAndReturn(ctxt, instance, value);
}
/*
/**********************************************************************
/* Helper methods
/**********************************************************************
*/
/**
* Helper method to inject back reference into value(s).
*/
private void _setBackReference(DeserializationContext ctxt, Object instance, Object value)
{
if (value == null) {
return;
}
// 04-Feb-2014, tatu: As per [#390], it may be necessary to switch the
// ordering of forward/backward references, and start with back ref.
if (_isContainer) { // ok, this gets ugly... but has to do for now
if (value instanceof Object[]) {
for (Object ob : (Object[]) value) {
if (ob != null) {
_backProperty.set(ctxt, ob, instance);
}
}
} else if (value instanceof Collection<?>) {
for (Object ob : (Collection<?>) value) {
if (ob != null) {
_backProperty.set(ctxt, ob, instance);
}
}
} else if (value instanceof Map<?,?>) {
for (Object ob : ((Map<?,?>) value).values()) {
if (ob != null) {
_backProperty.set(ctxt, ob, instance);
}
}
} else {
throw new IllegalStateException("Unsupported container type (" + value.getClass().getName()
+ ") when resolving reference '" + _referenceName + "'");
}
} else {
_backProperty.set(ctxt, value, instance);
}
}
}