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 ee8ef35  [SYNCOPE-1508] PullActions and PropagationActions extended
ee8ef35 is described below

commit ee8ef35a22bcbcc916c19b9f7efa18a58c264ea9
Author: Francesco Chicchiriccò <[email protected]>
AuthorDate: Mon Nov 4 15:08:06 2019 +0100

    [SYNCOPE-1508] PullActions and PropagationActions extended
---
 .../implementations/MyPropagationActions.groovy    | 14 +++++
 .../console/implementations/MyPullActions.groovy   | 16 +++++-
 .../syncope/core/logic/ReconciliationLogic.java    |  4 +-
 .../apache/syncope/core/logic/ResourceLogic.java   |  4 +-
 .../api/propagation/PropagationActions.java        | 47 ++++++++++++++++
 .../provisioning/api/pushpull/PullActions.java     | 27 ++++++++-
 .../AbstractPropagationTaskExecutor.java           | 50 ++++++++++-------
 .../pushpull/DefaultUserPushResultHandler.java     |  7 ++-
 .../java/pushpull/OutboundMatcher.java             | 64 ++++++++++++++++------
 .../java/pushpull/PullJobDelegate.java             | 15 ++++-
 .../java/pushpull/SinglePullJobDelegate.java       |  8 ++-
 11 files changed, 211 insertions(+), 45 deletions(-)

diff --git 
a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/implementations/MyPropagationActions.groovy
 
b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/implementations/MyPropagationActions.groovy
index 6a24777..6f58ce0 100644
--- 
a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/implementations/MyPropagationActions.groovy
+++ 
b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/implementations/MyPropagationActions.groovy
@@ -18,6 +18,10 @@
  * under the License.
  */
 import groovy.transform.CompileStatic
+import java.util.Collections
+import java.util.Set
+import org.apache.syncope.core.persistence.api.entity.resource.OrgUnit
+import org.apache.syncope.core.persistence.api.entity.resource.Provision
 import org.apache.syncope.core.persistence.api.entity.task.PropagationTask
 import org.apache.syncope.core.persistence.api.entity.task.TaskExec
 import org.apache.syncope.core.provisioning.api.propagation.PropagationActions
