This is an automated email from the ASF dual-hosted git repository.

ilgrosso pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/syncope.git


The following commit(s) were added to refs/heads/master by this push:
     new eb6ac66e2a Adjusting Realm propagation
eb6ac66e2a is described below

commit eb6ac66e2a4ec5d9cd9ded587689c88e2844d0ae
Author: Francesco Chicchiriccò <[email protected]>
AuthorDate: Mon Dec 1 15:46:32 2025 +0100

    Adjusting Realm propagation
---
 .../api/rules/PushCorrelationRule.java             |  8 +--
 .../core/provisioning/java/data/AnyDataBinder.java | 28 ----------
 .../java/data/AttributableDataBinder.java          | 31 +++++++++++
 .../java/data/RealmDataBinderImpl.java             | 60 +++++++++++++++++-----
 .../java/pushpull/DefaultPushCorrelationRule.java  |  4 +-
 .../java/pushpull/OutboundMatcher.java             |  2 +-
 .../core/provisioning/java/utils/MappingUtils.java |  6 +--
 7 files changed, 87 insertions(+), 52 deletions(-)

diff --git 
a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/rules/PushCorrelationRule.java
 
b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/rules/PushCorrelationRule.java
index 8700509985..a614b50990 100644
--- 
a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/rules/PushCorrelationRule.java
+++ 
b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/rules/PushCorrelationRule.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.core.provisioning.api.rules;
 
-import java.util.function.BiFunction;
+import java.util.function.Function;
 import org.apache.syncope.common.lib.policy.PushCorrelationRuleConf;
 import org.apache.syncope.common.lib.to.Provision;
 import org.apache.syncope.core.persistence.api.entity.Any;
@@ -36,8 +36,8 @@ public interface PushCorrelationRule {
     /**
      * Default FIQL builder using __UID__.
      */
-    BiFunction<ConnectorObject, Provision, String> DEFAULT_FIQL_BUILDER =
-            (connectorObject, provision) -> Uid.NAME + "==" + 
connectorObject.getUid().getUidValue();
+    Function<ConnectorObject, String> DEFAULT_FIQL_BUILDER =
+            connectorObject -> Uid.NAME + "==" + 
connectorObject.getUid().getUidValue();
 
     default void setConf(PushCorrelationRuleConf conf) {
     }
@@ -62,6 +62,6 @@ public interface PushCorrelationRule {
      * @return fiql
      */
     default String getFIQL(ConnectorObject connectorObject, Provision 
provision) {
-        return DEFAULT_FIQL_BUILDER.apply(connectorObject, provision);
+        return DEFAULT_FIQL_BUILDER.apply(connectorObject);
     }
 }
diff --git 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyDataBinder.java
 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyDataBinder.java
index e46db5fe01..c14fcec373 100644
--- 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyDataBinder.java
+++ 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyDataBinder.java
@@ -47,7 +47,6 @@ import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.AttrSchemaType;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
 import org.apache.syncope.common.lib.types.PatchOperation;
-import org.apache.syncope.common.lib.types.ResourceOperation;
 import 
org.apache.syncope.core.persistence.api.attrvalue.PlainAttrValidationManager;
 import org.apache.syncope.core.persistence.api.dao.AllowedSchemas;
 import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
@@ -82,7 +81,6 @@ import org.apache.syncope.core.provisioning.api.IntAttrName;
 import org.apache.syncope.core.provisioning.api.IntAttrNameParser;
 import org.apache.syncope.core.provisioning.api.MappingManager;
 import org.apache.syncope.core.provisioning.api.PlainAttrGetter;
-import org.apache.syncope.core.provisioning.api.PropagationByResource;
 import org.apache.syncope.core.provisioning.api.jexl.JexlTools;
 import org.apache.syncope.core.provisioning.java.pushpull.OutboundMatcher;
 import org.apache.syncope.core.provisioning.java.utils.ConnObjectUtils;
@@ -505,32 +503,6 @@ abstract class AnyDataBinder extends 
AttributableDataBinder {
         }
     }
 
