OptionController (@NotNull Object obj) { return of( bindId -> { int dot = bindId.indexOf('.'); Field field = getField(obj, bindId, dot); Object value = ReflectionUtil.getFieldValue(field, obj); if (dot >= 0) { if (!(value instanceof OptionContainer container)) { throw new IllegalArgumentException(obj.getClass().getName() + ": Field " + field.getName() + " (" + (value == null ? null : value.getClass()) + ")" + " does not implement OptionContainer (bindId = " + bindId + ")"); } try { return container.getOptionController().getOption(bindId.substring(dot + 1)); } catch (IllegalArgumentException e) { throw new IllegalArgumentException(obj.getClass().getName() + ": Field " + field.getName() + ": unable to query nested option", e); } } return value; }, (bindId, value) -> { int dot = bindId.indexOf('.'); Field field = getField(obj, bindId, dot); Object curValue = ReflectionUtil.getFieldValue(field, obj); if (dot >= 0) { if (!(curValue instanceof OptionContainer container)) { throw new IllegalArgumentException(obj.getClass().getName() + ": Field " + field.getName() + " (" + (curValue == null ? null : curValue.getClass()) + ")" + " does not implement OptionContainer (bindId = " + bindId + ")"); } try { container.getOptionController().setOption(bindId.substring(dot + 1), value); } catch (IllegalArgumentException e) { throw new IllegalArgumentException(obj.getClass().getName() + ": Field " + field.getName() + ": unable to update nested option", e); } } // Avoid updating field if new value is not the same // this way we can support final mutable fields, used by e.g. OptSet else if (curValue != value) { try { field.set(obj, value); } catch (IllegalAccessException e) { throw new IllegalArgumentException( "Inspection " + obj.getClass().getName() + ": Unable to assign field " + field.getName() + " (bindId = " + bindId + ")", e); } } } ); }