private Object setInner()

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);
		}
	}