-    protected PropagationByResource<String> propByRes(
-            final Map<String, ConnObject> before,
-            final Map<String, ConnObject> after) {
-
-        PropagationByResource<String> propByRes = new 
PropagationByResource<>();
-
-        after.forEach((resource, connObject) -> {
-            if (before.containsKey(resource)) {
-                ConnObject beforeObject = before.get(resource);
-                if (!beforeObject.equals(connObject)) {
-                    propByRes.add(ResourceOperation.UPDATE, resource);
-
-                    beforeObject.getAttr(Uid.NAME).map(attr -> 
attr.getValues().getFirst()).
-                            ifPresent(value -> 
propByRes.addOldConnObjectKey(resource, value));
-                }
-            } else {
-                propByRes.add(ResourceOperation.CREATE, resource);
-            }
-        });
-        propByRes.addAll(
-                ResourceOperation.DELETE,
-                before.keySet().stream().filter(resource -> 
!after.containsKey(resource)).collect(Collectors.toSet()));
-
-        return propByRes;
-    }
-
     protected void fill(
             final AnyTO anyTO,
             final Any any,
diff --git 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AttributableDataBinder.java
 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AttributableDataBinder.java
index eac3acf877..8480cade31 100644
--- 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AttributableDataBinder.java
+++ 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AttributableDataBinder.java
@@ -22,9 +22,12 @@ import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Collectors;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.to.AttributableTO;
+import org.apache.syncope.common.lib.to.ConnObject;
+import org.apache.syncope.common.lib.types.ResourceOperation;
 import org.apache.syncope.core.persistence.api.attrvalue.DropdownValueProvider;
 import 
org.apache.syncope.core.persistence.api.attrvalue.InvalidPlainAttrValueException;
 import 
org.apache.syncope.core.persistence.api.attrvalue.PlainAttrValidationManager;
@@ -35,8 +38,10 @@ import 
org.apache.syncope.core.persistence.api.entity.PlainSchema;
 import org.apache.syncope.core.provisioning.api.DerAttrHandler;
 import org.apache.syncope.core.provisioning.api.IntAttrNameParser;
 import org.apache.syncope.core.provisioning.api.MappingManager;
+import org.apache.syncope.core.provisioning.api.PropagationByResource;
 import org.apache.syncope.core.provisioning.api.jexl.JexlTools;
 import org.apache.syncope.core.spring.implementation.ImplementationManager;
+import org.identityconnectors.framework.common.objects.Uid;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -169,4 +174,30 @@ abstract class AttributableDataBinder {
             }
         });
     }
+
+    protected PropagationByResource<String> propByRes(
+            final Map<String, ConnObject> before,
+            final Map<String, ConnObject> after) {
+
+        PropagationByResource<String> propByRes = new 
PropagationByResource<>();
+
+        after.forEach((resource, connObject) -> {
+            if (before.containsKey(resource)) {
+                ConnObject beforeObject = before.get(resource);
+                if (!beforeObject.equals(connObject)) {
+                    propByRes.add(ResourceOperation.UPDATE, resource);
+
+                    beforeObject.getAttr(Uid.NAME).map(attr -> 
attr.getValues().getFirst()).
+                            ifPresent(value -> 
propByRes.addOldConnObjectKey(resource, value));
+                }
+            } else {
+                propByRes.add(ResourceOperation.CREATE, resource);
+            }
+        });
+        propByRes.addAll(
+                ResourceOperation.DELETE,
+                before.keySet().stream().filter(resource -> 
!after.containsKey(resource)).collect(Collectors.toSet()));
+
+        return propByRes;
+    }
 }
diff --git 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/RealmDataBinderImpl.java
 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/RealmDataBinderImpl.java