@@ -27,6 +31,16 @@ import 
org.identityconnectors.framework.common.objects.ConnectorObject
 class MyPropagationActions implements PropagationActions {
   
   @Override
+  Set<String> moreAttrsToGet(PropagationTask task, OrgUnit orgUnit) {
+    return Collections.emptySet();
+  }
+
+  @Override
+  Set<String> moreAttrsToGet(PropagationTask task, Provision provision) {
+    return Collections.emptySet();
+  }
+
+  @Override
   void before(PropagationTask task, ConnectorObject beforeObj) {
     // do nothing
   }
diff --git 
a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/implementations/MyPullActions.groovy
 
b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/implementations/MyPullActions.groovy
index ce039eb..9cd64e1 100644
--- 
a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/implementations/MyPullActions.groovy
+++ 
b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/implementations/MyPullActions.groovy
@@ -17,10 +17,14 @@
  * under the License.
  */
 import groovy.transform.CompileStatic
+import java.util.Set
 import org.apache.syncope.common.lib.request.AnyCR
 import org.apache.syncope.common.lib.request.AnyUR
-import org.apache.syncope.common.lib.to.EntityTO
+import org.apache.syncope.common.lib.to.LinkedAccountTO
 import org.apache.syncope.common.lib.to.RealmTO
+import org.apache.syncope.common.lib.to.EntityTO
+import org.apache.syncope.core.persistence.api.entity.resource.OrgUnit
+import org.apache.syncope.core.persistence.api.entity.resource.Provision
 import org.apache.syncope.core.persistence.api.entity.task.ProvisioningTask
 import 
org.apache.syncope.core.provisioning.api.pushpull.IgnoreProvisionException
 import org.apache.syncope.core.provisioning.api.pushpull.ProvisioningActions
@@ -32,6 +36,16 @@ import org.quartz.JobExecutionException
 
 @CompileStatic
 class MyPullActions implements PullActions {
+
+  @Override
+  Set<String> moreAttrsToGet(ProvisioningProfile profile, OrgUnit orgUnit) {
+    return Set.of();
+  }
+
+  @Override
+  Set<String> moreAttrsToGet(ProvisioningProfile profile, Provision provision) 
{
+    return Set.of();
+  }
   
   @Override
   SyncDelta preprocess(ProvisioningProfile profile, SyncDelta delta) {
diff --git 
a/core/idm/logic/src/main/java/org/apache/syncope/core/logic/ReconciliationLogic.java
 
b/core/idm/logic/src/main/java/org/apache/syncope/core/logic/ReconciliationLogic.java
index 490864f..ba2c522 100644
--- 
a/core/idm/logic/src/main/java/org/apache/syncope/core/logic/ReconciliationLogic.java
+++ 
b/core/idm/logic/src/main/java/org/apache/syncope/core/logic/ReconciliationLogic.java
@@ -199,7 +199,9 @@ public class ReconciliationLogic extends 
AbstractTransactionalLogic<EntityTO> {
                     connFactory.getConnector(provision.getResource()),
                     connObjectKeyItem,
                     query.getConnObjectKeyValue(),
-                    provision).
+                    provision,
+                    Optional.empty(),
+                    Optional.empty()).
                     ifPresent(connObj -> {
                         
status.setOnResource(ConnObjectUtils.getConnObjectTO(connObj.getAttributes()));
 
diff --git 
a/core/idm/logic/src/main/java/org/apache/syncope/core/logic/ResourceLogic.java 
b/core/idm/logic/src/main/java/org/apache/syncope/core/logic/ResourceLogic.java
index ca512cb..51b1bc6 100644
--- 
a/core/idm/logic/src/main/java/org/apache/syncope/core/logic/ResourceLogic.java
+++ 
b/core/idm/logic/src/main/java/org/apache/syncope/core/logic/ResourceLogic.java
@@ -332,7 +332,9 @@ public class ResourceLogic extends 
AbstractTransactionalLogic<ResourceTO> {
                 connFactory.getConnector(provision.getResource()),
                 connObjectKeyItem,
                 connObjectKeyValue,
-                provision);
+                provision,
+                Optional.empty(),
+                Optional.empty());
         if (connObj.isPresent()) {
             return 
ConnObjectUtils.getConnObjectTO(connObj.get().getAttributes());
         }
diff --git 
a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/propagation/PropagationActions.java
 
b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/propagation/PropagationActions.java
index d21edea..9f4c40f 100644
--- 
a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/propagation/PropagationActions.java
+++ 
b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/propagation/PropagationActions.java
@@ -18,20 +18,67 @@
  */
 package org.apache.syncope.core.provisioning.api.propagation;
 
+import java.util.Set;
+import org.apache.syncope.core.persistence.api.entity.resource.OrgUnit;
+import org.apache.syncope.core.persistence.api.entity.resource.Provision;
 import org.apache.syncope.core.persistence.api.entity.task.PropagationTask;
 import org.apache.syncope.core.persistence.api.entity.task.TaskExec;
 import org.identityconnectors.framework.common.objects.ConnectorObject;
 
 public interface PropagationActions {
 
+    /**
+     * Return additional attributes to include in the result from the 
underlying connector.
+     *
+     * @param task propagation task
+     * @param orgUnit Realm provisioning information
+     * @return additional attributes to include in the result from the 
underlying connector
+     */
+    default Set<String> moreAttrsToGet(PropagationTask task, OrgUnit orgUnit) {
+        return Set.of();
+    }
+
+    /**
+     * Return additional attributes to include in the result from the 
underlying connector.
+     *
+     * @param task propagation task
+     * @param provision Any provisioning information
+     * @return additional attributes to include in the result from the 
underlying connector
+     */
+    default Set<String> moreAttrsToGet(PropagationTask task, Provision 
provision) {
+        return Set.of();
+    }
+
+    /**
+     * Executes logic before actual propagation.
+     *
+     * @param task propagation task
+     * @param beforeObj connector object read before propagation
+     */
     default void before(PropagationTask task, ConnectorObject beforeObj) {
         // do nothing
     }
 
+    /**
+     * Executes logic in case of propagation error.
+     * This method can throw {@link 
org.apache.syncope.core.provisioning.api.pushpull.IgnoreProvisionException} to
+     * ignore the reported error and continue.
+     *
+     * @param task propagation task
+     * @param execution execution result
+     * @param error propagation error
+     */
     default void onError(PropagationTask task, TaskExec execution, Exception 
error) {
         // do nothing
     }
 
+    /**
+     * Executes logic after actual propagation.
+     *
+     * @param task propagation task
+     * @param execution execution result
+     * @param afterObj connector object read after propagation
+     */
     default void after(PropagationTask task, TaskExec execution, 
ConnectorObject afterObj) {
         // do nothing
     }
diff --git 
a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/PullActions.java
 
b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/PullActions.java
index a9e93ca..ae97ff1 100644
--- 
a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/PullActions.java
+++ 
b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/PullActions.java
@@ -18,11 +18,14 @@
  */
 package org.apache.syncope.core.provisioning.api.pushpull;
 
+import java.util.Set;
 import org.apache.syncope.common.lib.request.AnyCR;
 import org.apache.syncope.common.lib.request.AnyUR;
-import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.syncope.common.lib.to.LinkedAccountTO;
 import org.apache.syncope.common.lib.to.RealmTO;
+import org.apache.syncope.common.lib.to.EntityTO;
+import org.apache.syncope.core.persistence.api.entity.resource.OrgUnit;
+import org.apache.syncope.core.persistence.api.entity.resource.Provision;
 import org.identityconnectors.framework.common.objects.SyncDelta;
 import org.quartz.JobExecutionException;
 
@@ -34,6 +37,28 @@ import org.quartz.JobExecutionException;
 public interface PullActions extends ProvisioningActions {
 
     /**
+     * Return additional attributes to include in the result from the 
underlying connector.
+     *
+     * @param profile profile of the pull being executed.
+     * @param orgUnit Realm provisioning information
+     * @return additional attributes to include in the result from the 
underlying connector
+     */
+    default Set<String> moreAttrsToGet(ProvisioningProfile<?, ?> profile, 
OrgUnit orgUnit) {
+        return Set.of();
+    }
+
+    /**
+     * Return additional attributes to include in the result from the 
underlying connector.
+     *
+     * @param profile profile of the pull being executed.
+     * @param provision Any provisioning information
+     * @return additional attributes to include in the result from the 
underlying connector
+     */
+    default Set<String> moreAttrsToGet(ProvisioningProfile<?, ?> profile, 
Provision provision) {
+        return Set.of();
+    }
+
+    /**
      * Pre-process the pull information received by the underlying connector, 
before any internal activity occurs.
      *
      * @param profile profile of the pull being executed.
diff --git 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/AbstractPropagationTaskExecutor.java
 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/AbstractPropagationTaskExecutor.java
index bbfc20d..aa7bde0 100644
--- 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/AbstractPropagationTaskExecutor.java
+++ 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/AbstractPropagationTaskExecutor.java
@@ -295,28 +295,28 @@ public abstract class AbstractPropagationTaskExecutor 
implements PropagationTask
                 switch (task.getAnyTypeKind()) {
                     case USER:
                         try {
-                            resources = 
userDAO.findAllResourceKeys(task.getEntityKey());
-                        } catch (Exception e) {
-                            LOG.error("Could not read user {}", 
task.getEntityKey(), e);
-                        }
-                        break;
+                        resources = 
userDAO.findAllResourceKeys(task.getEntityKey());
+                    } catch (Exception e) {
+                        LOG.error("Could not read user {}", 
task.getEntityKey(), e);
+                    }
+                    break;
 
                     case GROUP:
                         try {
-                            resources = 
groupDAO.findAllResourceKeys(task.getEntityKey());
-                        } catch (Exception e) {
-                            LOG.error("Could not read group {}", 
task.getEntityKey(), e);
-                        }
-                        break;
+                        resources = 
groupDAO.findAllResourceKeys(task.getEntityKey());
+                    } catch (Exception e) {
+                        LOG.error("Could not read group {}", 
task.getEntityKey(), e);
+                    }
+                    break;
 
                     case ANY_OBJECT:
                     default:
                         try {
-                            resources = 
anyObjectDAO.findAllResourceKeys(task.getEntityKey());
-                        } catch (Exception e) {
-                            LOG.error("Could not read any object {}", 
task.getEntityKey(), e);
-                        }
-                        break;
+                        resources = 
anyObjectDAO.findAllResourceKeys(task.getEntityKey());
+                    } catch (Exception e) {
+                        LOG.error("Could not read any object {}", 
task.getEntityKey(), e);
+                    }
+                    break;
                 }
             }
             if (task.getAnyTypeKind() == null || 
!resources.contains(task.getResource().getKey())) {
@@ -394,8 +394,8 @@ public abstract class AbstractPropagationTaskExecutor 
implements PropagationTask
                 beforeObj = provision == null && orgUnit == null
                         ? null
                         : orgUnit == null
-                                ? getRemoteObject(task, connector, provision, 
false)
-                                : getRemoteObject(task, connector, orgUnit, 
false);
+                                ? getRemoteObject(task, connector, provision, 
actions, false)
+                                : getRemoteObject(task, connector, orgUnit, 
actions, false);
             } else if (taskInfo.getBeforeObj().isPresent()) {
                 beforeObj = taskInfo.getBeforeObj().get();
             }
@@ -462,8 +462,8 @@ public abstract class AbstractPropagationTaskExecutor 
implements PropagationTask
                     afterObj = provision == null && orgUnit == null
                             ? null
                             : orgUnit == null
-                                    ? getRemoteObject(task, connector, 
provision, true)
-                                    : getRemoteObject(task, connector, 
orgUnit, true);
+                                    ? getRemoteObject(task, connector, 
provision, actions, true)
+                                    : getRemoteObject(task, connector, 
orgUnit, actions, true);
                 } catch (Exception ignore) {
                     // ignore exception
                     LOG.error("Error retrieving after object", ignore);
@@ -608,6 +608,7 @@ public abstract class AbstractPropagationTaskExecutor 
implements PropagationTask
      * @param connector connector facade proxy.
      * @param task current propagation task.
      * @param provision provision
+     * @param actions propagation actions
      * @param latest 'FALSE' to retrieve object using old connObjectKey if not 
null.
      * @return remote connector object.
      */
@@ -615,13 +616,14 @@ public abstract class AbstractPropagationTaskExecutor 
implements PropagationTask
             final PropagationTask task,
             final Connector connector,
             final Provision provision,
+            final List<PropagationActions> actions,
             final boolean latest) {
 
         String connObjectKeyValue = latest || task.getOldConnObjectKey() == 
null
                 ? task.getConnObjectKey()
                 : task.getOldConnObjectKey();
 
-        List<ConnectorObject> matches = outboundMatcher.match(task, connector, 
provision, connObjectKeyValue);
+        List<ConnectorObject> matches = outboundMatcher.match(task, connector, 
provision, actions, connObjectKeyValue);
         LOG.debug("Found for propagation task {}: {}", task, matches);
 
         return matches.isEmpty() ? null : matches.get(0);
@@ -633,6 +635,7 @@ public abstract class AbstractPropagationTaskExecutor 
implements PropagationTask
      * @param connector connector facade proxy.
      * @param task current propagation task.
      * @param orgUnit orgUnit
+     * @param actions propagation actions
      * @param latest 'FALSE' to retrieve object using old connObjectKey if not 
null.
      * @return remote connector object.
      */
@@ -640,12 +643,16 @@ public abstract class AbstractPropagationTaskExecutor 
implements PropagationTask
             final PropagationTask task,
             final Connector connector,
             final OrgUnit orgUnit,
+            final List<PropagationActions> actions,
             final boolean latest) {
 
         String connObjectKey = latest || task.getOldConnObjectKey() == null
                 ? task.getConnObjectKey()
                 : task.getOldConnObjectKey();
 
+        Set<String> moreAttrsToGet = new HashSet<>();
+        actions.forEach(action -> 
moreAttrsToGet.addAll(action.moreAttrsToGet(task, orgUnit)));
+
         ConnectorObject obj = null;
         Optional<? extends OrgUnitItem> connObjectKeyItem = 
orgUnit.getConnObjectKeyItem();
         if (connObjectKeyItem.isPresent()) {
@@ -655,7 +662,8 @@ public abstract class AbstractPropagationTaskExecutor 
implements PropagationTask
                         
AttributeBuilder.build(connObjectKeyItem.get().getExtAttrName(), connObjectKey),
                         orgUnit.isIgnoreCaseMatch(),
                         MappingUtils.buildOperationOptions(
-                                
MappingUtils.getPropagationItems(orgUnit.getItems().stream())));
+                                
MappingUtils.getPropagationItems(orgUnit.getItems().stream()),
+                                moreAttrsToGet.toArray(new String[0])));
             } catch (TimeoutException toe) {
                 LOG.debug("Request timeout", toe);
                 throw toe;
diff --git 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultUserPushResultHandler.java
 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultUserPushResultHandler.java
index d7060c3..a34bc6b 100644
--- 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultUserPushResultHandler.java
+++ 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/DefaultUserPushResultHandler.java
@@ -222,7 +222,12 @@ public class DefaultUserPushResultHandler extends 
AbstractPushResultHandler impl
         // Try to read remote object BEFORE any actual operation
         Optional<ConnectorObject> connObj = 
MappingUtils.getConnObjectKeyItem(provision).
                 map(connObjectKeyItem -> 
outboundMatcher.matchByConnObjectKeyValue(
-                profile.getConnector(), connObjectKeyItem, 
account.getConnObjectKeyValue(), provision)).
+                profile.getConnector(),
+                connObjectKeyItem,
+                account.getConnObjectKeyValue(),
+                provision,
+                Optional.empty(),
+                Optional.empty())).
                 orElse(Optional.empty());
         LOG.debug("Match found for linked account {} as {}: {}", account, 
provision.getObjectClass(), connObj);
 
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 e206ca8..6e98595 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
@@ -19,8 +19,12 @@
 package org.apache.syncope.core.provisioning.java.pushpull;
 
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Optional;
+import java.util.Set;
 import java.util.stream.Stream;
 import org.apache.commons.lang3.ArrayUtils;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
@@ -39,6 +43,7 @@ import org.apache.syncope.core.provisioning.api.Connector;
 import org.apache.syncope.core.provisioning.api.MappingManager;
 import org.apache.syncope.core.provisioning.api.TimeoutException;
 import org.apache.syncope.core.provisioning.api.VirAttrHandler;
+import org.apache.syncope.core.provisioning.api.propagation.PropagationActions;
 import org.apache.syncope.core.provisioning.java.utils.MappingUtils;
 import org.apache.syncope.core.spring.ImplementationManager;
 import org.identityconnectors.framework.common.objects.AttributeBuilder;
@@ -93,6 +98,7 @@ public class OutboundMatcher {
             final PropagationTask task,
             final Connector connector,
             final Provision provision,
+            final List<PropagationActions> actions,
             final String connObjectKeyValue) {
 
         Optional<PushCorrelationRule> rule = rule(provision);
@@ -104,14 +110,27 @@ public class OutboundMatcher {
             any = 
anyUtilsFactory.getInstance(task.getAnyTypeKind()).dao().find(task.getEntityKey());
         }
 
+        Set<String> moreAttrsToGet = new HashSet<>();
+        actions.forEach(action -> 
moreAttrsToGet.addAll(action.moreAttrsToGet(task, provision)));
+
         List<ConnectorObject> result = new ArrayList<>();
         try {
             if (any != null && rule.isPresent()) {
-                result.addAll(matchByCorrelationRule(connector, 
rule.get().getFilter(any, provision), provision));
+                result.addAll(matchByCorrelationRule(
+                        connector,
+                        rule.get().getFilter(any, provision),
+                        provision,
+                        Optional.empty(),
+                        Optional.of(moreAttrsToGet.toArray(new String[0]))));
             } else {
-                
MappingUtils.getConnObjectKeyItem(provision).ifPresent(connObjectKeyItem
-                        -> matchByConnObjectKeyValue(connector, 
connObjectKeyItem, connObjectKeyValue, provision).
-                                ifPresent(result::add));
+                
MappingUtils.getConnObjectKeyItem(provision).ifPresent(connObjectKeyItem -> 
matchByConnObjectKeyValue(
+                        connector,
+                        connObjectKeyItem,
+                        connObjectKeyValue,
+                        provision,
+                        Optional.empty(),
+                        Optional.of(moreAttrsToGet.toArray(new String[0]))).
+                        ifPresent(result::add));
             }
         } catch (RuntimeException e) {
             LOG.error("Could not match {} with any existing {}", any, 
provision.getObjectClass(), e);
@@ -137,14 +156,25 @@ public class OutboundMatcher {
         try {
             if (rule.isPresent()) {
                 result.addAll(matchByCorrelationRule(
-                        connector, rule.get().getFilter(any, provision), 
provision, linkingItems));
+                        connector,
+                        rule.get().getFilter(any, provision),
+                        provision,
+                        ArrayUtils.isEmpty(linkingItems)
+                        ? Optional.empty() : 
Optional.of(Arrays.asList(linkingItems)),
+                        Optional.empty()));
             } else {
                 Optional<? extends MappingItem> connObjectKeyItem = 
MappingUtils.getConnObjectKeyItem(provision);
                 Optional<String> connObjectKeyValue = 
mappingManager.getConnObjectKeyValue(any, provision);
 
                 if (connObjectKeyItem.isPresent() && 
connObjectKeyValue.isPresent()) {
                     matchByConnObjectKeyValue(
-                            connector, connObjectKeyItem.get(), 
connObjectKeyValue.get(), provision, linkingItems).
+                            connector,
+                            connObjectKeyItem.get(),
+                            connObjectKeyValue.get(),
+                            provision,
+                            ArrayUtils.isEmpty(linkingItems)
+                            ? Optional.empty() : 
Optional.of(Arrays.asList(linkingItems)),
+                            Optional.empty()).
                             ifPresent(result::add);
                 }
             }
@@ -163,13 +193,14 @@ public class OutboundMatcher {
             final Connector connector,
             final Filter filter,
             final Provision provision,
-            final LinkingMappingItem... linkingItems) {
+            final Optional<Collection<LinkingMappingItem>> linkingItems,
+            final Optional<String[]> moreAttrsToGet) {
 
         Stream<MappingItem> items = Stream.concat(
                 provision.getMapping().getItems().stream(),
-                ArrayUtils.isEmpty(linkingItems)
-                ? 
virSchemaDAO.findByProvision(provision).stream().map(VirSchema::asLinkingMappingItem)
-                : Stream.of(linkingItems));
+                linkingItems.isPresent()
+                ? linkingItems.get().stream()
+                : 
virSchemaDAO.findByProvision(provision).stream().map(VirSchema::asLinkingMappingItem));
 
         List<ConnectorObject> objs = new ArrayList<>();
         try {
@@ -185,7 +216,7 @@ public class OutboundMatcher {
                     objs.add(connectorObject);
                     return true;
                 }
-            }, MappingUtils.buildOperationOptions(items));
+            }, MappingUtils.buildOperationOptions(items, 
moreAttrsToGet.orElse(null)));
         } catch (TimeoutException toe) {
             LOG.debug("Request timeout", toe);
             throw toe;
@@ -202,13 +233,14 @@ public class OutboundMatcher {
             final MappingItem connObjectKeyItem,
             final String connObjectKeyValue,
             final Provision provision,
-            final LinkingMappingItem... linkingItems) {
+            final Optional<Collection<LinkingMappingItem>> linkingItems,
+            final Optional<String[]> moreAttrsToGet) {
 
         Stream<MappingItem> items = Stream.concat(
                 provision.getMapping().getItems().stream(),
-                ArrayUtils.isEmpty(linkingItems)
-                ? 
virSchemaDAO.findByProvision(provision).stream().map(VirSchema::asLinkingMappingItem)
-                : Stream.of(linkingItems));
+                linkingItems.isPresent()
+                ? linkingItems.get().stream()
+                : 
virSchemaDAO.findByProvision(provision).stream().map(VirSchema::asLinkingMappingItem));
 
         ConnectorObject obj = null;
         try {
@@ -216,7 +248,7 @@ public class OutboundMatcher {
                     provision.getObjectClass(),
                     AttributeBuilder.build(connObjectKeyItem.getExtAttrName(), 
connObjectKeyValue),
                     provision.isIgnoreCaseMatch(),
-                    MappingUtils.buildOperationOptions(items));
+                    MappingUtils.buildOperationOptions(items, 
moreAttrsToGet.orElse(null)));
         } catch (TimeoutException toe) {
             LOG.debug("Request timeout", toe);
             throw toe;
diff --git 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullJobDelegate.java
 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullJobDelegate.java
index 3f87d55..6ddcca0 100644
--- 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullJobDelegate.java
+++ 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/PullJobDelegate.java
@@ -20,9 +20,11 @@ package org.apache.syncope.core.provisioning.java.pushpull;
 
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
+import java.util.Set;
 import java.util.stream.Stream;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.types.ConflictResolutionAction;
@@ -217,8 +219,12 @@ public class PullJobDelegate extends 
AbstractProvisioningJobDelegate<PullTask> i
             status.set("Pulling " + 
pullTask.getResource().getOrgUnit().getObjectClass().getObjectClassValue());
 
             OrgUnit orgUnit = pullTask.getResource().getOrgUnit();
+
+            Set<String> moreAttrsToGet = new HashSet<>();
+            actions.forEach(action -> 
moreAttrsToGet.addAll(action.moreAttrsToGet(profile, orgUnit)));
+
             OperationOptions options = MappingUtils.buildOperationOptions(
-                    MappingUtils.getPullItems(orgUnit.getItems().stream()));
+                    MappingUtils.getPullItems(orgUnit.getItems().stream()), 
moreAttrsToGet.toArray(new String[0]));
 
             RealmPullResultHandler handler = buildRealmHandler();
             handler.setProfile(profile);
