You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by il...@apache.org on 2017/10/10 06:37:06 UTC

[17/18] syncope git commit: [SYNCOPE-956] Protecting delete when Implementation is in use + refining Pull correlation rules

[SYNCOPE-956] Protecting delete when Implementation is in use + refining Pull correlation rules


Project: http://git-wip-us.apache.org/repos/asf/syncope/repo
Commit: http://git-wip-us.apache.org/repos/asf/syncope/commit/b47d4328
Tree: http://git-wip-us.apache.org/repos/asf/syncope/tree/b47d4328
Diff: http://git-wip-us.apache.org/repos/asf/syncope/diff/b47d4328

Branch: refs/heads/master
Commit: b47d4328687d173dfd220f6e6f107f042438d8cd
Parents: 9889072
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Tue Oct 10 06:54:07 2017 +0200
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Tue Oct 10 08:34:14 2017 +0200

----------------------------------------------------------------------
 .../commands/policy/PolicyResultManager.java    | 10 +--
 .../ResourceHistoryConfDirectoryPanel.java      |  2 -
 .../console/policies/PolicySpecModalPanel.java  | 16 ++--
 .../policies/PullPolicyDirectoryPanel.java      |  2 -
 .../common/lib/policy/PullPolicySpec.java       | 64 --------------
 .../syncope/common/lib/policy/PullPolicyTO.java | 27 ++++--
 .../common/lib/types/ClientExceptionType.java   |  2 +-
 .../syncope/core/logic/AccessTokenLogic.java    |  2 -
 .../syncope/core/logic/ImplementationLogic.java | 91 ++++++++++++++++++++
 .../syncope/core/logic/MailTemplateLogic.java   |  2 +-
 .../syncope/core/logic/ReportTemplateLogic.java |  2 +-
 .../api/dao/ExternalResourceDAO.java            |  7 ++
 .../persistence/api/dao/NotificationDAO.java    |  3 +
 .../persistence/api/dao/PlainSchemaDAO.java     |  2 +
 .../core/persistence/api/dao/PolicyDAO.java     | 12 ++-
 .../core/persistence/api/dao/RealmDAO.java      |  3 +
 .../core/persistence/api/dao/ReportDAO.java     |  3 +
 .../core/persistence/api/dao/TaskDAO.java       | 13 +++
 .../api/entity/policy/CorrelationRule.java      | 38 ++++++++
 .../api/entity/policy/PullPolicy.java           | 14 ++-
 .../jpa/dao/JPAExternalResourceDAO.java         | 21 +++++
 .../persistence/jpa/dao/JPANotificationDAO.java | 11 +++
 .../persistence/jpa/dao/JPAPlainSchemaDAO.java  | 11 +++
 .../core/persistence/jpa/dao/JPAPolicyDAO.java  | 32 +++++++
 .../core/persistence/jpa/dao/JPARealmDAO.java   | 11 +++
 .../core/persistence/jpa/dao/JPAReportDAO.java  | 10 +++
 .../core/persistence/jpa/dao/JPATaskDAO.java    | 45 ++++++++++
 .../jpa/entity/JPAEntityFactory.java            |  4 +
 .../persistence/jpa/entity/JPANotification.java |  3 +-
 .../persistence/jpa/entity/JPAPlainSchema.java  |  3 -
 .../jpa/entity/policy/JPACorrelationRule.java   | 86 ++++++++++++++++++
 .../jpa/entity/policy/JPAPullPolicy.java        | 48 +++++++++--
 .../jpa/entity/task/JPAPushTaskAnyFilter.java   |  4 +-
 .../jpa/inner/ImplementationTest.java           |  5 +-
 .../core/persistence/jpa/inner/PolicyTest.java  | 50 +++++++----
 .../core/persistence/jpa/outer/TaskTest.java    |  1 +
 .../test/resources/domains/MasterContent.xml    | 17 ++--
 .../java/data/PolicyDataBinderImpl.java         | 42 ++++++---
 .../java/pushpull/PullJobDelegate.java          | 22 +----
 .../provisioning/java/pushpull/PullUtils.java   | 54 ++++--------
 .../syncope/fit/core/ImplementationITCase.java  | 42 ++++++++-
 .../apache/syncope/fit/core/PolicyITCase.java   | 27 +-----
 .../apache/syncope/fit/core/PullTaskITCase.java |  2 +-
 43 files changed, 635 insertions(+), 231 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/b47d4328/client/cli/src/main/java/org/apache/syncope/client/cli/commands/policy/PolicyResultManager.java