index 2e3de205da..ab9572e14c 100644
--- 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/RealmDataBinderImpl.java
+++ 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/RealmDataBinderImpl.java
@@ -20,15 +20,18 @@ package org.apache.syncope.core.provisioning.java.data;
 
 import java.text.ParseException;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Optional;
+import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.Attr;
 import org.apache.syncope.common.lib.SyncopeClientCompositeException;
 import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.ConnObject;
 import org.apache.syncope.common.lib.to.RealmTO;
 import org.apache.syncope.common.lib.types.AttrSchemaType;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
-import org.apache.syncope.common.lib.types.ResourceOperation;
 import 
org.apache.syncope.core.persistence.api.attrvalue.PlainAttrValidationManager;
 import org.apache.syncope.core.persistence.api.dao.AnyTypeClassDAO;
 import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
@@ -59,7 +62,13 @@ import 
org.apache.syncope.core.provisioning.api.PropagationByResource;
 import org.apache.syncope.core.provisioning.api.data.RealmDataBinder;
 import org.apache.syncope.core.provisioning.api.jexl.JexlTools;
 import org.apache.syncope.core.provisioning.api.jexl.TemplateUtils;
+import org.apache.syncope.core.provisioning.api.rules.PushCorrelationRule;
+import org.apache.syncope.core.provisioning.java.utils.ConnObjectUtils;
 import org.apache.syncope.core.provisioning.java.utils.MappingUtils;
+import org.identityconnectors.framework.common.objects.AttributeBuilder;
+import org.identityconnectors.framework.common.objects.ConnectorObject;
+import org.identityconnectors.framework.common.objects.ConnectorObjectBuilder;
+import org.identityconnectors.framework.common.objects.Uid;
 
 public class RealmDataBinderImpl extends AttributableDataBinder implements 
RealmDataBinder {
 
@@ -281,36 +290,59 @@ public class RealmDataBinderImpl extends 
AttributableDataBinder implements Realm
         return realm;
     }
 
+    protected Map<String, ConnObject> onResources(final Realm realm) {
+        Map<String, ConnObject> onResources = new HashMap<>();
+
+        realm.getResources().forEach(resource -> 
Optional.ofNullable(resource.getOrgUnit()).
+                ifPresent(orgUnit -> 
orgUnit.getConnObjectKeyItem().ifPresent(keyItem -> {
+
+            MappingManager.PreparedAttrs prepared = 
mappingManager.prepareAttrsFromRealm(realm, resource);
+
+            ConnObject connObjectTO;
+            if (StringUtils.isBlank(prepared.connObjectLink())) {
+                connObjectTO = ConnObjectUtils.getConnObjectTO(null, 
prepared.attributes());
+            } else {
+                ConnectorObject connectorObject = new ConnectorObjectBuilder().
+                        addAttributes(prepared.attributes()).
+                        addAttribute(new Uid(prepared.connObjectLink())).
+                        
addAttribute(AttributeBuilder.build(keyItem.getExtAttrName(), 
prepared.connObjectLink())).
+                        build();
+
+                connObjectTO = ConnObjectUtils.getConnObjectTO(
+                        
PushCorrelationRule.DEFAULT_FIQL_BUILDER.apply(connectorObject),
+                        connectorObject.getAttributes());
+            }
+
+            onResources.put(resource.getKey(), connObjectTO);
+        })));
+
+        return onResources;
+    }
+
     @Override
     public PropagationByResource<String> update(final Realm realm, final 
RealmTO realmTO) {
+        // Save projection on Resources (before update)
+        Map<String, ConnObject> beforeOnResources = onResources(realm);
+
         
realm.setParent(Optional.ofNullable(realmTO.getParent()).flatMap(realmDAO::findById).orElse(null));
 
         SyncopeClientCompositeException scce = 
SyncopeClientException.buildComposite();
 
         bind(realm, realmTO, scce);
 
-        PropagationByResource<String> propByRes = new 
PropagationByResource<>();
         realmTO.getResources().forEach(key -> 
resourceDAO.findById(key).ifPresentOrElse(
-                resource -> {
-                    realm.add(resource);
-                    propByRes.add(ResourceOperation.CREATE, resource.getKey());
-                },
+                realm::add,
                 () -> LOG.debug("Invalid {} {}, ignoring...", 
ExternalResource.class.getSimpleName(), key)));
         // remove all resources not contained in the TO
-        realm.getResources().removeIf(resource -> {
-            boolean contained = 
realmTO.getResources().contains(resource.getKey());
-            if (!contained) {
-                propByRes.add(ResourceOperation.DELETE, resource.getKey());
-            }
-            return !contained;
-        });
+        realm.getResources().removeIf(resource -> 
!realmTO.getResources().contains(resource.getKey()));
 
         SyncopeClientException requiredValuesMissing = 
checkMandatoryOnResources(realm);
         if (!requiredValuesMissing.isEmpty()) {
             scce.addException(requiredValuesMissing);
         }
 
-        return propByRes;
+        // Build final information for next stage (propagation)
+        return propByRes(beforeOnResources, onResources(realm));
     }
 
     @Override