@@ -288,10 +294,15 @@ public class PullJobDelegate extends 
AbstractProvisioningJobDelegate<PullTask> i
                 handler.setPullExecutor(this);
 
                 try {
+                    Set<String> moreAttrsToGet = new HashSet<>();
+                    actions.forEach(action -> 
moreAttrsToGet.addAll(action.moreAttrsToGet(profile, provision)));
+
                     Stream<? extends Item> mapItems = Stream.concat(
                             
MappingUtils.getPullItems(provision.getMapping().getItems().stream()),
                             
virSchemaDAO.findByProvision(provision).stream().map(VirSchema::asLinkingMappingItem));
-                    OperationOptions options = 
MappingUtils.buildOperationOptions(mapItems);
+
+                    OperationOptions options = 
MappingUtils.buildOperationOptions(
+                            mapItems, moreAttrsToGet.toArray(new String[0]));
 
                     switch (pullTask.getPullMode()) {
                         case INCREMENTAL:
diff --git 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/SinglePullJobDelegate.java
 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/SinglePullJobDelegate.java
index 154fe5f..02abde5 100644
--- 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/SinglePullJobDelegate.java
+++ 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/SinglePullJobDelegate.java
@@ -19,7 +19,9 @@
 package org.apache.syncope.core.provisioning.java.pushpull;
 
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 import java.util.stream.Stream;
 import org.apache.syncope.common.lib.to.PullTaskTO;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
@@ -149,14 +151,18 @@ public class SinglePullJobDelegate extends 
PullJobDelegate implements SyncopeSin
             handler.setPullExecutor(this);
 
             // execute filtered pull
+            Set<String> moreAttrsToGet = new HashSet<>();
+            actions.forEach(action -> 
moreAttrsToGet.addAll(action.moreAttrsToGet(profile, provision)));
+
             Stream<? extends Item> mapItems = Stream.concat(
                     
MappingUtils.getPullItems(provision.getMapping().getItems().stream()),
                     
virSchemaDAO.findByProvision(provision).stream().map(VirSchema::asLinkingMappingItem));
+
             connector.filteredReconciliation(
                     provision.getObjectClass(),
                     new AccountReconciliationFilterBuilder(connObjectKey, 
connObjectValue),
                     handler,
-                    MappingUtils.buildOperationOptions(mapItems));
+                    MappingUtils.buildOperationOptions(mapItems, 
moreAttrsToGet.toArray(new String[0])));
 
             try {
                 setGroupOwners(ghandler);

Reply via email to