[SYNCOPE-1687] Adding prefetch option to PropagationPolicy
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/policies/PropagationPolicyDirectoryPanel.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/policies/PropagationPolicyDirectoryPanel.java
index 8a9a793..058304c 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/policies/PropagationPolicyDirectoryPanel.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/policies/PropagationPolicyDirectoryPanel.java
@@ -19,6 +19,7 @@
 package org.apache.syncope.client.console.policies;
 
 import java.util.List;
+import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.BooleanPropertyColumn;
 import org.apache.syncope.common.lib.policy.PropagationPolicyTO;
 import org.apache.syncope.common.lib.types.IdRepoEntitlement;
 import org.apache.syncope.common.lib.types.PolicyType;
@@ -46,6 +47,7 @@
 
     @Override
     protected void addCustomColumnFields(final List<IColumn<PropagationPolicyTO, String>> columns) {
+        columns.add(new BooleanPropertyColumn<>(new StringResourceModel("prefetch", this), "prefetch", "prefetch"));
         columns.add(new PropertyColumn<>(new StringResourceModel("maxAttempts", this), "maxAttempts", "maxAttempts"));
     }
 }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/PolicyModalPanelBuilder.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/PolicyModalPanelBuilder.java
index f3b8a5e..3bd9da6 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/PolicyModalPanelBuilder.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/PolicyModalPanelBuilder.java
@@ -178,6 +178,12 @@
                     break;
 
                 case PROPAGATION:
