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 2019/03/29 15:46:53 UTC

[syncope] branch master updated: [SYNCOPE-1410] Manage implementation types as Entitlements, e.g. allow for custom

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

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


The following commit(s) were added to refs/heads/master by this push:
     new ce9d79d  [SYNCOPE-1410] Manage implementation types as Entitlements, e.g. allow for custom
ce9d79d is described below

commit ce9d79d9907448298b7809fe41f7746a890c0b19
Author: Francesco Chicchiriccò <il...@apache.org>
AuthorDate: Fri Mar 29 16:46:30 2019 +0100

    [SYNCOPE-1410] Manage implementation types as Entitlements, e.g. allow for custom
---
 .../commons/IdMImplementationInfoProvider.java     | 172 +++++++
 .../console/commons/IdMPolicyTabProvider.java      |  60 +++
 .../policies/ProvisioningPolicyModalPanel.java     |   8 +-
 .../console/policies/PullPolicyDirectoryPanel.java |   0
 .../console/policies/PushPolicyDirectoryPanel.java |   0
 .../client/console/status/ReconTaskPanel.java      |   6 +-
 .../resources/ItemTransformersTogglePanel.java     |   4 +-
 .../wizards/resources/ResourceDetailsPanel.java    |   4 +-
 ...oningPolicyModalPanel$CorrelationRulePanel.html |   0
 .../policies/ProvisioningPolicyModalPanel.html     |   0
 .../ProvisioningPolicyModalPanel.properties        |   0
 .../ProvisioningPolicyModalPanel_it.properties     |   0
 .../ProvisioningPolicyModalPanel_ja.properties     |   0
 .../ProvisioningPolicyModalPanel_pt_BR.properties  |   0
 .../ProvisioningPolicyModalPanel_ru.properties     |   0
 .../client/console/SyncopeWebApplication.java      |  17 +
 .../commons/IdRepoImplementationInfoProvider.java  | 207 +++++++++
 .../IdRepoPolicyTabProvider.java}                  |  54 +--
 .../commons/ImplementationInfoProvider.java        |  40 +-
 .../client/console/commons/PolicyTabProvider.java  |  20 +-
 .../init/ClassPathScanImplementationLookup.java    |  85 +++-
 .../notifications/NotificationWizardBuilder.java   |   4 +-
 .../client/console/pages/Implementations.java      |  15 +-
 .../syncope/client/console/pages/Policies.java     |  60 +--
 .../panels/ImplementationDirectoryPanel.java       |   5 +-
 .../console/panels/ImplementationModalPanel.java   | 161 +------
 .../panels/ParametersCreateWizardSchemaStep.java   |   4 +-
 .../client/console/panels/PlainSchemaDetails.java  |   4 +-
 .../client/console/panels/RealmDetails.java        |   4 +-
 .../console/policies/PolicyRuleDirectoryPanel.java |   8 +-
 .../console/policies/PolicyRuleWizardBuilder.java  |  12 +-
 .../console/reports/ReportletDirectoryPanel.java   |   4 +-
 .../console/reports/ReportletWizardBuilder.java    |  10 +-
 .../console/rest/ImplementationRestClient.java     |   7 +-
 .../console/tasks/SchedTaskWizardBuilder.java      |  60 +--
 .../common/lib/types/IdMImplementationType.java    |  62 +++
 .../syncope/common/lib/info/JavaImplInfo.java      |   7 +-
 .../syncope/common/lib/info/PlatformInfo.java      |  14 +-
 .../syncope/common/lib/to/ImplementationTO.java    |   7 +-
 .../common/lib/types/ClientExceptionType.java      |   1 +
 .../common/lib/types}/EntitlementsHolder.java      |  18 +-
 .../common/lib/types/IdRepoImplementationType.java |  66 +++
 ...ionType.java => ImplementationTypesHolder.java} |  34 +-
 .../{ImplementationType.java => ValueHolder.java}  |  32 +-
 .../rest/api/service/ImplementationService.java    |  22 +-
 .../logic/init/IdMImplementationTypeLoader.java    |  10 +-
 .../org/apache/syncope/core/logic/GroupLogic.java  |   6 +-
 .../syncope/core/logic/ImplementationLogic.java    |  62 ++-
 .../apache/syncope/core/logic/SyncopeLogic.java    |  21 +-
 .../init/ClassPathScanImplementationLookup.java    |  50 +--
 .../core/logic/init/EntitlementAccessor.java       |  11 +-
 .../syncope/core/logic/init/EntitlementLoader.java |   6 +-
 .../logic/init/IdRepoImplementationTypeLoader.java |  10 +-
 .../cxf/service/ImplementationServiceImpl.java     |   8 +-
 .../core/persistence/api/ImplementationLookup.java |   3 +-
 .../persistence/api/dao/ImplementationDAO.java     |   4 +-
 .../persistence/api/entity/Implementation.java     |   5 +-
 .../persistence/jpa/dao/JPAImplementationDAO.java  |   3 +-
 .../persistence/jpa/entity/AbstractEntity.java     |   5 +-
 .../persistence/jpa/entity/JPAImplementation.java  |   9 +-
 .../persistence/jpa/entity/JPANotification.java    |   4 +-
 .../persistence/jpa/entity/JPAPlainSchema.java     |   4 +-
 .../core/persistence/jpa/entity/JPARealm.java      |   4 +-
 .../core/persistence/jpa/entity/JPAReport.java     |   4 +-
 .../policy/AbstractCorrelationRuleEntity.java      |   3 +-
 .../jpa/entity/policy/JPAAccountPolicy.java        |   4 +-
 .../jpa/entity/policy/JPAPasswordPolicy.java       |   4 +-
 .../policy/JPAPullCorrelationRuleEntity.java       |   6 +-
 .../policy/JPAPushCorrelationRuleEntity.java       |   6 +-
 .../jpa/entity/resource/JPAExternalResource.java   |   4 +-
 .../jpa/entity/resource/JPAMappingItem.java        |   5 +-
 .../jpa/entity/resource/JPAOrgUnitItem.java        |   4 +-
 .../persistence/jpa/entity/task/JPAPullTask.java   |   6 +-
 .../persistence/jpa/entity/task/JPAPushTask.java   |   4 +-
 .../persistence/jpa/entity/task/JPASchedTask.java  |   4 +-
 .../persistence/jpa/DummyImplementationLookup.java |   3 +-
 .../persistence/jpa/inner/ImplementationTest.java  |  23 +-
 .../core/persistence/jpa/inner/PolicyTest.java     |   9 +-
 .../core/persistence/jpa/inner/ReportTest.java     |   6 +-
 .../core/persistence/jpa/outer/TaskTest.java       |   6 +-
 .../java/data/AnyTypeDataBinderImpl.java           |   2 +-
 .../java/data/ImplementationDataBinderImpl.java    | 108 ++---
 .../provisioning/java/data/TaskDataBinderImpl.java |  10 +-
 .../core/provisioning/java/job/JobManagerImpl.java |   6 +-
 .../java/pushpull/SinglePullJobDelegate.java       |   4 +-
 .../java/pushpull/SinglePushJobDelegate.java       |   4 +-
 .../java/DummyImplementationLookup.java            |   3 +-
 .../core/spring/security/AuthContextUtils.java     |   2 +-
 .../core/spring/security/AuthDataAccessor.java     |   2 +-
 .../spring/security/DummyImplementationLookup.java |   3 +-
 .../core/spring/security/TestImplementation.java   |   8 +-
 .../syncope/core/logic/init/CamelRouteLoader.java  |   4 +-
 .../syncope/core/logic/init/FlowableLoader.java    |   4 +-
 .../syncope/core/logic/init/OIDCClientLoader.java  |   4 +-
 .../jpa/entity/JPAOIDCProviderItem.java            |   4 +-
 .../syncope/core/logic/init/SAML2SPLoader.java     |   4 +-
 .../persistence/jpa/entity/JPASAML2IdPItem.java    |   4 +-
 .../apache/syncope/core/logic/init/SCIMLoader.java |   4 +-
 .../syncope/core/logic/init/ElasticsearchInit.java |   6 +-
 .../fit/core/reference/ITImplementationLookup.java |  48 +-
 .../syncope/fit/core/ImplementationITCase.java     |   8 +-
 .../syncope/fit/core/NotificationTaskITCase.java   |   4 +-
 .../org/apache/syncope/fit/core/PolicyITCase.java  |  22 +-
 .../syncope/fit/core/PropagationTaskITCase.java    |  10 +-
 .../apache/syncope/fit/core/PullTaskITCase.java    |  21 +-
 .../apache/syncope/fit/core/PushTaskITCase.java    |   4 +-
 .../org/apache/syncope/fit/core/RealmITCase.java   |   4 +-
 .../org/apache/syncope/fit/core/ReportITCase.java  |  20 +-
 .../apache/syncope/fit/core/ResourceITCase.java    |   4 +-
 .../apache/syncope/fit/core/SchedTaskITCase.java   |  10 +-
 .../org/apache/syncope/fit/core/UserITCase.java    |   8 +-
 .../apache/syncope/fit/core/UserIssuesITCase.java  |  14 +-
 .../syncope/ide/netbeans/ResourceConnector.java    |  16 +
 .../service/ImplementationManagerService.java      |   7 +-
 .../netbeans/service/SyncopeManagerService.java    |  26 +-
 .../view/ResourceExplorerTopComponent.java         | 498 +++++++++------------
 116 files changed, 1420 insertions(+), 1114 deletions(-)

diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/commons/IdMImplementationInfoProvider.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/commons/IdMImplementationInfoProvider.java
new file mode 100644
index 0000000..4873fdf
--- /dev/null
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/commons/IdMImplementationInfoProvider.java
@@ -0,0 +1,172 @@
+/*
+ * 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.client.console.commons;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.apache.syncope.client.console.init.ClassPathScanImplementationLookup;
+import org.apache.syncope.common.lib.to.EntityTO;
+import org.apache.syncope.common.lib.to.ImplementationTO;
+import org.apache.syncope.common.lib.types.IdMImplementationType;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.LoadableDetachableModel;
+
+public class IdMImplementationInfoProvider extends IdRepoImplementationInfoProvider {
+
+    private static final long serialVersionUID = -5385695412826366167L;
+
+    public IdMImplementationInfoProvider(final ClassPathScanImplementationLookup lookup) {
+        super(lookup);
+    }
+
+    @Override
+    public ViewMode getViewMode(final ImplementationTO implementation) {
+        return IdMImplementationType.PULL_CORRELATION_RULE.equals(implementation.getType())
+                || IdMImplementationType.PUSH_CORRELATION_RULE.equals(implementation.getType())
+                ? ViewMode.JSON_BODY
+                : super.getViewMode(implementation);
+    }
+
+    @Override
+    public List<String> getClasses(final ImplementationTO implementation, final ViewMode viewMode) {
+        List<String> classes = Collections.emptyList();
+        if (viewMode == ViewMode.JSON_BODY) {
+            switch (implementation.getType()) {
+                case IdMImplementationType.PULL_CORRELATION_RULE:
+                    classes = lookup.getPullCorrelationRuleConfs().keySet().stream().
+                            collect(Collectors.toList());
+                    break;
+
+                case IdMImplementationType.PUSH_CORRELATION_RULE:
+                    classes = lookup.getPushCorrelationRuleConfs().keySet().stream().
+                            collect(Collectors.toList());
+                    break;
+
+                default:
+            }
+            Collections.sort(classes);
+        } else {
+            classes = super.getClasses(implementation, viewMode);
+        }
+
+        return classes;
+    }
+
+    @Override
+    public String getGroovyTemplateClassName(final String implementationType) {
+        String templateClassName = null;
+
+        switch (implementationType) {
+            case IdMImplementationType.ITEM_TRANSFORMER:
+                templateClassName = "MyItemTransformer";
+                break;
+
+            case IdMImplementationType.RECON_FILTER_BUILDER:
+                templateClassName = "MyReconFilterBuilder";
+                break;
+
+            case IdMImplementationType.PROPAGATION_ACTIONS:
+                templateClassName = "MyPropagationActions";
+                break;
+
+            case IdMImplementationType.PULL_ACTIONS:
+                templateClassName = "MyPullActions";
+                break;
+
+            case IdMImplementationType.PUSH_ACTIONS:
+                templateClassName = "MyPushActions";
+                break;
+
+            case IdMImplementationType.PULL_CORRELATION_RULE:
+                templateClassName = "MyPullCorrelationRule";
+                break;
+
+            case IdMImplementationType.PUSH_CORRELATION_RULE:
+                templateClassName = "MyPushCorrelationRule";
+                break;
+
+            default:
+                templateClassName = super.getGroovyTemplateClassName(implementationType);
+        }
+
+        return templateClassName;
+    }
+
+    @Override
+    public Class<?> getClass(final String implementationType, final String name) {
+        Class<?> clazz = null;
+        switch (implementationType) {
+            case IdMImplementationType.PULL_CORRELATION_RULE:
+                clazz = lookup.getPullCorrelationRuleConfs().get(name);
+                break;
+
+            case IdMImplementationType.PUSH_CORRELATION_RULE:
+                clazz = lookup.getPushCorrelationRuleConfs().get(name);
+                break;
+
+            default:
+                clazz = super.getClass(implementationType, name);
+        }
+
+        return clazz;
+    }
+
+    @Override
+    public IModel<List<String>> getReconFilterBuilders() {
+        return new LoadableDetachableModel<List<String>>() {
+
+            private static final long serialVersionUID = 5275935387613157437L;
+
+            @Override
+            protected List<String> load() {
+                return implRestClient.list(IdMImplementationType.RECON_FILTER_BUILDER).stream().
+                        map(EntityTO::getKey).sorted().collect(Collectors.toList());
+            }
+        };
+    }
+
+    @Override
+    public IModel<List<String>> getPullActions() {
+        return new LoadableDetachableModel<List<String>>() {
+
+            private static final long serialVersionUID = 5275935387613157437L;
+
+            @Override
+            protected List<String> load() {
+                return implRestClient.list(IdMImplementationType.PULL_ACTIONS).stream().
+                        map(EntityTO::getKey).sorted().collect(Collectors.toList());
+            }
+        };
+    }
+
+    @Override
+    public IModel<List<String>> getPushActions() {
+        return new LoadableDetachableModel<List<String>>() {
+
+            private static final long serialVersionUID = 5275935387613157437L;
+
+            @Override
+            protected List<String> load() {
+                return implRestClient.list(IdMImplementationType.PUSH_ACTIONS).stream().
+                        map(EntityTO::getKey).sorted().collect(Collectors.toList());
+            }
+        };
+    }
+}
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/commons/IdMPolicyTabProvider.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/commons/IdMPolicyTabProvider.java
new file mode 100644
index 0000000..d3b1630
--- /dev/null
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/commons/IdMPolicyTabProvider.java
@@ -0,0 +1,60 @@
+/*
+ * 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.client.console.commons;
+
+import java.util.List;
+import org.apache.syncope.client.console.policies.PullPolicyDirectoryPanel;
+import org.apache.syncope.client.console.policies.PushPolicyDirectoryPanel;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.extensions.markup.html.tabs.AbstractTab;
+import org.apache.wicket.extensions.markup.html.tabs.ITab;
+import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.model.ResourceModel;
+
+public class IdMPolicyTabProvider extends IdRepoPolicyTabProvider {
+
+    private static final long serialVersionUID = 2822554006571803418L;
+
+    @Override
+    public List<ITab> buildTabList(final PageReference pageRef) {
+        List<ITab> tabs = super.buildTabList(pageRef);
+
+        tabs.add(new AbstractTab(new ResourceModel("policy.pull")) {
+
+            private static final long serialVersionUID = -6815067322125799251L;
+
+            @Override
+            public Panel getPanel(final String panelId) {
+                return new PullPolicyDirectoryPanel(panelId, pageRef);
+            }
+        });
+
+        tabs.add(new AbstractTab(new ResourceModel("policy.push")) {
+
+            private static final long serialVersionUID = -6815067322125799251L;
+
+            @Override
+            public Panel getPanel(final String panelId) {
+                return new PushPolicyDirectoryPanel(panelId, pageRef);
+            }
+        });
+
+        return tabs;
+    }
+}
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/ProvisioningPolicyModalPanel.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/policies/ProvisioningPolicyModalPanel.java
similarity index 98%
rename from client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/ProvisioningPolicyModalPanel.java
rename to client/idm/console/src/main/java/org/apache/syncope/client/console/policies/ProvisioningPolicyModalPanel.java
index 629c0be..0f114ce 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/ProvisioningPolicyModalPanel.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/policies/ProvisioningPolicyModalPanel.java
@@ -49,8 +49,8 @@ import org.apache.syncope.common.lib.policy.PullPolicyTO;
 import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.syncope.common.lib.to.ImplementationTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.IdMImplementationType;
 import org.apache.syncope.common.lib.types.ImplementationEngine;
-import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.common.lib.types.PolicyType;
 import org.apache.syncope.common.lib.types.SchemaType;
 import org.apache.wicket.PageReference;
@@ -74,7 +74,7 @@ public class ProvisioningPolicyModalPanel extends AbstractModalPanel<Provisionin
 
     private final SchemaRestClient schemaRestClient = new SchemaRestClient();
 
-    private final LoadableDetachableModel<Map<String, ImplementationTO>> implementations;
+    private final IModel<Map<String, ImplementationTO>> implementations;
 
     private final IModel<List<CorrelationRule>> model;
 
@@ -94,8 +94,8 @@ public class ProvisioningPolicyModalPanel extends AbstractModalPanel<Provisionin
             @Override
             protected Map<String, ImplementationTO> load() {
                 return implRestClient.list(policyTO instanceof PullPolicyTO
-                        ? ImplementationType.PULL_CORRELATION_RULE
-                        : ImplementationType.PUSH_CORRELATION_RULE).stream().
+                        ? IdMImplementationType.PULL_CORRELATION_RULE
+                        : IdMImplementationType.PUSH_CORRELATION_RULE).stream().
                         collect(Collectors.toMap(EntityTO::getKey, Function.identity()));
             }
         };
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/PullPolicyDirectoryPanel.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/policies/PullPolicyDirectoryPanel.java
similarity index 100%
rename from client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/PullPolicyDirectoryPanel.java
rename to client/idm/console/src/main/java/org/apache/syncope/client/console/policies/PullPolicyDirectoryPanel.java
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/PushPolicyDirectoryPanel.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/policies/PushPolicyDirectoryPanel.java
similarity index 100%
rename from client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/PushPolicyDirectoryPanel.java
rename to client/idm/console/src/main/java/org/apache/syncope/client/console/policies/PushPolicyDirectoryPanel.java
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/status/ReconTaskPanel.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/status/ReconTaskPanel.java
index 31cb9b8..8cf5010 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/status/ReconTaskPanel.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/status/ReconTaskPanel.java
@@ -36,7 +36,7 @@ import org.apache.syncope.common.lib.to.ProvisioningTaskTO;
 import org.apache.syncope.common.lib.to.PullTaskTO;
 import org.apache.syncope.common.lib.to.PushTaskTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
-import org.apache.syncope.common.lib.types.ImplementationType;
+import org.apache.syncope.common.lib.types.IdMImplementationType;
 import org.apache.syncope.common.lib.types.MatchingRule;
 import org.apache.syncope.common.lib.types.UnmatchingRule;
 import org.apache.wicket.PageReference;
@@ -67,7 +67,7 @@ public class ReconTaskPanel extends MultilevelPanel.SecondLevel {
 
         @Override
         protected List<String> load() {
-            return implRestClient.list(ImplementationType.PULL_ACTIONS).stream().
+            return implRestClient.list(IdMImplementationType.PULL_ACTIONS).stream().
                     map(EntityTO::getKey).sorted().collect(Collectors.toList());
         }
     };
@@ -78,7 +78,7 @@ public class ReconTaskPanel extends MultilevelPanel.SecondLevel {
 
         @Override
         protected List<String> load() {
-            return implRestClient.list(ImplementationType.PUSH_ACTIONS).stream().
+            return implRestClient.list(IdMImplementationType.PUSH_ACTIONS).stream().
                     map(EntityTO::getKey).sorted().collect(Collectors.toList());
         }
     };
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ItemTransformersTogglePanel.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ItemTransformersTogglePanel.java
index 8905016..dfd00fb 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ItemTransformersTogglePanel.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ItemTransformersTogglePanel.java
@@ -28,7 +28,7 @@ import org.apache.syncope.client.console.rest.ImplementationRestClient;
 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxPalettePanel;
 import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.syncope.common.lib.to.ItemTO;
-import org.apache.syncope.common.lib.types.ImplementationType;
+import org.apache.syncope.common.lib.types.IdMImplementationType;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.ajax.markup.html.form.AjaxSubmitLink;
@@ -66,7 +66,7 @@ public class ItemTransformersTogglePanel extends TogglePanel<Serializable> {
         Form<?> form = new Form<>("form");
         addInnerObject(form);
 
-        List<String> choices = implRestClient.list(ImplementationType.ITEM_TRANSFORMER).stream().
+        List<String> choices = implRestClient.list(IdMImplementationType.ITEM_TRANSFORMER).stream().
                 map(EntityTO::getKey).sorted().collect(Collectors.toList());
 
         form.add(new AjaxPalettePanel.Builder<String>().setAllowOrder(true).setRenderer(new IChoiceRenderer<String>() {
diff --git a/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel.java b/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel.java
index 6d40209..6d2d686 100644
--- a/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel.java
+++ b/client/idm/console/src/main/java/org/apache/syncope/client/console/wizards/resources/ResourceDetailsPanel.java
@@ -29,7 +29,7 @@ import org.apache.syncope.client.ui.commons.markup.html.form.AjaxSpinnerFieldPan
 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
 import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.syncope.common.lib.to.ResourceTO;
-import org.apache.syncope.common.lib.types.ImplementationType;
+import org.apache.syncope.common.lib.types.IdMImplementationType;
 import org.apache.syncope.common.lib.types.TraceLevel;
 import org.apache.wicket.extensions.wizard.WizardStep;
 import org.apache.wicket.markup.html.WebMarkupContainer;
@@ -52,7 +52,7 @@ public class ResourceDetailsPanel extends WizardStep {
 
         @Override
         protected List<String> load() {
-            return implRestClient.list(ImplementationType.PROPAGATION_ACTIONS).stream().
+            return implRestClient.list(IdMImplementationType.PROPAGATION_ACTIONS).stream().
                     map(EntityTO::getKey).sorted().collect(Collectors.toList());
         }
     };
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/policies/ProvisioningPolicyModalPanel$CorrelationRulePanel.html b/client/idm/console/src/main/resources/org/apache/syncope/client/console/policies/ProvisioningPolicyModalPanel$CorrelationRulePanel.html
similarity index 100%
rename from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/policies/ProvisioningPolicyModalPanel$CorrelationRulePanel.html
rename to client/idm/console/src/main/resources/org/apache/syncope/client/console/policies/ProvisioningPolicyModalPanel$CorrelationRulePanel.html
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/policies/ProvisioningPolicyModalPanel.html b/client/idm/console/src/main/resources/org/apache/syncope/client/console/policies/ProvisioningPolicyModalPanel.html
similarity index 100%
rename from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/policies/ProvisioningPolicyModalPanel.html
rename to client/idm/console/src/main/resources/org/apache/syncope/client/console/policies/ProvisioningPolicyModalPanel.html
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/policies/ProvisioningPolicyModalPanel.properties b/client/idm/console/src/main/resources/org/apache/syncope/client/console/policies/ProvisioningPolicyModalPanel.properties
similarity index 100%
rename from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/policies/ProvisioningPolicyModalPanel.properties
rename to client/idm/console/src/main/resources/org/apache/syncope/client/console/policies/ProvisioningPolicyModalPanel.properties
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/policies/ProvisioningPolicyModalPanel_it.properties b/client/idm/console/src/main/resources/org/apache/syncope/client/console/policies/ProvisioningPolicyModalPanel_it.properties
similarity index 100%
rename from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/policies/ProvisioningPolicyModalPanel_it.properties
rename to client/idm/console/src/main/resources/org/apache/syncope/client/console/policies/ProvisioningPolicyModalPanel_it.properties
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/policies/ProvisioningPolicyModalPanel_ja.properties b/client/idm/console/src/main/resources/org/apache/syncope/client/console/policies/ProvisioningPolicyModalPanel_ja.properties
similarity index 100%
rename from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/policies/ProvisioningPolicyModalPanel_ja.properties
rename to client/idm/console/src/main/resources/org/apache/syncope/client/console/policies/ProvisioningPolicyModalPanel_ja.properties
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/policies/ProvisioningPolicyModalPanel_pt_BR.properties b/client/idm/console/src/main/resources/org/apache/syncope/client/console/policies/ProvisioningPolicyModalPanel_pt_BR.properties
similarity index 100%
rename from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/policies/ProvisioningPolicyModalPanel_pt_BR.properties
rename to client/idm/console/src/main/resources/org/apache/syncope/client/console/policies/ProvisioningPolicyModalPanel_pt_BR.properties
diff --git a/client/idrepo/console/src/main/resources/org/apache/syncope/client/console/policies/ProvisioningPolicyModalPanel_ru.properties b/client/idm/console/src/main/resources/org/apache/syncope/client/console/policies/ProvisioningPolicyModalPanel_ru.properties
similarity index 100%
rename from client/idrepo/console/src/main/resources/org/apache/syncope/client/console/policies/ProvisioningPolicyModalPanel_ru.properties
rename to client/idm/console/src/main/resources/org/apache/syncope/client/console/policies/ProvisioningPolicyModalPanel_ru.properties
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/SyncopeWebApplication.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/SyncopeWebApplication.java
index a9356b9..ecf17d0 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/SyncopeWebApplication.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/SyncopeWebApplication.java
@@ -69,6 +69,8 @@ import org.apache.wicket.util.lang.Args;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.apache.syncope.client.console.commons.ExternalResourceProvider;
+import org.apache.syncope.client.console.commons.ImplementationInfoProvider;
+import org.apache.syncope.client.console.commons.PolicyTabProvider;
 import org.apache.syncope.client.console.commons.StatusProvider;
 import org.apache.syncope.client.console.commons.VirSchemaDetailsPanelProvider;
 import org.apache.syncope.client.ui.commons.SyncopeUIRequestCycleListener;
@@ -138,6 +140,10 @@ public class SyncopeWebApplication extends WicketBootSecuredWebApplication {
 
     private AnyDirectoryPanelAditionalActionLinksProvider anyDirectoryPanelAditionalActionLinksProvider;
 
+    private ImplementationInfoProvider implementationInfoProvider;
+
+    private PolicyTabProvider policyTabProvider;
+
     private Map<String, Class<? extends BasePage>> pageClasses;
 
     @SuppressWarnings("unchecked")
@@ -225,6 +231,9 @@ public class SyncopeWebApplication extends WicketBootSecuredWebApplication {
         statusProvider = lookup.getStatusProvider();
         virSchemaDetailsPanelProvider = lookup.getVirSchemaDetailsPanelProvider();
         anyDirectoryPanelAditionalActionLinksProvider = lookup.getAnyDirectoryPanelAditionalActionLinksProvider();
+        implementationInfoProvider = lookup.getImplementationInfoProvider();
+        policyTabProvider = lookup.getPolicyTabProvider();
+
         lookup.getPageClasses().
                 forEach(cls -> MetaDataRoleAuthorizationStrategy.authorize(cls, Constants.ROLE_AUTHENTICATED));
 
@@ -397,4 +406,12 @@ public class SyncopeWebApplication extends WicketBootSecuredWebApplication {
     public AnyDirectoryPanelAditionalActionLinksProvider getAnyDirectoryPanelAditionalActionLinksProvider() {
         return anyDirectoryPanelAditionalActionLinksProvider;
     }
+
+    public ImplementationInfoProvider getImplementationInfoProvider() {
+        return implementationInfoProvider;
+    }
+
+    public PolicyTabProvider getPolicyTabProvider() {
+        return policyTabProvider;
+    }
 }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/IdRepoImplementationInfoProvider.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/IdRepoImplementationInfoProvider.java
new file mode 100644
index 0000000..5ac63af
--- /dev/null
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/IdRepoImplementationInfoProvider.java
@@ -0,0 +1,207 @@
+/*
+ * 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.client.console.commons;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import org.apache.syncope.client.console.SyncopeConsoleSession;
+import org.apache.syncope.client.console.init.ClassPathScanImplementationLookup;
+import org.apache.syncope.client.console.rest.ImplementationRestClient;
+import org.apache.syncope.common.lib.info.JavaImplInfo;
+import org.apache.syncope.common.lib.to.EntityTO;
+import org.apache.syncope.common.lib.to.ImplementationTO;
+import org.apache.syncope.common.lib.types.IdRepoImplementationType;
+import org.apache.syncope.common.lib.types.ImplementationEngine;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.LoadableDetachableModel;
+
+public class IdRepoImplementationInfoProvider implements ImplementationInfoProvider {
+
+    private static final long serialVersionUID = -6620368595630782392L;
+
+    protected final ClassPathScanImplementationLookup lookup;
+
+    protected final ImplementationRestClient implRestClient = new ImplementationRestClient();
+
+    public IdRepoImplementationInfoProvider(final ClassPathScanImplementationLookup lookup) {
+        this.lookup = lookup;
+    }
+
+    @Override
+    public ViewMode getViewMode(final ImplementationTO implementation) {
+        return implementation.getEngine() == ImplementationEngine.GROOVY
+                ? ViewMode.GROOVY_BODY
+                : IdRepoImplementationType.REPORTLET.equals(implementation.getType())
+                || IdRepoImplementationType.ACCOUNT_RULE.equals(implementation.getType())
+                || IdRepoImplementationType.PASSWORD_RULE.equals(implementation.getType())
+                ? ViewMode.JSON_BODY
+                : ViewMode.JAVA_CLASS;
+    }
+
+    @Override
+    public List<String> getClasses(final ImplementationTO implementation, final ViewMode viewMode) {
+        List<String> classes = Collections.emptyList();
+        if (viewMode == ViewMode.JAVA_CLASS) {
+            Optional<JavaImplInfo> javaClasses = SyncopeConsoleSession.get().getPlatformInfo().
+                    getJavaImplInfo(implementation.getType());
+            classes = javaClasses.isPresent()
+                    ? new ArrayList<>(javaClasses.get().getClasses())
+                    : new ArrayList<>();
+        } else if (viewMode == ViewMode.JSON_BODY) {
+            switch (implementation.getType()) {
+                case IdRepoImplementationType.REPORTLET:
+                    classes = lookup.getReportletConfs().keySet().stream().
+                            collect(Collectors.toList());
+                    break;
+
+                case IdRepoImplementationType.ACCOUNT_RULE:
+                    classes = lookup.getAccountRuleConfs().keySet().stream().
+                            collect(Collectors.toList());
+                    break;
+
+                case IdRepoImplementationType.PASSWORD_RULE:
+                    classes = lookup.getPasswordRuleConfs().keySet().stream().
+                            collect(Collectors.toList());
+                    break;
+
+                default:
+            }
+        }
+        Collections.sort(classes);
+
+        return classes;
+    }
+
+    @Override
+    public String getGroovyTemplateClassName(final String implementationType) {
+        String templateClassName = null;
+
+        switch (implementationType) {
+            case IdRepoImplementationType.REPORTLET:
+                templateClassName = "MyReportlet";
+                break;
+
+            case IdRepoImplementationType.ACCOUNT_RULE:
+                templateClassName = "MyAccountRule";
+                break;
+
+            case IdRepoImplementationType.PASSWORD_RULE:
+                templateClassName = "MyPasswordRule";
+                break;
+
+            case IdRepoImplementationType.TASKJOB_DELEGATE:
+                templateClassName = "MySchedTaskJobDelegate";
+                break;
+
+            case IdRepoImplementationType.LOGIC_ACTIONS:
+                templateClassName = "MyLogicActions";
+                break;
+
+            case IdRepoImplementationType.VALIDATOR:
+                templateClassName = "MyValidator";
+                break;
+
+            case IdRepoImplementationType.RECIPIENTS_PROVIDER:
+                templateClassName = "MyRecipientsProvider";
+                break;
+
+            default:
+        }
+
+        return templateClassName;
+    }
+
+    @Override
+    public Class<?> getClass(final String implementationType, final String name) {
+        Class<?> clazz = null;
+        switch (implementationType) {
+            case IdRepoImplementationType.REPORTLET:
+                clazz = lookup.getReportletConfs().get(name);
+                break;
+
+            case IdRepoImplementationType.ACCOUNT_RULE:
+                clazz = lookup.getAccountRuleConfs().get(name);
+                break;
+
+            case IdRepoImplementationType.PASSWORD_RULE:
+                clazz = lookup.getPasswordRuleConfs().get(name);
+                break;
+
+            default:
+        }
+
+        return clazz;
+    }
+
+    @Override
+    public IModel<List<String>> getTaskJobDelegates() {
+        return new LoadableDetachableModel<List<String>>() {
+
+            private static final long serialVersionUID = 5275935387613157437L;
+
+            @Override
+            protected List<String> load() {
+                return implRestClient.list(IdRepoImplementationType.TASKJOB_DELEGATE).stream().
+                        map(EntityTO::getKey).sorted().collect(Collectors.toList());
+            }
+        };
+    }
+
+    @Override
+    public IModel<List<String>> getReconFilterBuilders() {
+        return new LoadableDetachableModel<List<String>>() {
+
+            private static final long serialVersionUID = 5275935387613157437L;
+
+            @Override
+            protected List<String> load() {
+                return Collections.emptyList();
+            }
+        };
+    }
+
+    @Override
+    public IModel<List<String>> getPullActions() {
+        return new LoadableDetachableModel<List<String>>() {
+
+            private static final long serialVersionUID = 5275935387613157437L;
+
+            @Override
+            protected List<String> load() {
+                return Collections.emptyList();
+            }
+        };
+    }
+
+    @Override
+    public IModel<List<String>> getPushActions() {
+        return new LoadableDetachableModel<List<String>>() {
+
+            private static final long serialVersionUID = 5275935387613157437L;
+
+            @Override
+            protected List<String> load() {
+                return Collections.emptyList();
+            }
+        };
+    }
+}
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/Policies.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/IdRepoPolicyTabProvider.java
similarity index 50%
copy from client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/Policies.java
copy to client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/IdRepoPolicyTabProvider.java
index 294b238..e22d101 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/Policies.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/IdRepoPolicyTabProvider.java
@@ -16,41 +16,25 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.client.console.pages;
+package org.apache.syncope.client.console.commons;
 
-import de.agilecoders.wicket.core.markup.html.bootstrap.tabs.AjaxBootstrapTabbedPanel;
 import java.util.ArrayList;
 import java.util.List;
-import org.apache.syncope.client.console.BookmarkablePageLinkBuilder;
 import org.apache.syncope.client.console.policies.AccountPolicyDirectoryPanel;
 import org.apache.syncope.client.console.policies.PasswordPolicyDirectoryPanel;
-import org.apache.syncope.client.console.policies.PullPolicyDirectoryPanel;
-import org.apache.syncope.client.console.policies.PushPolicyDirectoryPanel;
+import org.apache.wicket.PageReference;
 import org.apache.wicket.extensions.markup.html.tabs.AbstractTab;
 import org.apache.wicket.extensions.markup.html.tabs.ITab;
-import org.apache.wicket.markup.html.WebMarkupContainer;
 import org.apache.wicket.markup.html.panel.Panel;
 import org.apache.wicket.model.ResourceModel;
-import org.apache.wicket.request.mapper.parameter.PageParameters;
 
-public class Policies extends BasePage {
+public class IdRepoPolicyTabProvider implements PolicyTabProvider {
 
-    private static final long serialVersionUID = -1100228004207271271L;
+    private static final long serialVersionUID = 5017230231088263303L;
 
-    public Policies(final PageParameters parameters) {
-        super(parameters);
-
-        body.add(BookmarkablePageLinkBuilder.build("dashboard", "dashboardBr", Dashboard.class));
-
-        WebMarkupContainer content = new WebMarkupContainer("content");
-        content.setOutputMarkupId(true);
-        content.setMarkupId("policies");
-        content.add(new AjaxBootstrapTabbedPanel<>("tabbedPanel", buildTabList()));
-        body.add(content);
-    }
-
-    private List<ITab> buildTabList() {
-        final List<ITab> tabs = new ArrayList<>();
+    @Override
+    public List<ITab> buildTabList(final PageReference pageRef) {
+        List<ITab> tabs = new ArrayList<>();
 
         tabs.add(new AbstractTab(new ResourceModel("policy.account")) {
 
@@ -58,7 +42,7 @@ public class Policies extends BasePage {
 
             @Override
             public Panel getPanel(final String panelId) {
-                return new AccountPolicyDirectoryPanel(panelId, getPageReference());
+                return new AccountPolicyDirectoryPanel(panelId, pageRef);
             }
         });
 
@@ -68,27 +52,7 @@ public class Policies extends BasePage {
 
             @Override
             public Panel getPanel(final String panelId) {
-                return new PasswordPolicyDirectoryPanel(panelId, getPageReference());
-            }
-        });
-
-        tabs.add(new AbstractTab(new ResourceModel("policy.pull")) {
-
-            private static final long serialVersionUID = -6815067322125799251L;
-
-            @Override
-            public Panel getPanel(final String panelId) {
-                return new PullPolicyDirectoryPanel(panelId, getPageReference());
-            }
-        });
-
-        tabs.add(new AbstractTab(new ResourceModel("policy.push")) {
-
-            private static final long serialVersionUID = -6815067322125799251L;
-
-            @Override
-            public Panel getPanel(final String panelId) {
-                return new PushPolicyDirectoryPanel(panelId, getPageReference());
+                return new PasswordPolicyDirectoryPanel(panelId, pageRef);
             }
         });
 
diff --git a/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/init/SCIMLoader.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/ImplementationInfoProvider.java
similarity index 52%
copy from ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/init/SCIMLoader.java
copy to client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/ImplementationInfoProvider.java
index db981b8..b1cdbe8 100644
--- a/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/init/SCIMLoader.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/ImplementationInfoProvider.java
@@ -16,23 +16,35 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.core.logic.init;
+package org.apache.syncope.client.console.commons;
 
-import org.apache.syncope.common.lib.scim.types.SCIMEntitlement;
-import org.apache.syncope.core.persistence.api.SyncopeCoreLoader;
-import org.apache.syncope.core.provisioning.api.EntitlementsHolder;
-import org.springframework.stereotype.Component;
+import java.io.Serializable;
+import java.util.List;
+import org.apache.syncope.common.lib.to.ImplementationTO;
+import org.apache.wicket.model.IModel;
 
-@Component
-public class SCIMLoader implements SyncopeCoreLoader {
+public interface ImplementationInfoProvider extends Serializable {
 
-    @Override
-    public int getOrder() {
-        return 1000;
-    }
+    enum ViewMode {
+        JAVA_CLASS,
+        JSON_BODY,
+        GROOVY_BODY
 
-    @Override
-    public void load() {
-        EntitlementsHolder.getInstance().init(SCIMEntitlement.values());
     }
+
+    ViewMode getViewMode(ImplementationTO implementation);
+
+    List<String> getClasses(ImplementationTO implementation, ViewMode viewMode);
+
+    String getGroovyTemplateClassName(String implementationType);
+
+    Class<?> getClass(String implementationType, String name);
+
+    IModel<List<String>> getTaskJobDelegates();
+
+    IModel<List<String>> getReconFilterBuilders();
+
+    IModel<List<String>> getPullActions();
+
+    IModel<List<String>> getPushActions();
 }
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/ImplementationDAO.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/PolicyTabProvider.java
similarity index 64%
copy from core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/ImplementationDAO.java
copy to client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/PolicyTabProvider.java
index 71b7399..c36944d 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/ImplementationDAO.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/commons/PolicyTabProvider.java
@@ -16,22 +16,14 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.core.persistence.api.dao;
+package org.apache.syncope.client.console.commons;
 
+import java.io.Serializable;
 import java.util.List;
-import org.apache.syncope.common.lib.types.ImplementationType;
-import org.apache.syncope.core.persistence.api.entity.Implementation;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.extensions.markup.html.tabs.ITab;
 
-public interface ImplementationDAO extends DAO<Implementation> {
-
-    Implementation find(String key);
-
-    List<Implementation> find(ImplementationType type);
-
-    List<Implementation> findAll();
-
-    Implementation save(Implementation implementation);
-
-    void delete(String key);
+public interface PolicyTabProvider extends Serializable {
 
+    List<ITab> buildTabList(PageReference pageRef);
 }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/init/ClassPathScanImplementationLookup.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/init/ClassPathScanImplementationLookup.java
index 08b79e3..15bd621 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/init/ClassPathScanImplementationLookup.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/init/ClassPathScanImplementationLookup.java
@@ -63,6 +63,10 @@ import org.springframework.context.annotation.ClassPathScanningCandidateComponen
 import org.springframework.core.type.filter.AssignableTypeFilter;
 import org.springframework.util.ClassUtils;
 import org.apache.syncope.client.console.commons.ExternalResourceProvider;
+import org.apache.syncope.client.console.commons.IdRepoImplementationInfoProvider;
+import org.apache.syncope.client.console.commons.IdRepoPolicyTabProvider;
+import org.apache.syncope.client.console.commons.ImplementationInfoProvider;
+import org.apache.syncope.client.console.commons.PolicyTabProvider;
 import org.apache.syncope.client.console.commons.StatusProvider;
 import org.apache.syncope.client.console.commons.VirSchemaDetailsPanelProvider;
 
@@ -111,6 +115,10 @@ public class ClassPathScanImplementationLookup {
     private AnyDirectoryPanelAditionalActionLinksProvider anyDirectoryPanelAditionalActionLinksProvider =
             new EmptyAnyDirectoryPanelAditionalActionLinksProvider();
 
+    private ImplementationInfoProvider implementationInfoProvider = new IdRepoImplementationInfoProvider(this);
+
+    private PolicyTabProvider policyTabProvider = new IdRepoPolicyTabProvider();
+
     private List<Class<? extends BasePage>> pages;
 
     private List<Class<? extends AbstractBinaryPreviewer>> previewers;
@@ -180,6 +188,8 @@ public class ClassPathScanImplementationLookup {
         scanner.addIncludeFilter(new AssignableTypeFilter(StatusProvider.class));
         scanner.addIncludeFilter(new AssignableTypeFilter(VirSchemaDetailsPanelProvider.class));
         scanner.addIncludeFilter(new AssignableTypeFilter(AnyDirectoryPanelAditionalActionLinksProvider.class));
+        scanner.addIncludeFilter(new AssignableTypeFilter(ImplementationInfoProvider.class));
+        scanner.addIncludeFilter(new AssignableTypeFilter(PolicyTabProvider.class));
 
         scanner.findCandidateComponents(getBasePackage()).forEach(bd -> {
             try {
@@ -273,6 +283,24 @@ public class ClassPathScanImplementationLookup {
                                             getConstructor().newInstance();
 
                         }
+                    } else if (ImplementationInfoProvider.class.isAssignableFrom(clazz)) {
+                        if (!clazz.equals(IdRepoImplementationInfoProvider.class)
+                                && !clazz.isInstance(implementationInfoProvider)) {
+
+                            implementationInfoProvider =
+                                    (ImplementationInfoProvider) clazz.
+                                            getConstructor(ClassPathScanImplementationLookup.class).newInstance(this);
+
+                        }
+                    } else if (PolicyTabProvider.class.isAssignableFrom(clazz)) {
+                        if (!clazz.equals(IdRepoPolicyTabProvider.class)
+                                && !clazz.isInstance(policyTabProvider)) {
+
+                            policyTabProvider =
+                                    (PolicyTabProvider) clazz.
+                                            getConstructor().newInstance();
+
+                        }
                     }
                 }
             } catch (Throwable t) {
@@ -323,12 +351,21 @@ public class ClassPathScanImplementationLookup {
         LOG.debug("Pull Correlation Rule configurations found: {}", pullCorrelationRuleConfs);
         LOG.debug("Push Correlation Rule configurations found: {}", pushCorrelationRuleConfs);
         LOG.debug("Wicket Resources found: {}", resources);
+
         LOG.debug("{}: {}", ExternalResourceProvider.class.getSimpleName(),
                 resourceProvider.getClass().getSimpleName());
         LOG.debug("{}: {}", AnyWizardBuilderAdditionalSteps.class.getSimpleName(),
                 anyWizardBuilderAdditionalSteps.getClass().getSimpleName());
         LOG.debug("{}: {}", StatusProvider.class.getSimpleName(),
                 statusProvider.getClass().getSimpleName());
+        LOG.debug("{}: {}", VirSchemaDetailsPanelProvider.class.getSimpleName(),
+                virSchemaDetailsPanelProvider.getClass().getSimpleName());
+        LOG.debug("{}: {}", AnyDirectoryPanelAditionalActionLinksProvider.class.getSimpleName(),
+                anyDirectoryPanelAditionalActionLinksProvider.getClass().getSimpleName());
+        LOG.debug("{}: {}", ImplementationInfoProvider.class.getSimpleName(),
+                implementationInfoProvider.getClass().getSimpleName());
+        LOG.debug("{}: {}", PolicyTabProvider.class.getSimpleName(),
+                policyTabProvider.getClass().getSimpleName());
     }
 
     public Class<? extends AbstractBinaryPreviewer> getPreviewerClass(final String mimeType) {
@@ -345,26 +382,6 @@ public class ClassPathScanImplementationLookup {
         return previewer;
     }
 
-    public ExternalResourceProvider getResourceProvider() {
-        return resourceProvider;
-    }
-
-    public AnyWizardBuilderAdditionalSteps getAnyWizardBuilderAdditionalSteps() {
-        return anyWizardBuilderAdditionalSteps;
-    }
-
-    public StatusProvider getStatusProvider() {
-        return statusProvider;
-    }
-
-    public VirSchemaDetailsPanelProvider getVirSchemaDetailsPanelProvider() {
-        return virSchemaDetailsPanelProvider;
-    }
-
-    public AnyDirectoryPanelAditionalActionLinksProvider getAnyDirectoryPanelAditionalActionLinksProvider() {
-        return anyDirectoryPanelAditionalActionLinksProvider;
-    }
-
     public List<Class<? extends BasePage>> getPageClasses() {
         return pages;
     }
@@ -412,4 +429,32 @@ public class ClassPathScanImplementationLookup {
     public List<Class<? extends AbstractResource>> getResources() {
         return resources;
     }
+
+    public ExternalResourceProvider getResourceProvider() {
+        return resourceProvider;
+    }
+
+    public AnyWizardBuilderAdditionalSteps getAnyWizardBuilderAdditionalSteps() {
+        return anyWizardBuilderAdditionalSteps;
+    }
+
+    public StatusProvider getStatusProvider() {
+        return statusProvider;
+    }
+
+    public VirSchemaDetailsPanelProvider getVirSchemaDetailsPanelProvider() {
+        return virSchemaDetailsPanelProvider;
+    }
+
+    public AnyDirectoryPanelAditionalActionLinksProvider getAnyDirectoryPanelAditionalActionLinksProvider() {
+        return anyDirectoryPanelAditionalActionLinksProvider;
+    }
+
+    public ImplementationInfoProvider getImplementationInfoProvider() {
+        return implementationInfoProvider;
+    }
+
+    public PolicyTabProvider getPolicyTabProvider() {
+        return policyTabProvider;
+    }
 }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationWizardBuilder.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationWizardBuilder.java
index be4b0c2..f4698a3 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationWizardBuilder.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/notifications/NotificationWizardBuilder.java
@@ -52,7 +52,7 @@ import org.apache.syncope.common.lib.to.NotificationTO;
 import org.apache.syncope.common.lib.to.PlainSchemaTO;
 import org.apache.syncope.common.lib.to.VirSchemaTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
-import org.apache.syncope.common.lib.types.ImplementationType;
+import org.apache.syncope.common.lib.types.IdRepoImplementationType;
 import org.apache.syncope.common.lib.types.SchemaType;
 import org.apache.syncope.common.lib.types.TraceLevel;
 import org.apache.wicket.PageReference;
@@ -341,7 +341,7 @@ public class NotificationWizardBuilder extends BaseAjaxWizardBuilder<Notificatio
 
             @Override
             protected List<String> load() {
-                return implRestClient.list(ImplementationType.RECIPIENTS_PROVIDER).stream().
+                return implRestClient.list(IdRepoImplementationType.RECIPIENTS_PROVIDER).stream().
                         map(EntityTO::getKey).sorted().collect(Collectors.toList());
             }
         };
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/Implementations.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/Implementations.java
index 0cd1c43..591bb3a 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/Implementations.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/Implementations.java
@@ -19,13 +19,12 @@
 package org.apache.syncope.client.console.pages;
 
 import de.agilecoders.wicket.core.markup.html.bootstrap.tabs.AjaxBootstrapTabbedPanel;
-import java.util.Arrays;
-import java.util.Comparator;
 import java.util.List;
 import java.util.stream.Collectors;
 import org.apache.syncope.client.console.BookmarkablePageLinkBuilder;
+import org.apache.syncope.client.console.SyncopeConsoleSession;
 import org.apache.syncope.client.console.panels.ImplementationDirectoryPanel;
-import org.apache.syncope.common.lib.types.ImplementationType;
+import org.apache.syncope.common.lib.types.IdRepoImplementationType;
 import org.apache.wicket.extensions.markup.html.tabs.AbstractTab;
 import org.apache.wicket.extensions.markup.html.tabs.ITab;
 import org.apache.wicket.markup.html.WebMarkupContainer;
@@ -49,11 +48,11 @@ public class Implementations extends BasePage {
     }
 
     private List<ITab> buildTabList() {
-        return Arrays.stream(ImplementationType.values()).
-                filter(type -> type != ImplementationType.JWT_SSO_PROVIDER
-                && type != ImplementationType.AUDIT_APPENDER).
-                sorted(Comparator.comparing(ImplementationType::name)).
-                map(type -> new AbstractTab(Model.of(type.name())) {
+        return SyncopeConsoleSession.get().getPlatformInfo().getImplementationTypes().stream().
+                filter(type -> !IdRepoImplementationType.JWT_SSO_PROVIDER.equals(type)
+                && !IdRepoImplementationType.AUDIT_APPENDER.equals(type)).
+                sorted().
+                map(type -> new AbstractTab(Model.of(type)) {
 
             private static final long serialVersionUID = -5861786415855103549L;
 
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/Policies.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/Policies.java
index 294b238..bdb772a 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/Policies.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/pages/Policies.java
@@ -19,18 +19,9 @@
 package org.apache.syncope.client.console.pages;
 
 import de.agilecoders.wicket.core.markup.html.bootstrap.tabs.AjaxBootstrapTabbedPanel;
-import java.util.ArrayList;
-import java.util.List;
 import org.apache.syncope.client.console.BookmarkablePageLinkBuilder;
-import org.apache.syncope.client.console.policies.AccountPolicyDirectoryPanel;
-import org.apache.syncope.client.console.policies.PasswordPolicyDirectoryPanel;
-import org.apache.syncope.client.console.policies.PullPolicyDirectoryPanel;
-import org.apache.syncope.client.console.policies.PushPolicyDirectoryPanel;
-import org.apache.wicket.extensions.markup.html.tabs.AbstractTab;
-import org.apache.wicket.extensions.markup.html.tabs.ITab;
+import org.apache.syncope.client.console.SyncopeWebApplication;
 import org.apache.wicket.markup.html.WebMarkupContainer;
-import org.apache.wicket.markup.html.panel.Panel;
-import org.apache.wicket.model.ResourceModel;
 import org.apache.wicket.request.mapper.parameter.PageParameters;
 
 public class Policies extends BasePage {
@@ -45,53 +36,8 @@ public class Policies extends BasePage {
         WebMarkupContainer content = new WebMarkupContainer("content");
         content.setOutputMarkupId(true);
         content.setMarkupId("policies");
-        content.add(new AjaxBootstrapTabbedPanel<>("tabbedPanel", buildTabList()));
+        content.add(new AjaxBootstrapTabbedPanel<>(
+                "tabbedPanel", SyncopeWebApplication.get().getPolicyTabProvider().buildTabList(getPageReference())));
         body.add(content);
     }
-
-    private List<ITab> buildTabList() {
-        final List<ITab> tabs = new ArrayList<>();
-
-        tabs.add(new AbstractTab(new ResourceModel("policy.account")) {
-
-            private static final long serialVersionUID = -6815067322125799251L;
-
-            @Override
-            public Panel getPanel(final String panelId) {
-                return new AccountPolicyDirectoryPanel(panelId, getPageReference());
-            }
-        });
-
-        tabs.add(new AbstractTab(new ResourceModel("policy.password")) {
-
-            private static final long serialVersionUID = -6815067322125799251L;
-
-            @Override
-            public Panel getPanel(final String panelId) {
-                return new PasswordPolicyDirectoryPanel(panelId, getPageReference());
-            }
-        });
-
-        tabs.add(new AbstractTab(new ResourceModel("policy.pull")) {
-
-            private static final long serialVersionUID = -6815067322125799251L;
-
-            @Override
-            public Panel getPanel(final String panelId) {
-                return new PullPolicyDirectoryPanel(panelId, getPageReference());
-            }
-        });
-
-        tabs.add(new AbstractTab(new ResourceModel("policy.push")) {
-
-            private static final long serialVersionUID = -6815067322125799251L;
-
-            @Override
-            public Panel getPanel(final String panelId) {
-                return new PushPolicyDirectoryPanel(panelId, getPageReference());
-            }
-        });
-
-        return tabs;
-    }
 }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ImplementationDirectoryPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ImplementationDirectoryPanel.java
index 6d2e0be..1de9c3a 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ImplementationDirectoryPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ImplementationDirectoryPanel.java
@@ -38,7 +38,6 @@ import org.apache.syncope.client.console.wicket.markup.html.form.ActionsPanel;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.to.ImplementationTO;
 import org.apache.syncope.common.lib.types.ImplementationEngine;
-import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.common.lib.types.StandardEntitlement;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AjaxRequestTarget;
@@ -59,9 +58,9 @@ public class ImplementationDirectoryPanel extends DirectoryPanel<
 
     private static final long serialVersionUID = 1868839768348072635L;
 
-    private final ImplementationType type;
+    private final String type;
 
-    public ImplementationDirectoryPanel(final String id, final ImplementationType type, final PageReference pageRef) {
+    public ImplementationDirectoryPanel(final String id, final String type, final PageReference pageRef) {
         super(id, pageRef, true);
         this.type = type;
 
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ImplementationModalPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ImplementationModalPanel.java
index 29176b9..4290600 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ImplementationModalPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ImplementationModalPanel.java
@@ -21,24 +21,19 @@ package org.apache.syncope.client.console.panels;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
 import java.util.List;
-import java.util.Optional;
-import java.util.stream.Collectors;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.client.console.SyncopeConsoleSession;
+import org.apache.syncope.client.console.SyncopeWebApplication;
 import org.apache.syncope.client.console.commons.Constants;
-import org.apache.syncope.client.console.init.ClassPathScanImplementationLookup;
+import org.apache.syncope.client.console.commons.ImplementationInfoProvider.ViewMode;
 import org.apache.syncope.client.console.pages.BasePage;
 import org.apache.syncope.client.console.rest.ImplementationRestClient;
 import org.apache.syncope.client.console.wicket.markup.html.bootstrap.dialog.BaseModal;
 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoicePanel;
 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
-import org.apache.syncope.common.lib.info.JavaImplInfo;
 import org.apache.syncope.common.lib.to.ImplementationTO;
 import org.apache.syncope.common.lib.types.ImplementationEngine;
-import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AjaxEventBehavior;
 import org.apache.wicket.ajax.AjaxRequestTarget;
@@ -48,25 +43,14 @@ import org.apache.wicket.markup.html.WebMarkupContainer;
 import org.apache.wicket.markup.html.form.TextArea;
 import org.apache.wicket.model.Model;
 import org.apache.wicket.model.PropertyModel;
-import org.apache.wicket.spring.injection.annot.SpringBean;
 import org.apache.wicket.util.io.IOUtils;
 
 public class ImplementationModalPanel extends AbstractModalPanel<ImplementationTO> {
 
     private static final long serialVersionUID = 5283548960927517342L;
 
-    private enum ViewMode {
-        JAVA_CLASS,
-        JSON_BODY,
-        GROOVY_BODY
-
-    }
-
     private static final ObjectMapper MAPPER = new ObjectMapper();
 
-    @SpringBean
-    private ClassPathScanImplementationLookup lookup;
-
     private final ImplementationRestClient restClient = new ImplementationRestClient();
 
     private final ImplementationTO implementation;
@@ -82,59 +66,15 @@ public class ImplementationModalPanel extends AbstractModalPanel<ImplementationT
 
         super(modal, pageRef);
         this.implementation = implementation;
-        this.viewMode = implementation.getEngine() == ImplementationEngine.GROOVY
-                ? ViewMode.GROOVY_BODY
-                : implementation.getType() == ImplementationType.REPORTLET
-                || implementation.getType() == ImplementationType.ACCOUNT_RULE
-                || implementation.getType() == ImplementationType.PASSWORD_RULE
-                || implementation.getType() == ImplementationType.PULL_CORRELATION_RULE
-                || implementation.getType() == ImplementationType.PUSH_CORRELATION_RULE
-                ? ViewMode.JSON_BODY
-                : ViewMode.JAVA_CLASS;
+        this.viewMode = SyncopeWebApplication.get().getImplementationInfoProvider().getViewMode(implementation);
         this.create = implementation.getKey() == null;
 
         add(new AjaxTextFieldPanel(
                 "key", "key", new PropertyModel<>(implementation, "key"), false).
                 addRequiredLabel().setEnabled(create));
 
-        List<String> classes = Collections.emptyList();
-        if (viewMode == ViewMode.JAVA_CLASS) {
-            Optional<JavaImplInfo> javaClasses = SyncopeConsoleSession.get().getPlatformInfo().
-                    getJavaImplInfo(implementation.getType());
-            classes = javaClasses.isPresent()
-                    ? new ArrayList<>(javaClasses.get().getClasses())
-                    : new ArrayList<>();
-        } else if (viewMode == ViewMode.JSON_BODY) {
-            switch (implementation.getType()) {
-                case REPORTLET:
-                    classes = lookup.getReportletConfs().keySet().stream().
-                            collect(Collectors.toList());
-                    break;
-
-                case ACCOUNT_RULE:
-                    classes = lookup.getAccountRuleConfs().keySet().stream().
-                            collect(Collectors.toList());
-                    break;
-
-                case PASSWORD_RULE:
-                    classes = lookup.getPasswordRuleConfs().keySet().stream().
-                            collect(Collectors.toList());
-                    break;
-
-                case PULL_CORRELATION_RULE:
-                    classes = lookup.getPullCorrelationRuleConfs().keySet().stream().
-                            collect(Collectors.toList());
-                    break;
-
-                case PUSH_CORRELATION_RULE:
-                    classes = lookup.getPushCorrelationRuleConfs().keySet().stream().
-                            collect(Collectors.toList());
-                    break;
-
-                default:
-            }
-        }
-        Collections.sort(classes);
+        List<String> classes = SyncopeWebApplication.get().getImplementationInfoProvider().
+                getClasses(implementation, viewMode);
 
         AjaxDropDownChoicePanel<String> javaClass = new AjaxDropDownChoicePanel<>(
                 "javaClass", "Class", new PropertyModel<>(implementation, "body"));
@@ -173,68 +113,8 @@ public class ImplementationModalPanel extends AbstractModalPanel<ImplementationT
         if (StringUtils.isBlank(implementation.getBody())
                 && implementation.getEngine() == ImplementationEngine.GROOVY) {
 
-            String templateClassName = null;
-
-            switch (implementation.getType()) {
-                case REPORTLET:
-                    templateClassName = "MyReportlet";
-                    break;
-
-                case ACCOUNT_RULE:
-                    templateClassName = "MyAccountRule";
-                    break;
-
-                case PASSWORD_RULE:
-                    templateClassName = "MyPasswordRule";
-                    break;
-
-                case ITEM_TRANSFORMER:
-                    templateClassName = "MyItemTransformer";
-                    break;
-
-                case TASKJOB_DELEGATE:
-                    templateClassName = "MySchedTaskJobDelegate";
-                    break;
-
-                case RECON_FILTER_BUILDER:
-                    templateClassName = "MyReconFilterBuilder";
-                    break;
-
-                case LOGIC_ACTIONS:
-                    templateClassName = "MyLogicActions";
-                    break;
-
-                case PROPAGATION_ACTIONS:
-                    templateClassName = "MyPropagationActions";
-                    break;
-
-                case PULL_ACTIONS:
-                    templateClassName = "MyPullActions";
-                    break;
-
-                case PUSH_ACTIONS:
-                    templateClassName = "MyPushActions";
-                    break;
-
-                case PULL_CORRELATION_RULE:
-                    templateClassName = "MyPullCorrelationRule";
-                    break;
-
-                case PUSH_CORRELATION_RULE:
-                    templateClassName = "MyPushCorrelationRule";
-                    break;
-
-                case VALIDATOR:
-                    templateClassName = "MyValidator";
-                    break;
-
-                case RECIPIENTS_PROVIDER:
-                    templateClassName = "MyRecipientsProvider";
-                    break;
-
-                default:
-            }
-
+            String templateClassName = SyncopeWebApplication.get().getImplementationInfoProvider().
+                    getGroovyTemplateClassName(implementation.getType());
             if (templateClassName != null) {
                 try {
                     implementation.setBody(StringUtils.substringAfter(IOUtils.toString(getClass().
@@ -261,31 +141,8 @@ public class ImplementationModalPanel extends AbstractModalPanel<ImplementationT
 
             @Override
             protected void onEvent(final AjaxRequestTarget target) {
-                Class<?> clazz = null;
-                switch (implementation.getType()) {
-                    case REPORTLET:
-                        clazz = lookup.getReportletConfs().get(jsonClass.getModelObject());
-                        break;
-
-                    case ACCOUNT_RULE:
-                        clazz = lookup.getAccountRuleConfs().get(jsonClass.getModelObject());
-                        break;
-
-                    case PASSWORD_RULE:
-                        clazz = lookup.getPasswordRuleConfs().get(jsonClass.getModelObject());
-                        break;
-
-                    case PULL_CORRELATION_RULE:
-                        clazz = lookup.getPullCorrelationRuleConfs().get(jsonClass.getModelObject());
-                        break;
-
-                    case PUSH_CORRELATION_RULE:
-                        clazz = lookup.getPushCorrelationRuleConfs().get(jsonClass.getModelObject());
-                        break;
-
-                    default:
-                }
-
+                Class<?> clazz = SyncopeWebApplication.get().getImplementationInfoProvider().
+                        getClass(implementation.getType(), jsonClass.getModelObject());
                 if (clazz != null) {
                     try {
                         target.appendJavaScript("editor.getDoc().setValue('"
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersCreateWizardSchemaStep.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersCreateWizardSchemaStep.java
index 9bd7b5a..de7fa2d 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersCreateWizardSchemaStep.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/ParametersCreateWizardSchemaStep.java
@@ -35,7 +35,7 @@ import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.syncope.common.lib.to.PlainSchemaTO;
 import org.apache.syncope.common.lib.types.AttrSchemaType;
 import org.apache.syncope.common.lib.types.CipherAlgorithm;
-import org.apache.syncope.common.lib.types.ImplementationType;
+import org.apache.syncope.common.lib.types.IdRepoImplementationType;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.extensions.wizard.WizardStep;
 import org.apache.wicket.markup.html.WebMarkupContainer;
@@ -233,7 +233,7 @@ public class ParametersCreateWizardSchemaStep extends WizardStep {
 
             @Override
             protected List<String> load() {
-                return implRestClient.list(ImplementationType.VALIDATOR).stream().
+                return implRestClient.list(IdRepoImplementationType.VALIDATOR).stream().
                         map(EntityTO::getKey).sorted().collect(Collectors.toList());
             }
         };
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/PlainSchemaDetails.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/PlainSchemaDetails.java
index fc5baa5..4f319ed 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/PlainSchemaDetails.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/PlainSchemaDetails.java
@@ -39,7 +39,7 @@ import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.syncope.common.lib.to.PlainSchemaTO;
 import org.apache.syncope.common.lib.types.AttrSchemaType;
 import org.apache.syncope.common.lib.types.CipherAlgorithm;
-import org.apache.syncope.common.lib.types.ImplementationType;
+import org.apache.syncope.common.lib.types.IdRepoImplementationType;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.extensions.ajax.markup.html.autocomplete.AutoCompleteTextField;
 import org.apache.wicket.markup.html.WebMarkupContainer;
@@ -238,7 +238,7 @@ public class PlainSchemaDetails extends AbstractSchemaDetailsPanel {
 
             @Override
             protected List<String> load() {
-                return implRestClient.list(ImplementationType.VALIDATOR).stream().
+                return implRestClient.list(IdRepoImplementationType.VALIDATOR).stream().
                         map(EntityTO::getKey).sorted().collect(Collectors.toList());
             }
         };
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RealmDetails.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RealmDetails.java
index bb07693..e601ca6 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RealmDetails.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/panels/RealmDetails.java
@@ -34,7 +34,7 @@ import org.apache.syncope.client.console.wicket.markup.html.form.PolicyRenderer;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.syncope.common.lib.to.RealmTO;
-import org.apache.syncope.common.lib.types.ImplementationType;
+import org.apache.syncope.common.lib.types.IdRepoImplementationType;
 import org.apache.syncope.common.lib.types.PolicyType;
 import org.apache.wicket.markup.html.WebMarkupContainer;
 import org.apache.wicket.markup.html.form.DropDownChoice;
@@ -86,7 +86,7 @@ public class RealmDetails extends Panel {
 
         @Override
         protected List<String> load() {
-            return implRestClient.list(ImplementationType.LOGIC_ACTIONS).stream().
+            return implRestClient.list(IdRepoImplementationType.LOGIC_ACTIONS).stream().
                     map(EntityTO::getKey).sorted().collect(Collectors.toList());
         }
     };
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/PolicyRuleDirectoryPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/PolicyRuleDirectoryPanel.java
index cf4db2b..ecd249f 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/PolicyRuleDirectoryPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/PolicyRuleDirectoryPanel.java
@@ -47,8 +47,8 @@ import org.apache.syncope.common.lib.policy.ComposablePolicy;
 import org.apache.syncope.common.lib.policy.PolicyTO;
 import org.apache.syncope.common.lib.policy.RuleConf;
 import org.apache.syncope.common.lib.to.ImplementationTO;
+import org.apache.syncope.common.lib.types.IdRepoImplementationType;
 import org.apache.syncope.common.lib.types.ImplementationEngine;
-import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.common.lib.types.PolicyType;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AjaxRequestTarget;
@@ -83,7 +83,7 @@ public class PolicyRuleDirectoryPanel<T extends PolicyTO> extends DirectoryPanel
 
     private final PolicyType type;
 
-    private final ImplementationType implementationType;
+    private final String implementationType;
 
     private final String policy;
 
@@ -96,8 +96,8 @@ public class PolicyRuleDirectoryPanel<T extends PolicyTO> extends DirectoryPanel
         this.baseModal = baseModal;
         this.type = type;
         this.implementationType = type == PolicyType.ACCOUNT
-                ? ImplementationType.ACCOUNT_RULE
-                : ImplementationType.PASSWORD_RULE;
+                ? IdRepoImplementationType.ACCOUNT_RULE
+                : IdRepoImplementationType.PASSWORD_RULE;
         this.policy = policy;
         this.restClient = new PolicyRestClient();
 
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/PolicyRuleWizardBuilder.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/PolicyRuleWizardBuilder.java
index d649d93..7ef78a8 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/PolicyRuleWizardBuilder.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/policies/PolicyRuleWizardBuilder.java
@@ -34,8 +34,8 @@ import org.apache.syncope.common.lib.policy.ComposablePolicy;
 import org.apache.syncope.common.lib.policy.RuleConf;
 import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.syncope.common.lib.to.ImplementationTO;
+import org.apache.syncope.common.lib.types.IdRepoImplementationType;
 import org.apache.syncope.common.lib.types.ImplementationEngine;
-import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.common.lib.types.PolicyType;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AjaxEventBehavior;
@@ -59,7 +59,7 @@ public class PolicyRuleWizardBuilder extends BaseAjaxWizardBuilder<PolicyRuleWra
 
     private final PolicyType type;
 
-    private final ImplementationType implementationType;
+    private final String implementationType;
 
     public PolicyRuleWizardBuilder(
             final String policy,
@@ -72,8 +72,8 @@ public class PolicyRuleWizardBuilder extends BaseAjaxWizardBuilder<PolicyRuleWra
         this.policy = policy;
         this.type = type;
         this.implementationType = type == PolicyType.ACCOUNT
-                ? ImplementationType.ACCOUNT_RULE
-                : ImplementationType.PASSWORD_RULE;
+                ? IdRepoImplementationType.ACCOUNT_RULE
+                : IdRepoImplementationType.PASSWORD_RULE;
     }
 
     @Override
@@ -127,12 +127,12 @@ public class PolicyRuleWizardBuilder extends BaseAjaxWizardBuilder<PolicyRuleWra
             List<String> choices;
             switch (type) {
                 case ACCOUNT:
-                    choices = implementationClient.list(ImplementationType.ACCOUNT_RULE).stream().
+                    choices = implementationClient.list(IdRepoImplementationType.ACCOUNT_RULE).stream().
                             map(EntityTO::getKey).sorted().collect(Collectors.toList());
                     break;
 
                 case PASSWORD:
-                    choices = implementationClient.list(ImplementationType.PASSWORD_RULE).stream().
+                    choices = implementationClient.list(IdRepoImplementationType.PASSWORD_RULE).stream().
                             map(EntityTO::getKey).sorted().collect(Collectors.toList());
                     break;
 
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportletDirectoryPanel.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportletDirectoryPanel.java
index 9bd791e..f72c8b6 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportletDirectoryPanel.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportletDirectoryPanel.java
@@ -46,8 +46,8 @@ import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.report.ReportletConf;
 import org.apache.syncope.common.lib.to.ImplementationTO;
 import org.apache.syncope.common.lib.to.ReportTO;
+import org.apache.syncope.common.lib.types.IdRepoImplementationType;
 import org.apache.syncope.common.lib.types.ImplementationEngine;
-import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AjaxRequestTarget;
 import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
@@ -223,7 +223,7 @@ public class ReportletDirectoryPanel extends DirectoryPanel<
 
         private List<ReportletWrapper> getReportletWrappers(final ReportTO reportTO) {
             return reportTO.getReportlets().stream().map(reportlet -> {
-                ImplementationTO impl = implementationClient.read(ImplementationType.REPORTLET, reportlet);
+                ImplementationTO impl = implementationClient.read(IdRepoImplementationType.REPORTLET, reportlet);
 
                 ReportletWrapper wrapper = new ReportletWrapper(false).
                         setImplementationKey(impl.getKey()).
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportletWizardBuilder.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportletWizardBuilder.java
index 43c3a6b..54ac4f3 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportletWizardBuilder.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/reports/ReportletWizardBuilder.java
@@ -31,8 +31,8 @@ import org.apache.syncope.common.lib.report.ReportletConf;
 import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.syncope.common.lib.to.ImplementationTO;
 import org.apache.syncope.common.lib.to.ReportTO;
+import org.apache.syncope.common.lib.types.IdRepoImplementationType;
 import org.apache.syncope.common.lib.types.ImplementationEngine;
-import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AjaxEventBehavior;
 import org.apache.wicket.ajax.AjaxRequestTarget;
@@ -65,7 +65,7 @@ public class ReportletWizardBuilder extends BaseAjaxWizardBuilder<ReportletWrapp
     protected Serializable onApplyInternal(final ReportletWrapper modelObject) {
         if (modelObject.getImplementationEngine() == ImplementationEngine.JAVA) {
             ImplementationTO reportlet = implementationClient.read(
-                    ImplementationType.REPORTLET, modelObject.getImplementationKey());
+                    IdRepoImplementationType.REPORTLET, modelObject.getImplementationKey());
             try {
                 reportlet.setBody(MAPPER.writeValueAsString(modelObject.getConf()));
                 implementationClient.update(reportlet);
@@ -97,9 +97,9 @@ public class ReportletWizardBuilder extends BaseAjaxWizardBuilder<ReportletWrapp
 
         public Profile(final ReportletWrapper reportlet) {
             final AjaxDropDownChoicePanel<String> conf = new AjaxDropDownChoicePanel<>(
-                    "reportlet", getString("reportlet"), new PropertyModel<String>(reportlet, "implementationKey"));
+                    "reportlet", getString("reportlet"), new PropertyModel<>(reportlet, "implementationKey"));
 
-            conf.setChoices(implementationClient.list(ImplementationType.REPORTLET).stream().
+            conf.setChoices(implementationClient.list(IdRepoImplementationType.REPORTLET).stream().
                     map(EntityTO::getKey).sorted().collect(Collectors.toList()));
             conf.addRequiredLabel();
             conf.setNullValid(false);
@@ -111,7 +111,7 @@ public class ReportletWizardBuilder extends BaseAjaxWizardBuilder<ReportletWrapp
                 @Override
                 protected void onEvent(final AjaxRequestTarget target) {
                     ImplementationTO impl = implementationClient.read(
-                            ImplementationType.REPORTLET, conf.getModelObject());
+                            IdRepoImplementationType.REPORTLET, conf.getModelObject());
                     reportlet.setImplementationEngine(impl.getEngine());
                     if (impl.getEngine() == ImplementationEngine.JAVA) {
                         try {
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/ImplementationRestClient.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/ImplementationRestClient.java
index 746ea70..73d0b1a 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/ImplementationRestClient.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/rest/ImplementationRestClient.java
@@ -20,18 +20,17 @@ package org.apache.syncope.client.console.rest;
 
 import java.util.List;
 import org.apache.syncope.common.lib.to.ImplementationTO;
-import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.common.rest.api.service.ImplementationService;
 
 public class ImplementationRestClient extends BaseRestClient {
 
     private static final long serialVersionUID = -4111950555473526287L;
 
-    public List<ImplementationTO> list(final ImplementationType type) {
+    public List<ImplementationTO> list(final String type) {
         return getService(ImplementationService.class).list(type);
     }
 
-    public ImplementationTO read(final ImplementationType type, final String key) {
+    public ImplementationTO read(final String type, final String key) {
         return getService(ImplementationService.class).read(type, key);
     }
 
@@ -43,7 +42,7 @@ public class ImplementationRestClient extends BaseRestClient {
         getService(ImplementationService.class).update(implementation);
     }
 
-    public void delete(final ImplementationType type, final String key) {
+    public void delete(final String type, final String key) {
         getService(ImplementationService.class).delete(type, key);
     }
 }
diff --git a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder.java b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder.java
index 67c126e..165d035 100644
--- a/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder.java
+++ b/client/idrepo/console/src/main/java/org/apache/syncope/client/console/tasks/SchedTaskWizardBuilder.java
@@ -23,8 +23,8 @@ import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 import java.util.stream.Collectors;
+import org.apache.syncope.client.console.SyncopeWebApplication;
 import org.apache.syncope.client.console.commons.Constants;
-import org.apache.syncope.client.console.rest.ImplementationRestClient;
 import org.apache.syncope.client.console.rest.RealmRestClient;
 import org.apache.syncope.client.console.rest.TaskRestClient;
 import org.apache.syncope.client.ui.commons.ajax.form.IndicatorAjaxFormComponentUpdatingBehavior;
@@ -33,13 +33,11 @@ import org.apache.syncope.client.ui.commons.markup.html.form.AjaxDropDownChoiceP
 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxPalettePanel;
 import org.apache.syncope.client.console.wizards.BaseAjaxWizardBuilder;
 import org.apache.syncope.client.ui.commons.markup.html.form.AjaxTextFieldPanel;
-import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.syncope.common.lib.to.ProvisioningTaskTO;
 import org.apache.syncope.common.lib.to.SchedTaskTO;
 import org.apache.syncope.common.lib.to.PullTaskTO;
 import org.apache.syncope.common.lib.to.PushTaskTO;
 import org.apache.syncope.common.lib.to.RealmTO;
-import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.common.lib.types.MatchingRule;
 import org.apache.syncope.common.lib.types.PullMode;
 import org.apache.syncope.common.lib.types.TaskType;
@@ -58,9 +56,7 @@ public class SchedTaskWizardBuilder<T extends SchedTaskTO> extends BaseAjaxWizar
 
     private static final long serialVersionUID = 5945391813567245081L;
 
-    private final TaskRestClient taskRestClient = new TaskRestClient();
-
-    private final ImplementationRestClient implRestClient = new ImplementationRestClient();
+    private final TaskRestClient restClient = new TaskRestClient();
 
     private final TaskType type;
 
@@ -95,9 +91,9 @@ public class SchedTaskWizardBuilder<T extends SchedTaskTO> extends BaseAjaxWizar
 
         modelObject.setCronExpression(crontabPanel.getCronExpression());
         if (modelObject.getKey() == null) {
-            taskRestClient.create(type, modelObject);
+            restClient.create(type, modelObject);
         } else {
-            taskRestClient.update(type, modelObject);
+            restClient.update(type, modelObject);
         }
         return modelObject;
     }
@@ -117,49 +113,17 @@ public class SchedTaskWizardBuilder<T extends SchedTaskTO> extends BaseAjaxWizar
 
         private static final long serialVersionUID = -3043839139187792810L;
 
-        private final IModel<List<String>> taskJobDelegates = new LoadableDetachableModel<List<String>>() {
-
-            private static final long serialVersionUID = 5275935387613157437L;
-
-            @Override
-            protected List<String> load() {
-                return implRestClient.list(ImplementationType.TASKJOB_DELEGATE).stream().
-                        map(EntityTO::getKey).sorted().collect(Collectors.toList());
-            }
-        };
+        private final IModel<List<String>> taskJobDelegates = SyncopeWebApplication.get().
+                getImplementationInfoProvider().getTaskJobDelegates();
 
-        private final IModel<List<String>> reconFilterBuilders = new LoadableDetachableModel<List<String>>() {
-
-            private static final long serialVersionUID = 5275935387613157437L;
-
-            @Override
-            protected List<String> load() {
-                return implRestClient.list(ImplementationType.RECON_FILTER_BUILDER).stream().
-                        map(EntityTO::getKey).sorted().collect(Collectors.toList());
-            }
-        };
+        private final IModel<List<String>> reconFilterBuilders = SyncopeWebApplication.get().
+                getImplementationInfoProvider().getReconFilterBuilders();
 
-        private final IModel<List<String>> pullActions = new LoadableDetachableModel<List<String>>() {
+        private final IModel<List<String>> pullActions = SyncopeWebApplication.get().
+                getImplementationInfoProvider().getPullActions();
 
-            private static final long serialVersionUID = 5275935387613157437L;
-
-            @Override
-            protected List<String> load() {
-                return implRestClient.list(ImplementationType.PULL_ACTIONS).stream().
-                        map(EntityTO::getKey).sorted().collect(Collectors.toList());
-            }
-        };
-
-        private final IModel<List<String>> pushActions = new LoadableDetachableModel<List<String>>() {
-
-            private static final long serialVersionUID = 5275935387613157437L;
-
-            @Override
-            protected List<String> load() {
-                return implRestClient.list(ImplementationType.PUSH_ACTIONS).stream().
-                        map(EntityTO::getKey).sorted().collect(Collectors.toList());
-            }
-        };
+        private final IModel<List<String>> pushActions = SyncopeWebApplication.get().
+                getImplementationInfoProvider().getPushActions();
 
         public Profile(final SchedTaskTO taskTO) {
             AjaxTextFieldPanel name = new AjaxTextFieldPanel("name", "name", new PropertyModel<>(taskTO, "name"),
diff --git a/common/idm/lib/src/main/java/org/apache/syncope/common/lib/types/IdMImplementationType.java b/common/idm/lib/src/main/java/org/apache/syncope/common/lib/types/IdMImplementationType.java
new file mode 100644
index 0000000..7413a16
--- /dev/null
+++ b/common/idm/lib/src/main/java/org/apache/syncope/common/lib/types/IdMImplementationType.java
@@ -0,0 +1,62 @@
+/*
+ * 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.types;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.Collections;
+import java.util.Set;
+import java.util.TreeSet;
+
+public final class IdMImplementationType {
+
+    public static final String ITEM_TRANSFORMER = "ITEM_TRANSFORMER";
+
+    public static final String RECON_FILTER_BUILDER = "RECON_FILTER_BUILDER";
+
+    public static final String PROPAGATION_ACTIONS = "PROPAGATION_ACTIONS";
+
+    public static final String PULL_ACTIONS = "PULL_ACTIONS";
+
+    public static final String PUSH_ACTIONS = "PUSH_ACTIONS";
+
+    public static final String PULL_CORRELATION_RULE = "PULL_CORRELATION_RULE";
+
+    public static final String PUSH_CORRELATION_RULE = "PUSH_CORRELATION_RULE";
+
+    private static final Set<String> VALUES;
+
+    static {
+        Set<String> values = new TreeSet<>();
+        for (Field field : IdMImplementationType.class.getDeclaredFields()) {
+            if (Modifier.isStatic(field.getModifiers()) && String.class.equals(field.getType())) {
+                values.add(field.getName());
+            }
+        }
+        VALUES = Collections.unmodifiableSet(values);
+    }
+
+    public static Set<String> values() {
+        return VALUES;
+    }
+
+    private IdMImplementationType() {
+        // private constructor for static utility class
+    }
+}
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/info/JavaImplInfo.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/info/JavaImplInfo.java
index 8ba3b4a..df5579a 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/info/JavaImplInfo.java
+++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/info/JavaImplInfo.java
@@ -26,7 +26,6 @@ import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlElementWrapper;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlType;
-import org.apache.syncope.common.lib.types.ImplementationType;
 
 @XmlRootElement(name = "javaImplInfo")
 @XmlType
@@ -34,15 +33,15 @@ public class JavaImplInfo implements Serializable {
 
     private static final long serialVersionUID = 4036793959111794959L;
 
-    private ImplementationType type;
+    private String type;
 
     private final Set<String> classes = new HashSet<>();
 
-    public ImplementationType getType() {
+    public String getType() {
         return type;
     }
 
-    public void setType(final ImplementationType type) {
+    public void setType(final String type) {
         this.type = type;
     }
 
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/info/PlatformInfo.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/info/PlatformInfo.java
index 5e585b9..5c0d138 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/info/PlatformInfo.java
+++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/info/PlatformInfo.java
@@ -30,7 +30,6 @@ import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlElementWrapper;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlType;
-import org.apache.syncope.common.lib.types.ImplementationType;
 
 @XmlRootElement(name = "platformInfo")
 @XmlType
@@ -279,6 +278,8 @@ public class PlatformInfo implements Serializable {
 
     private final Set<String> entitlements = new HashSet<>();
 
+    private final Set<String> implementationTypes = new HashSet<>();
+
     private final Set<JavaImplInfo> javaImplInfos = new HashSet<>();
 
     public String getVersion() {
@@ -363,9 +364,16 @@ public class PlatformInfo implements Serializable {
         return entitlements;
     }
 
+    @XmlElementWrapper(name = "implementationTypes")
+    @XmlElement(name = "implementationType")
+    @JsonProperty("implementationTypes")
+    public Set<String> getImplementationTypes() {
+        return implementationTypes;
+    }
+
     @JsonIgnore
-    public Optional<JavaImplInfo> getJavaImplInfo(final ImplementationType type) {
-        return javaImplInfos.stream().filter(javaImplInfo -> javaImplInfo.getType() == type).findFirst();
+    public Optional<JavaImplInfo> getJavaImplInfo(final String type) {
+        return javaImplInfos.stream().filter(javaImplInfo -> javaImplInfo.getType().equals(type)).findFirst();
     }
 
     @XmlElementWrapper(name = "javaImplInfos")
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/ImplementationTO.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/ImplementationTO.java
index cae2fb6..c68bf5c 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/ImplementationTO.java
+++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/to/ImplementationTO.java
@@ -24,7 +24,6 @@ import javax.xml.bind.annotation.XmlType;
 import org.apache.commons.lang3.builder.EqualsBuilder;
 import org.apache.commons.lang3.builder.HashCodeBuilder;
 import org.apache.syncope.common.lib.types.ImplementationEngine;
-import org.apache.syncope.common.lib.types.ImplementationType;
 
 @XmlRootElement(name = "implementation")
 @XmlType
@@ -36,7 +35,7 @@ public class ImplementationTO implements EntityTO {
 
     private ImplementationEngine engine;
 
-    private ImplementationType type;
+    private String type;
 
     private String body;
 
@@ -59,12 +58,12 @@ public class ImplementationTO implements EntityTO {
         this.engine = engine;
     }
 
-    public ImplementationType getType() {
+    public String getType() {
         return type;
     }
 
     @PathParam("type")
-    public void setType(final ImplementationType type) {
+    public void setType(final String type) {
         this.type = type;
     }
 
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/ClientExceptionType.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/ClientExceptionType.java
index 8a8f744..271d7a1 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/ClientExceptionType.java
+++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/ClientExceptionType.java
@@ -33,6 +33,7 @@ public enum ClientExceptionType {
     HasChildren(Response.Status.BAD_REQUEST),
     InvalidPrivilege(Response.Status.BAD_REQUEST),
     InvalidImplementation(Response.Status.BAD_REQUEST),
+    InvalidImplementationType(Response.Status.NOT_FOUND),
     InvalidSecurityAnswer(Response.Status.BAD_REQUEST),
     InvalidEntity(Response.Status.BAD_REQUEST),
     InvalidLogger(Response.Status.BAD_REQUEST),
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/EntitlementsHolder.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/EntitlementsHolder.java
similarity index 79%
rename from core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/EntitlementsHolder.java
rename to common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/EntitlementsHolder.java
index 6d810ea..067629d 100644
--- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/EntitlementsHolder.java
+++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/EntitlementsHolder.java
@@ -16,16 +16,12 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.core.provisioning.api;
+package org.apache.syncope.common.lib.types;
 
-import java.util.Collection;
-import java.util.Collections;
 import java.util.HashSet;
 import java.util.Set;
 
-import org.apache.syncope.common.lib.types.AnyEntitlement;
-
-public final class EntitlementsHolder {
+public final class EntitlementsHolder extends ValueHolder<String> {
 
     private static final Object MONITOR = new Object();
 
@@ -40,16 +36,10 @@ public final class EntitlementsHolder {
         return INSTANCE;
     }
 
-    private final Set<String> values = Collections.synchronizedSet(new HashSet<>());
-
     private EntitlementsHolder() {
         // private constructor for singleton
     }
 
-    public void init(final Collection<String> values) {
-        this.values.addAll(values);
-    }
-
     public Set<String> addFor(final String anyType) {
         Set<String> added = new HashSet<>();
 
@@ -71,8 +61,4 @@ public final class EntitlementsHolder {
 
         return removed;
     }
-
-    public Set<String> getValues() {
-        return Collections.unmodifiableSet(values);
-    }
 }
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/IdRepoImplementationType.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/IdRepoImplementationType.java
new file mode 100644
index 0000000..9145e6d
--- /dev/null
+++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/IdRepoImplementationType.java
@@ -0,0 +1,66 @@
+/*
+ * 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.types;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.Collections;
+import java.util.Set;
+import java.util.TreeSet;
+
+public final class IdRepoImplementationType {
+
+    public static final String JWT_SSO_PROVIDER = "JWT_SSO_PROVIDER";
+
+    public static final String REPORTLET = "REPORTLET";
+
+    public static final String ACCOUNT_RULE = "ACCOUNT_RULE";
+
+    public static final String PASSWORD_RULE = "PASSWORD_RULE";
+
+    public static final String TASKJOB_DELEGATE = "TASKJOB_DELEGATE";
+
+    public static final String LOGIC_ACTIONS = "LOGIC_ACTIONS";
+
+    public static final String VALIDATOR = "VALIDATOR";
+
+    public static final String RECIPIENTS_PROVIDER = "RECIPIENTS_PROVIDER";
+
+    public static final String AUDIT_APPENDER = "AUDIT_APPENDER";
+
+    private static final Set<String> VALUES;
+
+    static {
+        Set<String> values = new TreeSet<>();
+        for (Field field : IdRepoImplementationType.class.getDeclaredFields()) {
+            if (Modifier.isStatic(field.getModifiers()) && String.class.equals(field.getType())) {
+                values.add(field.getName());
+            }
+        }
+        VALUES = Collections.unmodifiableSet(values);
+    }
+
+    public static Set<String> values() {
+        return VALUES;
+    }
+
+    private IdRepoImplementationType() {
+        // private constructor for static utility class
+    }
+}
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/ImplementationType.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/ImplementationTypesHolder.java
similarity index 62%
copy from common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/ImplementationType.java
copy to common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/ImplementationTypesHolder.java
index 98e10b7..1960352 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/ImplementationType.java
+++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/ImplementationTypesHolder.java
@@ -18,26 +18,22 @@
  */
 package org.apache.syncope.common.lib.types;
 