diff --git 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultPushCorrelationRule.java
 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultPushCorrelationRule.java
index 107b96665e..1f6f066c3c 100644
--- 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultPushCorrelationRule.java
+++ 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultPushCorrelationRule.java
@@ -60,8 +60,8 @@ public class DefaultPushCorrelationRule implements 
PushCorrelationRule {
 
     @Override
     public void setConf(final PushCorrelationRuleConf conf) {
-        if (conf instanceof DefaultPushCorrelationRuleConf) {
-            this.conf = DefaultPushCorrelationRuleConf.class.cast(conf);
+        if (conf instanceof final DefaultPushCorrelationRuleConf 
defaultPushCorrelationRuleConf) {
+            this.conf = defaultPushCorrelationRuleConf;
         } else {
             throw new IllegalArgumentException(
                     DefaultPushCorrelationRuleConf.class.getName() + " 
expected, got " + conf.getClass().getName());
diff --git 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/OutboundMatcher.java
 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/OutboundMatcher.java
index c0020ea25e..ebd0157255 100644
--- 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/OutboundMatcher.java
+++ 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/OutboundMatcher.java
@@ -105,7 +105,7 @@ public class OutboundMatcher {
 
         return rule(resource, provision).
                 map(rule -> rule.getFIQL(connectorObject, provision)).
-                orElseGet(() -> 
PushCorrelationRule.DEFAULT_FIQL_BUILDER.apply(connectorObject, provision));
+                orElseGet(() -> 
PushCorrelationRule.DEFAULT_FIQL_BUILDER.apply(connectorObject));
     }
 
     public List<ConnectorObject> match(
diff --git 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/utils/MappingUtils.java
 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/utils/MappingUtils.java
index 79af4dd636..9eb69b097a 100644
--- 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/utils/MappingUtils.java
+++ 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/utils/MappingUtils.java
@@ -29,7 +29,7 @@ import java.util.stream.Stream;
 import org.apache.commons.lang3.ArrayUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.to.Item;
-import org.apache.syncope.common.lib.to.Mapping;
+import org.apache.syncope.common.lib.to.ItemContainer;
 import org.apache.syncope.common.lib.to.Provision;
 import org.apache.syncope.common.lib.types.MappingPurpose;
 import org.apache.syncope.core.persistence.api.ApplicationContextProvider;
@@ -55,8 +55,8 @@ public final class MappingUtils {
     public static Optional<Item> getConnObjectKeyItem(final Provision 
provision) {
         return Optional.ofNullable(provision).
                 flatMap(p -> Optional.ofNullable(p.getMapping())).
-                map(Mapping::getConnObjectKeyItem).
-            orElseGet(Optional::empty);
+                map(ItemContainer::getConnObjectKeyItem).
+                orElseGet(Optional::empty);
     }
 
     public static Stream<Item> getPropagationItems(final Stream<Item> items) {

Reply via email to