package org.javersion.object; import static org.assertj.core.api.Assertions.assertThat; import static org.javersion.path.PropertyPath.ROOT; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import org.javersion.core.Persistent; import org.javersion.object.types.MapType; import org.javersion.object.types.SetType; import org.javersion.path.PropertyPath; import org.javersion.reflect.Param; import org.junit.Test; import com.fasterxml.jackson.annotation.JsonCreator; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.reflect.TypeToken; public class DelegateTest { static class Wrapper<T> { final T value; public Wrapper(T value) { this.value = value; } @VersionValue public T value() { return value; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Wrapper that = (Wrapper) o; return value.equals(that.value); } @Override public int hashCode() { return value.hashCode(); } } static class Container<T> { Set<T> set = new HashSet<>(); public Container(T... values) { this(ImmutableSet.copyOf(values)); } public Container(Set<T> set) { this.set = set; } @VersionCreator public static <T> Container<T> toContainer(Set<T> set) { return new Container<>(set); } @VersionValue Set<T> toSet() { return set; } } @Versionable(alias = "Int") static class Int { @Id final int id; @VersionCreator public Int(@Param("id") int id) { this.id = id; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Int that = (Int) o; return id == that.id; } @Override public int hashCode() { return id; } } @Versionable static class SetKeyObject { final String value; @VersionCreator public SetKeyObject(String value) { this.value = value; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; SetKeyObject that = (SetKeyObject) o; return value.equals(that.value); } @Override public int hashCode() { return value.hashCode(); } } static class SetKeyContainer { private Set<SetKeyObject> set; public SetKeyContainer(Set<SetKeyObject> set) { this.set = set; } @SetKey("value") @VersionValue public Set<SetKeyObject> asSet() { return set; } } static class BadDelegate1 { // No matching constructor public BadDelegate1() {} @Override @VersionValue public String toString() { return super.toString(); } } static class BadDelegate2 { // Two version values @Override @VersionValue public String toString() { return super.toString(); } @VersionValue public String value() { return toString(); } } static class BadDelegate3 { @VersionCreator public BadDelegate3(String value) {} @VersionCreator public static BadDelegate3 valueOf(String value) { return null; } @Override @VersionValue public String toString() { return super.toString(); } } static class BadDelegate8 { @VersionCreator public static BadDelegate8 of(String value) { return null; } @VersionCreator public static BadDelegate8 valueOf(String value) { return null; } @Override @VersionValue public String toString() { return super.toString(); } } static class BadDelegate4 { @VersionValue public static int value() { return 0; } } static abstract class BadDelegate5 { @VersionValue public abstract int value(); } static abstract class BadDelegate6 { @VersionValue public int value(String parameter) { return 0; } } static abstract class BadDelegate7 { @VersionValue public void value() { } } static abstract class BadDelegate9 { @VersionCreator public static BadDelegate9 of(int value) { return null; } @VersionValue @Override public String toString() { return super.toString(); } } static abstract class BadDelegate10 { @VersionCreator public static BadDelegate9 of(String value) { return null; } @VersionValue @Override public String toString() { return super.toString(); } } static abstract class BadDelegate11 { @VersionCreator public BadDelegate11 of(String value) { return null; } @VersionValue @Override public String toString() { return super.toString(); } } @Versionable static class VersionAnnotationOverridesJson { private final String value; VersionAnnotationOverridesJson(String value) { this.value = value; } @VersionCreator public static VersionAnnotationOverridesJson fromValue(String value) { return new VersionAnnotationOverridesJson(value); } @JsonCreator public static VersionAnnotationOverridesJson fromJson(int value) { throw new UnsupportedOperationException(); } } @Test public void read_write_string_wrapper() { ObjectSerializer<Wrapper<String>> serializer = new ObjectSerializer<>(new TypeToken<Wrapper<String>>() {}); Map<PropertyPath, Object> properties = serializer.toPropertyMap(new Wrapper<>("foobar")); assertThat(properties).isEqualTo(ImmutableMap.of(ROOT, "foobar")); Wrapper wrapper = serializer.fromPropertyMap(properties); assertThat(wrapper.value()).isEqualTo("foobar"); } @Test public void string_wrapper_component() { ObjectSerializer<Container<Wrapper<String>>> serializer = new ObjectSerializer<>(new TypeToken<Container<Wrapper<String>>>() {}); Container<Wrapper<String>> container = new Container<>(new Wrapper<>("foo")); Map<PropertyPath, Object> properties = serializer.toPropertyMap(container); assertThat(properties).isEqualTo(ImmutableMap.of( ROOT, SetType.CONSTANT, ROOT.key("foo"), "foo")); container = serializer.fromPropertyMap(properties); assertThat(container.set).isEqualTo(ImmutableSet.of(new Wrapper<>("foo"))); } @Test public void string_wrapper_identifiable_component() { ObjectSerializer<Container<Wrapper<Int>>> serializer = new ObjectSerializer<>(new TypeToken<Container<Wrapper<Int>>>() {}); Wrapper<Int> wrapper = new Wrapper<>(new Int(123)); Container<Wrapper<Int>> container = new Container<>(wrapper); Map<PropertyPath, Object> properties = serializer.toPropertyMap(container); assertThat(properties).isEqualTo(ImmutableMap.of( ROOT, SetType.CONSTANT, ROOT.index(123), Persistent.object("Int"), ROOT.index(123).property("id"), 123l)); container = serializer.fromPropertyMap(properties); assertThat(container.set).isEqualTo(ImmutableSet.of(wrapper)); } @Test public void string_wrapper_scalar() { ObjectSerializer<Map<Wrapper<String>, Wrapper<String>>> serializer = new ObjectSerializer<>(new TypeToken<Map<Wrapper<String>, Wrapper<String>>>() {}); Map<Wrapper<String>, Wrapper<String>> map = new HashMap<>(); map.put(new Wrapper<>("foo"), new Wrapper<>("bar")); Map<PropertyPath, Object> properties = serializer.toPropertyMap(map); assertThat(properties).isEqualTo(ImmutableMap.of( ROOT, MapType.CONSTANT, ROOT.key("foo"), "bar")); Map<Wrapper<String>, Wrapper<String>> result = serializer.fromPropertyMap(properties); assertThat(result).isEqualTo(map); } @Test public void set_delegate_with_SetKey() { ObjectSerializer<SetKeyContainer> serializer = new ObjectSerializer<>(SetKeyContainer.class); SetKeyContainer container = new SetKeyContainer(ImmutableSet.of(new SetKeyObject("foobar"))); Map<PropertyPath, Object> properties = serializer.toPropertyMap(container); container = serializer.fromPropertyMap(properties); assertThat(container.set).isEqualTo(ImmutableSet.of(new SetKeyObject("foobar"))); } @Test public void version_annotation_overrides_json() { ObjectSerializer<VersionAnnotationOverridesJson> serializer = new ObjectSerializer<>(VersionAnnotationOverridesJson.class); Map<PropertyPath, Object> properties = serializer.toPropertyMap(new VersionAnnotationOverridesJson("Javersion")); VersionAnnotationOverridesJson object = serializer.fromPropertyMap(properties); assertThat(object.value).isEqualTo("Javersion"); } @Test(expected = IllegalArgumentException.class) public void no_matching_creator() { new ObjectSerializer<>(BadDelegate1.class); } @Test(expected = IllegalArgumentException.class) public void two_version_value_annotations() { new ObjectSerializer<>(BadDelegate2.class); } @Test(expected = IllegalArgumentException.class) public void two_version_creators() { new ObjectSerializer<>(BadDelegate3.class); } @Test(expected = IllegalArgumentException.class) public void two_version_creator_methods() { new ObjectSerializer<>(BadDelegate8.class); } @Test(expected = IllegalArgumentException.class) public void static_value_method_not_allowed() { new ObjectSerializer<>(BadDelegate4.class); } @Test(expected = IllegalArgumentException.class) public void abstract_value_method_not_allowed() { new ObjectSerializer<>(BadDelegate5.class); } @Test(expected = IllegalArgumentException.class) public void value_method_parameters_not_allowed() { new ObjectSerializer<>(BadDelegate6.class); } @Test(expected = IllegalArgumentException.class) public void value_method_must_not_be_void() { new ObjectSerializer<>(BadDelegate7.class); } @Test(expected = IllegalArgumentException.class) public void bad_creator_method_parameter_type() { new ObjectSerializer<>(BadDelegate9.class); } @Test(expected = IllegalArgumentException.class) public void bad_creator_method_return_type() { new ObjectSerializer<>(BadDelegate10.class); } @Test(expected = IllegalArgumentException.class) public void creator_method_should_not_be_static() { new ObjectSerializer<>(BadDelegate11.class); } }