-import javax.xml.bind.annotation.XmlEnum;
+public final class ImplementationTypesHolder extends ValueHolder<String> {
 
-@XmlEnum
-public enum ImplementationType {
+    private static final Object MONITOR = new Object();
 
-    JWT_SSO_PROVIDER,
-    REPORTLET,
-    ACCOUNT_RULE,
-    PASSWORD_RULE,
-    ITEM_TRANSFORMER,
-    TASKJOB_DELEGATE,
-    RECON_FILTER_BUILDER,
-    LOGIC_ACTIONS,
-    PROPAGATION_ACTIONS,
-    PULL_ACTIONS,
-    PUSH_ACTIONS,
-    PULL_CORRELATION_RULE,
-    PUSH_CORRELATION_RULE,
-    VALIDATOR,
-    RECIPIENTS_PROVIDER,
-    AUDIT_APPENDER;
+    private static ImplementationTypesHolder INSTANCE;
 
+    public static ImplementationTypesHolder getInstance() {
+        synchronized (MONITOR) {
+            if (INSTANCE == null) {
+                INSTANCE = new ImplementationTypesHolder();
+            }
+        }
+        return INSTANCE;
+    }
+
+    private ImplementationTypesHolder() {
+        // private constructor for singleton
+    }
 }
diff --git a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/ImplementationType.java b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/ValueHolder.java
similarity index 67%
rename from common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/ImplementationType.java
rename to common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/ValueHolder.java
index 98e10b7..8c514cb 100644
--- a/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/ImplementationType.java
+++ b/common/idrepo/lib/src/main/java/org/apache/syncope/common/lib/types/ValueHolder.java
@@ -18,26 +18,20 @@
  */
 package org.apache.syncope.common.lib.types;
 
-import javax.xml.bind.annotation.XmlEnum;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
 
-@XmlEnum
-public enum ImplementationType {
+abstract class ValueHolder<T> {
 
-    JWT_SSO_PROVIDER,
-    REPORTLET,
-    ACCOUNT_RULE,
-    PASSWORD_RULE,
-    ITEM_TRANSFORMER,
-    TASKJOB_DELEGATE,
-    RECON_FILTER_BUILDER,
-    LOGIC_ACTIONS,
-    PROPAGATION_ACTIONS,
-    PULL_ACTIONS,
-    PUSH_ACTIONS,
-    PULL_CORRELATION_RULE,
-    PUSH_CORRELATION_RULE,
-    VALIDATOR,
-    RECIPIENTS_PROVIDER,
-    AUDIT_APPENDER;
+    protected final Set<T> values = Collections.synchronizedSet(new HashSet<>());
 
+    public void addAll(final Collection<T> values) {
+        this.values.addAll(values);
+    }
+
+    public Set<T> getValues() {
+        return Collections.unmodifiableSet(values);
+    }
 }
diff --git a/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/ImplementationService.java b/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/ImplementationService.java
index 912b4ab..af8590f 100644
--- a/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/ImplementationService.java
+++ b/common/idrepo/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/ImplementationService.java
@@ -37,7 +37,6 @@ import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import org.apache.syncope.common.lib.to.ImplementationTO;
-import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.common.rest.api.RESTHeaders;
 
 /**
@@ -56,10 +55,12 @@ public interface ImplementationService extends JAXRSService {
      * @param type implementation type
      * @return list of all implementations.
      */
+    @Parameter(name = "type", description = "Implementation's type", in = ParameterIn.PATH, schema =
+            @Schema(type = "string"))
     @GET
     @Path("{type}")
     @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML })
-    List<ImplementationTO> list(@NotNull @PathParam("type") ImplementationType type);
+    List<ImplementationTO> list(@NotNull @PathParam("type") String type);
 
     /**
      * Returns implementation with matching type and key.
@@ -68,10 +69,14 @@ public interface ImplementationService extends JAXRSService {
      * @param key key of implementation to be read
      * @return implementation with matching key
      */
+    @Parameter(name = "type", description = "Implementation's type", in = ParameterIn.PATH, schema =
+            @Schema(type = "string"))
+    @Parameter(name = "key", description = "Implementation's key", in = ParameterIn.PATH, schema =
+            @Schema(type = "string"))
     @GET
     @Path("{type}/{key}")
     @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML })
-    ImplementationTO read(@NotNull @PathParam("type") ImplementationType type, @NotNull @PathParam("key") String key);
+    ImplementationTO read(@NotNull @PathParam("type") String type, @NotNull @PathParam("key") String key);
 
     /**
      * Creates a new implementation.
@@ -80,7 +85,7 @@ public interface ImplementationService extends JAXRSService {
      * @return Response object featuring Location header of created implementation
      */
     @Parameter(name = "type", description = "Implementation's type", in = ParameterIn.PATH, schema =
-            @Schema(implementation = ImplementationType.class))
+            @Schema(type = "string"))
     @Parameter(name = "key", description = "Implementation's key", in = ParameterIn.PATH, schema =
             @Schema(type = "string"))
     @POST
@@ -96,7 +101,7 @@ public interface ImplementationService extends JAXRSService {
      * @return an empty response if operation was successful
      */
     @Parameter(name = "type", description = "Implementation's type", in = ParameterIn.PATH, schema =
-            @Schema(implementation = ImplementationType.class))
+            @Schema(type = "string"))
     @Parameter(name = "key", description = "Implementation's key", in = ParameterIn.PATH, schema =
             @Schema(type = "string"))
     @PUT
@@ -112,9 +117,12 @@ public interface ImplementationService extends JAXRSService {
      * @param key key for implementation to be deleted
      * @return an empty response if operation was successful
      */
+    @Parameter(name = "type", description = "Implementation's type", in = ParameterIn.PATH, schema =
+            @Schema(type = "string"))
+    @Parameter(name = "key", description = "Implementation's key", in = ParameterIn.PATH, schema =
+            @Schema(type = "string"))
     @DELETE
     @Path("{type}/{key}")
     @Produces({ MediaType.APPLICATION_JSON, RESTHeaders.APPLICATION_YAML, MediaType.APPLICATION_XML })
-    Response delete(@NotNull @PathParam("type") ImplementationType type, @NotNull @PathParam("key") String key);
-
+    Response delete(@NotNull @PathParam("type") String type, @NotNull @PathParam("key") String key);
 }
diff --git a/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/init/OIDCClientLoader.java b/core/idm/logic/src/main/java/org/apache/syncope/core/logic/init/IdMImplementationTypeLoader.java
similarity index 76%
copy from ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/init/OIDCClientLoader.java
copy to core/idm/logic/src/main/java/org/apache/syncope/core/logic/init/IdMImplementationTypeLoader.java
index 847905f..34a85ca 100644
--- a/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/init/OIDCClientLoader.java
+++ b/core/idm/logic/src/main/java/org/apache/syncope/core/logic/init/IdMImplementationTypeLoader.java
@@ -18,21 +18,21 @@
  */
 package org.apache.syncope.core.logic.init;
 
-import org.apache.syncope.common.lib.types.OIDCClientEntitlement;
+import org.apache.syncope.common.lib.types.IdMImplementationType;
+import org.apache.syncope.common.lib.types.ImplementationTypesHolder;
 import org.apache.syncope.core.persistence.api.SyncopeCoreLoader;
-import org.apache.syncope.core.provisioning.api.EntitlementsHolder;
 import org.springframework.stereotype.Component;
 
 @Component
