in juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanPropertyMeta.java [664:840]
private Object setInner(BeanMap<?> m, String pName, Object value) throws BeanRuntimeException {
try {
if (readOnly)
return null;
BeanSession session = m.getBeanSession();
// Convert to raw form.
value = unswap(session, value);
if (m.bean == null) {
// Read-only beans get their properties stored in a cache.
if (m.propertyCache != null)
return m.propertyCache.put(name, value);
throw new BeanRuntimeException("Non-existent bean instance on bean.");
}
boolean isMap = rawTypeMeta.isMap();
boolean isCollection = rawTypeMeta.isCollection();
if ((! isDyna) && field == null && setter == null && ! (isMap || isCollection)) {
if ((value == null && beanContext.isIgnoreUnknownNullBeanProperties()) || beanContext.isIgnoreMissingSetters())
return null;
throw new BeanRuntimeException(beanMeta.c, "Setter or public field not defined on property ''{0}''", name);
}
Object bean = m.getBean(true); // Don't use getBean() because it triggers array creation!
try {
Object r = (beanContext.isBeanMapPutReturnsOldValue() || isMap || isCollection) && (getter != null || field != null) ? get(m, pName) : null;
Class<?> propertyClass = rawTypeMeta.getInnerClass();
ClassInfo pcInfo = rawTypeMeta.getInfo();
if (value == null && (isMap || isCollection)) {
invokeSetter(bean, pName, null);
return r;
}
Class<?> vc = value == null ? null : value.getClass();
if (isMap && (setter == null || ! pcInfo.isParentOf(vc))) {
if (! (value instanceof Map)) {
if (value instanceof CharSequence)
value = JsonMap.ofJson((CharSequence)value).session(session);
else
throw new BeanRuntimeException(beanMeta.c, "Cannot set property ''{0}'' of type ''{1}'' to object of type ''{2}''", name, propertyClass.getName(), findClassName(value));
}
Map valueMap = (Map)value;
Map propMap = (Map)r;
ClassMeta<?> valueType = rawTypeMeta.getValueType();
// If the property type is abstract, then we either need to reuse the existing
// map (if it's not null), or try to assign the value directly.
if (! rawTypeMeta.canCreateNewInstance()) {
if (propMap == null) {
if (setter == null && field == null)
throw new BeanRuntimeException(beanMeta.c, "Cannot set property ''{0}'' of type ''{1}'' to object of type ''{2}'' because no setter or public field is defined, and the current value is null", name, propertyClass.getName(), findClassName(value));
if (propertyClass.isInstance(valueMap)) {
if (! valueType.isObject()) {
Flag needsConversion = Flag.create();
valueMap.forEach((k,v) -> {
if (v != null && ! valueType.getInnerClass().isInstance(v)) {
needsConversion.set();
}
});
if (needsConversion.isSet())
valueMap = (Map)session.convertToType(valueMap, rawTypeMeta);
}
invokeSetter(bean, pName, valueMap);
return r;
}
throw new BeanRuntimeException(beanMeta.c, "Cannot set property ''{0}'' of type ''{2}'' to object of type ''{2}'' because the assigned map cannot be converted to the specified type because the property type is abstract, and the property value is currently null", name, propertyClass.getName(), findClassName(value));
}
} else {
if (propMap == null) {
propMap = BeanCreator.of(Map.class).type(propertyClass).run();
} else {
propMap.clear();
}
}
// Set the values.
Map propMap2 = propMap;
valueMap.forEach((k,v) -> {
if (! valueType.isObject())
v = session.convertToType(v, valueType);
propMap2.put(k, v);
});
if (setter != null || field != null)
invokeSetter(bean, pName, propMap);
} else if (isCollection && (setter == null || ! pcInfo.isParentOf(vc))) {
if (! (value instanceof Collection)) {
if (value instanceof CharSequence)
value = new JsonList((CharSequence)value).setBeanSession(session);
else
throw new BeanRuntimeException(beanMeta.c, "Cannot set property ''{0}'' of type ''{1}'' to object of type ''{2}''", name, propertyClass.getName(), findClassName(value));
}
Collection valueList = (Collection)value;
Collection propList = (Collection)r;
ClassMeta elementType = rawTypeMeta.getElementType();
// If the property type is abstract, then we either need to reuse the existing
// collection (if it's not null), or try to assign the value directly.
if (! rawTypeMeta.canCreateNewInstance()) {
if (propList == null) {
if (setter == null && field == null)
throw new BeanRuntimeException(beanMeta.c, "Cannot set property ''{0}'' of type ''{1}'' to object of type ''{2}'' because no setter or public field is defined, and the current value is null", name, propertyClass.getName(), findClassName(value));
if (propertyClass.isInstance(valueList) || (setter != null && setter.getParameterTypes()[0] == Collection.class)) {
if (! elementType.isObject()) {
List l = new JsonList(valueList);
for (ListIterator<Object> i = l.listIterator(); i.hasNext(); ) {
Object v = i.next();
if (v != null && (! elementType.getInnerClass().isInstance(v))) {
i.set(session.convertToType(v, elementType));
}
}
valueList = l;
}
invokeSetter(bean, pName, valueList);
return r;
}
throw new BeanRuntimeException(beanMeta.c, "Cannot set property ''{0}'' of type ''{1}'' to object of type ''{2}'' because the assigned map cannot be converted to the specified type because the property type is abstract, and the property value is currently null", name, propertyClass.getName(), findClassName(value));
}
propList.clear();
} else {
if (propList == null) {
propList = BeanCreator.of(Collection.class).type(propertyClass).run();
invokeSetter(bean, pName, propList);
} else {
propList.clear();
}
}
// Set the values.
Collection propList2 = propList;
valueList.forEach(x -> {
if (! elementType.isObject())
x = session.convertToType(x, elementType);
propList2.add(x);
});
} else {
if (swap != null && value != null && swap.getSwapClass().isParentOf(value.getClass())) {
value = swap.unswap(session, value, rawTypeMeta);
} else {
value = session.convertToType(value, rawTypeMeta);
}
invokeSetter(bean, pName, value);
}
return r;
} catch (BeanRuntimeException e) {
throw e;
} catch (Exception e) {
if (beanContext.isIgnoreInvocationExceptionsOnSetters()) {
if (rawTypeMeta.isPrimitive())
return rawTypeMeta.getPrimitiveDefault();
return null;
}
throw new BeanRuntimeException(e, beanMeta.c, "Error occurred trying to set property ''{0}''", name);
}
} catch (ParseException e) {
throw new BeanRuntimeException(e);
}
}