+                    fields.add(new AjaxCheckBoxPanel(
+                            "field",
+                            "prefetch",
+                            new PropertyModel<>(policyTO, "prefetch"),
+                            false));
+
                     fields.add(new AjaxSpinnerFieldPanel.Builder<Integer>().build(
                             "field",
                             "maxAttempts",
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/policies/PolicyDirectoryPanel.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/policies/PolicyDirectoryPanel.properties
index 1f1d3dc..98454bb 100644
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/policies/PolicyDirectoryPanel.properties
+++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/policies/PolicyDirectoryPanel.properties
@@ -53,3 +53,4 @@
 unauthorizedRedirectUrl=Unauthorized Redirect URL
 maxAttempts=Max Attempts
 backOffStrategy=BackOff Strategy
+prefetch=Prefetch
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/policies/PolicyDirectoryPanel_fr_CA.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/policies/PolicyDirectoryPanel_fr_CA.properties
index a7858b0..8adddbd 100644
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/policies/PolicyDirectoryPanel_fr_CA.properties
+++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/policies/PolicyDirectoryPanel_fr_CA.properties
@@ -53,3 +53,4 @@
 unauthorizedRedirectUrl=Unauthorized Redirect URL
 maxAttempts=Max Attempts
 backOffStrategy=BackOff Strategy
+prefetch=Prefetch
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/policies/PolicyDirectoryPanel_it.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/policies/PolicyDirectoryPanel_it.properties
index 690c704..99c62d4 100644
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/policies/PolicyDirectoryPanel_it.properties
+++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/policies/PolicyDirectoryPanel_it.properties
@@ -53,3 +53,4 @@
 unauthorizedRedirectUrl=URL di Ridirezione Per Mancata Autorizzazione
 maxAttempts=Tentativi Massimi
 backOffStrategy=Strategia di BackOff
+prefetch=Prefetch
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/policies/PolicyDirectoryPanel_ja.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/policies/PolicyDirectoryPanel_ja.properties
index ebefed5..f167bf3 100644
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/policies/PolicyDirectoryPanel_ja.properties
+++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/policies/PolicyDirectoryPanel_ja.properties
@@ -53,3 +53,4 @@
 unauthorizedRedirectUrl=Unauthorized Redirect URL
 maxAttempts=Max Attempts
 backOffStrategy=BackOff Strategy
+prefetch=Prefetch
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/policies/PolicyDirectoryPanel_pt_BR.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/policies/PolicyDirectoryPanel_pt_BR.properties
index 29e278e..87254c0 100644
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/policies/PolicyDirectoryPanel_pt_BR.properties
+++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/policies/PolicyDirectoryPanel_pt_BR.properties
@@ -53,3 +53,4 @@
 unauthorizedRedirectUrl=Unauthorized Redirect URL
 maxAttempts=Max Attempts
 backOffStrategy=BackOff Strategy
+prefetch=Prefetch
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/policies/PolicyDirectoryPanel_ru.properties b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/policies/PolicyDirectoryPanel_ru.properties
index 4212773..963b7d6 100644
--- a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/policies/PolicyDirectoryPanel_ru.properties
+++ b/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/policies/PolicyDirectoryPanel_ru.properties
@@ -54,3 +54,4 @@
 unauthorizedRedirectUrl=Unauthorized Redirect URL
 maxAttempts=Max Attempts
 backOffStrategy=BackOff Strategy
+prefetch=Prefetch
diff --git a/common/idm/lib/src/main/java/org/apache/syncope/common/lib/policy/PropagationPolicyTO.java b/common/idm/lib/src/main/java/org/apache/syncope/common/lib/policy/PropagationPolicyTO.java
index 90bc7cd..1fd7ac0 100644
--- a/common/idm/lib/src/main/java/org/apache/syncope/common/lib/policy/PropagationPolicyTO.java
+++ b/common/idm/lib/src/main/java/org/apache/syncope/common/lib/policy/PropagationPolicyTO.java
@@ -28,6 +28,8 @@
 
     private static final long serialVersionUID = 10604950933449L;
 
+    private boolean prefetch = true;
+
     private BackOffStrategy backOffStrategy = BackOffStrategy.FIXED;
 
     private String backOffParams = BackOffStrategy.FIXED.getDefaultBackOffParams();
@@ -42,6 +44,14 @@
         return getClass().getName();
     }
 
+    public boolean isPrefetch() {
+        return prefetch;
+    }
+
+    public void setPrefetch(final boolean prefetch) {
+        this.prefetch = prefetch;
+    }
+
     public BackOffStrategy getBackOffStrategy() {
         return backOffStrategy;
     }
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/PropagationPolicy.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/PropagationPolicy.java
index d4e8172..532b27d 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/PropagationPolicy.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/PropagationPolicy.java
@@ -22,6 +22,10 @@
 
 public interface PropagationPolicy extends Policy {
 
+    boolean isPrefetch();
+
+    void setPrefetch(boolean prefetch);
+
     BackOffStrategy getBackOffStrategy();
 
     void setBackOffStrategy(BackOffStrategy backOffStrategy);
diff --git a/core/persistence-jpa-json/src/test/resources/domains/MasterContent.xml b/core/persistence-jpa-json/src/test/resources/domains/MasterContent.xml
index d508cad..fb42997 100644
--- a/core/persistence-jpa-json/src/test/resources/domains/MasterContent.xml
+++ b/core/persistence-jpa-json/src/test/resources/domains/MasterContent.xml
@@ -44,7 +44,7 @@
                   body='{"_class":"org.apache.syncope.common.lib.policy.DefaultPasswordRuleConf","maxLength":0,"minLength":10,"special":1,"specialChars":["@","!"],"digit":1,"lowercase":1,"uppercase":1,"wordsNotPermitted":["notpermitted1","notpermitted2"]}'/>
   <PasswordPolicyRule policy_id="55e5de0b-c79c-4e66-adda-251b6fb8579a" implementation_id="DefaultPasswordRuleConf3"/>
   <PropagationPolicy id="89d322db-9878-420c-b49c-67be13df9a12" name="sample propagation policy"
-                     maxAttempts="5" backOffStrategy="FIXED" backOffParams="10000"/>
+                     prefetch="1" maxAttempts="5" backOffStrategy="FIXED" backOffParams="10000"/>
 
   <!-- Authentication policies -->
   <AuthPolicy id="659b9906-4b6e-4bc0-aca0-6809dff346d4" name="MyDefaultAuthPolicyConf"
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPropagationPolicy.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPropagationPolicy.java
index 207886f..e3b634a 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPropagationPolicy.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPropagationPolicy.java
@@ -35,6 +35,9 @@
 
     public static final String TABLE = "PropagationPolicy";
 
+    @NotNull
+    private Boolean prefetch = true;
+
     @Enumerated(EnumType.STRING)
     @NotNull
     private BackOffStrategy backOffStrategy;
@@ -45,6 +48,16 @@
     private Integer maxAttempts = 3;
 
     @Override
+    public boolean isPrefetch() {
+        return prefetch;
+    }
+
+    @Override
+    public void setPrefetch(final boolean prefetch) {
+        this.prefetch = prefetch;
+    }
+
+    @Override
     public BackOffStrategy getBackOffStrategy() {
         return backOffStrategy;
     }
diff --git a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
index 7a90dee..1336795 100644
--- a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
+++ b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
@@ -44,7 +44,7 @@
                   body='{"_class":"org.apache.syncope.common.lib.policy.DefaultPasswordRuleConf","maxLength":0,"minLength":10,"special":1,"specialChars":["@","!"],"digit":1,"lowercase":1,"uppercase":1,"wordsNotPermitted":["notpermitted1","notpermitted2"]}'/>
   <PasswordPolicyRule policy_id="55e5de0b-c79c-4e66-adda-251b6fb8579a" implementation_id="DefaultPasswordRuleConf3"/>
   <PropagationPolicy id="89d322db-9878-420c-b49c-67be13df9a12" name="sample propagation policy"
-                     maxAttempts="5" backOffStrategy="FIXED" backOffParams="10000"/>
+                     prefetch="1" maxAttempts="5" backOffStrategy="FIXED" backOffParams="10000"/>
 
   <!-- Authentication policies -->
   <AuthPolicy id="659b9906-4b6e-4bc0-aca0-6809dff346d4" name="MyDefaultAuthPolicyConf"
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/PolicyDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/PolicyDataBinderImpl.java
index db197f3..0a97c96 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/PolicyDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/PolicyDataBinderImpl.java
@@ -148,6 +148,7 @@
             PropagationPolicy propagationPolicy = PropagationPolicy.class.cast(result);
             PropagationPolicyTO propagationPolicyTO = PropagationPolicyTO.class.cast(policyTO);
 
+            propagationPolicy.setPrefetch(propagationPolicyTO.isPrefetch());
             propagationPolicy.setBackOffStrategy(propagationPolicyTO.getBackOffStrategy());
             propagationPolicy.setBackOffParams(propagationPolicyTO.getBackOffParams());
             propagationPolicy.setMaxAttempts(propagationPolicyTO.getMaxAttempts());
@@ -307,6 +308,7 @@
             PropagationPolicyTO propagationPolicyTO = new PropagationPolicyTO();
             policyTO = (T) propagationPolicyTO;
 
+            propagationPolicyTO.setPrefetch(propagationPolicy.isPrefetch());
             propagationPolicyTO.setBackOffStrategy(propagationPolicy.getBackOffStrategy());
             propagationPolicyTO.setBackOffParams(propagationPolicy.getBackOffParams());
             propagationPolicyTO.setMaxAttempts(propagationPolicy.getMaxAttempts());
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 eb22d2d..4ee1a26 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
@@ -705,6 +705,13 @@
             final List<PropagationActions> actions,
             final boolean latest) {
 
+        if (task.getResource().getPropagationPolicy() != null
+                && !task.getResource().getPropagationPolicy().isPrefetch()) {
+
+            LOG.debug("Skipping because of configured PropagationPolicy");
+            return null;
+        }
+
         String connObjectKeyValue = latest || task.getOldConnObjectKey() == null
                 ? task.getConnObjectKey()
                 : task.getOldConnObjectKey();
@@ -732,6 +739,13 @@
             final List<PropagationActions> actions,
             final boolean latest) {
 
+        if (task.getResource().getPropagationPolicy() != null
+                && !task.getResource().getPropagationPolicy().isPrefetch()) {
+
+            LOG.debug("Skipping because of configured PropagationPolicy");
+            return null;
+        }
+
         String connObjectKey = latest || task.getOldConnObjectKey() == null
                 ? task.getConnObjectKey()
                 : task.getOldConnObjectKey();
diff --git a/src/main/asciidoc/reference-guide/concepts/policies.adoc b/src/main/asciidoc/reference-guide/concepts/policies.adoc
index 51746fd..9325fd5 100644
--- a/src/main/asciidoc/reference-guide/concepts/policies.adoc
+++ b/src/main/asciidoc/reference-guide/concepts/policies.adoc
@@ -324,10 +324,12 @@
 ==== Propagation
 
 Propagation policies are evaluated during the execution of <<tasks-propagation,propagation tasks>> and are meant to
-retry the configured operations in case of propagation failures.
+tweak the propagation process by setting the pre-fetch option or letting Syncope to retry the configured operations in
+case of failures.
 
 When defining a propagation policy, the following information must be provided:
 
+* pre-fetch - the default behavior to attempt to read upfront the object being propagated can be disabled
 * max number of attempts
 * back-off strategy
 ** `FIXED` - pauses for a fixed period of time before continuing