data = new LinkedHashMap<>();
+
+ protected MapBasedModelImpl() {
+ }
+
+ /**
+ * Merge all properties from another map-based model object into this one
+ *
+ * Usually this method will return {@code this}, but it may return {@code other} or a new object.
+ *
+ * @param other the other map-based model object
+ * @return the merged object
+ */
+ public MapBasedModelImpl mergeFrom(MapBasedModelImpl other) {
+ mergeMap(data, other.data, getNonMergableCollections());
+ return this;
+ }
+
+ public Map getDataMap() {
+ return data;
+ }
+
+ private static void mergeMap(Map into, Map from, Set nonMergableNames) {
+ for (Entry entry : from.entrySet()) {
+ String name = entry.getKey();
+ T value = entry.getValue();
+ T oldValue = into.get(entry.getKey());
+ if (oldValue == null || oldValue.getClass() != value.getClass()) {
+ into.put(name, value);
+ } else {
+ if (oldValue instanceof Map && !nonMergableNames.contains(name)) {
+ mergeMap((Map) oldValue, (Map) value, nonMergableNames);
+ } else if (oldValue instanceof List && !nonMergableNames.contains(name)) {
+ mergeList((List