-public class OIDCClientLoader implements SyncopeCoreLoader {
+public class IdMImplementationTypeLoader implements SyncopeCoreLoader {
 
     @Override
     public int getOrder() {
-        return 1000;
+        return Integer.MIN_VALUE;
     }
 
     @Override
     public void load() {
-        EntitlementsHolder.getInstance().init(OIDCClientEntitlement.values());
+        ImplementationTypesHolder.getInstance().addAll(IdMImplementationType.values());
     }
 }
diff --git a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/GroupLogic.java b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/GroupLogic.java
index a7aa6a0..b33165f 100644
--- a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/GroupLogic.java
+++ b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/GroupLogic.java
@@ -43,8 +43,8 @@ import org.apache.syncope.common.lib.to.ProvisioningResult;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.ProvisionAction;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.common.lib.types.IdRepoImplementationType;
 import org.apache.syncope.common.lib.types.ImplementationEngine;
-import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.common.lib.types.JobType;
 import org.apache.syncope.common.lib.types.PatchOperation;
 import org.apache.syncope.common.lib.types.StandardEntitlement;
@@ -390,13 +390,13 @@ public class GroupLogic extends AbstractAnyLogic<GroupTO, GroupCR, GroupUR> {
             throw new NotFoundException("Group " + key);
         }
 
-        Implementation jobDelegate = implementationDAO.find(ImplementationType.TASKJOB_DELEGATE).stream().
+        Implementation jobDelegate = implementationDAO.findByType(IdRepoImplementationType.TASKJOB_DELEGATE).stream().
                 filter(impl -> GroupMemberProvisionTaskJobDelegate.class.getName().equals(impl.getBody())).
                 findFirst().orElseGet(() -> {
                     Implementation caz = entityFactory.newEntity(Implementation.class);
                     caz.setKey(GroupMemberProvisionTaskJobDelegate.class.getSimpleName());
                     caz.setEngine(ImplementationEngine.JAVA);
-                    caz.setType(ImplementationType.TASKJOB_DELEGATE);
+                    caz.setType(IdRepoImplementationType.TASKJOB_DELEGATE);
                     caz.setBody(GroupMemberProvisionTaskJobDelegate.class.getName());
                     caz = implementationDAO.save(caz);
                     return caz;
diff --git a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/ImplementationLogic.java b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/ImplementationLogic.java
index 19efd1f..1a53cf4 100644
--- a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/ImplementationLogic.java
+++ b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/ImplementationLogic.java
@@ -26,7 +26,9 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.to.ImplementationTO;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
-import org.apache.syncope.common.lib.types.ImplementationType;
+import org.apache.syncope.common.lib.types.IdMImplementationType;
+import org.apache.syncope.common.lib.types.IdRepoImplementationType;
+import org.apache.syncope.common.lib.types.ImplementationTypesHolder;
 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;
@@ -75,15 +77,28 @@ public class ImplementationLogic extends AbstractTransactionalLogic<Implementati
     @Autowired
     private NotificationDAO notificationDAO;
 
+    private void checkType(final String type) {
+        if (!ImplementationTypesHolder.getInstance().getValues().contains(type)) {
+            SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidImplementationType);
+            sce.getElements().add("Implementation type not found: ");
+            throw sce;
+        }
+    }
+
     @PreAuthorize("hasRole('" + StandardEntitlement.IMPLEMENTATION_LIST + "')")
     @Transactional(readOnly = true)
-    public List<ImplementationTO> list(final ImplementationType type) {
-        return implementationDAO.find(type).stream().map(binder::getImplementationTO).collect(Collectors.toList());
+    public List<ImplementationTO> list(final String type) {
+        checkType(type);
+
+        return implementationDAO.findByType(type).stream().
+                map(binder::getImplementationTO).collect(Collectors.toList());
     }
 
     @PreAuthorize("hasRole('" + StandardEntitlement.IMPLEMENTATION_READ + "')")
     @Transactional(readOnly = true)
-    public ImplementationTO read(final ImplementationType type, final String key) {
+    public ImplementationTO read(final String type, final String key) {
+        checkType(type);
+
         Implementation implementation = implementationDAO.find(key);
         if (implementation == null) {
             LOG.error("Could not find implementation '" + key + "'");
@@ -91,7 +106,7 @@ public class ImplementationLogic extends AbstractTransactionalLogic<Implementati
             throw new NotFoundException(key);
         }
 
-        if (implementation.getType() != type) {
+        if (!implementation.getType().equals(type)) {
             SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidRequest);
             sce.getElements().add("Found " + type + ", expected " + implementation.getType());
             throw sce;
@@ -108,6 +123,8 @@ public class ImplementationLogic extends AbstractTransactionalLogic<Implementati
             throw sce;
         }
 
+        checkType(implementationTO.getType());
+
         Implementation implementation = implementationDAO.find(implementationTO.getKey());
         if (implementation != null) {
             throw new DuplicateException(implementationTO.getKey());
@@ -125,6 +142,8 @@ public class ImplementationLogic extends AbstractTransactionalLogic<Implementati
             throw new NotFoundException(implementationTO.getKey());
         }
 
+        checkType(implementationTO.getType());
+
         binder.update(implementation, implementationTO);
         implementation = implementationDAO.save(implementation);
 
@@ -132,7 +151,7 @@ public class ImplementationLogic extends AbstractTransactionalLogic<Implementati
     }
 
     @PreAuthorize("hasRole('" + StandardEntitlement.IMPLEMENTATION_DELETE + "')")
-    public void delete(final ImplementationType type, final String key) {
+    public void delete(final String type, final String key) {
         Implementation implementation = implementationDAO.find(key);
         if (implementation == null) {
             LOG.error("Could not find implementation '" + key + "'");
@@ -140,7 +159,7 @@ public class ImplementationLogic extends AbstractTransactionalLogic<Implementati
             throw new NotFoundException(key);
         }
 
-        if (implementation.getType() != type) {
+        if (!implementation.getType().equals(type)) {
             SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidRequest);
             sce.getElements().add("Found " + type + ", expected " + implementation.getType());
             throw sce;
@@ -148,59 +167,59 @@ public class ImplementationLogic extends AbstractTransactionalLogic<Implementati
 
         boolean inUse = false;
         switch (implementation.getType()) {
-            case REPORTLET:
+            case IdRepoImplementationType.REPORTLET:
                 inUse = !reportDAO.findByReportlet(implementation).isEmpty();
                 break;
 
-            case ACCOUNT_RULE:
+            case IdRepoImplementationType.ACCOUNT_RULE:
                 inUse = !policyDAO.findByAccountRule(implementation).isEmpty();
                 break;
 
-            case PASSWORD_RULE:
+            case IdRepoImplementationType.PASSWORD_RULE:
                 inUse = !policyDAO.findByPasswordRule(implementation).isEmpty();
                 break;
 
-            case ITEM_TRANSFORMER:
+            case IdMImplementationType.ITEM_TRANSFORMER:
                 inUse = !resourceDAO.findByTransformer(implementation).isEmpty();
                 break;
 
-            case TASKJOB_DELEGATE:
+            case IdRepoImplementationType.TASKJOB_DELEGATE:
                 inUse = !taskDAO.findByDelegate(implementation).isEmpty();
                 break;
 
-            case RECON_FILTER_BUILDER:
+            case IdMImplementationType.RECON_FILTER_BUILDER:
                 inUse = !taskDAO.findByReconFilterBuilder(implementation).isEmpty();
                 break;
 
-            case LOGIC_ACTIONS:
+            case IdRepoImplementationType.LOGIC_ACTIONS:
                 inUse = !realmDAO.findByLogicActions(implementation).isEmpty();
                 break;
 
-            case PROPAGATION_ACTIONS:
+            case IdMImplementationType.PROPAGATION_ACTIONS:
                 inUse = !resourceDAO.findByPropagationActions(implementation).isEmpty();
                 break;
 
-            case PULL_ACTIONS:
+            case IdMImplementationType.PULL_ACTIONS:
                 inUse = !taskDAO.findByPullActions(implementation).isEmpty();
                 break;
 
-            case PUSH_ACTIONS:
+            case IdMImplementationType.PUSH_ACTIONS:
                 inUse = !taskDAO.findByPushActions(implementation).isEmpty();
                 break;
 
-            case PULL_CORRELATION_RULE:
+            case IdMImplementationType.PULL_CORRELATION_RULE:
                 inUse = !policyDAO.findByPullCorrelationRule(implementation).isEmpty();
                 break;
 
-            case PUSH_CORRELATION_RULE:
+            case IdMImplementationType.PUSH_CORRELATION_RULE:
                 inUse = !policyDAO.findByPushCorrelationRule(implementation).isEmpty();
                 break;
 
-            case VALIDATOR:
+            case IdRepoImplementationType.VALIDATOR:
                 inUse = !plainSchemaDAO.findByValidator(implementation).isEmpty();
                 break;
 
-            case RECIPIENTS_PROVIDER:
+            case IdRepoImplementationType.RECIPIENTS_PROVIDER:
                 inUse = !notificationDAO.findByRecipientsProvider(implementation).isEmpty();
                 break;
 
@@ -243,5 +262,4 @@ public class ImplementationLogic extends AbstractTransactionalLogic<Implementati
 
         throw new UnresolvedReferenceException();
     }
-
 }
diff --git a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/SyncopeLogic.java b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/SyncopeLogic.java
index edeaecd..20749b4 100644
--- a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/SyncopeLogic.java
+++ b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/SyncopeLogic.java
@@ -25,7 +25,6 @@ import java.lang.reflect.Method;
 import java.net.InetAddress;
 import java.net.URI;
 import java.net.UnknownHostException;
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
@@ -44,7 +43,8 @@ import org.apache.syncope.common.lib.to.EntityTO;
 import org.apache.syncope.common.lib.to.GroupTO;
 import org.apache.syncope.common.lib.to.TypeExtensionTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
-import org.apache.syncope.common.lib.types.ImplementationType;
+import org.apache.syncope.common.lib.types.EntitlementsHolder;
+import org.apache.syncope.common.lib.types.ImplementationTypesHolder;
 import org.apache.syncope.common.lib.types.TaskType;
 import org.apache.syncope.core.spring.security.PasswordGenerator;
 import org.apache.syncope.core.persistence.api.ImplementationLookup;
@@ -81,7 +81,6 @@ import org.apache.syncope.core.persistence.api.entity.policy.PasswordPolicy;
 import org.apache.syncope.core.provisioning.api.AnyObjectProvisioningManager;
 import org.apache.syncope.core.provisioning.api.AuditManager;
 import org.apache.syncope.core.provisioning.api.ConnIdBundleManager;
-import org.apache.syncope.core.provisioning.api.EntitlementsHolder;
 import org.apache.syncope.core.provisioning.api.GroupProvisioningManager;
 import org.apache.syncope.core.provisioning.api.UserProvisioningManager;
 import org.apache.syncope.core.provisioning.api.cache.VirAttrCache;
@@ -283,14 +282,13 @@ public class SyncopeLogic extends AbstractLogic<EntityTO> {
                 PLATFORM_INFO.getPersistenceInfo().
                         setConfDAO(AopUtils.getTargetClass(confDAO).getName());
 
-                Arrays.stream(ImplementationType.values()).
-                        forEach(type -> {
-                            JavaImplInfo javaImplInfo = new JavaImplInfo();
-                            javaImplInfo.setType(type);
-                            javaImplInfo.getClasses().addAll(implLookup.getClassNames(type));
+                ImplementationTypesHolder.getInstance().getValues().forEach(type -> {
+                    JavaImplInfo javaImplInfo = new JavaImplInfo();
+                    javaImplInfo.setType(type);
+                    javaImplInfo.getClasses().addAll(implLookup.getClassNames(type));
 
-                            PLATFORM_INFO.getJavaImplInfos().add(javaImplInfo);
-                        });
+                    PLATFORM_INFO.getJavaImplInfos().add(javaImplInfo);
+                });
             }
 
             PLATFORM_INFO.setSelfRegAllowed(isSelfRegAllowed());
@@ -300,6 +298,9 @@ public class SyncopeLogic extends AbstractLogic<EntityTO> {
             PLATFORM_INFO.getEntitlements().clear();
             PLATFORM_INFO.getEntitlements().addAll(EntitlementsHolder.getInstance().getValues());
 
+            PLATFORM_INFO.getImplementationTypes().clear();
+            PLATFORM_INFO.getImplementationTypes().addAll(ImplementationTypesHolder.getInstance().getValues());
+
             AuthContextUtils.execWithAuthContext(AuthContextUtils.getDomain(), () -> {
                 PLATFORM_INFO.getAnyTypes().clear();
                 PLATFORM_INFO.getAnyTypes().addAll(anyTypeDAO.findAll().stream().
diff --git a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/init/ClassPathScanImplementationLookup.java b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/init/ClassPathScanImplementationLookup.java
index 79f1c87..db296da 100644
--- a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/init/ClassPathScanImplementationLookup.java
+++ b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/init/ClassPathScanImplementationLookup.java
@@ -20,7 +20,6 @@ package org.apache.syncope.core.logic.init;
 
 import java.lang.reflect.Modifier;
 import java.util.Collections;
-import java.util.EnumMap;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
@@ -30,7 +29,9 @@ import org.apache.syncope.common.lib.policy.PasswordRuleConf;
 import org.apache.syncope.common.lib.policy.PullCorrelationRuleConf;
 import org.apache.syncope.common.lib.policy.PushCorrelationRuleConf;
 import org.apache.syncope.common.lib.report.ReportletConf;
-import org.apache.syncope.common.lib.types.ImplementationType;
+import org.apache.syncope.common.lib.types.IdMImplementationType;
+import org.apache.syncope.common.lib.types.IdRepoImplementationType;
+import org.apache.syncope.common.lib.types.ImplementationTypesHolder;
 import org.apache.syncope.core.logic.audit.AuditAppender;
 import org.apache.syncope.core.persistence.api.ImplementationLookup;
 import org.apache.syncope.core.persistence.api.attrvalue.validation.Validator;
@@ -72,7 +73,7 @@ public class ClassPathScanImplementationLookup implements ImplementationLookup {
 
     private static final String DEFAULT_BASE_PACKAGE = "org.apache.syncope.core";
 
-    private Map<ImplementationType, Set<String>> classNames;
+    private Map<String, Set<String>> classNames;
 
     private Set<Class<?>> jwtSSOProviderClasses;
 
@@ -90,7 +91,7 @@ public class ClassPathScanImplementationLookup implements ImplementationLookup {
 
     @Override
     public int getOrder() {
-        return Integer.MIN_VALUE;
+        return Integer.MAX_VALUE;
     }
 
     /**
@@ -105,10 +106,9 @@ public class ClassPathScanImplementationLookup implements ImplementationLookup {
     @SuppressWarnings("unchecked")
     @Override
     public void load() {
-        classNames = new EnumMap<>(ImplementationType.class);
-        for (ImplementationType type : ImplementationType.values()) {
-            classNames.put(type, new HashSet<>());
-        }
+        classNames = new HashMap<>();
+        ImplementationTypesHolder.getInstance().getValues().
+                forEach(type -> classNames.put(type, new HashSet<>()));
 
         jwtSSOProviderClasses = new HashSet<>();
         reportletClasses = new HashMap<>();
@@ -143,7 +143,7 @@ public class ClassPathScanImplementationLookup implements ImplementationLookup {
                 boolean isAbstractClazz = Modifier.isAbstract(clazz.getModifiers());
 
                 if (JWTSSOProvider.class.isAssignableFrom(clazz) && !isAbstractClazz) {
-                    classNames.get(ImplementationType.JWT_SSO_PROVIDER).add(clazz.getName());
+                    classNames.get(IdRepoImplementationType.JWT_SSO_PROVIDER).add(clazz.getName());
                     jwtSSOProviderClasses.add(clazz);
                 }
 
@@ -152,7 +152,7 @@ public class ClassPathScanImplementationLookup implements ImplementationLookup {
                     if (annotation == null) {
                         LOG.warn("Found Reportlet {} without declared configuration", clazz.getName());
                     } else {
-                        classNames.get(ImplementationType.REPORTLET).add(clazz.getName());
+                        classNames.get(IdRepoImplementationType.REPORTLET).add(clazz.getName());
                         reportletClasses.put(annotation.value(), (Class<? extends Reportlet>) clazz);
                     }
                 }
@@ -162,7 +162,7 @@ public class ClassPathScanImplementationLookup implements ImplementationLookup {
                     if (annotation == null) {
                         LOG.warn("Found account policy rule {} without declared configuration", clazz.getName());
                     } else {
-                        classNames.get(ImplementationType.ACCOUNT_RULE).add(clazz.getName());
+                        classNames.get(IdRepoImplementationType.ACCOUNT_RULE).add(clazz.getName());
                         accountRuleClasses.put(annotation.value(), (Class<? extends AccountRule>) clazz);
                     }
                 }
@@ -172,7 +172,7 @@ public class ClassPathScanImplementationLookup implements ImplementationLookup {
                     if (annotation == null) {
                         LOG.warn("Found password policy rule {} without declared configuration", clazz.getName());
                     } else {
-                        classNames.get(ImplementationType.PASSWORD_RULE).add(clazz.getName());
+                        classNames.get(IdRepoImplementationType.PASSWORD_RULE).add(clazz.getName());
                         passwordRuleClasses.put(annotation.value(), (Class<? extends PasswordRule>) clazz);
                     }
                 }
@@ -182,7 +182,7 @@ public class ClassPathScanImplementationLookup implements ImplementationLookup {
                     if (annotation == null) {
                         LOG.warn("Found pull correlation rule {} without declared configuration", clazz.getName());
                     } else {
-                        classNames.get(ImplementationType.PULL_CORRELATION_RULE).add(clazz.getName());
+                        classNames.get(IdMImplementationType.PULL_CORRELATION_RULE).add(clazz.getName());
                         pullCRClasses.put(annotation.value(), (Class<? extends PullCorrelationRule>) clazz);
                     }
                 }
@@ -192,7 +192,7 @@ public class ClassPathScanImplementationLookup implements ImplementationLookup {
                     if (annotation == null) {
                         LOG.warn("Found push correlation rule {} without declared configuration", clazz.getName());
                     } else {
-                        classNames.get(ImplementationType.PUSH_CORRELATION_RULE).add(clazz.getName());
+                        classNames.get(IdMImplementationType.PUSH_CORRELATION_RULE).add(clazz.getName());
                         pushCRClasses.put(annotation.value(), (Class<? extends PushCorrelationRule>) clazz);
                     }
                 }
@@ -200,7 +200,7 @@ public class ClassPathScanImplementationLookup implements ImplementationLookup {
                 if (ItemTransformer.class.isAssignableFrom(clazz) && !isAbstractClazz
                         && !clazz.equals(JEXLItemTransformerImpl.class)) {
 
-                    classNames.get(ImplementationType.ITEM_TRANSFORMER).add(clazz.getName());
+                    classNames.get(IdMImplementationType.ITEM_TRANSFORMER).add(clazz.getName());
                 }
 
                 if (SchedTaskJobDelegate.class.isAssignableFrom(clazz) && !isAbstractClazz
@@ -208,39 +208,39 @@ public class ClassPathScanImplementationLookup implements ImplementationLookup {
                         && !PushJobDelegate.class.isAssignableFrom(clazz)
                         && !GroupMemberProvisionTaskJobDelegate.class.isAssignableFrom(clazz)) {
 
-                    classNames.get(ImplementationType.TASKJOB_DELEGATE).add(bd.getBeanClassName());
+                    classNames.get(IdRepoImplementationType.TASKJOB_DELEGATE).add(bd.getBeanClassName());
                 }
 
                 if (ReconFilterBuilder.class.isAssignableFrom(clazz) && !isAbstractClazz) {
-                    classNames.get(ImplementationType.RECON_FILTER_BUILDER).add(bd.getBeanClassName());
+                    classNames.get(IdMImplementationType.RECON_FILTER_BUILDER).add(bd.getBeanClassName());
                 }
 
                 if (LogicActions.class.isAssignableFrom(clazz) && !isAbstractClazz) {
-                    classNames.get(ImplementationType.LOGIC_ACTIONS).add(bd.getBeanClassName());
+                    classNames.get(IdRepoImplementationType.LOGIC_ACTIONS).add(bd.getBeanClassName());
                 }
 
                 if (PropagationActions.class.isAssignableFrom(clazz) && !isAbstractClazz) {
-                    classNames.get(ImplementationType.PROPAGATION_ACTIONS).add(bd.getBeanClassName());
+                    classNames.get(IdMImplementationType.PROPAGATION_ACTIONS).add(bd.getBeanClassName());
                 }
 
                 if (PullActions.class.isAssignableFrom(clazz) && !isAbstractClazz) {
-                    classNames.get(ImplementationType.PULL_ACTIONS).add(bd.getBeanClassName());
+                    classNames.get(IdMImplementationType.PULL_ACTIONS).add(bd.getBeanClassName());
                 }
 
                 if (PushActions.class.isAssignableFrom(clazz) && !isAbstractClazz) {
-                    classNames.get(ImplementationType.PUSH_ACTIONS).add(bd.getBeanClassName());
+                    classNames.get(IdMImplementationType.PUSH_ACTIONS).add(bd.getBeanClassName());
                 }
 
                 if (Validator.class.isAssignableFrom(clazz) && !isAbstractClazz) {
-                    classNames.get(ImplementationType.VALIDATOR).add(bd.getBeanClassName());
+                    classNames.get(IdRepoImplementationType.VALIDATOR).add(bd.getBeanClassName());
                 }
 
                 if (RecipientsProvider.class.isAssignableFrom(clazz) && !isAbstractClazz) {
-                    classNames.get(ImplementationType.RECIPIENTS_PROVIDER).add(bd.getBeanClassName());
+                    classNames.get(IdRepoImplementationType.RECIPIENTS_PROVIDER).add(bd.getBeanClassName());
                 }
 
                 if (AuditAppender.class.isAssignableFrom(clazz) && !isAbstractClazz) {
-                    classNames.get(ImplementationType.AUDIT_APPENDER).add(clazz.getName());
+                    classNames.get(IdRepoImplementationType.AUDIT_APPENDER).add(clazz.getName());
                     auditAppenderClasses.add(clazz);
                 }
             } catch (Throwable t) {
@@ -261,7 +261,7 @@ public class ClassPathScanImplementationLookup implements ImplementationLookup {
     }
 
     @Override
-    public Set<String> getClassNames(final ImplementationType type) {
+    public Set<String> getClassNames(final String type) {
         return classNames.get(type);
     }
 
diff --git a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/init/EntitlementAccessor.java b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/init/EntitlementAccessor.java
index 75b2fa2..dfae712 100644
--- a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/init/EntitlementAccessor.java
+++ b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/init/EntitlementAccessor.java
@@ -18,9 +18,8 @@
  */
 package org.apache.syncope.core.logic.init;
 
-import org.apache.syncope.core.provisioning.api.EntitlementsHolder;
+import org.apache.syncope.common.lib.types.EntitlementsHolder;
 import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
-import org.apache.syncope.core.persistence.api.entity.AnyType;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 import org.springframework.transaction.annotation.Transactional;
@@ -38,10 +37,8 @@ public class EntitlementAccessor {
 
     @Transactional(readOnly = true)
     public void addEntitlementsForAnyTypes() {
-        for (AnyType anyType : anyTypeDAO.findAll()) {
-            if (anyType != anyTypeDAO.findUser() && anyType != anyTypeDAO.findGroup()) {
-                EntitlementsHolder.getInstance().addFor(anyType.getKey());
-            }
-        }
+        anyTypeDAO.findAll().stream().
+                filter(anyType -> anyType != anyTypeDAO.findUser() && anyType != anyTypeDAO.findGroup()).
+                forEach(anyType -> EntitlementsHolder.getInstance().addFor(anyType.getKey()));
     }
 }
diff --git a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/init/EntitlementLoader.java b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/init/EntitlementLoader.java
index 41716cb..7fbbad3 100644
--- a/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/init/EntitlementLoader.java
+++ b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/init/EntitlementLoader.java
@@ -19,10 +19,10 @@
 package org.apache.syncope.core.logic.init;
 
 import javax.sql.DataSource;
+import org.apache.syncope.common.lib.types.EntitlementsHolder;
 import org.apache.syncope.common.lib.types.StandardEntitlement;
-import org.apache.syncope.core.provisioning.api.EntitlementsHolder;
-import org.apache.syncope.core.spring.security.AuthContextUtils;
 import org.apache.syncope.core.persistence.api.SyncopeCoreLoader;
+import org.apache.syncope.core.spring.security.AuthContextUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
@@ -39,7 +39,7 @@ public class EntitlementLoader implements SyncopeCoreLoader {
 
     @Override
     public void load() {
-        EntitlementsHolder.getInstance().init(StandardEntitlement.values());
+        EntitlementsHolder.getInstance().addAll(StandardEntitlement.values());
     }
 
     @Override
diff --git a/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/init/OIDCClientLoader.java b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/init/IdRepoImplementationTypeLoader.java
similarity index 76%
copy from ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/init/OIDCClientLoader.java
copy to core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/init/IdRepoImplementationTypeLoader.java
index 847905f..aef14be 100644
--- a/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/init/OIDCClientLoader.java
+++ b/core/idrepo/logic/src/main/java/org/apache/syncope/core/logic/init/IdRepoImplementationTypeLoader.java
@@ -18,21 +18,21 @@
  */
 package org.apache.syncope.core.logic.init;
 
-import org.apache.syncope.common.lib.types.OIDCClientEntitlement;
+import org.apache.syncope.common.lib.types.IdRepoImplementationType;
+import org.apache.syncope.common.lib.types.ImplementationTypesHolder;
 import org.apache.syncope.core.persistence.api.SyncopeCoreLoader;
-import org.apache.syncope.core.provisioning.api.EntitlementsHolder;
 import org.springframework.stereotype.Component;
 
 @Component
-public class OIDCClientLoader implements SyncopeCoreLoader {
+public class IdRepoImplementationTypeLoader implements SyncopeCoreLoader {
 
     @Override
     public int getOrder() {
-        return 1000;
+        return Integer.MIN_VALUE;
     }
 
     @Override
     public void load() {
-        EntitlementsHolder.getInstance().init(OIDCClientEntitlement.values());
+        ImplementationTypesHolder.getInstance().addAll(IdRepoImplementationType.values());
     }
 }
diff --git a/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ImplementationServiceImpl.java b/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ImplementationServiceImpl.java
index 6113c81..d4db74d 100644
--- a/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ImplementationServiceImpl.java
+++ b/core/idrepo/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ImplementationServiceImpl.java
@@ -22,7 +22,6 @@ import java.net.URI;
 import java.util.List;
 import javax.ws.rs.core.Response;
 import org.apache.syncope.common.lib.to.ImplementationTO;
-import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.common.rest.api.RESTHeaders;
 import org.apache.syncope.common.rest.api.service.ImplementationService;
 import org.apache.syncope.core.logic.ImplementationLogic;
@@ -36,12 +35,12 @@ public class ImplementationServiceImpl extends AbstractServiceImpl implements Im
     private ImplementationLogic logic;
 
     @Override
-    public List<ImplementationTO> list(final ImplementationType type) {
+    public List<ImplementationTO> list(final String type) {
         return logic.list(type);
     }
 
     @Override
-    public ImplementationTO read(final ImplementationType type, final String key) {
+    public ImplementationTO read(final String type, final String key) {
         return logic.read(type, key);
     }
 
@@ -61,9 +60,8 @@ public class ImplementationServiceImpl extends AbstractServiceImpl implements Im
     }
 
     @Override
-    public Response delete(final ImplementationType type, final String key) {
+    public Response delete(final String type, final String key) {
         logic.delete(type, key);
         return Response.noContent().build();
     }
-
 }
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/ImplementationLookup.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/ImplementationLookup.java
index 7893946..0fea24c 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/ImplementationLookup.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/ImplementationLookup.java
@@ -24,7 +24,6 @@ import org.apache.syncope.common.lib.policy.PasswordRuleConf;
 import org.apache.syncope.common.lib.policy.PullCorrelationRuleConf;
 import org.apache.syncope.common.lib.policy.PushCorrelationRuleConf;
 import org.apache.syncope.common.lib.report.ReportletConf;
-import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.core.persistence.api.dao.AccountRule;
 import org.apache.syncope.core.persistence.api.dao.PasswordRule;
 import org.apache.syncope.core.persistence.api.dao.PullCorrelationRule;
@@ -33,7 +32,7 @@ import org.apache.syncope.core.persistence.api.dao.Reportlet;
 
 public interface ImplementationLookup extends SyncopeCoreLoader {
 
-    Set<String> getClassNames(ImplementationType type);
+    Set<String> getClassNames(String type);
 
     Set<Class<?>> getJWTSSOProviderClasses();
 
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/ImplementationDAO.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/ImplementationDAO.java
index 71b7399..44b19e9 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/ImplementationDAO.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/ImplementationDAO.java
@@ -19,19 +19,17 @@
 package org.apache.syncope.core.persistence.api.dao;
 
 import java.util.List;
-import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.core.persistence.api.entity.Implementation;
 
 public interface ImplementationDAO extends DAO<Implementation> {
 
     Implementation find(String key);
 
-    List<Implementation> find(ImplementationType type);
+    List<Implementation> findByType(String type);
 
     List<Implementation> findAll();
 
     Implementation save(Implementation implementation);
 
     void delete(String key);
-
 }
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Implementation.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Implementation.java
index 761a06e..481a286 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Implementation.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/Implementation.java
@@ -19,7 +19,6 @@
 package org.apache.syncope.core.persistence.api.entity;
 
 import org.apache.syncope.common.lib.types.ImplementationEngine;
-import org.apache.syncope.common.lib.types.ImplementationType;
 
 public interface Implementation extends ProvidedKeyEntity {
 
@@ -27,9 +26,9 @@ public interface Implementation extends ProvidedKeyEntity {
 
     void setEngine(ImplementationEngine engine);
 
-    ImplementationType getType();
+    String getType();
 
-    void setType(ImplementationType type);
+    void setType(String type);
 
     String getBody();
 
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAImplementationDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAImplementationDAO.java
index 9148fbb..85e5613 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAImplementationDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAImplementationDAO.java
@@ -20,7 +20,6 @@ package org.apache.syncope.core.persistence.jpa.dao;
 
 import java.util.List;
 import javax.persistence.TypedQuery;
-import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.core.persistence.api.dao.ImplementationDAO;
 import org.apache.syncope.core.persistence.api.entity.Implementation;
 import org.apache.syncope.core.persistence.jpa.entity.JPAImplementation;
@@ -38,7 +37,7 @@ public class JPAImplementationDAO extends AbstractDAO<Implementation> implements
     }
 
     @Override
-    public List<Implementation> find(final ImplementationType type) {
+    public List<Implementation> findByType(final String type) {
         TypedQuery<Implementation> query = entityManager().createQuery(
                 "SELECT e FROM " + JPAImplementation.class.getSimpleName() + " e WHERE e.type=:type",
                 Implementation.class);
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractEntity.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractEntity.java
index 93e281e..1dd570d 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractEntity.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractEntity.java
@@ -19,7 +19,6 @@
 package org.apache.syncope.core.persistence.jpa.entity;
 
 import java.util.Objects;
-import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.core.persistence.api.entity.Entity;
 import org.apache.syncope.core.persistence.api.entity.Implementation;
 import org.slf4j.Logger;
@@ -37,8 +36,8 @@ public abstract class AbstractEntity implements Entity {
         }
     }
 
-    protected void checkImplementationType(final Implementation object, final ImplementationType expected) {
-        if (object != null && object.getType() != expected) {
+    protected void checkImplementationType(final Implementation object, final String expected) {
+        if (object != null && !object.getType().equals(expected)) {
             throw new ClassCastException("Expected " + expected + ", got " + object.getType());
         }
     }
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAImplementation.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAImplementation.java
index c4945fd..008f521 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAImplementation.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAImplementation.java
@@ -26,7 +26,6 @@ import javax.persistence.Enumerated;
 import javax.persistence.Lob;
 import javax.persistence.Table;
 import org.apache.syncope.common.lib.types.ImplementationEngine;
-import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.core.persistence.api.entity.Implementation;
 import org.apache.syncope.core.persistence.jpa.validation.entity.ImplementationCheck;
 
@@ -45,8 +44,7 @@ public class JPAImplementation extends AbstractProvidedKeyEntity implements Impl
     private ImplementationEngine engine;
 
     @Column(nullable = false)
-    @Enumerated(EnumType.STRING)
-    private ImplementationType type;
+    private String type;
 
     @Lob
     private String body;
@@ -62,12 +60,12 @@ public class JPAImplementation extends AbstractProvidedKeyEntity implements Impl
     }
 
     @Override
-    public ImplementationType getType() {
+    public String getType() {
         return type;
     }
 
     @Override
-    public void setType(final ImplementationType type) {
+    public void setType(final String type) {
         this.type = type;
     }
 
@@ -80,5 +78,4 @@ public class JPAImplementation extends AbstractProvidedKeyEntity implements Impl
     public void setBody(final String body) {
         this.body = body;
     }
-
 }
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 5543ef8..087375e 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
@@ -34,7 +34,7 @@ import javax.persistence.ManyToOne;
 import javax.persistence.OneToMany;
 import javax.persistence.Table;
 import javax.validation.constraints.NotNull;
-import org.apache.syncope.common.lib.types.ImplementationType;
+import org.apache.syncope.common.lib.types.IdRepoImplementationType;
 import org.apache.syncope.common.lib.types.TraceLevel;
 import org.apache.syncope.core.persistence.api.entity.AnyAbout;
 import org.apache.syncope.core.persistence.api.entity.AnyType;
@@ -123,7 +123,7 @@ public class JPANotification extends AbstractGeneratedKeyEntity implements Notif
     @Override
     public void setRecipientsProvider(final Implementation recipientsProvider) {
         checkType(recipientsProvider, JPAImplementation.class);
-        checkImplementationType(recipientsProvider, ImplementationType.RECIPIENTS_PROVIDER);
+        checkImplementationType(recipientsProvider, IdRepoImplementationType.RECIPIENTS_PROVIDER);
         this.recipientsProvider = (JPAImplementation) recipientsProvider;
     }
 
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 e26f5e9..e795177 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
@@ -31,7 +31,7 @@ import javax.persistence.Transient;
 import javax.validation.constraints.NotNull;
 import org.apache.syncope.common.lib.types.AttrSchemaType;
 import org.apache.syncope.common.lib.types.CipherAlgorithm;
-import org.apache.syncope.common.lib.types.ImplementationType;
+import org.apache.syncope.common.lib.types.IdRepoImplementationType;
 import org.apache.syncope.core.persistence.api.attrvalue.validation.Validator;
 import org.apache.syncope.core.persistence.api.entity.AnyTypeClass;
 import org.apache.syncope.core.persistence.api.entity.Implementation;
@@ -183,7 +183,7 @@ public class JPAPlainSchema extends AbstractSchema implements PlainSchema {
     @Override
     public void setValidator(final Implementation validator) {
         checkType(validator, JPAImplementation.class);
-        checkImplementationType(validator, ImplementationType.VALIDATOR);
+        checkImplementationType(validator, IdRepoImplementationType.VALIDATOR);
         this.validator = (JPAImplementation) validator;
     }
 
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPARealm.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPARealm.java
index 49bb739..3e0feca 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPARealm.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPARealm.java
@@ -36,7 +36,7 @@ import javax.persistence.UniqueConstraint;
 import javax.validation.constraints.Size;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.SyncopeConstants;
-import org.apache.syncope.common.lib.types.ImplementationType;
+import org.apache.syncope.common.lib.types.IdRepoImplementationType;
 import org.apache.syncope.core.persistence.api.entity.AnyTemplateRealm;
 import org.apache.syncope.core.persistence.api.entity.AnyType;
 import org.apache.syncope.core.persistence.api.entity.Implementation;
@@ -143,7 +143,7 @@ public class JPARealm extends AbstractGeneratedKeyEntity implements Realm {
     @Override
     public boolean add(final Implementation action) {
         checkType(action, JPAImplementation.class);
-        checkImplementationType(action, ImplementationType.LOGIC_ACTIONS);
+        checkImplementationType(action, IdRepoImplementationType.LOGIC_ACTIONS);
         return actions.contains((JPAImplementation) action) || actions.add((JPAImplementation) action);
     }
 
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAReport.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAReport.java
index bed6e36..334f511 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAReport.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAReport.java
@@ -31,7 +31,7 @@ import javax.persistence.ManyToOne;
 import javax.persistence.OneToMany;
 import javax.persistence.Table;
 import javax.validation.constraints.NotNull;
-import org.apache.syncope.common.lib.types.ImplementationType;
+import org.apache.syncope.common.lib.types.IdRepoImplementationType;
 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.ReportExec;
@@ -94,7 +94,7 @@ public class JPAReport extends AbstractGeneratedKeyEntity implements Report {
     @Override
     public boolean add(final Implementation reportlet) {
         checkType(reportlet, JPAImplementation.class);
-        checkImplementationType(reportlet, ImplementationType.REPORTLET);
+        checkImplementationType(reportlet, IdRepoImplementationType.REPORTLET);
         return reportlets.contains((JPAImplementation) reportlet) || reportlets.add((JPAImplementation) reportlet);
     }
 
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/AbstractCorrelationRuleEntity.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/AbstractCorrelationRuleEntity.java
index 93b457b..9604649 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/AbstractCorrelationRuleEntity.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/AbstractCorrelationRuleEntity.java
@@ -20,7 +20,6 @@ package org.apache.syncope.core.persistence.jpa.entity.policy;
 
 import javax.persistence.ManyToOne;
 import javax.persistence.MappedSuperclass;
-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.CorrelationRuleEntity;
@@ -55,7 +54,7 @@ abstract class AbstractCorrelationRuleEntity extends AbstractGeneratedKeyEntity
         return implementation;
     }
 
-    protected abstract ImplementationType getImplementationType();
+    protected abstract String getImplementationType();
 
     @Override
     public void setImplementation(final Implementation implementation) {
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAAccountPolicy.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAAccountPolicy.java
index 24b1a2e..af2cfb4 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAAccountPolicy.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAAccountPolicy.java
@@ -29,7 +29,7 @@ import javax.persistence.JoinTable;
 import javax.persistence.ManyToMany;
 import javax.persistence.Table;
 import javax.validation.constraints.NotNull;
-import org.apache.syncope.common.lib.types.ImplementationType;
+import org.apache.syncope.common.lib.types.IdRepoImplementationType;
 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;
@@ -90,7 +90,7 @@ public class JPAAccountPolicy extends AbstractPolicy implements AccountPolicy {
     @Override
     public boolean add(final Implementation rule) {
         checkType(rule, JPAImplementation.class);
-        checkImplementationType(rule, ImplementationType.ACCOUNT_RULE);
+        checkImplementationType(rule, IdRepoImplementationType.ACCOUNT_RULE);
         return rules.contains((JPAImplementation) rule) || rules.add((JPAImplementation) rule);
     }
 
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPasswordPolicy.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPasswordPolicy.java
index c3de4e2..aa1dc1a 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPasswordPolicy.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPasswordPolicy.java
@@ -27,7 +27,7 @@ import javax.persistence.JoinTable;
 import javax.persistence.ManyToMany;
 import javax.persistence.Table;
 import javax.validation.constraints.NotNull;
-import org.apache.syncope.common.lib.types.ImplementationType;
+import org.apache.syncope.common.lib.types.IdRepoImplementationType;
 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.jpa.entity.JPAImplementation;
@@ -76,7 +76,7 @@ public class JPAPasswordPolicy extends AbstractPolicy implements PasswordPolicy
     @Override
     public boolean add(final Implementation rule) {
         checkType(rule, JPAImplementation.class);
-        checkImplementationType(rule, ImplementationType.PASSWORD_RULE);
+        checkImplementationType(rule, IdRepoImplementationType.PASSWORD_RULE);
         return rules.contains((JPAImplementation) rule) || rules.add((JPAImplementation) rule);
     }
 
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPullCorrelationRuleEntity.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPullCorrelationRuleEntity.java
index 394ad08..b3135c1 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPullCorrelationRuleEntity.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPullCorrelationRuleEntity.java
@@ -22,7 +22,7 @@ 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.common.lib.types.IdMImplementationType;
 import org.apache.syncope.core.persistence.api.entity.policy.PullPolicy;
 import org.apache.syncope.core.persistence.api.entity.policy.PullCorrelationRuleEntity;
 
@@ -39,8 +39,8 @@ public class JPAPullCorrelationRuleEntity extends AbstractCorrelationRuleEntity
     private JPAPullPolicy pullPolicy;
 
     @Override
-    protected ImplementationType getImplementationType() {
-        return ImplementationType.PULL_CORRELATION_RULE;
+    protected String getImplementationType() {
+        return IdMImplementationType.PULL_CORRELATION_RULE;
     }
 
     @Override
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPushCorrelationRuleEntity.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPushCorrelationRuleEntity.java
index bdf05a7..aad1473 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPushCorrelationRuleEntity.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/policy/JPAPushCorrelationRuleEntity.java
@@ -22,7 +22,7 @@ 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.common.lib.types.IdMImplementationType;
 import org.apache.syncope.core.persistence.api.entity.policy.PushPolicy;
 import org.apache.syncope.core.persistence.api.entity.policy.PushCorrelationRuleEntity;
 
@@ -39,8 +39,8 @@ public class JPAPushCorrelationRuleEntity extends AbstractCorrelationRuleEntity
     private JPAPushPolicy pushPolicy;
 
     @Override
-    protected ImplementationType getImplementationType() {
-        return ImplementationType.PUSH_CORRELATION_RULE;
+    protected String getImplementationType() {
+        return IdMImplementationType.PUSH_CORRELATION_RULE;
     }
 
     @Override
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAExternalResource.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAExternalResource.java
index b44035e..054b7f1 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAExternalResource.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAExternalResource.java
@@ -45,7 +45,7 @@ import javax.validation.constraints.NotNull;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.types.ConnConfProperty;
 import org.apache.syncope.common.lib.types.ConnectorCapability;
-import org.apache.syncope.common.lib.types.ImplementationType;
+import org.apache.syncope.common.lib.types.IdMImplementationType;
 import org.apache.syncope.common.lib.types.TraceLevel;
 import org.apache.syncope.core.persistence.api.entity.policy.AccountPolicy;
 import org.apache.syncope.core.persistence.api.entity.ConnInstance;
@@ -361,7 +361,7 @@ public class JPAExternalResource extends AbstractProvidedKeyEntity implements Ex
     @Override
     public boolean add(final Implementation propagationAction) {
         checkType(propagationAction, JPAImplementation.class);
-        checkImplementationType(propagationAction, ImplementationType.PROPAGATION_ACTIONS);
+        checkImplementationType(propagationAction, IdMImplementationType.PROPAGATION_ACTIONS);
         return propagationActions.contains((JPAImplementation) propagationAction)
                 || propagationActions.add((JPAImplementation) propagationAction);
     }
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMappingItem.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMappingItem.java
index 1f55c8d..63d3292 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMappingItem.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAMappingItem.java
@@ -28,7 +28,7 @@ import javax.persistence.JoinTable;
 import javax.persistence.ManyToMany;
 import javax.persistence.ManyToOne;
 import javax.persistence.Table;
-import org.apache.syncope.common.lib.types.ImplementationType;
+import org.apache.syncope.common.lib.types.IdMImplementationType;
 import org.apache.syncope.core.persistence.api.entity.Implementation;
 import org.apache.syncope.core.persistence.api.entity.resource.Mapping;
 import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
@@ -68,7 +68,7 @@ public class JPAMappingItem extends AbstractItem implements MappingItem {
     @Override
     public boolean add(final Implementation transformer) {
         checkType(transformer, JPAImplementation.class);
-        checkImplementationType(transformer, ImplementationType.ITEM_TRANSFORMER);
+        checkImplementationType(transformer, IdMImplementationType.ITEM_TRANSFORMER);
         return transformers.contains((JPAImplementation) transformer)
                 || transformers.add((JPAImplementation) transformer);
     }
@@ -77,5 +77,4 @@ public class JPAMappingItem extends AbstractItem implements MappingItem {
     public List<? extends Implementation> getTransformers() {
         return transformers;
     }
-
 }
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAOrgUnitItem.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAOrgUnitItem.java
index 49b8cdd..bde929a 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAOrgUnitItem.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/resource/JPAOrgUnitItem.java
@@ -28,7 +28,7 @@ import javax.persistence.JoinTable;
 import javax.persistence.ManyToMany;
 import javax.persistence.ManyToOne;
 import javax.persistence.Table;
-import org.apache.syncope.common.lib.types.ImplementationType;
+import org.apache.syncope.common.lib.types.IdMImplementationType;
 import org.apache.syncope.core.persistence.api.entity.Implementation;
 import org.apache.syncope.core.persistence.api.entity.resource.OrgUnit;
 import org.apache.syncope.core.persistence.api.entity.resource.OrgUnitItem;
@@ -73,7 +73,7 @@ public class JPAOrgUnitItem extends AbstractItem implements OrgUnitItem {
     @Override
     public boolean add(final Implementation transformer) {
         checkType(transformer, JPAImplementation.class);
-        checkImplementationType(transformer, ImplementationType.ITEM_TRANSFORMER);
+        checkImplementationType(transformer, IdMImplementationType.ITEM_TRANSFORMER);
         return transformers.contains((JPAImplementation) transformer)
                 || transformers.add((JPAImplementation) transformer);
     }
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPullTask.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPullTask.java
index 3dc7ee6..df20f1a 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPullTask.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPullTask.java
@@ -34,7 +34,7 @@ import javax.persistence.ManyToOne;
 import javax.persistence.OneToMany;
 import javax.persistence.OneToOne;
 import javax.validation.constraints.NotNull;
-import org.apache.syncope.common.lib.types.ImplementationType;
+import org.apache.syncope.common.lib.types.IdMImplementationType;
 import org.apache.syncope.common.lib.types.PullMode;
 import org.apache.syncope.core.persistence.api.entity.AnyType;
 import org.apache.syncope.core.persistence.api.entity.Implementation;
@@ -92,7 +92,7 @@ public class JPAPullTask extends AbstractProvisioningTask implements PullTask {
     @Override
     public void setReconFilterBuilder(final Implementation reconFilterBuilder) {
         checkType(reconFilterBuilder, JPAImplementation.class);
-        checkImplementationType(reconFilterBuilder, ImplementationType.RECON_FILTER_BUILDER);
+        checkImplementationType(reconFilterBuilder, IdMImplementationType.RECON_FILTER_BUILDER);
         this.reconFilterBuilder = (JPAImplementation) reconFilterBuilder;
     }
 
@@ -110,7 +110,7 @@ public class JPAPullTask extends AbstractProvisioningTask implements PullTask {
     @Override
     public boolean add(final Implementation action) {
         checkType(action, JPAImplementation.class);
-        checkImplementationType(action, ImplementationType.PULL_ACTIONS);
+        checkImplementationType(action, IdMImplementationType.PULL_ACTIONS);
         return actions.contains((JPAImplementation) action) || actions.add((JPAImplementation) action);
     }
 
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPushTask.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPushTask.java
index abadd8c..45e7625 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPushTask.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPushTask.java
@@ -30,7 +30,7 @@ import javax.persistence.JoinTable;
 import javax.persistence.ManyToMany;
 import javax.persistence.ManyToOne;
 import javax.persistence.OneToMany;
-import org.apache.syncope.common.lib.types.ImplementationType;
+import org.apache.syncope.common.lib.types.IdMImplementationType;
 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.Realm;
@@ -73,7 +73,7 @@ public class JPAPushTask extends AbstractProvisioningTask implements PushTask {
     @Override
     public boolean add(final Implementation action) {
         checkType(action, JPAImplementation.class);
-        checkImplementationType(action, ImplementationType.PUSH_ACTIONS);
+        checkImplementationType(action, IdMImplementationType.PUSH_ACTIONS);
         return actions.contains((JPAImplementation) action) || actions.add((JPAImplementation) action);
     }
 
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPASchedTask.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPASchedTask.java
index 16b2bb7..e2c722f 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPASchedTask.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPASchedTask.java
@@ -25,7 +25,7 @@ import javax.persistence.OneToOne;
 import javax.persistence.Temporal;
 import javax.persistence.TemporalType;
 import javax.validation.constraints.NotNull;
-import org.apache.syncope.common.lib.types.ImplementationType;
+import org.apache.syncope.common.lib.types.IdRepoImplementationType;
 import org.apache.syncope.core.persistence.api.entity.Implementation;
 import org.apache.syncope.core.persistence.api.entity.task.SchedTask;
 import org.apache.syncope.core.persistence.jpa.entity.JPAImplementation;
@@ -89,7 +89,7 @@ public class JPASchedTask extends AbstractTask implements SchedTask {
     @Override
     public void setJobDelegate(final Implementation jobDelegate) {
         checkType(jobDelegate, JPAImplementation.class);
-        checkImplementationType(jobDelegate, ImplementationType.TASKJOB_DELEGATE);
+        checkImplementationType(jobDelegate, IdRepoImplementationType.TASKJOB_DELEGATE);
         this.jobDelegate = (JPAImplementation) jobDelegate;
     }
 
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/DummyImplementationLookup.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/DummyImplementationLookup.java
index c80c33c..f449237 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/DummyImplementationLookup.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/DummyImplementationLookup.java
@@ -25,7 +25,6 @@ import org.apache.syncope.common.lib.policy.PasswordRuleConf;
 import org.apache.syncope.common.lib.policy.PullCorrelationRuleConf;
 import org.apache.syncope.common.lib.policy.PushCorrelationRuleConf;
 import org.apache.syncope.common.lib.report.ReportletConf;
-import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.core.persistence.api.ImplementationLookup;
 import org.apache.syncope.core.persistence.api.dao.AccountRule;
 import org.apache.syncope.core.persistence.api.dao.PasswordRule;
@@ -47,7 +46,7 @@ public class DummyImplementationLookup implements ImplementationLookup {
     }
 
     @Override
-    public Set<String> getClassNames(final ImplementationType type) {
+    public Set<String> getClassNames(final String type) {
         return Collections.emptySet();
     }
 
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 2f29e17..21297d0 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
@@ -23,8 +23,9 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 
 import java.util.List;
+import org.apache.syncope.common.lib.types.IdMImplementationType;
+import org.apache.syncope.common.lib.types.IdRepoImplementationType;
 import org.apache.syncope.common.lib.types.ImplementationEngine;
-import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.core.persistence.api.dao.ImplementationDAO;
 import org.apache.syncope.core.persistence.api.entity.Implementation;
 import org.apache.syncope.core.persistence.jpa.AbstractTest;
@@ -45,31 +46,31 @@ public class ImplementationTest extends AbstractTest {
 
         assertEquals(18, implementations.size());
 
-        implementations = implementationDAO.find(ImplementationType.PULL_ACTIONS);
+        implementations = implementationDAO.findByType(IdMImplementationType.PULL_ACTIONS);
         assertEquals(1, implementations.size());
 
-        implementations = implementationDAO.find(ImplementationType.PROPAGATION_ACTIONS);
+        implementations = implementationDAO.findByType(IdMImplementationType.PROPAGATION_ACTIONS);
         assertEquals(1, implementations.size());
 
-        implementations = implementationDAO.find(ImplementationType.TASKJOB_DELEGATE);
+        implementations = implementationDAO.findByType(IdRepoImplementationType.TASKJOB_DELEGATE);
         assertEquals(5, implementations.size());
 
-        implementations = implementationDAO.find(ImplementationType.REPORTLET);
+        implementations = implementationDAO.findByType(IdRepoImplementationType.REPORTLET);
         assertEquals(2, implementations.size());
 
-        implementations = implementationDAO.find(ImplementationType.ACCOUNT_RULE);
+        implementations = implementationDAO.findByType(IdRepoImplementationType.ACCOUNT_RULE);
         assertEquals(2, implementations.size());
 
-        implementations = implementationDAO.find(ImplementationType.PASSWORD_RULE);
+        implementations = implementationDAO.findByType(IdRepoImplementationType.PASSWORD_RULE);
         assertEquals(3, implementations.size());
 
-        implementations = implementationDAO.find(ImplementationType.VALIDATOR);
+        implementations = implementationDAO.findByType(IdRepoImplementationType.VALIDATOR);
         assertEquals(2, implementations.size());
 
-        implementations = implementationDAO.find(ImplementationType.PULL_CORRELATION_RULE);
+        implementations = implementationDAO.findByType(IdMImplementationType.PULL_CORRELATION_RULE);
         assertEquals(1, implementations.size());
 
-        implementations = implementationDAO.find(ImplementationType.PUSH_CORRELATION_RULE);
+        implementations = implementationDAO.findByType(IdMImplementationType.PUSH_CORRELATION_RULE);
         assertEquals(1, implementations.size());
     }
 
@@ -78,7 +79,7 @@ public class ImplementationTest extends AbstractTest {
         Implementation impl = entityFactory.newEntity(Implementation.class);
         impl.setKey("new");
         impl.setEngine(ImplementationEngine.GROOVY);
-        impl.setType(ImplementationType.VALIDATOR);
+        impl.setType(IdRepoImplementationType.VALIDATOR);
         impl.setBody("");
 
         Implementation actual = implementationDAO.save(impl);
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 6a6b16c..0b2ed8f 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
@@ -30,8 +30,9 @@ import org.apache.syncope.common.lib.policy.DefaultPasswordRuleConf;
 import org.apache.syncope.common.lib.policy.DefaultPullCorrelationRuleConf;
 import org.apache.syncope.common.lib.policy.DefaultPushCorrelationRuleConf;
 import org.apache.syncope.common.lib.types.ConflictResolutionAction;
+import org.apache.syncope.common.lib.types.IdMImplementationType;
+import org.apache.syncope.common.lib.types.IdRepoImplementationType;
 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;
 import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
 import org.apache.syncope.core.persistence.api.dao.ImplementationDAO;
@@ -113,7 +114,7 @@ public class PolicyTest extends AbstractTest {
         Implementation impl1 = entityFactory.newEntity(Implementation.class);
         impl1.setKey(pullURuleName);
         impl1.setEngine(ImplementationEngine.JAVA);
-        impl1.setType(ImplementationType.PULL_CORRELATION_RULE);
+        impl1.setType(IdMImplementationType.PULL_CORRELATION_RULE);
         impl1.setBody(PullCorrelationRule.class.getName());
         impl1 = implementationDAO.save(impl1);
 
@@ -126,7 +127,7 @@ public class PolicyTest extends AbstractTest {
         Implementation impl2 = entityFactory.newEntity(Implementation.class);
         impl2.setKey(pullGRuleName);
         impl2.setEngine(ImplementationEngine.JAVA);
-        impl2.setType(ImplementationType.PULL_CORRELATION_RULE);
+        impl2.setType(IdMImplementationType.PULL_CORRELATION_RULE);
         impl2.setBody(PullCorrelationRule.class.getName());
         impl2 = implementationDAO.save(impl2);
 
@@ -158,7 +159,7 @@ public class PolicyTest extends AbstractTest {
         Implementation rule = entityFactory.newEntity(Implementation.class);
         rule.setKey("PasswordRule" + UUID.randomUUID().toString());
         rule.setEngine(ImplementationEngine.JAVA);
-        rule.setType(ImplementationType.PASSWORD_RULE);
+        rule.setType(IdRepoImplementationType.PASSWORD_RULE);
         rule.setBody(POJOHelper.serialize(ruleConf));
         rule = implementationDAO.save(rule);
 
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ReportTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ReportTest.java
index e35b0bf..204e6bf 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ReportTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/inner/ReportTest.java
@@ -25,8 +25,8 @@ import static org.junit.jupiter.api.Assertions.assertNull;
 import java.util.List;
 import java.util.UUID;
 import org.apache.syncope.common.lib.report.UserReportletConf;
+import org.apache.syncope.common.lib.types.IdRepoImplementationType;
 import org.apache.syncope.common.lib.types.ImplementationEngine;
-import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.core.persistence.api.dao.ImplementationDAO;
 import org.apache.syncope.core.persistence.api.dao.ReportDAO;
 import org.apache.syncope.core.persistence.api.dao.ReportTemplateDAO;
@@ -71,14 +71,14 @@ public class ReportTest extends AbstractTest {
         Implementation reportlet1 = entityFactory.newEntity(Implementation.class);
         reportlet1.setKey("UserReportlet" + UUID.randomUUID().toString());
         reportlet1.setEngine(ImplementationEngine.JAVA);
-        reportlet1.setType(ImplementationType.REPORTLET);
+        reportlet1.setType(IdRepoImplementationType.REPORTLET);
         reportlet1.setBody(POJOHelper.serialize(new UserReportletConf("first")));
         reportlet1 = implementationDAO.save(reportlet1);
 
         Implementation reportlet2 = entityFactory.newEntity(Implementation.class);
         reportlet2.setKey("UserReportlet" + UUID.randomUUID().toString());
         reportlet2.setEngine(ImplementationEngine.JAVA);
-        reportlet2.setType(ImplementationType.REPORTLET);
+        reportlet2.setType(IdRepoImplementationType.REPORTLET);
         reportlet2.setBody(POJOHelper.serialize(new UserReportletConf("second")));
         reportlet2 = implementationDAO.save(reportlet2);
 
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 6785746..beabab3 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
@@ -34,9 +34,9 @@ import java.util.UUID;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.ImplementationEngine;
-import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.common.lib.types.MatchingRule;
 import org.apache.syncope.common.lib.types.ExecStatus;
+import org.apache.syncope.common.lib.types.IdMImplementationType;
 import org.apache.syncope.common.lib.types.ResourceOperation;
 import org.apache.syncope.common.lib.types.PullMode;
 import org.apache.syncope.common.lib.types.TaskType;
@@ -276,7 +276,7 @@ public class TaskTest extends AbstractTest {
         Implementation pullActions = entityFactory.newEntity(Implementation.class);
         pullActions.setKey("PullActions" + UUID.randomUUID().toString());
         pullActions.setEngine(ImplementationEngine.JAVA);
-        pullActions.setType(ImplementationType.PULL_ACTIONS);
+        pullActions.setType(IdMImplementationType.PULL_ACTIONS);
         pullActions.setBody(PullActions.class.getName());
         pullActions = implementationDAO.save(pullActions);
 
@@ -298,7 +298,7 @@ public class TaskTest extends AbstractTest {
         Implementation pullActions = entityFactory.newEntity(Implementation.class);
         pullActions.setKey("syncope144");
         pullActions.setEngine(ImplementationEngine.JAVA);
-        pullActions.setType(ImplementationType.PULL_ACTIONS);
+        pullActions.setType(IdMImplementationType.PULL_ACTIONS);
         pullActions.setBody(PullActions.class.getName());
         pullActions = implementationDAO.save(pullActions);
 
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyTypeDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyTypeDataBinderImpl.java
index 974088c..3fa5f1b 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyTypeDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyTypeDataBinderImpl.java
@@ -36,7 +36,7 @@ import org.apache.syncope.core.persistence.api.entity.AccessToken;
 import org.apache.syncope.core.persistence.api.entity.EntityFactory;
 import org.apache.syncope.core.persistence.api.entity.AnyType;
 import org.apache.syncope.core.persistence.api.entity.AnyTypeClass;
-import org.apache.syncope.core.provisioning.api.EntitlementsHolder;
+import org.apache.syncope.common.lib.types.EntitlementsHolder;
 import org.apache.syncope.core.provisioning.api.data.AnyTypeDataBinder;
 import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
 import org.apache.syncope.core.spring.security.AuthContextUtils;
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ImplementationDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ImplementationDataBinderImpl.java
index 1346a91..1b530a3 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ImplementationDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ImplementationDataBinderImpl.java
@@ -25,8 +25,9 @@ import org.apache.syncope.common.lib.policy.RuleConf;
 import org.apache.syncope.common.lib.report.ReportletConf;
 import org.apache.syncope.common.lib.to.ImplementationTO;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.common.lib.types.IdMImplementationType;
+import org.apache.syncope.common.lib.types.IdRepoImplementationType;
 import org.apache.syncope.common.lib.types.ImplementationEngine;
-import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.core.persistence.api.attrvalue.validation.Validator;
 import org.apache.syncope.core.persistence.api.dao.AccountRule;
 import org.apache.syncope.core.persistence.api.dao.PasswordRule;
@@ -69,7 +70,7 @@ public class ImplementationDataBinderImpl implements ImplementationDataBinder {
     public void update(final Implementation implementation, final ImplementationTO implementationTO) {
         SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidImplementation);
 
-        if (implementation.getType() != null && implementation.getType() != implementationTO.getType()) {
+        if (implementation.getType() != null && !implementation.getType().equals(implementationTO.getType())) {
             sce.getElements().add("ImplementationType cannot be changed");
             throw sce;
         }
@@ -87,59 +88,59 @@ public class ImplementationDataBinderImpl implements ImplementationDataBinder {
         if (implementation.getEngine() == ImplementationEngine.JAVA) {
             Class<?> base = null;
             switch (implementation.getType()) {
-                case REPORTLET:
+                case IdRepoImplementationType.REPORTLET:
                     base = Reportlet.class;
                     break;
 
-                case ACCOUNT_RULE:
+                case IdRepoImplementationType.ACCOUNT_RULE:
                     base = AccountRule.class;
                     break;
 
-                case PASSWORD_RULE:
+                case IdRepoImplementationType.PASSWORD_RULE:
                     base = PasswordRule.class;
                     break;
 
-                case ITEM_TRANSFORMER:
+                case IdMImplementationType.ITEM_TRANSFORMER:
                     base = ItemTransformer.class;
                     break;
 
-                case TASKJOB_DELEGATE:
+                case IdRepoImplementationType.TASKJOB_DELEGATE:
                     base = SchedTaskJobDelegate.class;
                     break;
 
-                case RECON_FILTER_BUILDER:
+                case IdMImplementationType.RECON_FILTER_BUILDER:
                     base = ReconFilterBuilder.class;
                     break;
 
-                case LOGIC_ACTIONS:
+                case IdRepoImplementationType.LOGIC_ACTIONS:
                     base = LogicActions.class;
                     break;
 
-                case PROPAGATION_ACTIONS:
+                case IdMImplementationType.PROPAGATION_ACTIONS:
                     base = PropagationActions.class;
                     break;
 
-                case PULL_ACTIONS:
+                case IdMImplementationType.PULL_ACTIONS:
                     base = PullActions.class;
                     break;
 
-                case PUSH_ACTIONS:
+                case IdMImplementationType.PUSH_ACTIONS:
                     base = PushActions.class;
                     break;
 
-                case PULL_CORRELATION_RULE:
+                case IdMImplementationType.PULL_CORRELATION_RULE:
                     base = PullCorrelationRule.class;
                     break;
 
-                case PUSH_CORRELATION_RULE:
+                case IdMImplementationType.PUSH_CORRELATION_RULE:
                     base = PushCorrelationRule.class;
                     break;
 
-                case VALIDATOR:
+                case IdRepoImplementationType.VALIDATOR:
                     base = Validator.class;
                     break;
 
-                case RECIPIENTS_PROVIDER:
+                case IdRepoImplementationType.RECIPIENTS_PROVIDER:
                     base = RecipientsProvider.class;
                     break;
 
@@ -151,41 +152,46 @@ public class ImplementationDataBinderImpl implements ImplementationDataBinder {
                 throw sce;
             }
 
-            if (implementation.getType() == ImplementationType.REPORTLET) {
-                ReportletConf reportlet = POJOHelper.deserialize(implementation.getBody(), ReportletConf.class);
-                if (reportlet == null) {
-                    sce.getElements().add("Could not deserialize as ReportletConf");
-                    throw sce;
-                }
-            } else if (implementation.getType() == ImplementationType.ACCOUNT_RULE
-                    || implementation.getType() == ImplementationType.PASSWORD_RULE
-                    || implementation.getType() == ImplementationType.PULL_CORRELATION_RULE
-                    || implementation.getType() == ImplementationType.PUSH_CORRELATION_RULE) {
-
-                RuleConf rule = POJOHelper.deserialize(implementation.getBody(), RuleConf.class);
-                if (rule == null) {
-                    sce.getElements().add("Could not deserialize as neither "
-                            + "Account, Password, Pull nor Push Correlation RuleConf");
-                    throw sce;
-                }
-            } else {
-                Class<?> clazz = null;
-                try {
-                    clazz = Class.forName(implementation.getBody());
-                } catch (Exception e) {
-                    LOG.error("Class '{}' not found", implementation.getBody(), e);
-                    sce.getElements().add("No Java class found: " + implementation.getBody());
-                    throw sce;
-                }
-                if (!base.isAssignableFrom(clazz)) {
-                    sce.getElements().add(
-                            "Java class " + implementation.getBody() + " must comply with " + base.getName());
-                    throw sce;
-                }
-                if (Modifier.isAbstract(clazz.getModifiers())) {
-                    sce.getElements().add("Java class " + implementation.getBody() + " is abstract");
-                    throw sce;
-                }
+            switch (implementation.getType()) {
+                case IdRepoImplementationType.REPORTLET:
+                    ReportletConf reportlet = POJOHelper.deserialize(implementation.getBody(), ReportletConf.class);
+                    if (reportlet == null) {
+                        sce.getElements().add("Could not deserialize as ReportletConf");
+                        throw sce;
+                    }
+                    break;
+
+                case IdRepoImplementationType.ACCOUNT_RULE:
+                case IdRepoImplementationType.PASSWORD_RULE:
+                case IdMImplementationType.PULL_CORRELATION_RULE:
+                case IdMImplementationType.PUSH_CORRELATION_RULE:
+                    RuleConf rule = POJOHelper.deserialize(implementation.getBody(), RuleConf.class);
+                    if (rule == null) {
+                        sce.getElements().add("Could not deserialize as neither "
+                                + "Account, Password, Pull nor Push Correlation RuleConf");
+                        throw sce;
+                    }
+                    break;
+
+                default:
+                    Class<?> clazz = null;
+                    try {
+                        clazz = Class.forName(implementation.getBody());
+                    } catch (Exception e) {
+                        LOG.error("Class '{}' not found", implementation.getBody(), e);
+                        sce.getElements().add("No Java class found: " + implementation.getBody());
+                        throw sce;
+                    }
+                    if (!base.isAssignableFrom(clazz)) {
+                        sce.getElements().add(
+                                "Java class " + implementation.getBody() + " must comply with " + base.getName());
+                        throw sce;
+                    }
+                    if (Modifier.isAbstract(clazz.getModifiers())) {
+                        sce.getElements().add("Java class " + implementation.getBody() + " is abstract");
+                        throw sce;
+                    }
+                    break;
             }
         }
     }
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/TaskDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/TaskDataBinderImpl.java
index aae4c62..7f02963 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/TaskDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/TaskDataBinderImpl.java
@@ -32,8 +32,8 @@ import org.apache.syncope.common.lib.to.PullTaskTO;
 import org.apache.syncope.common.lib.to.ExecTO;
 import org.apache.syncope.common.lib.to.NotificationTaskTO;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.common.lib.types.IdRepoImplementationType;
 import org.apache.syncope.common.lib.types.ImplementationEngine;
-import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.common.lib.types.JobType;
 import org.apache.syncope.common.lib.types.MatchingRule;
 import org.apache.syncope.common.lib.types.TaskType;
@@ -113,7 +113,7 @@ public class TaskDataBinderImpl implements TaskDataBinder {
             PushTaskTO pushTaskTO = (PushTaskTO) provisioningTaskTO;
 
             Implementation jobDelegate = pushTaskTO.getJobDelegate() == null
-                    ? implementationDAO.find(ImplementationType.TASKJOB_DELEGATE).stream().
+                    ? implementationDAO.findByType(IdRepoImplementationType.TASKJOB_DELEGATE).stream().
                             filter(impl -> PushJobDelegate.class.getName().equals(impl.getBody())).
                             findFirst().orElse(null)
                     : implementationDAO.find(pushTaskTO.getJobDelegate());
@@ -121,7 +121,7 @@ public class TaskDataBinderImpl implements TaskDataBinder {
                 jobDelegate = entityFactory.newEntity(Implementation.class);
                 jobDelegate.setKey(PushJobDelegate.class.getSimpleName());
                 jobDelegate.setEngine(ImplementationEngine.JAVA);
-                jobDelegate.setType(ImplementationType.TASKJOB_DELEGATE);
+                jobDelegate.setType(IdRepoImplementationType.TASKJOB_DELEGATE);
                 jobDelegate.setBody(PushJobDelegate.class.getName());
                 jobDelegate = implementationDAO.save(jobDelegate);
             }
@@ -157,7 +157,7 @@ public class TaskDataBinderImpl implements TaskDataBinder {
             PullTaskTO pullTaskTO = (PullTaskTO) provisioningTaskTO;
 
             Implementation jobDelegate = pullTaskTO.getJobDelegate() == null
-                    ? implementationDAO.find(ImplementationType.TASKJOB_DELEGATE).stream().
+                    ? implementationDAO.findByType(IdRepoImplementationType.TASKJOB_DELEGATE).stream().
                             filter(impl -> PullJobDelegate.class.getName().equals(impl.getBody())).
                             findFirst().orElse(null)
                     : implementationDAO.find(pullTaskTO.getJobDelegate());
@@ -165,7 +165,7 @@ public class TaskDataBinderImpl implements TaskDataBinder {
                 jobDelegate = entityFactory.newEntity(Implementation.class);
                 jobDelegate.setKey(PullJobDelegate.class.getSimpleName());
                 jobDelegate.setEngine(ImplementationEngine.JAVA);
-                jobDelegate.setType(ImplementationType.TASKJOB_DELEGATE);
+                jobDelegate.setType(IdRepoImplementationType.TASKJOB_DELEGATE);
                 jobDelegate.setBody(PullJobDelegate.class.getName());
                 jobDelegate = implementationDAO.save(jobDelegate);
             }
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/JobManagerImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/JobManagerImpl.java
index 2a38f1e..8d9fc73 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/JobManagerImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/job/JobManagerImpl.java
@@ -34,7 +34,7 @@ import javax.sql.DataSource;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.syncope.common.lib.SyncopeConstants;
-import org.apache.syncope.common.lib.types.ImplementationType;
+import org.apache.syncope.common.lib.types.IdRepoImplementationType;
 import org.apache.syncope.common.lib.types.TaskType;
 import org.apache.syncope.core.persistence.api.dao.ConfDAO;
 import org.apache.syncope.core.persistence.api.dao.NotFoundException;
@@ -227,11 +227,11 @@ public class JobManagerImpl implements JobManager, SyncopeCoreLoader {
 
         Implementation jobDelegate = task.getJobDelegate() == null
                 ? task instanceof PullTask
-                        ? implementationDAO.find(ImplementationType.TASKJOB_DELEGATE).stream().
+                        ? implementationDAO.findByType(IdRepoImplementationType.TASKJOB_DELEGATE).stream().
                                 filter(impl -> PullJobDelegate.class.getName().equals(impl.getBody())).
                                 findFirst().orElse(null)
                         : task instanceof PushTask
-                                ? implementationDAO.find(ImplementationType.TASKJOB_DELEGATE).stream().
+                                ? implementationDAO.findByType(IdRepoImplementationType.TASKJOB_DELEGATE).stream().
                                         filter(impl -> PushJobDelegate.class.getName().equals(impl.getBody())).
                                         findFirst().orElse(null)
                                 : null
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/SinglePullJobDelegate.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/SinglePullJobDelegate.java
index f67f750..0a8e029 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/SinglePullJobDelegate.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/SinglePullJobDelegate.java
@@ -28,7 +28,7 @@ import org.apache.syncope.common.lib.collections.IteratorChain;
 import org.apache.syncope.common.lib.to.PullTaskTO;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
 import org.apache.syncope.common.lib.types.ConflictResolutionAction;
-import org.apache.syncope.common.lib.types.ImplementationType;
+import org.apache.syncope.common.lib.types.IdMImplementationType;
 import org.apache.syncope.common.lib.types.MatchingRule;
 import org.apache.syncope.common.lib.types.PullMode;
 import org.apache.syncope.common.lib.types.UnmatchingRule;
@@ -82,7 +82,7 @@ public class SinglePullJobDelegate extends PullJobDelegate implements SyncopeSin
         List<PullActions> actions = new ArrayList<>();
         pullTaskTO.getActions().forEach(key -> {
             Implementation impl = implementationDAO.find(key);
-            if (impl == null || impl.getType() != ImplementationType.PULL_ACTIONS) {
+            if (impl == null || !IdMImplementationType.PULL_ACTIONS.equals(impl.getType())) {
                 LOG.debug("Invalid " + Implementation.class.getSimpleName() + " {}, ignoring...", key);
             } else {
                 try {
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/SinglePushJobDelegate.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/SinglePushJobDelegate.java
index 08ff9c7..2911fd8 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/SinglePushJobDelegate.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/SinglePushJobDelegate.java
@@ -23,7 +23,7 @@ import java.util.Arrays;
 import java.util.List;
 import org.apache.syncope.common.lib.to.PushTaskTO;
 import org.apache.syncope.common.lib.types.ConflictResolutionAction;
-import org.apache.syncope.common.lib.types.ImplementationType;
+import org.apache.syncope.common.lib.types.IdMImplementationType;
 import org.apache.syncope.common.lib.types.MatchingRule;
 import org.apache.syncope.common.lib.types.UnmatchingRule;
 import org.apache.syncope.core.persistence.api.dao.ImplementationDAO;
@@ -60,7 +60,7 @@ public class SinglePushJobDelegate extends PushJobDelegate implements SyncopeSin
         List<PushActions> actions = new ArrayList<>();
         pushTaskTO.getActions().forEach(key -> {
             Implementation impl = implementationDAO.find(key);
-            if (impl == null || impl.getType() != ImplementationType.PUSH_ACTIONS) {
+            if (impl == null || !IdMImplementationType.PUSH_ACTIONS.equals(impl.getType())) {
                 LOG.debug("Invalid " + Implementation.class.getSimpleName() + " {}, ignoring...", key);
             } else {
                 try {
diff --git a/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/DummyImplementationLookup.java b/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/DummyImplementationLookup.java
index 91fce4d..821b30e 100644
--- a/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/DummyImplementationLookup.java
+++ b/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/DummyImplementationLookup.java
@@ -25,7 +25,6 @@ import org.apache.syncope.common.lib.policy.PasswordRuleConf;
 import org.apache.syncope.common.lib.policy.PullCorrelationRuleConf;
 import org.apache.syncope.common.lib.policy.PushCorrelationRuleConf;
 import org.apache.syncope.common.lib.report.ReportletConf;
-import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.core.persistence.api.ImplementationLookup;
 import org.apache.syncope.core.persistence.api.dao.AccountRule;
 import org.apache.syncope.core.persistence.api.dao.PasswordRule;
@@ -47,7 +46,7 @@ public class DummyImplementationLookup implements ImplementationLookup {
     }
 
     @Override
-    public Set<String> getClassNames(final ImplementationType type) {
+    public Set<String> getClassNames(final String type) {
         return Collections.emptySet();
     }
 
diff --git a/core/spring/src/main/java/org/apache/syncope/core/spring/security/AuthContextUtils.java b/core/spring/src/main/java/org/apache/syncope/core/spring/security/AuthContextUtils.java
index ee99056..f505d09 100644
--- a/core/spring/src/main/java/org/apache/syncope/core/spring/security/AuthContextUtils.java
+++ b/core/spring/src/main/java/org/apache/syncope/core/spring/security/AuthContextUtils.java
@@ -18,6 +18,7 @@
  */
 package org.apache.syncope.core.spring.security;
 
+import org.apache.syncope.common.lib.types.EntitlementsHolder;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
@@ -25,7 +26,6 @@ import java.util.Set;
 import java.util.stream.Collectors;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.SyncopeConstants;
-import org.apache.syncope.core.provisioning.api.EntitlementsHolder;
 import org.apache.syncope.core.spring.ApplicationContextProvider;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
diff --git a/core/spring/src/main/java/org/apache/syncope/core/spring/security/AuthDataAccessor.java b/core/spring/src/main/java/org/apache/syncope/core/spring/security/AuthDataAccessor.java
index e7b90d6..4487f08 100644
--- a/core/spring/src/main/java/org/apache/syncope/core/spring/security/AuthDataAccessor.java
+++ b/core/spring/src/main/java/org/apache/syncope/core/spring/security/AuthDataAccessor.java
@@ -18,6 +18,7 @@
  */
 package org.apache.syncope.core.spring.security;
 
+import org.apache.syncope.common.lib.types.EntitlementsHolder;
 import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
@@ -56,7 +57,6 @@ import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 import org.apache.syncope.core.persistence.api.entity.user.User;
 import org.apache.syncope.core.provisioning.api.AuditManager;
 import org.apache.syncope.core.provisioning.api.ConnectorFactory;
-import org.apache.syncope.core.provisioning.api.EntitlementsHolder;
 import org.apache.syncope.core.provisioning.api.MappingManager;
 import org.apache.syncope.core.spring.ApplicationContextProvider;
 import org.identityconnectors.framework.common.objects.Uid;
diff --git a/core/spring/src/test/java/org/apache/syncope/core/spring/security/DummyImplementationLookup.java b/core/spring/src/test/java/org/apache/syncope/core/spring/security/DummyImplementationLookup.java
index 502067c..6c7061b 100644
--- a/core/spring/src/test/java/org/apache/syncope/core/spring/security/DummyImplementationLookup.java
+++ b/core/spring/src/test/java/org/apache/syncope/core/spring/security/DummyImplementationLookup.java
@@ -25,7 +25,6 @@ import org.apache.syncope.common.lib.policy.PasswordRuleConf;
 import org.apache.syncope.common.lib.policy.PullCorrelationRuleConf;
 import org.apache.syncope.common.lib.policy.PushCorrelationRuleConf;
 import org.apache.syncope.common.lib.report.ReportletConf;
-import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.core.persistence.api.ImplementationLookup;
 import org.apache.syncope.core.persistence.api.dao.AccountRule;
 import org.apache.syncope.core.persistence.api.dao.PasswordRule;
@@ -41,7 +40,7 @@ public class DummyImplementationLookup implements ImplementationLookup {
     }
 
     @Override
-    public Set<String> getClassNames(final ImplementationType type) {
+    public Set<String> getClassNames(final String type) {
         return Collections.emptySet();
     }
 
diff --git a/core/spring/src/test/java/org/apache/syncope/core/spring/security/TestImplementation.java b/core/spring/src/test/java/org/apache/syncope/core/spring/security/TestImplementation.java
index 96479ce..5b4db33 100644
--- a/core/spring/src/test/java/org/apache/syncope/core/spring/security/TestImplementation.java
+++ b/core/spring/src/test/java/org/apache/syncope/core/spring/security/TestImplementation.java
@@ -18,8 +18,8 @@
  */
 package org.apache.syncope.core.spring.security;
 
+import org.apache.syncope.common.lib.types.IdRepoImplementationType;
 import org.apache.syncope.common.lib.types.ImplementationEngine;
-import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.core.persistence.api.entity.Implementation;
 
 public class TestImplementation implements Implementation {
@@ -49,12 +49,12 @@ public class TestImplementation implements Implementation {
     }
 
     @Override
-    public ImplementationType getType() {
-        return ImplementationType.PASSWORD_RULE;
+    public String getType() {
+        return IdRepoImplementationType.PASSWORD_RULE;
     }
 
     @Override
-    public void setType(ImplementationType type) {
+    public void setType(String type) {
         // nothing to do
     }
 
diff --git a/ext/camel/logic/src/main/java/org/apache/syncope/core/logic/init/CamelRouteLoader.java b/ext/camel/logic/src/main/java/org/apache/syncope/core/logic/init/CamelRouteLoader.java
index f9c7020..baaad37 100644
--- a/ext/camel/logic/src/main/java/org/apache/syncope/core/logic/init/CamelRouteLoader.java
+++ b/ext/camel/logic/src/main/java/org/apache/syncope/core/logic/init/CamelRouteLoader.java
@@ -31,7 +31,7 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.cxf.staxutils.StaxUtils;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.CamelEntitlement;
-import org.apache.syncope.core.provisioning.api.EntitlementsHolder;
+import org.apache.syncope.common.lib.types.EntitlementsHolder;
 import org.apache.syncope.core.spring.ResourceWithFallbackLoader;
 import org.apache.syncope.core.persistence.api.SyncopeCoreLoader;
 import org.apache.syncope.core.persistence.api.entity.CamelRoute;
@@ -89,7 +89,7 @@ public class CamelRouteLoader implements SyncopeCoreLoader {
 
     @Override
     public void load() {
-        EntitlementsHolder.getInstance().init(CamelEntitlement.values());
+        EntitlementsHolder.getInstance().addAll(CamelEntitlement.values());
     }
 
     @Override
diff --git a/ext/flowable/logic/src/main/java/org/apache/syncope/core/logic/init/FlowableLoader.java b/ext/flowable/logic/src/main/java/org/apache/syncope/core/logic/init/FlowableLoader.java
index c8dee7a..333c91d 100644
--- a/ext/flowable/logic/src/main/java/org/apache/syncope/core/logic/init/FlowableLoader.java
+++ b/ext/flowable/logic/src/main/java/org/apache/syncope/core/logic/init/FlowableLoader.java
@@ -25,12 +25,12 @@ import java.util.List;
 import javax.annotation.Resource;
 import javax.sql.DataSource;
 import org.apache.commons.io.IOUtils;
+import org.apache.syncope.common.lib.types.EntitlementsHolder;
 import org.apache.syncope.common.lib.types.FlowableEntitlement;
 import org.apache.syncope.core.flowable.impl.FlowableDeployUtils;
 import org.apache.syncope.core.flowable.impl.FlowableRuntimeUtils;
 import org.apache.syncope.core.flowable.support.DomainProcessEngine;
 import org.apache.syncope.core.persistence.api.SyncopeCoreLoader;
-import org.apache.syncope.core.provisioning.api.EntitlementsHolder;
 import org.apache.syncope.core.spring.ResourceWithFallbackLoader;
 import org.flowable.engine.ProcessEngine;
 import org.flowable.engine.impl.db.DbIdGenerator;
@@ -58,7 +58,7 @@ public class FlowableLoader implements SyncopeCoreLoader {
 
     @Override
     public void load() {
-        EntitlementsHolder.getInstance().init(FlowableEntitlement.values());
+        EntitlementsHolder.getInstance().addAll(FlowableEntitlement.values());
     }
 
     @Override
diff --git a/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/init/OIDCClientLoader.java b/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/init/OIDCClientLoader.java
index 847905f..53a0386 100644
--- a/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/init/OIDCClientLoader.java
+++ b/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/init/OIDCClientLoader.java
@@ -18,9 +18,9 @@
  */
 package org.apache.syncope.core.logic.init;
 
+import org.apache.syncope.common.lib.types.EntitlementsHolder;
 import org.apache.syncope.common.lib.types.OIDCClientEntitlement;
 import org.apache.syncope.core.persistence.api.SyncopeCoreLoader;
-import org.apache.syncope.core.provisioning.api.EntitlementsHolder;
 import org.springframework.stereotype.Component;
 
 @Component
@@ -33,6 +33,6 @@ public class OIDCClientLoader implements SyncopeCoreLoader {
 
     @Override
     public void load() {
-        EntitlementsHolder.getInstance().init(OIDCClientEntitlement.values());
+        EntitlementsHolder.getInstance().addAll(OIDCClientEntitlement.values());
     }
 }
diff --git a/ext/oidcclient/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAOIDCProviderItem.java b/ext/oidcclient/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAOIDCProviderItem.java
index 69268cb..b0c397f 100644
--- a/ext/oidcclient/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAOIDCProviderItem.java
+++ b/ext/oidcclient/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPAOIDCProviderItem.java
@@ -28,7 +28,7 @@ import javax.persistence.JoinTable;
 import javax.persistence.ManyToMany;
 import javax.persistence.ManyToOne;
 import javax.persistence.Table;
-import org.apache.syncope.common.lib.types.ImplementationType;
+import org.apache.syncope.common.lib.types.IdMImplementationType;
 import org.apache.syncope.core.persistence.api.entity.Implementation;
 import org.apache.syncope.core.persistence.api.entity.OIDCProvider;
 import org.apache.syncope.core.persistence.api.entity.OIDCProviderItem;
@@ -68,7 +68,7 @@ public class JPAOIDCProviderItem extends AbstractItem implements OIDCProviderIte
     @Override
     public boolean add(final Implementation transformer) {
         checkType(transformer, JPAImplementation.class);
-        checkImplementationType(transformer, ImplementationType.ITEM_TRANSFORMER);
+        checkImplementationType(transformer, IdMImplementationType.ITEM_TRANSFORMER);
         return this.transformers.add((JPAImplementation) transformer);
     }
 
diff --git a/ext/saml2sp/logic/src/main/java/org/apache/syncope/core/logic/init/SAML2SPLoader.java b/ext/saml2sp/logic/src/main/java/org/apache/syncope/core/logic/init/SAML2SPLoader.java
index a63b2ca..5e5030e 100644
--- a/ext/saml2sp/logic/src/main/java/org/apache/syncope/core/logic/init/SAML2SPLoader.java
+++ b/ext/saml2sp/logic/src/main/java/org/apache/syncope/core/logic/init/SAML2SPLoader.java
@@ -27,7 +27,7 @@ import javax.sql.DataSource;
 import net.shibboleth.utilities.java.support.resolver.CriteriaSet;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.PropertyUtils;
-import org.apache.syncope.core.provisioning.api.EntitlementsHolder;
+import org.apache.syncope.common.lib.types.EntitlementsHolder;
 import org.apache.syncope.common.lib.types.SAML2SPEntitlement;
 import org.apache.syncope.core.logic.saml2.SAML2IdPCache;
 import org.apache.syncope.core.logic.saml2.SAML2ReaderWriter;
@@ -89,7 +89,7 @@ public class SAML2SPLoader implements SyncopeCoreLoader {
 
     @Override
     public void load() {
-        EntitlementsHolder.getInstance().init(SAML2SPEntitlement.values());
+        EntitlementsHolder.getInstance().addAll(SAML2SPEntitlement.values());
 
         Properties props = PropertyUtils.read(getClass(), SAML2SP_LOGIC_PROPERTIES, "conf.directory");
         String confDirectory = props.getProperty("conf.directory");
diff --git a/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPASAML2IdPItem.java b/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPASAML2IdPItem.java
index 6e22a43..98b5760 100644
--- a/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPASAML2IdPItem.java
+++ b/ext/saml2sp/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/JPASAML2IdPItem.java
@@ -28,7 +28,7 @@ import javax.persistence.JoinTable;
 import javax.persistence.ManyToMany;
 import javax.persistence.ManyToOne;
 import javax.persistence.Table;
-import org.apache.syncope.common.lib.types.ImplementationType;
+import org.apache.syncope.common.lib.types.IdMImplementationType;
 import org.apache.syncope.core.persistence.api.entity.Implementation;
 import org.apache.syncope.core.persistence.api.entity.SAML2IdP;
 import org.apache.syncope.core.persistence.api.entity.SAML2IdPItem;
@@ -68,7 +68,7 @@ public class JPASAML2IdPItem extends AbstractItem implements SAML2IdPItem {
     @Override
     public boolean add(final Implementation transformer) {
         checkType(transformer, JPAImplementation.class);
-        checkImplementationType(transformer, ImplementationType.ITEM_TRANSFORMER);
+        checkImplementationType(transformer, IdMImplementationType.ITEM_TRANSFORMER);
         return this.transformers.add((JPAImplementation) transformer);
     }
 
diff --git a/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/init/SCIMLoader.java b/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/init/SCIMLoader.java
index db981b8..758ce00 100644
--- a/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/init/SCIMLoader.java
+++ b/ext/scimv2/logic/src/main/java/org/apache/syncope/core/logic/init/SCIMLoader.java
@@ -19,8 +19,8 @@
 package org.apache.syncope.core.logic.init;
 
 import org.apache.syncope.common.lib.scim.types.SCIMEntitlement;
+import org.apache.syncope.common.lib.types.EntitlementsHolder;
 import org.apache.syncope.core.persistence.api.SyncopeCoreLoader;
-import org.apache.syncope.core.provisioning.api.EntitlementsHolder;
 import org.springframework.stereotype.Component;
 
 @Component
@@ -33,6 +33,6 @@ public class SCIMLoader implements SyncopeCoreLoader {
 
     @Override
     public void load() {
-        EntitlementsHolder.getInstance().init(SCIMEntitlement.values());
+        EntitlementsHolder.getInstance().addAll(SCIMEntitlement.values());
     }
 }
diff --git a/fit/core-reference/src/main/java/org/apache/syncope/core/logic/init/ElasticsearchInit.java b/fit/core-reference/src/main/java/org/apache/syncope/core/logic/init/ElasticsearchInit.java
index 404f789..4a9f0d4 100644
--- a/fit/core-reference/src/main/java/org/apache/syncope/core/logic/init/ElasticsearchInit.java
+++ b/fit/core-reference/src/main/java/org/apache/syncope/core/logic/init/ElasticsearchInit.java
@@ -19,8 +19,8 @@
 package org.apache.syncope.core.logic.init;
 
 import org.apache.syncope.common.lib.to.SchedTaskTO;
+import org.apache.syncope.common.lib.types.IdRepoImplementationType;
 import org.apache.syncope.common.lib.types.ImplementationEngine;
-import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.common.lib.types.TaskType;
 import org.apache.syncope.core.logic.TaskLogic;
 import org.apache.syncope.core.persistence.api.dao.ImplementationDAO;
@@ -46,7 +46,7 @@ public class ElasticsearchInit {
 
     @Transactional
     public void init() {
-        Implementation reindex = implementationDAO.find(ImplementationType.TASKJOB_DELEGATE).
+        Implementation reindex = implementationDAO.findByType(IdRepoImplementationType.TASKJOB_DELEGATE).
                 stream().
                 filter(impl -> impl.getEngine() == ImplementationEngine.JAVA
                 && ES_REINDEX.equals(impl.getBody())).
@@ -55,7 +55,7 @@ public class ElasticsearchInit {
             reindex = entityFactory.newEntity(Implementation.class);
             reindex.setKey(ES_REINDEX);
             reindex.setEngine(ImplementationEngine.JAVA);
-            reindex.setType(ImplementationType.TASKJOB_DELEGATE);
+            reindex.setType(IdRepoImplementationType.TASKJOB_DELEGATE);
             reindex.setBody(ES_REINDEX);
             reindex = implementationDAO.save(reindex);
         }
diff --git a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/ITImplementationLookup.java b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/ITImplementationLookup.java
index 5169eb8..08b2cd9 100644
--- a/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/ITImplementationLookup.java
+++ b/fit/core-reference/src/main/java/org/apache/syncope/fit/core/reference/ITImplementationLookup.java
@@ -40,7 +40,8 @@ import org.apache.syncope.common.lib.report.ReconciliationReportletConf;
 import org.apache.syncope.common.lib.report.ReportletConf;
 import org.apache.syncope.common.lib.report.StaticReportletConf;
 import org.apache.syncope.common.lib.report.UserReportletConf;
-import org.apache.syncope.common.lib.types.ImplementationType;
+import org.apache.syncope.common.lib.types.IdMImplementationType;
+import org.apache.syncope.common.lib.types.IdRepoImplementationType;
 import org.apache.syncope.core.logic.init.ElasticsearchInit;
 import org.apache.syncope.core.logic.init.EnableFlowableForTestUsers;
 import org.apache.syncope.core.provisioning.java.job.report.AuditReportlet;
@@ -150,15 +151,14 @@ public class ITImplementationLookup implements ImplementationLookup {
     private static final Set<Class<?>> AUDITAPPENDER_CLASSES = new HashSet<>(
             Arrays.asList(TestFileAuditAppender.class, TestFileRewriteAuditAppender.class));
 
-    private static final Map<ImplementationType, Set<String>> CLASS_NAMES =
-            new HashMap<ImplementationType, Set<String>>() {
+    private static final Map<String, Set<String>> CLASS_NAMES = new HashMap<String, Set<String>>() {
 
         private static final long serialVersionUID = 3109256773218160485L;
 
         {
             Set<String> classNames = ITImplementationLookup.JWTSSOPROVIDER_CLASSES.stream().
                     map(Class::getName).collect(Collectors.toSet());
-            put(ImplementationType.JWT_SSO_PROVIDER, classNames);
+            put(IdRepoImplementationType.JWT_SSO_PROVIDER, classNames);
 
             classNames = new HashSet<>();
             classNames.add(ReconciliationReportletConf.class.getName());
@@ -166,30 +166,30 @@ public class ITImplementationLookup implements ImplementationLookup {
             classNames.add(GroupReportletConf.class.getName());
             classNames.add(AuditReportletConf.class.getName());
             classNames.add(StaticReportletConf.class.getName());
-            put(ImplementationType.REPORTLET, classNames);
+            put(IdRepoImplementationType.REPORTLET, classNames);
 
             classNames = ITImplementationLookup.ACCOUNT_RULE_CLASSES.values().stream().
                     map(Class::getName).collect(Collectors.toSet());
-            put(ImplementationType.ACCOUNT_RULE, classNames);
+            put(IdRepoImplementationType.ACCOUNT_RULE, classNames);
 
             classNames = ITImplementationLookup.PASSWORD_RULE_CLASSES.values().stream().
                     map(Class::getName).collect(Collectors.toSet());
-            put(ImplementationType.PASSWORD_RULE, classNames);
+            put(IdRepoImplementationType.PASSWORD_RULE, classNames);
 
             classNames = new HashSet<>();
             classNames.add(DateToDateItemTransformer.class.getName());
             classNames.add(DateToLongItemTransformer.class.getName());
-            put(ImplementationType.ITEM_TRANSFORMER, classNames);
+            put(IdMImplementationType.ITEM_TRANSFORMER, classNames);
 
             classNames = new HashSet<>();
             classNames.add(TestSampleJobDelegate.class.getName());
-            put(ImplementationType.TASKJOB_DELEGATE, classNames);
+            put(IdRepoImplementationType.TASKJOB_DELEGATE, classNames);
 
             classNames = new HashSet<>();
-            put(ImplementationType.RECON_FILTER_BUILDER, classNames);
+            put(IdMImplementationType.RECON_FILTER_BUILDER, classNames);
 
             classNames = new HashSet<>();
-            put(ImplementationType.LOGIC_ACTIONS, classNames);
+            put(IdRepoImplementationType.LOGIC_ACTIONS, classNames);
 
             classNames = new HashSet<>();
             classNames.add(LDAPMembershipPropagationActions.class.getName());
@@ -197,40 +197,40 @@ public class ITImplementationLookup implements ImplementationLookup {
             classNames.add(DBPasswordPropagationActions.class.getName());
             classNames.add(AzurePropagationActions.class.getName());
             classNames.add(GoogleAppsPropagationActions.class.getName());
-            put(ImplementationType.PROPAGATION_ACTIONS, classNames);
+            put(IdMImplementationType.PROPAGATION_ACTIONS, classNames);
 
             classNames = new HashSet<>();
             classNames.add(LDAPPasswordPullActions.class.getName());
             classNames.add(TestPullActions.class.getName());
             classNames.add(LDAPMembershipPullActions.class.getName());
             classNames.add(DBPasswordPullActions.class.getName());
-            put(ImplementationType.PULL_ACTIONS, classNames);
+            put(IdMImplementationType.PULL_ACTIONS, classNames);
 
             classNames = new HashSet<>();
-            put(ImplementationType.PUSH_ACTIONS, classNames);
+            put(IdMImplementationType.PUSH_ACTIONS, classNames);
 
             classNames = new HashSet<>();
             classNames.add(DummyPullCorrelationRule.class.getName());
-            put(ImplementationType.PULL_CORRELATION_RULE, classNames);
+            put(IdMImplementationType.PULL_CORRELATION_RULE, classNames);
 
             classNames = new HashSet<>();
             classNames.add(DummyPushCorrelationRule.class.getName());
-            put(ImplementationType.PUSH_CORRELATION_RULE, classNames);
+            put(IdMImplementationType.PUSH_CORRELATION_RULE, classNames);
 
             classNames = new HashSet<>();
             classNames.add(BasicValidator.class.getName());
             classNames.add(EmailAddressValidator.class.getName());
             classNames.add(AlwaysTrueValidator.class.getName());
             classNames.add(BinaryValidator.class.getName());
-            put(ImplementationType.VALIDATOR, classNames);
+            put(IdRepoImplementationType.VALIDATOR, classNames);
 
             classNames = new HashSet<>();
             classNames.add(TestNotificationRecipientsProvider.class.getName());
-            put(ImplementationType.RECIPIENTS_PROVIDER, classNames);
+            put(IdRepoImplementationType.RECIPIENTS_PROVIDER, classNames);
 
             classNames = ITImplementationLookup.AUDITAPPENDER_CLASSES.stream().
                     map(Class::getName).collect(Collectors.toSet());
-            put(ImplementationType.AUDIT_APPENDER, classNames);
+            put(IdRepoImplementationType.AUDIT_APPENDER, classNames);
         }
     };
 
@@ -255,10 +255,10 @@ public class ITImplementationLookup implements ImplementationLookup {
     public void load(final String domain, final DataSource datasource) {
         // in case the Flowable extension is enabled, enable modifications for test users
         if (enableFlowableForTestUsers != null && AopUtils.getTargetClass(uwf).getName().contains("Flowable")) {
-                AuthContextUtils.execWithAuthContext(domain, () -> {
-                    enableFlowableForTestUsers.init(datasource);
-                    return null;
-                });
+            AuthContextUtils.execWithAuthContext(domain, () -> {
+                enableFlowableForTestUsers.init(datasource);
+                return null;
+            });
         }
 
         // in case the Elasticsearch extension is enabled, reinit a clean index for all available domains
@@ -271,7 +271,7 @@ public class ITImplementationLookup implements ImplementationLookup {
     }
 
     @Override
-    public Set<String> getClassNames(final ImplementationType type) {
+    public Set<String> getClassNames(final String type) {
         return CLASS_NAMES.get(type);
     }
 
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ImplementationITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ImplementationITCase.java
index 7b5bb7e..db8ef45 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ImplementationITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ImplementationITCase.java
@@ -28,8 +28,8 @@ import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.to.ImplementationTO;
 import org.apache.syncope.common.lib.to.PullTaskTO;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.common.lib.types.IdMImplementationType;
 import org.apache.syncope.common.lib.types.ImplementationEngine;
-import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.common.lib.types.TaskType;
 import org.apache.syncope.common.rest.api.RESTHeaders;
 import org.apache.syncope.fit.AbstractITCase;
@@ -43,7 +43,7 @@ public class ImplementationITCase extends AbstractITCase {
         ImplementationTO implementationTO = new ImplementationTO();
         implementationTO.setKey(UUID.randomUUID().toString());
         implementationTO.setEngine(ImplementationEngine.JAVA);
-        implementationTO.setType(ImplementationType.PUSH_ACTIONS);
+        implementationTO.setType(IdMImplementationType.PUSH_ACTIONS);
         implementationTO.setBody(TestPullActions.class.getName());
 
         // fail because type is wrong
@@ -53,7 +53,7 @@ public class ImplementationITCase extends AbstractITCase {
         } catch (SyncopeClientException e) {
             assertEquals(ClientExceptionType.InvalidImplementation, e.getType());
         }
-        implementationTO.setType(ImplementationType.PULL_ACTIONS);
+        implementationTO.setType(IdMImplementationType.PULL_ACTIONS);
 
         Response response = implementationService.create(implementationTO);
         if (response.getStatusInfo().getStatusCode() != Response.Status.CREATED.getStatusCode()) {
@@ -74,7 +74,7 @@ public class ImplementationITCase extends AbstractITCase {
         ImplementationTO implementationTO = new ImplementationTO();
         implementationTO.setKey(UUID.randomUUID().toString());
         implementationTO.setEngine(ImplementationEngine.JAVA);
-        implementationTO.setType(ImplementationType.PULL_ACTIONS);
+        implementationTO.setType(IdMImplementationType.PULL_ACTIONS);
         implementationTO.setBody(TestPullActions.class.getName());
 
         implementationService.create(implementationTO);
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/NotificationTaskITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/NotificationTaskITCase.java
index c574788..cf88cbe 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/NotificationTaskITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/NotificationTaskITCase.java
@@ -37,8 +37,8 @@ import org.apache.syncope.common.lib.to.ImplementationTO;
 import org.apache.syncope.common.lib.to.NotificationTO;
 import org.apache.syncope.common.lib.to.PagedResult;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.IdRepoImplementationType;
 import org.apache.syncope.common.lib.types.ImplementationEngine;
-import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.common.lib.types.TaskType;
 import org.apache.syncope.common.lib.types.TraceLevel;
 import org.apache.syncope.common.rest.api.RESTHeaders;
@@ -232,7 +232,7 @@ public class NotificationTaskITCase extends AbstractNotificationTaskITCase {
         ImplementationTO recipientsProvider = new ImplementationTO();
         recipientsProvider.setKey(TestNotificationRecipientsProvider.class.getSimpleName());
         recipientsProvider.setEngine(ImplementationEngine.JAVA);
-        recipientsProvider.setType(ImplementationType.RECIPIENTS_PROVIDER);
+        recipientsProvider.setType(IdRepoImplementationType.RECIPIENTS_PROVIDER);
         recipientsProvider.setBody(TestNotificationRecipientsProvider.class.getName());
         Response response = implementationService.create(recipientsProvider);
         recipientsProvider = implementationService.read(
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PolicyITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PolicyITCase.java
index e47fcf7..4ee3e8a 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PolicyITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PolicyITCase.java
@@ -43,8 +43,9 @@ import org.apache.syncope.common.lib.policy.DefaultPasswordRuleConf;
 import org.apache.syncope.common.lib.policy.PushPolicyTO;
 import org.apache.syncope.common.lib.types.PolicyType;
 import org.apache.syncope.common.lib.to.ImplementationTO;
+import org.apache.syncope.common.lib.types.IdMImplementationType;
+import org.apache.syncope.common.lib.types.IdRepoImplementationType;
 import org.apache.syncope.common.lib.types.ImplementationEngine;
-import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.common.rest.api.RESTHeaders;
 import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
 import org.apache.syncope.fit.AbstractITCase;
@@ -57,13 +58,13 @@ public class PolicyITCase extends AbstractITCase {
     private PullPolicyTO buildPullPolicyTO() throws IOException {
         ImplementationTO corrRule = null;
         try {
-            corrRule = implementationService.read(ImplementationType.PULL_CORRELATION_RULE, "TestPullRule");
+            corrRule = implementationService.read(IdMImplementationType.PULL_CORRELATION_RULE, "TestPullRule");
         } catch (SyncopeClientException e) {
             if (e.getType().getResponseStatus() == Response.Status.NOT_FOUND) {
                 corrRule = new ImplementationTO();
                 corrRule.setKey("TestPullRule");
                 corrRule.setEngine(ImplementationEngine.GROOVY);
-                corrRule.setType(ImplementationType.PULL_CORRELATION_RULE);
+                corrRule.setType(IdMImplementationType.PULL_CORRELATION_RULE);
                 corrRule.setBody(IOUtils.toString(
                         getClass().getResourceAsStream("/TestPullRule.groovy"), StandardCharsets.UTF_8));
                 Response response = implementationService.create(corrRule);
@@ -84,13 +85,13 @@ public class PolicyITCase extends AbstractITCase {
     private PushPolicyTO buildPushPolicyTO() throws IOException {
         ImplementationTO corrRule = null;
         try {
-            corrRule = implementationService.read(ImplementationType.PUSH_CORRELATION_RULE, "TestPushRule");
+            corrRule = implementationService.read(IdMImplementationType.PUSH_CORRELATION_RULE, "TestPushRule");
         } catch (SyncopeClientException e) {
             if (e.getType().getResponseStatus() == Response.Status.NOT_FOUND) {
                 corrRule = new ImplementationTO();
                 corrRule.setKey("TestPushRule");
                 corrRule.setEngine(ImplementationEngine.GROOVY);
-                corrRule.setType(ImplementationType.PUSH_CORRELATION_RULE);
+                corrRule.setType(IdMImplementationType.PUSH_CORRELATION_RULE);
                 corrRule.setBody(IOUtils.toString(
                         getClass().getResourceAsStream("/TestPushRule.groovy"), StandardCharsets.UTF_8));
                 Response response = implementationService.create(corrRule);
@@ -165,7 +166,8 @@ public class PolicyITCase extends AbstractITCase {
         assertNotNull(policy);
         assertNotEquals("ce93fcda-dc3a-4369-a7b0-a6108c261c85", policy.getKey());
 
-        ImplementationTO rule = implementationService.read(ImplementationType.PASSWORD_RULE, policy.getRules().get(0));
+        ImplementationTO rule = implementationService.read(
+                IdRepoImplementationType.PASSWORD_RULE, policy.getRules().get(0));
         assertNotNull(rule);
 
         DefaultPasswordRuleConf ruleConf = POJOHelper.deserialize(rule.getBody(), DefaultPasswordRuleConf.class);
@@ -202,7 +204,7 @@ public class PolicyITCase extends AbstractITCase {
     @Test
     public void getPullCorrelationRuleJavaClasses() {
         Set<String> classes = syncopeService.platform().
-                getJavaImplInfo(ImplementationType.PULL_CORRELATION_RULE).get().getClasses();
+                getJavaImplInfo(IdMImplementationType.PULL_CORRELATION_RULE).get().getClasses();
         assertEquals(1, classes.size());
         assertEquals(DummyPullCorrelationRule.class.getName(), classes.iterator().next());
     }
@@ -210,7 +212,7 @@ public class PolicyITCase extends AbstractITCase {
     @Test
     public void getPushCorrelationRuleJavaClasses() {
         Set<String> classes = syncopeService.platform().
-                getJavaImplInfo(ImplementationType.PUSH_CORRELATION_RULE).get().getClasses();
+                getJavaImplInfo(IdMImplementationType.PUSH_CORRELATION_RULE).get().getClasses();
         assertEquals(1, classes.size());
         assertEquals(DummyPushCorrelationRule.class.getName(), classes.iterator().next());
     }
@@ -227,7 +229,7 @@ public class PolicyITCase extends AbstractITCase {
         ImplementationTO rule = new ImplementationTO();
         rule.setKey("DefaultAccountRuleConf" + getUUIDString());
         rule.setEngine(ImplementationEngine.JAVA);
-        rule.setType(ImplementationType.ACCOUNT_RULE);
+        rule.setType(IdRepoImplementationType.ACCOUNT_RULE);
         rule.setBody(POJOHelper.serialize(ruleConf));
         Response response = implementationService.create(rule);
         rule.setKey(response.getHeaderString(RESTHeaders.RESOURCE_KEY));
@@ -251,7 +253,7 @@ public class PolicyITCase extends AbstractITCase {
         ImplementationTO rule = new ImplementationTO();
         rule.setKey("DefaultAccountRuleConf" + getUUIDString());
         rule.setEngine(ImplementationEngine.JAVA);
-        rule.setType(ImplementationType.ACCOUNT_RULE);
+        rule.setType(IdRepoImplementationType.ACCOUNT_RULE);
         rule.setBody(POJOHelper.serialize(ruleConf));
         Response response = implementationService.create(rule);
         rule.setKey(response.getHeaderString(RESTHeaders.RESOURCE_KEY));
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PropagationTaskITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PropagationTaskITCase.java
index cf9aa77..458e09f 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PropagationTaskITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PropagationTaskITCase.java
@@ -57,8 +57,8 @@ import org.apache.syncope.common.lib.to.ProvisioningResult;
 import org.apache.syncope.common.lib.to.ResourceTO;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.IdMImplementationType;
 import org.apache.syncope.common.lib.types.ImplementationEngine;
-import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.common.lib.types.MappingPurpose;
 import org.apache.syncope.common.lib.types.PatchOperation;
 import org.apache.syncope.common.lib.types.TaskType;
@@ -83,15 +83,15 @@ public class PropagationTaskITCase extends AbstractTaskITCase {
         ImplementationTO dateToDate = null;
         try {
             dateToLong = implementationService.read(
-                    ImplementationType.ITEM_TRANSFORMER, DateToLongItemTransformer.class.getSimpleName());
+                    IdMImplementationType.ITEM_TRANSFORMER, DateToLongItemTransformer.class.getSimpleName());
             dateToDate = implementationService.read(
-                    ImplementationType.ITEM_TRANSFORMER, DateToDateItemTransformer.class.getSimpleName());
+                    IdMImplementationType.ITEM_TRANSFORMER, DateToDateItemTransformer.class.getSimpleName());
         } catch (SyncopeClientException e) {
             if (e.getType().getResponseStatus() == Response.Status.NOT_FOUND) {
                 dateToLong = new ImplementationTO();
                 dateToLong.setKey(DateToLongItemTransformer.class.getSimpleName());
                 dateToLong.setEngine(ImplementationEngine.JAVA);
-                dateToLong.setType(ImplementationType.ITEM_TRANSFORMER);
+                dateToLong.setType(IdMImplementationType.ITEM_TRANSFORMER);
                 dateToLong.setBody(DateToLongItemTransformer.class.getName());
                 Response response = implementationService.create(dateToLong);
                 dateToLong = implementationService.read(
@@ -101,7 +101,7 @@ public class PropagationTaskITCase extends AbstractTaskITCase {
                 dateToDate = new ImplementationTO();
                 dateToDate.setKey(DateToDateItemTransformer.class.getSimpleName());
                 dateToDate.setEngine(ImplementationEngine.JAVA);
-                dateToDate.setType(ImplementationType.ITEM_TRANSFORMER);
+                dateToDate.setType(IdMImplementationType.ITEM_TRANSFORMER);
                 dateToDate.setBody(DateToDateItemTransformer.class.getName());
                 response = implementationService.create(dateToDate);
                 dateToDate = implementationService.read(
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PullTaskITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PullTaskITCase.java
index 586f63b..73b296c 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PullTaskITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PullTaskITCase.java
@@ -79,9 +79,9 @@ import org.apache.syncope.common.lib.types.ClientExceptionType;
 import org.apache.syncope.common.lib.types.ConnConfProperty;
 import org.apache.syncope.common.lib.types.ConnectorCapability;
 import org.apache.syncope.common.lib.types.ImplementationEngine;
-import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.common.lib.types.PolicyType;
 import org.apache.syncope.common.lib.types.ExecStatus;
+import org.apache.syncope.common.lib.types.IdMImplementationType;
 import org.apache.syncope.common.lib.types.ResourceDeassociationAction;
 import org.apache.syncope.common.lib.types.PullMode;
 import org.apache.syncope.common.lib.types.ResourceOperation;
@@ -92,7 +92,6 @@ import org.apache.syncope.common.rest.api.beans.RemediationQuery;
 import org.apache.syncope.common.rest.api.beans.TaskQuery;
 import org.apache.syncope.common.rest.api.service.ConnectorService;
 import org.apache.syncope.common.rest.api.service.TaskService;
-import org.apache.syncope.core.provisioning.api.pushpull.ProvisioningReport;
 import org.apache.syncope.core.provisioning.java.pushpull.DBPasswordPullActions;
 import org.apache.syncope.core.provisioning.java.pushpull.LDAPPasswordPullActions;
 import org.apache.syncope.core.spring.security.Encryptor;
@@ -116,13 +115,13 @@ public class PullTaskITCase extends AbstractTaskITCase {
         ImplementationTO pullActions = null;
         try {
             pullActions = implementationService.read(
-                    ImplementationType.PULL_ACTIONS, TestPullActions.class.getSimpleName());
+                    IdMImplementationType.PULL_ACTIONS, TestPullActions.class.getSimpleName());
         } catch (SyncopeClientException e) {
             if (e.getType().getResponseStatus() == Response.Status.NOT_FOUND) {
                 pullActions = new ImplementationTO();
                 pullActions.setKey(TestPullActions.class.getSimpleName());
                 pullActions.setEngine(ImplementationEngine.JAVA);
-                pullActions.setType(ImplementationType.PULL_ACTIONS);
+                pullActions.setType(IdMImplementationType.PULL_ACTIONS);
                 pullActions.setBody(TestPullActions.class.getName());
                 Response response = implementationService.create(pullActions);
                 pullActions = implementationService.read(
@@ -140,7 +139,7 @@ public class PullTaskITCase extends AbstractTaskITCase {
     @Test
     public void getPullActionsClasses() {
         Set<String> actions = syncopeService.platform().
-                getJavaImplInfo(ImplementationType.PULL_ACTIONS).get().getClasses();
+                getJavaImplInfo(IdMImplementationType.PULL_ACTIONS).get().getClasses();
         assertNotNull(actions);
         assertFalse(actions.isEmpty());
     }
@@ -499,7 +498,7 @@ public class PullTaskITCase extends AbstractTaskITCase {
         ImplementationTO transformer = new ImplementationTO();
         transformer.setKey("PrefixItemTransformer");
         transformer.setEngine(ImplementationEngine.GROOVY);
-        transformer.setType(ImplementationType.ITEM_TRANSFORMER);
+        transformer.setType(IdMImplementationType.ITEM_TRANSFORMER);
         transformer.setBody(IOUtils.toString(
                 getClass().getResourceAsStream("/PrefixItemTransformer.groovy"), StandardCharsets.UTF_8));
         Response response = implementationService.create(transformer);
@@ -589,7 +588,7 @@ public class PullTaskITCase extends AbstractTaskITCase {
             ImplementationTO reconFilterBuilder = new ImplementationTO();
             reconFilterBuilder.setKey("TestReconFilterBuilder");
             reconFilterBuilder.setEngine(ImplementationEngine.GROOVY);
-            reconFilterBuilder.setType(ImplementationType.RECON_FILTER_BUILDER);
+            reconFilterBuilder.setType(IdMImplementationType.RECON_FILTER_BUILDER);
             reconFilterBuilder.setBody(IOUtils.toString(
                     getClass().getResourceAsStream("/TestReconFilterBuilder.groovy"), StandardCharsets.UTF_8));
             Response response = implementationService.create(reconFilterBuilder);
@@ -907,13 +906,13 @@ public class PullTaskITCase extends AbstractTaskITCase {
         // -----------------------------
         ImplementationTO corrRule = null;
         try {
-            corrRule = implementationService.read(ImplementationType.PULL_CORRELATION_RULE, "TestPullRule");
+            corrRule = implementationService.read(IdMImplementationType.PULL_CORRELATION_RULE, "TestPullRule");
         } catch (SyncopeClientException e) {
             if (e.getType().getResponseStatus() == Response.Status.NOT_FOUND) {
                 corrRule = new ImplementationTO();
                 corrRule.setKey("TestPullRule");
                 corrRule.setEngine(ImplementationEngine.GROOVY);
-                corrRule.setType(ImplementationType.PULL_CORRELATION_RULE);
+                corrRule.setType(IdMImplementationType.PULL_CORRELATION_RULE);
                 corrRule.setBody(IOUtils.toString(
                         getClass().getResourceAsStream("/TestPullRule.groovy"), StandardCharsets.UTF_8));
                 Response response = implementationService.create(corrRule);
@@ -1069,7 +1068,7 @@ public class PullTaskITCase extends AbstractTaskITCase {
         ImplementationTO pullActions = new ImplementationTO();
         pullActions.setKey(DBPasswordPullActions.class.getSimpleName());
         pullActions.setEngine(ImplementationEngine.JAVA);
-        pullActions.setType(ImplementationType.PULL_ACTIONS);
+        pullActions.setType(IdMImplementationType.PULL_ACTIONS);
         pullActions.setBody(DBPasswordPullActions.class.getName());
         Response response = implementationService.create(pullActions);
         pullActions = implementationService.read(
@@ -1159,7 +1158,7 @@ public class PullTaskITCase extends AbstractTaskITCase {
             ImplementationTO pullActions = new ImplementationTO();
             pullActions.setKey(LDAPPasswordPullActions.class.getSimpleName());
             pullActions.setEngine(ImplementationEngine.JAVA);
-            pullActions.setType(ImplementationType.PULL_ACTIONS);
+            pullActions.setType(IdMImplementationType.PULL_ACTIONS);
             pullActions.setBody(LDAPPasswordPullActions.class.getName());
             Response response = implementationService.create(pullActions);
             pullActions = implementationService.read(
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PushTaskITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PushTaskITCase.java
index d9a46ce..b52e44d 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PushTaskITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/PushTaskITCase.java
@@ -49,10 +49,10 @@ import org.apache.syncope.common.lib.to.ReconStatus;
 import org.apache.syncope.common.lib.to.ResourceTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.AttrSchemaType;
-import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.common.lib.types.MappingPurpose;
 import org.apache.syncope.common.lib.types.MatchingRule;
 import org.apache.syncope.common.lib.types.ExecStatus;
+import org.apache.syncope.common.lib.types.IdMImplementationType;
 import org.apache.syncope.common.lib.types.SchemaType;
 import org.apache.syncope.common.lib.types.TaskType;
 import org.apache.syncope.common.lib.types.TraceLevel;
@@ -76,7 +76,7 @@ public class PushTaskITCase extends AbstractTaskITCase {
     @Test
     public void getPushActionsClasses() {
         Set<String> actions = syncopeService.platform().
-                getJavaImplInfo(ImplementationType.PUSH_ACTIONS).get().getClasses();
+                getJavaImplInfo(IdMImplementationType.PUSH_ACTIONS).get().getClasses();
         assertNotNull(actions);
     }
 
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RealmITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RealmITCase.java
index f62f2f9..4d5f7c7 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RealmITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/RealmITCase.java
@@ -39,9 +39,9 @@ import org.apache.syncope.common.lib.to.ImplementationTO;
 import org.apache.syncope.common.lib.to.ProvisioningResult;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
 import org.apache.syncope.common.lib.types.ImplementationEngine;
-import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.common.lib.types.PolicyType;
 import org.apache.syncope.common.lib.types.ExecStatus;
+import org.apache.syncope.common.lib.types.IdRepoImplementationType;
 import org.apache.syncope.common.rest.api.RESTHeaders;
 import org.apache.syncope.common.rest.api.service.RealmService;
 import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
@@ -136,7 +136,7 @@ public class RealmITCase extends AbstractITCase {
         ImplementationTO rule = new ImplementationTO();
         rule.setKey("DefaultAccountRuleConf" + UUID.randomUUID().toString());
         rule.setEngine(ImplementationEngine.JAVA);
-        rule.setType(ImplementationType.ACCOUNT_RULE);
+        rule.setType(IdRepoImplementationType.ACCOUNT_RULE);
         rule.setBody(POJOHelper.serialize(ruleConf));
         Response response = implementationService.create(rule);
         rule.setKey(response.getHeaderString(RESTHeaders.RESOURCE_KEY));
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ReportITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ReportITCase.java
index d8c5d27..2dcaeb4 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ReportITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ReportITCase.java
@@ -43,8 +43,8 @@ import org.apache.syncope.common.lib.to.ReportTO;
 import org.apache.syncope.common.lib.types.AuditElements;
 import org.apache.syncope.common.lib.types.AuditLoggerName;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.common.lib.types.IdRepoImplementationType;
 import org.apache.syncope.common.lib.types.ImplementationEngine;
-import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.common.lib.types.LoggerLevel;
 import org.apache.syncope.common.lib.types.LoggerType;
 import org.apache.syncope.common.lib.types.ReportExecExportFormat;
@@ -96,7 +96,7 @@ public class ReportITCase extends AbstractITCase {
     @Test
     public void getReportletConfs() {
         Set<String> reportletConfs = syncopeService.platform().
-                getJavaImplInfo(ImplementationType.REPORTLET).get().getClasses();
+                getJavaImplInfo(IdRepoImplementationType.REPORTLET).get().getClasses();
         assertNotNull(reportletConfs);
         assertFalse(reportletConfs.isEmpty());
         assertTrue(reportletConfs.contains(UserReportletConf.class.getName()));
@@ -126,7 +126,7 @@ public class ReportITCase extends AbstractITCase {
         ImplementationTO reportlet1 = new ImplementationTO();
         reportlet1.setKey("UserReportletConf" + getUUIDString());
         reportlet1.setEngine(ImplementationEngine.JAVA);
-        reportlet1.setType(ImplementationType.REPORTLET);
+        reportlet1.setType(IdRepoImplementationType.REPORTLET);
         reportlet1.setBody(POJOHelper.serialize(new UserReportletConf("first")));
         Response response = implementationService.create(reportlet1);
         reportlet1.setKey(response.getHeaderString(RESTHeaders.RESOURCE_KEY));
@@ -134,7 +134,7 @@ public class ReportITCase extends AbstractITCase {
         ImplementationTO reportlet2 = new ImplementationTO();
         reportlet2.setKey("UserReportletConf" + getUUIDString());
         reportlet2.setEngine(ImplementationEngine.JAVA);
-        reportlet2.setType(ImplementationType.REPORTLET);
+        reportlet2.setType(IdRepoImplementationType.REPORTLET);
         reportlet2.setBody(POJOHelper.serialize(new UserReportletConf("second")));
         response = implementationService.create(reportlet2);
         reportlet2.setKey(response.getHeaderString(RESTHeaders.RESOURCE_KEY));
@@ -159,7 +159,7 @@ public class ReportITCase extends AbstractITCase {
         ImplementationTO reportlet1 = new ImplementationTO();
         reportlet1.setKey("UserReportletConf" + getUUIDString());
         reportlet1.setEngine(ImplementationEngine.JAVA);
-        reportlet1.setType(ImplementationType.REPORTLET);
+        reportlet1.setType(IdRepoImplementationType.REPORTLET);
         reportlet1.setBody(POJOHelper.serialize(new UserReportletConf("first")));
         Response response = implementationService.create(reportlet1);
         reportlet1.setKey(response.getHeaderString(RESTHeaders.RESOURCE_KEY));
@@ -167,7 +167,7 @@ public class ReportITCase extends AbstractITCase {
         ImplementationTO reportlet2 = new ImplementationTO();
         reportlet2.setKey("UserReportletConf" + getUUIDString());
         reportlet2.setEngine(ImplementationEngine.JAVA);
-        reportlet2.setType(ImplementationType.REPORTLET);
+        reportlet2.setType(IdRepoImplementationType.REPORTLET);
         reportlet2.setBody(POJOHelper.serialize(new UserReportletConf("second")));
         response = implementationService.create(reportlet2);
         reportlet2.setKey(response.getHeaderString(RESTHeaders.RESOURCE_KEY));
@@ -185,7 +185,7 @@ public class ReportITCase extends AbstractITCase {
         ImplementationTO reportlet3 = new ImplementationTO();
         reportlet3.setKey("UserReportletConf" + getUUIDString());
         reportlet3.setEngine(ImplementationEngine.JAVA);
-        reportlet3.setType(ImplementationType.REPORTLET);
+        reportlet3.setType(IdRepoImplementationType.REPORTLET);
         reportlet3.setBody(POJOHelper.serialize(new UserReportletConf("last")));
         response = implementationService.create(reportlet3);
         reportlet3.setKey(response.getHeaderString(RESTHeaders.RESOURCE_KEY));
@@ -203,7 +203,7 @@ public class ReportITCase extends AbstractITCase {
         ImplementationTO reportlet1 = new ImplementationTO();
         reportlet1.setKey("UserReportletConf" + getUUIDString());
         reportlet1.setEngine(ImplementationEngine.JAVA);
-        reportlet1.setType(ImplementationType.REPORTLET);
+        reportlet1.setType(IdRepoImplementationType.REPORTLET);
         reportlet1.setBody(POJOHelper.serialize(new UserReportletConf("first")));
         Response response = implementationService.create(reportlet1);
         reportlet1.setKey(response.getHeaderString(RESTHeaders.RESOURCE_KEY));
@@ -211,7 +211,7 @@ public class ReportITCase extends AbstractITCase {
         ImplementationTO reportlet2 = new ImplementationTO();
         reportlet2.setKey("UserReportletConf" + getUUIDString());
         reportlet2.setEngine(ImplementationEngine.JAVA);
-        reportlet2.setType(ImplementationType.REPORTLET);
+        reportlet2.setType(IdRepoImplementationType.REPORTLET);
         reportlet2.setBody(POJOHelper.serialize(new UserReportletConf("second")));
         response = implementationService.create(reportlet2);
         reportlet2.setKey(response.getHeaderString(RESTHeaders.RESOURCE_KEY));
@@ -328,7 +328,7 @@ public class ReportITCase extends AbstractITCase {
             ImplementationTO auditReportlet = new ImplementationTO();
             auditReportlet.setKey("UserReportletConf" + getUUIDString());
             auditReportlet.setEngine(ImplementationEngine.JAVA);
-            auditReportlet.setType(ImplementationType.REPORTLET);
+            auditReportlet.setType(IdRepoImplementationType.REPORTLET);
             auditReportlet.setBody(POJOHelper.serialize(new AuditReportletConf("auditReportlet" + getUUIDString())));
             Response response = implementationService.create(auditReportlet);
             auditReportlet.setKey(response.getHeaderString(RESTHeaders.RESOURCE_KEY));
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ResourceITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ResourceITCase.java
index 8e92368..3ce7f84 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ResourceITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ResourceITCase.java
@@ -56,7 +56,7 @@ import org.apache.syncope.common.lib.types.ClientExceptionType;
 import org.apache.syncope.common.lib.types.ConnConfPropSchema;
 import org.apache.syncope.common.lib.types.ConnConfProperty;
 import org.apache.syncope.common.lib.types.EntityViolationType;
-import org.apache.syncope.common.lib.types.ImplementationType;
+import org.apache.syncope.common.lib.types.IdMImplementationType;
 import org.apache.syncope.common.lib.types.MappingPurpose;
 import org.apache.syncope.common.lib.types.TraceLevel;
 import org.apache.syncope.common.rest.api.beans.ConnObjectTOListQuery;
@@ -106,7 +106,7 @@ public class ResourceITCase extends AbstractITCase {
     @Test
     public void getPropagationActionsClasses() {
         Set<String> actions = syncopeService.platform().
-                getJavaImplInfo(ImplementationType.PROPAGATION_ACTIONS).get().getClasses();
+                getJavaImplInfo(IdMImplementationType.PROPAGATION_ACTIONS).get().getClasses();
         assertNotNull(actions);
         assertFalse(actions.isEmpty());
     }
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SchedTaskITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SchedTaskITCase.java
index 24eacad..d68c279 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SchedTaskITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/SchedTaskITCase.java
@@ -38,7 +38,7 @@ import org.apache.syncope.common.lib.to.SchedTaskTO;
 import org.apache.syncope.common.lib.to.PullTaskTO;
 import org.apache.syncope.common.lib.to.ExecTO;
 import org.apache.syncope.common.lib.to.ImplementationTO;
-import org.apache.syncope.common.lib.types.ImplementationType;
+import org.apache.syncope.common.lib.types.IdRepoImplementationType;
 import org.apache.syncope.common.lib.types.JobAction;
 import org.apache.syncope.common.lib.types.TaskType;
 import org.apache.syncope.common.rest.api.beans.ExecuteQuery;
@@ -53,7 +53,7 @@ public class SchedTaskITCase extends AbstractTaskITCase {
     @Test
     public void getJobClasses() {
         Set<String> jobClasses = syncopeService.platform().
-                getJavaImplInfo(ImplementationType.TASKJOB_DELEGATE).get().getClasses();
+                getJavaImplInfo(IdRepoImplementationType.TASKJOB_DELEGATE).get().getClasses();
         assertNotNull(jobClasses);
         assertFalse(jobClasses.isEmpty());
     }
@@ -90,7 +90,7 @@ public class SchedTaskITCase extends AbstractTaskITCase {
     @Test
     public void deferred() {
         ImplementationTO taskJobDelegate = implementationService.read(
-                ImplementationType.TASKJOB_DELEGATE, TestSampleJobDelegate.class.getSimpleName());
+                IdRepoImplementationType.TASKJOB_DELEGATE, TestSampleJobDelegate.class.getSimpleName());
         assertNotNull(taskJobDelegate);
 
         SchedTaskTO task = new SchedTaskTO();
@@ -136,7 +136,7 @@ public class SchedTaskITCase extends AbstractTaskITCase {
     @Test
     public void issueSYNCOPE144() {
         ImplementationTO taskJobDelegate = implementationService.read(
-                ImplementationType.TASKJOB_DELEGATE, TestSampleJobDelegate.class.getSimpleName());
+                IdRepoImplementationType.TASKJOB_DELEGATE, TestSampleJobDelegate.class.getSimpleName());
         assertNotNull(taskJobDelegate);
 
         SchedTaskTO task = new SchedTaskTO();
@@ -171,7 +171,7 @@ public class SchedTaskITCase extends AbstractTaskITCase {
         int old_size = jobs.size();
 
         ImplementationTO taskJobDelegate = implementationService.read(
-                ImplementationType.TASKJOB_DELEGATE, TestSampleJobDelegate.class.getSimpleName());
+                IdRepoImplementationType.TASKJOB_DELEGATE, TestSampleJobDelegate.class.getSimpleName());
         assertNotNull(taskJobDelegate);
 
         SchedTaskTO task = new SchedTaskTO();
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserITCase.java
index 9bfbc83..dbe70f5 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserITCase.java
@@ -75,8 +75,8 @@ import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
 import org.apache.syncope.common.lib.types.PatchOperation;
 import org.apache.syncope.common.lib.types.ExecStatus;
+import org.apache.syncope.common.lib.types.IdRepoImplementationType;
 import org.apache.syncope.common.lib.types.ImplementationEngine;
-import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.common.lib.types.PolicyType;
 import org.apache.syncope.common.lib.types.ResourceAssociationAction;
 import org.apache.syncope.common.lib.types.ResourceDeassociationAction;
@@ -939,7 +939,7 @@ public class UserITCase extends AbstractITCase {
         ImplementationTO implementationTO = new ImplementationTO();
         implementationTO.setKey("TestAccountRuleConf" + UUID.randomUUID().toString());
         implementationTO.setEngine(ImplementationEngine.JAVA);
-        implementationTO.setType(ImplementationType.ACCOUNT_RULE);
+        implementationTO.setType(IdRepoImplementationType.ACCOUNT_RULE);
         implementationTO.setBody(POJOHelper.serialize(new TestAccountRuleConf()));
         Response response = implementationService.create(implementationTO);
         implementationTO.setKey(response.getHeaderString(RESTHeaders.RESOURCE_KEY));
@@ -953,7 +953,7 @@ public class UserITCase extends AbstractITCase {
         implementationTO = new ImplementationTO();
         implementationTO.setKey("TestPasswordRuleConf" + UUID.randomUUID().toString());
         implementationTO.setEngine(ImplementationEngine.JAVA);
-        implementationTO.setType(ImplementationType.PASSWORD_RULE);
+        implementationTO.setType(IdRepoImplementationType.PASSWORD_RULE);
         implementationTO.setBody(POJOHelper.serialize(new TestPasswordRuleConf()));
         response = implementationService.create(implementationTO);
         implementationTO.setKey(response.getHeaderString(RESTHeaders.RESOURCE_KEY));
@@ -1359,7 +1359,7 @@ public class UserITCase extends AbstractITCase {
         ImplementationTO rule = new ImplementationTO();
         rule.setKey("HaveIBeenPwnedPasswordRuleConf" + getUUIDString());
         rule.setEngine(ImplementationEngine.JAVA);
-        rule.setType(ImplementationType.PASSWORD_RULE);
+        rule.setType(IdRepoImplementationType.PASSWORD_RULE);
         rule.setBody(POJOHelper.serialize(new HaveIBeenPwnedPasswordRuleConf()));
         Response response = implementationService.create(rule);
         rule.setKey(response.getHeaderString(RESTHeaders.RESOURCE_KEY));
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserIssuesITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserIssuesITCase.java
index cc4df0c..88eea92 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserIssuesITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/UserIssuesITCase.java
@@ -71,11 +71,12 @@ import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.CipherAlgorithm;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
 import org.apache.syncope.common.lib.types.ImplementationEngine;
-import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.common.lib.types.MappingPurpose;
 import org.apache.syncope.common.lib.types.PatchOperation;
 import org.apache.syncope.common.lib.types.PolicyType;
 import org.apache.syncope.common.lib.types.ExecStatus;
+import org.apache.syncope.common.lib.types.IdMImplementationType;
+import org.apache.syncope.common.lib.types.IdRepoImplementationType;
 import org.apache.syncope.common.rest.api.RESTHeaders;
 import org.apache.syncope.core.provisioning.api.serialization.POJOHelper;
 import org.apache.syncope.core.provisioning.java.propagation.DBPasswordPropagationActions;
@@ -799,12 +800,13 @@ public class UserIssuesITCase extends AbstractITCase {
     public void issueSYNCOPE420() throws IOException {
         ImplementationTO logicActions;
         try {
-            logicActions = implementationService.read(ImplementationType.LOGIC_ACTIONS, "DoubleValueLogicActions");
+            logicActions = implementationService.read(
+                    IdRepoImplementationType.LOGIC_ACTIONS, "DoubleValueLogicActions");
         } catch (SyncopeClientException e) {
             logicActions = new ImplementationTO();
             logicActions.setKey("DoubleValueLogicActions");
             logicActions.setEngine(ImplementationEngine.GROOVY);
-            logicActions.setType(ImplementationType.LOGIC_ACTIONS);
+            logicActions.setType(IdRepoImplementationType.LOGIC_ACTIONS);
             logicActions.setBody(org.apache.commons.io.IOUtils.toString(
                     getClass().getResourceAsStream("/DoubleValueLogicActions.groovy"), StandardCharsets.UTF_8));
             Response response = implementationService.create(logicActions);
@@ -989,7 +991,7 @@ public class UserIssuesITCase extends AbstractITCase {
         ImplementationTO propagationActions = new ImplementationTO();
         propagationActions.setKey(DBPasswordPropagationActions.class.getSimpleName());
         propagationActions.setEngine(ImplementationEngine.JAVA);
-        propagationActions.setType(ImplementationType.PROPAGATION_ACTIONS);
+        propagationActions.setType(IdMImplementationType.PROPAGATION_ACTIONS);
         propagationActions.setBody(DBPasswordPropagationActions.class.getName());
         Response response = implementationService.create(propagationActions);
         propagationActions = implementationService.read(
@@ -1039,7 +1041,7 @@ public class UserIssuesITCase extends AbstractITCase {
         ImplementationTO propagationActions = new ImplementationTO();
         propagationActions.setKey(LDAPPasswordPropagationActions.class.getSimpleName());
         propagationActions.setEngine(ImplementationEngine.JAVA);
-        propagationActions.setType(ImplementationType.PROPAGATION_ACTIONS);
+        propagationActions.setType(IdMImplementationType.PROPAGATION_ACTIONS);
         propagationActions.setBody(LDAPPasswordPropagationActions.class.getName());
         Response response = implementationService.create(propagationActions);
         propagationActions = implementationService.read(
@@ -1231,7 +1233,7 @@ public class UserIssuesITCase extends AbstractITCase {
         ImplementationTO rule = new ImplementationTO();
         rule.setKey("DefaultPasswordRuleConf" + getUUIDString());
         rule.setEngine(ImplementationEngine.JAVA);
-        rule.setType(ImplementationType.PASSWORD_RULE);
+        rule.setType(IdRepoImplementationType.PASSWORD_RULE);
         rule.setBody(POJOHelper.serialize(ruleConf));
         Response response = implementationService.create(rule);
         rule.setKey(response.getHeaderString(RESTHeaders.RESOURCE_KEY));
diff --git a/ide/netbeans/src/main/java/org/apache/syncope/ide/netbeans/ResourceConnector.java b/ide/netbeans/src/main/java/org/apache/syncope/ide/netbeans/ResourceConnector.java
index 92bf881..fe47dbf 100644
--- a/ide/netbeans/src/main/java/org/apache/syncope/ide/netbeans/ResourceConnector.java
+++ b/ide/netbeans/src/main/java/org/apache/syncope/ide/netbeans/ResourceConnector.java
@@ -24,17 +24,22 @@ import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.ide.netbeans.service.MailTemplateManagerService;
 import org.apache.syncope.ide.netbeans.service.ReportTemplateManagerService;
 import org.apache.syncope.ide.netbeans.service.ImplementationManagerService;
+import org.apache.syncope.ide.netbeans.service.SyncopeManagerService;
 import org.apache.syncope.ide.netbeans.view.ResourceExplorerTopComponent;
 import org.openide.util.NbPreferences;
 
 public final class ResourceConnector {
 
+    private static SyncopeManagerService SYNCOPE_MANAGER_SERVICE;
+
     private static MailTemplateManagerService MAIL_TEMPLATE_MANAGER_SERVICE;
 
     private static ReportTemplateManagerService REPORT_TEMPLATE_MANAGER_SERVICE;
 
     private static ImplementationManagerService IMPLEMENTATION_MANAGER_SERVICE;
 
+    private static final Object SYNCOPE_MONITOR = new Object();
+
     private static final Object MAIL_TEMPLATE_MONITOR = new Object();
 
     private static final Object REPORT_TEMPLATE_MONITOR = new Object();
@@ -44,6 +49,17 @@ public final class ResourceConnector {
     private ResourceConnector() {
     }
 
+    public static SyncopeManagerService getSyncopeManagerService() {
+        synchronized (SYNCOPE_MONITOR) {
+            ConnectionParams connParams = getConnectionParams();
+            SYNCOPE_MANAGER_SERVICE = new SyncopeManagerService(
+                    connParams.getUrl(),
+                    connParams.getUsername(),
+                    connParams.getPassword());
+        }
+        return SYNCOPE_MANAGER_SERVICE;
+    }
+
     public static MailTemplateManagerService getMailTemplateManagerService() throws IOException {
         synchronized (MAIL_TEMPLATE_MONITOR) {
             ConnectionParams connParams = getConnectionParams();
diff --git a/ide/netbeans/src/main/java/org/apache/syncope/ide/netbeans/service/ImplementationManagerService.java b/ide/netbeans/src/main/java/org/apache/syncope/ide/netbeans/service/ImplementationManagerService.java
index b8f7621..96d8517 100644
--- a/ide/netbeans/src/main/java/org/apache/syncope/ide/netbeans/service/ImplementationManagerService.java
+++ b/ide/netbeans/src/main/java/org/apache/syncope/ide/netbeans/service/ImplementationManagerService.java
@@ -23,7 +23,6 @@ import javax.ws.rs.core.Response;
 import org.apache.syncope.client.lib.SyncopeClient;
 import org.apache.syncope.client.lib.SyncopeClientFactoryBean;
 import org.apache.syncope.common.lib.to.ImplementationTO;
-import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.common.rest.api.service.ImplementationService;
 
 public class ImplementationManagerService {
@@ -35,11 +34,11 @@ public class ImplementationManagerService {
         service = syncopeClient.getService(ImplementationService.class);
     }
 
-    public List<ImplementationTO> list(final ImplementationType type) {
+    public List<ImplementationTO> list(final String type) {
         return service.list(type);
     }
 
-    public ImplementationTO read(final ImplementationType type, final String key) {
+    public ImplementationTO read(final String type, final String key) {
         return service.read(type, key);
     }
 
@@ -47,7 +46,7 @@ public class ImplementationManagerService {
         return Response.Status.CREATED.getStatusCode() == service.create(implementationTO).getStatus();
     }
 
-    public boolean delete(final ImplementationType type, final String key) {
+    public boolean delete(final String type, final String key) {
         return Response.Status.NO_CONTENT.getStatusCode() == service.delete(type, key).getStatus();
     }
 
diff --git a/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/init/OIDCClientLoader.java b/ide/netbeans/src/main/java/org/apache/syncope/ide/netbeans/service/SyncopeManagerService.java
similarity index 53%
copy from ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/init/OIDCClientLoader.java
copy to ide/netbeans/src/main/java/org/apache/syncope/ide/netbeans/service/SyncopeManagerService.java
index 847905f..4e8697a 100644
--- a/ext/oidcclient/logic/src/main/java/org/apache/syncope/core/logic/init/OIDCClientLoader.java
+++ b/ide/netbeans/src/main/java/org/apache/syncope/ide/netbeans/service/SyncopeManagerService.java
@@ -16,23 +16,23 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.core.logic.init;
+package org.apache.syncope.ide.netbeans.service;
 
-import org.apache.syncope.common.lib.types.OIDCClientEntitlement;
-import org.apache.syncope.core.persistence.api.SyncopeCoreLoader;
-import org.apache.syncope.core.provisioning.api.EntitlementsHolder;
-import org.springframework.stereotype.Component;
+import java.util.Set;
+import org.apache.syncope.client.lib.SyncopeClient;
+import org.apache.syncope.client.lib.SyncopeClientFactoryBean;
+import org.apache.syncope.common.rest.api.service.SyncopeService;
 
-@Component
-public class OIDCClientLoader implements SyncopeCoreLoader {
+public class SyncopeManagerService {
 
-    @Override
-    public int getOrder() {
-        return 1000;
+    private final SyncopeService service;
+
+    public SyncopeManagerService(final String url, final String userName, final String password) {
+        SyncopeClient syncopeClient = new SyncopeClientFactoryBean().setAddress(url).create(userName, password);
+        service = syncopeClient.getService(SyncopeService.class);
     }
 
-    @Override
-    public void load() {
-        EntitlementsHolder.getInstance().init(OIDCClientEntitlement.values());
+    public Set<String> getImplementationTypes() {
+        return service.platform().getImplementationTypes();
     }
 }
diff --git a/ide/netbeans/src/main/java/org/apache/syncope/ide/netbeans/view/ResourceExplorerTopComponent.java b/ide/netbeans/src/main/java/org/apache/syncope/ide/netbeans/view/ResourceExplorerTopComponent.java
index 8eb17cd..4f5bccd 100644
--- a/ide/netbeans/src/main/java/org/apache/syncope/ide/netbeans/view/ResourceExplorerTopComponent.java
+++ b/ide/netbeans/src/main/java/org/apache/syncope/ide/netbeans/view/ResourceExplorerTopComponent.java
@@ -20,15 +20,13 @@ package org.apache.syncope.ide.netbeans.view;
 
 import java.awt.Image;
 import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
 import java.awt.event.MouseEvent;
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
 import java.io.File;
 import java.io.FileWriter;
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
 import java.util.List;
 import java.util.logging.Level;
 import java.util.logging.Logger;
@@ -48,15 +46,17 @@ import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.to.MailTemplateTO;
 import org.apache.syncope.common.lib.to.ReportTemplateTO;
 import org.apache.syncope.common.lib.to.ImplementationTO;
+import org.apache.syncope.common.lib.types.IdMImplementationType;
+import org.apache.syncope.common.lib.types.IdRepoImplementationType;
 import org.apache.syncope.common.lib.types.MailTemplateFormat;
 import org.apache.syncope.common.lib.types.ReportTemplateFormat;
-import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.common.lib.types.ImplementationEngine;
 import org.apache.syncope.ide.netbeans.PluginConstants;
 import org.apache.syncope.ide.netbeans.ResourceConnector;
 import org.apache.syncope.ide.netbeans.service.MailTemplateManagerService;
 import org.apache.syncope.ide.netbeans.service.ReportTemplateManagerService;
 import org.apache.syncope.ide.netbeans.service.ImplementationManagerService;
+import org.apache.syncope.ide.netbeans.service.SyncopeManagerService;
 import org.netbeans.api.editor.EditorRegistry;
 import org.netbeans.api.progress.ProgressHandle;
 import org.netbeans.api.settings.ConvertAsProperties;
@@ -66,7 +66,6 @@ import org.openide.cookies.OpenCookie;
 import org.openide.filesystems.FileObject;
 import org.openide.filesystems.FileUtil;
 import org.openide.loaders.DataObject;
-import org.openide.util.Cancellable;
 import org.openide.util.Exceptions;
 import org.openide.util.NbPreferences;
 import org.openide.util.RequestProcessor;
@@ -111,6 +110,8 @@ public final class ResourceExplorerTopComponent extends TopComponent {
 
     private final DefaultMutableTreeNode groovyScripts;
 
+    private SyncopeManagerService syncopeManagerService;
+
     private MailTemplateManagerService mailTemplateManagerService;
 
     private ReportTemplateManagerService reportTemplateManagerService;
@@ -243,9 +244,11 @@ public final class ResourceExplorerTopComponent extends TopComponent {
                 || StringUtils.isBlank(prefs.get("port", null))
                 || StringUtils.isBlank(prefs.get("username", null))
                 || StringUtils.isBlank(prefs.get("password", null))) {
+
             new ServerDetailsView(null, true).setVisible(true);
         }
         try {
+            syncopeManagerService = ResourceConnector.getSyncopeManagerService();
             mailTemplateManagerService = ResourceConnector.getMailTemplateManagerService();
             reportTemplateManagerService = ResourceConnector.getReportTemplateManagerService();
             implementationManagerService = ResourceConnector.getImplementationManagerService();
@@ -253,32 +256,20 @@ public final class ResourceExplorerTopComponent extends TopComponent {
             initTemplatesTree();
             // Load templates
             LOG.info("Loading Apache Syncope templates...");
-            Runnable tsk = new Runnable() {
-
-                @Override
-                public void run() {
-
-                    final ProgressHandle progr = ProgressHandle.createHandle("Loading Templates", new Cancellable() {
-
-                        @Override
-                        public boolean cancel() {
-                            return true;
-                        }
-                    });
-
-                    progr.start();
-                    progr.progress("Loading Templates.");
-                    addMailTemplates();
-                    addReportXslts();
-                    addGroovyScripts();
-                    progr.finish();
-                }
-
+            Runnable tsk = () -> {
+                final ProgressHandle progr = ProgressHandle.createHandle("Loading Templates", () -> true);
+
+                progr.start();
+                progr.progress("Loading Templates.");
+                addMailTemplates();
+                addReportXslts();
+                addGroovyScripts();
+                progr.finish();
             };
             REQUEST_PROCESSOR.post(tsk);
         } catch (IOException e) {
             JOptionPane.showMessageDialog(null, e.getMessage(), "Generic Error", JOptionPane.ERROR_MESSAGE);
-            ServerDetailsView serverDetails = getRefreshServerDetails();
+            getRefreshServerDetails();
         } catch (Exception ex) {
             getRefreshServerDetails().setVisible(true);
         }
@@ -304,38 +295,33 @@ public final class ResourceExplorerTopComponent extends TopComponent {
 
     private void addMailTemplates() {
         List<MailTemplateTO> mailTemplateList = mailTemplateManagerService.list();
-        for (MailTemplateTO mailTemplate : mailTemplateList) {
-            this.mailTemplates.add(new DefaultMutableTreeNode(
-                    mailTemplate.getKey()));
-        }
+        mailTemplateList.forEach(mailTemplate -> {
+            this.mailTemplates.add(new DefaultMutableTreeNode(mailTemplate.getKey()));
+        });
         treeModel.reload();
     }
 
     private void addReportXslts() {
         List<ReportTemplateTO> reportTemplates = reportTemplateManagerService.list();
-        for (ReportTemplateTO reportTemplate : reportTemplates) {
-            reportXslts.add(new DefaultMutableTreeNode(
-                    reportTemplate.getKey()));
-        }
+        reportTemplates.forEach(reportTemplate -> {
+            reportXslts.add(new DefaultMutableTreeNode(reportTemplate.getKey()));
+        });
         treeModel.reload();
     }
 
     private void addGroovyScripts() {
-        for (ImplementationType type : ImplementationType.values()) {
-            String implType = type.toString();
-            DefaultMutableTreeNode tempNode = new DefaultMutableTreeNode(implType.toString());
-            if (implType.equals("JWT_SSO_PROVIDER") || implType.equals("AUDIT_APPENDER")) {
-                continue;
-            }
-            List<ImplementationTO> scripts = implementationManagerService.list(type);
-            for (ImplementationTO script : scripts) {
-                if (script.getEngine() == ImplementationEngine.GROOVY) {
-                    tempNode.add(new DefaultMutableTreeNode(
-                            script.getKey()));
-                }
-            }
-            groovyScripts.add(tempNode);
-        }
+        syncopeManagerService.getImplementationTypes().stream().
+                filter(type -> !IdRepoImplementationType.JWT_SSO_PROVIDER.equals(type)
+                && !IdRepoImplementationType.AUDIT_APPENDER.equals(type)).
+                forEach(type -> {
+
+                    DefaultMutableTreeNode tempNode = new DefaultMutableTreeNode(type);
+                    List<ImplementationTO> scripts = implementationManagerService.list(type);
+                    scripts.stream().
+                            filter((script) -> (script.getEngine() == ImplementationEngine.GROOVY)).
+                            forEach(script -> tempNode.add(new DefaultMutableTreeNode(script.getKey())));
+                    groovyScripts.add(tempNode);
+                });
 
         treeModel.reload();
     }
@@ -347,176 +333,154 @@ public final class ResourceExplorerTopComponent extends TopComponent {
         menu.add(refreshItem);
         menu.add(resetConnectionItem);
 
-        refreshItem.addActionListener(new ActionListener() {
-
-            @Override
-            public void actionPerformed(final ActionEvent e) {
-                // simulate close and open to refresh the tree
-                componentClosed();
-                componentOpened();
-            }
+        refreshItem.addActionListener(event -> {
+            // simulate close and open to refresh the tree
+            componentClosed();
+            componentOpened();
         });
 
-        resetConnectionItem.addActionListener(new ActionListener() {
-
-            @Override
-            public void actionPerformed(final ActionEvent evt) {
-                ServerDetailsView serverDetails = getRefreshServerDetails();
-                // set previous preferences
-                Preferences prefs = NbPreferences.forModule(ResourceExplorerTopComponent.class);
-                serverDetails.setDetails(prefs.get("scheme", "http"),
-                        prefs.get("host", "localhost"),
-                        prefs.get("port", "8080"),
-                        prefs.get("username", StringUtils.EMPTY),
-                        prefs.get("password", StringUtils.EMPTY));
-                // reset connection preferences
-                prefs.remove("scheme");
-                prefs.remove("host");
-                prefs.remove("port");
-                prefs.remove("username");
-                prefs.remove("password");
-                serverDetails.setVisible(true);
-            }
+        resetConnectionItem.addActionListener(event -> {
+            ServerDetailsView serverDetails = getRefreshServerDetails();
+            // set previous preferences
+            Preferences prefs = NbPreferences.forModule(ResourceExplorerTopComponent.class);
+            serverDetails.setDetails(prefs.get("scheme", "http"),
+                    prefs.get("host", "localhost"),
+                    prefs.get("port", "8080"),
+                    prefs.get("username", StringUtils.EMPTY),
+                    prefs.get("password", StringUtils.EMPTY));
+            // reset connection preferences
+            prefs.remove("scheme");
+            prefs.remove("host");
+            prefs.remove("port");
+            prefs.remove("username");
+            prefs.remove("password");
+            serverDetails.setVisible(true);
         });
 
         menu.show(evt.getComponent(), evt.getX(), evt.getY());
     }
 
-    private void folderRightClickAction(final MouseEvent evt,
-            final DefaultMutableTreeNode node) {
+    private void folderRightClickAction(final MouseEvent evt, final DefaultMutableTreeNode node) {
         JPopupMenu menu = new JPopupMenu();
         JMenuItem addItem = new JMenuItem("New");
         menu.add(addItem);
 
-        addItem.addActionListener(new ActionListener() {
-
-            @Override
-            public void actionPerformed(final ActionEvent event) {
-                try {
-                    String name = JOptionPane.showInputDialog("Enter Name");
-                    if (StringUtils.isBlank(name)) {
-                        return;
-                    }
-
-                    DefaultMutableTreeNode parent = (DefaultMutableTreeNode) node.getParent();
-                    boolean added = false;
-
-                    if (!"exit".equals(event.getActionCommand())) {
-                        if (PluginConstants.MAIL_TEMPLATES.equals(node.getUserObject())) {
-
-                            MailTemplateTO mailTemplate = new MailTemplateTO();
-                            mailTemplate.setKey(name);
-                            added = mailTemplateManagerService.create(mailTemplate);
-                            mailTemplateManagerService.setFormat(name,
-                                    MailTemplateFormat.HTML,
-                                    IOUtils.toInputStream("//Enter Content here", encodingPattern));
-                            mailTemplateManagerService.setFormat(name,
-                                    MailTemplateFormat.TEXT,
-                                    IOUtils.toInputStream("//Enter Content here", encodingPattern));
-                            openMailEditor(name);
-                        } else if (PluginConstants.GROOVY_SCRIPTS.equals(parent.getUserObject())) {
-                            ImplementationTO newNode = new ImplementationTO();
-                            ImplementationType type = getType((String) node.getUserObject());
-                            newNode.setKey(name);
-                            newNode.setEngine(ImplementationEngine.GROOVY);
-                            newNode.setType(type);
-                            String templateClassName = null;
-                            switch (type) {
-                                case REPORTLET:
-                                    templateClassName = "MyReportlet";
-                                    break;
-
-                                case ACCOUNT_RULE:
-                                    templateClassName = "MyAccountRule";
-                                    break;
-
-                                case PASSWORD_RULE:
-                                    templateClassName = "MyPasswordRule";
-                                    break;
-
-                                case ITEM_TRANSFORMER:
-                                    templateClassName = "MyItemTransformer";
-                                    break;
-
-                                case TASKJOB_DELEGATE:
-                                    templateClassName = "MySchedTaskJobDelegate";
-                                    break;
-
-                                case RECON_FILTER_BUILDER:
-                                    templateClassName = "MyReconFilterBuilder";
-                                    break;
-
-                                case LOGIC_ACTIONS:
-                                    templateClassName = "MyLogicActions";
-                                    break;
-
-                                case PROPAGATION_ACTIONS:
-                                    templateClassName = "MyPropagationActions";
-                                    break;
-
-                                case PULL_ACTIONS:
-                                    templateClassName = "MyPullActions";
-                                    break;
-
-                                case PUSH_ACTIONS:
-                                    templateClassName = "MyPushActions";
-                                    break;
-
-                                case PULL_CORRELATION_RULE:
-                                    templateClassName = "MyPullCorrelationRule";
-                                    break;
-
-                                case PUSH_CORRELATION_RULE:
-                                    templateClassName = "MyPushCorrelationRule";
-                                    break;
-
-                                case VALIDATOR:
-                                    templateClassName = "MyValidator";
-                                    break;
-
-                                case RECIPIENTS_PROVIDER:
-                                    templateClassName = "MyRecipientsProvider";
-                                    break;
-
-                                default:
-                            }
-                            newNode.setBody(IOUtils.toString(
-                                    getClass().getResourceAsStream("/org/apache/syncope/ide/netbeans/implementations/"
-                                            + templateClassName + ".groovy")));
-                            added = implementationManagerService.create(newNode);
-                            openScriptEditor(name, (String) node.getUserObject());
-                        } else {
-                            ReportTemplateTO reportTemplate = new ReportTemplateTO();
-                            reportTemplate.setKey(name);
-                            added = reportTemplateManagerService.create(reportTemplate);
-                            reportTemplateManagerService.setFormat(name,
-                                    ReportTemplateFormat.FO,
-                                    IOUtils.toInputStream("//Enter content here", encodingPattern));
-                            reportTemplateManagerService.setFormat(name,
-                                    ReportTemplateFormat.CSV,
-                                    IOUtils.toInputStream("//Enter content here", encodingPattern));
-                            reportTemplateManagerService.setFormat(name,
-                                    ReportTemplateFormat.HTML,
-                                    IOUtils.toInputStream("//Enter content here", encodingPattern));
-                            openReportEditor(name);
-                        }
-
-                        if (added) {
-                            node.add(new DefaultMutableTreeNode(name));
-                            treeModel.reload(node);
-                        } else {
-                            JOptionPane.showMessageDialog(
-                                    null, "Error while creating new element", "Error", JOptionPane.ERROR_MESSAGE);
+        addItem.addActionListener(event -> {
+            try {
+                String name1 = JOptionPane.showInputDialog("Enter Name");
+                if (StringUtils.isBlank(name1)) {
+                    return;
+                }
+                DefaultMutableTreeNode parent1 = (DefaultMutableTreeNode) node.getParent();
+                if (!"exit".equals(event.getActionCommand())) {
+                    boolean added;
+                    if (PluginConstants.MAIL_TEMPLATES.equals(node.getUserObject())) {
+                        MailTemplateTO mailTemplate = new MailTemplateTO();
+                        mailTemplate.setKey(name1);
+                        added = mailTemplateManagerService.create(mailTemplate);
+                        mailTemplateManagerService.setFormat(name1, MailTemplateFormat.HTML,
+                                IOUtils.toInputStream("//Enter Content here", encodingPattern));
+                        mailTemplateManagerService.setFormat(name1, MailTemplateFormat.TEXT,
+                                IOUtils.toInputStream("//Enter Content here", encodingPattern));
+                        openMailEditor(name1);
+                    } else if (PluginConstants.GROOVY_SCRIPTS.equals(parent1.getUserObject())) {
+                        ImplementationTO newNode = new ImplementationTO();
+                        String type = (String) node.getUserObject();
+                        newNode.setKey(name1);
+                        newNode.setEngine(ImplementationEngine.GROOVY);
+                        newNode.setType(type);
+                        String templateClassName = null;
+                        switch (type) {
+                            case IdRepoImplementationType.REPORTLET:
+                                templateClassName = "MyReportlet";
+                                break;
+
+                            case IdRepoImplementationType.ACCOUNT_RULE:
+                                templateClassName = "MyAccountRule";
+                                break;
+
+                            case IdRepoImplementationType.PASSWORD_RULE:
+                                templateClassName = "MyPasswordRule";
+                                break;
+
+                            case IdMImplementationType.ITEM_TRANSFORMER:
+                                templateClassName = "MyItemTransformer";
+                                break;
+
+                            case IdRepoImplementationType.TASKJOB_DELEGATE:
+                                templateClassName = "MySchedTaskJobDelegate";
+                                break;
+
+                            case IdMImplementationType.RECON_FILTER_BUILDER:
+                                templateClassName = "MyReconFilterBuilder";
+                                break;
+
+                            case IdRepoImplementationType.LOGIC_ACTIONS:
+                                templateClassName = "MyLogicActions";
+                                break;
+
+                            case IdMImplementationType.PROPAGATION_ACTIONS:
+                                templateClassName = "MyPropagationActions";
+                                break;
+
+                            case IdMImplementationType.PULL_ACTIONS:
+                                templateClassName = "MyPullActions";
+                                break;
+
+                            case IdMImplementationType.PUSH_ACTIONS:
+                                templateClassName = "MyPushActions";
+                                break;
+
+                            case IdMImplementationType.PULL_CORRELATION_RULE:
+                                templateClassName = "MyPullCorrelationRule";
+                                break;
+
+                            case IdMImplementationType.PUSH_CORRELATION_RULE:
+                                templateClassName = "MyPushCorrelationRule";
+                                break;
+
+                            case IdRepoImplementationType.VALIDATOR:
+                                templateClassName = "MyValidator";
+                                break;
+
+                            case IdRepoImplementationType.RECIPIENTS_PROVIDER:
+                                templateClassName = "MyRecipientsProvider";
+                                break;
+
+                            default:
                         }
+                        newNode.setBody(IOUtils.toString(getClass().getResourceAsStream(
+                                "/org/apache/syncope/ide/netbeans/implementations/" + templateClassName + ".groovy"),
+                                StandardCharsets.UTF_8));
+                        added = implementationManagerService.create(newNode);
+                        openScriptEditor(name1, (String) node.getUserObject());
+                    } else {
+                        ReportTemplateTO reportTemplate = new ReportTemplateTO();
+                        reportTemplate.setKey(name1);
+                        added = reportTemplateManagerService.create(reportTemplate);
+                        reportTemplateManagerService.setFormat(name1, ReportTemplateFormat.FO,
+                                IOUtils.toInputStream("//Enter content here", encodingPattern));
+                        reportTemplateManagerService.setFormat(name1, ReportTemplateFormat.CSV,
+                                IOUtils.toInputStream("//Enter content here", encodingPattern));
+                        reportTemplateManagerService.setFormat(name1, ReportTemplateFormat.HTML,
+                                IOUtils.toInputStream("//Enter content here", encodingPattern));
+                        openReportEditor(name1);
+                    }
+                    if (added) {
+                        node.add(new DefaultMutableTreeNode(name1));
+                        treeModel.reload(node);
+                    } else {
+                        JOptionPane.showMessageDialog(
+                                null, "Error while creating new element", "Error", JOptionPane.ERROR_MESSAGE);
                     }
-                } catch (SyncopeClientException excp) {
-                    JOptionPane.showMessageDialog(null, excp.getMessage(), "Syncope Error", JOptionPane.ERROR_MESSAGE);
-                } catch (IOException ex) {
-                    JOptionPane.showMessageDialog(null, ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
-                } catch (Exception exc) {
-                    LOG.log(Level.WARNING, "Refreshing after exception");
-                    getRefreshServerDetails().setVisible(true);
                 }
+            } catch (SyncopeClientException sce) {
+                JOptionPane.showMessageDialog(null, sce.getMessage(), "Syncope Error", JOptionPane.ERROR_MESSAGE);
+            } catch (IOException ioe) {
+                JOptionPane.showMessageDialog(null, ioe.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
+            } catch (Exception e) {
+                LOG.log(Level.WARNING, "Refreshing after exception", e);
+                getRefreshServerDetails().setVisible(true);
             }
         });
 
@@ -529,37 +493,33 @@ public final class ResourceExplorerTopComponent extends TopComponent {
         JMenuItem deleteItem = new JMenuItem("Delete");
         menu.add(deleteItem);
 
-        deleteItem.addActionListener(new ActionListener() {
-
-            @Override
-            public void actionPerformed(final ActionEvent e) {
-                int result = JOptionPane.showConfirmDialog(null, "Are you sure to delete the item?");
-                if (result == JOptionPane.OK_OPTION) {
-                    DefaultMutableTreeNode parent = (DefaultMutableTreeNode) node.getParent();
-                    String nodeName = (String) node.getUserObject();
-                    boolean deleted = false;
-                    try {
-                        if (PluginConstants.MAIL_TEMPLATES.equals(parent.getUserObject())) {
-                            deleted = mailTemplateManagerService.delete(nodeName);
-                        } else if (PluginConstants.REPORT_XSLTS.equals(parent.getUserObject())) {
-                            deleted = reportTemplateManagerService.delete(nodeName);
-                        } else {
-                            ImplementationType type = getType((String) parent.getUserObject());
-                            deleted = implementationManagerService.delete(type, nodeName);
-                        }
-                        if (deleted) {
-                            node.removeFromParent();
-                            treeModel.reload(parent);
-                        } else {
-                            JOptionPane.showMessageDialog(
-                                    null, "Error while deleting new element", "Error", JOptionPane.ERROR_MESSAGE);
-                        }
-                    } catch (SyncopeClientException exc) {
+        deleteItem.addActionListener(event -> {
+            int result = JOptionPane.showConfirmDialog(null, "Are you sure to delete the item?");
+            if (result == JOptionPane.OK_OPTION) {
+                DefaultMutableTreeNode parent1 = (DefaultMutableTreeNode) node.getParent();
+                String nodeName1 = (String) node.getUserObject();
+                try {
+                    boolean deleted;
+                    if (PluginConstants.MAIL_TEMPLATES.equals(parent1.getUserObject())) {
+                        deleted = mailTemplateManagerService.delete(nodeName1);
+                    } else if (PluginConstants.REPORT_XSLTS.equals(parent1.getUserObject())) {
+                        deleted = reportTemplateManagerService.delete(nodeName1);
+                    } else {
+                        String type = (String) parent1.getUserObject();
+                        deleted = implementationManagerService.delete(type, nodeName1);
+                    }
+                    if (deleted) {
+                        node.removeFromParent();
+                        treeModel.reload(parent1);
+                    } else {
                         JOptionPane.showMessageDialog(
-                                null, exc.getMessage(), "Syncope Error", JOptionPane.ERROR_MESSAGE);
-                    } catch (Exception ex) {
-                        getRefreshServerDetails().setVisible(true);
+                                null, "Error while deleting new element", "Error", JOptionPane.ERROR_MESSAGE);
                     }
+                } catch (SyncopeClientException exc) {
+                    JOptionPane.showMessageDialog(
+                            null, exc.getMessage(), "Syncope Error", JOptionPane.ERROR_MESSAGE);
+                } catch (Exception ex) {
+                    getRefreshServerDetails().setVisible(true);
                 }
             }
         });
@@ -605,24 +565,19 @@ public final class ResourceExplorerTopComponent extends TopComponent {
             fob.setAttribute("description", "TEXT");
             DataObject data = DataObject.find(fob);
             data.getLookup().lookup(OpenCookie.class).open();
-            data.addPropertyChangeListener(new PropertyChangeListener() {
-
-                @Override
-                public void propertyChange(final PropertyChangeEvent evt) {
-                    if (DataObject.PROP_MODIFIED.equals(evt.getPropertyName())) {
-                        //save item remotely
-                        LOG.info(String.format("Saving Mail template [%s]", name));
-                        saveContent();
-                    }
+            data.addPropertyChangeListener(event -> {
+                if (DataObject.PROP_MODIFIED.equals(event.getPropertyName())) {
+                    //save item remotely
+                    LOG.info(String.format("Saving Mail template [%s]", name));
+                    saveContent();
                 }
             });
         }
     }
 
     private void openScriptEditor(final String name, final String type) throws IOException {
-        ImplementationTO node = implementationManagerService.read(getType(type), name);
-        String groovyScriptsDirName = System.getProperty("java.io.tmpdir") + "/Groovy/"
-                + node.getType().toString() + "/";
+        ImplementationTO node = implementationManagerService.read(type, name);
+        String groovyScriptsDirName = System.getProperty("java.io.tmpdir") + "/Groovy/" + node.getType() + "/";
         File groovyScriptsDir = new File(groovyScriptsDirName);
         if (!groovyScriptsDir.exists()) {
             groovyScriptsDir.mkdirs();
@@ -634,18 +589,13 @@ public final class ResourceExplorerTopComponent extends TopComponent {
         FileObject fob = FileUtil.toFileObject(file.getAbsoluteFile());
         DataObject data = DataObject.find(fob);
         data.getLookup().lookup(OpenCookie.class).open();
-        data.addPropertyChangeListener(new PropertyChangeListener() {
-
-            @Override
-            public void propertyChange(final PropertyChangeEvent evt) {
-                if (DataObject.PROP_MODIFIED.equals(evt.getPropertyName())) {
-                    //save item remotely
-                    LOG.info(String.format("Saving Groovy template [%s]", name));
-                    saveContent();
-                }
+        data.addPropertyChangeListener(event -> {
+            if (DataObject.PROP_MODIFIED.equals(event.getPropertyName())) {
+                //save item remotely
+                LOG.info(String.format("Saving Groovy template [%s]", name));
+                saveContent();
             }
         });
-
     }
 
     private void openReportEditor(final String name) throws IOException {
@@ -685,15 +635,11 @@ public final class ResourceExplorerTopComponent extends TopComponent {
             FileObject fob = FileUtil.toFileObject(file.getAbsoluteFile());
             DataObject data = DataObject.find(fob);
             data.getLookup().lookup(OpenCookie.class).open();
-            data.addPropertyChangeListener(new PropertyChangeListener() {
-
-                @Override
-                public void propertyChange(final PropertyChangeEvent evt) {
-                    if (DataObject.PROP_MODIFIED.equals(evt.getPropertyName())) {
-                        //save item remotely
-                        LOG.info(String.format("Saving Report template [%s]", name));
-                        saveContent();
-                    }
+            data.addPropertyChangeListener(event -> {
+                if (DataObject.PROP_MODIFIED.equals(event.getPropertyName())) {
+                    //save item remotely
+                    LOG.info(String.format("Saving Report template [%s]", name));
+                    saveContent();
                 }
             });
         }
@@ -736,7 +682,7 @@ public final class ResourceExplorerTopComponent extends TopComponent {
                         ReportTemplateFormat.CSV,
                         IOUtils.toInputStream(content, encodingPattern));
             } else if ("Groovy".equals(fileName)) {
-                ImplementationTO node = implementationManagerService.read(getType(templateType), key);
+                ImplementationTO node = implementationManagerService.read(templateType, key);
                 node.setBody(content);
                 implementationManagerService.update(node);
             }
@@ -747,24 +693,6 @@ public final class ResourceExplorerTopComponent extends TopComponent {
         }
     }
 
-    private ImplementationType getType(final String typeName) {
-        ImplementationType type = null;
-        for (ImplementationType implType : ImplementationType.values()) {
-            if (implType.toString().equals(typeName)) {
-                type = implType;
-            }
-
-        }
-        return (type);
-    }
-
-    private void closeComponent() {
-        boolean isClosed = this.close();
-        if (!isClosed) {
-            LOG.log(Level.SEVERE, "Unable to close {0}", getClass().getSimpleName());
-        }
-    }
-
     private void initTemplatesTree() {
         visibleRoot.add(mailTemplates);
         visibleRoot.add(reportXslts);