private boolean mergeSystemProperties()

in services/src/main/java/org/apache/unomi/services/impl/profiles/ProfileServiceImpl.java [1221:1283]


    private boolean mergeSystemProperties(Map<String, Object> targetProperties, Map<String, Object> sourceProperties) {
        boolean changed = false;
        for (Map.Entry<String, Object> sourceProperty : sourceProperties.entrySet()) {
            if (sourceProperty.getValue() != null) {
                if (!targetProperties.containsKey(sourceProperty.getKey())) {
                    targetProperties.put(sourceProperty.getKey(), sourceProperty.getValue());
                    changed = true;
                } else {
                    Object targetProperty = targetProperties.get(sourceProperty.getKey());

                    if (targetProperty instanceof Map && sourceProperty.getValue() instanceof Map) {
                        // merge Maps like "goals", "campaigns"
                        @SuppressWarnings("unchecked")
                        Map<String, Object> mapSourceProp = (Map<String, Object>) sourceProperty.getValue();
                        @SuppressWarnings("unchecked")
                        Map<String, Object> mapTargetProp = (Map<String, Object>) targetProperty;

                        for (Map.Entry<String, ?> mapSourceEntry : mapSourceProp.entrySet()) {
                            if (!mapTargetProp.containsKey(mapSourceEntry.getKey())) {
                                mapTargetProp.put(mapSourceEntry.getKey(), mapSourceEntry.getValue());
                                changed = true;
                            }
                        }
                    } else if (targetProperty instanceof Collection && sourceProperty.getValue() instanceof Collection) {
                        // merge Collections like "lists"
                        if (ControlGroupPersonalizationStrategy.PERSONALIZATION_STRATEGY_STATUS.equals(sourceProperty.getKey())) {
                            // Special handling for personalization strategy statuses
                            // TODO UNOMI-719: move this in a dedicated extension point to handle this kind of merge strategy in a more generic way
                            List<Map<String, Object>> sourceStatuses = (List<Map<String, Object>>) sourceProperty.getValue();
                            List<Map<String, Object>> targetStatuses = (List<Map<String, Object>>) targetProperty;

                            for (Map<String, Object> sourceStatus : sourceStatuses) {
                                if (targetStatuses
                                        .stream()
                                        .noneMatch(targetStatus -> targetStatus.get(ControlGroupPersonalizationStrategy.PERSONALIZATION_STRATEGY_STATUS_ID)
                                                .equals(sourceStatus.get(ControlGroupPersonalizationStrategy.PERSONALIZATION_STRATEGY_STATUS_ID)))) {
                                    // there is no existing status for the status ID, we can safely add it to master
                                    targetStatuses.add(sourceStatus);
                                    changed = true;
                                }
                            }
                        } else {
                            Collection sourceCollection = (Collection) sourceProperty.getValue();
                            Collection targetCollection = (Collection) targetProperty;

                            for (Object sourceItem : sourceCollection) {
                                if (!targetCollection.contains(sourceItem)) {
                                    try {
                                        targetCollection.add(sourceItem);
                                        changed = true;
                                    } catch (Exception e) {
                                        // may be Collection type issue
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        return changed;
    }