----------------------------------------------------------------------
diff --git a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/policy/PolicyResultManager.java b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/policy/PolicyResultManager.java
index 11ec813..4bdba0d 100644
--- a/client/cli/src/main/java/org/apache/syncope/client/cli/commands/policy/PolicyResultManager.java
+++ b/client/cli/src/main/java/org/apache/syncope/client/cli/commands/policy/PolicyResultManager.java
@@ -103,12 +103,10 @@ public class PolicyResultManager extends CommonsResultManager {
         System.out.println("    description: " + policyTO.getDescription());
         System.out.println("    resources : " + policyTO.getUsedByResources().toString());
         System.out.println("    realms : " + policyTO.getUsedByRealms().toString());
-        if (policyTO.getSpecification() != null) {
-            System.out.println("    conflict resolution action: "
-                    + policyTO.getSpecification().getConflictResolutionAction().name());
-            System.out.println("    correlation rule : "
-                    + policyTO.getSpecification().getCorrelationRules().toString());
-        }
+        System.out.println("    conflict resolution action: "
+                + policyTO.getConflictResolutionAction().name());
+        System.out.println("    correlation rules : "
+                + policyTO.getCorrelationRules().toString());
         System.out.println("");
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/b47d4328/client/console/src/main/java/org/apache/syncope/client/console/panels/ResourceHistoryConfDirectoryPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/panels/ResourceHistoryConfDirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/panels/ResourceHistoryConfDirectoryPanel.java
index c666313..c964c29 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/panels/ResourceHistoryConfDirectoryPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/panels/ResourceHistoryConfDirectoryPanel.java
@@ -18,8 +18,6 @@
  */
 package org.apache.syncope.client.console.panels;
 
-import static org.apache.syncope.client.console.panels.DirectoryPanel.LOG;
-
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;

http://git-wip-us.apache.org/repos/asf/syncope/blob/b47d4328/client/console/src/main/java/org/apache/syncope/client/console/policies/PolicySpecModalPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/policies/PolicySpecModalPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/policies/PolicySpecModalPanel.java
index 313d869..4280996 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/policies/PolicySpecModalPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/policies/PolicySpecModalPanel.java
@@ -81,15 +81,15 @@ public class PolicySpecModalPanel extends AbstractModalPanel<PullPolicyTO> {
         add(new AjaxDropDownChoicePanel<>(
                 "conflictResolutionAction",
                 "conflictResolutionAction",
-                new PropertyModel<>(policyTO.getSpecification(), "conflictResolutionAction")).
+                new PropertyModel<>(policyTO, "conflictResolutionAction")).
                 setChoices(Arrays.asList((Serializable[]) ConflictResolutionAction.values())));
 
-        model = new PropertyModel<List<CorrelationRule>>(policyTO.getSpecification(), "correlationRules") {
+        model = new PropertyModel<List<CorrelationRule>>(policyTO, "correlationRules") {
 
             private static final long serialVersionUID = -8168676563540297301L;
 
-            private List<CorrelationRule> rules = policyTO.getSpecification().getCorrelationRules().keySet().stream().
-                    map(rule -> new CorrelationRule(rule, policyTO.getSpecification().getCorrelationRules().get(rule))).
+            private List<CorrelationRule> rules = policyTO.getCorrelationRules().keySet().stream().
+                    map(rule -> new CorrelationRule(rule, policyTO.getCorrelationRules().get(rule))).
                     collect(Collectors.toList());
 
             @Override
@@ -99,9 +99,9 @@ public class PolicySpecModalPanel extends AbstractModalPanel<PullPolicyTO> {
 
             @Override
             public void setObject(final List<CorrelationRule> object) {
-                policyTO.getSpecification().getCorrelationRules().clear();
+                policyTO.getCorrelationRules().clear();
                 rules.forEach(rule -> {
-                    policyTO.getSpecification().getCorrelationRules().put(rule.getAny(), rule.getRule());
+                    policyTO.getCorrelationRules().put(rule.getAny(), rule.getRule());
                 });
             }
         };
@@ -125,9 +125,9 @@ public class PolicySpecModalPanel extends AbstractModalPanel<PullPolicyTO> {
     @Override
     public void onSubmit(final AjaxRequestTarget target, final Form<?> form) {
         try {
-            getItem().getSpecification().getCorrelationRules().clear();
+            getItem().getCorrelationRules().clear();
             model.getObject().forEach(rule -> {
-                getItem().getSpecification().getCorrelationRules().put(rule.getAny(), rule.getRule());
+                getItem().getCorrelationRules().put(rule.getAny(), rule.getRule());
             });
             restClient.updatePolicy(getItem());
             SyncopeConsoleSession.get().info(getString(Constants.OPERATION_SUCCEEDED));

http://git-wip-us.apache.org/repos/asf/syncope/blob/b47d4328/client/console/src/main/java/org/apache/syncope/client/console/policies/PullPolicyDirectoryPanel.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/policies/PullPolicyDirectoryPanel.java b/client/console/src/main/java/org/apache/syncope/client/console/policies/PullPolicyDirectoryPanel.java
index 4d55249..5a29cae 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/policies/PullPolicyDirectoryPanel.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/policies/PullPolicyDirectoryPanel.java
@@ -20,7 +20,6 @@ package org.apache.syncope.client.console.policies;
 
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
 import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
-import org.apache.syncope.common.lib.policy.PullPolicySpec;
 import org.apache.syncope.common.lib.policy.PullPolicyTO;
 import org.apache.syncope.common.lib.types.PolicyType;
 import org.apache.syncope.common.lib.types.StandardEntitlement;
@@ -42,7 +41,6 @@ public class PullPolicyDirectoryPanel extends PolicyDirectoryPanel<PullPolicyTO>
         super(id, PolicyType.PULL, pageRef);
 
         final PullPolicyTO defaultItem = new PullPolicyTO();
-        defaultItem.setSpecification(new PullPolicySpec());
 
         this.addNewItemPanelBuilder(
                 new PolicyModalPanelBuilder<>(defaultItem, modal, pageRef), true);

http://git-wip-us.apache.org/repos/asf/syncope/blob/b47d4328/common/lib/src/main/java/org/apache/syncope/common/lib/policy/PullPolicySpec.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/policy/PullPolicySpec.java b/common/lib/src/main/java/org/apache/syncope/common/lib/policy/PullPolicySpec.java
deleted file mode 100644
index a6b5338..0000000
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/policy/PullPolicySpec.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.common.lib.policy;
-
-import com.fasterxml.jackson.annotation.JsonIgnore;
-import com.fasterxml.jackson.annotation.JsonProperty;
-import java.util.HashMap;
-import java.util.Map;
-import javax.xml.bind.annotation.XmlType;
-import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
-import org.apache.syncope.common.lib.AbstractBaseBean;
-import org.apache.syncope.common.lib.jaxb.XmlGenericMapAdapter;
-import org.apache.syncope.common.lib.types.ConflictResolutionAction;
-
-@XmlType
-public class PullPolicySpec extends AbstractBaseBean {
-
-    private static final long serialVersionUID = -3144027171719498127L;
-
-    private ConflictResolutionAction conflictResolutionAction;
-
-    /**
-     * Associates anyTypeKey to either:
-     * <ol>
-     * <li>Java class name, implementing {@code PullCorrelationRule}</li>
-     * <li>JSON array containing plain schema names - this will be used to feed
-     * {@code PlainAttrsPullCorrelationRule}</li>
-     * </ol>
-     */
-    @XmlJavaTypeAdapter(XmlGenericMapAdapter.class)
-    @JsonIgnore
-    private final Map<String, String> correlationRules = new HashMap<>();
-
-    public ConflictResolutionAction getConflictResolutionAction() {
-        return conflictResolutionAction == null
-                ? ConflictResolutionAction.IGNORE
-                : conflictResolutionAction;
-    }
-
-    public void setConflictResolutionAction(final ConflictResolutionAction conflictResolutionAction) {
-        this.conflictResolutionAction = conflictResolutionAction;
-    }
-
-    @JsonProperty
-    public Map<String, String> getCorrelationRules() {
-        return correlationRules;
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/b47d4328/common/lib/src/main/java/org/apache/syncope/common/lib/policy/PullPolicyTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/policy/PullPolicyTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/policy/PullPolicyTO.java
index 2618e43..1ab6000 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/policy/PullPolicyTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/policy/PullPolicyTO.java
@@ -18,8 +18,15 @@
  */
 package org.apache.syncope.common.lib.policy;
 
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.HashMap;
+import java.util.Map;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+import org.apache.syncope.common.lib.jaxb.XmlGenericMapAdapter;
+import org.apache.syncope.common.lib.types.ConflictResolutionAction;
 
 @XmlRootElement(name = "pullPolicy")
 @XmlType
@@ -27,14 +34,24 @@ public class PullPolicyTO extends AbstractPolicyTO {
 
     private static final long serialVersionUID = 993024634238024242L;
 
-    private PullPolicySpec specification;
+    private ConflictResolutionAction conflictResolutionAction;
 
-    public PullPolicySpec getSpecification() {
-        return specification;
+    @XmlJavaTypeAdapter(XmlGenericMapAdapter.class)
+    @JsonIgnore
+    private final Map<String, String> correlationRules = new HashMap<>();
+
+    public ConflictResolutionAction getConflictResolutionAction() {
+        return conflictResolutionAction == null
+                ? ConflictResolutionAction.IGNORE
+                : conflictResolutionAction;
     }
 
-    public void setSpecification(final PullPolicySpec specification) {
-        this.specification = specification;
+    public void setConflictResolutionAction(final ConflictResolutionAction conflictResolutionAction) {
+        this.conflictResolutionAction = conflictResolutionAction;
     }
 
+    @JsonProperty
+    public Map<String, String> getCorrelationRules() {
+        return correlationRules;
+    }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/b47d4328/common/lib/src/main/java/org/apache/syncope/common/lib/types/ClientExceptionType.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/types/ClientExceptionType.java b/common/lib/src/main/java/org/apache/syncope/common/lib/types/ClientExceptionType.java
index 92238d8..c75ab5b 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/types/ClientExceptionType.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/types/ClientExceptionType.java
@@ -72,7 +72,7 @@ public enum ClientExceptionType {
     RequiredValuesMissing(Response.Status.BAD_REQUEST),
     RESTValidation(Response.Status.BAD_REQUEST),
     GroupOwnership(Response.Status.BAD_REQUEST),
-    InUseByNotifications(Response.Status.BAD_REQUEST),
+    InUse(Response.Status.BAD_REQUEST),
     Scheduling(Response.Status.BAD_REQUEST),
     DelegatedAdministration(Response.Status.FORBIDDEN),
     Unknown(Response.Status.BAD_REQUEST),

http://git-wip-us.apache.org/repos/asf/syncope/blob/b47d4328/core/logic/src/main/java/org/apache/syncope/core/logic/AccessTokenLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/AccessTokenLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/AccessTokenLogic.java
index 077b6df..d4915ce 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/AccessTokenLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/AccessTokenLogic.java
@@ -18,8 +18,6 @@
  */
 package org.apache.syncope.core.logic;
 
-import static org.apache.syncope.core.logic.AbstractLogic.LOG;
-
 import java.lang.reflect.Method;
 import java.util.Collections;
 import java.util.Date;

http://git-wip-us.apache.org/repos/asf/syncope/blob/b47d4328/core/logic/src/main/java/org/apache/syncope/core/logic/ImplementationLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/ImplementationLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/ImplementationLogic.java
index fadaa15..65e6290 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/ImplementationLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/ImplementationLogic.java
@@ -29,8 +29,15 @@ import org.apache.syncope.common.lib.types.ClientExceptionType;
 import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.common.lib.types.StandardEntitlement;
 import org.apache.syncope.core.persistence.api.dao.DuplicateException;
+import org.apache.syncope.core.persistence.api.dao.ExternalResourceDAO;
 import org.apache.syncope.core.persistence.api.dao.ImplementationDAO;
 import org.apache.syncope.core.persistence.api.dao.NotFoundException;
+import org.apache.syncope.core.persistence.api.dao.NotificationDAO;
+import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
+import org.apache.syncope.core.persistence.api.dao.PolicyDAO;
+import org.apache.syncope.core.persistence.api.dao.RealmDAO;
+import org.apache.syncope.core.persistence.api.dao.ReportDAO;
+import org.apache.syncope.core.persistence.api.dao.TaskDAO;
 import org.apache.syncope.core.persistence.api.entity.Implementation;
 import org.apache.syncope.core.provisioning.api.data.ImplementationDataBinder;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -46,6 +53,27 @@ public class ImplementationLogic extends AbstractTransactionalLogic<Implementati
     @Autowired
     private ImplementationDAO implementationDAO;
 
+    @Autowired
+    private ReportDAO reportDAO;
+
+    @Autowired
+    private PolicyDAO policyDAO;
+
+    @Autowired
+    private ExternalResourceDAO resourceDAO;
+
+    @Autowired
+    private TaskDAO taskDAO;
+
+    @Autowired
+    private RealmDAO realmDAO;
+
+    @Autowired
+    private PlainSchemaDAO plainSchemaDAO;
+
+    @Autowired
+    private NotificationDAO notificationDAO;
+
     @PreAuthorize("hasRole('" + StandardEntitlement.IMPLEMENTATION_LIST + "')")
     public List<ImplementationTO> list(final ImplementationType type) {
         return implementationDAO.find(type).stream().
@@ -104,6 +132,69 @@ public class ImplementationLogic extends AbstractTransactionalLogic<Implementati
             throw new NotFoundException(key);
         }
 
+        boolean inUse = false;
+        switch (implementation.getType()) {
+            case REPORTLET:
+                inUse = !reportDAO.findByReportlet(implementation).isEmpty();
+                break;
+
+            case ACCOUNT_RULE:
+                inUse = !policyDAO.findByAccountRule(implementation).isEmpty();
+                break;
+
+            case PASSWORD_RULE:
+                inUse = !policyDAO.findByPasswordRule(implementation).isEmpty();
+                break;
+
+            case ITEM_TRANSFORMER:
+                inUse = !resourceDAO.findByTransformer(implementation).isEmpty();
+                break;
+
+            case TASKJOB_DELEGATE:
+                inUse = !taskDAO.findByDelegate(implementation).isEmpty();
+                break;
+
+            case RECON_FILTER_BUILDER:
+                inUse = !taskDAO.findByReconFilterBuilder(implementation).isEmpty();
+                break;
+
+            case LOGIC_ACTIONS:
+                inUse = !realmDAO.findByLogicActions(implementation).isEmpty();
+                break;
+
+            case PROPAGATION_ACTIONS:
+                inUse = !resourceDAO.findByPropagationActions(implementation).isEmpty();
+                break;
+
+            case PULL_ACTIONS:
+                inUse = !taskDAO.findByPullActions(implementation).isEmpty();
+                break;
+
+            case PUSH_ACTIONS:
+                inUse = !taskDAO.findByPushActions(implementation).isEmpty();
+                break;
+
+            case PULL_CORRELATION_RULE:
+                inUse = !policyDAO.findByCorrelationRule(implementation).isEmpty();
+                break;
+
+            case VALIDATOR:
+                inUse = !plainSchemaDAO.findByValidator(implementation).isEmpty();
+                break;
+
+            case RECIPIENTS_PROVIDER:
+                inUse = !notificationDAO.findByRecipientsProvider(implementation).isEmpty();
+                break;
+
+            default:
+        }
+
+        if (inUse) {
+            SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InUse);
+            sce.getElements().add("This implementation is in use");
+            throw sce;
+        }
+
         implementationDAO.delete(key);
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/b47d4328/core/logic/src/main/java/org/apache/syncope/core/logic/MailTemplateLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/MailTemplateLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/MailTemplateLogic.java
index ff742c5..3f2b7c8 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/MailTemplateLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/MailTemplateLogic.java
@@ -138,7 +138,7 @@ public class MailTemplateLogic extends AbstractTransactionalLogic<MailTemplateTO
 
         List<Notification> notifications = notificationDAO.findByTemplate(mailTemplate);
         if (!notifications.isEmpty()) {
-            SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InUseByNotifications);
+            SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InUse);
             sce.getElements().addAll(notifications.stream().map(Entity::getKey).collect(Collectors.toList()));
             throw sce;
         }

http://git-wip-us.apache.org/repos/asf/syncope/blob/b47d4328/core/logic/src/main/java/org/apache/syncope/core/logic/ReportTemplateLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/ReportTemplateLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/ReportTemplateLogic.java
index 4d150d9..d59831c 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/ReportTemplateLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/ReportTemplateLogic.java
@@ -150,7 +150,7 @@ public class ReportTemplateLogic extends AbstractTransactionalLogic<ReportTempla
 
         List<Report> reports = reportDAO.findByTemplate(reportTemplate);
         if (!reports.isEmpty()) {
-            SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InUseByNotifications);
+            SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InUse);
             sce.getElements().addAll(reports.stream().map(Entity::getKey).collect(Collectors.toList()));
             throw sce;
         }

http://git-wip-us.apache.org/repos/asf/syncope/blob/b47d4328/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/ExternalResourceDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/ExternalResourceDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/ExternalResourceDAO.java
index b48fd79..ea1ceb8 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/ExternalResourceDAO.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/ExternalResourceDAO.java
@@ -20,8 +20,10 @@ package org.apache.syncope.core.persistence.api.dao;
 
 import java.util.List;
 import org.apache.syncope.core.persistence.api.entity.AnyTypeClass;
+import org.apache.syncope.core.persistence.api.entity.Implementation;
 import org.apache.syncope.core.persistence.api.entity.Policy;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
+import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
 import org.apache.syncope.core.persistence.api.entity.resource.Provision;
 
 public interface ExternalResourceDAO extends DAO<ExternalResource> {
@@ -34,6 +36,10 @@ public interface ExternalResourceDAO extends DAO<ExternalResource> {
 
     List<Provision> findProvisionsByAuxClass(AnyTypeClass anyTypeClass);
 
+    List<MappingItem> findByTransformer(Implementation transformer);
+
+    List<ExternalResource> findByPropagationActions(Implementation propagationActions);
+
     List<ExternalResource> findByPolicy(Policy policy);
 
     List<ExternalResource> findAll();
@@ -43,4 +49,5 @@ public interface ExternalResourceDAO extends DAO<ExternalResource> {
     void deleteMapping(String schemaName);
 
     void delete(String key);
+
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/b47d4328/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/NotificationDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/NotificationDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/NotificationDAO.java
index 569e6db..48f410d 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/NotificationDAO.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/NotificationDAO.java
@@ -19,6 +19,7 @@
 package org.apache.syncope.core.persistence.api.dao;
 
 import java.util.List;
+import org.apache.syncope.core.persistence.api.entity.Implementation;
 import org.apache.syncope.core.persistence.api.entity.MailTemplate;
 import org.apache.syncope.core.persistence.api.entity.Notification;
 
@@ -28,6 +29,8 @@ public interface NotificationDAO extends DAO<Notification> {
 
     List<Notification> findByTemplate(MailTemplate template);
 
+    List<Notification> findByRecipientsProvider(Implementation recipientsProvider);
+
     List<Notification> findAll();
 
     Notification save(Notification notification);

http://git-wip-us.apache.org/repos/asf/syncope/blob/b47d4328/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PlainSchemaDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PlainSchemaDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PlainSchemaDAO.java
index c832cdc..7f066ac 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PlainSchemaDAO.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PlainSchemaDAO.java
@@ -19,6 +19,7 @@
 package org.apache.syncope.core.persistence.api.dao;
 
 import java.util.List;
+import org.apache.syncope.core.persistence.api.entity.Implementation;
 import org.apache.syncope.core.persistence.api.entity.PlainAttr;
 import org.apache.syncope.core.persistence.api.entity.PlainSchema;
 
@@ -26,4 +27,5 @@ public interface PlainSchemaDAO extends SchemaDAO<PlainSchema> {
 
     <T extends PlainAttr<?>> List<T> findAttrs(PlainSchema schema, Class<T> reference);
 
+    List<PlainSchema> findByValidator(Implementation validator);
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/b47d4328/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PolicyDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PolicyDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PolicyDAO.java
index 245758b..456850c 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PolicyDAO.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/PolicyDAO.java
@@ -19,9 +19,12 @@
 package org.apache.syncope.core.persistence.api.dao;
 
 import java.util.List;
-import org.apache.syncope.core.persistence.api.entity.policy.AccountPolicy;
+import org.apache.syncope.core.persistence.api.entity.Implementation;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 import org.apache.syncope.core.persistence.api.entity.Policy;
+import org.apache.syncope.core.persistence.api.entity.policy.AccountPolicy;
+import org.apache.syncope.core.persistence.api.entity.policy.PasswordPolicy;
+import org.apache.syncope.core.persistence.api.entity.policy.PullPolicy;
 
 public interface PolicyDAO extends DAO<Policy> {
 
@@ -29,6 +32,12 @@ public interface PolicyDAO extends DAO<Policy> {
 
     <T extends Policy> List<T> find(Class<T> reference);
 
+    List<AccountPolicy> findByAccountRule(Implementation accountRule);
+
+    List<PasswordPolicy> findByPasswordRule(Implementation passwordRule);
+
+    List<PullPolicy> findByCorrelationRule(Implementation correlationRule);
+
     List<AccountPolicy> findByResource(ExternalResource resource);
 
     List<Policy> findAll();
@@ -36,4 +45,5 @@ public interface PolicyDAO extends DAO<Policy> {
     <T extends Policy> T save(T policy);
 
     <T extends Policy> void delete(T policy);
+
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/b47d4328/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/RealmDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/RealmDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/RealmDAO.java
index de23601..c838338 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/RealmDAO.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/RealmDAO.java
@@ -20,6 +20,7 @@ package org.apache.syncope.core.persistence.api.dao;
 
 import java.util.List;
 import java.util.regex.Pattern;
+import org.apache.syncope.core.persistence.api.entity.Implementation;
 import org.apache.syncope.core.persistence.api.entity.Policy;
 import org.apache.syncope.core.persistence.api.entity.Realm;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
@@ -40,6 +41,8 @@ public interface RealmDAO extends DAO<Realm> {
 
     <T extends Policy> List<Realm> findByPolicy(T policy);
 
+    List<Realm> findByLogicActions(Implementation logicActions);
+
     List<Realm> findAncestors(Realm realm);
 
     List<Realm> findChildren(Realm realm);

http://git-wip-us.apache.org/repos/asf/syncope/blob/b47d4328/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/ReportDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/ReportDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/ReportDAO.java
index 89f07ff..50d2c5e 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/ReportDAO.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/ReportDAO.java
@@ -19,6 +19,7 @@
 package org.apache.syncope.core.persistence.api.dao;
 
 import java.util.List;
+import org.apache.syncope.core.persistence.api.entity.Implementation;
 import org.apache.syncope.core.persistence.api.entity.Report;
 import org.apache.syncope.core.persistence.api.entity.ReportTemplate;
 
@@ -26,6 +27,8 @@ public interface ReportDAO extends DAO<Report> {
 
     Report find(String key);
 
+    List<Report> findByReportlet(Implementation reportlet);
+
     List<Report> findByTemplate(ReportTemplate template);
 
     List<Report> findAll();

http://git-wip-us.apache.org/repos/asf/syncope/blob/b47d4328/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/TaskDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/TaskDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/TaskDAO.java
index 603cfab..f619154 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/TaskDAO.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/TaskDAO.java
@@ -22,8 +22,12 @@ import java.util.List;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.TaskType;
 import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
+import org.apache.syncope.core.persistence.api.entity.Implementation;
 import org.apache.syncope.core.persistence.api.entity.Notification;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
+import org.apache.syncope.core.persistence.api.entity.task.PullTask;
+import org.apache.syncope.core.persistence.api.entity.task.PushTask;
+import org.apache.syncope.core.persistence.api.entity.task.SchedTask;
 import org.apache.syncope.core.persistence.api.entity.task.Task;
 
 public interface TaskDAO extends DAO<Task> {
@@ -32,6 +36,14 @@ public interface TaskDAO extends DAO<Task> {
 
     <T extends Task> T find(String key);
 
+    List<SchedTask> findByDelegate(Implementation delegate);
+
+    List<PullTask> findByReconFilterBuilder(Implementation reconFilterBuilder);
+
+    List<PullTask> findByPullActions(Implementation pullActions);
+
+    List<PushTask> findByPushActions(Implementation pushActions);
+
     <T extends Task> List<T> findToExec(TaskType type);
 
     <T extends Task> List<T> findAll(TaskType type);
@@ -60,4 +72,5 @@ public interface TaskDAO extends DAO<Task> {
     void delete(Task task);
 
     void deleteAll(ExternalResource resource, TaskType type);
+
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/b47d4328/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/CorrelationRule.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/CorrelationRule.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/CorrelationRule.java
new file mode 100644
index 0000000..69ad1de
--- /dev/null
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/CorrelationRule.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.persistence.api.entity.policy;
+
+import org.apache.syncope.core.persistence.api.entity.AnyType;
+import org.apache.syncope.core.persistence.api.entity.Entity;
+import org.apache.syncope.core.persistence.api.entity.Implementation;
+
+public interface CorrelationRule extends Entity {
+
+    PullPolicy getPullPolicy();
+
+    void setPullPolicy(PullPolicy pullPolicy);
+
+    AnyType getAnyType();
+
+    void setAnyType(AnyType anyType);
+
+    Implementation getImplementation();
+
+    void setImplementation(Implementation implementation);
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/b47d4328/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/PullPolicy.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/PullPolicy.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/PullPolicy.java
index da82cb7..6612fe5 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/PullPolicy.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/policy/PullPolicy.java
@@ -18,13 +18,21 @@
  */
 package org.apache.syncope.core.persistence.api.entity.policy;
 
-import org.apache.syncope.common.lib.policy.PullPolicySpec;
+import java.util.List;
+import java.util.Optional;
+import org.apache.syncope.common.lib.types.ConflictResolutionAction;
+import org.apache.syncope.core.persistence.api.entity.AnyType;
 import org.apache.syncope.core.persistence.api.entity.Policy;
 
 public interface PullPolicy extends Policy {
 
-    PullPolicySpec getSpecification();
+    ConflictResolutionAction getConflictResolutionAction();
 
-    void setSpecification(PullPolicySpec spec);
+    void setConflictResolutionAction(ConflictResolutionAction conflictResolutionAction);
 
+    boolean add(CorrelationRule rule);
+
+    Optional<? extends CorrelationRule> getCorrelationRule(AnyType anyType);
+
+    List<? extends CorrelationRule> getCorrelationRules();
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/b47d4328/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAExternalResourceDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAExternalResourceDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAExternalResourceDAO.java
index 8e6485f..530b539 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAExternalResourceDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAExternalResourceDAO.java
@@ -38,6 +38,7 @@ import org.apache.syncope.core.persistence.api.dao.TaskDAO;
 import org.apache.syncope.core.persistence.api.dao.UserDAO;
 import org.apache.syncope.core.persistence.api.dao.VirSchemaDAO;
 import org.apache.syncope.core.persistence.api.entity.AnyTypeClass;
+import org.apache.syncope.core.persistence.api.entity.Implementation;
 import org.apache.syncope.core.persistence.api.entity.policy.AccountPolicy;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
@@ -195,6 +196,26 @@ public class JPAExternalResourceDAO extends AbstractDAO<ExternalResource> implem
         return query.getResultList();
     }
 
+    @Override
+    public List<MappingItem> findByTransformer(final Implementation transformer) {
+        TypedQuery<MappingItem> query = entityManager().createQuery(
+                "SELECT e FROM " + JPAMappingItem.class.getSimpleName()
+                + " e WHERE :transformer MEMBER OF e.transformers", MappingItem.class);
+        query.setParameter("transformer", transformer);
+
+        return query.getResultList();
+    }
+
+    @Override
+    public List<ExternalResource> findByPropagationActions(final Implementation propagationActions) {
+        TypedQuery<ExternalResource> query = entityManager().createQuery(
+                "SELECT e FROM " + JPAExternalResource.class.getSimpleName() + " e "
+                + "WHERE :propagationActions MEMBER OF e.propagationActions", ExternalResource.class);
+        query.setParameter("propagationActions", propagationActions);
+
+        return query.getResultList();
+    }
+
     private StringBuilder getByPolicyQuery(final Class<? extends Policy> policyClass) {
         StringBuilder query = new StringBuilder("SELECT e FROM ").
                 append(JPAExternalResource.class.getSimpleName()).

http://git-wip-us.apache.org/repos/asf/syncope/blob/b47d4328/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPANotificationDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPANotificationDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPANotificationDAO.java
index ca5f0c4..1005ac7 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPANotificationDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPANotificationDAO.java
@@ -26,6 +26,7 @@ import org.apache.syncope.core.persistence.api.dao.NotificationDAO;
 import org.apache.syncope.core.persistence.api.dao.TaskDAO;
 import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
 import org.apache.syncope.core.persistence.api.entity.Entity;
+import org.apache.syncope.core.persistence.api.entity.Implementation;
 import org.apache.syncope.core.persistence.api.entity.MailTemplate;
 import org.apache.syncope.core.persistence.api.entity.Notification;
 import org.apache.syncope.core.persistence.jpa.entity.JPANotification;
@@ -55,6 +56,16 @@ public class JPANotificationDAO extends AbstractDAO<Notification> implements Not
         return query.getResultList();
     }
 
+    @Override
+    public List<Notification> findByRecipientsProvider(final Implementation recipientsProvider) {
+        TypedQuery<Notification> query = entityManager().createQuery(
+                "SELECT e FROM " + JPANotification.class.getSimpleName()
+                + " e WHERE e.recipientsProvider=:recipientsProvider", Notification.class);
+        query.setParameter("recipientsProvider", recipientsProvider);
+
+        return query.getResultList();
+    }
+
     @Transactional(readOnly = true)
     @Override
     public List<Notification> findAll() {

http://git-wip-us.apache.org/repos/asf/syncope/blob/b47d4328/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPlainSchemaDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPlainSchemaDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPlainSchemaDAO.java
index dfc3840..eef9ff1 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPlainSchemaDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPlainSchemaDAO.java
@@ -28,6 +28,7 @@ import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
 import org.apache.syncope.core.persistence.api.entity.AnyTypeClass;
 import org.apache.syncope.core.persistence.api.entity.AnyUtils;
 import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
+import org.apache.syncope.core.persistence.api.entity.Implementation;
 import org.apache.syncope.core.persistence.api.entity.PlainAttr;
 import org.apache.syncope.core.persistence.api.entity.PlainSchema;
 import org.apache.syncope.core.persistence.jpa.entity.JPAAnyUtilsFactory;
@@ -74,6 +75,16 @@ public class JPAPlainSchemaDAO extends AbstractDAO<PlainSchema> implements Plain
     }
 
     @Override
+    public List<PlainSchema> findByValidator(final Implementation validator) {
+        TypedQuery<PlainSchema> query = entityManager().createQuery(
+                "SELECT e FROM " + JPAPlainSchema.class.getSimpleName()
+                + " e WHERE e.validator=:validator", PlainSchema.class);
+        query.setParameter("validator", validator);
+
+        return query.getResultList();
+    }
+
+    @Override
     public List<PlainSchema> findAll() {
         TypedQuery<PlainSchema> query = entityManager().createQuery(
                 "SELECT e FROM " + JPAPlainSchema.class.getSimpleName() + " e", PlainSchema.class);

http://git-wip-us.apache.org/repos/asf/syncope/blob/b47d4328/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPolicyDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPolicyDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPolicyDAO.java
index 4c76f44..38d260f 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPolicyDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPolicyDAO.java
@@ -22,6 +22,7 @@ import java.util.List;
 import javax.persistence.TypedQuery;
 import org.apache.syncope.core.persistence.api.dao.PolicyDAO;
 import org.apache.syncope.core.persistence.api.dao.RealmDAO;
+import org.apache.syncope.core.persistence.api.entity.Implementation;
 import org.apache.syncope.core.persistence.api.entity.policy.AccountPolicy;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 import org.apache.syncope.core.persistence.api.entity.policy.PasswordPolicy;
@@ -31,6 +32,7 @@ import org.apache.syncope.core.persistence.api.entity.policy.PullPolicy;
 import org.apache.syncope.core.persistence.api.entity.policy.PushPolicy;
 import org.apache.syncope.core.persistence.jpa.entity.policy.AbstractPolicy;
 import org.apache.syncope.core.persistence.jpa.entity.policy.JPAAccountPolicy;
+import org.apache.syncope.core.persistence.jpa.entity.policy.JPACorrelationRule;
 import org.apache.syncope.core.persistence.jpa.entity.policy.JPAPasswordPolicy;
 import org.apache.syncope.core.persistence.jpa.entity.policy.JPAPullPolicy;
 import org.apache.syncope.core.persistence.jpa.entity.policy.JPAPushPolicy;
@@ -70,6 +72,36 @@ public class JPAPolicyDAO extends AbstractDAO<Policy> implements PolicyDAO {
     }
 
     @Override
+    public List<AccountPolicy> findByAccountRule(final Implementation accountRule) {
+        TypedQuery<AccountPolicy> query = entityManager().createQuery(
+                "SELECT e FROM " + JPAAccountPolicy.class.getSimpleName() + " e "
+                + "WHERE :accountRule MEMBER OF e.rules", AccountPolicy.class);
+        query.setParameter("accountRule", accountRule);
+
+        return query.getResultList();
+    }
+
+    @Override
+    public List<PasswordPolicy> findByPasswordRule(final Implementation passwordRule) {
+        TypedQuery<PasswordPolicy> query = entityManager().createQuery(
+                "SELECT e FROM " + JPAPasswordPolicy.class.getSimpleName() + " e "
+                + "WHERE :passwordRule MEMBER OF e.rules", PasswordPolicy.class);
+        query.setParameter("passwordRule", passwordRule);
+
+        return query.getResultList();
+    }
+
+    @Override
+    public List<PullPolicy> findByCorrelationRule(final Implementation correlationRule) {
+        TypedQuery<PullPolicy> query = entityManager().createQuery(
+                "SELECT DISTINCT e.pullPolicy FROM " + JPACorrelationRule.class.getSimpleName() + " e "
+                + "WHERE e.implementation=:correlationRule", PullPolicy.class);
+        query.setParameter("correlationRule", correlationRule);
+
+        return query.getResultList();
+    }
+
+    @Override
     public List<AccountPolicy> findByResource(final ExternalResource resource) {
         TypedQuery<AccountPolicy> query = entityManager().createQuery(
                 "SELECT e FROM " + JPAAccountPolicy.class.getSimpleName() + " e "

http://git-wip-us.apache.org/repos/asf/syncope/blob/b47d4328/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARealmDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARealmDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARealmDAO.java
index a03451f..3594b70 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARealmDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPARealmDAO.java
@@ -29,6 +29,7 @@ import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.core.persistence.api.dao.MalformedPathException;
 import org.apache.syncope.core.persistence.api.dao.RealmDAO;
 import org.apache.syncope.core.persistence.api.dao.RoleDAO;
+import org.apache.syncope.core.persistence.api.entity.Implementation;
 import org.apache.syncope.core.persistence.api.entity.policy.AccountPolicy;
 import org.apache.syncope.core.persistence.api.entity.Policy;
 import org.apache.syncope.core.persistence.api.entity.Realm;
@@ -151,6 +152,16 @@ public class JPARealmDAO extends AbstractDAO<Realm> implements RealmDAO {
         return result;
     }
 
+    @Override
+    public List<Realm> findByLogicActions(final Implementation logicActions) {
+        TypedQuery<Realm> query = entityManager().createQuery(
+                "SELECT e FROM " + JPARealm.class.getSimpleName() + " e "
+                + "WHERE :logicActions MEMBER OF e.actions", Realm.class);
+        query.setParameter("logicActions", logicActions);
+
+        return query.getResultList();
+    }
+
     private void findAncestors(final List<Realm> result, final Realm realm) {
         if (realm.getParent() != null && !result.contains(realm.getParent())) {
             result.add(realm.getParent());

http://git-wip-us.apache.org/repos/asf/syncope/blob/b47d4328/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAReportDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAReportDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAReportDAO.java
index 959eac2..a281e2b 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAReportDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAReportDAO.java
@@ -21,6 +21,7 @@ package org.apache.syncope.core.persistence.jpa.dao;
 import java.util.List;
 import javax.persistence.TypedQuery;
 import org.apache.syncope.core.persistence.api.dao.ReportDAO;
+import org.apache.syncope.core.persistence.api.entity.Implementation;
 import org.apache.syncope.core.persistence.api.entity.Report;
 import org.apache.syncope.core.persistence.api.entity.ReportTemplate;
 import org.apache.syncope.core.persistence.jpa.entity.JPAReport;
@@ -36,6 +37,15 @@ public class JPAReportDAO extends AbstractDAO<Report> implements ReportDAO {
         return entityManager().find(JPAReport.class, key);
     }
 
+    @Override
+    public List<Report> findByReportlet(final Implementation reportlet) {
+        TypedQuery<Report> query = entityManager().createQuery(
+                "SELECT e FROM " + JPAReport.class.getSimpleName() + " e "
+                + "WHERE :reportlet MEMBER OF e.reportlets", Report.class);
+        query.setParameter("reportlet", reportlet);
+        return query.getResultList();
+    }
+
     @Transactional(readOnly = true)
     @Override
     public List<Report> findByTemplate(final ReportTemplate template) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/b47d4328/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPATaskDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPATaskDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPATaskDAO.java
index 55ca241..792a661 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPATaskDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPATaskDAO.java
@@ -21,14 +21,19 @@ package org.apache.syncope.core.persistence.jpa.dao;
 import java.util.Collections;
 import java.util.List;
 import javax.persistence.Query;
+import javax.persistence.TypedQuery;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.TaskType;
 import org.apache.syncope.core.persistence.api.dao.TaskDAO;
 import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
 import org.apache.syncope.core.persistence.api.entity.Entity;
+import org.apache.syncope.core.persistence.api.entity.Implementation;
 import org.apache.syncope.core.persistence.api.entity.Notification;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
+import org.apache.syncope.core.persistence.api.entity.task.PullTask;
+import org.apache.syncope.core.persistence.api.entity.task.PushTask;
+import org.apache.syncope.core.persistence.api.entity.task.SchedTask;
 import org.apache.syncope.core.persistence.api.entity.task.Task;
 import org.apache.syncope.core.persistence.jpa.entity.task.JPANotificationTask;
 import org.apache.syncope.core.persistence.jpa.entity.task.JPAPropagationTask;
@@ -81,6 +86,46 @@ public class JPATaskDAO extends AbstractDAO<Task> implements TaskDAO {
         return (T) entityManager().find(AbstractTask.class, key);
     }
 
+    @Override
+    public List<SchedTask> findByDelegate(final Implementation delegate) {
+        TypedQuery<SchedTask> query = entityManager().createQuery(
+                "SELECT e FROM " + JPASchedTask.class.getSimpleName()
+                + " e WHERE e.jobDelegate=:delegate", SchedTask.class);
+        query.setParameter("delegate", delegate);
+
+        return query.getResultList();
+    }
+
+    @Override
+    public List<PullTask> findByReconFilterBuilder(final Implementation reconFilterBuilder) {
+        TypedQuery<PullTask> query = entityManager().createQuery(
+                "SELECT e FROM " + JPAPullTask.class.getSimpleName()
+                + " e WHERE e.reconFilterBuilder=:reconFilterBuilder", PullTask.class);
+        query.setParameter("reconFilterBuilder", reconFilterBuilder);
+
+        return query.getResultList();
+    }
+
+    @Override
+    public List<PullTask> findByPullActions(final Implementation pullActions) {
+        TypedQuery<PullTask> query = entityManager().createQuery(
+                "SELECT e FROM " + JPAPullTask.class.getSimpleName() + " e "
+                + "WHERE :pullActions MEMBER OF e.actions", PullTask.class);
+        query.setParameter("pullActions", pullActions);
+
+        return query.getResultList();
+    }
+
+    @Override
+    public List<PushTask> findByPushActions(final Implementation pushActions) {
+        TypedQuery<PushTask> query = entityManager().createQuery(
+                "SELECT e FROM " + JPAPushTask.class.getSimpleName() + " e "
+                + "WHERE :pushActions MEMBER OF e.actions", PushTask.class);
+        query.setParameter("pushActions", pushActions);
+
+        return query.getResultList();
+    }
+
     private <T extends Task> StringBuilder buildFindAllQuery(final TaskType type) {
         StringBuilder builder = new StringBuilder("SELECT t FROM ").
                 append(getEntityReference(type).getSimpleName()).

http://git-wip-us.apache.org/repos/asf/syncope/blob/b47d4328/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAEntityFactory.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAEntityFactory.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAEntityFactory.java
index 3223f18..fe3a037 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAEntityFactory.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAEntityFactory.java
@@ -128,8 +128,10 @@ import org.apache.syncope.core.persistence.jpa.entity.resource.JPAOrgUnit;
 import org.apache.syncope.core.persistence.api.entity.DynRealm;
 import org.apache.syncope.core.persistence.api.entity.DynRealmMembership;
 import org.apache.syncope.core.persistence.api.entity.Implementation;
+import org.apache.syncope.core.persistence.api.entity.policy.CorrelationRule;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResourceHistoryConf;
 import org.apache.syncope.core.persistence.api.entity.resource.OrgUnitItem;
+import org.apache.syncope.core.persistence.jpa.entity.policy.JPACorrelationRule;
 import org.apache.syncope.core.persistence.jpa.entity.resource.JPAExternalResourceHistoryConf;
 import org.apache.syncope.core.persistence.jpa.entity.resource.JPAOrgUnitItem;
 
@@ -159,6 +161,8 @@ public class JPAEntityFactory implements EntityFactory {
             result = (E) new JPAPushPolicy();
         } else if (reference.equals(PullPolicy.class)) {
             result = (E) new JPAPullPolicy();
+        } else if (reference.equals(CorrelationRule.class)) {
+            result = (E) new JPACorrelationRule();
         } else if (reference.equals(AnyTypeClass.class)) {
             result = (E) new JPAAnyTypeClass();
         } else if (reference.equals(AnyType.class)) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/b47d4328/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPANotification.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPANotification.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPANotification.java
index b895d65..aec4e9b 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPANotification.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPANotification.java
@@ -33,7 +33,6 @@ import javax.persistence.FetchType;
 import javax.persistence.JoinColumn;
 import javax.persistence.ManyToOne;
 import javax.persistence.OneToMany;
-import javax.persistence.OneToOne;
 import javax.persistence.Table;
 import javax.validation.constraints.Max;
 import javax.validation.constraints.Min;
@@ -76,7 +75,7 @@ public class JPANotification extends AbstractGeneratedKeyEntity implements Notif
     @NotNull
     private String recipientAttrName;
 
-    @OneToOne
+    @ManyToOne
     private JPAImplementation recipientsProvider;
 
     @NotNull

http://git-wip-us.apache.org/repos/asf/syncope/blob/b47d4328/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAPlainSchema.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAPlainSchema.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAPlainSchema.java
index e97017f..d4c7bb7 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAPlainSchema.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAPlainSchema.java
@@ -82,9 +82,6 @@ public class JPAPlainSchema extends AbstractSchema implements PlainSchema {
     private String conversionPattern;
 
     @Column(nullable = true)
-    private String validatorClass;
-
-    @Column(nullable = true)
     @Lob
     private String enumerationValues;
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/b47d4328/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPACorrelationRule.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPACorrelationRule.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPACorrelationRule.java
new file mode 100644
index 0000000..7b4bb1c
--- /dev/null
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPACorrelationRule.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.persistence.jpa.entity.policy;
+
+import javax.persistence.Entity;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
+import org.apache.syncope.common.lib.types.ImplementationType;
+import org.apache.syncope.core.persistence.api.entity.AnyType;
+import org.apache.syncope.core.persistence.api.entity.Implementation;
+import org.apache.syncope.core.persistence.api.entity.policy.CorrelationRule;
+import org.apache.syncope.core.persistence.api.entity.policy.PullPolicy;
+import org.apache.syncope.core.persistence.jpa.entity.AbstractGeneratedKeyEntity;
+import org.apache.syncope.core.persistence.jpa.entity.JPAAnyType;
+import org.apache.syncope.core.persistence.jpa.entity.JPAImplementation;
+
+@Entity
+@Table(name = JPACorrelationRule.TABLE, uniqueConstraints =
+        @UniqueConstraint(columnNames = { "pullPolicy_id", "anyType_id" }))
+public class JPACorrelationRule extends AbstractGeneratedKeyEntity implements CorrelationRule {
+
+    private static final long serialVersionUID = 4276417265524083919L;
+
+    public static final String TABLE = "CorrelationRule";
+
+    @ManyToOne(optional = false)
+    private JPAPullPolicy pullPolicy;
+
+    @ManyToOne(optional = false)
+    private JPAAnyType anyType;
+
+    @ManyToOne(optional = false)
+    private JPAImplementation implementation;
+
+    @Override
+    public PullPolicy getPullPolicy() {
+        return pullPolicy;
+    }
+
+    @Override
+    public void setPullPolicy(final PullPolicy pullPolicy) {
+        checkType(pullPolicy, JPAPullPolicy.class);
+        this.pullPolicy = (JPAPullPolicy) pullPolicy;
+    }
+
+    @Override
+    public AnyType getAnyType() {
+        return anyType;
+    }
+
+    @Override
+    public void setAnyType(final AnyType anyType) {
+        checkType(anyType, JPAAnyType.class);
+        this.anyType = (JPAAnyType) anyType;
+    }
+
+    @Override
+    public Implementation getImplementation() {
+        return implementation;
+    }
+
+    @Override
+    public void setImplementation(final Implementation implementation) {
+        checkType(implementation, JPAImplementation.class);
+        checkImplementationType(implementation, ImplementationType.PULL_CORRELATION_RULE);
+        this.implementation = (JPAImplementation) implementation;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/b47d4328/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPullPolicy.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPullPolicy.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPullPolicy.java
index e5fb20f..b7d0720 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPullPolicy.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPullPolicy.java
@@ -18,11 +18,20 @@
  */
 package org.apache.syncope.core.persistence.jpa.entity.policy;
 
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import javax.persistence.CascadeType;
 import javax.persistence.Entity;
-import javax.persistence.Lob;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.FetchType;
+import javax.persistence.OneToMany;
 import javax.persistence.Table;
-import org.apache.syncope.common.lib.policy.PullPolicySpec;
-import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
+import javax.validation.constraints.NotNull;
+import org.apache.syncope.common.lib.types.ConflictResolutionAction;
+import org.apache.syncope.core.persistence.api.entity.AnyType;
+import org.apache.syncope.core.persistence.api.entity.policy.CorrelationRule;
 import org.apache.syncope.core.persistence.api.entity.policy.PullPolicy;
 
 @Entity
@@ -33,16 +42,37 @@ public class JPAPullPolicy extends AbstractPolicy implements PullPolicy {
 
     public static final String TABLE = "PullPolicy";
 
-    @Lob
-    private String specification;
+    @Enumerated(EnumType.STRING)
+    @NotNull
+    private ConflictResolutionAction conflictResolutionAction;
+
+    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "pullPolicy")
+    private List<JPACorrelationRule> correlationRules = new ArrayList<>();
+
+    @Override
+    public ConflictResolutionAction getConflictResolutionAction() {
+        return conflictResolutionAction;
+    }
+
+    @Override
+    public void setConflictResolutionAction(final ConflictResolutionAction conflictResolutionAction) {
+        this.conflictResolutionAction = conflictResolutionAction;
+    }
+
+    @Override
+    public boolean add(final CorrelationRule filter) {
+        checkType(filter, JPACorrelationRule.class);
+        return this.correlationRules.add((JPACorrelationRule) filter);
+    }
 
     @Override
-    public PullPolicySpec getSpecification() {
-        return POJOHelper.deserialize(specification, PullPolicySpec.class);
+    public Optional<? extends CorrelationRule> getCorrelationRule(final AnyType anyType) {
+        return correlationRules.stream().
+                filter(rule -> anyType != null && anyType.equals(rule.getAnyType())).findFirst();
     }
 
     @Override
-    public void setSpecification(final PullPolicySpec policy) {
-        this.specification = POJOHelper.serialize(policy);
+    public List<? extends CorrelationRule> getCorrelationRules() {
+        return correlationRules;
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/b47d4328/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPushTaskAnyFilter.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPushTaskAnyFilter.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPushTaskAnyFilter.java
index df2f62c..434e921 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPushTaskAnyFilter.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPushTaskAnyFilter.java
@@ -38,10 +38,10 @@ public class JPAPushTaskAnyFilter extends AbstractGeneratedKeyEntity implements
 
     public static final String TABLE = "PushTaskAnyFilter";
 
-    @ManyToOne
+    @ManyToOne(optional = false)
     private JPAPushTask pushTask;
 
-    @ManyToOne
+    @ManyToOne(optional = false)
     private JPAAnyType anyType;
 
     @NotNull

http://git-wip-us.apache.org/repos/asf/syncope/blob/b47d4328/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ImplementationTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ImplementationTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ImplementationTest.java
index 86acf12..eea08c9 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ImplementationTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ImplementationTest.java
@@ -43,7 +43,7 @@ public class ImplementationTest extends AbstractTest {
         List<Implementation> implementations = implementationDAO.findAll();
         assertFalse(implementations.isEmpty());
 
-        assertEquals(15, implementations.size());
+        assertEquals(16, implementations.size());
 
         implementations = implementationDAO.find(ImplementationType.PULL_ACTIONS);
         assertEquals(1, implementations.size());
@@ -65,6 +65,9 @@ public class ImplementationTest extends AbstractTest {
 
         implementations = implementationDAO.find(ImplementationType.VALIDATOR);
         assertEquals(1, implementations.size());
+
+        implementations = implementationDAO.find(ImplementationType.PULL_CORRELATION_RULE);
+        assertEquals(1, implementations.size());
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/syncope/blob/b47d4328/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PolicyTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PolicyTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PolicyTest.java
index e570aef..abf6ea3 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PolicyTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/PolicyTest.java
@@ -27,9 +27,8 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
 import java.util.List;
 import java.util.UUID;
 import org.apache.commons.lang3.ArrayUtils;
-import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.policy.DefaultPasswordRuleConf;
-import org.apache.syncope.common.lib.policy.PullPolicySpec;
+import org.apache.syncope.common.lib.types.ConflictResolutionAction;
 import org.apache.syncope.common.lib.types.ImplementationEngine;
 import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
@@ -39,11 +38,13 @@ import org.apache.syncope.core.persistence.api.dao.PolicyDAO;
 import org.apache.syncope.core.persistence.api.entity.Implementation;
 import org.apache.syncope.core.persistence.api.entity.policy.PasswordPolicy;
 import org.apache.syncope.core.persistence.api.entity.Policy;
+import org.apache.syncope.core.persistence.api.entity.policy.CorrelationRule;
 import org.apache.syncope.core.persistence.jpa.AbstractTest;
 import org.junit.jupiter.api.Test;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Transactional;
 import org.apache.syncope.core.persistence.api.entity.policy.PullPolicy;
+import org.apache.syncope.core.provisioning.api.pushpull.PullCorrelationRule;
 
 @Transactional("Master")
 public class PolicyTest extends AbstractTest {
@@ -69,12 +70,9 @@ public class PolicyTest extends AbstractTest {
         PullPolicy policy = policyDAO.find("880f8553-069b-4aed-9930-2cd53873f544");
         assertNotNull(policy);
 
-        PullPolicySpec spec = policy.getSpecification();
-        assertNotNull(spec);
-
-        String rule = spec.getCorrelationRules().get(AnyTypeKind.USER.name());
+        CorrelationRule rule = policy.getCorrelationRule(anyTypeDAO.findUser()).orElse(null);
         assertNotNull(rule);
-        String[] plainSchemas = POJOHelper.deserialize(rule, String[].class);
+        String[] plainSchemas = POJOHelper.deserialize(rule.getImplementation().getBody(), String[].class);
         assertNotNull(plainSchemas);
         assertEquals(2, plainSchemas.length);
         assertTrue(ArrayUtils.contains(plainSchemas, "username"));
@@ -91,25 +89,45 @@ public class PolicyTest extends AbstractTest {
     @Test
     public void create() {
         PullPolicy policy = entityFactory.newEntity(PullPolicy.class);
+        policy.setConflictResolutionAction(ConflictResolutionAction.IGNORE);
+        policy.setDescription("Pull policy");
 
         final String pullURuleName = "net.tirasa.pull.correlation.TirasaURule";
         final String pullGRuleName = "net.tirasa.pull.correlation.TirasaGRule";
 
-        PullPolicySpec pullPolicySpec = new PullPolicySpec();
-
-        pullPolicySpec.getCorrelationRules().put(anyTypeDAO.findUser().getKey(), pullURuleName);
-        pullPolicySpec.getCorrelationRules().put(anyTypeDAO.findGroup().getKey(), pullGRuleName);
-
-        policy.setSpecification(pullPolicySpec);
-        policy.setDescription("Pull policy");
+        Implementation impl1 = entityFactory.newEntity(Implementation.class);
+        impl1.setKey(pullURuleName);
+        impl1.setEngine(ImplementationEngine.JAVA);
+        impl1.setType(ImplementationType.PULL_CORRELATION_RULE);
+        impl1.setBody(PullCorrelationRule.class.getName());
+        impl1 = implementationDAO.save(impl1);
+
+        CorrelationRule rule1 = entityFactory.newEntity(CorrelationRule.class);
+        rule1.setAnyType(anyTypeDAO.findUser());
+        rule1.setPullPolicy(policy);
+        rule1.setImplementation(impl1);
+        policy.add(rule1);
+
+        Implementation impl2 = entityFactory.newEntity(Implementation.class);
+        impl2.setKey(pullGRuleName);
+        impl2.setEngine(ImplementationEngine.JAVA);
+        impl2.setType(ImplementationType.PULL_CORRELATION_RULE);
+        impl2.setBody(PullCorrelationRule.class.getName());
+        impl2 = implementationDAO.save(impl2);
+
+        CorrelationRule rule2 = entityFactory.newEntity(CorrelationRule.class);
+        rule2.setAnyType(anyTypeDAO.findGroup());
+        rule2.setPullPolicy(policy);
+        rule2.setImplementation(impl2);
+        policy.add(rule2);
 
         policy = policyDAO.save(policy);
 
         assertNotNull(policy);
         assertEquals(pullURuleName,
-                policy.getSpecification().getCorrelationRules().get(anyTypeDAO.findUser().getKey()));
+                policy.getCorrelationRule(anyTypeDAO.findUser()).get().getImplementation().getKey());
         assertEquals(pullGRuleName,
-                policy.getSpecification().getCorrelationRules().get(anyTypeDAO.findGroup().getKey()));
+                policy.getCorrelationRule(anyTypeDAO.findGroup()).get().getImplementation().getKey());
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/syncope/blob/b47d4328/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/TaskTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/TaskTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/TaskTest.java
index d73d25d..5205ffe 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/TaskTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/outer/TaskTest.java
@@ -279,6 +279,7 @@ public class TaskTest extends AbstractTest {
         assertNotNull(resource);
 
         Implementation pullActions = entityFactory.newEntity(Implementation.class);
+        pullActions.setKey("syncope144");
         pullActions.setEngine(ImplementationEngine.JAVA);
         pullActions.setType(ImplementationType.PULL_ACTIONS);
         pullActions.setBody(PullActions.class.getName());

http://git-wip-us.apache.org/repos/asf/syncope/blob/b47d4328/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
index 72a7a44..2a84a81 100644
--- a/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
+++ b/core/persistence-jpa/src/test/resources/domains/MasterContent.xml
@@ -170,15 +170,11 @@ under the License.
                    attribute_id="ae7ae53a-74cf-48b0-9a57-6d2c94928e60" longValue="10"/>
   
   <!-- sample policies -->
-  <PullPolicy id="66691e96-285f-4464-bc19-e68384ea4c85" description="a pull policy"
-              specification='{"conflictResolutionAction":"IGNORE"}'/>
   <PasswordPolicy id="ce93fcda-dc3a-4369-a7b0-a6108c261c85" description="a password policy"
                   historyLength="1" allowNullPassword="1"/>
   <Implementation id="DefaultPasswordRuleConf1" type="PASSWORD_RULE" engine="JAVA"
                   body='{"@class":"org.apache.syncope.common.lib.policy.DefaultPasswordRuleConf","maxLength":0,"minLength":8,"nonAlphanumericRequired":false,"alphanumericRequired":false,"digitRequired":false,"lowercaseRequired":false,"uppercaseRequired":false,"mustStartWithDigit":false,"mustntStartWithDigit":false,"mustEndWithDigit":false,"mustntEndWithDigit":false,"mustStartWithNonAlpha":false,"mustStartWithAlpha":false,"mustntStartWithNonAlpha":false,"mustntStartWithAlpha":false,"mustEndWithNonAlpha":false,"mustEndWithAlpha":false,"mustntEndWithNonAlpha":false,"mustntEndWithAlpha":false,"wordsNotPermitted":[],"schemasNotPermitted":[],"prefixesNotPermitted":["notpermitted1","notpermitted2"],"suffixesNotPermitted":[]}'/>
   <PasswordPolicyRule policy_id="ce93fcda-dc3a-4369-a7b0-a6108c261c85" implementation_id="DefaultPasswordRuleConf1"/>
-  <PullPolicy id="880f8553-069b-4aed-9930-2cd53873f544" description="another pull policy"
-              specification='{"conflictResolutionAction":"ALL","correlationRules":{"USER":"[\"username\",\"firstname\"]"}}'/>
   <PasswordPolicy id="986d1236-3ac5-4a19-810c-5ab21d79cba1"
                   description="sample password policy" historyLength="0" allowNullPassword="1"/> 
   <Implementation id="DefaultPasswordRuleConf2" type="PASSWORD_RULE"  engine="JAVA"
@@ -194,13 +190,10 @@ under the License.
   <Implementation id="DefaultAccountRuleConf2" type="ACCOUNT_RULE"  engine="JAVA"
                   body='{"@class":"org.apache.syncope.common.lib.policy.DefaultAccountRuleConf","maxLength":0,"minLength":4,"pattern":null,"allUpperCase":false,"allLowerCase":false,"wordsNotPermitted":[],"schemasNotPermitted":[],"prefixesNotPermitted":["notpermitted1","notpermitted2"],"suffixesNotPermitted":[]}'/>
   <AccountPolicyRule policy_id="06e2ed52-6966-44aa-a177-a0ca7434201f" implementation_id="DefaultAccountRuleConf2"/>
-  <PullPolicy id="4ad10d94-e002-4b3f-b771-16089cc71da9" description="pull policy 1" specification='{"conflictResolutionAction":"IGNORE"}'/>
   <PasswordPolicy id="55e5de0b-c79c-4e66-adda-251b6fb8579a" description="sample password policy" historyLength="0" allowNullPassword="0"/> 
   <Implementation id="DefaultPasswordRuleConf3" type="PASSWORD_RULE" engine="JAVA"
                   body='{"@class":"org.apache.syncope.common.lib.policy.DefaultPasswordRuleConf","maxLength":0,"minLength":10,"nonAlphanumericRequired":true,"alphanumericRequired":false,"digitRequired":true,"lowercaseRequired":true,"uppercaseRequired":true,"mustStartWithDigit":true,"mustntStartWithDigit":false,"mustEndWithDigit":true,"mustntEndWithDigit":false,"mustStartWithNonAlpha":false,"mustStartWithAlpha":false,"mustntStartWithNonAlpha":false,"mustntStartWithAlpha":false,"mustEndWithNonAlpha":false,"mustEndWithAlpha":false,"mustntEndWithNonAlpha":false,"mustntEndWithAlpha":false,"wordsNotPermitted":[],"schemasNotPermitted":[],"prefixesNotPermitted":["notpermitted1","notpermitted2"],"suffixesNotPermitted":[]}'/>
   <PasswordPolicyRule policy_id="55e5de0b-c79c-4e66-adda-251b6fb8579a" implementation_id="DefaultPasswordRuleConf3"/>
-  <PullPolicy id="9454b0d7-2610-400a-be82-fc23cf553dd6" description="pull policy for java rule"
-              specification='{"conflictResolutionAction":"IGNORE"}'/>
 
   <RelationshipType id="inclusion" description="Models the act that an object is included in another"/>
   <RelationshipType id="neighborhood" description="Models the act that an object is near another"/>
@@ -638,6 +631,16 @@ under the License.
   <GPlainAttr id="22690472-ed3f-4972-8979-4c9251fab044" owner_id="ba9ed509-b1f5-48ab-a334-c8530a6422dc" schema_id="title"/>
   <GPlainAttrValue attribute_id="22690472-ed3f-4972-8979-4c9251fab044" id="e16765e6-f806-469e-ae34-1ddf56f2102a" stringValue="r13"/>
 
+  <!-- pull policies -->
+  <PullPolicy id="66691e96-285f-4464-bc19-e68384ea4c85" description="a pull policy" conflictResolutionAction="IGNORE"/>
+  <PullPolicy id="880f8553-069b-4aed-9930-2cd53873f544" description="another pull policy" conflictResolutionAction="ALL"/>
+  <Implementation id="TestPullCorrelationRule" type="PULL_CORRELATION_RULE" engine="JAVA"
+                  body='["username","firstname"]'/>
+  <CorrelationRule id="10e3d196-7486-4c88-aefd-59e40d93a0c1" pullPolicy_id="880f8553-069b-4aed-9930-2cd53873f544" 
+                   anyType_id="USER" implementation_id="TestPullCorrelationRule"/>
+  <PullPolicy id="4ad10d94-e002-4b3f-b771-16089cc71da9" description="pull policy 1" conflictResolutionAction="IGNORE"/>
+  <PullPolicy id="9454b0d7-2610-400a-be82-fc23cf553dd6" description="pull policy for java rule" conflictResolutionAction="IGNORE"/>
+
   <ConnInstance id="88a7a819-dab5-46b4-9b90-0b9769eabdb8" displayName="ConnInstance100"
                 adminRealm_id="e4c28e7a-9dbf-4ee7-9441-93812a0d4a28"
                 location="${connid.location}"