Attrs { public static <E extends AcceptingVisitor> E populate(E instance, Map<String, Object> map) { return populate(instance, map, AliasMapper.SPI_DEFAULTS::fromName); }  static Map<String, Object> toMap(AcceptingVisitor composite); static Map<String, Object> toMap(
      AcceptingVisitor composite, Function<Object, String> classToName); static E fromMap(
      Class<? extends E> clazz, Map<String, Object> map); static E fromMap(
      Class<? extends E> clazz, Map<String, Object> map, Function<String, Object> nameToClass); static Map<String, Object> extract(
      AcceptingVisitor instance, Function<Object, String> classToName); static Map<String, Object> extract(AcceptingVisitor instance); static E populate(E instance, Map<String, Object> map); static E populate(
      E instance, Map<String, Object> map, Function<String, Object> nameToClass); static String toJson(AcceptingVisitor composite, ClassNameMapper classNameMapper); static String toJson(AcceptingVisitor composite, Function<Object, String> classToName);  }
@Test public void testFromMapAttrWithInvalidValue() { class Clazz extends AttrComposite { AttrBoolean attrBoolean = attributes.register("attrBoolean", AttrBoolean.builder().defaultValue(null)); AttrInteger attrInteger = attributes.register("attrInteger", AttrInteger.builder().defaultValue(null)); AttrDouble attrDouble = attributes.register("attrDouble", AttrDouble.builder().defaultValue(null)); AttrString attrString = attributes.register("attrString", AttrString.builder().defaultValue(null)); AttrEnum<EnumClazz> attrEnum = attributes.register("attrEnum", AttrEnum.builder(EnumClazz.class).defaultValue(null)); AttrObject<Clazz> attrObject = attributes.register( "attrObject", AttrObject.builder(Clazz.class).defaultValue(null, () -> new Clazz())); AttrObjectArray<Clazz> attrObjectArray = attributes.register( "attrObjectArray", AttrObjectArray.builder(Clazz.class, () -> new Clazz()).defaultValue(null)); } AliasMapper mapper = new AliasMapper(); mapper.alias("clazz", Clazz.class, () -> new Clazz()); Assertions.assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy( () -> { Map<String, Object> map = Collections.singletonMap("extraKey", ""); Attrs.populate(new Clazz(), map, mapper::fromName); }); Assertions.assertThatExceptionOfType(IllegalArgumentException.class) .isThrownBy( () -> { Map<String, Object> map = Collections.singletonMap( "attrObject", Collections.singletonMap("extraKey", "invalid-value")); Attrs.populate(new Clazz(), map, mapper::fromName); }); for (Object value : Arrays.asList(true, false, null)) { checkValueLegal(mapper, new Clazz(), "attrBoolean", value); } for (Object value : Arrays.asList(10, "true", 10d, new Object[0], new ArrayList<>())) { checkValueIllegal(mapper, new Clazz(), "attrBoolean", (c) -> c.attrBoolean.get(), value); } for (Object value : Arrays.asList(10, 10f, 10d, null)) { checkValueLegal(mapper, new Clazz(), "attrInteger", value); } for (Object value : Arrays.asList( true, "true", 10.1f, 10.1d, Long.MAX_VALUE, Double.NaN, new Object[0], new ArrayList<>())) { checkValueIllegal(mapper, new Clazz(), "attrInteger", (c) -> c.attrInteger.get(), value); } for (Object value : Arrays.asList(10, 10f, 10d, null, Double.NaN, Double.MAX_VALUE)) { checkValueLegal(mapper, new Clazz(), "attrDouble", value); } for (Object value : Arrays.asList(true, "true", new Object[0], new ArrayList<>())) { checkValueIllegal(mapper, new Clazz(), "attrDouble", (c) -> c.attrDouble.get(), value); } for (Object value : Arrays.asList(null, "abc", "")) { checkValueLegal(mapper, new Clazz(), "attrString", value); } for (Object value : Arrays.asList(true, 10, 10d, new Object[0], new ArrayList<>())) { checkValueIllegal(mapper, new Clazz(), "attrString", (c) -> c.attrString.get(), value); } for (Object value : Arrays.asList(null, EnumClazz.FOO, EnumClazz.FOO.name())) { checkValueLegal(mapper, new Clazz(), "attrEnum", value); } for (Object value : Arrays.asList(true, 10, 10d, "NONVALUE", new Object[0], new ArrayList<>())) { checkValueIllegal(mapper, new Clazz(), "attrEnum", (c) -> c.attrEnum.get(), value); } for (Object value : Arrays.asList(null, new HashMap<>())) { checkValueLegal(mapper, new Clazz(), "attrObject", value); } for (Object value : Arrays.asList( true, 10, 10d, "NONVALUE", Collections.singletonMap("attrInteger", "invalid-value"), new Object(), new Object[0], new ArrayList<>())) { checkValueIllegal(mapper, new Clazz(), "attrObject", (c) -> c.attrObject.get(), value); } for (Object value : Arrays.asList( null, new ArrayList<>(), new Object[] {Collections.emptyMap(), Collections.singletonMap("attrString", "foo")})) { checkValueLegal(mapper, new Clazz(), "attrObjectArray", value); } for (Object value : Arrays.asList(true, 10, 10d, new Object(), new Object[] {"invalid-value"})) { checkValueIllegal( mapper, new Clazz(), "attrObjectArray", (c) -> c.attrObjectArray.get(), value); } }