diff --git a/mvvmfx/src/main/java/de/saxsys/mvvmfx/utils/mapping/BeanMapPropertyField.java b/mvvmfx/src/main/java/de/saxsys/mvvmfx/utils/mapping/BeanMapPropertyField.java
new file mode 100644
index 000000000..c29fe98d1
--- /dev/null
+++ b/mvvmfx/src/main/java/de/saxsys/mvvmfx/utils/mapping/BeanMapPropertyField.java
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * Copyright 2018 Manuel Mauky
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+package de.saxsys.mvvmfx.utils.mapping;
+
+import de.saxsys.mvvmfx.internal.SideEffect;
+import de.saxsys.mvvmfx.utils.mapping.accessorfunctions.MapGetter;
+import de.saxsys.mvvmfx.utils.mapping.accessorfunctions.MapSetter;
+import javafx.beans.property.MapProperty;
+import javafx.beans.property.Property;
+import javafx.collections.FXCollections;
+import javafx.collections.MapChangeListener;
+import javafx.collections.ObservableMap;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.function.Supplier;
+
+/**
+ * An implementation of {@link PropertyField} that is used when the field of the model class is a {@link Map} and is
+ * not a JavaFX {@link javafx.beans.property.MapProperty} but is following the old Java-Beans standard, i.e.
+ * there is getter and setter method for the field.
+ *
+ * @param the type of the key.
+ * @param the type of the value.
+ */
+class BeanMapPropertyField, R extends Property>
+ implements PropertyField {
+
+ private final MapGetter getter;
+
+ private final MapSetter setter;
+
+ private Map defaultValue;
+
+ private final MapProperty targetProperty;
+
+ BeanMapPropertyField(SideEffect updateFunction, MapGetter getter, MapSetter setter,
+ Supplier> propertySupplier) {
+ this(updateFunction, getter, setter, propertySupplier, Collections.emptyMap());
+ }
+
+ BeanMapPropertyField(SideEffect updateFunction, MapGetter getter, MapSetter setter,
+ Supplier> propertySupplier,
+ Map defaultValue) {
+ this.defaultValue = defaultValue;
+ this.getter = getter;
+ this.setter = setter;
+ this.targetProperty = propertySupplier.get();
+ this.targetProperty.setValue(FXCollections.observableMap(new HashMap<>()));
+ this.targetProperty.addListener((MapChangeListener) change -> updateFunction.call());
+ }
+
+ static void setAll(Map target, Map newValues) {
+ target.keySet().retainAll(newValues.keySet());
+ target.putAll(newValues);
+ }
+
+ @Override
+ public void commit(M wrappedObject) {
+ setter.accept(wrappedObject, targetProperty.getValue());
+ }
+
+ @Override
+ public void reload(M wrappedObject) {
+ setAll(targetProperty, getter.apply(wrappedObject));
+ }
+
+ @Override
+ public void resetToDefault() {
+
+ targetProperty.get().clear();
+ setAll(targetProperty, defaultValue);
+ }
+
+ @Override
+ public void updateDefault(M wrappedObject) {
+ defaultValue = new HashMap<>(getter.apply(wrappedObject));
+ }
+
+ @Override
+ public R getProperty() {
+ return (R) targetProperty;
+ }
+
+ @Override
+ public boolean isDifferent(M wrappedObject) {
+ final Map modelValue = getter.apply(wrappedObject);
+ final Map wrapperValue = targetProperty;
+
+ return !Objects.equals(modelValue, wrapperValue);
+ }
+
+}
\ No newline at end of file
diff --git a/mvvmfx/src/main/java/de/saxsys/mvvmfx/utils/mapping/FxMapPropertyField.java b/mvvmfx/src/main/java/de/saxsys/mvvmfx/utils/mapping/FxMapPropertyField.java
new file mode 100644
index 000000000..78100e4d4
--- /dev/null
+++ b/mvvmfx/src/main/java/de/saxsys/mvvmfx/utils/mapping/FxMapPropertyField.java
@@ -0,0 +1,89 @@
+package de.saxsys.mvvmfx.utils.mapping;
+
+import de.saxsys.mvvmfx.internal.SideEffect;
+import de.saxsys.mvvmfx.utils.mapping.accessorfunctions.MapPropertyAccessor;
+import javafx.beans.property.MapProperty;
+import javafx.beans.property.Property;
+import javafx.collections.FXCollections;
+import javafx.collections.MapChangeListener;
+import javafx.collections.ObservableMap;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.function.Supplier;
+
+import static de.saxsys.mvvmfx.utils.mapping.BeanMapPropertyField.setAll;
+
+/**
+ * An implementation of {@link PropertyField} that is used when the field of the model class is a {@link Map} and will
+ * be mapped to a JavaFX {@link MapProperty}.
+ *
+ * @param the type of the key elements.
+ * @param the type of the value elements.
+ */
+class FxMapPropertyField, R extends Property>
+ implements PropertyField {
+
+ private Map defaultValue;
+
+ private final MapPropertyAccessor accessor;
+
+ private final MapProperty targetProperty;
+
+ FxMapPropertyField(
+ SideEffect updateFunction, MapPropertyAccessor accessor,
+ Supplier> propertySupplier) {
+ this(updateFunction, accessor, propertySupplier, Collections.emptyMap());
+ }
+
+ FxMapPropertyField(SideEffect updateFunction, MapPropertyAccessor accessor,
+ Supplier> propertySupplier,
+ Map defaultValue) {
+ this.accessor = accessor;
+ this.defaultValue = defaultValue;
+ this.targetProperty = propertySupplier.get();
+
+ this.targetProperty.setValue(FXCollections.observableMap(new HashMap<>()));
+ this.targetProperty.addListener((MapChangeListener) change -> updateFunction.call());
+ }
+
+ @Override
+ public void commit(M wrappedObject) {
+ setAll(accessor.apply(wrappedObject), targetProperty.getValue());
+ }
+
+ @Override
+ public void reload(M wrappedObject) {
+ setAll(targetProperty, accessor.apply(wrappedObject).getValue());
+ }
+
+ @Override
+ public void resetToDefault() {
+ try {
+ targetProperty.get().clear();
+ setAll(targetProperty, defaultValue);
+ } catch (Exception e) {
+ System.out.println(e);
+ }
+ }
+
+ @Override
+ public void updateDefault(M wrappedObject) {
+ defaultValue = new HashMap<>(accessor.apply(wrappedObject).getValue());
+ }
+
+ @Override
+ public R getProperty() {
+ return (R) targetProperty;
+ }
+
+ @Override
+ public boolean isDifferent(M wrappedObject) {
+ final Map modelValue = accessor.apply(wrappedObject).getValue();
+ final Map wrapperValue = targetProperty;
+
+ return !Objects.equals(modelValue, wrapperValue);
+ }
+}
\ No newline at end of file
diff --git a/mvvmfx/src/main/java/de/saxsys/mvvmfx/utils/mapping/ImmutableMapPropertyField.java b/mvvmfx/src/main/java/de/saxsys/mvvmfx/utils/mapping/ImmutableMapPropertyField.java
new file mode 100644
index 000000000..f3136b2f6
--- /dev/null
+++ b/mvvmfx/src/main/java/de/saxsys/mvvmfx/utils/mapping/ImmutableMapPropertyField.java
@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * Copyright 2018 Manuel Mauky
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+package de.saxsys.mvvmfx.utils.mapping;
+
+import de.saxsys.mvvmfx.internal.SideEffect;
+import de.saxsys.mvvmfx.utils.mapping.accessorfunctions.MapGetter;
+import de.saxsys.mvvmfx.utils.mapping.accessorfunctions.MapImmutableSetter;
+import javafx.beans.property.MapProperty;
+import javafx.beans.property.Property;
+import javafx.collections.FXCollections;
+import javafx.collections.MapChangeListener;
+import javafx.collections.ObservableMap;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.function.Supplier;
+
+import static de.saxsys.mvvmfx.utils.mapping.BeanMapPropertyField.setAll;
+
+class ImmutableMapPropertyField, R extends Property>
+ implements ImmutablePropertyField {
+
+ private final MapGetter getter;
+
+ private final MapImmutableSetter immutableSetter;
+
+ private Map defaultValue;
+
+ private final MapProperty targetProperty;
+
+ ImmutableMapPropertyField(
+ SideEffect updateFunction,
+ MapGetter getter, MapImmutableSetter immutableSetter,
+ Supplier> propertySupplier) {
+ this(updateFunction, getter, immutableSetter, propertySupplier, Collections.emptyMap());
+ }
+
+ ImmutableMapPropertyField(SideEffect updateFunction,
+ MapGetter getter, MapImmutableSetter immutableSetter,
+ Supplier> propertySupplier, Map defaultValue) {
+ this.defaultValue = defaultValue;
+ this.getter = getter;
+ this.immutableSetter = immutableSetter;
+ this.targetProperty = propertySupplier.get();
+ this.targetProperty.setValue(FXCollections.observableMap(new HashMap<>()));
+ this.targetProperty.addListener((MapChangeListener) change -> updateFunction.call());
+ }
+
+ @Override
+ public void commit(M wrappedObject) {
+ // commit is not supported because the model instance is immutable.
+ }
+
+ @Override
+ public M commitImmutable(M wrappedObject) {
+ return immutableSetter.apply(wrappedObject, targetProperty.getValue());
+ }
+
+ @Override
+ public void reload(M wrappedObject) {
+ setAll(targetProperty, getter.apply(wrappedObject));
+ }
+
+ @Override
+ public void resetToDefault() {
+ setAll(targetProperty, defaultValue);
+ }
+
+ @Override
+ public void updateDefault(M wrappedObject) {
+ defaultValue = new HashMap<>(getter.apply(wrappedObject));
+ }
+
+ @Override
+ public R getProperty() {
+ return (R) targetProperty;
+ }
+
+ @Override
+ public boolean isDifferent(M wrappedObject) {
+ final Map modelValue = getter.apply(wrappedObject);
+ final Map wrappedValue = targetProperty;
+
+ return !Objects.equals(modelValue, wrappedValue);
+ }
+}
\ No newline at end of file
diff --git a/mvvmfx/src/main/java/de/saxsys/mvvmfx/utils/mapping/ModelWrapper.java b/mvvmfx/src/main/java/de/saxsys/mvvmfx/utils/mapping/ModelWrapper.java
index e6678fa8e..922b2ce09 100644
--- a/mvvmfx/src/main/java/de/saxsys/mvvmfx/utils/mapping/ModelWrapper.java
+++ b/mvvmfx/src/main/java/de/saxsys/mvvmfx/utils/mapping/ModelWrapper.java
@@ -39,6 +39,10 @@
import de.saxsys.mvvmfx.utils.mapping.accessorfunctions.LongImmutableSetter;
import de.saxsys.mvvmfx.utils.mapping.accessorfunctions.LongPropertyAccessor;
import de.saxsys.mvvmfx.utils.mapping.accessorfunctions.LongSetter;
+import de.saxsys.mvvmfx.utils.mapping.accessorfunctions.MapGetter;
+import de.saxsys.mvvmfx.utils.mapping.accessorfunctions.MapImmutableSetter;
+import de.saxsys.mvvmfx.utils.mapping.accessorfunctions.MapPropertyAccessor;
+import de.saxsys.mvvmfx.utils.mapping.accessorfunctions.MapSetter;
import de.saxsys.mvvmfx.utils.mapping.accessorfunctions.ObjectGetter;
import de.saxsys.mvvmfx.utils.mapping.accessorfunctions.ObjectImmutableSetter;
import de.saxsys.mvvmfx.utils.mapping.accessorfunctions.ObjectPropertyAccessor;
@@ -68,6 +72,7 @@
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ListProperty;
import javafx.beans.property.LongProperty;
+import javafx.beans.property.MapProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.Property;
import javafx.beans.property.ReadOnlyBooleanProperty;
@@ -79,6 +84,7 @@
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleListProperty;
import javafx.beans.property.SimpleLongProperty;
+import javafx.beans.property.SimpleMapProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleSetProperty;
import javafx.beans.property.SimpleStringProperty;
@@ -1556,4 +1562,91 @@ public SetProperty field(String identifier, SetPropertyAccessor acc
return addIdentified(identifier, new FxSetPropertyField<>(this::propertyWasChanged, accessor,
() -> new SimpleSetProperty<>(null, identifier), defaultValue));
}
+
+ /* Field type map */
+
+ public MapProperty field(MapGetter getter, MapSetter setter) {
+ return add(new BeanMapPropertyField<>(this::propertyWasChanged, getter,
+ (m, map) -> setter.accept(m, FXCollections.observableMap(map)), SimpleMapProperty::new));
+ }
+
+ public MapProperty immutableField(MapGetter getter,
+ MapImmutableSetter immutableSetter) {
+ return addImmutable(new ImmutableMapPropertyField<>(
+ this::propertyWasChanged,
+ getter,
+ (m, map) -> immutableSetter.apply(m, FXCollections.observableMap(map)),
+ SimpleMapProperty::new
+ ));
+ }
+
+ public MapProperty field(MapGetter getter, MapSetter setter,
+ Map defaultValue) {
+ return add(new BeanMapPropertyField<>(this::propertyWasChanged, getter,
+ (m, map) -> setter.accept(m, FXCollections.observableMap(map)), SimpleMapProperty::new,
+ defaultValue));
+ }
+
+ public MapProperty immutableField(MapGetter getter,
+ MapImmutableSetter immutableSetter, Map defaultValue) {
+ return addImmutable(new ImmutableMapPropertyField<>(
+ this::propertyWasChanged,
+ getter,
+ (m, map) -> immutableSetter.apply(m, FXCollections.observableMap(map)),
+ SimpleMapProperty::new,
+ defaultValue));
+ }
+
+ public MapProperty field(MapPropertyAccessor accessor) {
+ return add(new FxMapPropertyField<>(this::propertyWasChanged, accessor, SimpleMapProperty::new));
+ }
+
+ public MapProperty field(MapPropertyAccessor accessor, Map defaultValue) {
+ return add(
+ new FxMapPropertyField<>(this::propertyWasChanged, accessor, SimpleMapProperty::new, defaultValue));
+ }
+
+ public MapProperty field(String identifier, MapGetter getter, MapSetter setter) {
+ return addIdentified(identifier, new BeanMapPropertyField<>(this::propertyWasChanged, getter,
+ (m, map) -> setter.accept(m, FXCollections.observableMap(map)),
+ () -> new SimpleMapProperty<>(null, identifier)));
+ }
+
+ public MapProperty field(String identifier, MapGetter getter, MapSetter setter,
+ Map defaultValue) {
+ return addIdentified(identifier, new BeanMapPropertyField<>(this::propertyWasChanged, getter,
+ (m, map) -> setter.accept(m, FXCollections.observableMap(map)),
+ () -> new SimpleMapProperty<>(null, identifier), defaultValue));
+ }
+
+ public MapProperty immutableField(String identifier, MapGetter getter,
+ MapImmutableSetter immutableSetter) {
+ return addIdentifiedImmutable(identifier, new ImmutableMapPropertyField<>(
+ this::propertyWasChanged,
+ getter,
+ (m, map) -> immutableSetter.apply(m, FXCollections.observableMap(map)),
+ () -> new SimpleMapProperty<>(null, identifier)));
+ }
+
+ public MapProperty immutableField(String identifier, MapGetter getter,
+ MapImmutableSetter immutableSetter,
+ Map defaultValue) {
+ return addIdentifiedImmutable(identifier, new ImmutableMapPropertyField<>(
+ this::propertyWasChanged,
+ getter,
+ (m, map) -> immutableSetter.apply(m, FXCollections.observableMap(map)),
+ () -> new SimpleMapProperty<>(null, identifier),
+ defaultValue));
+ }
+
+ public MapProperty field(String identifier, MapPropertyAccessor accessor) {
+ return addIdentified(identifier, new FxMapPropertyField<>(this::propertyWasChanged, accessor,
+ () -> new SimpleMapProperty<>(null, identifier)));
+ }
+
+ public MapProperty field(String identifier, MapPropertyAccessor accessor,
+ Map defaultValue) {
+ return addIdentified(identifier, new FxMapPropertyField<>(this::propertyWasChanged, accessor,
+ () -> new SimpleMapProperty<>(null, identifier), defaultValue));
+ }
}
diff --git a/mvvmfx/src/main/java/de/saxsys/mvvmfx/utils/mapping/accessorfunctions/MapGetter.java b/mvvmfx/src/main/java/de/saxsys/mvvmfx/utils/mapping/accessorfunctions/MapGetter.java
new file mode 100644
index 000000000..2199c9c6e
--- /dev/null
+++ b/mvvmfx/src/main/java/de/saxsys/mvvmfx/utils/mapping/accessorfunctions/MapGetter.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright 2018 Manuel Mauky
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+package de.saxsys.mvvmfx.utils.mapping.accessorfunctions;
+
+import java.util.Map;
+import java.util.function.Function;
+
+/**
+ * A functional interface to define a getter method of a map type.
+ *
+ * @param the generic type of the model.
+ * @param the type of the key.
+ * @param the type of the value.
+ */
+@FunctionalInterface
+public interface MapGetter extends Function> {
+
+ /**
+ * @param model the model instance
+ *
+ * @return the value of the field
+ */
+ @Override
+ Map apply(M model);
+}
\ No newline at end of file
diff --git a/mvvmfx/src/main/java/de/saxsys/mvvmfx/utils/mapping/accessorfunctions/MapImmutableSetter.java b/mvvmfx/src/main/java/de/saxsys/mvvmfx/utils/mapping/accessorfunctions/MapImmutableSetter.java
new file mode 100644
index 000000000..ff7c8909d
--- /dev/null
+++ b/mvvmfx/src/main/java/de/saxsys/mvvmfx/utils/mapping/accessorfunctions/MapImmutableSetter.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright 2018 Manuel Mauky
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+package de.saxsys.mvvmfx.utils.mapping.accessorfunctions;
+
+import java.util.Map;
+import java.util.function.BiFunction;
+
+/**
+ * A functional interface to define an immutable "setter" method of type {@link Map}. As the model element is immutable
+ * this method is not a real "setter". Instead it returns a new immutable copy of the original model element that has
+ * the specified field updated to the new value.
+ *
+ * @param the generic type of the model.
+ */
+@FunctionalInterface
+public interface MapImmutableSetter extends BiFunction, M> {
+
+ /**
+ * @param model the model instance
+ * @param newElements the new elements of this map field.
+ *
+ * @return a new model instance with the new values
+ */
+ @Override
+ M apply(M model, Map newElements);
+}
\ No newline at end of file
diff --git a/mvvmfx/src/main/java/de/saxsys/mvvmfx/utils/mapping/accessorfunctions/MapPropertyAccessor.java b/mvvmfx/src/main/java/de/saxsys/mvvmfx/utils/mapping/accessorfunctions/MapPropertyAccessor.java
new file mode 100644
index 000000000..cba684d9a
--- /dev/null
+++ b/mvvmfx/src/main/java/de/saxsys/mvvmfx/utils/mapping/accessorfunctions/MapPropertyAccessor.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright 2018 Manuel Mauky
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+package de.saxsys.mvvmfx.utils.mapping.accessorfunctions;
+
+import javafx.beans.property.MapProperty;
+
+import java.util.function.Function;
+
+/**
+ * A functional interface to define an accessor method for a property of a map type.
+ *
+ * @param the generic type of the model.
+ * @param the type of the key elements
+ * @param the type of the value elements
+ */
+@FunctionalInterface
+public interface MapPropertyAccessor extends Function> {
+
+ /**
+ * @param model the model instance
+ *
+ * @return the property field of the model
+ */
+ @Override
+ MapProperty apply(M model);
+}
\ No newline at end of file
diff --git a/mvvmfx/src/main/java/de/saxsys/mvvmfx/utils/mapping/accessorfunctions/MapSetter.java b/mvvmfx/src/main/java/de/saxsys/mvvmfx/utils/mapping/accessorfunctions/MapSetter.java
new file mode 100644
index 000000000..1346233f0
--- /dev/null
+++ b/mvvmfx/src/main/java/de/saxsys/mvvmfx/utils/mapping/accessorfunctions/MapSetter.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright 2018 Manuel Mauky
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ ******************************************************************************/
+package de.saxsys.mvvmfx.utils.mapping.accessorfunctions;
+
+import java.util.Map;
+import java.util.function.BiConsumer;
+
+/**
+ * A functional interface to define a getter method of a map type.
+ *
+ * @param the generic type of the model.
+ * @param the type of the key.
+ * @param the type of the value.
+ */
+@FunctionalInterface
+public interface MapSetter extends BiConsumer> {
+
+ /**
+ * @param model the model instance
+ *
+ * @return the value of the field
+ */
+ @Override
+ void accept(M model, Map value);
+}
\ No newline at end of file
diff --git a/mvvmfx/src/test/java/de/saxsys/mvvmfx/utils/mapping/ExampleModel.java b/mvvmfx/src/test/java/de/saxsys/mvvmfx/utils/mapping/ExampleModel.java
index 99475d47b..c3d84cb8c 100644
--- a/mvvmfx/src/test/java/de/saxsys/mvvmfx/utils/mapping/ExampleModel.java
+++ b/mvvmfx/src/test/java/de/saxsys/mvvmfx/utils/mapping/ExampleModel.java
@@ -16,6 +16,7 @@
package de.saxsys.mvvmfx.utils.mapping;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import javafx.beans.property.BooleanProperty;
@@ -24,6 +25,7 @@
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ListProperty;
import javafx.beans.property.LongProperty;
+import javafx.beans.property.MapProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SetProperty;
import javafx.beans.property.SimpleBooleanProperty;
@@ -32,6 +34,7 @@
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleListProperty;
import javafx.beans.property.SimpleLongProperty;
+import javafx.beans.property.SimpleMapProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleSetProperty;
import javafx.beans.property.SimpleStringProperty;
@@ -54,6 +57,7 @@ public class ExampleModel {
private SetProperty setProperty = new SimpleSetProperty<>();
+ private MapProperty mapProperty = new SimpleMapProperty<>();
public int getInteger() {
return integerProperty.get();
@@ -163,4 +167,17 @@ public void setSet(Set set) {
this.setProperty.retainAll(set);
this.setProperty.addAll(set);
}
+
+ public Map getMap() {
+ return mapProperty.get();
+ }
+
+ public MapProperty mapProperty() {
+ return mapProperty;
+ }
+
+ public void setMap(Map map) {
+ this.mapProperty.get().clear();
+ this.mapProperty.get().putAll(map);
+ }
}
diff --git a/mvvmfx/src/test/java/de/saxsys/mvvmfx/utils/mapping/FieldMethodOverloadingTest.java b/mvvmfx/src/test/java/de/saxsys/mvvmfx/utils/mapping/FieldMethodOverloadingTest.java
index 9e8531ac6..61da6cb39 100644
--- a/mvvmfx/src/test/java/de/saxsys/mvvmfx/utils/mapping/FieldMethodOverloadingTest.java
+++ b/mvvmfx/src/test/java/de/saxsys/mvvmfx/utils/mapping/FieldMethodOverloadingTest.java
@@ -21,6 +21,7 @@
import java.util.Collection;
import java.util.Collections;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import org.junit.jupiter.api.BeforeEach;
@@ -34,6 +35,7 @@
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ListProperty;
import javafx.beans.property.LongProperty;
+import javafx.beans.property.MapProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.Property;
import javafx.beans.property.SetProperty;
@@ -281,7 +283,7 @@ public void listProperty() {
}
@Test
- public void lsetProperty() {
+ public void setProperty() {
Set defaultValue = Collections.emptySet();
final SetProperty beanField = wrapper.field(ExampleModel::getSet, ExampleModel::setSet);
final SetProperty fxField = wrapper.field(ExampleModel::setProperty);
@@ -309,6 +311,38 @@ public void lsetProperty() {
verifyDefaultValues(idFxFieldDefault, defaultValue, alternativeValue);
}
+ @Test
+ public void mapProperty() {
+ Map defaultValue = Collections.emptyMap();
+ final MapProperty beanField = wrapper.field(ExampleModel::getMap, ExampleModel::setMap);
+ final MapProperty fxField = wrapper.field(ExampleModel::mapProperty);
+ final MapProperty beanFieldDefault = wrapper.field(ExampleModel::getMap, ExampleModel::setMap,
+ defaultValue);
+ final MapProperty fxFieldDefault = wrapper.field(ExampleModel::mapProperty, defaultValue);
+
+ final MapProperty idBeanField = wrapper
+ .field("idBeanField", ExampleModel::getMap, ExampleModel::setMap);
+ final MapProperty idFxField = wrapper.field("idFxField", ExampleModel::mapProperty);
+ final MapProperty idBeanFieldDefault = wrapper.field("idBeanFieldDefault",
+ ExampleModel::getMap,
+ ExampleModel::setMap, defaultValue);
+ final MapProperty idFxFieldDefault = wrapper
+ .field("idFxFieldDefault", ExampleModel::mapProperty,
+ defaultValue);
+
+ // for listProperty we can't use the other "verify" method because of type mismatch.
+ verifyId(idBeanField, "idBeanField");
+ verifyId(idFxField, "idFxField");
+ verifyId(idBeanFieldDefault, "idBeanFieldDefault");
+ verifyId(idFxFieldDefault, "idFxFieldDefault");
+
+ Map alternativeValue = Collections.singletonMap("1", "2");
+ verifyDefaultValues(beanFieldDefault, defaultValue, alternativeValue);
+ verifyDefaultValues(fxFieldDefault, defaultValue, alternativeValue);
+ verifyDefaultValues(idBeanFieldDefault, defaultValue, alternativeValue);
+ verifyDefaultValues(idFxFieldDefault, defaultValue, alternativeValue);
+ }
+
private void verifyDefaultValues(Collection property, Collection defaultValue, Collection otherValue) {
property.addAll(otherValue);
@@ -318,4 +352,16 @@ private void verifyDefaultValues(Collection property, Collection defau
wrapper.reset();
assertThat(property).containsAll(defaultValue);
}
+
+ private void verifyDefaultValues(Map property, Map defaultValue, Map otherValue) {
+
+ property.putAll(otherValue);
+
+ wrapper.commit();
+ assertThat(property.entrySet()).containsExactlyElementsOf(otherValue.entrySet());
+
+ wrapper.reset();
+ assertThat(property.entrySet()).containsExactlyElementsOf(defaultValue.entrySet());
+ }
}
diff --git a/mvvmfx/src/test/java/de/saxsys/mvvmfx/utils/mapping/ModelWrapperTest.java b/mvvmfx/src/test/java/de/saxsys/mvvmfx/utils/mapping/ModelWrapperTest.java
index 6d22d083d..b3fadd2ce 100644
--- a/mvvmfx/src/test/java/de/saxsys/mvvmfx/utils/mapping/ModelWrapperTest.java
+++ b/mvvmfx/src/test/java/de/saxsys/mvvmfx/utils/mapping/ModelWrapperTest.java
@@ -20,12 +20,19 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
+import de.saxsys.mvvmfx.utils.mapping.accessorfunctions.SetPropertyAccessor;
+import javafx.beans.property.MapProperty;
import javafx.collections.ObservableList;
+import javafx.collections.ObservableMap;
import javafx.collections.ObservableSet;
+
+import org.assertj.core.data.MapEntry;
import org.junit.jupiter.api.Test;
import javafx.beans.property.IntegerProperty;
@@ -45,6 +52,7 @@ public void testCopyValuesTo() {
personA.setAge(32);
personA.setNicknames(Collections.singletonList("captain"));
personA.setEmailAddresses(Collections.singleton("test@example.org"));
+ personA.setPhoneNumbers(Collections.singletonMap("private", "0351 1234567"));
ModelWrapper personWrapper = new ModelWrapper<>(personA);
@@ -52,11 +60,15 @@ public void testCopyValuesTo() {
final IntegerProperty ageProperty = personWrapper.field(Person::getAge, Person::setAge);
final ListProperty nicknamesProperty = personWrapper.field(Person::getNicknames, Person::setNicknames);
final SetProperty emailAddressesProperty = personWrapper.field(Person::getEmailAddresses, Person::setEmailAddresses);
+ final MapProperty phoneNumbersProperty = personWrapper.field(Person::getPhoneNumbers,
+ Person::setPhoneNumbers);
+
assertThat(nameProperty.getValue()).isEqualTo("horst");
assertThat(ageProperty.getValue()).isEqualTo(32);
assertThat(nicknamesProperty.getValue()).containsOnly("captain");
assertThat(emailAddressesProperty.getValue()).containsOnly("test@example.org");
+ assertThat(phoneNumbersProperty.getValue()).containsOnly(MapEntry.entry("private", "0351 1234567"));
// when
Person personB = new Person();
@@ -64,6 +76,7 @@ public void testCopyValuesTo() {
personB.setAge(23);
personB.setNicknames(Collections.singletonList("lui"));
personB.setEmailAddresses(Collections.singleton("luise@example.org"));
+ personB.setPhoneNumbers(Collections.singletonMap("private", "03581 7654321"));
personWrapper.copyValuesTo(personB);
@@ -73,19 +86,21 @@ public void testCopyValuesTo() {
assertThat(personB.getAge()).isEqualTo(32);
assertThat(personB.getNicknames()).containsExactly("captain");
assertThat(personB.getEmailAddresses()).containsExactly("test@example.org");
+ assertThat(personB.getPhoneNumbers()).containsExactly(MapEntry.entry("private", "0351 1234567"));
// the properties have still the old values
assertThat(nameProperty.getValue()).isEqualTo("horst");
assertThat(ageProperty.getValue()).isEqualTo(32);
assertThat(nicknamesProperty.getValue()).containsOnly("captain");
assertThat(emailAddressesProperty.getValue()).containsOnly("test@example.org");
+ assertThat(phoneNumbersProperty.getValue()).containsOnly(MapEntry.entry("private", "0351 1234567"));
// and of cause the old person a has it's old values too
assertThat(personA.getName()).isEqualTo("horst");
assertThat(personA.getAge()).isEqualTo(32);
assertThat(personA.getNicknames()).containsExactly("captain");
assertThat(personA.getEmailAddresses()).containsExactly("test@example.org");
-
+ assertThat(personA.getPhoneNumbers()).containsExactly(MapEntry.entry("private", "0351 1234567"));
}
@Test
@@ -93,8 +108,9 @@ public void testWithGetterAndSetter() {
Person person = new Person();
person.setName("horst");
person.setAge(32);
- person.setNicknames(Arrays.asList("captain"));
+ person.setNicknames(Collections.singletonList("captain"));
person.setEmailAddresses(Collections.singleton("test@example.org"));
+ person.setPhoneNumbers(Collections.singletonMap("private", "0351 1234567"));
ModelWrapper personWrapper = new ModelWrapper<>(person);
@@ -102,22 +118,27 @@ public void testWithGetterAndSetter() {
final IntegerProperty ageProperty = personWrapper.field(Person::getAge, Person::setAge);
final ListProperty nicknamesProperty = personWrapper.field(Person::getNicknames, Person::setNicknames);
final SetProperty emailAddressesProperty = personWrapper.field(Person::getEmailAddresses, Person::setEmailAddresses);
+ final MapProperty phoneNumbersProperty = personWrapper.field(Person::getPhoneNumbers,
+ Person::setPhoneNumbers);
assertThat(nameProperty.getValue()).isEqualTo("horst");
assertThat(ageProperty.getValue()).isEqualTo(32);
assertThat(nicknamesProperty.getValue()).containsOnly("captain");
assertThat(emailAddressesProperty.getValue()).containsOnly("test@example.org");
+ assertThat(phoneNumbersProperty.getValue()).containsOnly(MapEntry.entry("private", "0351 1234567"));
nameProperty.setValue("hugo");
ageProperty.setValue(33);
nicknamesProperty.add("player");
emailAddressesProperty.add("test2@example.org");
+ phoneNumbersProperty.putIfAbsent("mobile", "0123 4567890");
// still the old values
assertThat(person.getName()).isEqualTo("horst");
assertThat(person.getAge()).isEqualTo(32);
assertThat(person.getNicknames()).containsOnly("captain");
assertThat(person.getEmailAddresses()).containsOnly("test@example.org");
+ assertThat(person.getPhoneNumbers()).containsOnly(MapEntry.entry("private", "0351 1234567"));
personWrapper.commit();
@@ -126,11 +147,15 @@ public void testWithGetterAndSetter() {
assertThat(person.getAge()).isEqualTo(33);
assertThat(person.getNicknames()).containsOnly("captain", "player");
assertThat(person.getEmailAddresses()).containsOnly("test@example.org", "test2@example.org");
+ assertThat(person.getPhoneNumbers()).containsOnly(
+ MapEntry.entry("private", "0351 1234567"),
+ MapEntry.entry("mobile", "0123 4567890"));
nameProperty.setValue("luise");
ageProperty.setValue(15);
nicknamesProperty.setValue(FXCollections.observableArrayList("student"));
emailAddressesProperty.setValue(FXCollections.observableSet("luise@example.org"));
+ phoneNumbersProperty.setValue(observableMap("mobile", "0124 9876543"));
personWrapper.reset();
@@ -138,12 +163,16 @@ public void testWithGetterAndSetter() {
assertThat(ageProperty.getValue()).isEqualTo(0);
assertThat(nicknamesProperty.getValue()).isEmpty();
assertThat(emailAddressesProperty.getValue()).isEmpty();
+ assertThat(phoneNumbersProperty.getValue()).isEmpty();
// the wrapped object has still the values from the last commit.
assertThat(person.getName()).isEqualTo("hugo");
assertThat(person.getAge()).isEqualTo(33);
assertThat(person.getNicknames()).containsOnly("captain", "player");
assertThat(person.getEmailAddresses()).containsOnly("test@example.org", "test2@example.org");
+ assertThat(person.getPhoneNumbers()).containsOnly(
+ MapEntry.entry("private", "0351 1234567"),
+ MapEntry.entry("mobile", "0123 4567890"));
personWrapper.reload();
// now the properties have the values from the wrapped object
@@ -151,12 +180,17 @@ public void testWithGetterAndSetter() {
assertThat(ageProperty.getValue()).isEqualTo(33);
assertThat(nicknamesProperty.get()).containsOnly("captain", "player");
assertThat(emailAddressesProperty.get()).containsOnly("test@example.org", "test2@example.org");
+ assertThat(phoneNumbersProperty.get()).containsOnly(
+ MapEntry.entry("private", "0351 1234567"),
+ MapEntry.entry("mobile", "0123 4567890"));
+
Person otherPerson = new Person();
otherPerson.setName("gisela");
otherPerson.setAge(23);
- otherPerson.setNicknames(Arrays.asList("referee"));
+ otherPerson.setNicknames(Collections.singletonList("referee"));
otherPerson.setEmailAddresses(Collections.singleton("gisela@example.org"));
+ otherPerson.setPhoneNumbers(Collections.singletonMap("private", "030 112233"));
personWrapper.set(otherPerson);
personWrapper.reload();
@@ -165,11 +199,16 @@ public void testWithGetterAndSetter() {
assertThat(ageProperty.getValue()).isEqualTo(23);
assertThat(nicknamesProperty.getValue()).containsOnly("referee");
assertThat(emailAddressesProperty.getValue()).containsOnly("gisela@example.org");
+ assertThat(phoneNumbersProperty.get()).containsOnly(
+ MapEntry.entry("private", "030 112233")
+ );
nameProperty.setValue("georg");
ageProperty.setValue(24);
nicknamesProperty.setValue(FXCollections.observableArrayList("spectator"));
emailAddressesProperty.setValue(FXCollections.observableSet("georg@example.org"));
+ phoneNumbersProperty.setValue(observableMap("private",
+ "0351 7654321"));
personWrapper.commit();
@@ -178,12 +217,16 @@ public void testWithGetterAndSetter() {
assertThat(person.getAge()).isEqualTo(33);
assertThat(person.getNicknames()).containsOnly("captain", "player");
assertThat(person.getEmailAddresses()).containsOnly("test@example.org", "test2@example.org");
+ assertThat(person.getPhoneNumbers()).containsOnly(
+ MapEntry.entry("private", "0351 1234567"),
+ MapEntry.entry("mobile", "0123 4567890"));
// new person has the new values
assertThat(otherPerson.getName()).isEqualTo("georg");
assertThat(otherPerson.getAge()).isEqualTo(24);
assertThat(otherPerson.getNicknames()).containsOnly("spectator");
assertThat(otherPerson.getEmailAddresses()).containsOnly("georg@example.org");
+ assertThat(otherPerson.getPhoneNumbers()).containsOnly(MapEntry.entry("private", "0351 7654321"));
}
@@ -192,8 +235,9 @@ public void testWithJavaFXPropertiesField() {
PersonFX person = new PersonFX();
person.setName("horst");
person.setAge(32);
- person.setNicknames(Arrays.asList("captain"));
+ person.setNicknames(Collections.singletonList("captain"));
person.setEmailAddresses(Collections.singleton("test@example.org"));
+ person.setPhoneNumbers(observableMap("private", "0351 1234567"));
ModelWrapper personWrapper = new ModelWrapper<>(person);
@@ -201,22 +245,26 @@ public void testWithJavaFXPropertiesField() {
final IntegerProperty ageProperty = personWrapper.field(PersonFX::ageProperty);
final ListProperty nicknamesProperty = personWrapper.field(PersonFX::nicknamesProperty);
final SetProperty emailAddressesProperty = personWrapper.field(PersonFX::emailAddressesProperty);
+ final MapProperty phoneNumbersProperty = personWrapper.field(PersonFX::phoneNumbersProperty);
assertThat(nameProperty.getValue()).isEqualTo("horst");
assertThat(ageProperty.getValue()).isEqualTo(32);
assertThat(nicknamesProperty.getValue()).containsOnly("captain");
assertThat(emailAddressesProperty.getValue()).containsOnly("test@example.org");
+ assertThat(phoneNumbersProperty.getValue()).containsOnly(MapEntry.entry("private", "0351 1234567"));
nameProperty.setValue("hugo");
ageProperty.setValue(33);
nicknamesProperty.add("player");
emailAddressesProperty.add("test2@example.org");
+ phoneNumbersProperty.putIfAbsent("mobile", "0123 4567890");
// still the old values
assertThat(person.getName()).isEqualTo("horst");
assertThat(person.getAge()).isEqualTo(32);
assertThat(person.getNicknames()).containsOnly("captain");
assertThat(person.getEmailAddresses()).containsOnly("test@example.org");
+ assertThat(person.getPhoneNumbers()).containsOnly(MapEntry.entry("private", "0351 1234567"));
personWrapper.commit();
@@ -225,11 +273,16 @@ public void testWithJavaFXPropertiesField() {
assertThat(person.getAge()).isEqualTo(33);
assertThat(person.getNicknames()).containsOnly("captain", "player");
assertThat(person.getEmailAddresses()).containsOnly("test@example.org", "test2@example.org");
+ assertThat(person.getPhoneNumbers()).containsOnly(
+ MapEntry.entry("private", "0351 1234567"),
+ MapEntry.entry("mobile", "0123 4567890"));
+
nameProperty.setValue("luise");
ageProperty.setValue(15);
nicknamesProperty.setValue(FXCollections.observableArrayList("student"));
emailAddressesProperty.setValue(FXCollections.observableSet("luise@example.org"));
+ phoneNumbersProperty.setValue(observableMap("mobile", "0124 9876543"));
personWrapper.reset();
@@ -237,12 +290,16 @@ public void testWithJavaFXPropertiesField() {
assertThat(ageProperty.getValue()).isEqualTo(0);
assertThat(nicknamesProperty.getValue()).isEmpty();
assertThat(emailAddressesProperty.getValue()).isEmpty();
+ assertThat(phoneNumbersProperty.getValue()).isEmpty();
// the wrapped object has still the values from the last commit.
assertThat(person.getName()).isEqualTo("hugo");
assertThat(person.getAge()).isEqualTo(33);
assertThat(person.getNicknames()).containsOnly("captain", "player");
assertThat(person.getEmailAddresses()).containsOnly("test@example.org", "test2@example.org");
+ assertThat(person.getPhoneNumbers()).containsOnly(
+ MapEntry.entry("private", "0351 1234567"),
+ MapEntry.entry("mobile", "0123 4567890"));
personWrapper.reload();
// now the properties have the values from the wrapped object
@@ -250,12 +307,16 @@ public void testWithJavaFXPropertiesField() {
assertThat(ageProperty.getValue()).isEqualTo(33);
assertThat(nicknamesProperty.get()).containsOnly("captain", "player");
assertThat(emailAddressesProperty.get()).containsOnly("test@example.org", "test2@example.org");
+ assertThat(person.getPhoneNumbers()).containsOnly(
+ MapEntry.entry("private", "0351 1234567"),
+ MapEntry.entry("mobile", "0123 4567890"));
PersonFX otherPerson = new PersonFX();
otherPerson.setName("gisela");
otherPerson.setAge(23);
- otherPerson.setNicknames(Arrays.asList("referee"));
+ otherPerson.setNicknames(Collections.singletonList("referee"));
otherPerson.setEmailAddresses(Collections.singleton("gisela@example.org"));
+ otherPerson.setPhoneNumbers(Collections.singletonMap("private", "030 112233"));
personWrapper.set(otherPerson);
personWrapper.reload();
@@ -264,11 +325,13 @@ public void testWithJavaFXPropertiesField() {
assertThat(ageProperty.getValue()).isEqualTo(23);
assertThat(nicknamesProperty.getValue()).containsOnly("referee");
assertThat(emailAddressesProperty.getValue()).containsOnly("gisela@example.org");
+ assertThat(phoneNumbersProperty.getValue()).containsOnly(MapEntry.entry("private", "030 112233"));
nameProperty.setValue("georg");
ageProperty.setValue(24);
nicknamesProperty.setValue(FXCollections.observableArrayList("spectator"));
emailAddressesProperty.setValue(FXCollections.observableSet("georg@example.org"));
+ phoneNumbersProperty.setValue(observableMap("private", "0351 7654321"));
personWrapper.commit();
@@ -277,13 +340,17 @@ public void testWithJavaFXPropertiesField() {
assertThat(person.getAge()).isEqualTo(33);
assertThat(person.getNicknames()).containsOnly("captain", "player");
assertThat(person.getEmailAddresses()).containsOnly("test@example.org", "test2@example.org");
+ assertThat(person.getPhoneNumbers()).containsOnly(
+ MapEntry.entry("private", "0351 1234567"),
+ MapEntry.entry("mobile", "0123 4567890"));
+
// new person has the new values
assertThat(otherPerson.getName()).isEqualTo("georg");
assertThat(otherPerson.getAge()).isEqualTo(24);
assertThat(otherPerson.getNicknames()).containsOnly("spectator");
assertThat(otherPerson.getEmailAddresses()).containsOnly("georg@example.org");
-
+ assertThat(otherPerson.getPhoneNumbers()).containsOnly(MapEntry.entry("private", "0351 7654321"));
}
@Test
@@ -293,7 +360,8 @@ public void testWithImmutables() {
.withName("horst")
.withAge(32)
.withNicknames(Collections.singletonList("captain"))
- .withEmailAddresses(Collections.singleton("test@example.org"));
+ .withEmailAddresses(Collections.singleton("test@example.org"))
+ .withPhoneNumbers(Collections.singletonMap("private", "0351 1234567"));
ModelWrapper personWrapper = new ModelWrapper<>(person1);
@@ -304,16 +372,20 @@ public void testWithImmutables() {
final ListProperty nicknamesProperty = personWrapper.immutableField(PersonImmutable::getNicknames, PersonImmutable::withNicknames);
final SetProperty emailAddressesProperty = personWrapper.immutableField(PersonImmutable::getEmailAddresses,
PersonImmutable::withEmailAddresses);
+ final MapProperty phoneNumbersProperty = personWrapper.immutableField(
+ PersonImmutable::getPhoneNumbers, PersonImmutable::withPhoneNumbers);
assertThat(nameProperty.getValue()).isEqualTo("horst");
assertThat(ageProperty.getValue()).isEqualTo(32);
assertThat(nicknamesProperty.getValue()).containsOnly("captain");
assertThat(emailAddressesProperty.getValue()).containsOnly("test@example.org");
+ assertThat(phoneNumbersProperty.getValue()).containsOnly(MapEntry.entry("private", "0351 1234567"));
nameProperty.setValue("hugo");
ageProperty.setValue(33);
nicknamesProperty.add("player");
emailAddressesProperty.add("hugo@example.org");
+ phoneNumbersProperty.putIfAbsent("mobile", "0123 4567890");
personWrapper.commit();
@@ -322,6 +394,7 @@ public void testWithImmutables() {
assertThat(person1.getAge()).isEqualTo(32);
assertThat(person1.getNicknames()).containsOnly("captain");
assertThat(person1.getEmailAddresses()).containsOnly("test@example.org");
+ assertThat(person1.getPhoneNumbers()).containsOnly(MapEntry.entry("private", "0351 1234567"));
PersonImmutable person2 = personWrapper.get();
@@ -330,11 +403,15 @@ public void testWithImmutables() {
assertThat(person2.getAge()).isEqualTo(33);
assertThat(person2.getNicknames()).containsOnly("captain", "player");
assertThat(person2.getEmailAddresses()).containsOnly("test@example.org", "hugo@example.org");
+ assertThat(person2.getPhoneNumbers()).containsOnly(
+ MapEntry.entry("mobile", "0123 4567890"),
+ MapEntry.entry("private", "0351 1234567"));
nameProperty.setValue("luise");
ageProperty.setValue(33);
nicknamesProperty.setValue(FXCollections.observableArrayList("student"));
emailAddressesProperty.setValue(FXCollections.observableSet("luise@example.org"));
+ phoneNumbersProperty.setValue(observableMap("mobile", "0124 9876543"));
personWrapper.reset();
@@ -342,6 +419,7 @@ public void testWithImmutables() {
assertThat(ageProperty.getValue()).isEqualTo(0);
assertThat(nicknamesProperty.getValue()).isEmpty();
assertThat(emailAddressesProperty.getValue()).isEmpty();
+ assertThat(phoneNumbersProperty.getValue()).isEmpty();
personWrapper.reload();
// now the properties have the values from the wrapped object
@@ -349,11 +427,15 @@ public void testWithImmutables() {
assertThat(ageProperty.getValue()).isEqualTo(33);
assertThat(nicknamesProperty.get()).containsOnly("captain", "player");
assertThat(emailAddressesProperty.get()).containsOnly("test@example.org", "hugo@example.org");
+ assertThat(phoneNumbersProperty.get()).containsOnly(
+ MapEntry.entry("mobile", "0123 4567890"),
+ MapEntry.entry("private", "0351 1234567"));
PersonImmutable person3 = person1.withName("gisela")
.withAge(23)
.withNicknames(Collections.singletonList("referee"))
- .withEmailAddresses(Collections.singleton("gisela@example.org"));
+ .withEmailAddresses(Collections.singleton("gisela@example.org"))
+ .withPhoneNumbers(Collections.singletonMap("private", "030 112233"));
personWrapper.set(person3);
personWrapper.reload();
@@ -362,6 +444,7 @@ public void testWithImmutables() {
assertThat(ageProperty.getValue()).isEqualTo(23);
assertThat(nicknamesProperty.getValue()).containsOnly("referee");
assertThat(emailAddressesProperty.getValue()).containsOnly("gisela@example.org");
+ assertThat(phoneNumbersProperty.getValue()).containsOnly(MapEntry.entry("private", "030 112233"));
}
@Test
@@ -369,8 +452,9 @@ public void testIdentifiedFields() {
Person person = new Person();
person.setName("horst");
person.setAge(32);
- person.setNicknames(Arrays.asList("captain"));
+ person.setNicknames(Collections.singletonList("captain"));
person.setEmailAddresses(Collections.singleton("test@example.org"));
+ person.setPhoneNumbers(Collections.singletonMap("private", "0351 1234567"));
ModelWrapper personWrapper = new ModelWrapper<>();
@@ -380,6 +464,10 @@ public void testIdentifiedFields() {
Person::setNicknames);
final SetProperty emailAddressesProperty = personWrapper.field("emailAddresses", Person::getEmailAddresses,
Person::setEmailAddresses);
+ final MapProperty phoneNumbersProperty = personWrapper.field("phoneNumbers",
+ Person::getPhoneNumbers,
+ Person::setPhoneNumbers);
+
final StringProperty nameProperty2 = personWrapper.field("name", Person::getName, Person::setName);
final IntegerProperty ageProperty2 = personWrapper.field("age", Person::getAge, Person::setAge);
@@ -387,17 +475,22 @@ public void testIdentifiedFields() {
Person::setNicknames);
final SetProperty emailAddressesProperty2 = personWrapper.field("emailAddresses", Person::getEmailAddresses,
Person::setEmailAddresses);
+ final MapProperty phoneNumbersProperty2 = personWrapper.field("phoneNumbers",
+ Person::getPhoneNumbers,
+ Person::setPhoneNumbers);
assertThat(nameProperty).isSameAs(nameProperty2);
assertThat(ageProperty).isSameAs(ageProperty2);
assertThat(nicknamesProperty).isSameAs(nicknamesProperty2);
assertThat(emailAddressesProperty).isSameAs(emailAddressesProperty2);
+ assertThat(phoneNumbersProperty).isSameAs(phoneNumbersProperty2);
// with identified fields the "name" of the created properties should be set
assertThat(nameProperty.getName()).isEqualTo("name");
assertThat(ageProperty.getName()).isEqualTo("age");
assertThat(nicknamesProperty.getName()).isEqualTo("nicknames");
assertThat(emailAddressesProperty.getName()).isEqualTo("emailAddresses");
+ assertThat(phoneNumbersProperty.getName()).isEqualTo("phoneNumbers");
}
@Test
@@ -407,7 +500,8 @@ public void testIdentifiedFieldsWithImmutables() {
.withName("horst")
.withAge(32)
.withNicknames(Collections.singletonList("captain"))
- .withEmailAddresses(Collections.singleton("test@example.org"));
+ .withEmailAddresses(Collections.singleton("test@example.org"))
+ .withPhoneNumbers(Collections.singletonMap("private", "0351 1234567"));
ModelWrapper personWrapper = new ModelWrapper<>(person1);
@@ -418,6 +512,10 @@ public void testIdentifiedFieldsWithImmutables() {
personWrapper.immutableField("nicknames", PersonImmutable::getNicknames, PersonImmutable::withNicknames);
final SetProperty emailAddressesProperty = personWrapper.immutableField("emailAddresses", PersonImmutable::getEmailAddresses,
PersonImmutable::withEmailAddresses);
+ final MapProperty phoneNumbersProperty = personWrapper.immutableField("phoneNumbers",
+ PersonImmutable::getPhoneNumbers,
+ PersonImmutable::withPhoneNumbers);
+
final StringProperty nameProperty2 = personWrapper
.immutableField("name", PersonImmutable::getName, PersonImmutable::withName);
@@ -426,16 +524,21 @@ public void testIdentifiedFieldsWithImmutables() {
personWrapper.immutableField("nicknames", PersonImmutable::getNicknames, PersonImmutable::withNicknames);
final SetProperty emailAddressesProperty2 = personWrapper.immutableField("emailAddresses", PersonImmutable::getEmailAddresses,
PersonImmutable::withEmailAddresses);
+ final MapProperty phoneNumbersProperty2 = personWrapper.immutableField("phoneNumbers",
+ PersonImmutable::getPhoneNumbers,
+ PersonImmutable::withPhoneNumbers);
assertThat(nameProperty).isSameAs(nameProperty2);
assertThat(ageProperty).isSameAs(ageProperty2);
assertThat(nicknamesProperty).isSameAs(nicknamesProperty2);
assertThat(emailAddressesProperty).isSameAs(emailAddressesProperty2);
+ assertThat(phoneNumbersProperty).isSameAs(phoneNumbersProperty2);
assertThat(nameProperty.getName()).isEqualTo("name");
assertThat(ageProperty.getName()).isEqualTo("age");
assertThat(nicknamesProperty.getName()).isEqualTo("nicknames");
assertThat(emailAddressesProperty.getName()).isEqualTo("emailAddresses");
+ assertThat(phoneNumbersProperty.getName()).isEqualTo("phoneNumbers");
}
@Test
@@ -443,7 +546,9 @@ public void testDirtyFlag() {
Person person = new Person();
person.setName("horst");
person.setAge(32);
- person.setNicknames(Arrays.asList("captain"));
+ person.setNicknames(Collections.singletonList("captain"));
+ person.setEmailAddresses(Collections.singleton("test@example.org"));
+ person.setPhoneNumbers(Collections.singletonMap("private", "+49 1234567"));
ModelWrapper personWrapper = new ModelWrapper<>(person);
@@ -452,6 +557,10 @@ public void testDirtyFlag() {
final StringProperty name = personWrapper.field(Person::getName, Person::setName);
final IntegerProperty age = personWrapper.field(Person::getAge, Person::setAge);
final ListProperty nicknames = personWrapper.field(Person::getNicknames, Person::setNicknames);
+ final SetProperty emailAddresses = personWrapper.field(Person::getEmailAddresses,
+ Person::setEmailAddresses);
+ final MapProperty phoneNumbers = personWrapper.field(Person::getPhoneNumbers,
+ Person::setPhoneNumbers);
name.set("hugo");
@@ -496,6 +605,25 @@ public void testDirtyFlag() {
personWrapper.reload();
assertThat(personWrapper.isDirty()).isFalse();
+
+ emailAddresses.setValue(FXCollections.observableSet("player@example.org"));
+ assertThat(personWrapper.isDirty()).isTrue();
+
+ personWrapper.reset();
+ assertThat(personWrapper.isDirty()).isTrue();
+
+ personWrapper.reload();
+ assertThat(personWrapper.isDirty()).isFalse();
+
+
+ phoneNumbers.setValue(observableMap("other", "+49 203204303"));
+ assertThat(personWrapper.isDirty()).isTrue();
+
+ personWrapper.reset();
+ assertThat(personWrapper.isDirty()).isTrue();
+
+ personWrapper.reload();
+ assertThat(personWrapper.isDirty()).isFalse();
}
@Test
@@ -503,6 +631,9 @@ public void testDirtyFlagWithFxProperties() {
PersonFX person = new PersonFX();
person.setName("horst");
person.setAge(32);
+ person.setNicknames(Collections.singletonList("captain"));
+ person.setEmailAddresses(Collections.singleton("test@example.org"));
+ person.setPhoneNumbers(Collections.singletonMap("private", "+49 1234567"));
ModelWrapper personWrapper = new ModelWrapper<>(person);
@@ -511,6 +642,8 @@ public void testDirtyFlagWithFxProperties() {
final StringProperty name = personWrapper.field(PersonFX::nameProperty);
final IntegerProperty age = personWrapper.field(PersonFX::ageProperty);
final ListProperty nicknames = personWrapper.field(PersonFX::nicknamesProperty);
+ final SetProperty emailAddresses = personWrapper.field(PersonFX::emailAddressesProperty);
+ final MapProperty phoneNumbers = personWrapper.field(PersonFX::phoneNumbersProperty);
name.set("hugo");
@@ -554,6 +687,27 @@ public void testDirtyFlagWithFxProperties() {
personWrapper.reload();
assertThat(personWrapper.isDirty()).isFalse();
+
+
+
+ emailAddresses.setValue(FXCollections.observableSet("player@example.org"));
+ assertThat(personWrapper.isDirty()).isTrue();
+
+ personWrapper.reset();
+ assertThat(personWrapper.isDirty()).isTrue();
+
+ personWrapper.reload();
+ assertThat(personWrapper.isDirty()).isFalse();
+
+
+ phoneNumbers.setValue(observableMap("other", "+49 203204303"));
+ assertThat(personWrapper.isDirty()).isTrue();
+
+ personWrapper.reset();
+ assertThat(personWrapper.isDirty()).isTrue();
+
+ personWrapper.reload();
+ assertThat(personWrapper.isDirty()).isFalse();
}
@Test
@@ -562,7 +716,9 @@ public void testDirtyFlagWithImmutables() {
PersonImmutable person = PersonImmutable.create()
.withName("horst")
.withAge(32)
- .withNicknames(Collections.singletonList("captain"));
+ .withNicknames(Collections.singletonList("captain"))
+ .withEmailAddresses(Collections.singleton("test@example.org"))
+ .withPhoneNumbers(Collections.singletonMap("private", "+49 1234567"));
ModelWrapper personWrapper = new ModelWrapper<>(person);
@@ -573,6 +729,10 @@ public void testDirtyFlagWithImmutables() {
final IntegerProperty age = personWrapper.immutableField(PersonImmutable::getAge,
PersonImmutable::withAge);
final ListProperty nicknames = personWrapper.immutableField(PersonImmutable::getNicknames, PersonImmutable::withNicknames);
+ final SetProperty emailAddresses = personWrapper.field(PersonImmutable::getEmailAddresses,
+ PersonImmutable::withEmailAddresses);
+ final MapProperty phoneNumbers = personWrapper.field(PersonImmutable::getPhoneNumbers,
+ PersonImmutable::withPhoneNumbers);
name.set("hugo");
@@ -616,6 +776,27 @@ public void testDirtyFlagWithImmutables() {
personWrapper.reload();
assertThat(personWrapper.isDirty()).isFalse();
+
+
+
+ emailAddresses.setValue(FXCollections.observableSet("player@example.org"));
+ assertThat(personWrapper.isDirty()).isTrue();
+
+ personWrapper.reset();
+ assertThat(personWrapper.isDirty()).isTrue();
+
+ personWrapper.reload();
+ assertThat(personWrapper.isDirty()).isFalse();
+
+
+ phoneNumbers.setValue(observableMap("other", "+49 203204303"));
+ assertThat(personWrapper.isDirty()).isTrue();
+
+ personWrapper.reset();
+ assertThat(personWrapper.isDirty()).isTrue();
+
+ personWrapper.reload();
+ assertThat(personWrapper.isDirty()).isFalse();
}
@Test
@@ -623,8 +804,9 @@ public void testDifferentFlag() {
Person person = new Person();
person.setName("horst");
person.setAge(32);
- person.setNicknames(Arrays.asList("captain"));
+ person.setNicknames(Collections.singletonList("captain"));
person.setEmailAddresses(Collections.singleton("test@example.org"));
+ person.setPhoneNumbers(Collections.singletonMap("private", "0351 1234567"));
ModelWrapper personWrapper = new ModelWrapper<>(person);
@@ -634,6 +816,7 @@ public void testDifferentFlag() {
final IntegerProperty age = personWrapper.field(Person::getAge, Person::setAge);
final ListProperty nicknames = personWrapper.field(Person::getNicknames, Person::setNicknames);
final SetProperty emailAddresses = personWrapper.field(Person::getEmailAddresses, Person::setEmailAddresses);
+ final MapProperty phoneNumbers = personWrapper.field(Person::getPhoneNumbers, Person::setPhoneNumbers);
assertThat(personWrapper.isDifferent()).isFalse();
@@ -713,6 +896,15 @@ public void testDifferentFlag() {
personWrapper.reset();
assertThat(personWrapper.isDifferent()).isTrue();
+
+ personWrapper.reload();
+ assertThat(personWrapper.isDifferent()).isFalse();
+
+ phoneNumbers.set(observableMap("other", "+49 12445"));
+ assertThat(personWrapper.isDifferent()).isTrue();
+
+ phoneNumbers.remove("other");
+ assertThat(personWrapper.isDifferent()).isFalse();
}
@@ -721,8 +913,9 @@ public void testDifferentFlagWithFxProperties() {
PersonFX person = new PersonFX();
person.setName("horst");
person.setAge(32);
- person.setNicknames(Arrays.asList("captain"));
+ person.setNicknames(Collections.singletonList("captain"));
person.setEmailAddresses(Collections.singleton("test@example.org"));
+ person.setPhoneNumbers(Collections.singletonMap("private", "0351 1234567"));
ModelWrapper personWrapper = new ModelWrapper<>(person);
@@ -732,6 +925,7 @@ public void testDifferentFlagWithFxProperties() {
final IntegerProperty age = personWrapper.field(PersonFX::ageProperty);
final ListProperty nicknames = personWrapper.field(PersonFX::nicknamesProperty);
final SetProperty emailAddresses = personWrapper.field(PersonFX::emailAddressesProperty);
+ final MapProperty phoneNumbers = personWrapper.field(PersonFX::phoneNumbersProperty);
name.set("hugo");
assertThat(personWrapper.isDifferent()).isTrue();
@@ -795,6 +989,16 @@ public void testDifferentFlagWithFxProperties() {
personWrapper.reset();
assertThat(personWrapper.isDifferent()).isTrue();
+
+ personWrapper.reload();
+ assertThat(personWrapper.isDifferent()).isFalse();
+
+ phoneNumbers.put("other", "+49 12445");
+ assertThat(personWrapper.isDifferent()).isTrue();
+
+ phoneNumbers.remove("other");
+ assertThat(personWrapper.isDifferent()).isFalse();
+
}
@Test
@@ -802,7 +1006,9 @@ public void testDifferentFlagWithImmutables() {
PersonImmutable person = PersonImmutable.create()
.withName("horst")
.withAge(32)
- .withNicknames(Collections.singletonList("captain"));
+ .withNicknames(Collections.singletonList("captain"))
+ .withEmailAddresses(Collections.singleton("test@example.org"))
+ .withPhoneNumbers(Collections.singletonMap("private", "+49 12342434"));
ModelWrapper personWrapper = new ModelWrapper<>(person);
@@ -813,6 +1019,11 @@ public void testDifferentFlagWithImmutables() {
final IntegerProperty age = personWrapper.immutableField(PersonImmutable::getAge,
PersonImmutable::withAge);
final ListProperty nicknames = personWrapper.immutableField(PersonImmutable::getNicknames, PersonImmutable::withNicknames);
+ final SetProperty emailAddresses = personWrapper.immutableField(PersonImmutable::getEmailAddresses,
+ PersonImmutable::withEmailAddresses);
+ final MapProperty phoneNumbers =
+ personWrapper.immutableField(PersonImmutable::getPhoneNumbers,
+ PersonImmutable::withPhoneNumbers);
name.set("hugo");
assertThat(personWrapper.isDifferent()).isTrue();
@@ -849,6 +1060,16 @@ public void testDifferentFlagWithImmutables() {
nicknames.add("player");
assertThat(personWrapper.isDifferent()).isTrue();
+
+ personWrapper.reload();
+ assertThat(personWrapper.isDifferent()).isFalse();
+
+ phoneNumbers.put("other", "+49 12445");
+ assertThat(personWrapper.isDifferent()).isTrue();
+
+ phoneNumbers.remove("other");
+ assertThat(personWrapper.isDifferent()).isFalse();
+
}
@Test
@@ -856,8 +1077,9 @@ public void defaultValuesCanBeUpdatedToCurrentValues() {
final Person person = new Person();
person.setName("horst");
person.setAge(32);
- person.setNicknames(Arrays.asList("captain"));
+ person.setNicknames(Collections.singletonList("captain"));
person.setEmailAddresses(Collections.singleton("test@example.org"));
+ person.setPhoneNumbers(Collections.singletonMap("private", "+49 11223434"));
final ModelWrapper personWrapper = new ModelWrapper<>(person);
@@ -894,6 +1116,17 @@ public void defaultValuesCanBeUpdatedToCurrentValues() {
personWrapper.useCurrentValuesAsDefaults();
personWrapper.reset();
assertThat(person.getEmailAddresses()).containsExactly("hugo@example.org");
+
+
+ final MapProperty phoneNumbers = personWrapper.field(Person::getPhoneNumbers,
+ Person::setPhoneNumbers,
+ person.getPhoneNumbers());
+ phoneNumbers.put("other", "112324232");
+ phoneNumbers.remove("private");
+ personWrapper.commit();
+ personWrapper.useCurrentValuesAsDefaults();
+ personWrapper.reset();
+ assertThat(person.getPhoneNumbers()).containsExactly(MapEntry.entry("other", "112324232"));
}
@Test
@@ -902,7 +1135,8 @@ public void defaultValuesCanBeUpdatedToCurrentValuesWithImmutables() {
.withName("Luise")
.withAge(32)
.withNicknames(Collections.singletonList("captain"))
- .withEmailAddresses(Collections.singleton("test@example.org"));
+ .withEmailAddresses(Collections.singleton("test@example.org"))
+ .withPhoneNumbers(Collections.singletonMap("private", "+49 1234567"));
ModelWrapper personWrapper = new ModelWrapper<>(person);
@@ -918,6 +1152,9 @@ public void defaultValuesCanBeUpdatedToCurrentValuesWithImmutables() {
final SetProperty emailAddresses = personWrapper.immutableField(PersonImmutable::getEmailAddresses,
PersonImmutable::withEmailAddresses, person.getEmailAddresses());
+ final MapProperty phoneNumbers = personWrapper.immutableField(PersonImmutable::getPhoneNumbers,
+ PersonImmutable::withPhoneNumbers, person.getPhoneNumbers());
+
name.set("test");
personWrapper.commit();
personWrapper.useCurrentValuesAsDefaults();
@@ -943,6 +1180,14 @@ public void defaultValuesCanBeUpdatedToCurrentValuesWithImmutables() {
personWrapper.useCurrentValuesAsDefaults();
personWrapper.reset();
assertThat(emailAddresses.get()).containsExactly("hugo@example.org");
+
+
+ phoneNumbers.put("other", "1234567");
+ phoneNumbers.remove("private");
+ personWrapper.commit();
+ personWrapper.useCurrentValuesAsDefaults();
+ personWrapper.reset();
+ assertThat(phoneNumbers.get()).containsExactly(MapEntry.entry("other", "1234567"));
}
@Test
@@ -950,13 +1195,15 @@ public void valuesShouldBeUpdatedWhenModelInstanceChanges() {
final Person person1 = new Person();
person1.setName("horst");
person1.setAge(32);
- person1.setNicknames(Arrays.asList("captain"));
+ person1.setNicknames(Collections.singletonList("captain"));
person1.setEmailAddresses(Collections.singleton("test@example.org"));
+ person1.setPhoneNumbers(Collections.singletonMap("private_Horst", "0351 1234567"));
final Person person2 = new Person();
person2.setName("dieter");
person2.setAge(42);
- person2.setNicknames(Arrays.asList("robin"));
+ person2.setNicknames(Collections.singletonList("robin"));
person2.setEmailAddresses(Collections.singleton("dieter@example.org"));
+ person2.setPhoneNumbers(Collections.singletonMap("private_Dieter", "030 001199"));
final SimpleObjectProperty modelProp = new SimpleObjectProperty<>(person1);
@@ -968,23 +1215,28 @@ public void valuesShouldBeUpdatedWhenModelInstanceChanges() {
.field(Person::getNicknames, Person::setNicknames, person1.getNicknames());
final SetProperty emailAddresses = personWrapper.field(Person::getEmailAddresses, Person::setEmailAddresses,
person1.getEmailAddresses());
+ final MapProperty phoneNumbers = personWrapper.field(Person::getPhoneNumbers,
+ Person::setPhoneNumbers, person1.getPhoneNumbers());
assertThat(nameField.get()).isEqualTo(person1.getName());
assertThat(ageField.get()).isEqualTo(person1.getAge());
assertThat(nicknames.get()).containsExactlyElementsOf(person1.getNicknames());
assertThat(emailAddresses.get()).containsExactlyElementsOf(person1.getEmailAddresses());
+ assertThat(phoneNumbers.get().entrySet()).containsExactlyElementsOf(person1.getPhoneNumbers().entrySet());
modelProp.set(person2);
assertThat(nameField.get()).isEqualTo(person2.getName());
assertThat(ageField.get()).isEqualTo(person2.getAge());
assertThat(nicknames.get()).containsExactlyElementsOf(person2.getNicknames());
assertThat(emailAddresses.get()).containsExactlyElementsOf(person2.getEmailAddresses());
+ assertThat(phoneNumbers.get().entrySet()).containsExactlyElementsOf(person2.getPhoneNumbers().entrySet());
personWrapper.reset();
assertThat(nameField.get()).isEqualTo(person1.getName());
assertThat(ageField.get()).isEqualTo(person1.getAge());
assertThat(nicknames.get()).containsExactlyElementsOf(person1.getNicknames());
assertThat(emailAddresses.get()).containsExactlyElementsOf(person1.getEmailAddresses());
+ assertThat(phoneNumbers.get().entrySet()).containsExactlyElementsOf(person1.getPhoneNumbers().entrySet());
}
@Test
@@ -993,13 +1245,15 @@ public void valuesShouldBeUpdatedWhenModelInstanceChangesWithImmutables() {
.withName("horst")
.withAge(32)
.withNicknames(Collections.singletonList("captain"))
- .withEmailAddresses(Collections.singleton("test@example.org"));
+ .withEmailAddresses(Collections.singleton("test@example.org"))
+ .withPhoneNumbers(Collections.singletonMap("private_Horst", "0351 1234567"));
PersonImmutable person2 = PersonImmutable.create()
.withName("dieter")
.withAge(42)
.withNicknames(Collections.singletonList("robin"))
- .withEmailAddresses(Collections.singleton("dieter@example.org"));
+ .withEmailAddresses(Collections.singleton("dieter@example.org"))
+ .withPhoneNumbers(Collections.singletonMap("private_Dieter", "030 001199"));
final SimpleObjectProperty modelProp = new SimpleObjectProperty<>(person1);
@@ -1013,23 +1267,29 @@ public void valuesShouldBeUpdatedWhenModelInstanceChangesWithImmutables() {
personWrapper.immutableField(PersonImmutable::getNicknames, PersonImmutable::withNicknames, person1.getNicknames());
final SetProperty emailAddresses = personWrapper.immutableField(PersonImmutable::getEmailAddresses,
PersonImmutable::withEmailAddresses, person1.getEmailAddresses());
+ final MapProperty phoneNumbers = personWrapper.immutableField(PersonImmutable::getPhoneNumbers,
+ PersonImmutable::withPhoneNumbers,
+ person1.getPhoneNumbers());
assertThat(nameField.get()).isEqualTo(person1.getName());
assertThat(ageField.get()).isEqualTo(person1.getAge());
assertThat(nicknames.get()).containsExactlyElementsOf(person1.getNicknames());
assertThat(emailAddresses.get()).containsExactlyElementsOf(person1.getEmailAddresses());
+ assertThat(phoneNumbers.get().entrySet()).containsExactlyElementsOf(person1.getPhoneNumbers().entrySet());
modelProp.set(person2);
assertThat(nameField.get()).isEqualTo(person2.getName());
assertThat(ageField.get()).isEqualTo(person2.getAge());
assertThat(nicknames.get()).containsExactlyElementsOf(person2.getNicknames());
assertThat(emailAddresses.get()).containsExactlyElementsOf(person2.getEmailAddresses());
+ assertThat(phoneNumbers.get().entrySet()).containsExactlyElementsOf(person2.getPhoneNumbers().entrySet());
personWrapper.reset();
assertThat(nameField.get()).isEqualTo(person1.getName());
assertThat(ageField.get()).isEqualTo(person1.getAge());
assertThat(nicknames.get()).containsExactlyElementsOf(person1.getNicknames());
assertThat(emailAddresses.get()).containsExactlyElementsOf(person1.getEmailAddresses());
+ assertThat(phoneNumbers.get().entrySet()).containsExactlyElementsOf(person1.getPhoneNumbers().entrySet());
}
@Test
@@ -1043,6 +1303,8 @@ public void testUseCurrentValuesAsDefaultWhenModelIsNull() {
));
SetProperty emailAddresses = wrapper.field("emailAddresses", Person::getEmailAddresses, Person::setEmailAddresses,
Collections.singleton("test@example.org"));
+ MapProperty phoneNumbers = wrapper.field("phoneNumbers", Person::getPhoneNumbers,
+ Person::setPhoneNumbers, Collections.singletonMap("private_Horst", "0351 1234567"));
wrapper.reset();
@@ -1050,6 +1312,7 @@ public void testUseCurrentValuesAsDefaultWhenModelIsNull() {
assertThat(age.get()).isEqualTo(12);
assertThat(nicknames.get()).containsExactly("captain");
assertThat(emailAddresses.get()).containsExactly("test@example.org");
+ assertThat(phoneNumbers.get()).containsOnly(MapEntry.entry("private_Horst", "0351 1234567"));
wrapper.useCurrentValuesAsDefaults();
@@ -1060,6 +1323,7 @@ public void testUseCurrentValuesAsDefaultWhenModelIsNull() {
assertThat(age.get()).isEqualTo(12);
assertThat(nicknames.get()).containsExactly("captain");
assertThat(emailAddresses.get()).containsExactly("test@example.org");
+ assertThat(phoneNumbers.get()).containsOnly(MapEntry.entry("private_Horst", "0351 1234567"));
}
@Test
@@ -1067,7 +1331,7 @@ public void testDefaultValues() {
final Person person = new Person();
person.setName("horst");
person.setAge(32);
- person.setNicknames(Arrays.asList("captain"));
+ person.setNicknames(Collections.singletonList("captain"));
ModelWrapper wrapperWithDefaults = new ModelWrapper<>();
ModelWrapper wrapperWithoutDefaults = new ModelWrapper<>();
@@ -1139,4 +1403,11 @@ public void testSet() {
// then
assertThat(person.getEmailAddresses()).containsOnly("test@example.org");
}
+
+
+ private ObservableMap observableMap(K key, V value) {
+ Map map = new HashMap<>();
+ map.put(key, value);
+ return FXCollections.observableMap(map);
+ }
}
diff --git a/mvvmfx/src/test/java/de/saxsys/mvvmfx/utils/mapping/Person.java b/mvvmfx/src/test/java/de/saxsys/mvvmfx/utils/mapping/Person.java
index 46e6c2dd2..dd28e5d09 100644
--- a/mvvmfx/src/test/java/de/saxsys/mvvmfx/utils/mapping/Person.java
+++ b/mvvmfx/src/test/java/de/saxsys/mvvmfx/utils/mapping/Person.java
@@ -16,8 +16,10 @@
package de.saxsys.mvvmfx.utils.mapping;
import java.util.ArrayList;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
public class Person {
@@ -30,6 +32,8 @@ public class Person {
private Set emailAddresses = new HashSet<>();
+ private Map phoneNumbers = new HashMap<>();
+
public List getNicknames() {
return nicknames;
}
@@ -61,4 +65,12 @@ public String getName() {
public void setName(String name) {
this.name = name;
}
+
+ public Map getPhoneNumbers() {
+ return phoneNumbers;
+ }
+
+ public void setPhoneNumbers(Map phoneNumbers) {
+ this.phoneNumbers = phoneNumbers;
+ }
}
diff --git a/mvvmfx/src/test/java/de/saxsys/mvvmfx/utils/mapping/PersonFX.java b/mvvmfx/src/test/java/de/saxsys/mvvmfx/utils/mapping/PersonFX.java
index 1b6b70b6e..64a1fc92c 100644
--- a/mvvmfx/src/test/java/de/saxsys/mvvmfx/utils/mapping/PersonFX.java
+++ b/mvvmfx/src/test/java/de/saxsys/mvvmfx/utils/mapping/PersonFX.java
@@ -17,17 +17,22 @@
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.ListProperty;
+import javafx.beans.property.MapProperty;
import javafx.beans.property.SetProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleListProperty;
+import javafx.beans.property.SimpleMapProperty;
import javafx.beans.property.SimpleSetProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
+import javafx.collections.ObservableMap;
import javafx.collections.ObservableSet;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
public class PersonFX {
@@ -40,6 +45,9 @@ public class PersonFX {
private SetProperty emailAddresses = new SimpleSetProperty<>(FXCollections.observableSet(new HashSet<>()));
+ private MapProperty phoneNumbers = new SimpleMapProperty<>(
+ FXCollections.observableMap(new HashMap<>()));
+
public String getName() {
return name.get();
}
@@ -87,4 +95,17 @@ public SetProperty emailAddressesProperty() {
public void setEmailAddresses(Set emailAddresses) {
this.emailAddresses.addAll(emailAddresses);
}
+
+ public Map getPhoneNumbers() {
+ return phoneNumbers.get();
+ }
+
+ public MapProperty phoneNumbersProperty() {
+ return phoneNumbers;
+ }
+
+ public void setPhoneNumbers(Map phoneNumbers) {
+ this.phoneNumbers.clear();
+ this.phoneNumbers.putAll(phoneNumbers);
+ }
}
diff --git a/mvvmfx/src/test/java/de/saxsys/mvvmfx/utils/mapping/PersonImmutable.java b/mvvmfx/src/test/java/de/saxsys/mvvmfx/utils/mapping/PersonImmutable.java
index 984e5ef41..8bfe637c3 100644
--- a/mvvmfx/src/test/java/de/saxsys/mvvmfx/utils/mapping/PersonImmutable.java
+++ b/mvvmfx/src/test/java/de/saxsys/mvvmfx/utils/mapping/PersonImmutable.java
@@ -2,8 +2,10 @@
import java.util.ArrayList;
import java.util.Collections;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
+import java.util.Map;
import java.util.Set;
public class PersonImmutable {
@@ -13,15 +15,19 @@ public class PersonImmutable {
private final Set emailAddresses = new HashSet<>();
+ private final Map phoneNumbers = new HashMap<>();
+
public static PersonImmutable create(){
- return new PersonImmutable("", 0, Collections.emptyList(), Collections.emptySet());
+ return new PersonImmutable("", 0, Collections.emptyList(), Collections.emptySet(), Collections.emptyMap());
}
- private PersonImmutable(String name, int age, List nicknames, Set emailAddresses) {
+ private PersonImmutable(String name, int age, List nicknames, Set emailAddresses, Map phoneNumbers) {
this.name = name;
this.age = age;
this.nicknames.addAll(nicknames);
this.emailAddresses.addAll(emailAddresses);
+ this.phoneNumbers.putAll(phoneNumbers);
}
public String getName() {
@@ -29,7 +35,7 @@ public String getName() {
}
public PersonImmutable withName(String name) {
- return new PersonImmutable(name, this.age, this.nicknames, this.emailAddresses);
+ return new PersonImmutable(name, this.age, this.nicknames, this.emailAddresses, this.phoneNumbers);
}
public int getAge() {
@@ -37,7 +43,7 @@ public int getAge() {
}
public PersonImmutable withAge(int age) {
- return new PersonImmutable(this.name, age, this.nicknames, this.emailAddresses);
+ return new PersonImmutable(this.name, age, this.nicknames, this.emailAddresses, this.phoneNumbers);
}
public List getNicknames() {
@@ -45,7 +51,7 @@ public List getNicknames() {
}
public PersonImmutable withNicknames(List nicknames) {
- return new PersonImmutable(this.name, this.age, nicknames, this.emailAddresses);
+ return new PersonImmutable(this.name, this.age, nicknames, this.emailAddresses, this.phoneNumbers);
}
public Set