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 2015/06/05 17:11:36 UTC

[01/21] syncope git commit: [SYNCOPE-660] Added console utilities for runtime task management

Repository: syncope
Updated Branches:
  refs/heads/SYNCOPE-666 79b1e80aa -> dd88efbd0


[SYNCOPE-660] Added console utilities for runtime task management


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

Branch: refs/heads/SYNCOPE-666
Commit: 790704c08790f8a2536af84ed46290f1596851f0
Parents: f672ce4
Author: giacomolm <gi...@hotmail.it>
Authored: Thu May 28 17:27:12 2015 +0200
Committer: giacomolm <gi...@hotmail.it>
Committed: Fri May 29 10:30:57 2015 +0200

----------------------------------------------------------------------
 .../apache/syncope/console/pages/Reports.java   |  11 ++
 .../org/apache/syncope/console/pages/Tasks.java |  15 ++-
 .../console/pages/panels/NotificationTasks.java |   4 +
 .../console/pages/panels/RuntimePanel.java      | 105 +++++++++++++++++++
 .../console/pages/panels/SchedTasks.java        |   6 ++
 .../console/pages/panels/SyncTasksPanel.java    |   4 +
 .../syncope/console/rest/JobRestClient.java     |  31 ++++++
 .../syncope/console/rest/ReportRestClient.java  |  25 ++++-
 .../syncope/console/rest/TaskRestClient.java    |  23 +++-
 .../html/repeater/data/table/JobColumn.java     |  94 +++++++++++++++++
 .../apache/syncope/console/pages/Reports.html   |  13 +++
 .../org/apache/syncope/console/pages/Tasks.html |  15 +++
 .../console/pages/panels/RuntimePanel.html      |  49 +++++++++
 .../rest/controller/AbstractJobController.java  |  15 ++-
 14 files changed, 404 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/790704c0/console/src/main/java/org/apache/syncope/console/pages/Reports.java
----------------------------------------------------------------------
diff --git a/console/src/main/java/org/apache/syncope/console/pages/Reports.java b/console/src/main/java/org/apache/syncope/console/pages/Reports.java
index 3f09762..88fdf1c 100644
--- a/console/src/main/java/org/apache/syncope/console/pages/Reports.java
+++ b/console/src/main/java/org/apache/syncope/console/pages/Reports.java
@@ -38,6 +38,7 @@ import org.apache.syncope.console.rest.LoggerRestClient;
 import org.apache.syncope.console.wicket.ajax.markup.html.ClearIndicatingAjaxLink;
 import org.apache.syncope.console.wicket.extensions.markup.html.repeater.data.table.ActionColumn;
 import org.apache.syncope.console.wicket.extensions.markup.html.repeater.data.table.DatePropertyColumn;
+import org.apache.syncope.console.wicket.extensions.markup.html.repeater.data.table.JobColumn;
 import org.apache.syncope.console.wicket.markup.html.form.ActionLink;
 import org.apache.syncope.console.wicket.markup.html.form.ActionLinksPanel;
 import org.apache.wicket.Component;
@@ -61,6 +62,7 @@ import org.apache.wicket.model.IModel;
 import org.apache.wicket.model.Model;
 import org.apache.wicket.model.PropertyModel;
 import org.apache.wicket.model.ResourceModel;
+import org.apache.wicket.model.StringResourceModel;
 import org.apache.wicket.model.util.ListModel;
 import org.apache.wicket.request.mapper.parameter.PageParameters;
 import org.apache.wicket.spring.injection.annot.SpringBean;
@@ -123,6 +125,8 @@ public class Reports extends BasePage {
         columns.add(new DatePropertyColumn<ReportTO>(new ResourceModel("endDate"), "endDate", "endDate"));
         columns.add(new PropertyColumn<ReportTO, String>(
                 new ResourceModel("latestExecStatus"), "latestExecStatus", "latestExecStatus"));
+        columns.add(new JobColumn<ReportTO, String>(new StringResourceModel("", this, null, ""), "runtime",
+                getPageReference(), reportRestClient));
         columns.add(new ActionColumn<ReportTO, String>(new ResourceModel("actions", "")) {
 
             private static final long serialVersionUID = 2054811145491901166L;
@@ -411,4 +415,11 @@ public class Reports extends BasePage {
             };
         }
     }
+    /**
+     * IndicatorMarkupId behaviour is embedded in Reports.html
+     */
+    @Override
+    public String getAjaxIndicatorMarkupId() {
+        return "";
+    }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/790704c0/console/src/main/java/org/apache/syncope/console/pages/Tasks.java
----------------------------------------------------------------------
diff --git a/console/src/main/java/org/apache/syncope/console/pages/Tasks.java b/console/src/main/java/org/apache/syncope/console/pages/Tasks.java
index aae3622..11819c6 100644
--- a/console/src/main/java/org/apache/syncope/console/pages/Tasks.java
+++ b/console/src/main/java/org/apache/syncope/console/pages/Tasks.java
@@ -152,10 +152,10 @@ public class Tasks extends BasePage {
         @Override
         public Iterator<T> iterator(final long first, final long count) {
             final List<T> tasks = new ArrayList<T>();
-            
+
             final int page = ((int) first / paginatorRows);
-            
-            for (T task : restClient.list(reference, (page < 0 ? 0 : page)  + 1, paginatorRows, getSort())) {
+
+            for (T task : restClient.list(reference, (page < 0 ? 0 : page) + 1, paginatorRows, getSort())) {
                 if (task instanceof SchedTaskTO && ((SchedTaskTO) task).getLastExec() == null
                         && task.getExecutions() != null && !task.getExecutions().isEmpty()) {
 
@@ -227,4 +227,13 @@ public class Tasks extends BasePage {
 
         return table;
     }
+
+    /**
+     * IndicatorMarkupId behaviour is embedded in Tasks.html
+     */
+    @Override
+    public String getAjaxIndicatorMarkupId() {
+        return "";
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/790704c0/console/src/main/java/org/apache/syncope/console/pages/panels/NotificationTasks.java
----------------------------------------------------------------------
diff --git a/console/src/main/java/org/apache/syncope/console/pages/panels/NotificationTasks.java b/console/src/main/java/org/apache/syncope/console/pages/panels/NotificationTasks.java
index 86fd7bc..9c7b458 100644
--- a/console/src/main/java/org/apache/syncope/console/pages/panels/NotificationTasks.java
+++ b/console/src/main/java/org/apache/syncope/console/pages/panels/NotificationTasks.java
@@ -28,6 +28,7 @@ import org.apache.syncope.console.pages.NotificationTaskModalPage;
 import org.apache.syncope.console.pages.Tasks;
 import org.apache.syncope.console.pages.Tasks.TasksProvider;
 import org.apache.syncope.console.wicket.extensions.markup.html.repeater.data.table.ActionColumn;
+import org.apache.syncope.console.wicket.extensions.markup.html.repeater.data.table.JobColumn;
 import org.apache.syncope.console.wicket.markup.html.form.ActionLink;
 import org.apache.syncope.console.wicket.markup.html.form.ActionLinksPanel;
 import org.apache.wicket.Component;
@@ -152,6 +153,9 @@ public class NotificationTasks extends AbstractTasks {
         columns.add(new PropertyColumn<AbstractTaskTO, String>(
                 new StringResourceModel("latestExecStatus", this, null), "latestExecStatus", "latestExecStatus"));
 
+        columns.add(new JobColumn<AbstractTaskTO, String>(new StringResourceModel("", this, null, ""), "runtime",
+                pageRef, restClient)); 
+
         columns.add(new ActionColumn<AbstractTaskTO, String>(new StringResourceModel("actions", this, null, "")) {
 
             private static final long serialVersionUID = 2054811145491901166L;

http://git-wip-us.apache.org/repos/asf/syncope/blob/790704c0/console/src/main/java/org/apache/syncope/console/pages/panels/RuntimePanel.java
----------------------------------------------------------------------
diff --git a/console/src/main/java/org/apache/syncope/console/pages/panels/RuntimePanel.java b/console/src/main/java/org/apache/syncope/console/pages/panels/RuntimePanel.java
new file mode 100644
index 0000000..3bc525c
--- /dev/null
+++ b/console/src/main/java/org/apache/syncope/console/pages/panels/RuntimePanel.java
@@ -0,0 +1,105 @@
+/*
+ * 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.console.pages.panels;
+
+import org.apache.syncope.console.rest.JobRestClient;
+import org.apache.syncope.console.wicket.ajax.markup.html.ClearIndicatingAjaxLink;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AbstractAjaxTimerBehavior;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.markup.html.panel.Fragment;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.markup.html.panel.Panel;
+
+public class RuntimePanel extends Panel {
+
+    private static final long serialVersionUID = -9002724127542172464L;
+
+    private boolean latestStatus;
+
+    private Fragment fragmentStop, fragmentSpinner;
+
+    public AbstractAjaxTimerBehavior timer;
+
+    private final PageReference pageRef;
+
+    private final long jobId;
+
+    private final JobRestClient jobRestClient;
+
+    public RuntimePanel(final String componentId, final IModel<?> model, final PageReference pageRef, final long jobId,
+            final JobRestClient jobRestClient) {
+        super(componentId, model);
+        this.pageRef = pageRef;
+        this.jobId = jobId;
+        this.jobRestClient = jobRestClient;
+        latestStatus = false;
+        this.refresh();
+
+    }
+
+    public final void refresh() {
+        boolean currentStatus = jobRestClient.isJobRunning(jobId);
+        if (currentStatus && !latestStatus) {
+            setRunning();
+        } else if (!currentStatus) {
+            setNotRunning();
+        }
+        latestStatus = currentStatus;
+    }
+
+    public void setRunning() {
+        fragmentStop = new Fragment("panelStop", "fragmentStop", this);
+        fragmentStop.addOrReplace(new ClearIndicatingAjaxLink<Void>("stopLink", pageRef) {
+
+            private static final long serialVersionUID = -7978723352517770644L;
+
+            @Override
+            protected void onClickInternal(final AjaxRequestTarget target) {
+                jobRestClient.stopJob(jobId);
+                this.setEnabled(false);
+                target.add(this);
+            }
+
+            @Override
+            public String getAjaxIndicatorMarkupId() {
+                return "";
+            }
+        });
+        addOrReplace(fragmentStop);
+        fragmentSpinner = new Fragment("panelSpinner", "fragmentSpinner", this);
+        addOrReplace(fragmentSpinner);
+    }
+
+    public void setNotRunning() {
+        fragmentStop = new Fragment("panelStop", "emptyFragment", this);
+        addOrReplace(fragmentStop);
+        fragmentSpinner = new Fragment("panelSpinner", "emptyFragment", this);
+        addOrReplace(fragmentSpinner);
+    }
+
+    public void setTimer(AbstractAjaxTimerBehavior timer) {
+        if (this.timer != null) {
+            remove(this.timer);
+        }
+        this.timer = timer;
+        this.add(this.timer);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/790704c0/console/src/main/java/org/apache/syncope/console/pages/panels/SchedTasks.java
----------------------------------------------------------------------
diff --git a/console/src/main/java/org/apache/syncope/console/pages/panels/SchedTasks.java b/console/src/main/java/org/apache/syncope/console/pages/panels/SchedTasks.java
index f092e55..78591a8 100644
--- a/console/src/main/java/org/apache/syncope/console/pages/panels/SchedTasks.java
+++ b/console/src/main/java/org/apache/syncope/console/pages/panels/SchedTasks.java
@@ -18,6 +18,8 @@
  */
 package org.apache.syncope.console.pages.panels;
 
+import static org.apache.syncope.console.pages.panels.AbstractTasks.TASKS;
+
 import java.util.ArrayList;
 import java.util.List;
 import org.apache.syncope.common.to.SchedTaskTO;
@@ -30,6 +32,7 @@ import org.apache.syncope.console.pages.Tasks.TasksProvider;
 import org.apache.syncope.console.wicket.ajax.markup.html.ClearIndicatingAjaxLink;
 import org.apache.syncope.console.wicket.extensions.markup.html.repeater.data.table.ActionColumn;
 import org.apache.syncope.console.wicket.extensions.markup.html.repeater.data.table.DatePropertyColumn;
+import org.apache.syncope.console.wicket.extensions.markup.html.repeater.data.table.JobColumn;
 import org.apache.syncope.console.wicket.markup.html.form.ActionLink;
 import org.apache.syncope.console.wicket.markup.html.form.ActionLinksPanel;
 import org.apache.wicket.Component;
@@ -167,6 +170,9 @@ public class SchedTasks extends AbstractTasks {
         columns.add(new PropertyColumn<AbstractTaskTO, String>(
                 new StringResourceModel("latestExecStatus", this, null), "latestExecStatus", "latestExecStatus"));
 
+        columns.add(new JobColumn<AbstractTaskTO, String>(new StringResourceModel("", this, null, ""), "runtime",
+                pageRef, restClient)); 
+
         columns.add(new ActionColumn<AbstractTaskTO, String>(new StringResourceModel("actions", this, null, "")) {
 
             private static final long serialVersionUID = 2054811145491901166L;

http://git-wip-us.apache.org/repos/asf/syncope/blob/790704c0/console/src/main/java/org/apache/syncope/console/pages/panels/SyncTasksPanel.java
----------------------------------------------------------------------
diff --git a/console/src/main/java/org/apache/syncope/console/pages/panels/SyncTasksPanel.java b/console/src/main/java/org/apache/syncope/console/pages/panels/SyncTasksPanel.java
index 71fd2b5..032f4e4 100644
--- a/console/src/main/java/org/apache/syncope/console/pages/panels/SyncTasksPanel.java
+++ b/console/src/main/java/org/apache/syncope/console/pages/panels/SyncTasksPanel.java
@@ -29,6 +29,7 @@ import org.apache.syncope.console.pages.SyncTaskModalPage;
 import org.apache.syncope.console.pages.UserTemplateModalPage;
 import org.apache.syncope.console.wicket.extensions.markup.html.repeater.data.table.ActionColumn;
 import org.apache.syncope.console.wicket.extensions.markup.html.repeater.data.table.DatePropertyColumn;
+import org.apache.syncope.console.wicket.extensions.markup.html.repeater.data.table.JobColumn;
 import org.apache.syncope.console.wicket.markup.html.form.ActionLink;
 import org.apache.syncope.console.wicket.markup.html.form.ActionLinksPanel;
 import org.apache.wicket.Component;
@@ -69,6 +70,9 @@ public class SyncTasksPanel extends AbstractSyncTasksPanel<SyncTaskTO> {
                 new StringResourceModel("nextExec", this, null), "nextExec", "nextExec"));
         syncTaskscolumns.add(new PropertyColumn<AbstractTaskTO, String>(
                 new StringResourceModel("latestExecStatus", this, null), "latestExecStatus", "latestExecStatus"));
+        
+        syncTaskscolumns.add(new JobColumn<AbstractTaskTO, String>(new StringResourceModel("", this, null, ""), "runtime",
+                pageRef, restClient));        
 
         syncTaskscolumns.add(
                 new ActionColumn<AbstractTaskTO, String>(new StringResourceModel("actions", this, null, "")) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/790704c0/console/src/main/java/org/apache/syncope/console/rest/JobRestClient.java
----------------------------------------------------------------------
diff --git a/console/src/main/java/org/apache/syncope/console/rest/JobRestClient.java b/console/src/main/java/org/apache/syncope/console/rest/JobRestClient.java
new file mode 100644
index 0000000..de361f3
--- /dev/null
+++ b/console/src/main/java/org/apache/syncope/console/rest/JobRestClient.java
@@ -0,0 +1,31 @@
+/*
+ * 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.console.rest;
+
+import org.springframework.stereotype.Component;
+
+@Component
+public abstract class JobRestClient extends BaseRestClient{
+
+    public abstract boolean isJobRunning(final long id);
+
+    public abstract void startJob(final long id);
+
+    public abstract void stopJob(final long id);
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/790704c0/console/src/main/java/org/apache/syncope/console/rest/ReportRestClient.java
----------------------------------------------------------------------
diff --git a/console/src/main/java/org/apache/syncope/console/rest/ReportRestClient.java b/console/src/main/java/org/apache/syncope/console/rest/ReportRestClient.java
index dff42bf..9b8afdb 100644
--- a/console/src/main/java/org/apache/syncope/console/rest/ReportRestClient.java
+++ b/console/src/main/java/org/apache/syncope/console/rest/ReportRestClient.java
@@ -25,12 +25,15 @@ import org.apache.syncope.common.services.ReportService;
 import org.apache.syncope.common.to.ReportTO;
 import org.apache.syncope.common.types.ReportExecExportFormat;
 import org.apache.syncope.common.SyncopeClientException;
+import org.apache.syncope.common.to.ReportExecTO;
+import org.apache.syncope.common.types.JobAction;
+import org.apache.syncope.common.types.JobStatusType;
 import org.apache.syncope.common.wrap.ReportletConfClass;
 import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;
 import org.springframework.stereotype.Component;
 
 @Component
-public class ReportRestClient extends BaseRestClient implements ExecutionRestClient {
+public class ReportRestClient extends JobRestClient implements ExecutionRestClient {
 
     private static final long serialVersionUID = 1644689667998953604L;
 
@@ -105,4 +108,24 @@ public class ReportRestClient extends BaseRestClient implements ExecutionRestCli
     public Response exportExecutionResult(final Long executionId, final ReportExecExportFormat fmt) {
         return getService(ReportService.class).exportExecutionResult(executionId, fmt);
     }
+
+    @Override
+    public boolean isJobRunning(final long reportId) {
+        for (ReportExecTO reportExecTO : getService(ReportService.class).listJobs(JobStatusType.RUNNING)) {
+            if (reportExecTO.getReport() == reportId) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public void startJob(final long reportId) {
+        getService(ReportService.class).actionJob(reportId, JobAction.START);
+    }
+
+    @Override
+    public void stopJob(final long reportId) {
+        getService(ReportService.class).actionJob(reportId, JobAction.STOP);
+    }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/790704c0/console/src/main/java/org/apache/syncope/console/rest/TaskRestClient.java
----------------------------------------------------------------------
diff --git a/console/src/main/java/org/apache/syncope/console/rest/TaskRestClient.java b/console/src/main/java/org/apache/syncope/console/rest/TaskRestClient.java
index 863e51a..c83ce88 100644
--- a/console/src/main/java/org/apache/syncope/console/rest/TaskRestClient.java
+++ b/console/src/main/java/org/apache/syncope/console/rest/TaskRestClient.java
@@ -34,6 +34,9 @@ import org.apache.syncope.common.types.TaskType;
 import org.apache.syncope.common.util.CollectionWrapper;
 import org.apache.syncope.common.SyncopeClientException;
 import org.apache.syncope.common.to.PushTaskTO;
+import org.apache.syncope.common.to.TaskExecTO;
+import org.apache.syncope.common.types.JobAction;
+import org.apache.syncope.common.types.JobStatusType;
 import org.apache.syncope.common.wrap.PushActionClass;
 import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;
 import org.springframework.stereotype.Component;
@@ -42,7 +45,7 @@ import org.springframework.stereotype.Component;
  * Console client for invoking Rest Tasks services.
  */
 @Component
-public class TaskRestClient extends BaseRestClient implements ExecutionRestClient {
+public class TaskRestClient extends JobRestClient implements ExecutionRestClient {
 
     private static final long serialVersionUID = 6284485820911028843L;
 
@@ -167,4 +170,22 @@ public class TaskRestClient extends BaseRestClient implements ExecutionRestClien
     public BulkActionResult bulkAction(final BulkAction action) {
         return getService(TaskService.class).bulk(action);
     }
+    
+    @Override
+    public boolean isJobRunning(final long taskId){
+        for(TaskExecTO taskExecTO : getService(TaskService.class).listJobs(JobStatusType.RUNNING)){
+            if(taskExecTO.getTask()== taskId) return true;
+        }
+        return false;
+    }
+    
+    @Override
+    public void startJob(final long taskId){
+        getService(TaskService.class).actionJob(taskId, JobAction.START);
+    }
+
+    @Override
+    public void stopJob(final long taskId) {
+        getService(TaskService.class).actionJob(taskId, JobAction.STOP);
+    }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/790704c0/console/src/main/java/org/apache/syncope/console/wicket/extensions/markup/html/repeater/data/table/JobColumn.java
----------------------------------------------------------------------
diff --git a/console/src/main/java/org/apache/syncope/console/wicket/extensions/markup/html/repeater/data/table/JobColumn.java b/console/src/main/java/org/apache/syncope/console/wicket/extensions/markup/html/repeater/data/table/JobColumn.java
new file mode 100644
index 0000000..563e3cb
--- /dev/null
+++ b/console/src/main/java/org/apache/syncope/console/wicket/extensions/markup/html/repeater/data/table/JobColumn.java
@@ -0,0 +1,94 @@
+/*
+ * 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.console.wicket.extensions.markup.html.repeater.data.table;
+
+import org.apache.syncope.common.to.AbstractTaskTO;
+import org.apache.syncope.common.to.ReportTO;
+import org.apache.syncope.console.pages.panels.RuntimePanel;
+import org.apache.syncope.console.rest.JobRestClient;
+import org.apache.wicket.PageReference;
+import org.apache.wicket.ajax.AbstractAjaxTimerBehavior;
+import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
+import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
+import org.apache.wicket.extensions.markup.html.repeater.data.table.AbstractColumn;
+import org.apache.wicket.markup.repeater.Item;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.util.time.Duration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class JobColumn<T, S> extends AbstractColumn<T, S> {
+
+    private static final long serialVersionUID = 7955560320949560725L;
+
+    protected static final Logger LOG = LoggerFactory.getLogger(JobColumn.class);
+
+    private final PageReference pageRef;
+
+    private RuntimePanel panel;
+
+    private final JobRestClient jobRestClient;
+
+    public JobColumn(final IModel<String> displayModel, final S sortProperty, final PageReference pageRef,
+            final JobRestClient jobRestClient) {
+        super(displayModel, sortProperty);
+        this.pageRef = pageRef;
+        this.jobRestClient = jobRestClient;
+    }
+
+    @Override
+    public void populateItem(final Item<ICellPopulator<T>> item, final String componentId, final IModel<T> model) {
+        Long jobId = null;
+        if (model.getObject() instanceof AbstractTaskTO) {
+            jobId = ((AbstractTaskTO) model.getObject()).getId();
+        } else if (model.getObject() instanceof ReportTO) {
+            jobId = ((ReportTO) model.getObject()).getId();
+        }
+        if (jobId != null) {
+            panel = new RuntimePanel(componentId, model, pageRef, jobId, jobRestClient);
+            startPolling(10);
+            item.add(panel);
+        }
+    }
+
+    public void startPolling(final int seconds) {
+        AbstractAjaxTimerBehavior timer = new AbstractAjaxTimerBehavior(Duration.seconds(seconds)) {
+
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            protected void onTimer(AjaxRequestTarget target) {
+                panel.refresh();
+                target.add(panel);
+            }
+
+            @Override
+            protected void updateAjaxAttributes(AjaxRequestAttributes attributes) {
+                super.updateAjaxAttributes(attributes);
+                attributes.getExtraParameters().put("pollingTimeout", "true");
+            }
+
+        };
+
+        panel.setTimer(timer);
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/790704c0/console/src/main/resources/org/apache/syncope/console/pages/Reports.html
----------------------------------------------------------------------
diff --git a/console/src/main/resources/org/apache/syncope/console/pages/Reports.html b/console/src/main/resources/org/apache/syncope/console/pages/Reports.html
index 456f7a3..ff5fb37 100644
--- a/console/src/main/resources/org/apache/syncope/console/pages/Reports.html
+++ b/console/src/main/resources/org/apache/syncope/console/pages/Reports.html
@@ -18,7 +18,20 @@ under the License.
 -->
 <html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
   <wicket:extend>
+    <script type="text/javascript">
+      window.onload = setupFunc;
 
+      function setupFunc() {
+        Wicket.Event.subscribe('/ajax/call/beforeSend', function (attributes, jqXHR, settings) {
+          if (!jqXHR.ep || !jqXHR.ep[0] || !jqXHR.ep[0]["value"]) {
+            document.getElementById("veil").style.display = "block";
+          }
+        });
+        Wicket.Event.subscribe('/ajax/call/complete', function (attributes, jqXHR, textStatus) {
+          document.getElementById("veil").style.display = "none";
+        });
+      }
+    </script>
     <div id="tabs">
       <ul>
         <li class="tabs-selected"><a href="#tabs-1"><span><wicket:message key="reports"/></span></a></li>

http://git-wip-us.apache.org/repos/asf/syncope/blob/790704c0/console/src/main/resources/org/apache/syncope/console/pages/Tasks.html
----------------------------------------------------------------------
diff --git a/console/src/main/resources/org/apache/syncope/console/pages/Tasks.html b/console/src/main/resources/org/apache/syncope/console/pages/Tasks.html
index 7df418a..81c9237 100644
--- a/console/src/main/resources/org/apache/syncope/console/pages/Tasks.html
+++ b/console/src/main/resources/org/apache/syncope/console/pages/Tasks.html
@@ -18,6 +18,21 @@ under the License.
 -->
 <wicket:extend>
 
+  <script type="text/javascript">
+    window.onload = setupFunc;
+
+    function setupFunc() {
+      Wicket.Event.subscribe('/ajax/call/beforeSend', function (attributes, jqXHR, settings) {
+        if (!jqXHR.ep || !jqXHR.ep[0] || !jqXHR.ep[0]["value"]){
+          document.getElementById("veil").style.display = "block";
+        }
+      });
+      Wicket.Event.subscribe('/ajax/call/complete', function (attributes, jqXHR, textStatus) {
+        document.getElementById("veil").style.display = "none";
+      });
+    }
+  </script>
+
   <div id="tabs">
     <ul>
       <li class="tabs-selected"><a href="#tabs-1"><span><wicket:message key="tab1"/></span></a></li>

http://git-wip-us.apache.org/repos/asf/syncope/blob/790704c0/console/src/main/resources/org/apache/syncope/console/pages/panels/RuntimePanel.html
----------------------------------------------------------------------
diff --git a/console/src/main/resources/org/apache/syncope/console/pages/panels/RuntimePanel.html b/console/src/main/resources/org/apache/syncope/console/pages/panels/RuntimePanel.html
new file mode 100644
index 0000000..828192c
--- /dev/null
+++ b/console/src/main/resources/org/apache/syncope/console/pages/panels/RuntimePanel.html
@@ -0,0 +1,49 @@
+<!--
+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.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
+  <wicket:head>
+    <style>
+      #runtime{
+        text-align: center;
+      }
+    </style>
+  </wicket:head>
+  <wicket:panel wicket:id="runtime">
+    <div>
+      <div id="runtime">
+        <div id="runtimePanel">
+          <span wicket:id="panelStop"></span>
+          <span wicket:id="panelSpinner"></span>
+
+          <wicket:fragment wicket:id="fragmentStop">
+            <a href="#" wicket:id="stopLink"><img src="img/actions/suspend.png" alt="stop icon" title="Stop Now"/></a>
+          </wicket:fragment>
+
+          <wicket:fragment wicket:id="fragmentSpinner">
+            <img src="img/loading.gif" alt="spinner icon" title="Spinner"/>
+          </wicket:fragment>
+
+          <wicket:fragment wicket:id="emptyFragment"></wicket:fragment>
+
+        </div>
+
+      </div>
+    </div>
+  </wicket:panel>
+</html>

http://git-wip-us.apache.org/repos/asf/syncope/blob/790704c0/core/src/main/java/org/apache/syncope/core/rest/controller/AbstractJobController.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/syncope/core/rest/controller/AbstractJobController.java b/core/src/main/java/org/apache/syncope/core/rest/controller/AbstractJobController.java
index ca759d9..e7aa31e 100644
--- a/core/src/main/java/org/apache/syncope/core/rest/controller/AbstractJobController.java
+++ b/core/src/main/java/org/apache/syncope/core/rest/controller/AbstractJobController.java
@@ -158,7 +158,20 @@ abstract class AbstractJobController<T extends AbstractBaseBean> extends Abstrac
                 if (scheduler.getScheduler().checkExists(jobKey)) {
                     switch (action) {
                         case START:
-                            scheduler.getScheduler().triggerJob(jobKey);
+                            Long currentId = getIdFromJobName(jobKey);
+                            boolean found = false;
+                            //Two or more equals jobs cannot be executed concurrently
+                            for (int i = 0; i < scheduler.getScheduler().getCurrentlyExecutingJobs().size() && !found;
+                                    i++) {
+                                JobExecutionContext jec = scheduler.getScheduler().getCurrentlyExecutingJobs().get(i);
+                                Long jobId = getIdFromJobName(jec.getJobDetail().getKey());
+                                if (jobId == currentId) {
+                                    found = true;
+                                }
+                            }
+                            if (!found) {
+                                scheduler.getScheduler().triggerJob(jobKey);
+                            }
                             break;
 
                         case STOP:


[08/21] syncope git commit: Upgading izpack

Posted by il...@apache.org.
Upgading izpack


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

Branch: refs/heads/SYNCOPE-666
Commit: 8cc3ffc1feba36af7414c380b6ac833662b58f73
Parents: 4ded5ba 5dbe698
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Wed Jun 3 15:08:55 2015 +0200
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Wed Jun 3 15:08:55 2015 +0200

----------------------------------------------------------------------
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/8cc3ffc1/pom.xml
----------------------------------------------------------------------
diff --cc pom.xml
index 13f4ac1,cbcc04f..c32fbb8
--- a/pom.xml
+++ b/pom.xml
@@@ -370,22 -394,13 +370,22 @@@ under the License
      <connid.location>file:${bundles.directory}/</connid.location>
      <log.directory>${project.build.directory}/log</log.directory>
      <activiti-modeler.directory>${project.build.directory}/activiti-modeler</activiti-modeler.directory>
 -                
 -    <cargo.servlet.port>9080</cargo.servlet.port>
 -    <cargo.tomcat.ajp.port>9889</cargo.tomcat.ajp.port>
 -    <cargo.rmi.port>9805</cargo.rmi.port>
 -    <cargo.run.dir>${project.build.directory}/syncope-core-test</cargo.run.dir>
 -    <cargo.log>${log.directory}/cargo.log</cargo.log>
 -    <cargo.output>${log.directory}/cargo-output.log</cargo.output>
 +    
 +    <jquery.version>2.1.3</jquery.version>
 +    <jquery-ui.version>1.11.4</jquery-ui.version>
 +    <bootstrap.version>3.3.4</bootstrap.version>
 +    <bootstrap-select.version>1.6.3</bootstrap-select.version>
 +    <font-awesome.version>4.3.0</font-awesome.version>
 +    <ionicons.version>2.0.1</ionicons.version>
 +    <highlightjs.version>8.4-4</highlightjs.version>
 +    <codemirror.version>5.1</codemirror.version>
 +    
 +    <wicket.version>7.0.0-M5</wicket.version>
 +    <wicket-jqueryui.version>7.0.0-M5</wicket-jqueryui.version>
 +
-     <izpack.version>5.0.0-rc4</izpack.version>
++    <izpack.version>5.0.0-rc5</izpack.version>
 +    <httpclient.version>4.3.6</httpclient.version>
 +    <maven-invoker.version>2.1.1</maven-invoker.version>
  
      <testds.port>1389</testds.port>
      <testdb.webport>9082</testdb.webport>


[09/21] syncope git commit: [SYNCOPE-667] During tasks creation, the notification manager now returns a list of notification task

Posted by il...@apache.org.
[SYNCOPE-667] During tasks creation, the notification manager now returns a list of notification task


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

Branch: refs/heads/SYNCOPE-666
Commit: 18394d3c5027ae9e4442414a7f886e422904d77f
Parents: 8106e24
Author: giacomolm <gi...@hotmail.it>
Authored: Fri Jun 5 09:30:16 2015 +0200
Committer: giacomolm <gi...@hotmail.it>
Committed: Fri Jun 5 09:30:16 2015 +0200

----------------------------------------------------------------------
 .../syncope/core/notification/NotificationManager.java   | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/18394d3c/core/src/main/java/org/apache/syncope/core/notification/NotificationManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/syncope/core/notification/NotificationManager.java b/core/src/main/java/org/apache/syncope/core/notification/NotificationManager.java
index 341a0bd..48caa54 100644
--- a/core/src/main/java/org/apache/syncope/core/notification/NotificationManager.java
+++ b/core/src/main/java/org/apache/syncope/core/notification/NotificationManager.java
@@ -262,7 +262,7 @@ public class NotificationManager {
     /**
      * Create notification tasks for each notification matching the given user id and (some of) tasks performed.
      */
-    public void createTasks(
+    public List<NotificationTask> createTasks(
             final AuditElements.EventCategoryType type,
             final String category,
             final String subcategory,
@@ -274,6 +274,7 @@ public class NotificationManager {
 
         SubjectType subjectType = null;
         AbstractSubject subject = null;
+        List<NotificationTask> notificationList = new ArrayList<NotificationTask>();
 
         if (before instanceof UserTO) {
             subjectType = SubjectType.USER;
@@ -327,15 +328,17 @@ public class NotificationManager {
                     } else if (subject instanceof SyncopeRole) {
                         model.put("role", roleDataBinder.getRoleTO((SyncopeRole) subject));
                     }
-
-                    taskDAO.save(getNotificationTask(notification, subject, model));
+                    NotificationTask notificationTask = getNotificationTask(notification, subject, model);
+                    notificationTask = taskDAO.save(notificationTask);
+                    notificationList.add(notificationTask);                    
                 }
             } else {
                 LOG.debug("Notification {}, userAbout {}, roleAbout {} is deactivated, "
                         + "notification task will not be created", notification.getId(),
                         notification.getUserAbout(), notification.getRoleAbout());
             }
-        }
+        }        
+        return notificationList;
     }
 
     private String getRecipientEmail(


[19/21] syncope git commit: [SYNCOPE-666] All tests are green, time to add more

Posted by il...@apache.org.
http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/main/resources/META-INF/spring-orm-sqlserver.xml
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/resources/META-INF/spring-orm-sqlserver.xml b/core/persistence-jpa/src/main/resources/META-INF/spring-orm-sqlserver.xml
index c592c31..a75e4b6 100644
--- a/core/persistence-jpa/src/main/resources/META-INF/spring-orm-sqlserver.xml
+++ b/core/persistence-jpa/src/main/resources/META-INF/spring-orm-sqlserver.xml
@@ -312,6 +312,56 @@ under the License.
     </attributes>
   </entity>
 
+  <entity class="org.apache.syncope.core.persistence.jpa.entity.anyobject.JPAADerAttr">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_ADerAttr" strategy="TABLE"/>
+        <table-generator name="SEQ_ADerAttr" pk-column-value="SEQ_ADerAttr" initial-value="1000"/>
+      </id>
+    </attributes>
+  </entity>
+  <entity class="org.apache.syncope.core.persistence.jpa.entity.user.JPAUDerAttr">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_UDerAttr" strategy="TABLE"/>
+        <table-generator name="SEQ_UDerAttr" pk-column-value="SEQ_UDerAttr" initial-value="1000"/>
+      </id>
+    </attributes>
+  </entity>
+  <entity class="org.apache.syncope.core.persistence.jpa.entity.group.JPAGDerAttr">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_GDerAttr" strategy="TABLE"/>
+        <table-generator name="SEQ_GDerAttr" pk-column-value="SEQ_GDerAttr" initial-value="1000"/>
+      </id>
+    </attributes>
+  </entity>
+
+  <entity class="org.apache.syncope.core.persistence.jpa.entity.anyobject.JPAAVirAttr">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_AVirAttr" strategy="TABLE"/>
+        <table-generator name="SEQ_AVirAttr" pk-column-value="SEQ_AVirAttr" initial-value="1000"/>
+      </id>
+    </attributes>
+  </entity>
+  <entity class="org.apache.syncope.core.persistence.jpa.entity.user.JPAUVirAttr">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_UVirAttr" strategy="TABLE"/>
+        <table-generator name="SEQ_UVirAttr" pk-column-value="SEQ_UVirAttr" initial-value="1000"/>
+      </id>
+    </attributes>
+  </entity>
+  <entity class="org.apache.syncope.core.persistence.jpa.entity.group.JPAGVirAttr">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_GVirAttr" strategy="TABLE"/>
+        <table-generator name="SEQ_GVirAttr" pk-column-value="SEQ_GVirAttr" initial-value="1000"/>
+      </id>
+    </attributes>
+  </entity>
+
   <entity class="org.apache.syncope.core.persistence.jpa.entity.task.JPAAnyTemplate">
     <attributes>
       <id name="id">

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/main/resources/META-INF/spring-orm.xml
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/resources/META-INF/spring-orm.xml b/core/persistence-jpa/src/main/resources/META-INF/spring-orm.xml
index 746314c..6f83543 100644
--- a/core/persistence-jpa/src/main/resources/META-INF/spring-orm.xml
+++ b/core/persistence-jpa/src/main/resources/META-INF/spring-orm.xml
@@ -360,6 +360,56 @@ under the License.
     </attributes>
   </entity>
 
+  <entity class="org.apache.syncope.core.persistence.jpa.entity.anyobject.JPAADerAttr">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_ADerAttr" strategy="TABLE"/>
+        <table-generator name="SEQ_ADerAttr" pk-column-value="SEQ_ADerAttr" initial-value="1000"/>
+      </id>
+    </attributes>
+  </entity>
+  <entity class="org.apache.syncope.core.persistence.jpa.entity.user.JPAUDerAttr">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_UDerAttr" strategy="TABLE"/>
+        <table-generator name="SEQ_UDerAttr" pk-column-value="SEQ_UDerAttr" initial-value="1000"/>
+      </id>
+    </attributes>
+  </entity>
+  <entity class="org.apache.syncope.core.persistence.jpa.entity.group.JPAGDerAttr">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_GDerAttr" strategy="TABLE"/>
+        <table-generator name="SEQ_GDerAttr" pk-column-value="SEQ_GDerAttr" initial-value="1000"/>
+      </id>
+    </attributes>
+  </entity>
+
+  <entity class="org.apache.syncope.core.persistence.jpa.entity.anyobject.JPAAVirAttr">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_AVirAttr" strategy="TABLE"/>
+        <table-generator name="SEQ_AVirAttr" pk-column-value="SEQ_AVirAttr" initial-value="1000"/>
+      </id>
+    </attributes>
+  </entity>
+  <entity class="org.apache.syncope.core.persistence.jpa.entity.user.JPAUVirAttr">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_UVirAttr" strategy="TABLE"/>
+        <table-generator name="SEQ_UVirAttr" pk-column-value="SEQ_UVirAttr" initial-value="1000"/>
+      </id>
+    </attributes>
+  </entity>
+  <entity class="org.apache.syncope.core.persistence.jpa.entity.group.JPAGVirAttr">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_GVirAttr" strategy="TABLE"/>
+        <table-generator name="SEQ_GVirAttr" pk-column-value="SEQ_GVirAttr" initial-value="1000"/>
+      </id>
+    </attributes>
+  </entity>
+  
   <entity class="org.apache.syncope.core.persistence.jpa.entity.task.JPAAnyTemplate">
     <attributes>
       <id name="id">

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/entity/VirAttrTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/entity/VirAttrTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/entity/VirAttrTest.java
index e1ffc11..02815b8 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/entity/VirAttrTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/entity/VirAttrTest.java
@@ -60,7 +60,7 @@ public class VirAttrTest extends AbstractTest {
 
     @Test
     public void findById() {
-        UVirAttr attribute = virAttrDAO.find(1000L, UVirAttr.class);
+        UVirAttr attribute = virAttrDAO.find(100L, UVirAttr.class);
         assertNotNull("did not find expected attribute schema", attribute);
     }
 
@@ -104,7 +104,7 @@ public class VirAttrTest extends AbstractTest {
 
     @Test
     public void delete() {
-        UVirAttr attribute = virAttrDAO.find(1000L, UVirAttr.class);
+        UVirAttr attribute = virAttrDAO.find(100L, UVirAttr.class);
         String attributeSchemaName = attribute.getSchema().getKey();
 
         virAttrDAO.delete(attribute.getKey(), UVirAttr.class);

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/relationship/AnyTypeTest.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/relationship/AnyTypeTest.java b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/relationship/AnyTypeTest.java
index e6a919d..60ff041 100644
--- a/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/relationship/AnyTypeTest.java
+++ b/core/persistence-jpa/src/test/java/org/apache/syncope/core/persistence/jpa/relationship/AnyTypeTest.java
@@ -52,13 +52,8 @@ public class AnyTypeTest extends AbstractTest {
 
         anyTypeClassDAO.delete("other");
 
-        try {
         anyTypeDAO.flush();
-        } catch(Exception e) {
-            System.err.println("EEEEEEEEEEEE");
-            e.printStackTrace();
-        }
-        
+
         userType = anyTypeDAO.findUser();
         assertNotNull(userType);
         assertEquals(before, userType.getClasses().size() + 1);

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/test/resources/content.xml
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/test/resources/content.xml b/core/persistence-jpa/src/test/resources/content.xml
index 8d2ef54..7c123a7 100644
--- a/core/persistence-jpa/src/test/resources/content.xml
+++ b/core/persistence-jpa/src/test/resources/content.xml
@@ -94,11 +94,11 @@ under the License.
   
   <!-- sample policies -->
   <Policy DTYPE="SyncPolicy" id="1" description="a sync policy" type="SYNC" 
-          specification='{"userJavaRule":null,"groupJavaRule":null,"conflictResolutionAction":"IGNORE","userAltSearchSchemas":[],"groupAltSearchSchemas":[]}'/>
+          specification='{"conflictResolutionAction":"IGNORE","items":[]}'/>
   <Policy DTYPE="PasswordPolicy" id="2" description="a password policy" type="PASSWORD" 
           specification='{"historyLength":1,"maxLength":0,"minLength":8,"nonAlphanumericRequired":false,"alphanumericRequired":false,"digitRequired":false,"lowercaseRequired":false,"uppercaseRequired":false,"mustStartWithDigit":false,"mustntStartWithDigit":false,"mustEndWithDigit":false,"mustntEndWithDigit":false,"mustStartWithNonAlpha":false,"mustStartWithAlpha":false,"mustntStartWithNonAlpha":false,"mustntStartWithAlpha":false,"mustEndWithNonAlpha":false,"mustEndWithAlpha":false,"mustntEndWithNonAlpha":false,"mustntEndWithAlpha":false,"wordsNotPermitted":[],"schemasNotPermitted":[],"prefixesNotPermitted":["notpermitted1","notpermitted2"],"suffixesNotPermitted":[],"allowNullPassword":true}'/>
   <Policy DTYPE="SyncPolicy" id="3" description="sync policy 2" type="SYNC" 
-          specification='{"userJavaRule":null,"groupJavaRule":null,"conflictResolutionAction":"ALL","userAltSearchSchemas":["username","firstname"],"groupAltSearchSchemas":[]}'/>
+          specification='{"conflictResolutionAction":"ALL","items":[{"anyTypeKey":"USER","javaRule":null,"altSearchSchemas":["username","firstname"]}]}'/>
   <Policy DTYPE="PasswordPolicy" id="4" description="sample password policy" type="PASSWORD" 
           specification='{"historyLength":0,"maxLength":0,"minLength":10,"nonAlphanumericRequired":false,"alphanumericRequired":false,"digitRequired":true,"lowercaseRequired":false,"uppercaseRequired":false,"mustStartWithDigit":false,"mustntStartWithDigit":false,"mustEndWithDigit":false,"mustntEndWithDigit":false,"mustStartWithNonAlpha":false,"mustStartWithAlpha":false,"mustntStartWithNonAlpha":false,"mustntStartWithAlpha":false,"mustEndWithNonAlpha":false,"mustEndWithAlpha":false,"mustntEndWithNonAlpha":false,"mustntEndWithAlpha":false,"wordsNotPermitted":[],"schemasNotPermitted":[],"prefixesNotPermitted":["notpermitted1","notpermitted2"],"suffixesNotPermitted":[], "allowNullPassword":true}'/>
   <Policy DTYPE="AccountPolicy" id="5" description="an account policy" type="ACCOUNT" 
@@ -106,11 +106,11 @@ under the License.
   <Policy DTYPE="AccountPolicy" id="6" description="sample account policy" type="ACCOUNT" 
           specification='{"maxLength":0,"minLength":4,"pattern":null,"allUpperCase":false,"allLowerCase":false,"propagateSuspension":false,"maxAuthenticationAttempts":3,"wordsNotPermitted":[],"schemasNotPermitted":[],"prefixesNotPermitted":["notpermitted1","notpermitted2"],"suffixesNotPermitted":[]}'/>
   <Policy DTYPE="SyncPolicy" id="7" description="sync policy 1" type="SYNC" 
-          specification='{"userJavaRule":null,"groupJavaRule":null,"conflictResolutionAction":"IGNORE","userAltSearchSchemas":[],"groupAltSearchSchemas":[]}'/>
+          specification='{"conflictResolutionAction":"IGNORE","items":[]}'/>
   <Policy DTYPE="PasswordPolicy" id="8" description="sample password policy" type="PASSWORD" 
           specification='{"historyLength":0,"maxLength":0,"minLength":10,"nonAlphanumericRequired":true,"alphanumericRequired":false,"digitRequired":true,"lowercaseRequired":true,"uppercaseRequired":true,"mustStartWithDigit":true,"mustntStartWithDigit":false,"mustEndWithDigit":true,"mustntEndWithDigit":false,"mustStartWithNonAlpha":false,"mustStartWithAlpha":false,"mustntStartWithNonAlpha":false,"mustntStartWithAlpha":false,"mustEndWithNonAlpha":false,"mustEndWithAlpha":false,"mustntEndWithNonAlpha":false,"mustntEndWithAlpha":false,"wordsNotPermitted":[],"schemasNotPermitted":[],"prefixesNotPermitted":["notpermitted1","notpermitted2"],"suffixesNotPermitted":[],"allowNullPassword":false}'/>
   <Policy DTYPE="SyncPolicy" id="9" description="sync policy for java rule" type="SYNC" 
-          specification='{"userJavaRule":null,"groupJavaRule":null,"conflictResolutionAction":"IGNORE","userAltSearchSchemas":[],"groupAltSearchSchemas":[]}'/>
+          specification='{"conflictResolutionAction":"IGNORE","items":[]}'/>
 
   <AnyTypeClass name="generic membership"/>
 
@@ -307,6 +307,7 @@ under the License.
   <DerSchema name="noschema" expression="surname + ', ' + notfound" anyTypeClass_name="other"/>
 
   <VirSchema name="virtualdata" anyTypeClass_name="minimal user"/>
+  <VirSchema name="virtualReadOnly" READONLY="1"  anyTypeClass_name="minimal user"/>
 
   <PlainSchema name="icon" type="String" anyTypeClass_name="minimal group"
                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"/>                
@@ -328,7 +329,7 @@ under the License.
 
   <VirSchema name="rvirtualdata" anyTypeClass_name="minimal group"/>
 
-  <DerSchema name="rderivedschema" expression="rderived_sx + '-' + rderived_dx"/>
+  <DerSchema name="rderivedschema" expression="rderived_sx + '-' + rderived_dx"  anyTypeClass_name="minimal group"/>
 
   <PlainSchema name="subscriptionDate" type="Date" anyTypeClass_name="generic membership"
                mandatoryCondition="false" multivalue="0" uniqueConstraint="0" readonly="0"
@@ -412,9 +413,7 @@ under the License.
   <UPlainAttr id="126" owner_id="3" schema_name="type"/>
   <UPlainAttrValue id="37" attribute_id="126" stringValue="F"/>
     
-  <UVirAttr id="1000" schema_name="virtualdata" owner_id="3"/>
-
-  <VirSchema name="virtualReadOnly" READONLY="1"/>
+  <UVirAttr id="100" schema_name="virtualdata" owner_id="3"/>
   
   <UDerAttr id="100" schema_name="cn" owner_id="3"/>
   <UDerAttr id="101" schema_name="cn" owner_id="1"/>
@@ -446,13 +445,13 @@ under the License.
   <GPlainAttr id="995" owner_id="13" schema_name="title"/>
   <GPlainAttrValue attribute_id="995" id="95" stringValue="r13"/>
 
-  <GDerAttr id="1000" owner_id="1" schema_name="rderiveddata"/>
+  <GDerAttr id="100" owner_id="1" schema_name="rderiveddata"/>
     
-  <GDerAttr id="1001" owner_id="1" schema_name="displayProperty"/>
+  <GDerAttr id="101" owner_id="1" schema_name="displayProperty"/>
   
-  <GDerAttr id="1002" owner_id="4" schema_name="displayProperty"/>
+  <GDerAttr id="102" owner_id="4" schema_name="displayProperty"/>
 
-  <GDerAttr id="1003" owner_id="1" schema_name="rderToBePropagated"/>    
+  <GDerAttr id="103" owner_id="1" schema_name="rderToBePropagated"/>    
 
   <GVirAttr id="98" owner_id="4" schema_name="rvirtualdata"/>
 
@@ -816,10 +815,10 @@ under the License.
                connObjectKey="1" password="0" purpose="BOTH"/>
   <MappingItem id="208" extAttrName="theirgroup" mapping_id="9"
                intAttrName="rderToBePropagated" intMappingType="GroupDerivedSchema" mandatoryCondition="false"
-               connObjectKey="0" password="0" purpose="BOTH"/>
+               connObjectKey="0" password="0" purpose="PROPAGATION"/>
   <MappingItem id="209" extAttrName="membership" mapping_id="9"
                intAttrName="mderToBePropagated" intMappingType="AnyDerivedSchema" mandatoryCondition="false"
-               connObjectKey="0" password="0" purpose="BOTH"/>
+               connObjectKey="0" password="0" purpose="PROPAGATION"/>
                          
   <Provision id="10" resource_name="ws-target-resource-update-resetsynctoken" anyType_name="USER" objectClass="__ACCOUNT__"
              serializedSyncToken='{"value":null}'/>
@@ -853,7 +852,7 @@ under the License.
                extAttrName="title" intAttrName="title" intMappingType="GroupPlainSchema"
                mandatoryCondition="false" purpose="BOTH"/>
   <MappingItem id="317" connObjectKey="0" password="0" mapping_id="11"
-               extAttrName="postalAddress" intAttrName="postalAddress" intMappingType="AnyPlainSchema"
+               extAttrName="postalAddress" intAttrName="postalAddress" intMappingType="UserPlainSchema"
                mandatoryCondition="false" purpose="BOTH"/>
   <MappingItem id="318" connObjectKey="0" password="0" mapping_id="11"
                extAttrName="mail" intAttrName="userId" intMappingType="UserPlainSchema"
@@ -940,9 +939,9 @@ under the License.
         destinationRealm_id="1" performCreate="1" performUpdate="1" performDelete="1" syncStatus="1" fullReconciliation="0"
         jobClassName="org.apache.syncope.core.provisioning.api.job.SyncJob" unmatchingRule="ASSIGN" matchingRule="UPDATE"/>
   <AnyTemplate id="41" syncTask_id="4" anyType_name="USER"
-               template='{"creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":0,"password":null,"status":null,"token":null,"tokenExpireTime":null,"username":null,"lastLoginDate":null,"changePwdDate":null,"failedLogins":null,"plainAttrs":[{"schema":"type","readonly":false,"values":["email == &apos;test8@syncope.apache.org&apos;? &apos;TYPE_8&apos;: &apos;TYPE_OTHER&apos;"]}],"derAttrs":[{"schema":"cn","readonly":false,"values":[null]}],"virAttrs":[],"resources":["resource-testdb"],"propagationStatuses":[],"memberships":[{"creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":0,"groupKey":8,"groupName":null,"plainAttrs":[{"schema":"subscriptionDate","readonly":false,"values":["&apos;2009-08-18T16:33:12.203+0200&apos;"]}],"derAttrs":[],"virAttrs":[]}]}'/>
+               template='{"@class":"org.apache.syncope.common.lib.to.UserTO","creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":0,"type":"USER","realm":null,"status":null,"password":null,"token":null,"tokenExpireTime":null,"username":null,"lastLoginDate":null,"changePwdDate":null,"failedLogins":null,"securityQuestion":null,"securityAnswer":null,"auxClasses":["csv"],"derAttrs":[{"schema":"cn","readonly":false,"values":[""]}],"virAttrs":[],"resources":["resource-testdb"],"propagationStatuses":[],"relationships":[],"memberships":[{"leftType":null,"leftKey":0,"rightType":"GROUP","rightKey":8,"groupName":null}],"dynGroups":[],"roles":[],"dynRoles":[],"plainAttrs":[{"schema":"type","readonly":false,"values":["email == &apos;test8@syncope.apache.org&apos;? &apos;TYPE_8&apos;: &apos;TYPE_OTHER&apos;"]}]}'/>
   <AnyTemplate id="42" syncTask_id="4" anyType_name="GROUP"
-               template='{"creator": null,"creationDate": null,"lastModifier": null,"lastChangeDate": null,"key": 0,"name": null,"userOwner": null,"groupOwner": null,"plainAttrs": [], "derAttrs": [],"virAttrs": [],"resources": [],"propagationStatuses": []}'/>
+               template='{"@class":"org.apache.syncope.common.lib.to.GroupTO","creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":0,"type":"GROUP","realm":null,"status":null,"name":null,"userOwner":null,"groupOwner":null,"adynMembershipCond":null,"udynMembershipCond":null,"auxClasses":[],"derAttrs":[],"virAttrs":[],"resources":[],"propagationStatuses":[],"plainAttrs":[]}'/>
   <Task DTYPE="SchedTask" type="SCHEDULED" id="5" name="SampleJob Task" jobClassName="org.apache.syncope.core.provisioning.java.job.SampleJob" cronExpression="0 0 0 1 * ?"/>
   <Task DTYPE="PropagationTask" type="PROPAGATION" id="6" propagationMode="TWO_PHASES" propagationOperation="UPDATE"
         objectClassName="__ACCOUNT__" resource_name="ws-target-resource-nopropagation" anyTypeKind="USER" anyKey="1"
@@ -951,10 +950,10 @@ under the License.
   <Task DTYPE="SyncTask" type="SYNCHRONIZATION" id="7" name="TestDB Task" resource_name="resource-testdb"
         destinationRealm_id="1" performCreate="1" performUpdate="1" performDelete="0" syncStatus="1" fullReconciliation="1"
         jobClassName="org.apache.syncope.core.provisioning.api.job.SyncJob" unmatchingRule="PROVISION" matchingRule="UPDATE"/>
-  <AnyTemplate id="61" syncTask_id="7" anyType_name="USER"
-               template='{"creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":0,"password":null,"status":null,"token":null,"tokenExpireTime":null,"username":null,"lastLoginDate":null,"changePwdDate":null,"failedLogins":null,"plainAttrs":[{"schema":"type","readonly":false,"values":["email == &apos;test8@syncope.apache.org&apos;? &apos;TYPE_8&apos;: &apos;TYPE_OTHER&apos;"]}],"derAttrs":[{"schema":"cn","readonly":false,"values":[null]}],"virAttrs":[],"resources":["resource-testdb"],"propagationStatuses":[],"memberships":[{"creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":0,"groupKey":8,"groupName":null,"plainAttrs":[{"schema":"subscriptionDate","readonly":false,"values":["&apos;2009-08-18T16:33:12.203+0200&apos;"]}],"derAttrs":[],"virAttrs":[]}]}'/>
-  <AnyTemplate id="62" syncTask_id="7" anyType_name="GROUP"
-               template='{"creator": null,"creationDate": null,"lastModifier": null,"lastChangeDate": null,"key": 0,"name": null,"userOwner": null,"groupOwner": null,"plainAttrs": [], "derAttrs": [],"virAttrs": [],"resources": [],"propagationStatuses": []}'/>
+  <AnyTemplate id="71" syncTask_id="7" anyType_name="USER"
+               template='{"@class":"org.apache.syncope.common.lib.to.UserTO","creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":0,"type":"USER","realm":null,"status":null,"password":null,"token":null,"tokenExpireTime":null,"username":null,"lastLoginDate":null,"changePwdDate":null,"failedLogins":null,"securityQuestion":null,"securityAnswer":null,"auxClasses":[],"derAttrs":[],"virAttrs":[],"resources":[],"propagationStatuses":[],"relationships":[],"memberships":[],"dynGroups":[],"roles":[],"dynRoles":[],"plainAttrs":[{"schema":"type","readonly":false,"values":["&apos;type a&apos;"]},{"schema":"userId","readonly":false,"values":["&apos;reconciled@syncope.apache.org&apos;"]},{"schema":"fullname","readonly":false,"values":["&apos;reconciled fullname&apos;"]},{"schema":"surname","readonly":false,"values":["&apos;surname&apos;"]}]}'/>
+  <AnyTemplate id="72" syncTask_id="7" anyType_name="GROUP"
+               template='{"@class":"org.apache.syncope.common.lib.to.GroupTO","creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":0,"type":"GROUP","realm":null,"status":null,"name":null,"userOwner":null,"groupOwner":null,"adynMembershipCond":null,"udynMembershipCond":null,"auxClasses":[],"derAttrs":[],"virAttrs":[],"resources":[],"propagationStatuses":[],"plainAttrs":[]}'/>
   <Task DTYPE="NotificationTask" type="NOTIFICATION" id="8" sender="admin@prova.org" subject="Notification for SYNCOPE-81" 
         textBody="NOTIFICATION-81" htmlBody="NOTIFICATION-81" traceLevel="ALL"/>
   <Task DTYPE="SyncTask" type="SYNCHRONIZATION" id="9" name="TestDB2 Task" resource_name="resource-testdb2"
@@ -967,9 +966,9 @@ under the License.
         destinationRealm_id="1" fullReconciliation="1" performCreate="1" performDelete="1" performUpdate="1" syncStatus="0"
         jobClassName="org.apache.syncope.core.provisioning.api.job.SyncJob" unmatchingRule="PROVISION" matchingRule="UPDATE"/>
   <AnyTemplate id="1" syncTask_id="11" anyType_name="USER"
-               template='{"creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":0,"password":null,"status":null,"token":null,"tokenExpireTime":null,"username":null,"lastLoginDate":null,"changePwdDate":null,"failedLogins":null,"plainAttrs":[{"schema":"type","readonly":false,"values":["email == &apos;test8@syncope.apache.org&apos;? &apos;TYPE_8&apos;: &apos;TYPE_OTHER&apos;"]}],"derAttrs":[{"schema":"cn","readonly":false,"values":[null]}],"virAttrs":[],"resources":["resource-testdb"],"propagationStatuses":[],"memberships":[{"creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":0,"groupKey":8,"groupName":null,"plainAttrs":[{"schema":"subscriptionDate","readonly":false,"values":["&apos;2009-08-18T16:33:12.203+0200&apos;"]}],"derAttrs":[],"virAttrs":[]}]}'/>
+               template='{"@class":"org.apache.syncope.common.lib.to.UserTO","creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":0,"type":"USER","realm":null,"status":null,"password":null,"token":null,"tokenExpireTime":null,"username":null,"lastLoginDate":null,"changePwdDate":null,"failedLogins":null,"securityQuestion":null,"securityAnswer":null,"auxClasses":[],"derAttrs":[],"virAttrs":[{"schema":"virtualReadOnly","readonly":true,"values":[""]}],"resources":["resource-ldap"],"propagationStatuses":[],"roles":[],"dynRoles":[],"relationships":[],"memberships":[],"dynGroups":[],"plainAttrs":[]}'/>
   <AnyTemplate id="2" syncTask_id="11" anyType_name="GROUP"
-               template='{"creator": null,"creationDate": null,"lastModifier": null,"lastChangeDate": null,"key": 0,"name": null,"userOwner": null,"groupOwner": null,"plainAttrs": [], "derAttrs": [],"virAttrs": [],"resources": [],"propagationStatuses": []}'/>
+               template='{"@class":"org.apache.syncope.common.lib.to.GroupTO","creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":0,"type":"GROUP","realm":null,"status":null,"name":null,"userOwner":null,"groupOwner":null,"adynMembershipCond":null,"udynMembershipCond":null,"auxClasses":[],"derAttrs":[],"virAttrs":[],"resources":[],"propagationStatuses":[],"plainAttrs":[{"schema":"show","readonly":false,"values":["true"]}]}'/>
   <SyncTask_actionsClassNames SyncTask_id="11" actionClassName="org.apache.syncope.core.provisioning.java.sync.LDAPMembershipSyncActions"/>
   <Task DTYPE="SyncTask" type="SYNCHRONIZATION" id="12" name="VirAttrCache test" resource_name="resource-csv"
         destinationRealm_id="1" performCreate="0" performUpdate="1" performDelete="0" syncStatus="0" fullReconciliation="1"
@@ -1044,9 +1043,9 @@ under the License.
         destinationRealm_id="1" performCreate="1" performUpdate="1" performDelete="1" syncStatus="1" fullReconciliation="0"
         jobClassName="org.apache.syncope.core.provisioning.api.job.SyncJob" unmatchingRule="PROVISION" matchingRule="UPDATE"/>
   <AnyTemplate id="3" syncTask_id="24" anyType_name="USER"
-               template='{"creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":0,"password":null,"status":null,"token":null,"tokenExpireTime":null,"username":null,"lastLoginDate":null,"changePwdDate":null,"failedLogins":null,"plainAttrs":[{"schema":"type","readonly":false,"values":["email == &apos;test8@syncope.apache.org&apos;? &apos;TYPE_8&apos;: &apos;TYPE_OTHER&apos;"]}],"derAttrs":[{"schema":"cn","readonly":false,"values":[null]}],"virAttrs":[],"resources":["resource-testdb"],"propagationStatuses":[],"memberships":[{"creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":0,"groupKey":8,"groupName":null,"plainAttrs":[{"schema":"subscriptionDate","readonly":false,"values":["&apos;2009-08-18T16:33:12.203+0200&apos;"]}],"derAttrs":[],"virAttrs":[]}]}'/>
+               template='{"@class":"org.apache.syncope.common.lib.to.UserTO","creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":0,"type":"USER","realm":null,"status":null,"password":null,"token":null,"tokenExpireTime":null,"username":null,"lastLoginDate":null,"changePwdDate":null,"failedLogins":null,"securityQuestion":null,"securityAnswer":null,"auxClasses":[],"derAttrs":[],"virAttrs":[],"resources":["resource-testdb"],"propagationStatuses":[],"roles":[],"dynRoles":[],"relationships":[],"memberships":[],"dynGroups":[],"plainAttrs":[{"schema":"firstname","readonly":false,"values":[""]},{"schema":"userId","readonly":false,"values":["&apos;test&apos;"]},{"schema":"fullname","readonly":false,"values":["&apos;test&apos;"]},{"schema":"surname","readonly":false,"values":["&apos;test&apos;"]}]}'/>
   <AnyTemplate id="4" syncTask_id="24" anyType_name="GROUP"
-               template='{"creator": null,"creationDate": null,"lastModifier": null,"lastChangeDate": null,"key": 0,"name": null,"userOwner": null,"groupOwner": null,"plainAttrs": [], "derAttrs": [],"virAttrs": [],"resources": [],"propagationStatuses": []}'/>
+               template='{"@class":"org.apache.syncope.common.lib.to.GroupTO","creator":null,"creationDate":null,"lastModifier":null,"lastChangeDate":null,"key":0,"type":"GROUP","realm":null,"status":null,"name":null,"userOwner":null,"groupOwner":null,"adynMembershipCond":null,"udynMembershipCond":null,"auxClasses":[],"derAttrs":[],"virAttrs":[],"resources":[],"propagationStatuses":[],"plainAttrs":[]}'/>
   <Task DTYPE="SyncTask" type="SYNCHRONIZATION" id="25" name="CSV (unlink matching; ignore unmatching)" resource_name="resource-csv"
         destinationRealm_id="1" performCreate="1" performUpdate="1" performDelete="1" syncStatus="1" fullReconciliation="0"
         jobClassName="org.apache.syncope.core.provisioning.api.job.SyncJob" unmatchingRule="IGNORE" matchingRule="UNLINK"/>

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/VirAttrHandler.java
----------------------------------------------------------------------
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/VirAttrHandler.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/VirAttrHandler.java
new file mode 100644
index 0000000..4cec074
--- /dev/null
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/VirAttrHandler.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.provisioning.api;
+
+import java.util.Collection;
+import java.util.Set;
+import org.apache.syncope.common.lib.mod.AttrMod;
+import org.apache.syncope.common.lib.to.AttrTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.IntMappingType;
+import org.apache.syncope.common.lib.types.PropagationByResource;
+import org.apache.syncope.core.persistence.api.entity.Any;
+import org.apache.syncope.core.persistence.api.entity.AnyUtils;
+import org.apache.syncope.core.persistence.api.entity.VirSchema;
+import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
+
+public interface VirAttrHandler {
+
+    PropagationByResource fillVirtual(Any any, Set<String> vAttrsToBeRemoved, Set<AttrMod> vAttrsToBeUpdated);
+
+    /**
+     * Add virtual attributes and specify values to be propagated.
+     *
+     * @param any any.
+     * @param vAttrs virtual attributes to be added.
+     */
+    void fillVirtual(Any any, Collection<AttrTO> vAttrs);
+
+    /**
+     * SYNCOPE-459: build virtual attribute changes in case no other changes were made.
+     *
+     * @param key any key
+     * @param anyTypeKind type kind
+     * @param vAttrsToBeRemoved virtual attributes to be removed.
+     * @param vAttrsToBeUpdated virtual attributes to be updated.
+     * @return operations to be performed on external resources for virtual attributes changes
+     */
+    PropagationByResource fillVirtual(
+            Long key, AnyTypeKind anyTypeKind, Set<String> vAttrsToBeRemoved, Set<AttrMod> vAttrsToBeUpdated);
+
+    VirSchema getVirSchema(String virSchemaName);
+
+    /**
+     * Query connected external resources for values to populated virtual attributes associated with the given owner.
+     *
+     * @param any any object
+     */
+    void retrieveVirAttrValues(Any<?, ?, ?> any);
+
+    void updateOnResourcesIfMappingMatches(
+            Any<?, ?, ?> any, AnyUtils anyUtils, String schemaKey,
+            Iterable<? extends ExternalResource> resources, IntMappingType mappingType,
+            PropagationByResource propByRes);
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/AnyTypeClassDataBinder.java
----------------------------------------------------------------------
diff --git a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/AnyTypeClassDataBinder.java b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/AnyTypeClassDataBinder.java
new file mode 100644
index 0000000..18187be
--- /dev/null
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/data/AnyTypeClassDataBinder.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.provisioning.api.data;
+
+import org.apache.syncope.common.lib.to.AnyTypeClassTO;
+import org.apache.syncope.core.persistence.api.entity.AnyTypeClass;
+
+public interface AnyTypeClassDataBinder {
+
+    AnyTypeClass create(AnyTypeClassTO anyTypeClassTO);
+
+    void update(AnyTypeClass anyTypeClass, AnyTypeClassTO anyTypeClassTO);
+
+    AnyTypeClassTO getAnyTypeClassTO(AnyTypeClass anyTypeClass);
+}

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

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultAnyObjectProvisioningManager.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultAnyObjectProvisioningManager.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultAnyObjectProvisioningManager.java
index 1bd2638..fd6bcf1 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultAnyObjectProvisioningManager.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultAnyObjectProvisioningManager.java
@@ -30,6 +30,8 @@ import org.apache.commons.lang3.tuple.Pair;
 import org.apache.syncope.common.lib.mod.AnyObjectMod;
 import org.apache.syncope.common.lib.to.PropagationStatus;
 import org.apache.syncope.common.lib.to.AnyObjectTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.PropagationByResource;
 import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
 import org.apache.syncope.core.persistence.api.entity.task.PropagationTask;
 import org.apache.syncope.core.provisioning.api.AnyObjectProvisioningManager;
@@ -40,6 +42,7 @@ import org.apache.syncope.core.provisioning.api.propagation.PropagationReporter;
 import org.apache.syncope.core.provisioning.api.propagation.PropagationTaskExecutor;
 import org.apache.syncope.core.misc.spring.ApplicationContextProvider;
 import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
+import org.apache.syncope.core.provisioning.api.VirAttrHandler;
 import org.apache.syncope.core.workflow.api.AnyObjectWorkflowAdapter;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -102,6 +105,18 @@ public class DefaultAnyObjectProvisioningManager implements AnyObjectProvisionin
 
         List<PropagationTask> tasks = propagationManager.getAnyObjectUpdateTasks(updated,
                 anyObjectMod.getVirAttrsToRemove(), anyObjectMod.getVirAttrsToUpdate(), null);
+        if (tasks.isEmpty()) {
+            // SYNCOPE-459: take care of user virtual attributes ...
+            PropagationByResource propByResVirAttr = virtAttrHandler.fillVirtual(
+                    updated.getResult(),
+                    AnyTypeKind.ANY_OBJECT,
+                    anyObjectMod.getVirAttrsToRemove(),
+                    anyObjectMod.getVirAttrsToUpdate());
+            tasks.addAll(!propByResVirAttr.isEmpty()
+                    ? propagationManager.getAnyObjectUpdateTasks(updated, null, null, null)
+                    : Collections.<PropagationTask>emptyList());
+        }
+
         PropagationReporter propagationReporter =
                 ApplicationContextProvider.getApplicationContext().getBean(PropagationReporter.class);
         try {

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultGroupProvisioningManager.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultGroupProvisioningManager.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultGroupProvisioningManager.java
index c7bc1c4..5661df4 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultGroupProvisioningManager.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultGroupProvisioningManager.java
@@ -36,6 +36,7 @@ import org.apache.syncope.common.lib.mod.GroupMod;
 import org.apache.syncope.common.lib.to.AttrTO;
 import org.apache.syncope.common.lib.to.PropagationStatus;
 import org.apache.syncope.common.lib.to.GroupTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.PropagationByResource;
 import org.apache.syncope.core.persistence.api.dao.GroupDAO;
 import org.apache.syncope.core.persistence.api.entity.group.Group;
@@ -47,6 +48,7 @@ import org.apache.syncope.core.provisioning.api.propagation.PropagationManager;
 import org.apache.syncope.core.provisioning.api.propagation.PropagationReporter;
 import org.apache.syncope.core.provisioning.api.propagation.PropagationTaskExecutor;
 import org.apache.syncope.core.misc.spring.ApplicationContextProvider;
+import org.apache.syncope.core.provisioning.api.VirAttrHandler;
 import org.apache.syncope.core.workflow.api.GroupWorkflowAdapter;
 
 public class DefaultGroupProvisioningManager implements GroupProvisioningManager {
@@ -65,6 +67,9 @@ public class DefaultGroupProvisioningManager implements GroupProvisioningManager
     @Autowired
     protected GroupDAO groupDAO;
 
+    @Autowired
+    protected VirAttrHandler virtAttrHandler;
+
     @Override
     public Pair<Long, List<PropagationStatus>> create(final GroupTO group) {
         return create(group, Collections.<String>emptySet());
@@ -119,6 +124,18 @@ public class DefaultGroupProvisioningManager implements GroupProvisioningManager
 
         List<PropagationTask> tasks = propagationManager.getGroupUpdateTasks(updated,
                 groupMod.getVirAttrsToRemove(), groupMod.getVirAttrsToUpdate(), excludedResources);
+        if (tasks.isEmpty()) {
+            // SYNCOPE-459: take care of user virtual attributes ...
+            PropagationByResource propByResVirAttr = virtAttrHandler.fillVirtual(
+                    updated.getResult(),
+                    AnyTypeKind.GROUP,
+                    groupMod.getVirAttrsToRemove(),
+                    groupMod.getVirAttrsToUpdate());
+            tasks.addAll(!propByResVirAttr.isEmpty()
+                    ? propagationManager.getGroupUpdateTasks(updated, null, null, null)
+                    : Collections.<PropagationTask>emptyList());
+        }
+
         PropagationReporter propagationReporter =
                 ApplicationContextProvider.getApplicationContext().getBean(PropagationReporter.class);
         try {

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultUserProvisioningManager.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultUserProvisioningManager.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultUserProvisioningManager.java
index 88d3094..656bc75 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultUserProvisioningManager.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/DefaultUserProvisioningManager.java
@@ -30,6 +30,7 @@ import org.apache.syncope.common.lib.mod.StatusMod;
 import org.apache.syncope.common.lib.mod.UserMod;
 import org.apache.syncope.common.lib.to.PropagationStatus;
 import org.apache.syncope.common.lib.to.UserTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.core.persistence.api.dao.UserDAO;
 import org.apache.syncope.core.persistence.api.entity.task.PropagationTask;
 import org.apache.syncope.core.persistence.api.entity.user.User;
@@ -42,6 +43,7 @@ import org.apache.syncope.core.provisioning.api.propagation.PropagationReporter;
 import org.apache.syncope.core.provisioning.api.propagation.PropagationTaskExecutor;
 import org.apache.syncope.core.provisioning.api.sync.ProvisioningResult;
 import org.apache.syncope.core.misc.spring.ApplicationContextProvider;
+import org.apache.syncope.core.provisioning.api.VirAttrHandler;
 import org.apache.syncope.core.workflow.api.UserWorkflowAdapter;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -120,6 +122,7 @@ public class DefaultUserProvisioningManager implements UserProvisioningManager {
             // SYNCOPE-459: take care of user virtual attributes ...
             PropagationByResource propByResVirAttr = virtAttrHandler.fillVirtual(
                     updated.getResult().getKey().getKey(),
+                    AnyTypeKind.USER,
                     userMod.getVirAttrsToRemove(),
                     userMod.getVirAttrsToUpdate());
             tasks.addAll(!propByResVirAttr.isEmpty()

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/VirAttrHandler.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/VirAttrHandler.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/VirAttrHandler.java
deleted file mode 100644
index 6c11f8a..0000000
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/VirAttrHandler.java
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.core.provisioning.java;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.syncope.common.lib.mod.AttrMod;
-import org.apache.syncope.common.lib.to.AttrTO;
-import org.apache.syncope.common.lib.types.AnyTypeKind;
-import org.apache.syncope.common.lib.types.IntMappingType;
-import org.apache.syncope.common.lib.types.MappingPurpose;
-import org.apache.syncope.common.lib.types.PropagationByResource;
-import org.apache.syncope.common.lib.types.ResourceOperation;
-import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
-import org.apache.syncope.core.persistence.api.dao.UserDAO;
-import org.apache.syncope.core.persistence.api.dao.VirAttrDAO;
-import org.apache.syncope.core.persistence.api.dao.VirSchemaDAO;
-import org.apache.syncope.core.persistence.api.entity.Any;
-import org.apache.syncope.core.persistence.api.entity.AnyUtils;
-import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
-import org.apache.syncope.core.persistence.api.entity.VirAttr;
-import org.apache.syncope.core.persistence.api.entity.VirSchema;
-import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
-import org.apache.syncope.core.persistence.api.entity.group.Group;
-import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
-import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
-import org.apache.syncope.core.persistence.api.entity.user.User;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
-import org.springframework.transaction.annotation.Transactional;
-
-@Component
-@Transactional(rollbackFor = { Throwable.class })
-public class VirAttrHandler {
-
-    private static final Logger LOG = LoggerFactory.getLogger(VirAttrHandler.class);
-
-    @Autowired
-    private VirSchemaDAO virSchemaDAO;
-
-    @Autowired
-    private VirAttrDAO virAttrDAO;
-
-    @Autowired
-    private AnyObjectDAO anyObjectDAO;
-
-    @Autowired
-    private UserDAO userDAO;
-
-    @Autowired
-    private AnyUtilsFactory anyUtilsFactory;
-
-    public VirSchema getVirSchema(final String virSchemaName) {
-        VirSchema virtualSchema = null;
-        if (StringUtils.isNotBlank(virSchemaName)) {
-            virtualSchema = virSchemaDAO.find(virSchemaName);
-
-            if (virtualSchema == null) {
-                LOG.debug("Ignoring invalid virtual schema {}", virSchemaName);
-            }
-        }
-
-        return virtualSchema;
-    }
-
-    public void updateOnResourcesIfMappingMatches(final Any<?, ?, ?> any, final AnyUtils anyUtils,
-            final String schemaKey, final Set<ExternalResource> resources, final IntMappingType mappingType,
-            final PropagationByResource propByRes) {
-
-        for (ExternalResource resource : resources) {
-            for (MappingItem mapItem : anyUtils.getMappingItems(
-                    resource.getProvision(any.getType()), MappingPurpose.PROPAGATION)) {
-
-                if (schemaKey.equals(mapItem.getIntAttrName()) && mapItem.getIntMappingType() == mappingType) {
-                    propByRes.add(ResourceOperation.UPDATE, resource.getKey());
-                }
-            }
-        }
-    }
-
-    @SuppressWarnings({ "unchecked", "rawtypes" })
-    public PropagationByResource fillVirtual(final Any any,
-            final Set<String> vAttrsToBeRemoved, final Set<AttrMod> vAttrsToBeUpdated, final AnyUtils anyUtils) {
-
-        PropagationByResource propByRes = new PropagationByResource();
-
-        Set<ExternalResource> externalResources = new HashSet<>();
-        if (any instanceof User) {
-            externalResources.addAll(userDAO.findAllResources((User) any));
-        } else if (any instanceof Group) {
-            externalResources.addAll(((Group) any).getResources());
-        } else if (any instanceof AnyObject) {
-            externalResources.addAll(anyObjectDAO.findAllResources((AnyObject) any));
-        }
-
-        // 1. virtual attributes to be removed
-        for (String vAttrToBeRemoved : vAttrsToBeRemoved) {
-            VirSchema virSchema = getVirSchema(vAttrToBeRemoved);
-            if (virSchema != null) {
-                VirAttr virAttr = any.getVirAttr(virSchema.getKey());
-                if (virAttr == null) {
-                    LOG.debug("No virtual attribute found for schema {}", virSchema.getKey());
-                } else {
-                    any.remove(virAttr);
-                    virAttrDAO.delete(virAttr);
-                }
-
-                for (ExternalResource resource : externalResources) {
-                    for (MappingItem mapItem : anyUtils.getMappingItems(
-                            resource.getProvision(any.getType()), MappingPurpose.PROPAGATION)) {
-
-                        if (virSchema.getKey().equals(mapItem.getIntAttrName())
-                                && mapItem.getIntMappingType() == anyUtils.virIntMappingType()) {
-
-                            propByRes.add(ResourceOperation.UPDATE, resource.getKey());
-
-                            // Using virtual attribute as ConnObjectKey must be avoided
-                            if (mapItem.isConnObjectKey() && virAttr != null && !virAttr.getValues().isEmpty()) {
-                                propByRes.addOldConnObjectKey(resource.getKey(), virAttr.getValues().get(0).toString());
-                            }
-                        }
-                    }
-                }
-            }
-        }
-
-        LOG.debug("Virtual attributes to be removed:\n{}", propByRes);
-
-        // 2. virtual attributes to be updated
-        for (AttrMod vAttrToBeUpdated : vAttrsToBeUpdated) {
-            VirSchema virSchema = getVirSchema(vAttrToBeUpdated.getSchema());
-            VirAttr virAttr = null;
-            if (virSchema != null) {
-                virAttr = any.getVirAttr(virSchema.getKey());
-                if (virAttr == null) {
-                    virAttr = anyUtils.newVirAttr();
-                    virAttr.setSchema(virSchema);
-                    if (virAttr.getSchema() == null) {
-                        LOG.debug("Ignoring {} because no valid schema was found", vAttrToBeUpdated);
-                    } else {
-                        any.add(virAttr);
-                    }
-                }
-            }
-
-            if (virSchema != null && virAttr != null && virAttr.getSchema() != null) {
-                updateOnResourcesIfMappingMatches(any, anyUtils, virSchema.getKey(),
-                        externalResources, anyUtils.derIntMappingType(), propByRes);
-
-                List<String> values = new ArrayList<>(virAttr.getValues());
-                values.removeAll(vAttrToBeUpdated.getValuesToBeRemoved());
-                values.addAll(vAttrToBeUpdated.getValuesToBeAdded());
-
-                virAttr.getValues().clear();
-                virAttr.getValues().addAll(values);
-
-                // Owner cannot be specified before otherwise a virtual attribute remove will be invalidated.
-                virAttr.setOwner(any);
-            }
-        }
-
-        LOG.debug("Virtual attributes to be added:\n{}", propByRes);
-
-        return propByRes;
-    }
-
-    /**
-     * Add virtual attributes and specify values to be propagated.
-     *
-     * @param any any.
-     * @param vAttrs virtual attributes to be added.
-     * @param anyUtils utils
-     */
-    @SuppressWarnings({ "unchecked", "rawtypes" })
-    public void fillVirtual(final Any any, final Collection<AttrTO> vAttrs, final AnyUtils anyUtils) {
-        for (AttrTO attrTO : vAttrs) {
-            VirAttr virAttr = any.getVirAttr(attrTO.getSchema());
-            if (virAttr == null) {
-                VirSchema virSchema = getVirSchema(attrTO.getSchema());
-                if (virSchema != null) {
-                    virAttr = anyUtils.newVirAttr();
-                    virAttr.setSchema(virSchema);
-                    if (virAttr.getSchema() == null) {
-                        LOG.debug("Ignoring {} because no valid schema was found", attrTO);
-                    } else {
-                        virAttr.setOwner(any);
-                        any.add(virAttr);
-                        virAttr.getValues().clear();
-                        virAttr.getValues().addAll(attrTO.getValues());
-                    }
-                }
-            } else {
-                virAttr.getValues().clear();
-                virAttr.getValues().addAll(attrTO.getValues());
-            }
-        }
-    }
-
-    /**
-     * SYNCOPE-459: build virtual attribute changes in case no other changes were made.
-     *
-     * @param key user id
-     * @param vAttrsToBeRemoved virtual attributes to be removed.
-     * @param vAttrsToBeUpdated virtual attributes to be updated.
-     * @return operations to be performed on external resources for virtual attributes changes
-     */
-    public PropagationByResource fillVirtual(
-            final Long key, final Set<String> vAttrsToBeRemoved, final Set<AttrMod> vAttrsToBeUpdated) {
-
-        return fillVirtual(
-                anyObjectDAO.authFind(key),
-                vAttrsToBeRemoved,
-                vAttrsToBeUpdated,
-                anyUtilsFactory.getInstance(AnyTypeKind.USER));
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/VirAttrHandlerImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/VirAttrHandlerImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/VirAttrHandlerImpl.java
new file mode 100644
index 0000000..21626f5
--- /dev/null
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/VirAttrHandlerImpl.java
@@ -0,0 +1,411 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.provisioning.java;
+
+import org.apache.syncope.core.provisioning.api.VirAttrHandler;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.Predicate;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.mod.AttrMod;
+import org.apache.syncope.common.lib.to.AttrTO;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.IntMappingType;
+import org.apache.syncope.common.lib.types.MappingPurpose;
+import org.apache.syncope.common.lib.types.PropagationByResource;
+import org.apache.syncope.common.lib.types.ResourceOperation;
+import org.apache.syncope.core.misc.MappingUtils;
+import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
+import org.apache.syncope.core.persistence.api.dao.GroupDAO;
+import org.apache.syncope.core.persistence.api.dao.UserDAO;
+import org.apache.syncope.core.persistence.api.dao.VirAttrDAO;
+import org.apache.syncope.core.persistence.api.dao.VirSchemaDAO;
+import org.apache.syncope.core.persistence.api.entity.Any;
+import org.apache.syncope.core.persistence.api.entity.AnyType;
+import org.apache.syncope.core.persistence.api.entity.AnyUtils;
+import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
+import org.apache.syncope.core.persistence.api.entity.VirAttr;
+import org.apache.syncope.core.persistence.api.entity.VirSchema;
+import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
+import org.apache.syncope.core.persistence.api.entity.group.Group;
+import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
+import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
+import org.apache.syncope.core.persistence.api.entity.resource.Provision;
+import org.apache.syncope.core.persistence.api.entity.user.User;
+import org.apache.syncope.core.provisioning.api.Connector;
+import org.apache.syncope.core.provisioning.api.ConnectorFactory;
+import org.apache.syncope.core.provisioning.api.cache.VirAttrCache;
+import org.apache.syncope.core.provisioning.api.cache.VirAttrCacheValue;
+import org.identityconnectors.framework.common.objects.Attribute;
+import org.identityconnectors.framework.common.objects.ConnectorObject;
+import org.identityconnectors.framework.common.objects.OperationOptions;
+import org.identityconnectors.framework.common.objects.Uid;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
+
+@Component
+@Transactional(rollbackFor = { Throwable.class })
+public class VirAttrHandlerImpl implements VirAttrHandler {
+
+    private static final Logger LOG = LoggerFactory.getLogger(VirAttrHandler.class);
+
+    @Autowired
+    private VirSchemaDAO virSchemaDAO;
+
+    @Autowired
+    private VirAttrDAO virAttrDAO;
+
+    @Autowired
+    private AnyObjectDAO anyObjectDAO;
+
+    @Autowired
+    private UserDAO userDAO;
+
+    @Autowired
+    private GroupDAO groupDAO;
+
+    @Autowired
+    private AnyUtilsFactory anyUtilsFactory;
+
+    @Autowired
+    private ConnectorFactory connFactory;
+
+    /**
+     * Virtual attribute cache.
+     */
+    @Autowired
+    private VirAttrCache virAttrCache;
+
+    @Override
+    public VirSchema getVirSchema(final String virSchemaName) {
+        VirSchema virtualSchema = null;
+        if (StringUtils.isNotBlank(virSchemaName)) {
+            virtualSchema = virSchemaDAO.find(virSchemaName);
+
+            if (virtualSchema == null) {
+                LOG.debug("Ignoring invalid virtual schema {}", virSchemaName);
+            }
+        }
+
+        return virtualSchema;
+    }
+
+    @Override
+    public void updateOnResourcesIfMappingMatches(final Any<?, ?, ?> any, final AnyUtils anyUtils,
+            final String schemaKey, final Iterable<? extends ExternalResource> resources,
+            final IntMappingType mappingType, final PropagationByResource propByRes) {
+
+        for (ExternalResource resource : resources) {
+            for (MappingItem mapItem : anyUtils.getMappingItems(
+                    resource.getProvision(any.getType()), MappingPurpose.PROPAGATION)) {
+
+                if (schemaKey.equals(mapItem.getIntAttrName()) && mapItem.getIntMappingType() == mappingType) {
+                    propByRes.add(ResourceOperation.UPDATE, resource.getKey());
+                }
+            }
+        }
+    }
+
+    private Iterable<? extends ExternalResource> getAllResources(final Any<?, ?, ?> any) {
+        return any instanceof User
+                ? userDAO.findAllResources((User) any)
+                : any instanceof AnyObject
+                        ? anyObjectDAO.findAllResources((AnyObject) any)
+                        : any instanceof Group
+                                ? ((Group) any).getResources()
+                                : Collections.<ExternalResource>emptySet();
+    }
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    @Override
+    public PropagationByResource fillVirtual(final Any any,
+            final Set<String> vAttrsToBeRemoved, final Set<AttrMod> vAttrsToBeUpdated) {
+
+        AnyUtils anyUtils = anyUtilsFactory.getInstance(any);
+
+        PropagationByResource propByRes = new PropagationByResource();
+
+        Iterable<? extends ExternalResource> externalResources = getAllResources(any);
+
+        // 1. virtual attributes to be removed
+        for (String vAttrToBeRemoved : vAttrsToBeRemoved) {
+            VirSchema virSchema = getVirSchema(vAttrToBeRemoved);
+            if (virSchema != null) {
+                VirAttr virAttr = any.getVirAttr(virSchema.getKey());
+                if (virAttr == null) {
+                    LOG.debug("No virtual attribute found for schema {}", virSchema.getKey());
+                } else {
+                    any.remove(virAttr);
+                    virAttrDAO.delete(virAttr);
+                }
+
+                for (ExternalResource resource : externalResources) {
+                    for (MappingItem mapItem : anyUtils.getMappingItems(
+                            resource.getProvision(any.getType()), MappingPurpose.PROPAGATION)) {
+
+                        if (virSchema.getKey().equals(mapItem.getIntAttrName())
+                                && mapItem.getIntMappingType() == anyUtils.virIntMappingType()) {
+
+                            propByRes.add(ResourceOperation.UPDATE, resource.getKey());
+
+                            // Using virtual attribute as ConnObjectKey must be avoided
+                            if (mapItem.isConnObjectKey() && virAttr != null && !virAttr.getValues().isEmpty()) {
+                                propByRes.addOldConnObjectKey(resource.getKey(), virAttr.getValues().get(0).toString());
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        LOG.debug("Virtual attributes to be removed:\n{}", propByRes);
+
+        // 2. virtual attributes to be updated
+        for (AttrMod vAttrToBeUpdated : vAttrsToBeUpdated) {
+            VirSchema virSchema = getVirSchema(vAttrToBeUpdated.getSchema());
+            if (virSchema != null) {
+                VirAttr virAttr = any.getVirAttr(virSchema.getKey());
+                if (virAttr == null) {
+                    virAttr = anyUtils.newVirAttr();
+                    virAttr.setOwner(any);
+                    virAttr.setSchema(virSchema);
+
+                    any.add(virAttr);
+                }
+
+                updateOnResourcesIfMappingMatches(any, anyUtils, virSchema.getKey(),
+                        externalResources, anyUtils.derIntMappingType(), propByRes);
+
+                List<String> values = new ArrayList<>(virAttr.getValues());
+                values.removeAll(vAttrToBeUpdated.getValuesToBeRemoved());
+                values.addAll(vAttrToBeUpdated.getValuesToBeAdded());
+
+                virAttr.getValues().clear();
+                virAttr.getValues().addAll(values);
+            }
+        }
+
+        LOG.debug("Virtual attributes to be added:\n{}", propByRes);
+
+        return propByRes;
+    }
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    @Override
+    public void fillVirtual(final Any any, final Collection<AttrTO> vAttrs) {
+        AnyUtils anyUtils = anyUtilsFactory.getInstance(any);
+
+        for (AttrTO attrTO : vAttrs) {
+            VirAttr virAttr = any.getVirAttr(attrTO.getSchema());
+            if (virAttr == null) {
+                VirSchema virSchema = getVirSchema(attrTO.getSchema());
+                if (virSchema != null) {
+                    virAttr = anyUtils.newVirAttr();
+                    virAttr.setSchema(virSchema);
+                    if (virAttr.getSchema() == null) {
+                        LOG.debug("Ignoring {} because no valid schema was found", attrTO);
+                    } else {
+                        virAttr.setOwner(any);
+                        any.add(virAttr);
+                        virAttr.getValues().clear();
+                        virAttr.getValues().addAll(attrTO.getValues());
+                    }
+                }
+            } else {
+                virAttr.getValues().clear();
+                virAttr.getValues().addAll(attrTO.getValues());
+            }
+        }
+    }
+
+    private Any<?, ?, ?> find(final Long key, final AnyTypeKind anyTypeKind) {
+        Any<?, ?, ?> result;
+
+        switch (anyTypeKind) {
+            case USER:
+                result = userDAO.authFind(key);
+                break;
+
+            case GROUP:
+                result = groupDAO.authFind(key);
+                break;
+
+            case ANY_OBJECT:
+            default:
+                result = anyObjectDAO.authFind(key);
+        }
+
+        return result;
+    }
+
+    @Transactional
+    @Override
+    public PropagationByResource fillVirtual(
+            final Long key, final AnyTypeKind anyTypeKind,
+            final Set<String> vAttrsToBeRemoved, final Set<AttrMod> vAttrsToBeUpdated) {
+
+        return fillVirtual(
+                find(key, anyTypeKind),
+                vAttrsToBeRemoved,
+                vAttrsToBeUpdated);
+    }
+
+    @Override
+    public void retrieveVirAttrValues(final Any<?, ?, ?> any) {
+        IntMappingType type = any.getType().getKind() == AnyTypeKind.USER
+                ? IntMappingType.UserVirtualSchema
+                : any.getType().getKind() == AnyTypeKind.GROUP
+                        ? IntMappingType.GroupVirtualSchema
+                        : IntMappingType.AnyVirtualSchema;
+
+        Map<String, ConnectorObject> resources = new HashMap<>();
+
+        // -----------------------
+        // Retrieve virtual attribute values if and only if they have not been retrieved yet
+        // -----------------------
+        for (VirAttr<?> virAttr : any.getVirAttrs()) {
+            // reset value set
+            if (virAttr.getValues().isEmpty()) {
+                retrieveVirAttrValue(any, virAttr, type, resources);
+            }
+        }
+        // -----------------------
+    }
+
+    private void retrieveVirAttrValue(
+            final Any<?, ?, ?> any,
+            final VirAttr<?> virAttr,
+            final IntMappingType type,
+            final Map<String, ConnectorObject> externalResources) {
+
+        String schemaName = virAttr.getSchema().getKey();
+        VirAttrCacheValue virAttrCacheValue = virAttrCache.get(any.getType().getKey(), any.getKey(), schemaName);
+
+        LOG.debug("Retrieve values for virtual attribute {} ({})", schemaName, type);
+
+        if (virAttrCache.isValidEntry(virAttrCacheValue)) {
+            // cached ...
+            LOG.debug("Values found in cache {}", virAttrCacheValue);
+            virAttr.getValues().clear();
+            virAttr.getValues().addAll(new ArrayList<>(virAttrCacheValue.getValues()));
+        } else {
+            // not cached ...
+            LOG.debug("Need one or more remote connections");
+
+            VirAttrCacheValue toBeCached = new VirAttrCacheValue();
+
+            AnyUtils anyUtils = anyUtilsFactory.getInstance(any);
+
+            for (ExternalResource resource : getTargetResources(virAttr, type, anyUtils, any.getType())) {
+                Provision provision = resource.getProvision(any.getType());
+                LOG.debug("Search values into {},{}", resource, provision);
+
+                try {
+                    List<MappingItem> mappings = anyUtils.getMappingItems(provision, MappingPurpose.BOTH);
+
+                    ConnectorObject connectorObject;
+                    if (externalResources.containsKey(resource.getKey())) {
+                        connectorObject = externalResources.get(resource.getKey());
+                    } else {
+                        LOG.debug("Perform connection to {}", resource.getKey());
+                        String connObjectKey = anyUtils.getConnObjectKeyItem(provision) == null
+                                ? null
+                                : MappingUtils.getConnObjectKeyValue(any, provision);
+
+                        if (StringUtils.isBlank(connObjectKey)) {
+                            throw new IllegalArgumentException("No ConnObjectKey found for " + resource.getKey());
+                        }
+
+                        Connector connector = connFactory.getConnector(resource);
+
+                        OperationOptions oo =
+                                connector.getOperationOptions(MappingUtils.getMatchingMappingItems(mappings, type));
+
+                        connectorObject =
+                                connector.getObject(provision.getObjectClass(), new Uid(connObjectKey), oo);
+                        externalResources.put(resource.getKey(), connectorObject);
+                    }
+
+                    if (connectorObject != null) {
+                        // ask for searched virtual attribute value
+                        Collection<MappingItem> virAttrMappings =
+                                MappingUtils.getMatchingMappingItems(mappings, schemaName, type);
+
+                        // the same virtual attribute could be mapped with one or more external attribute 
+                        for (MappingItem mapping : virAttrMappings) {
+                            Attribute attribute = connectorObject.getAttributeByName(mapping.getExtAttrName());
+
+                            if (attribute != null && attribute.getValue() != null) {
+                                for (Object obj : attribute.getValue()) {
+                                    if (obj != null) {
+                                        virAttr.getValues().add(obj.toString());
+                                    }
+                                }
+                            }
+                        }
+
+                        toBeCached.setResourceValues(resource.getKey(), new HashSet<>(virAttr.getValues()));
+
+                        LOG.debug("Retrieved values {}", virAttr.getValues());
+                    }
+                } catch (Exception e) {
+                    LOG.error("Error reading connector object from {}", resource.getKey(), e);
+
+                    if (virAttrCacheValue != null) {
+                        toBeCached.forceExpiring();
+                        LOG.debug("Search for a cached value (even expired!) ...");
+                        final Set<String> cachedValues = virAttrCacheValue.getValues(resource.getKey());
+                        if (cachedValues != null) {
+                            LOG.debug("Use cached value {}", cachedValues);
+                            virAttr.getValues().addAll(cachedValues);
+                            toBeCached.setResourceValues(resource.getKey(), new HashSet<>(cachedValues));
+                        }
+                    }
+                }
+            }
+
+            virAttrCache.put(any.getType().getKey(), any.getKey(), schemaName, toBeCached);
+        }
+    }
+
+    private Collection<ExternalResource> getTargetResources(
+            final VirAttr<?> attr, final IntMappingType type, final AnyUtils anyUtils, final AnyType anyType) {
+
+        return CollectionUtils.select(getAllResources(attr.getOwner()), new Predicate<ExternalResource>() {
+
+            @Override
+            public boolean evaluate(final ExternalResource resource) {
+                return resource.getProvision(anyType) != null
+                        && !MappingUtils.getMatchingMappingItems(
+                                anyUtils.getMappingItems(resource.getProvision(anyType), MappingPurpose.BOTH),
+                                attr.getSchema().getKey(), type).isEmpty();
+            }
+        });
+    }
+}


[21/21] syncope git commit: [SYNCOPE-666] All tests are green, time to add more

Posted by il...@apache.org.
[SYNCOPE-666] All tests are green, time to add more


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

Branch: refs/heads/SYNCOPE-666
Commit: dd88efbd0ec6fabb98728a84a6fe103f285433d7
Parents: d8c9479
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Fri Jun 5 17:11:22 2015 +0200
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Fri Jun 5 17:11:22 2015 +0200

----------------------------------------------------------------------
 .travis.yml                                     |   3 +-
 .../console/rest/ConnectorRestClient.java       |   2 +-
 .../syncope/common/lib/AnyOperations.java       |  91 ++++
 .../lib/SyncopeClientCompositeException.java    |  14 +-
 .../common/lib/SyncopeClientException.java      |   8 +-
 .../common/lib/jaxb/GenericMapEntryType.java    |  59 +++
 .../syncope/common/lib/jaxb/GenericMapType.java |  49 +++
 .../common/lib/jaxb/XmlGenericMapAdapter.java   |  52 +++
 .../apache/syncope/common/lib/mod/AnyMod.java   |  18 +
 .../common/lib/report/UserReportletConf.java    |   1 +
 .../common/lib/search/SearchableFields.java     |   9 +-
 .../lib/to/AbstractProvisioningTaskTO.java      |   8 +-
 .../syncope/common/lib/to/AnyObjectTO.java      |  57 +++
 .../org/apache/syncope/common/lib/to/AnyTO.java |  59 +--
 .../syncope/common/lib/to/AnyTypeClassTO.java   |  73 ++++
 .../apache/syncope/common/lib/to/AnyTypeTO.java |  66 +++
 .../apache/syncope/common/lib/to/AttrTO.java    |  13 +-
 .../syncope/common/lib/to/BulkActionResult.java |  88 +---
 .../apache/syncope/common/lib/to/GroupTO.java   |  43 +-
 .../syncope/common/lib/to/MembershipTO.java     |  10 +-
 .../syncope/common/lib/to/NotificationTO.java   |   9 +
 .../syncope/common/lib/to/PushTaskTO.java       |  11 +-
 .../syncope/common/lib/to/RelationshipTO.java   |  10 -
 .../syncope/common/lib/to/ResourceTO.java       |  14 +-
 .../syncope/common/lib/to/SyncTaskTO.java       |  10 +
 .../apache/syncope/common/lib/to/UserTO.java    |  64 +++
 .../common/lib/to/WorkflowFormPropertyTO.java   |   7 +
 .../syncope/common/lib/types/AnyTypeKind.java   |  20 +-
 .../common/lib/types/ClientExceptionType.java   |   4 +-
 .../syncope/common/lib/types/Entitlement.java   |  20 +
 .../rest/api/service/AnyTypeClassService.java   |  97 +++++
 .../common/rest/api/service/AnyTypeService.java |  97 +++++
 .../common/rest/api/service/RoleService.java    |  26 +-
 .../common/rest/api/service/SchemaService.java  |   2 +-
 .../common/rest/api/service/UserService.java    |   2 +-
 .../rest/api/service/WorkflowService.java       |   2 +-
 .../syncope/core/logic/AnyTypeClassLogic.java   | 131 ++++++
 .../apache/syncope/core/logic/AnyTypeLogic.java | 131 ++++++
 .../core/logic/LogicInvocationHandler.java      |  13 +-
 .../syncope/core/logic/ResourceLogic.java       |   2 +-
 .../apache/syncope/core/logic/UserLogic.java    |   4 +-
 .../core/logic/init/JobInstanceLoaderImpl.java  |  36 +-
 .../core/logic/report/UserReportlet.java        |  39 +-
 .../syncope/core/misc/ConnObjectUtils.java      | 269 +++---------
 .../apache/syncope/core/misc/MappingUtils.java  |  25 +-
 .../syncope/core/misc/jexl/JexlUtils.java       |  12 +-
 .../api/dao/UnallowedSchemaException.java       |  29 ++
 .../api/entity/anyobject/AnyObject.java         |   4 +-
 .../api/entity/task/ProvisioningTask.java       |   4 +-
 .../core/persistence/api/entity/user/User.java  |   3 +-
 .../persistence/jpa/dao/AbstractAnyDAO.java     |   3 +-
 .../persistence/jpa/dao/JPADerSchemaDAO.java    |   4 +-
 .../persistence/jpa/dao/JPAPlainSchemaDAO.java  |   4 +-
 .../persistence/jpa/dao/JPAVirSchemaDAO.java    |   4 +-
 .../persistence/jpa/entity/AbstractAttr.java    |   3 +-
 .../persistence/jpa/entity/AbstractDerAttr.java |  12 -
 .../persistence/jpa/entity/AbstractVirAttr.java |  12 -
 .../jpa/entity/anyobject/JPAADerAttr.java       |   9 +
 .../jpa/entity/anyobject/JPAAVirAttr.java       |   9 +
 .../jpa/entity/anyobject/JPAAnyObject.java      |   4 +-
 .../jpa/entity/group/JPAGDerAttr.java           |   9 +
 .../jpa/entity/group/JPAGVirAttr.java           |   9 +
 .../jpa/entity/task/JPAAnyTemplate.java         |   4 +-
 .../jpa/entity/task/JPAPushTask.java            |   6 +-
 .../jpa/entity/task/JPASyncTask.java            |   6 +-
 .../jpa/entity/user/JPAUDerAttr.java            |   9 +
 .../jpa/entity/user/JPAUPlainAttr.java          |   3 -
 .../jpa/entity/user/JPAUVirAttr.java            |   9 +
 .../persistence/jpa/entity/user/JPAUser.java    |   5 +-
 .../resources/META-INF/spring-orm-oracle.xml    |  50 +++
 .../resources/META-INF/spring-orm-sqlserver.xml |  50 +++
 .../src/main/resources/META-INF/spring-orm.xml  |  50 +++
 .../persistence/jpa/entity/VirAttrTest.java     |   4 +-
 .../jpa/relationship/AnyTypeTest.java           |   7 +-
 .../src/test/resources/content.xml              |  49 ++-
 .../core/provisioning/api/VirAttrHandler.java   |  71 ++++
 .../api/data/AnyTypeClassDataBinder.java        |  31 ++
 .../api/data/AnyTypeDataBinder.java             |  31 ++
 .../DefaultAnyObjectProvisioningManager.java    |  15 +
 .../java/DefaultGroupProvisioningManager.java   |  17 +
 .../java/DefaultUserProvisioningManager.java    |   3 +
 .../core/provisioning/java/VirAttrHandler.java  | 238 -----------
 .../provisioning/java/VirAttrHandlerImpl.java   | 411 +++++++++++++++++++
 .../java/data/AbstractAnyDataBinder.java        | 262 +++++++-----
 .../java/data/AnyObjectDataBinderImpl.java      |  99 ++++-
 .../java/data/AnyTypeClassDataBinderImpl.java   | 115 ++++++
 .../java/data/AnyTypeDataBinderImpl.java        |  90 ++++
 .../java/data/ConfigurationDataBinderImpl.java  |   4 +-
 .../java/data/GroupDataBinderImpl.java          |   6 +-
 .../java/data/NotificationDataBinderImpl.java   |  30 +-
 .../java/data/ResourceDataBinderImpl.java       |  40 +-
 .../java/data/RoleDataBinderImpl.java           |   2 +-
 .../java/data/SchemaDataBinderImpl.java         |   2 +-
 .../java/data/TaskDataBinderImpl.java           | 177 ++++----
 .../java/data/UserDataBinderImpl.java           | 122 ++++--
 .../notification/NotificationManagerImpl.java   |  18 +-
 .../AbstractPropagationTaskExecutor.java        |  20 +-
 .../LDAPMembershipPropagationActions.java       |   4 +-
 .../propagation/PropagationManagerImpl.java     |  24 +-
 .../java/sync/AbstractProvisioningJob.java      |   3 +-
 .../java/sync/AbstractPushResultHandler.java    |   6 +-
 .../java/sync/AbstractSyncResultHandler.java    |  29 +-
 .../java/sync/AbstractSyncopeResultHandler.java |   5 +-
 .../java/sync/GroupSyncResultHandlerImpl.java   |   6 +-
 .../java/sync/LDAPMembershipSyncActions.java    |   8 +-
 .../provisioning/java/sync/PushJobImpl.java     |  36 +-
 .../provisioning/java/sync/SyncJobImpl.java     |  12 +-
 .../core/provisioning/java/sync/SyncUtils.java  |  62 ++-
 .../java/data/ResourceDataBinderTest.java       |   2 +-
 .../rest/cxf/RestServiceExceptionMapper.java    |   3 +
 .../cxf/service/AnyTypeClassServiceImpl.java    |  67 +++
 .../rest/cxf/service/AnyTypeServiceImpl.java    |  67 +++
 .../rest/cxf/service/ConnectorServiceImpl.java  |   9 +-
 .../core/rest/cxf/service/GroupServiceImpl.java |  34 +-
 .../rest/cxf/service/ResourceServiceImpl.java   |  12 +-
 .../core/rest/cxf/service/TaskServiceImpl.java  |  14 +-
 .../core/rest/cxf/service/UserServiceImpl.java  |  46 ++-
 .../activiti/ActivitiUserWorkflowAdapter.java   |  12 +-
 .../core/workflow/activiti/ActivitiUtils.java   |  39 ++
 .../workflow/activiti/SyncopeUserManager.java   |   4 +-
 .../main/resources/workflowActivitiContext.xml  |   2 +
 .../camel/processor/GroupUpdateProcessor.java   |  23 +-
 .../camel/processor/UserUpdateProcessor.java    |  12 +-
 .../main/resources/all/provisioning.properties  |   2 +-
 .../src/main/resources/userWorkflow.bpmn20.xml  |  12 +-
 .../fit/core/reference/AbstractITCase.java      |  12 +-
 .../fit/core/reference/AbstractTaskITCase.java  |  16 +-
 .../fit/core/reference/CamelRouteITCase.java    |   8 +
 .../fit/core/reference/ConfigurationITCase.java |  92 -----
 .../fit/core/reference/ConnectorITCase.java     |   6 +-
 .../core/reference/ExceptionMapperITCase.java   |   9 +
 .../syncope/fit/core/reference/GroupITCase.java |  51 ++-
 .../fit/core/reference/PlainSchemaITCase.java   |  30 +-
 .../fit/core/reference/PushTaskITCase.java      |  70 ++--
 .../fit/core/reference/ResourceITCase.java      |  20 +-
 .../fit/core/reference/SyncTaskITCase.java      |  55 ++-
 .../syncope/fit/core/reference/UserITCase.java  |  51 ++-
 .../fit/core/reference/UserWorkflowITCase.java  |  29 +-
 .../fit/core/reference/VirAttrITCase.java       |   7 +-
 139 files changed, 3540 insertions(+), 1429 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/.travis.yml
----------------------------------------------------------------------
diff --git a/.travis.yml b/.travis.yml
index e17fd2c..0e6f5c4 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -19,7 +19,6 @@ jdk:
 # default install is mvn install --quiet -DskipTests=true
 install: mvn --show-version --quiet -P all,skipTests
 #invoker.streamLogs: we cannot access to log files through Travis web ui, so display everything in the console
-#script: mvn --show-version --quiet clean install -Dinvoker.streamLogs=true
-script: mvn --show-version --quiet -PskipTests -Dinvoker.streamLogs=true
+script: mvn --show-version --quiet clean install -Dinvoker.streamLogs=true
 notifications:
   webhooks: http://rovere.tirasa.net/cgi-bin/travis.cgi

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/client/console/src/main/java/org/apache/syncope/client/console/rest/ConnectorRestClient.java
----------------------------------------------------------------------
diff --git a/client/console/src/main/java/org/apache/syncope/client/console/rest/ConnectorRestClient.java b/client/console/src/main/java/org/apache/syncope/client/console/rest/ConnectorRestClient.java
index a093dbd..e6f8488 100644
--- a/client/console/src/main/java/org/apache/syncope/client/console/rest/ConnectorRestClient.java
+++ b/client/console/src/main/java/org/apache/syncope/client/console/rest/ConnectorRestClient.java
@@ -172,7 +172,7 @@ public class ConnectorRestClient extends BaseRestClient {
         try {
             check = getService(ResourceService.class).check(resourceTO);
         } catch (Exception e) {
-            LOG.error("Connector not found {}", resourceTO.getConnectorId(), e);
+            LOG.error("Connector not found {}", resourceTO.getConnector(), e);
         }
 
         return check;

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/common/lib/src/main/java/org/apache/syncope/common/lib/AnyOperations.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/AnyOperations.java b/common/lib/src/main/java/org/apache/syncope/common/lib/AnyOperations.java
index cab3239..e8bcedb 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/AnyOperations.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/AnyOperations.java
@@ -29,13 +29,17 @@ import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.lang3.SerializationUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.mod.AnyMod;
+import org.apache.syncope.common.lib.mod.AnyObjectMod;
 import org.apache.syncope.common.lib.mod.AttrMod;
 import org.apache.syncope.common.lib.mod.ReferenceMod;
 import org.apache.syncope.common.lib.mod.GroupMod;
 import org.apache.syncope.common.lib.mod.UserMod;
+import org.apache.syncope.common.lib.to.AnyObjectTO;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.to.AttrTO;
 import org.apache.syncope.common.lib.to.GroupTO;
+import org.apache.syncope.common.lib.to.MembershipTO;
+import org.apache.syncope.common.lib.to.RelationshipTO;
 import org.apache.syncope.common.lib.to.UserTO;
 
 /**
@@ -193,6 +197,63 @@ public final class AnyOperations {
     /**
      * Calculate modifications needed by first in order to be equal to second.
      *
+     * @param updated updated AnyObjectTO
+     * @param original original AnyObjectTO
+     * @return AnyObjectMod containing differences
+     */
+    public static AnyObjectMod diff(final AnyObjectTO updated, final AnyObjectTO original) {
+        return diff(updated, original, false);
+    }
+
+    /**
+     * Calculate modifications needed by first in order to be equal to second.
+     *
+     * @param updated updated AnyObjectTO
+     * @param original original AnyObjectTO
+     * @param incremental perform incremental diff (without removing existing info)
+     * @return AnyObjectMod containing differences
+     */
+    public static AnyObjectMod diff(final AnyObjectTO updated, final AnyObjectTO original, final boolean incremental) {
+        AnyObjectMod result = new AnyObjectMod();
+
+        diff(updated, original, result, incremental);
+
+        // 1. relationships
+        Map<Long, RelationshipTO> updatedRels = updated.getRelationshipMap();
+        Map<Long, RelationshipTO> originalRels = original.getRelationshipMap();
+
+        for (Map.Entry<Long, RelationshipTO> entry : updatedRels.entrySet()) {
+            if (!originalRels.containsKey(entry.getKey())) {
+                result.getRelationshipsToAdd().add(entry.getKey());
+            }
+        }
+        if (!incremental) {
+            Set<Long> originalGroups = new HashSet<>(originalRels.keySet());
+            originalGroups.removeAll(updatedRels.keySet());
+            result.getRelationshipsToRemove().addAll(originalGroups);
+        }
+
+        // 2. memberships
+        Map<Long, MembershipTO> updatedMembs = updated.getMembershipMap();
+        Map<Long, MembershipTO> originalMembs = original.getMembershipMap();
+
+        for (Map.Entry<Long, MembershipTO> entry : updatedMembs.entrySet()) {
+            if (!originalMembs.containsKey(entry.getKey())) {
+                result.getMembershipsToAdd().add(entry.getKey());
+            }
+        }
+        if (!incremental) {
+            Set<Long> originalGroups = new HashSet<>(originalMembs.keySet());
+            originalGroups.removeAll(updatedMembs.keySet());
+            result.getMembershipsToRemove().addAll(originalGroups);
+        }
+
+        return result;
+    }
+
+    /**
+     * Calculate modifications needed by first in order to be equal to second.
+     *
      * @param updated updated UserTO
      * @param original original UserTO
      * @return UserMod containing differences
@@ -248,6 +309,36 @@ public final class AnyOperations {
         result.getRolesToRemove().addAll(CollectionUtils.subtract(original.getRoles(), updated.getRoles()));
         result.getRolesToAdd().addAll(CollectionUtils.subtract(updated.getRoles(), original.getRoles()));
 
+        // 5. relationships
+        Map<Long, RelationshipTO> updatedRels = updated.getRelationshipMap();
+        Map<Long, RelationshipTO> originalRels = original.getRelationshipMap();
+
+        for (Map.Entry<Long, RelationshipTO> entry : updatedRels.entrySet()) {
+            if (!originalRels.containsKey(entry.getKey())) {
+                result.getRelationshipsToAdd().add(entry.getKey());
+            }
+        }
+        if (!incremental) {
+            Set<Long> originalGroups = new HashSet<>(originalRels.keySet());
+            originalGroups.removeAll(updatedRels.keySet());
+            result.getRelationshipsToRemove().addAll(originalGroups);
+        }
+
+        // 6. memberships
+        Map<Long, MembershipTO> updatedMembs = updated.getMembershipMap();
+        Map<Long, MembershipTO> originalMembs = original.getMembershipMap();
+
+        for (Map.Entry<Long, MembershipTO> entry : updatedMembs.entrySet()) {
+            if (!originalMembs.containsKey(entry.getKey())) {
+                result.getMembershipsToAdd().add(entry.getKey());
+            }
+        }
+        if (!incremental) {
+            Set<Long> originalGroups = new HashSet<>(originalMembs.keySet());
+            originalGroups.removeAll(updatedMembs.keySet());
+            result.getMembershipsToRemove().addAll(originalGroups);
+        }
+
         return result;
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/common/lib/src/main/java/org/apache/syncope/common/lib/SyncopeClientCompositeException.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/SyncopeClientCompositeException.java b/common/lib/src/main/java/org/apache/syncope/common/lib/SyncopeClientCompositeException.java
index d139bda..ebdc5ae 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/SyncopeClientCompositeException.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/SyncopeClientCompositeException.java
@@ -21,6 +21,8 @@ package org.apache.syncope.common.lib;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Set;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.Predicate;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
 
 public class SyncopeClientCompositeException extends SyncopeClientException {
@@ -66,7 +68,17 @@ public class SyncopeClientCompositeException extends SyncopeClientException {
                     + ClientExceptionType.class.getName() + " set");
         }
 
-        return exceptions.add(exception);
+        SyncopeClientException alreadyAdded = CollectionUtils.find(exceptions, new Predicate<SyncopeClientException>() {
+
+            @Override
+            public boolean evaluate(final SyncopeClientException ex) {
+                return ex.getType() == exception.getType();
+            }
+        });
+
+        return alreadyAdded == null
+                ? exceptions.add(exception)
+                : alreadyAdded.getElements().addAll(exception.getElements());
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/common/lib/src/main/java/org/apache/syncope/common/lib/SyncopeClientException.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/SyncopeClientException.java b/common/lib/src/main/java/org/apache/syncope/common/lib/SyncopeClientException.java
index 8d015f2..f17d5e5 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/SyncopeClientException.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/SyncopeClientException.java
@@ -18,8 +18,8 @@
  */
 package org.apache.syncope.common.lib;
 
-import java.util.ArrayList;
-import java.util.List;
+import java.util.HashSet;
+import java.util.Set;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
 
 public class SyncopeClientException extends RuntimeException {
@@ -28,7 +28,7 @@ public class SyncopeClientException extends RuntimeException {
 
     private ClientExceptionType type;
 
-    private final List<String> elements = new ArrayList<>();
+    private final Set<String> elements = new HashSet<>();
 
     public static SyncopeClientException build(final ClientExceptionType type) {
         if (type == ClientExceptionType.Composite) {
@@ -66,7 +66,7 @@ public class SyncopeClientException extends RuntimeException {
         this.type = type;
     }
 
-    public List<String> getElements() {
+    public Set<String> getElements() {
         return elements;
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/common/lib/src/main/java/org/apache/syncope/common/lib/jaxb/GenericMapEntryType.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/jaxb/GenericMapEntryType.java b/common/lib/src/main/java/org/apache/syncope/common/lib/jaxb/GenericMapEntryType.java
new file mode 100644
index 0000000..2d30612
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/jaxb/GenericMapEntryType.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2011 John Yeary <jy...@bluelotussoftware.com>.
+ * Copyright 2011 Bluelotus Software, LLC.
+ *
+ * Licensed 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.
+ */
+/*
+ * $Id: MapEntryType.java 399 2011-12-03 04:22:50Z jyeary $
+ */
+package org.apache.syncope.common.lib.jaxb;
+
+import java.util.Map;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+
+@XmlAccessorType(XmlAccessType.PROPERTY)
+public class GenericMapEntryType<K, V> {
+
+    private K key;
+
+    private V value;
+
+    public GenericMapEntryType() {
+    }
+
+    public GenericMapEntryType(final Map.Entry<K, V> e) {
+        key = e.getKey();
+        value = e.getValue();
+    }
+
+    @XmlElement
+    public K getKey() {
+        return key;
+    }
+
+    public void setKey(final K key) {
+        this.key = key;
+    }
+
+    @XmlElement
+    public V getValue() {
+        return value;
+    }
+
+    public void setValue(final V value) {
+        this.value = value;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/common/lib/src/main/java/org/apache/syncope/common/lib/jaxb/GenericMapType.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/jaxb/GenericMapType.java b/common/lib/src/main/java/org/apache/syncope/common/lib/jaxb/GenericMapType.java
new file mode 100644
index 0000000..491a860
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/jaxb/GenericMapType.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2011 John Yeary <jy...@bluelotussoftware.com>.
+ * Copyright 2011 Bluelotus Software, LLC.
+ *
+ * Licensed 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.
+ */
+/*
+ * $Id: MapType.java 399 2011-12-03 04:22:50Z jyeary $
+ */
+package org.apache.syncope.common.lib.jaxb;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+public class GenericMapType<K, V> {
+
+    private final List<GenericMapEntryType<K, V>> entry = new ArrayList<>();
+
+    public GenericMapType() {
+    }
+
+    public GenericMapType(final Map<K, V> map) {
+        for (Map.Entry<K, V> e : map.entrySet()) {
+            entry.add(new GenericMapEntryType<>(e));
+        }
+    }
+
+    public List<GenericMapEntryType<K, V>> getEntry() {
+        return entry;
+    }
+
+    public void setEntry(final List<GenericMapEntryType<K, V>> entry) {
+        this.entry.clear();
+        if (entry != null) {
+            this.entry.addAll(entry);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/common/lib/src/main/java/org/apache/syncope/common/lib/jaxb/XmlGenericMapAdapter.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/jaxb/XmlGenericMapAdapter.java b/common/lib/src/main/java/org/apache/syncope/common/lib/jaxb/XmlGenericMapAdapter.java
new file mode 100644
index 0000000..1b10d5f
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/jaxb/XmlGenericMapAdapter.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2011 John Yeary <jy...@bluelotussoftware.com>.
+ * Copyright 2011 Bluelotus Software, LLC.
+ *
+ * Licensed 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.
+ */
+/*
+ * $Id: XmlGenericMapAdapter.java 399 2011-12-03 04:22:50Z jyeary $
+ */
+package org.apache.syncope.common.lib.jaxb;
+
+import java.util.HashMap;
+import java.util.Map;
+import javax.xml.bind.annotation.adapters.XmlAdapter;
+
+public class XmlGenericMapAdapter<K, V> extends XmlAdapter<GenericMapType<K, V>, Map<K, V>> {
+
+    @Override
+    public Map<K, V> unmarshal(final GenericMapType<K, V> v) throws Exception {
+        Map<K, V> map = new HashMap<>();
+
+        for (GenericMapEntryType<K, V> mapEntryType : v.getEntry()) {
+            map.put(mapEntryType.getKey(), mapEntryType.getValue());
+        }
+
+        return map;
+    }
+
+    @Override
+    public GenericMapType<K, V> marshal(final Map<K, V> v) throws Exception {
+        GenericMapType<K, V> mapType = new GenericMapType<>();
+
+        for (Map.Entry<K, V> entry : v.entrySet()) {
+            GenericMapEntryType<K, V> mapEntryType = new GenericMapEntryType<>();
+            mapEntryType.setKey(entry.getKey());
+            mapEntryType.setValue(entry.getValue());
+            mapType.getEntry().add(mapEntryType);
+        }
+
+        return mapType;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/common/lib/src/main/java/org/apache/syncope/common/lib/mod/AnyMod.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/mod/AnyMod.java b/common/lib/src/main/java/org/apache/syncope/common/lib/mod/AnyMod.java
index ec508c9..e5fcb85 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/mod/AnyMod.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/mod/AnyMod.java
@@ -35,6 +35,10 @@ public abstract class AnyMod extends AbstractBaseBean {
 
     private String realm;
 
+    protected final Set<String> auxClassesToAdd = new HashSet<>();
+
+    protected final Set<String> auxClassesToRemove = new HashSet<>();
+
     protected final Set<AttrMod> plainAttrsToUpdate = new HashSet<>();
 
     protected final Set<String> plainAttrsToRemove = new HashSet<>();
@@ -67,6 +71,20 @@ public abstract class AnyMod extends AbstractBaseBean {
         this.realm = realm;
     }
 
+    @XmlElementWrapper(name = "auxClassesToAdd")
+    @XmlElement(name = "class")
+    @JsonProperty("auxClassesToAdd")
+    public Set<String> getAuxClassesToAdd() {
+        return auxClassesToAdd;
+    }
+
+    @XmlElementWrapper(name = "auxClassesToRemove")
+    @XmlElement(name = "class")
+    @JsonProperty("auxClassesToRemove")
+    public Set<String> getAuxClassesToRemove() {
+        return auxClassesToRemove;
+    }
+
     @XmlElementWrapper(name = "plainAttrsToRemove")
     @XmlElement(name = "attribute")
     @JsonProperty("plainAttrsToRemove")

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/common/lib/src/main/java/org/apache/syncope/common/lib/report/UserReportletConf.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/report/UserReportletConf.java b/common/lib/src/main/java/org/apache/syncope/common/lib/report/UserReportletConf.java
index 72daf7b..afc459e 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/report/UserReportletConf.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/report/UserReportletConf.java
@@ -44,6 +44,7 @@ public class UserReportletConf extends AbstractAnyReportletConf {
         changePwdDate,
         passwordHistorySize,
         failedLoginCount,
+        relationships,
         memberships,
         resources
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/common/lib/src/main/java/org/apache/syncope/common/lib/search/SearchableFields.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/search/SearchableFields.java b/common/lib/src/main/java/org/apache/syncope/common/lib/search/SearchableFields.java
index 9a68a8d..6443eea 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/search/SearchableFields.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/search/SearchableFields.java
@@ -25,10 +25,7 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Map;
 import org.apache.commons.lang3.ArrayUtils;
-import org.apache.syncope.common.lib.to.AnyObjectTO;
 import org.apache.syncope.common.lib.to.AnyTO;
-import org.apache.syncope.common.lib.to.GroupTO;
-import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 
 public final class SearchableFields {
@@ -38,11 +35,7 @@ public final class SearchableFields {
     };
 
     public static List<String> get(final AnyTypeKind anyTypeKind) {
-        return get(anyTypeKind == AnyTypeKind.USER
-                ? UserTO.class
-                : anyTypeKind == AnyTypeKind.GROUP
-                        ? GroupTO.class
-                        : AnyObjectTO.class);
+        return get(anyTypeKind.getToClass());
     }
 
     public static List<String> get(final Class<? extends AnyTO> anyRef) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/common/lib/src/main/java/org/apache/syncope/common/lib/to/AbstractProvisioningTaskTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/AbstractProvisioningTaskTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/AbstractProvisioningTaskTO.java
index c1dcf1c..cd63bcd 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/AbstractProvisioningTaskTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/AbstractProvisioningTaskTO.java
@@ -19,8 +19,8 @@
 package org.apache.syncope.common.lib.to;
 
 import com.fasterxml.jackson.annotation.JsonProperty;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.HashSet;
+import java.util.Set;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlElementWrapper;
 import javax.xml.bind.annotation.XmlRootElement;
@@ -50,7 +50,7 @@ public class AbstractProvisioningTaskTO extends SchedTaskTO {
 
     private MatchingRule matchingRule;
 
-    private final List<String> actionsClassNames = new ArrayList<>();
+    private final Set<String> actionsClassNames = new HashSet<>();
 
     public String getResource() {
         return resource;
@@ -95,7 +95,7 @@ public class AbstractProvisioningTaskTO extends SchedTaskTO {
     @XmlElementWrapper(name = "actionsClassNames")
     @XmlElement(name = "actionsClassName")
     @JsonProperty("actionsClassNames")
-    public List<String> getActionsClassNames() {
+    public Set<String> getActionsClassNames() {
         return actionsClassNames;
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/common/lib/src/main/java/org/apache/syncope/common/lib/to/AnyObjectTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/AnyObjectTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/AnyObjectTO.java
index 6d2eb1b..f5599de 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/AnyObjectTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/AnyObjectTO.java
@@ -18,6 +18,15 @@
  */
 package org.apache.syncope.common.lib.to;
 
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlType;
 
@@ -27,4 +36,52 @@ public class AnyObjectTO extends AnyTO {
 
     private static final long serialVersionUID = 8841697496476959639L;
 
+    private final List<RelationshipTO> relationships = new ArrayList<>();
+
+    private final List<MembershipTO> memberships = new ArrayList<>();
+
+    private final List<Long> dynGroups = new ArrayList<>();
+
+    @XmlElementWrapper(name = "relationships")
+    @XmlElement(name = "relationship")
+    @JsonProperty("relationships")
+    public List<RelationshipTO> getRelationships() {
+        return relationships;
+    }
+
+    @JsonIgnore
+    public Map<Long, RelationshipTO> getRelationshipMap() {
+        Map<Long, RelationshipTO> result = new HashMap<>(getRelationships().size());
+        for (RelationshipTO membership : getRelationships()) {
+            result.put(membership.getRightKey(), membership);
+        }
+        result = Collections.unmodifiableMap(result);
+
+        return result;
+    }
+
+    @XmlElementWrapper(name = "memberships")
+    @XmlElement(name = "membership")
+    @JsonProperty("memberships")
+    public List<MembershipTO> getMemberships() {
+        return memberships;
+    }
+
+    @JsonIgnore
+    public Map<Long, MembershipTO> getMembershipMap() {
+        Map<Long, MembershipTO> result = new HashMap<>(getMemberships().size());
+        for (MembershipTO membership : getMemberships()) {
+            result.put(membership.getRightKey(), membership);
+        }
+        result = Collections.unmodifiableMap(result);
+
+        return result;
+    }
+
+    @XmlElementWrapper(name = "dynGroups")
+    @XmlElement(name = "role")
+    @JsonProperty("dynGroups")
+    public List<Long> getDynGroups() {
+        return dynGroups;
+    }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/common/lib/src/main/java/org/apache/syncope/common/lib/to/AnyTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/AnyTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/AnyTO.java
index bac9947..56b1c44 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/AnyTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/AnyTO.java
@@ -20,6 +20,7 @@ package org.apache.syncope.common.lib.to;
 
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -30,9 +31,14 @@ import java.util.Map;
 import java.util.Set;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlSeeAlso;
 import javax.xml.bind.annotation.XmlType;
 
+@XmlRootElement(name = "any")
 @XmlType
+@XmlSeeAlso({ UserTO.class, GroupTO.class, AnyObjectTO.class })
+@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class")
 public abstract class AnyTO extends ConnObjectTO {
 
     private static final long serialVersionUID = -754311920679872084L;
@@ -45,6 +51,8 @@ public abstract class AnyTO extends ConnObjectTO {
 
     private String status;
 
+    private final List<String> auxClasses = new ArrayList<>();
+
     private final Set<AttrTO> derAttrs = new LinkedHashSet<>();
 
     private final Set<AttrTO> virAttrs = new LinkedHashSet<>();
@@ -53,12 +61,6 @@ public abstract class AnyTO extends ConnObjectTO {
 
     private final List<PropagationStatus> propagationStatusTOs = new ArrayList<>();
 
-    private final List<RelationshipTO> relationships = new ArrayList<>();
-
-    private final List<MembershipTO> memberships = new ArrayList<>();
-
-    private final List<Long> dynGroups = new ArrayList<>();
-
     public long getKey() {
         return key;
     }
@@ -91,6 +93,13 @@ public abstract class AnyTO extends ConnObjectTO {
         this.status = status;
     }
 
+    @XmlElementWrapper(name = "auxClasses")
+    @XmlElement(name = "class")
+    @JsonProperty("auxClasses")
+    public List<String> getAuxClasses() {
+        return auxClasses;
+    }
+
     @XmlElementWrapper(name = "derAttrs")
     @XmlElement(name = "attribute")
     @JsonProperty("derAttrs")
@@ -139,42 +148,4 @@ public abstract class AnyTO extends ConnObjectTO {
         return propagationStatusTOs;
     }
 
-    @XmlElementWrapper(name = "relationships")
-    @XmlElement(name = "relationship")
-    @JsonProperty("relationships")
-    public List<RelationshipTO> getRelationships() {
-        return relationships;
-    }
-
-    @XmlElementWrapper(name = "memberships")
-    @XmlElement(name = "membership")
-    @JsonProperty("memberships")
-    public List<MembershipTO> getMemberships() {
-        return memberships;
-    }
-
-    @JsonIgnore
-    public Map<Long, MembershipTO> getMembershipMap() {
-        Map<Long, MembershipTO> result;
-
-        if (getMemberships() == null) {
-            result = Collections.emptyMap();
-        } else {
-            result = new HashMap<>(getMemberships().size());
-            for (MembershipTO membership : getMemberships()) {
-                result.put(membership.getRightKey(), membership);
-            }
-            result = Collections.unmodifiableMap(result);
-        }
-
-        return result;
-    }
-
-    @XmlElementWrapper(name = "dynGroups")
-    @XmlElement(name = "role")
-    @JsonProperty("dynGroups")
-    public List<Long> getDynGroups() {
-        return dynGroups;
-    }
-
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/common/lib/src/main/java/org/apache/syncope/common/lib/to/AnyTypeClassTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/AnyTypeClassTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/AnyTypeClassTO.java
new file mode 100644
index 0000000..1afbe4d
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/AnyTypeClassTO.java
@@ -0,0 +1,73 @@
+/*
+ * 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.to;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.ArrayList;
+import java.util.List;
+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.AbstractBaseBean;
+
+@XmlRootElement(name = "anyTypeClass")
+@XmlType
+public class AnyTypeClassTO extends AbstractBaseBean {
+
+    private static final long serialVersionUID = -591757688607551266L;
+
+    private String name;
+
+    private final List<String> plainSchemas = new ArrayList<>();
+
+    private final List<String> derSchemas = new ArrayList<>();
+
+    private final List<String> virSchemas = new ArrayList<>();
+
+    public String getKey() {
+        return name;
+    }
+
+    public void setKey(final String key) {
+        this.name = key;
+    }
+
+    @XmlElementWrapper(name = "plainSchemas")
+    @XmlElement(name = "schema")
+    @JsonProperty("plainSchemas")
+    public List<String> getPlainSchemas() {
+        return plainSchemas;
+    }
+
+    @XmlElementWrapper(name = "derSchemas")
+    @XmlElement(name = "schema")
+    @JsonProperty("derSchemas")
+    public List<String> getDerSchemas() {
+        return derSchemas;
+    }
+
+    @XmlElementWrapper(name = "virSchemas")
+    @XmlElement(name = "schema")
+    @JsonProperty("virSchemas")
+    public List<String> getVirSchemas() {
+        return virSchemas;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/common/lib/src/main/java/org/apache/syncope/common/lib/to/AnyTypeTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/AnyTypeTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/AnyTypeTO.java
new file mode 100644
index 0000000..9618bf5
--- /dev/null
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/AnyTypeTO.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.to;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.ArrayList;
+import java.util.List;
+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.AbstractBaseBean;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+
+@XmlRootElement(name = "anyType")
+@XmlType
+public class AnyTypeTO extends AbstractBaseBean {
+
+    private static final long serialVersionUID = 6771657557616874373L;
+
+    private String name;
+
+    private AnyTypeKind kind;
+
+    private final List<String> classes = new ArrayList<>();
+
+    public String getKey() {
+        return name;
+    }
+
+    public void setKey(final String key) {
+        this.name = key;
+    }
+
+    public AnyTypeKind getKind() {
+        return kind;
+    }
+
+    public void setKind(final AnyTypeKind kind) {
+        this.kind = kind;
+    }
+
+    @XmlElementWrapper(name = "classes")
+    @XmlElement(name = "class")
+    @JsonProperty("classes")
+    public List<String> getClasses() {
+        return classes;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/common/lib/src/main/java/org/apache/syncope/common/lib/to/AttrTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/AttrTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/AttrTO.java
index 829f309..cf385b4 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/AttrTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/AttrTO.java
@@ -41,21 +41,12 @@ public class AttrTO extends AbstractBaseBean {
     /**
      * Set of (string) values of this attribute.
      */
-    private final List<String> values;
+    private final List<String> values = new ArrayList<>();
 
     /**
      * Whether this attribute is read-only or not.
      */
-    private boolean readonly;
-
-    /**
-     * Default constructor.
-     */
-    public AttrTO() {
-        super();
-        values = new ArrayList<String>();
-        readonly = false;
-    }
+    private boolean readonly = false;
 
     /**
      * @return the name of the schema that this attribute is referring to

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/common/lib/src/main/java/org/apache/syncope/common/lib/to/BulkActionResult.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/BulkActionResult.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/BulkActionResult.java
index 9726a25..9b44b3f 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/BulkActionResult.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/BulkActionResult.java
@@ -25,15 +25,18 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlEnum;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
 import org.apache.syncope.common.lib.AbstractBaseBean;
+import org.apache.syncope.common.lib.jaxb.XmlGenericMapAdapter;
 
 @XmlRootElement(name = "bulkActionResult")
 @XmlType
+@XmlAccessorType(XmlAccessType.FIELD)
 public class BulkActionResult extends AbstractBaseBean {
 
     private static final long serialVersionUID = 2868894178821778133L;
@@ -52,86 +55,25 @@ public class BulkActionResult extends AbstractBaseBean {
 
     }
 
-    private final List<Result> results = new ArrayList<>();
-
-    @XmlElementWrapper(name = "result")
-    @XmlElement(name = "item")
-    @JsonProperty("result")
-    public List<Result> getResult() {
-        return results;
-    }
-
+    @XmlJavaTypeAdapter(XmlGenericMapAdapter.class)
     @JsonIgnore
-    public void add(final Object id, final Status status) {
-        if (id != null) {
-            results.add(new Result(id.toString(), status));
-        }
-    }
+    private final Map<String, Status> results = new HashMap<>();
 
-    @JsonIgnore
-    public void add(final Object id, final String status) {
-        if (id != null) {
-            results.add(new Result(id.toString(), Status.valueOf(status.toUpperCase())));
-        }
-    }
-
-    @JsonIgnore
-    public Map<String, Status> getResultMap() {
-        final Map<String, Status> res = new HashMap<>();
-
-        for (Result result : results) {
-            res.put(result.getKey(), result.getValue());
-        }
-
-        return Collections.unmodifiableMap(res);
+    @JsonProperty
+    public Map<String, Status> getResults() {
+        return results;
     }
 
     @JsonIgnore
     public List<String> getResultByStatus(final Status status) {
-        final List<String> res = new ArrayList<>();
+        final List<String> result = new ArrayList<>();
 
-        for (Result result : results) {
-            if (result.getValue() == status) {
-                res.add(result.getKey());
+        for (Map.Entry<String, Status> entry : results.entrySet()) {
+            if (entry.getValue() == status) {
+                result.add(entry.getKey());
             }
         }
 
-        return Collections.unmodifiableList(res);
-    }
-
-    public static class Result extends AbstractBaseBean {
-
-        private static final long serialVersionUID = -1149681964161193232L;
-
-        private String key;
-
-        private Status value;
-
-        public Result() {
-            super();
-        }
-
-        public Result(final String key, final Status value) {
-            super();
-
-            this.key = key;
-            this.value = value;
-        }
-
-        public String getKey() {
-            return key;
-        }
-
-        public Status getValue() {
-            return value;
-        }
-
-        public void setKey(final String key) {
-            this.key = key;
-        }
-
-        public void setValue(final Status value) {
-            this.value = value;
-        }
+        return Collections.unmodifiableList(result);
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/common/lib/src/main/java/org/apache/syncope/common/lib/to/GroupTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/GroupTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/GroupTO.java
index 873b15d..a5a33ca 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/GroupTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/GroupTO.java
@@ -18,13 +18,13 @@
  */
 package org.apache.syncope.common.lib.to;
 
-import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
+import com.fasterxml.jackson.annotation.JsonIgnore;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlType;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
 
 @XmlRootElement(name = "group")
 @XmlType
-@JsonIgnoreProperties({ "displayName" })
 public class GroupTO extends AnyTO {
 
     private static final long serialVersionUID = -7785920258290147542L;
@@ -35,9 +35,19 @@ public class GroupTO extends AnyTO {
 
     private Long groupOwner;
 
-    private String aDynMembershipCond;
+    private String adynMembershipCond;
 
-    private String uDynMembershipCond;
+    private String udynMembershipCond;
+
+    @Override
+    public String getType() {
+        return AnyTypeKind.GROUP.name();
+    }
+
+    @Override
+    public void setType(final String type) {
+        // fixed
+    }
 
     public String getName() {
         return name;
@@ -64,19 +74,36 @@ public class GroupTO extends AnyTO {
     }
 
     public String getADynMembershipCond() {
-        return aDynMembershipCond;
+        return adynMembershipCond;
     }
 
     public void setADynMembershipCond(final String aDynMembershipCond) {
-        this.aDynMembershipCond = aDynMembershipCond;
+        this.adynMembershipCond = aDynMembershipCond;
     }
 
     public String getUDynMembershipCond() {
-        return uDynMembershipCond;
+        return udynMembershipCond;
     }
 
     public void setUDynMembershipCond(final String uDynMembershipCond) {
-        this.uDynMembershipCond = uDynMembershipCond;
+        this.udynMembershipCond = uDynMembershipCond;
     }
 
+    @JsonIgnore
+    public String getDisplayName() {
+        return getKey() + " " + getName();
+    }
+
+    public static long fromDisplayName(final String displayName) {
+        long result = 0;
+        if (displayName != null && !displayName.isEmpty() && displayName.indexOf(' ') != -1) {
+            try {
+                result = Long.valueOf(displayName.split(" ")[0]);
+            } catch (NumberFormatException e) {
+                // ignore
+            }
+        }
+
+        return result;
+    }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/common/lib/src/main/java/org/apache/syncope/common/lib/to/MembershipTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/MembershipTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/MembershipTO.java
index 5c435e4..ef70589 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/MembershipTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/MembershipTO.java
@@ -20,6 +20,7 @@ package org.apache.syncope.common.lib.to;
 
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlType;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
 
 @XmlRootElement(name = "membership")
 @XmlType
@@ -29,9 +30,14 @@ public class MembershipTO extends RelationshipTO {
 
     private String groupName;
 
+    public MembershipTO() {
+        super();
+        super.setRightType(AnyTypeKind.GROUP.name());
+    }
+
     @Override
-    public String getRightType() {
-        return "group";
+    public void setRightType(final String rightType) {
+        // ignore
     }
 
     public String getGroupName() {

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/common/lib/src/main/java/org/apache/syncope/common/lib/to/NotificationTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/NotificationTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/NotificationTO.java
index 662a465..7cb6556 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/NotificationTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/NotificationTO.java
@@ -18,21 +18,27 @@
  */
 package org.apache.syncope.common.lib.to;
 
+import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
 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 javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
 import org.apache.syncope.common.lib.AbstractBaseBean;
+import org.apache.syncope.common.lib.jaxb.XmlGenericMapAdapter;
 import org.apache.syncope.common.lib.types.IntMappingType;
 import org.apache.syncope.common.lib.types.TraceLevel;
 
 @XmlRootElement(name = "notification")
 @XmlType
+@XmlAccessorType(XmlAccessType.FIELD)
 public class NotificationTO extends AbstractBaseBean {
 
     private static final long serialVersionUID = -6145117115632592612L;
@@ -41,6 +47,8 @@ public class NotificationTO extends AbstractBaseBean {
 
     private final List<String> events = new ArrayList<>();
 
+    @XmlJavaTypeAdapter(XmlGenericMapAdapter.class)
+    @JsonIgnore
     private final Map<String, String> abouts = new HashMap<>();
 
     private String recipients;
@@ -63,6 +71,7 @@ public class NotificationTO extends AbstractBaseBean {
 
     private boolean active;
 
+    @JsonProperty
     public Map<String, String> getAbouts() {
         return abouts;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/common/lib/src/main/java/org/apache/syncope/common/lib/to/PushTaskTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/PushTaskTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/PushTaskTO.java
index e1839af..dd3347a 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/PushTaskTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/PushTaskTO.java
@@ -18,21 +18,30 @@
  */
 package org.apache.syncope.common.lib.to;
 
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
 import java.util.HashMap;
 import java.util.Map;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+import org.apache.syncope.common.lib.jaxb.XmlGenericMapAdapter;
 
 @XmlRootElement(name = "pushTask")
 @XmlType
+@XmlAccessorType(XmlAccessType.FIELD)
 public class PushTaskTO extends AbstractProvisioningTaskTO {
 
     private static final long serialVersionUID = -2143537546915809018L;
 
+    @XmlJavaTypeAdapter(XmlGenericMapAdapter.class)
+    @JsonIgnore
     private final Map<String, String> filters = new HashMap<>();
 
+    @JsonProperty
     public Map<String, String> getFilters() {
         return filters;
     }
-
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/common/lib/src/main/java/org/apache/syncope/common/lib/to/RelationshipTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/RelationshipTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/RelationshipTO.java
index 2585b2b..d769719 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/RelationshipTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/RelationshipTO.java
@@ -28,8 +28,6 @@ public class RelationshipTO extends AbstractBaseBean {
 
     private static final long serialVersionUID = 360672942026613929L;
 
-    private long key;
-
     private String leftType;
 
     private long leftKey;
@@ -38,14 +36,6 @@ public class RelationshipTO extends AbstractBaseBean {
 
     private long rightKey;
 
-    public long getKey() {
-        return key;
-    }
-
-    public void setKey(final long key) {
-        this.key = key;
-    }
-
     public String getLeftType() {
         return leftType;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/common/lib/src/main/java/org/apache/syncope/common/lib/to/ResourceTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/ResourceTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/ResourceTO.java
index fb97113..dcec457 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/ResourceTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/ResourceTO.java
@@ -48,7 +48,7 @@ public class ResourceTO extends AbstractAnnotatedBean {
     /**
      * The resource type is identified by the associated connector.
      */
-    private Long connectorId;
+    private Long connector;
 
     /**
      * Convenience information: display name for the connector id.
@@ -83,10 +83,6 @@ public class ResourceTO extends AbstractAnnotatedBean {
 
     private final Set<ConnConfProperty> connConfProperties = new HashSet<>();
 
-    private String usyncToken;
-
-    private String rsyncToken;
-
     private final List<String> propagationActionsClassNames = new ArrayList<>();
 
     public ResourceTO() {
@@ -117,12 +113,12 @@ public class ResourceTO extends AbstractAnnotatedBean {
         this.enforceMandatoryCondition = enforceMandatoryCondition;
     }
 
-    public Long getConnectorId() {
-        return connectorId;
+    public Long getConnector() {
+        return connector;
     }
 
-    public void setConnectorId(final Long connectorId) {
-        this.connectorId = connectorId;
+    public void setConnector(final Long connector) {
+        this.connector = connector;
     }
 
     public String getConnectorDisplayName() {

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/common/lib/src/main/java/org/apache/syncope/common/lib/to/SyncTaskTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/SyncTaskTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/SyncTaskTO.java
index 4974505..a6a7a8a 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/SyncTaskTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/SyncTaskTO.java
@@ -18,19 +18,28 @@
  */
 package org.apache.syncope.common.lib.to;
 
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
 import java.util.HashMap;
 import java.util.Map;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+import org.apache.syncope.common.lib.jaxb.XmlGenericMapAdapter;
 
 @XmlRootElement(name = "syncTask")
 @XmlType
+@XmlAccessorType(XmlAccessType.FIELD)
 public class SyncTaskTO extends AbstractProvisioningTaskTO {
 
     private static final long serialVersionUID = -2143537546915809017L;
 
     private String destinationRealm;
 
+    @XmlJavaTypeAdapter(XmlGenericMapAdapter.class)
+    @JsonIgnore
     private final Map<String, AnyTO> templates = new HashMap<>();
 
     private boolean fullReconciliation;
@@ -43,6 +52,7 @@ public class SyncTaskTO extends AbstractProvisioningTaskTO {
         this.destinationRealm = destinationRealm;
     }
 
+    @JsonProperty
     public Map<String, AnyTO> getTemplates() {
         return templates;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/common/lib/src/main/java/org/apache/syncope/common/lib/to/UserTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/UserTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/UserTO.java
index 5de7b01..dd5ebee 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/UserTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/UserTO.java
@@ -18,17 +18,22 @@
  */
 package org.apache.syncope.common.lib.to;
 
+import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import java.lang.reflect.Field;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Date;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 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.commons.lang3.builder.ReflectionToStringBuilder;
 import org.apache.commons.lang3.builder.ToStringStyle;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
 
 @XmlRootElement(name = "user")
 @XmlType
@@ -58,6 +63,22 @@ public class UserTO extends AnyTO {
 
     private String securityAnswer;
 
+    private final List<RelationshipTO> relationships = new ArrayList<>();
+
+    private final List<MembershipTO> memberships = new ArrayList<>();
+
+    private final List<Long> dynGroups = new ArrayList<>();
+
+    @Override
+    public String getType() {
+        return AnyTypeKind.USER.name();
+    }
+
+    @Override
+    public void setType(final String type) {
+        // fixed
+    }
+
     public String getPassword() {
         return password;
     }
@@ -148,6 +169,49 @@ public class UserTO extends AnyTO {
         this.securityAnswer = securityAnswer;
     }
 
+    @XmlElementWrapper(name = "relationships")
+    @XmlElement(name = "relationship")
+    @JsonProperty("relationships")
+    public List<RelationshipTO> getRelationships() {
+        return relationships;
+    }
+
+    @JsonIgnore
+    public Map<Long, RelationshipTO> getRelationshipMap() {
+        Map<Long, RelationshipTO> result = new HashMap<>(getRelationships().size());
+        for (RelationshipTO membership : getRelationships()) {
+            result.put(membership.getRightKey(), membership);
+        }
+        result = Collections.unmodifiableMap(result);
+
+        return result;
+    }
+
+    @XmlElementWrapper(name = "memberships")
+    @XmlElement(name = "membership")
+    @JsonProperty("memberships")
+    public List<MembershipTO> getMemberships() {
+        return memberships;
+    }
+
+    @JsonIgnore
+    public Map<Long, MembershipTO> getMembershipMap() {
+        Map<Long, MembershipTO> result = new HashMap<>(getMemberships().size());
+        for (MembershipTO membership : getMemberships()) {
+            result.put(membership.getRightKey(), membership);
+        }
+        result = Collections.unmodifiableMap(result);
+
+        return result;
+    }
+
+    @XmlElementWrapper(name = "dynGroups")
+    @XmlElement(name = "role")
+    @JsonProperty("dynGroups")
+    public List<Long> getDynGroups() {
+        return dynGroups;
+    }
+
     @Override
     public String toString() {
         return new ReflectionToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/common/lib/src/main/java/org/apache/syncope/common/lib/to/WorkflowFormPropertyTO.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/to/WorkflowFormPropertyTO.java b/common/lib/src/main/java/org/apache/syncope/common/lib/to/WorkflowFormPropertyTO.java
index 5b67c92..9fa5928 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/to/WorkflowFormPropertyTO.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/to/WorkflowFormPropertyTO.java
@@ -18,11 +18,15 @@
  */
 package org.apache.syncope.common.lib.to;
 
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
 import java.util.HashMap;
 import java.util.Map;
 import javax.xml.bind.annotation.XmlRootElement;
 import javax.xml.bind.annotation.XmlType;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
 import org.apache.syncope.common.lib.AbstractBaseBean;
+import org.apache.syncope.common.lib.jaxb.XmlGenericMapAdapter;
 import org.apache.syncope.common.lib.types.WorkflowFormPropertyType;
 
 @XmlRootElement(name = "workflowFormProperty")
@@ -47,6 +51,8 @@ public class WorkflowFormPropertyTO extends AbstractBaseBean {
 
     private String datePattern;
 
+    @XmlJavaTypeAdapter(XmlGenericMapAdapter.class)
+    @JsonIgnore
     private final Map<String, String> enumValues = new HashMap<>();
 
     public String getId() {
@@ -113,6 +119,7 @@ public class WorkflowFormPropertyTO extends AbstractBaseBean {
         this.datePattern = datePattern;
     }
 
+    @JsonProperty
     public Map<String, String> getEnumValues() {
         return enumValues;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/common/lib/src/main/java/org/apache/syncope/common/lib/types/AnyTypeKind.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/types/AnyTypeKind.java b/common/lib/src/main/java/org/apache/syncope/common/lib/types/AnyTypeKind.java
index c7b4e47..ee35e28 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/types/AnyTypeKind.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/types/AnyTypeKind.java
@@ -19,12 +19,26 @@
 package org.apache.syncope.common.lib.types;
 
 import javax.xml.bind.annotation.XmlEnum;
+import org.apache.syncope.common.lib.to.AnyObjectTO;
+import org.apache.syncope.common.lib.to.AnyTO;
+import org.apache.syncope.common.lib.to.GroupTO;
+import org.apache.syncope.common.lib.to.UserTO;
 
 @XmlEnum
 public enum AnyTypeKind {
 
-    USER,
-    GROUP,
-    ANY_OBJECT;
+    USER(UserTO.class),
+    GROUP(GroupTO.class),
+    ANY_OBJECT(AnyObjectTO.class);
+
+    private final Class<? extends AnyTO> toClass;
+
+    private AnyTypeKind(final Class<? extends AnyTO> toClass) {
+        this.toClass = toClass;
+    }
+
+    public Class<? extends AnyTO> getToClass() {
+        return toClass;
+    }
 
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/common/lib/src/main/java/org/apache/syncope/common/lib/types/ClientExceptionType.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/types/ClientExceptionType.java b/common/lib/src/main/java/org/apache/syncope/common/lib/types/ClientExceptionType.java
index 498f603..8e96942 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/types/ClientExceptionType.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/types/ClientExceptionType.java
@@ -40,6 +40,7 @@ public enum ClientExceptionType {
     InvalidProvision(Response.Status.BAD_REQUEST),
     InvalidReport(Response.Status.BAD_REQUEST),
     InvalidReportExec(Response.Status.BAD_REQUEST),
+    InvalidAnyType(Response.Status.BAD_REQUEST),
     InvalidAnyObject(Response.Status.BAD_REQUEST),
     InvalidGroup(Response.Status.BAD_REQUEST),
     InvalidSchemaDefinition(Response.Status.BAD_REQUEST),
@@ -49,7 +50,7 @@ public enum ClientExceptionType {
     InvalidPlainSchema(Response.Status.BAD_REQUEST),
     InvalidDerSchema(Response.Status.BAD_REQUEST),
     InvalidVirSchema(Response.Status.BAD_REQUEST),
-    InvalidSchemaMapping(Response.Status.BAD_REQUEST),
+    InvalidMapping(Response.Status.BAD_REQUEST),
     InvalidRealm(Response.Status.BAD_REQUEST),
     InvalidUser(Response.Status.BAD_REQUEST),
     InvalidExternalResource(Response.Status.BAD_REQUEST),
@@ -65,6 +66,7 @@ public enum ClientExceptionType {
     GroupOwnership(Response.Status.BAD_REQUEST),
     Scheduling(Response.Status.BAD_REQUEST),
     Unauthorized(Response.Status.UNAUTHORIZED),
+    UnallowedSchemas(Response.Status.BAD_REQUEST),
     Unknown(Response.Status.BAD_REQUEST),
     Workflow(Response.Status.BAD_REQUEST);
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/common/lib/src/main/java/org/apache/syncope/common/lib/types/Entitlement.java
----------------------------------------------------------------------
diff --git a/common/lib/src/main/java/org/apache/syncope/common/lib/types/Entitlement.java b/common/lib/src/main/java/org/apache/syncope/common/lib/types/Entitlement.java
index 81caa77..6ffe318 100644
--- a/common/lib/src/main/java/org/apache/syncope/common/lib/types/Entitlement.java
+++ b/common/lib/src/main/java/org/apache/syncope/common/lib/types/Entitlement.java
@@ -36,6 +36,26 @@ public final class Entitlement {
 
     public static final String REALM_DELETE = "REALM_DELETE";
 
+    public static final String ANYTYPECLASS_LIST = "ANYTYPECLASS_LIST";
+
+    public static final String ANYTYPECLASS_CREATE = "ANYTYPECLASS_CREATE";
+
+    public static final String ANYTYPECLASS_READ = "ANYTYPECLASS_READ";
+
+    public static final String ANYTYPECLASS_UPDATE = "ANYTYPECLASS_UPDATE";
+
+    public static final String ANYTYPECLASS_DELETE = "ANYTYPECLASS_DELETE";
+
+    public static final String ANYTYPE_LIST = "ANYTYPE_LIST";
+
+    public static final String ANYTYPE_CREATE = "ANYTYPE_CREATE";
+
+    public static final String ANYTYPE_READ = "ANYTYPE_READ";
+
+    public static final String ANYTYPE_UPDATE = "ANYTYPE_UPDATE";
+
+    public static final String ANYTYPE_DELETE = "ANYTYPE_DELETE";
+
     public static final String ROLE_LIST = "ROLE_LIST";
 
     public static final String ROLE_CREATE = "ROLE_CREATE";

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/AnyTypeClassService.java
----------------------------------------------------------------------
diff --git a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/AnyTypeClassService.java b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/AnyTypeClassService.java
new file mode 100644
index 0000000..21831cf
--- /dev/null
+++ b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/AnyTypeClassService.java
@@ -0,0 +1,97 @@
+/*
+ * 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.rest.api.service;
+
+import java.util.List;
+import javax.validation.constraints.NotNull;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import org.apache.cxf.jaxrs.model.wadl.Description;
+import org.apache.cxf.jaxrs.model.wadl.Descriptions;
+import org.apache.cxf.jaxrs.model.wadl.DocTarget;
+import org.apache.syncope.common.lib.to.AnyTypeClassTO;
+
+/**
+ * REST operations for any type classes.
+ */
+@Path("anyTypeClassClasses")
+public interface AnyTypeClassService extends JAXRSService {
+
+    /**
+     * Returns a list of all anyTypeClasss.
+     *
+     * @return list of all anyTypeClasss.
+     */
+    @GET
+    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+    List<AnyTypeClassTO> list();
+
+    /**
+     * Returns anyTypeClass with matching key.
+     *
+     * @param key anyTypeClass key to be read
+     * @return anyTypeClass with matching key
+     */
+    @GET
+    @Path("{key}")
+    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+    AnyTypeClassTO read(@NotNull @PathParam("key") String key);
+
+    /**
+     * Creates a new anyTypeClass.
+     *
+     * @param anyTypeClassTO anyTypeClass to be created
+     * @return <tt>Response</tt> object featuring <tt>Location</tt> header of created anyTypeClass
+     */
+    @Descriptions({
+        @Description(target = DocTarget.RESPONSE,
+                value = "Featuring <tt>Location</tt> header of created anyTypeClass")
+    })
+    @POST
+    @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+    Response create(@NotNull AnyTypeClassTO anyTypeClassTO);
+
+    /**
+     * Updates the anyTypeClass matching the provided key.
+     *
+     * @param key anyTypeClass key to be updated
+     * @param anyTypeClassTO anyTypeClass to be stored
+     */
+    @PUT
+    @Path("{key}")
+    @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+    void update(@NotNull @PathParam("key") String key, @NotNull AnyTypeClassTO anyTypeClassTO);
+
+    /**
+     * Deletes the anyTypeClass matching the provided key.
+     *
+     * @param key anyTypeClass key to be deleted
+     */
+    @DELETE
+    @Path("{key}")
+    void delete(@NotNull @PathParam("key") String key);
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/AnyTypeService.java
----------------------------------------------------------------------
diff --git a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/AnyTypeService.java b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/AnyTypeService.java
new file mode 100644
index 0000000..ddedd25
--- /dev/null
+++ b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/AnyTypeService.java
@@ -0,0 +1,97 @@
+/*
+ * 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.rest.api.service;
+
+import java.util.List;
+import javax.validation.constraints.NotNull;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import org.apache.cxf.jaxrs.model.wadl.Description;
+import org.apache.cxf.jaxrs.model.wadl.Descriptions;
+import org.apache.cxf.jaxrs.model.wadl.DocTarget;
+import org.apache.syncope.common.lib.to.AnyTypeTO;
+
+/**
+ * REST operations for any types.
+ */
+@Path("anyTypes")
+public interface AnyTypeService extends JAXRSService {
+
+    /**
+     * Returns a list of all anyTypes.
+     *
+     * @return list of all anyTypes.
+     */
+    @GET
+    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+    List<AnyTypeTO> list();
+
+    /**
+     * Returns anyType with matching key.
+     *
+     * @param key anyType key to be read
+     * @return anyType with matching key
+     */
+    @GET
+    @Path("{key}")
+    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+    AnyTypeTO read(@NotNull @PathParam("key") String key);
+
+    /**
+     * Creates a new anyType.
+     *
+     * @param anyTypeTO anyType to be created
+     * @return <tt>Response</tt> object featuring <tt>Location</tt> header of created anyType
+     */
+    @Descriptions({
+        @Description(target = DocTarget.RESPONSE,
+                value = "Featuring <tt>Location</tt> header of created anyType")
+    })
+    @POST
+    @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+    Response create(@NotNull AnyTypeTO anyTypeTO);
+
+    /**
+     * Updates the anyType matching the provided key.
+     *
+     * @param key anyType key to be updated
+     * @param anyTypeTO anyType to be stored
+     */
+    @PUT
+    @Path("{key}")
+    @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+    void update(@NotNull @PathParam("key") String key, @NotNull AnyTypeTO anyTypeTO);
+
+    /**
+     * Deletes the anyType matching the provided key.
+     *
+     * @param key anyType key to be deleted
+     */
+    @DELETE
+    @Path("{key}")
+    void delete(@NotNull @PathParam("key") String key);
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/RoleService.java
----------------------------------------------------------------------
diff --git a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/RoleService.java b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/RoleService.java
index 172af5f..881e1bc 100644
--- a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/RoleService.java
+++ b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/RoleService.java
@@ -51,15 +51,15 @@ public interface RoleService extends JAXRSService {
     List<RoleTO> list();
 
     /**
-     * Returns role with matching id.
+     * Returns role with matching key.
      *
-     * @param roleKey role id to be read
-     * @return role with matching id
+     * @param key role key to be read
+     * @return role with matching key
      */
     @GET
-    @Path("{roleKey}")
+    @Path("{key}")
     @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    RoleTO read(@NotNull @PathParam("roleKey") Long roleKey);
+    RoleTO read(@NotNull @PathParam("key") Long key);
 
     /**
      * Creates a new role.
@@ -76,22 +76,22 @@ public interface RoleService extends JAXRSService {
     Response create(@NotNull RoleTO roleTO);
 
     /**
-     * Updates the role matching the provided id.
+     * Updates the role matching the provided key.
      *
-     * @param roleKey role id to be updated
+     * @param key role key to be updated
      * @param roleTO role to be stored
      */
     @PUT
-    @Path("{roleKey}")
+    @Path("{key}")
     @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    void update(@NotNull @PathParam("roleKey") Long roleKey, @NotNull RoleTO roleTO);
+    void update(@NotNull @PathParam("key") Long key, @NotNull RoleTO roleTO);
 
     /**
-     * Deletes the role matching the provided id.
+     * Deletes the role matching the provided key.
      *
-     * @param roleKey role id to be deleted
+     * @param key role key to be deleted
      */
     @DELETE
-    @Path("{roleKey}")
-    void delete(@NotNull @PathParam("roleKey") Long roleKey);
+    @Path("{key}")
+    void delete(@NotNull @PathParam("key") Long key);
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/SchemaService.java
----------------------------------------------------------------------
diff --git a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/SchemaService.java b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/SchemaService.java
index 4ffb3f6..352e310 100644
--- a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/SchemaService.java
+++ b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/SchemaService.java
@@ -39,7 +39,7 @@ import org.apache.syncope.common.lib.types.SchemaType;
 /**
  * REST operations for attribute schemas.
  */
-@Path("schemas/{kind}/{type}")
+@Path("schemas/{type}")
 public interface SchemaService extends JAXRSService {
 
     /**

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserService.java
----------------------------------------------------------------------
diff --git a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserService.java b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserService.java
index 9e280a5..8f9363cb 100644
--- a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserService.java
+++ b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/UserService.java
@@ -81,7 +81,7 @@ public interface UserService extends JAXRSService {
     })
     @OPTIONS
     @Path("{username}/userKey")
-    Response getUserId(@NotNull @PathParam("username") String username);
+    Response getUserKey(@NotNull @PathParam("username") String username);
 
     /**
      * Reads the user matching the provided userKey.

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/WorkflowService.java
----------------------------------------------------------------------
diff --git a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/WorkflowService.java b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/WorkflowService.java
index fc48429..68858c7 100644
--- a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/WorkflowService.java
+++ b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/WorkflowService.java
@@ -33,7 +33,7 @@ import org.apache.syncope.common.rest.api.RESTHeaders;
 /**
  * REST operations for workflow definition management.
  */
-@Path("workflows/{kind}")
+@Path("workflows/{anyTypeKind}")
 public interface WorkflowService extends JAXRSService {
 
     /**


[14/21] syncope git commit: Merge from 1_2_X

Posted by il...@apache.org.
Merge from 1_2_X


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

Branch: refs/heads/SYNCOPE-666
Commit: 6d120f753360546ada38d6e4efff507840c45403
Parents: 2f02892 632acda
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Fri Jun 5 14:51:29 2015 +0200
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Fri Jun 5 14:51:29 2015 +0200

----------------------------------------------------------------------
 pom.xml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/6d120f75/pom.xml
----------------------------------------------------------------------
diff --cc pom.xml
index c32fbb8,441f906..c097c4b
--- a/pom.xml
+++ b/pom.xml
@@@ -326,45 -335,60 +326,45 @@@ under the License
      <connid.ldap.version>1.4.0</connid.ldap.version>
      <connid.ad.version>1.2.3</connid.ad.version>
  
 -    <commons-jexl.version>2.1.1</commons-jexl.version>
 -    <commons-lang.version>3.3.2</commons-lang.version>
 -    <commons-codec.version>1.10</commons-codec.version>
 +    <cxf.version>3.1.0</cxf.version>
  
 -    <activiti.version>5.16.4</activiti.version>
 +    <camel.version>2.15.2</camel.version>	
  
 -    <aspectj.version>1.8.5</aspectj.version>
 +    <jackson.version>2.5.3</jackson.version>
  
 -    <cxf.version>3.0.5</cxf.version>	
 -    <spring.version>4.0.9.RELEASE</spring.version>
 -    <spring-security.version>3.2.7.RELEASE</spring-security.version>
 -    <jackson.version>2.4.6</jackson.version>
 -    <velocity.version>1.7</velocity.version>
 -    <velocitytools.version>2.0</velocitytools.version>
 -    <quartz.version>2.2.1</quartz.version>
 +    <spring.version>4.1.6.RELEASE</spring.version>
 +    <spring-security.version>4.0.1.RELEASE</spring-security.version>
  
 -    <openjpa.version>2.3.0</openjpa.version>
 +    <openjpa.version>2.4.0</openjpa.version>
 +    <commons-dbcp.version>2.1</commons-dbcp.version>
      <hibernate-validator.version>5.1.3.Final</hibernate-validator.version>
 -    <commons-dbcp.version>1.4</commons-dbcp.version>
 -    <commons.logging.version>1.1.3</commons.logging.version>
  
 -    <cocoon.version>3.0.0-alpha-3</cocoon.version>
 +    <jasypt.version>1.9.2</jasypt.version>
 +
 +    <quartz.version>2.2.1</quartz.version>
  
 -    <wicket.version>6.19.0</wicket.version>
 +    <cocoon.version>3.0.0-alpha-3</cocoon.version>
  
 -    <groovy.version>2.3.10</groovy.version>
 +    <groovy.version>2.4.3</groovy.version>
  
 -    <h2.version>1.4.187</h2.version>
 +    <activiti.version>5.17.0</activiti.version>
  
 -    <log4j.version>2.3</log4j.version>
      <slf4j.version>1.7.12</slf4j.version>
 +    <log4j.version>2.3</log4j.version>
      <disruptor.version>3.3.2</disruptor.version>
  
 -    <junit.version>4.11</junit.version>
 -    <selenium.version>2.46.0</selenium.version>
 -
 -    <apacheds.version>1.5.7</apacheds.version>
 -    
 -    <httpclient.version>4.3.6</httpclient.version>
 +    <commons-io.version>2.4</commons-io.version>
 +    <commons-codec.version>1.10</commons-codec.version>
 +    <commons-jexl.version>2.1.1</commons-jexl.version>
 +    <commons-lang.version>3.4</commons-lang.version>
 +    <commons-collection.version>4.0</commons-collection.version>
 +    <commons-logging.version>1.1.3</commons-logging.version>
  
 -    <tomcat.version>7.0.62</tomcat.version>
 +    <h2.version>1.4.187</h2.version>
  
 -    <jasypt.version>1.9.2</jasypt.version>
 - 
 -    <jquery.version>1.11.1</jquery.version>
 -    <jquery-ui.version>1.10.4</jquery-ui.version>
 -    <highlightjs.version>8.0</highlightjs.version>
 -    <codemirror.version>3.23</codemirror.version>
 +    <junit.version>4.12</junit.version>
-     <selenium.version>2.45.0</selenium.version>
++    <selenium.version>2.46.0</selenium.version>
  
 -    <izpack.version>5.0.0-rc5</izpack.version>
 -    <maven-invoker.version>2.1.1</maven-invoker.version>
 -    
 -    <jdeb.version>1.4</jdeb.version>
 - 
      <conf.directory>${project.build.directory}/test-classes</conf.directory>
      <bundles.directory>${project.build.directory}/bundles</bundles.directory>
      <connid.location>file:${bundles.directory}/</connid.location>
@@@ -1229,9 -1245,94 +1229,9 @@@
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
-           <version>2.5.4</version>
+           <version>2.5.5</version>
          </plugin>
 -        <plugin>
 -          <groupId>org.eclipse.m2e</groupId>
 -          <artifactId>lifecycle-mapping</artifactId>
 -          <version>1.0.0</version>
 -          <configuration>
 -            <lifecycleMappingMetadata>
 -              <pluginExecutions>
 -                <pluginExecution>
 -                  <pluginExecutionFilter>
 -                    <groupId>org.apache.maven.plugins</groupId>
 -                    <artifactId>maven-antrun-plugin</artifactId>
 -                    <versionRange>[1.7.0,)</versionRange>
 -                    <goals>
 -                      <goal>run</goal>
 -                    </goals>
 -                  </pluginExecutionFilter>
 -                  <action>
 -                    <execute>
 -                      <runOnIncremental>false</runOnIncremental>
 -                    </execute>
 -                  </action>
 -                </pluginExecution>
 -                <pluginExecution>
 -                  <pluginExecutionFilter>
 -                    <groupId>org.apache.maven.plugins</groupId>
 -                    <artifactId>maven-dependency-plugin</artifactId>
 -                    <versionRange>[2.0.0,)</versionRange>
 -                    <goals>
 -                      <goal>copy</goal>
 -                    </goals>
 -                  </pluginExecutionFilter>
 -                  <action>
 -                    <execute>
 -                      <runOnIncremental>false</runOnIncremental>
 -                    </execute>
 -                  </action>
 -                </pluginExecution>
 -                <pluginExecution>
 -                  <pluginExecutionFilter>
 -                    <groupId>org.codehaus.gmaven</groupId>
 -                    <artifactId>gmaven-plugin</artifactId>
 -                    <versionRange>[1.5.0,)</versionRange>
 -                    <goals>
 -                      <goal>execute</goal>
 -                    </goals>
 -                  </pluginExecutionFilter>
 -                  <action>
 -                    <execute>
 -                      <runOnIncremental>false</runOnIncremental>
 -                    </execute>
 -                  </action>
 -                </pluginExecution>
 -                <pluginExecution>
 -                  <pluginExecutionFilter>
 -                    <groupId>org.apache.openjpa</groupId>
 -                    <artifactId>openjpa-maven-plugin</artifactId>
 -                    <versionRange>[2.0.0,)</versionRange>
 -                    <goals>
 -                      <goal>enhance</goal>
 -                    </goals>
 -                  </pluginExecutionFilter>
 -                  <action>
 -                    <execute>
 -                      <runOnIncremental>false</runOnIncremental>
 -                    </execute>
 -                  </action>
 -                </pluginExecution>
 -                <pluginExecution>
 -                  <pluginExecutionFilter>
 -                    <groupId>org.codehaus.mojo</groupId>
 -                    <artifactId>xml-maven-plugin</artifactId>
 -                    <versionRange>[1.0,)</versionRange>
 -                    <goals>
 -                      <goal>transform</goal>
 -                    </goals>
 -                  </pluginExecutionFilter>
 -                  <action>
 -                    <execute>
 -                      <runOnIncremental>false</runOnIncremental>
 -                    </execute>
 -                  </action>
 -                </pluginExecution>
 -              </pluginExecutions>
 -            </lifecycleMappingMetadata>
 -          </configuration>
 -        </plugin>
 +        
          <plugin>
            <groupId>org.codehaus.izpack</groupId>
            <artifactId>izpack-maven-plugin</artifactId>


[17/21] syncope git commit: [SYNCOPE-666] All tests are green, time to add more

Posted by il...@apache.org.
http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/AbstractPropagationTaskExecutor.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/AbstractPropagationTaskExecutor.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/AbstractPropagationTaskExecutor.java
index 73a7896..6a67ccf 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/AbstractPropagationTaskExecutor.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/AbstractPropagationTaskExecutor.java
@@ -51,6 +51,7 @@ import org.apache.syncope.core.misc.ExceptionUtils2;
 import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
 import org.apache.syncope.core.persistence.api.entity.Any;
 import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
+import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
 import org.apache.syncope.core.persistence.api.entity.group.Group;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 import org.apache.syncope.core.persistence.api.entity.resource.Provision;
@@ -72,9 +73,6 @@ import org.springframework.transaction.annotation.Transactional;
 @Transactional(rollbackFor = { Throwable.class })
 public abstract class AbstractPropagationTaskExecutor implements PropagationTaskExecutor {
 
-    /**
-     * Logger.
-     */
     protected static final Logger LOG = LoggerFactory.getLogger(PropagationTaskExecutor.class);
 
     /**
@@ -299,9 +297,11 @@ public abstract class AbstractPropagationTaskExecutor implements PropagationTask
             Any<?, ?, ?> any = getAny(task);
             Collection<String> resources = any instanceof User
                     ? userDAO.findAllResourceNames((User) any)
-                    : any instanceof Group
-                            ? ((Group) any).getResourceNames()
-                            : Collections.<String>emptySet();
+                    : any instanceof AnyObject
+                            ? anyObjectDAO.findAllResourceNames((AnyObject) any)
+                            : any instanceof Group
+                                    ? ((Group) any).getResourceNames()
+                                    : Collections.<String>emptySet();
             if (!resources.contains(task.getResource().getKey())) {
                 LOG.debug("Delete {} on {}", beforeObj.getUid(), task.getResource().getKey());
 
@@ -339,13 +339,7 @@ public abstract class AbstractPropagationTaskExecutor implements PropagationTask
         Connector connector = null;
         Result result;
         try {
-            Any<?, ?, ?> any = getAny(task);
-            provision = task.getResource().getProvision(any.getType());
-            if (provision == null) {
-                throw new IllegalArgumentException("No provision found for " + any.getType() + " on " + task.
-                        getResource());
-            }
-
+            provision = task.getResource().getProvision(new ObjectClass(task.getObjectClassName()));
             connector = connFactory.getConnector(task.getResource());
 
             // Try to read remote object BEFORE any actual operation

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/LDAPMembershipPropagationActions.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/LDAPMembershipPropagationActions.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/LDAPMembershipPropagationActions.java
index 6d795d8..6dbd0eb 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/LDAPMembershipPropagationActions.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/LDAPMembershipPropagationActions.java
@@ -46,7 +46,7 @@ import org.springframework.transaction.annotation.Transactional;
  * Simple action for propagating group memberships to LDAP groups, when the same resource is configured for both users
  * and groups.
  *
- * @see org.apache.syncope.core.sync.impl.LDAPMembershipSyncActions
+ * @see org.apache.syncope.core.provisioning.java.sync.LDAPMembershipSyncActions
  */
 public class LDAPMembershipPropagationActions extends DefaultPropagationActions {
 
@@ -85,7 +85,7 @@ public class LDAPMembershipPropagationActions extends DefaultPropagationActions
 
                         JexlContext jexlContext = new MapContext();
                         JexlUtils.addFieldsToContext(group, jexlContext);
-                        JexlUtils.addAttrsToContext(group.getPlainAttrs(), jexlContext);
+                        JexlUtils.addPlainAttrsToContext(group.getPlainAttrs(), jexlContext);
                         JexlUtils.addDerAttrsToContext(group.getDerAttrs(), group.getPlainAttrs(), jexlContext);
 
                         String groupConnObjectLinkLink =

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/PropagationManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/PropagationManagerImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/PropagationManagerImpl.java
index 8f52059..2649623 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/PropagationManagerImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/propagation/PropagationManagerImpl.java
@@ -30,7 +30,6 @@ import org.apache.commons.lang3.tuple.Pair;
 import org.apache.syncope.common.lib.mod.AttrMod;
 import org.apache.syncope.common.lib.mod.UserMod;
 import org.apache.syncope.common.lib.to.AttrTO;
-import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.MappingPurpose;
 import org.apache.syncope.common.lib.types.PropagationByResource;
 import org.apache.syncope.common.lib.types.ResourceOperation;
@@ -45,7 +44,6 @@ import org.apache.syncope.core.persistence.api.entity.user.User;
 import org.apache.syncope.core.provisioning.api.WorkflowResult;
 import org.apache.syncope.core.provisioning.api.propagation.PropagationManager;
 import org.apache.syncope.core.provisioning.api.propagation.PropagationTaskExecutor;
-import org.apache.syncope.core.provisioning.java.VirAttrHandler;
 import org.apache.syncope.core.misc.ConnObjectUtils;
 import org.apache.syncope.core.misc.MappingUtils;
 import org.apache.syncope.core.misc.jexl.JexlUtils;
@@ -57,6 +55,7 @@ import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
 import org.apache.syncope.core.persistence.api.entity.resource.Provision;
+import org.apache.syncope.core.provisioning.api.VirAttrHandler;
 import org.identityconnectors.framework.common.objects.Attribute;
 import org.identityconnectors.framework.common.objects.AttributeBuilder;
 import org.identityconnectors.framework.common.objects.AttributeUtil;
@@ -71,9 +70,6 @@ import org.springframework.transaction.annotation.Transactional;
 @Transactional(rollbackFor = { Throwable.class })
 public class PropagationManagerImpl implements PropagationManager {
 
-    /**
-     * Logger.
-     */
     protected static final Logger LOG = LoggerFactory.getLogger(PropagationManager.class);
 
     protected AnyObjectDAO anyObjectDAO;
@@ -129,7 +125,7 @@ public class PropagationManagerImpl implements PropagationManager {
 
         AnyObject anyObject = anyObjectDAO.authFind(key);
         if (vAttrs != null && !vAttrs.isEmpty()) {
-            virAttrHandler.fillVirtual(anyObject, vAttrs, anyUtilsFactory.getInstance(AnyTypeKind.ANY_OBJECT));
+            virAttrHandler.fillVirtual(anyObject, vAttrs);
         }
 
         return getCreateTaskIds(anyObject, null, null, propByRes, noPropResourceNames);
@@ -146,7 +142,7 @@ public class PropagationManagerImpl implements PropagationManager {
 
         User user = userDAO.authFind(key);
         if (vAttrs != null && !vAttrs.isEmpty()) {
-            virAttrHandler.fillVirtual(user, vAttrs, anyUtilsFactory.getInstance(AnyTypeKind.USER));
+            virAttrHandler.fillVirtual(user, vAttrs);
         }
         return getCreateTaskIds(user, password, enable, propByRes, noPropResourceNames);
     }
@@ -169,7 +165,7 @@ public class PropagationManagerImpl implements PropagationManager {
 
         Group group = groupDAO.authFind(key);
         if (vAttrs != null && !vAttrs.isEmpty()) {
-            virAttrHandler.fillVirtual(group, vAttrs, anyUtilsFactory.getInstance(AnyTypeKind.GROUP));
+            virAttrHandler.fillVirtual(group, vAttrs);
         }
 
         return getCreateTaskIds(group, null, null, propByRes, noPropResourceNames);
@@ -287,11 +283,13 @@ public class PropagationManagerImpl implements PropagationManager {
             final Set<String> vAttrsToBeRemoved, final Set<AttrMod> vAttrsToBeUpdated,
             final PropagationByResource propByRes, final Collection<String> noPropResourceNames) {
 
-        PropagationByResource localPropByRes = virAttrHandler.fillVirtual(any, vAttrsToBeRemoved == null
-                ? Collections.<String>emptySet()
-                : vAttrsToBeRemoved, vAttrsToBeUpdated == null
+        PropagationByResource localPropByRes = virAttrHandler.fillVirtual(
+                any,
+                vAttrsToBeRemoved == null
+                        ? Collections.<String>emptySet()
+                        : vAttrsToBeRemoved, vAttrsToBeUpdated == null
                         ? Collections.<AttrMod>emptySet()
-                        : vAttrsToBeUpdated, anyUtilsFactory.getInstance(any));
+                        : vAttrsToBeUpdated);
 
         if (propByRes == null || propByRes.isEmpty()) {
             localPropByRes.addAll(ResourceOperation.UPDATE, any.getResourceNames());
@@ -419,7 +417,7 @@ public class PropagationManagerImpl implements PropagationManager {
         if (!propByRes.get(ResourceOperation.CREATE).isEmpty()
                 && vAttrsToBeRemoved != null && vAttrsToBeUpdated != null) {
 
-            connObjectUtils.retrieveVirAttrValues(any);
+            virAttrHandler.retrieveVirAttrValues(any);
 
             // update vAttrsToBeUpdated as well
             for (VirAttr<?> virAttr : any.getVirAttrs()) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/AbstractProvisioningJob.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/AbstractProvisioningJob.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/AbstractProvisioningJob.java
index 4f7b744..8f80ac0 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/AbstractProvisioningJob.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/AbstractProvisioningJob.java
@@ -302,7 +302,8 @@ public abstract class AbstractProvisioningJob<T extends ProvisioningTask, A exte
                 append(' ').
                 append("[deleted/failures]: ").append(gSuccDelete.size()).append('/').append(gFailDelete.size()).
                 append(' ').
-                append("[no operation/ignored]: ").append(gSuccNone.size()).append('/').append(gIgnore.size());
+                append("[no operation/ignored]: ").append(gSuccNone.size()).append('/').append(gIgnore.size()).
+                append('\n');
         report.append("Any objects ").
                 append("[created/failures]: ").append(aSuccCreate.size()).append('/').append(aFailCreate.size()).
                 append(' ').

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/AbstractPushResultHandler.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/AbstractPushResultHandler.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/AbstractPushResultHandler.java
index 275f648..fd5a482 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/AbstractPushResultHandler.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/AbstractPushResultHandler.java
@@ -116,14 +116,13 @@ public abstract class AbstractPushResultHandler extends AbstractSyncopeResultHan
 
         Object output = null;
         Result resultStatus = null;
-        ConnectorObject beforeObj = null;
         String operation = null;
 
-        // Try to read remote object (user / group) BEFORE any actual operation
+        // Try to read remote object BEFORE any actual operation
         Provision provision = profile.getTask().getResource().getProvision(any.getType());
         String connObjecKey = MappingUtils.getConnObjectKeyValue(any, provision);
 
-        beforeObj = getRemoteObject(connObjecKey, provision.getObjectClass());
+        ConnectorObject beforeObj = getRemoteObject(connObjecKey, provision.getObjectClass());
 
         Boolean status = profile.getTask().isSyncStatus() ? enabled : null;
 
@@ -186,7 +185,6 @@ public abstract class AbstractPushResultHandler extends AbstractSyncopeResultHan
                         default:
                         // do nothing
                     }
-
                 } else {
                     operation = MatchingRule.toEventName(profile.getTask().getMatchingRule());
                     result.setOperation(getResourceOperation(profile.getTask().getMatchingRule()));

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/AbstractSyncResultHandler.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/AbstractSyncResultHandler.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/AbstractSyncResultHandler.java
index 1ead6a7..6d8986a 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/AbstractSyncResultHandler.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/AbstractSyncResultHandler.java
@@ -109,7 +109,7 @@ public abstract class AbstractSyncResultHandler extends AbstractSyncopeResultHan
 
         anyTO.getResources().add(profile.getTask().getResource().getKey());
 
-        final ProvisioningResult result = new ProvisioningResult();
+        ProvisioningResult result = new ProvisioningResult();
         result.setOperation(ResourceOperation.CREATE);
         result.setAnyType(provision.getAnyType().getKey());
         result.setStatus(ProvisioningResult.Status.SUCCESS);
@@ -149,7 +149,7 @@ public abstract class AbstractSyncResultHandler extends AbstractSyncopeResultHan
         AnyTO transformed = anyTransformer.transform(anyTO);
         LOG.debug("Transformed: {}", transformed);
 
-        final ProvisioningResult result = new ProvisioningResult();
+        ProvisioningResult result = new ProvisioningResult();
         result.setOperation(ResourceOperation.CREATE);
         result.setAnyType(provision.getAnyType().getKey());
         result.setStatus(ProvisioningResult.Status.SUCCESS);
@@ -270,7 +270,7 @@ public abstract class AbstractSyncResultHandler extends AbstractSyncopeResultHan
                             workingDelta = action.beforeUpdate(this.getProfile(), workingDelta, before, anyMod);
                         }
 
-                        final AnyTO updated = doUpdate(before, anyMod, workingDelta, result);
+                        AnyTO updated = doUpdate(before, anyMod, workingDelta, result);
 
                         for (SyncActions action : profile.getActions()) {
                             action.after(this.getProfile(), workingDelta, updated, result);
@@ -335,13 +335,13 @@ public abstract class AbstractSyncResultHandler extends AbstractSyncopeResultHan
             Object output;
             Result resultStatus;
 
-            final ProvisioningResult result = new ProvisioningResult();
+            ProvisioningResult result = new ProvisioningResult();
             result.setOperation(ResourceOperation.DELETE);
             result.setAnyType(provision.getAnyType().getKey());
             result.setStatus(ProvisioningResult.Status.SUCCESS);
             result.setKey(id);
 
-            final AnyTO before = getAnyTO(id);
+            AnyTO before = getAnyTO(id);
 
             if (before == null) {
                 result.setStatus(ProvisioningResult.Status.FAILURE);
@@ -427,8 +427,8 @@ public abstract class AbstractSyncResultHandler extends AbstractSyncopeResultHan
 
         final List<ProvisioningResult> updResults = new ArrayList<>();
 
-        for (Long id : anys) {
-            LOG.debug("About to unassign resource {}", id);
+        for (Long key : anys) {
+            LOG.debug("About to unassign resource {}", key);
 
             Object output;
             Result resultStatus;
@@ -437,13 +437,13 @@ public abstract class AbstractSyncResultHandler extends AbstractSyncopeResultHan
             result.setOperation(ResourceOperation.NONE);
             result.setAnyType(provision.getAnyType().getKey());
             result.setStatus(ProvisioningResult.Status.SUCCESS);
-            result.setKey(id);
+            result.setKey(key);
 
-            final AnyTO before = getAnyTO(id);
+            AnyTO before = getAnyTO(key);
 
             if (before == null) {
                 result.setStatus(ProvisioningResult.Status.FAILURE);
-                result.setMessage(String.format("Any '%s(%d)' not found", provision.getAnyType().getKey(), id));
+                result.setMessage(String.format("Any '%s(%d)' not found", provision.getAnyType().getKey(), key));
             }
 
             if (!profile.isDryRun()) {
@@ -471,7 +471,7 @@ public abstract class AbstractSyncResultHandler extends AbstractSyncopeResultHan
                         }
 
                         resultStatus = Result.SUCCESS;
-                        LOG.debug("{} {} successfully updated", provision.getAnyType().getKey(), id);
+                        LOG.debug("{} {} successfully updated", provision.getAnyType().getKey(), key);
                     } catch (IgnoreProvisionException e) {
                         throw e;
                     } catch (PropagationException e) {
@@ -527,11 +527,10 @@ public abstract class AbstractSyncResultHandler extends AbstractSyncopeResultHan
             Object output;
             Result resultStatus = Result.FAILURE;
 
-            AnyTO before = null;
-            final ProvisioningResult result = new ProvisioningResult();
+            ProvisioningResult result = new ProvisioningResult();
 
             try {
-                before = getAnyTO(id);
+                AnyTO before = getAnyTO(id);
 
                 result.setKey(id);
                 result.setName(getName(before));
@@ -590,7 +589,7 @@ public abstract class AbstractSyncResultHandler extends AbstractSyncopeResultHan
         LOG.debug("Any to ignore {}", delta.getObject().getUid().getUidValue());
 
         final List<ProvisioningResult> ignoreResults = new ArrayList<>();
-        final ProvisioningResult result = new ProvisioningResult();
+        ProvisioningResult result = new ProvisioningResult();
 
         result.setKey(null);
         result.setName(delta.getObject().getUid().getUidValue());

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/AbstractSyncopeResultHandler.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/AbstractSyncopeResultHandler.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/AbstractSyncopeResultHandler.java
index fccecc4..cf08d8d 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/AbstractSyncopeResultHandler.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/AbstractSyncopeResultHandler.java
@@ -49,10 +49,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 public abstract class AbstractSyncopeResultHandler<T extends ProvisioningTask, A extends ProvisioningActions>
         implements SyncopeResultHandler<T, A> {
 
-    /**
-     * Logger.
-     */
-    protected static final Logger LOG = LoggerFactory.getLogger(AbstractSyncopeResultHandler.class);
+    protected static final Logger LOG = LoggerFactory.getLogger(SyncopeResultHandler.class);
 
     @Autowired
     protected AnyObjectDAO anyObjectDAO;

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/GroupSyncResultHandlerImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/GroupSyncResultHandlerImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/GroupSyncResultHandlerImpl.java
index b6d5ccb..860e10b 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/GroupSyncResultHandlerImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/GroupSyncResultHandlerImpl.java
@@ -36,7 +36,7 @@ import org.identityconnectors.framework.common.objects.SyncDelta;
 
 public class GroupSyncResultHandlerImpl extends AbstractSyncResultHandler implements GroupSyncResultHandler {
 
-    protected Map<Long, String> groupOwnerMap = new HashMap<>();
+    protected final Map<Long, String> groupOwnerMap = new HashMap<>();
 
     @Override
     public Map<Long, String> getGroupOwnerMap() {
@@ -107,7 +107,7 @@ public class GroupSyncResultHandlerImpl extends AbstractSyncResultHandler implem
         // moved after group provisioning manager
         String groupOwner = null;
         for (AttrMod attrMod : groupMod.getPlainAttrsToUpdate()) {
-            if (attrMod.getSchema().isEmpty()) {
+            if (attrMod.getSchema().isEmpty() && !attrMod.getValuesToBeAdded().isEmpty()) {
                 groupOwner = attrMod.getValuesToBeAdded().iterator().next();
             }
         }
@@ -115,7 +115,7 @@ public class GroupSyncResultHandlerImpl extends AbstractSyncResultHandler implem
             groupOwnerMap.put(updated.getKey(), groupOwner);
         }
 
-        final GroupTO after = groupDataBinder.getGroupTO(updated.getKey());
+        GroupTO after = groupDataBinder.getGroupTO(updated.getKey());
 
         result.setName(getName(after));
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/LDAPMembershipSyncActions.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/LDAPMembershipSyncActions.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/LDAPMembershipSyncActions.java
index fb2f9a4..873232f 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/LDAPMembershipSyncActions.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/LDAPMembershipSyncActions.java
@@ -46,6 +46,7 @@ import org.apache.syncope.core.provisioning.api.sync.ProvisioningProfile;
 import org.apache.syncope.core.provisioning.api.sync.ProvisioningResult;
 import org.apache.syncope.core.misc.AuditManager;
 import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
+import org.apache.syncope.core.persistence.api.dao.UserDAO;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 import org.apache.syncope.core.persistence.api.entity.user.UMembership;
 import org.apache.syncope.core.provisioning.api.notification.NotificationManager;
@@ -63,7 +64,7 @@ import org.springframework.beans.factory.annotation.Autowired;
  * Simple action for synchronizing LDAP groups memberships to Syncope group memberships, when the same resource is
  * configured for both users and groups.
  *
- * @see org.apache.syncope.core.propagation.impl.LDAPMembershipPropagationActions
+ * @see org.apache.syncope.core.provisioning.java.propagation.LDAPMembershipPropagationActions
  */
 public class LDAPMembershipSyncActions extends DefaultSyncActions {
 
@@ -73,6 +74,9 @@ public class LDAPMembershipSyncActions extends DefaultSyncActions {
     protected AnyTypeDAO anyTypeDAO;
 
     @Autowired
+    protected UserDAO userDAO;
+
+    @Autowired
     protected GroupDAO groupDAO;
 
     @Autowired
@@ -182,7 +186,7 @@ public class LDAPMembershipSyncActions extends DefaultSyncActions {
         Attribute membAttr = delta.getObject().getAttributeByName(groupMemberName);
         // if not found, perform an additional read on the underlying connector for the same connector object
         if (membAttr == null) {
-            final OperationOptionsBuilder oob = new OperationOptionsBuilder();
+            OperationOptionsBuilder oob = new OperationOptionsBuilder();
             oob.setAttributesToGet(groupMemberName);
             membAttr = connector.getObjectAttribute(ObjectClass.GROUP, delta.getUid(), oob.build(), groupMemberName);
         }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/PushJobImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/PushJobImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/PushJobImpl.java
index b13213a..b658bc4 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/PushJobImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/PushJobImpl.java
@@ -27,7 +27,6 @@ import org.apache.syncope.core.persistence.api.dao.GroupDAO;
 import org.apache.syncope.core.persistence.api.dao.UserDAO;
 import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
 import org.apache.syncope.core.persistence.api.entity.task.PushTask;
-import org.apache.syncope.core.persistence.api.entity.user.User;
 import org.apache.syncope.core.provisioning.api.Connector;
 import org.apache.syncope.core.provisioning.api.sync.ProvisioningProfile;
 import org.apache.syncope.core.provisioning.api.sync.PushActions;
@@ -39,7 +38,9 @@ import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
 import org.apache.syncope.core.persistence.api.entity.Any;
 import org.apache.syncope.core.persistence.api.entity.resource.Provision;
 import org.apache.syncope.core.provisioning.api.job.PushJob;
+import org.apache.syncope.core.provisioning.api.sync.AnyObjectPushResultHandler;
 import org.apache.syncope.core.provisioning.api.sync.GroupPushResultHandler;
+import org.apache.syncope.core.provisioning.api.sync.SyncopePushResultHandler;
 import org.apache.syncope.core.provisioning.api.sync.UserPushResultHandler;
 import org.quartz.JobExecutionException;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -111,15 +112,20 @@ public class PushJobImpl extends AbstractProvisioningJob<PushTask, PushActions>
         profile.setDryRun(dryRun);
         profile.setResAct(null);
 
+        AnyObjectPushResultHandler ahandler =
+                (AnyObjectPushResultHandler) ApplicationContextProvider.getApplicationContext().getBeanFactory().
+                createBean(AnyObjectPushResultHandlerImpl.class, AbstractBeanDefinition.AUTOWIRE_BY_NAME, false);
+        ahandler.setProfile(profile);
+
         UserPushResultHandler uhandler =
                 (UserPushResultHandler) ApplicationContextProvider.getApplicationContext().getBeanFactory().
                 createBean(UserPushResultHandlerImpl.class, AbstractBeanDefinition.AUTOWIRE_BY_NAME, false);
         uhandler.setProfile(profile);
 
-        GroupPushResultHandler rhandler =
+        GroupPushResultHandler ghandler =
                 (GroupPushResultHandler) ApplicationContextProvider.getApplicationContext().getBeanFactory().
                 createBean(GroupPushResultHandlerImpl.class, AbstractBeanDefinition.AUTOWIRE_BY_NAME, false);
-        rhandler.setProfile(profile);
+        ghandler.setProfile(profile);
 
         if (actions != null && !profile.isDryRun()) {
             for (PushActions action : actions) {
@@ -138,16 +144,32 @@ public class PushJobImpl extends AbstractProvisioningJob<PushTask, PushActions>
                 for (int page = 1; page <= (count / PAGE_SIZE) + 1; page++) {
                     List<? extends Any<?, ?, ?>> localAnys = StringUtils.isBlank(filter)
                             ? anyDAO.findAll(SyncopeConstants.FULL_ADMIN_REALMS, page, PAGE_SIZE)
-                            : searchDAO.<User>search(SyncopeConstants.FULL_ADMIN_REALMS,
+                            : searchDAO.search(SyncopeConstants.FULL_ADMIN_REALMS,
                                     SearchCondConverter.convert(filter),
                                     Collections.<OrderByClause>emptyList(), provision.getAnyType().getKind());
 
                     for (Any<?, ?, ?> any : localAnys) {
+                        SyncopePushResultHandler handler;
+                        switch (provision.getAnyType().getKind()) {
+                            case USER:
+                                handler = uhandler;
+                                break;
+
+                            case GROUP:
+                                handler = ghandler;
+                                break;
+
+                            case ANY_OBJECT:
+                            default:
+                                handler = ahandler;
+                        }
+
                         try {
-                            uhandler.handle(any.getKey());
+                            handler.handle(any.getKey());
                         } catch (Exception e) {
-                            LOG.warn("Failure pushing user '{}' on '{}'", any, pushTask.getResource(), e);
-                            throw new JobExecutionException("While pushing users on connector", e);
+                            LOG.warn("Failure pushing '{}' on '{}'", any, pushTask.getResource(), e);
+                            throw new JobExecutionException(
+                                    "While pushing " + any + " on " + pushTask.getResource(), e);
                         }
                     }
                 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/SyncJobImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/SyncJobImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/SyncJobImpl.java
index 1e19d02..479d342 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/SyncJobImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/SyncJobImpl.java
@@ -60,8 +60,8 @@ public class SyncJobImpl extends AbstractProvisioningJob<SyncTask, SyncActions>
     @Autowired
     protected SyncUtils syncUtils;
 
-    protected void setGroupOwners(final GroupSyncResultHandler rhandler) {
-        for (Map.Entry<Long, String> entry : rhandler.getGroupOwnerMap().entrySet()) {
+    protected void setGroupOwners(final GroupSyncResultHandler ghandler) {
+        for (Map.Entry<Long, String> entry : ghandler.getGroupOwnerMap().entrySet()) {
             GroupMod groupMod = new GroupMod();
             groupMod.setKey(entry.getKey());
 
@@ -72,15 +72,15 @@ public class SyncJobImpl extends AbstractProvisioningJob<SyncTask, SyncActions>
                 Long userKey = syncUtils.findMatchingAnyKey(
                         anyTypeDAO.findUser(),
                         entry.getValue(),
-                        rhandler.getProfile().getTask().getResource(),
-                        rhandler.getProfile().getConnector());
+                        ghandler.getProfile().getTask().getResource(),
+                        ghandler.getProfile().getConnector());
 
                 if (userKey == null) {
                     Long groupKey = syncUtils.findMatchingAnyKey(
                             anyTypeDAO.findGroup(),
                             entry.getValue(),
-                            rhandler.getProfile().getTask().getResource(),
-                            rhandler.getProfile().getConnector());
+                            ghandler.getProfile().getTask().getResource(),
+                            ghandler.getProfile().getConnector());
 
                     if (groupKey != null) {
                         groupMod.setGroupOwner(new ReferenceMod(groupKey));

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/SyncUtils.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/SyncUtils.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/SyncUtils.java
index 8982824..b748345 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/SyncUtils.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/sync/SyncUtils.java
@@ -32,9 +32,7 @@ import org.apache.syncope.core.persistence.api.attrvalue.validation.ParsingValid
 import org.apache.syncope.core.persistence.api.dao.AnyDAO;
 import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
 import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
-import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
 import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
-import org.apache.syncope.core.persistence.api.dao.PolicyDAO;
 import org.apache.syncope.core.persistence.api.dao.GroupDAO;
 import org.apache.syncope.core.persistence.api.dao.UserDAO;
 import org.apache.syncope.core.persistence.api.dao.search.AnyCond;
@@ -69,52 +67,40 @@ import org.springframework.stereotype.Component;
 @Component
 public class SyncUtils {
 
-    /**
-     * Logger.
-     */
-    protected static final Logger LOG = LoggerFactory.getLogger(SyncUtils.class);
-
-    /**
-     * Policy DAO.
-     */
-    @Autowired
-    protected PolicyDAO policyDAO;
+    private static final Logger LOG = LoggerFactory.getLogger(SyncUtils.class);
 
     /**
      * Schema DAO.
      */
     @Autowired
-    protected PlainSchemaDAO plainSchemaDAO;
-
-    @Autowired
-    protected AnyTypeDAO anyTypeDAO;
+    private PlainSchemaDAO plainSchemaDAO;
 
     /**
      * Any Object DAO.
      */
     @Autowired
-    protected AnyObjectDAO anyObjectDAO;
+    private AnyObjectDAO anyObjectDAO;
 
     /**
      * User DAO.
      */
     @Autowired
-    protected UserDAO userDAO;
+    private UserDAO userDAO;
 
     /**
      * Group DAO.
      */
     @Autowired
-    protected GroupDAO groupDAO;
+    private GroupDAO groupDAO;
 
     /**
      * Search DAO.
      */
     @Autowired
-    protected AnySearchDAO searchDAO;
+    private AnySearchDAO searchDAO;
 
     @Autowired
-    protected AnyUtilsFactory anyUtilsFactory;
+    private AnyUtilsFactory anyUtilsFactory;
 
     public Long findMatchingAnyKey(
             final AnyType anyType,
@@ -180,7 +166,8 @@ public class SyncUtils {
         switch (connObjectKeyItem.getIntMappingType()) {
             case UserPlainSchema:
             case GroupPlainSchema:
-                final PlainAttrValue value = anyUtils.newPlainAttrValue();
+            case AnyPlainSchema:
+                PlainAttrValue value = anyUtils.newPlainAttrValue();
 
                 PlainSchema schema = plainSchemaDAO.find(connObjectKeyItem.getIntAttrName());
                 if (schema == null) {
@@ -203,21 +190,24 @@ public class SyncUtils {
 
             case UserDerivedSchema:
             case GroupDerivedSchema:
+            case AnyDerivedSchema:
                 anys = getAnyDAO(connObjectKeyItem).findByDerAttrValue(connObjectKeyItem.getIntAttrName(), uid);
                 for (Any<?, ?, ?> any : anys) {
                     result.add(any.getKey());
                 }
                 break;
 
-            case Username:
-                User user = userDAO.find(uid);
-                if (user != null) {
-                    result.add(user.getKey());
+            case UserId:
+            case GroupId:
+            case AnyId:
+                Any<?, ?, ?> any = getAnyDAO(connObjectKeyItem).find(Long.parseLong(uid));
+                if (any != null) {
+                    result.add(any.getKey());
                 }
                 break;
 
-            case UserId:
-                user = userDAO.find(Long.parseLong(uid));
+            case Username:
+                User user = userDAO.find(uid);
                 if (user != null) {
                     result.add(user.getKey());
                 }
@@ -230,13 +220,6 @@ public class SyncUtils {
                 }
                 break;
 
-            case GroupId:
-                group = groupDAO.find(Long.parseLong(uid));
-                if (group != null) {
-                    result.add(group.getKey());
-                }
-                break;
-
             default:
                 LOG.error("Invalid connObjectKey type '{}'", connObjectKeyItem.getIntMappingType());
         }
@@ -354,7 +337,7 @@ public class SyncUtils {
     }
 
     /**
-     * Find users / groups based on mapped uid value (or previous uid value, if updated).
+     * Find any objects based on mapped uid value (or previous uid value, if updated).
      *
      * @param uid for finding by connObjectKey
      * @param connObj for finding by attribute value
@@ -381,9 +364,10 @@ public class SyncUtils {
             altSearchSchemas = getAltSearchSchemas(provision, syncPolicySpec);
         }
 
-        return syncRule == null ? altSearchSchemas == null || altSearchSchemas.isEmpty()
-                ? findByConnObjectKeyItem(uid, provision, anyUtils)
-                : findByAnySearch(connObj, altSearchSchemas, provision, anyUtils)
+        return syncRule == null
+                ? altSearchSchemas == null || altSearchSchemas.isEmpty()
+                        ? findByConnObjectKeyItem(uid, provision, anyUtils)
+                        : findByAnySearch(connObj, altSearchSchemas, provision, anyUtils)
                 : findByCorrelationRule(connObj, syncRule, anyUtils.getAnyTypeKind());
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderTest.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderTest.java b/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderTest.java
index 039337f..f2eb839 100644
--- a/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderTest.java
+++ b/core/provisioning-java/src/test/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderTest.java
@@ -79,7 +79,7 @@ public class ResourceDataBinderTest extends AbstractTest {
 
         ResourceTO resourceTO = new ResourceTO();
         resourceTO.setKey("resource-issue42");
-        resourceTO.setConnectorId(100L);
+        resourceTO.setConnector(100L);
         resourceTO.setPropagationMode(PropagationMode.ONE_PHASE);
         resourceTO.setEnforceMandatoryCondition(true);
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/RestServiceExceptionMapper.java
----------------------------------------------------------------------
diff --git a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/RestServiceExceptionMapper.java b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/RestServiceExceptionMapper.java
index f031c92..18f6101 100644
--- a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/RestServiceExceptionMapper.java
+++ b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/RestServiceExceptionMapper.java
@@ -51,6 +51,7 @@ import org.apache.syncope.core.persistence.api.attrvalue.validation.ParsingValid
 import org.apache.syncope.core.persistence.api.dao.DuplicateException;
 import org.apache.syncope.core.persistence.api.dao.MalformedPathException;
 import org.apache.syncope.core.persistence.api.dao.NotFoundException;
+import org.apache.syncope.core.persistence.api.dao.UnallowedSchemaException;
 import org.apache.syncope.core.workflow.api.WorkflowException;
 import org.identityconnectors.framework.common.exceptions.ConfigurationException;
 import org.identityconnectors.framework.common.exceptions.ConnectorException;
@@ -114,6 +115,8 @@ public class RestServiceExceptionMapper implements ExceptionMapper<Exception>, R
                     header(HttpHeaders.WWW_AUTHENTICATE, BASIC_REALM_UNAUTHORIZED);
         } else if (ex instanceof UnauthorizedException) {
             builder = builder(ClientExceptionType.Unauthorized, ExceptionUtils.getRootCauseMessage(ex));
+        } else if (ex instanceof UnallowedSchemaException) {
+            builder = builder(ClientExceptionType.UnallowedSchemas, ExceptionUtils.getRootCauseMessage(ex));
         } else if (ex instanceof EntityExistsException || ex instanceof DuplicateException) {
             builder = builder(ClientExceptionType.EntityExists, getJPAMessage(ex));
         } else if (ex instanceof DataIntegrityViolationException || ex instanceof JpaSystemException) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AnyTypeClassServiceImpl.java
----------------------------------------------------------------------
diff --git a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AnyTypeClassServiceImpl.java b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AnyTypeClassServiceImpl.java
new file mode 100644
index 0000000..47cdde2
--- /dev/null
+++ b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AnyTypeClassServiceImpl.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.rest.cxf.service;
+
+import java.net.URI;
+import java.util.List;
+import javax.ws.rs.core.Response;
+import org.apache.syncope.common.lib.to.AnyTypeClassTO;
+import org.apache.syncope.common.rest.api.RESTHeaders;
+import org.apache.syncope.common.rest.api.service.AnyTypeClassService;
+import org.apache.syncope.core.logic.AnyTypeClassLogic;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class AnyTypeClassServiceImpl extends AbstractServiceImpl implements AnyTypeClassService {
+
+    @Autowired
+    private AnyTypeClassLogic logic;
+
+    @Override
+    public List<AnyTypeClassTO> list() {
+        return logic.list();
+    }
+
+    @Override
+    public AnyTypeClassTO read(final String key) {
+        return logic.read(key);
+    }
+
+    @Override
+    public Response create(final AnyTypeClassTO anyTypeTO) {
+        AnyTypeClassTO created = logic.create(anyTypeTO);
+        URI location = uriInfo.getAbsolutePathBuilder().path(String.valueOf(created.getKey())).build();
+        return Response.created(location).
+                header(RESTHeaders.RESOURCE_ID, created.getKey()).
+                build();
+    }
+
+    @Override
+    public void update(final String key, final AnyTypeClassTO anyTypeTO) {
+        anyTypeTO.setKey(key);
+        logic.update(anyTypeTO);
+    }
+
+    @Override
+    public void delete(final String key) {
+        logic.delete(key);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AnyTypeServiceImpl.java
----------------------------------------------------------------------
diff --git a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AnyTypeServiceImpl.java b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AnyTypeServiceImpl.java
new file mode 100644
index 0000000..9b289d5
--- /dev/null
+++ b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/AnyTypeServiceImpl.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.rest.cxf.service;
+
+import java.net.URI;
+import java.util.List;
+import javax.ws.rs.core.Response;
+import org.apache.syncope.common.lib.to.AnyTypeTO;
+import org.apache.syncope.common.rest.api.RESTHeaders;
+import org.apache.syncope.common.rest.api.service.AnyTypeService;
+import org.apache.syncope.core.logic.AnyTypeLogic;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class AnyTypeServiceImpl extends AbstractServiceImpl implements AnyTypeService {
+
+    @Autowired
+    private AnyTypeLogic logic;
+
+    @Override
+    public List<AnyTypeTO> list() {
+        return logic.list();
+    }
+
+    @Override
+    public AnyTypeTO read(final String key) {
+        return logic.read(key);
+    }
+
+    @Override
+    public Response create(final AnyTypeTO anyTypeTO) {
+        AnyTypeTO created = logic.create(anyTypeTO);
+        URI location = uriInfo.getAbsolutePathBuilder().path(String.valueOf(created.getKey())).build();
+        return Response.created(location).
+                header(RESTHeaders.RESOURCE_ID, created.getKey()).
+                build();
+    }
+
+    @Override
+    public void update(final String key, final AnyTypeTO anyTypeTO) {
+        anyTypeTO.setKey(key);
+        logic.update(anyTypeTO);
+    }
+
+    @Override
+    public void delete(final String key) {
+        logic.delete(key);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ConnectorServiceImpl.java
----------------------------------------------------------------------
diff --git a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ConnectorServiceImpl.java b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ConnectorServiceImpl.java
index 618b245..9f6099c 100644
--- a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ConnectorServiceImpl.java
+++ b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ConnectorServiceImpl.java
@@ -135,12 +135,13 @@ public class ConnectorServiceImpl extends AbstractServiceImpl implements Connect
         BulkActionResult result = new BulkActionResult();
 
         if (bulkAction.getOperation() == BulkAction.Type.DELETE) {
-            for (String id : bulkAction.getTargets()) {
+            for (String key : bulkAction.getTargets()) {
                 try {
-                    result.add(logic.delete(Long.valueOf(id)).getKey(), BulkActionResult.Status.SUCCESS);
+                    result.getResults().put(
+                            String.valueOf(logic.delete(Long.valueOf(key)).getKey()), BulkActionResult.Status.SUCCESS);
                 } catch (Exception e) {
-                    LOG.error("Error performing delete for connector {}", id, e);
-                    result.add(id, BulkActionResult.Status.FAILURE);
+                    LOG.error("Error performing delete for connector {}", key, e);
+                    result.getResults().put(key, BulkActionResult.Status.FAILURE);
                 }
             }
         }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/GroupServiceImpl.java
----------------------------------------------------------------------
diff --git a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/GroupServiceImpl.java b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/GroupServiceImpl.java
index c8e42a1..5c640f0 100644
--- a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/GroupServiceImpl.java
+++ b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/GroupServiceImpl.java
@@ -155,21 +155,23 @@ public class GroupServiceImpl extends AbstractServiceImpl implements GroupServic
                 updated = logic.read(groupKey);
         }
 
-        final BulkActionResult res = new BulkActionResult();
+        BulkActionResult result = new BulkActionResult();
 
         if (type == ResourceDeassociationActionType.UNLINK) {
             for (ResourceName resourceName : resourceNames) {
-                res.add(resourceName.getElement(), updated.getResources().contains(resourceName.getElement())
-                        ? BulkActionResult.Status.FAILURE
-                        : BulkActionResult.Status.SUCCESS);
+                result.getResults().put(resourceName.getElement(),
+                        updated.getResources().contains(resourceName.getElement())
+                                ? BulkActionResult.Status.FAILURE
+                                : BulkActionResult.Status.SUCCESS);
             }
         } else {
             for (PropagationStatus propagationStatusTO : updated.getPropagationStatusTOs()) {
-                res.add(propagationStatusTO.getResource(), propagationStatusTO.getStatus().toString());
+                result.getResults().put(propagationStatusTO.getResource(),
+                        BulkActionResult.Status.valueOf(propagationStatusTO.getStatus().toString()));
             }
         }
 
-        return modificationResponse(res);
+        return modificationResponse(result);
     }
 
     @Override
@@ -198,21 +200,23 @@ public class GroupServiceImpl extends AbstractServiceImpl implements GroupServic
                 updated = logic.read(groupKey);
         }
 
-        final BulkActionResult res = new BulkActionResult();
+        BulkActionResult result = new BulkActionResult();
 
         if (type == ResourceAssociationActionType.LINK) {
             for (ResourceName resourceName : resourceNames) {
-                res.add(resourceName.getElement(), updated.getResources().contains(resourceName.getElement())
-                        ? BulkActionResult.Status.FAILURE
-                        : BulkActionResult.Status.SUCCESS);
+                result.getResults().put(resourceName.getElement(),
+                        updated.getResources().contains(resourceName.getElement())
+                                ? BulkActionResult.Status.FAILURE
+                                : BulkActionResult.Status.SUCCESS);
             }
         } else {
             for (PropagationStatus propagationStatusTO : updated.getPropagationStatusTOs()) {
-                res.add(propagationStatusTO.getResource(), propagationStatusTO.getStatus().toString());
+                result.getResults().put(propagationStatusTO.getResource(),
+                        BulkActionResult.Status.valueOf(propagationStatusTO.getStatus().toString()));
             }
         }
 
-        return modificationResponse(res);
+        return modificationResponse(result);
     }
 
     @Override
@@ -222,10 +226,12 @@ public class GroupServiceImpl extends AbstractServiceImpl implements GroupServic
         if (bulkAction.getOperation() == BulkAction.Type.DELETE) {
             for (String groupKey : bulkAction.getTargets()) {
                 try {
-                    result.add(logic.delete(Long.valueOf(groupKey)).getKey(), BulkActionResult.Status.SUCCESS);
+                    result.getResults().put(
+                            String.valueOf(logic.delete(Long.valueOf(groupKey)).getKey()),
+                            BulkActionResult.Status.SUCCESS);
                 } catch (Exception e) {
                     LOG.error("Error performing delete for group {}", groupKey, e);
-                    result.add(groupKey, BulkActionResult.Status.FAILURE);
+                    result.getResults().put(groupKey, BulkActionResult.Status.FAILURE);
                 }
             }
         } else {

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ResourceServiceImpl.java
----------------------------------------------------------------------
diff --git a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ResourceServiceImpl.java b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ResourceServiceImpl.java
index 7ace502..28b834b 100644
--- a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ResourceServiceImpl.java
+++ b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ResourceServiceImpl.java
@@ -107,7 +107,7 @@ public class ResourceServiceImpl extends AbstractServiceImpl implements Resource
                         ? groupLogic
                         : anyObjectLogic;
 
-        BulkActionResult res = new BulkActionResult();
+        BulkActionResult result = new BulkActionResult();
 
         for (AnyKey key : keys) {
             Set<String> resources = Collections.singleton(resourceKey);
@@ -128,14 +128,14 @@ public class ResourceServiceImpl extends AbstractServiceImpl implements Resource
                     default:
                 }
 
-                res.add(key, BulkActionResult.Status.SUCCESS);
+                result.getResults().put(String.valueOf(key.getElement()), BulkActionResult.Status.SUCCESS);
             } catch (Exception e) {
                 LOG.warn("While executing {} on {} {}", type, anyTypeKey, key.getElement(), e);
-                res.add(key, BulkActionResult.Status.FAILURE);
+                result.getResults().put(String.valueOf(key.getElement()), BulkActionResult.Status.FAILURE);
             }
         }
 
-        return res;
+        return result;
     }
 
     @Override
@@ -145,10 +145,10 @@ public class ResourceServiceImpl extends AbstractServiceImpl implements Resource
         if (bulkAction.getOperation() == BulkAction.Type.DELETE) {
             for (String name : bulkAction.getTargets()) {
                 try {
-                    result.add(logic.delete(name).getKey(), BulkActionResult.Status.SUCCESS);
+                    result.getResults().put(logic.delete(name).getKey(), BulkActionResult.Status.SUCCESS);
                 } catch (Exception e) {
                     LOG.error("Error performing delete for resource {}", name, e);
-                    result.add(name, BulkActionResult.Status.FAILURE);
+                    result.getResults().put(name, BulkActionResult.Status.FAILURE);
                 }
             }
         }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/TaskServiceImpl.java
----------------------------------------------------------------------
diff --git a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/TaskServiceImpl.java b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/TaskServiceImpl.java
index 9da72aa..d42ed6a 100644
--- a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/TaskServiceImpl.java
+++ b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/TaskServiceImpl.java
@@ -129,10 +129,12 @@ public class TaskServiceImpl extends AbstractServiceImpl implements TaskService
             case DELETE:
                 for (String taskKey : bulkAction.getTargets()) {
                     try {
-                        result.add(logic.delete(Long.valueOf(taskKey)).getKey(), BulkActionResult.Status.SUCCESS);
+                        result.getResults().put(
+                                String.valueOf(logic.delete(Long.valueOf(taskKey)).getKey()),
+                                BulkActionResult.Status.SUCCESS);
                     } catch (Exception e) {
                         LOG.error("Error performing delete for task {}", taskKey, e);
-                        result.add(taskKey, BulkActionResult.Status.FAILURE);
+                        result.getResults().put(taskKey, BulkActionResult.Status.FAILURE);
                     }
                 }
                 break;
@@ -141,10 +143,10 @@ public class TaskServiceImpl extends AbstractServiceImpl implements TaskService
                 for (String taskKey : bulkAction.getTargets()) {
                     try {
                         logic.execute(Long.valueOf(taskKey), true);
-                        result.add(taskKey, BulkActionResult.Status.SUCCESS);
+                        result.getResults().put(taskKey, BulkActionResult.Status.SUCCESS);
                     } catch (Exception e) {
                         LOG.error("Error performing dryrun for task {}", taskKey, e);
-                        result.add(taskKey, BulkActionResult.Status.FAILURE);
+                        result.getResults().put(taskKey, BulkActionResult.Status.FAILURE);
                     }
                 }
                 break;
@@ -153,10 +155,10 @@ public class TaskServiceImpl extends AbstractServiceImpl implements TaskService
                 for (String taskKey : bulkAction.getTargets()) {
                     try {
                         logic.execute(Long.valueOf(taskKey), false);
-                        result.add(taskKey, BulkActionResult.Status.SUCCESS);
+                        result.getResults().put(taskKey, BulkActionResult.Status.SUCCESS);
                     } catch (Exception e) {
                         LOG.error("Error performing execute for task {}", taskKey, e);
-                        result.add(taskKey, BulkActionResult.Status.FAILURE);
+                        result.getResults().put(taskKey, BulkActionResult.Status.FAILURE);
                     }
                 }
                 break;

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserServiceImpl.java
----------------------------------------------------------------------
diff --git a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserServiceImpl.java b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserServiceImpl.java
index 919cb0a..83f09a4 100644
--- a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserServiceImpl.java
+++ b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/UserServiceImpl.java
@@ -60,7 +60,7 @@ public class UserServiceImpl extends AbstractServiceImpl implements UserService
     }
 
     @Override
-    public Response getUserId(final String username) {
+    public Response getUserKey(final String username) {
         return Response.ok().header(HttpHeaders.ALLOW, OPTIONS_ALLOW).
                 header(RESTHeaders.USER_ID, logic.getKey(username)).
                 build();
@@ -179,21 +179,23 @@ public class UserServiceImpl extends AbstractServiceImpl implements UserService
                 updated = logic.read(userKey);
         }
 
-        final BulkActionResult res = new BulkActionResult();
+        BulkActionResult result = new BulkActionResult();
 
         if (type == ResourceDeassociationActionType.UNLINK) {
             for (ResourceName resourceName : resourceNames) {
-                res.add(resourceName.getElement(), updated.getResources().contains(resourceName.getElement())
-                        ? BulkActionResult.Status.FAILURE
-                        : BulkActionResult.Status.SUCCESS);
+                result.getResults().put(
+                        resourceName.getElement(), updated.getResources().contains(resourceName.getElement())
+                                ? BulkActionResult.Status.FAILURE
+                                : BulkActionResult.Status.SUCCESS);
             }
         } else {
             for (PropagationStatus propagationStatusTO : updated.getPropagationStatusTOs()) {
-                res.add(propagationStatusTO.getResource(), propagationStatusTO.getStatus().toString());
+                result.getResults().put(propagationStatusTO.getResource(),
+                        BulkActionResult.Status.valueOf(propagationStatusTO.getStatus().toString()));
             }
         }
 
-        return modificationResponse(res);
+        return modificationResponse(result);
     }
 
     @Override
@@ -232,21 +234,23 @@ public class UserServiceImpl extends AbstractServiceImpl implements UserService
                 updated = logic.read(userKey);
         }
 
-        final BulkActionResult res = new BulkActionResult();
+        BulkActionResult result = new BulkActionResult();
 
         if (type == ResourceAssociationActionType.LINK) {
             for (ResourceName resourceName : associationMod.getTargetResources()) {
-                res.add(resourceName.getElement(), updated.getResources().contains(resourceName.getElement())
-                        ? BulkActionResult.Status.FAILURE
-                        : BulkActionResult.Status.SUCCESS);
+                result.getResults().put(resourceName.getElement(),
+                        updated.getResources().contains(resourceName.getElement())
+                                ? BulkActionResult.Status.FAILURE
+                                : BulkActionResult.Status.SUCCESS);
             }
         } else {
             for (PropagationStatus propagationStatusTO : updated.getPropagationStatusTOs()) {
-                res.add(propagationStatusTO.getResource(), propagationStatusTO.getStatus().toString());
+                result.getResults().put(propagationStatusTO.getResource(),
+                        BulkActionResult.Status.valueOf(propagationStatusTO.getStatus().toString()));
             }
         }
 
-        return modificationResponse(res);
+        return modificationResponse(result);
     }
 
     @Override
@@ -257,10 +261,12 @@ public class UserServiceImpl extends AbstractServiceImpl implements UserService
             case DELETE:
                 for (String key : bulkAction.getTargets()) {
                     try {
-                        result.add(logic.delete(Long.valueOf(key)).getKey(), BulkActionResult.Status.SUCCESS);
+                        result.getResults().put(
+                                String.valueOf(logic.delete(Long.valueOf(key)).getKey()),
+                                BulkActionResult.Status.SUCCESS);
                     } catch (Exception e) {
                         LOG.error("Error performing delete for user {}", key, e);
-                        result.add(key, BulkActionResult.Status.FAILURE);
+                        result.getResults().put(key, BulkActionResult.Status.FAILURE);
                     }
                 }
                 break;
@@ -271,10 +277,11 @@ public class UserServiceImpl extends AbstractServiceImpl implements UserService
                     statusMod.setKey(Long.valueOf(key));
                     statusMod.setType(StatusMod.ModType.SUSPEND);
                     try {
-                        result.add(logic.status(statusMod).getKey(), BulkActionResult.Status.SUCCESS);
+                        result.getResults().put(
+                                String.valueOf(logic.status(statusMod).getKey()), BulkActionResult.Status.SUCCESS);
                     } catch (Exception e) {
                         LOG.error("Error performing suspend for user {}", key, e);
-                        result.add(key, BulkActionResult.Status.FAILURE);
+                        result.getResults().put(key, BulkActionResult.Status.FAILURE);
                     }
                 }
                 break;
@@ -285,10 +292,11 @@ public class UserServiceImpl extends AbstractServiceImpl implements UserService
                     statusMod.setKey(Long.valueOf(key));
                     statusMod.setType(StatusMod.ModType.REACTIVATE);
                     try {
-                        result.add(logic.status(statusMod).getKey(), BulkActionResult.Status.SUCCESS);
+                        result.getResults().put(
+                                String.valueOf(logic.status(statusMod).getKey()), BulkActionResult.Status.SUCCESS);
                     } catch (Exception e) {
                         LOG.error("Error performing reactivate for user {}", key, e);
-                        result.add(key, BulkActionResult.Status.FAILURE);
+                        result.getResults().put(key, BulkActionResult.Status.FAILURE);
                     }
                 }
                 break;

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/ActivitiUserWorkflowAdapter.java
----------------------------------------------------------------------
diff --git a/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/ActivitiUserWorkflowAdapter.java b/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/ActivitiUserWorkflowAdapter.java
index 938081f..2e00cb9 100644
--- a/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/ActivitiUserWorkflowAdapter.java
+++ b/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/ActivitiUserWorkflowAdapter.java
@@ -84,15 +84,10 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Transactional;
 
 /**
- * Activiti {
- *
- * @see http://www.activiti.org/} based implementation.
+ * Activiti {@link http://www.activiti.org/} based implementation.
  */
 public class ActivitiUserWorkflowAdapter extends AbstractUserWorkflowAdapter {
 
-    /**
-     * Logger.
-     */
     private static final Logger LOG = LoggerFactory.getLogger(ActivitiUserWorkflowAdapter.class);
 
     private static final String[] PROPERTY_IGNORE_PROPS = { "type" };
@@ -258,7 +253,7 @@ public class ActivitiUserWorkflowAdapter extends AbstractUserWorkflowAdapter {
     public WorkflowResult<Pair<Long, Boolean>> create(final UserTO userTO, final boolean disablePwdPolicyCheck,
             final Boolean enabled, final boolean storePassword) {
 
-        final Map<String, Object> variables = new HashMap<>();
+        Map<String, Object> variables = new HashMap<>();
         variables.put(WF_EXECUTOR, AuthContextUtils.getAuthenticatedUsername());
         variables.put(USER_TO, userTO);
         variables.put(ENABLED, enabled);
@@ -271,8 +266,7 @@ public class ActivitiUserWorkflowAdapter extends AbstractUserWorkflowAdapter {
             throwException(e, "While starting " + WF_PROCESS_ID + " instance");
         }
 
-        User user =
-                runtimeService.getVariable(processInstance.getProcessInstanceId(), USER, User.class);
+        User user = runtimeService.getVariable(processInstance.getProcessInstanceId(), USER, User.class);
 
         Boolean updatedEnabled =
                 runtimeService.getVariable(processInstance.getProcessInstanceId(), ENABLED, Boolean.class);

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/ActivitiUtils.java
----------------------------------------------------------------------
diff --git a/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/ActivitiUtils.java b/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/ActivitiUtils.java
new file mode 100644
index 0000000..f598410
--- /dev/null
+++ b/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/ActivitiUtils.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.workflow.activiti;
+
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.Predicate;
+import org.apache.syncope.core.persistence.api.entity.user.UMembership;
+import org.apache.syncope.core.persistence.api.entity.user.User;
+import org.springframework.transaction.annotation.Transactional;
+
+public class ActivitiUtils {
+
+    @Transactional(readOnly = true)
+    public boolean isUserIngroup(final User user, final Long groupKey) {
+        return CollectionUtils.exists(user.getMemberships(), new Predicate<UMembership>() {
+
+            @Override
+            public boolean evaluate(final UMembership membership) {
+                return groupKey != null && groupKey.equals(membership.getRightEnd().getKey());
+            }
+        });
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/SyncopeUserManager.java
----------------------------------------------------------------------
diff --git a/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/SyncopeUserManager.java b/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/SyncopeUserManager.java
index 2b568b1..658795c 100644
--- a/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/SyncopeUserManager.java
+++ b/core/workflow-activiti/src/main/java/org/apache/syncope/core/workflow/activiti/SyncopeUserManager.java
@@ -75,8 +75,8 @@ public class SyncopeUserManager implements UserIdentityManager, SyncopeSession {
         org.apache.syncope.core.persistence.api.entity.user.User user = userDAO.find(userKey);
         if (user != null) {
             result = new ArrayList<>();
-            for (Long groupId : userDAO.findAllGroupKeys(user)) {
-                result.add(new GroupEntity(groupId.toString()));
+            for (Long groupKey : userDAO.findAllGroupKeys(user)) {
+                result.add(new GroupEntity(groupKey.toString()));
             }
         }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/workflow-activiti/src/main/resources/workflowActivitiContext.xml
----------------------------------------------------------------------
diff --git a/core/workflow-activiti/src/main/resources/workflowActivitiContext.xml b/core/workflow-activiti/src/main/resources/workflowActivitiContext.xml
index d5e9b02..75f0c38 100644
--- a/core/workflow-activiti/src/main/resources/workflowActivitiContext.xml
+++ b/core/workflow-activiti/src/main/resources/workflowActivitiContext.xml
@@ -30,6 +30,8 @@ under the License.
     <property name="fallback" value="classpath:userWorkflow.bpmn20.xml"/>
   </bean>
 
+  <bean id="activitiUtils" class="org.apache.syncope.core.workflow.activiti.ActivitiUtils"/>
+
   <bean id="syncopeActivitiUserManager" class="org.apache.syncope.core.workflow.activiti.SyncopeUserManager"/>
   <bean id="syncopeActivitiGroupManager" class="org.apache.syncope.core.workflow.activiti.SyncopeGroupManager"/>
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/GroupUpdateProcessor.java
----------------------------------------------------------------------
diff --git a/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/GroupUpdateProcessor.java b/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/GroupUpdateProcessor.java
index 7a2f455..2aaec2a 100644
--- a/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/GroupUpdateProcessor.java
+++ b/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/GroupUpdateProcessor.java
@@ -18,14 +18,18 @@
  */
 package org.apache.syncope.core.provisioning.camel.processor;
 
+import java.util.Collections;
 import java.util.List;
 import java.util.Set;
 import org.apache.camel.Exchange;
 import org.apache.camel.Processor;
 import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.apache.syncope.common.lib.mod.GroupMod;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
+import org.apache.syncope.common.lib.types.PropagationByResource;
 import org.apache.syncope.core.misc.spring.ApplicationContextProvider;
 import org.apache.syncope.core.persistence.api.entity.task.PropagationTask;
+import org.apache.syncope.core.provisioning.api.VirAttrHandler;
 import org.apache.syncope.core.provisioning.api.WorkflowResult;
 import org.apache.syncope.core.provisioning.api.propagation.PropagationException;
 import org.apache.syncope.core.provisioning.api.propagation.PropagationManager;
@@ -47,15 +51,30 @@ public class GroupUpdateProcessor implements Processor {
     @Autowired
     protected PropagationTaskExecutor taskExecutor;
 
+    @Autowired
+    protected VirAttrHandler virtAttrHandler;
+
     @SuppressWarnings("unchecked")
     @Override
     public void process(final Exchange exchange) {
         WorkflowResult<Long> updated = (WorkflowResult) exchange.getIn().getBody();
-        GroupMod anyMod = exchange.getProperty("anyMod", GroupMod.class);
+        GroupMod groupMod = exchange.getProperty("anyMod", GroupMod.class);
         Set<String> excludedResources = exchange.getProperty("excludedResources", Set.class);
 
         List<PropagationTask> tasks = propagationManager.getGroupUpdateTasks(updated,
-                anyMod.getVirAttrsToRemove(), anyMod.getVirAttrsToUpdate(), excludedResources);
+                groupMod.getVirAttrsToRemove(), groupMod.getVirAttrsToUpdate(), excludedResources);
+        if (tasks.isEmpty()) {
+            // SYNCOPE-459: take care of user virtual attributes ...
+            PropagationByResource propByResVirAttr = virtAttrHandler.fillVirtual(
+                    updated.getResult(),
+                    AnyTypeKind.GROUP,
+                    groupMod.getVirAttrsToRemove(),
+                    groupMod.getVirAttrsToUpdate());
+            tasks.addAll(!propByResVirAttr.isEmpty()
+                    ? propagationManager.getGroupUpdateTasks(updated, null, null, null)
+                    : Collections.<PropagationTask>emptyList());
+        }
+
         PropagationReporter propagationReporter =
                 ApplicationContextProvider.getApplicationContext().getBean(PropagationReporter.class);
         try {

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/UserUpdateProcessor.java
----------------------------------------------------------------------
diff --git a/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/UserUpdateProcessor.java b/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/UserUpdateProcessor.java
index 355080b..e71a15a 100644
--- a/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/UserUpdateProcessor.java
+++ b/ext/camel/provisioning-camel/src/main/java/org/apache/syncope/core/provisioning/camel/processor/UserUpdateProcessor.java
@@ -25,15 +25,16 @@ import org.apache.camel.Processor;
 import org.apache.commons.lang3.tuple.ImmutablePair;
 import org.apache.commons.lang3.tuple.Pair;
 import org.apache.syncope.common.lib.mod.UserMod;
+import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.PropagationByResource;
 import org.apache.syncope.core.misc.spring.ApplicationContextProvider;
 import org.apache.syncope.core.persistence.api.entity.task.PropagationTask;
+import org.apache.syncope.core.provisioning.api.VirAttrHandler;
 import org.apache.syncope.core.provisioning.api.WorkflowResult;
 import org.apache.syncope.core.provisioning.api.propagation.PropagationException;
 import org.apache.syncope.core.provisioning.api.propagation.PropagationManager;
 import org.apache.syncope.core.provisioning.api.propagation.PropagationReporter;
 import org.apache.syncope.core.provisioning.api.propagation.PropagationTaskExecutor;
-import org.apache.syncope.core.provisioning.java.VirAttrHandler;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -57,15 +58,16 @@ public class UserUpdateProcessor implements Processor {
     @SuppressWarnings("unchecked")
     public void process(final Exchange exchange) {
         WorkflowResult<Pair<UserMod, Boolean>> updated = (WorkflowResult) exchange.getIn().getBody();
-        UserMod actual = exchange.getProperty("actual", UserMod.class);
+        UserMod userMod = exchange.getProperty("actual", UserMod.class);
 
         List<PropagationTask> tasks = propagationManager.getUserUpdateTasks(updated);
         if (tasks.isEmpty()) {
             // SYNCOPE-459: take care of user virtual attributes ...
-            final PropagationByResource propByResVirAttr = virtAttrHandler.fillVirtual(
+            PropagationByResource propByResVirAttr = virtAttrHandler.fillVirtual(
                     updated.getResult().getKey().getKey(),
-                    actual.getVirAttrsToRemove(),
-                    actual.getVirAttrsToUpdate());
+                    AnyTypeKind.USER,
+                    userMod.getVirAttrsToRemove(),
+                    userMod.getVirAttrsToUpdate());
             tasks.addAll(!propByResVirAttr.isEmpty()
                     ? propagationManager.getUserUpdateTasks(updated, false, null)
                     : Collections.<PropagationTask>emptyList());

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/fit/core-reference/src/main/resources/all/provisioning.properties
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/main/resources/all/provisioning.properties b/fit/core-reference/src/main/resources/all/provisioning.properties
index 5061502..4d0ecaf 100644
--- a/fit/core-reference/src/main/resources/all/provisioning.properties
+++ b/fit/core-reference/src/main/resources/all/provisioning.properties
@@ -18,4 +18,4 @@ camel.directory=${conf.directory}
 userProvisioningManager=org.apache.syncope.core.provisioning.camel.CamelUserProvisioningManager
 groupProvisioningManager=org.apache.syncope.core.provisioning.camel.CamelGroupProvisioningManager
 anyObjectProvisioningManager=org.apache.syncope.core.provisioning.java.DefaultAnyObjectProvisioningManager
-virAttrCache=org.apache.syncope.core.provisioning.java.cache.MemoryVirAttrCache
+virAttrCache=org.apache.syncope.core.provisioning.java.cache.MemoryVirAttrCache
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/fit/core-reference/src/main/resources/userWorkflow.bpmn20.xml
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/main/resources/userWorkflow.bpmn20.xml b/fit/core-reference/src/main/resources/userWorkflow.bpmn20.xml
index 9a6ee5b..df292b8 100644
--- a/fit/core-reference/src/main/resources/userWorkflow.bpmn20.xml
+++ b/fit/core-reference/src/main/resources/userWorkflow.bpmn20.xml
@@ -34,10 +34,14 @@ under the License.
     <sequenceFlow id="flow2" sourceRef="create" targetRef="createGW"/>
     <exclusiveGateway id="createGW"/>
     <sequenceFlow id="createAsAnonymous2Approval" sourceRef="createGW" targetRef="createApproval">
-      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${wfExecutor == 'anonymous' || user.getStaticGroupKeys().contains(9)}]]></conditionExpression>
+      <conditionExpression xsi:type="tFormalExpression">
+        <![CDATA[${wfExecutor == 'anonymous' || activitiUtils.isUserIngroup(user, 9)}]]>
+      </conditionExpression>
     </sequenceFlow>
     <sequenceFlow id="create2Activate" sourceRef="createGW" targetRef="enableGW">
-      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${!user.getStaticGroupKeys().contains(9)}]]></conditionExpression>
+      <conditionExpression xsi:type="tFormalExpression">
+        <![CDATA[${!activitiUtils.isUserIngroup(user, 9)}]]>
+      </conditionExpression>
     </sequenceFlow>
     <userTask id="createApproval" name="Create approval" activiti:candidateGroups="7" activiti:formKey="createApproval">
       <extensionElements>
@@ -56,7 +60,9 @@ under the License.
     </sequenceFlow>
     <exclusiveGateway id="enableGW"/>
     <sequenceFlow id="createApprovalGW2OptIn" sourceRef="enableGW" targetRef="generateToken">
-      <conditionExpression xsi:type="tFormalExpression"><![CDATA[${user.getStaticGroupKeys().contains(11)}]]></conditionExpression>
+      <conditionExpression xsi:type="tFormalExpression">
+        <![CDATA[${activitiUtils.isUserIngroup(user, 11)}]]>
+      </conditionExpression>
     </sequenceFlow>
     <sequenceFlow id="createApprovalGW2Activate" sourceRef="enableGW" targetRef="activate">
       <conditionExpression xsi:type="tFormalExpression"><![CDATA[${enabled == null}]]></conditionExpression>

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/AbstractITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/AbstractITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/AbstractITCase.java
index 3984c5e..97fc9d0 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/AbstractITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/AbstractITCase.java
@@ -48,6 +48,8 @@ import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.ConnConfProperty;
 import org.apache.syncope.common.lib.types.SchemaType;
 import org.apache.syncope.common.rest.api.RESTHeaders;
+import org.apache.syncope.common.rest.api.service.AnyTypeClassService;
+import org.apache.syncope.common.rest.api.service.AnyTypeService;
 import org.apache.syncope.common.rest.api.service.CamelRouteService;
 import org.apache.syncope.common.rest.api.service.ConfigurationService;
 import org.apache.syncope.common.rest.api.service.ConnectorService;
@@ -147,6 +149,10 @@ public abstract class AbstractITCase {
 
     protected static SyncopeService syncopeService;
 
+    protected static AnyTypeClassService anyTypeClassService;
+
+    protected static AnyTypeService anyTypeService;
+
     protected static RealmService realmService;
 
     protected static RoleService roleService;
@@ -217,6 +223,8 @@ public abstract class AbstractITCase {
         adminClient = clientFactory.create(ADMIN_UNAME, ADMIN_PWD);
 
         syncopeService = adminClient.getService(SyncopeService.class);
+        anyTypeClassService = adminClient.getService(AnyTypeClassService.class);
+        anyTypeService = adminClient.getService(AnyTypeService.class);
         realmService = adminClient.getService(RealmService.class);
         roleService = adminClient.getService(RoleService.class);
         userService = adminClient.getService(UserService.class);
@@ -272,7 +280,7 @@ public abstract class AbstractITCase {
 
     protected UserTO readUser(final String username) {
         return userService.read(Long.valueOf(
-                userService.getUserId(username).getHeaderString(RESTHeaders.USER_ID)));
+                userService.getUserKey(username).getHeaderString(RESTHeaders.USER_ID)));
     }
 
     protected UserTO updateUser(final UserMod userMod) {
@@ -361,7 +369,7 @@ public abstract class AbstractITCase {
             throws NamingException {
         ResourceTO ldapRes = resourceService.read(RESOURCE_NAME_LDAP);
         final Map<String, ConnConfProperty> ldapConnConf =
-                connectorService.read(ldapRes.getConnectorId()).getConfigurationMap();
+                connectorService.read(ldapRes.getConnector()).getConfigurationMap();
 
         Properties env = new Properties();
         env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");


[15/21] syncope git commit: Merge from master

Posted by il...@apache.org.
Merge from master


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

Branch: refs/heads/SYNCOPE-666
Commit: d8c9479dd1f14d8af8f2d5bd6ded992c40e2cfe6
Parents: 79b1e80 6d120f7
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Fri Jun 5 16:53:03 2015 +0200
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Fri Jun 5 16:53:03 2015 +0200

----------------------------------------------------------------------
 .../syncope/client/console/pages/Reports.java   |  12 ++
 .../syncope/client/console/pages/Tasks.java     |   9 ++
 .../console/panels/NotificationTasks.java       |   3 +
 .../client/console/panels/RuntimePanel.java     | 130 +++++++++++++++++++
 .../client/console/panels/SchedTasks.java       |   3 +
 .../client/console/panels/SyncTasksPanel.java   |   6 +-
 .../client/console/rest/JobRestClient.java      |  31 +++++
 .../client/console/rest/ReportRestClient.java   |  25 +++-
 .../client/console/rest/TaskRestClient.java     |  25 +++-
 .../html/repeater/data/table/JobColumn.java     |  66 ++++++++++
 .../syncope/client/console/pages/Reports.html   |  13 ++
 .../syncope/client/console/pages/Tasks.html     |  15 +++
 .../client/console/panels/RuntimePanel.html     |  49 +++++++
 .../syncope/core/logic/AbstractJobLogic.java    |  15 ++-
 .../api/notification/NotificationManager.java   |   4 +-
 .../notification/NotificationManagerImpl.java   |   8 +-
 pom.xml                                         |   6 +-
 17 files changed, 410 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/d8c9479d/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/NotificationManagerImpl.java
----------------------------------------------------------------------
diff --cc core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/NotificationManagerImpl.java
index 776b8db,900abc7..a0469a2
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/NotificationManagerImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/NotificationManagerImpl.java
@@@ -271,31 -266,29 +271,32 @@@ public class NotificationManagerImpl im
              final Object output,
              final Object... input) {
  
 -        SubjectType subjectType = null;
 -        Subject<?, ?, ?> subject = null;
 -        List<NotificationTask> notificationList = new ArrayList<NotificationTask>();
 +        Any<?, ?, ?> any = null;
  
          if (before instanceof UserTO) {
 -            subjectType = SubjectType.USER;
 -            subject = userDAO.find(((UserTO) before).getKey());
 +            any = userDAO.find(((UserTO) before).getKey());
          } else if (output instanceof UserTO) {
 -            subjectType = SubjectType.USER;
 -            subject = userDAO.find(((UserTO) output).getKey());
 +            any = userDAO.find(((UserTO) output).getKey());
 +        } else if (before instanceof AnyObjectTO) {
 +            any = anyObjectDAO.find(((AnyObjectTO) before).getKey());
 +        } else if (output instanceof AnyObjectTO) {
 +            any = anyObjectDAO.find(((AnyObjectTO) output).getKey());
          } else if (before instanceof GroupTO) {
 -            subjectType = SubjectType.GROUP;
 -            subject = groupDAO.find(((GroupTO) before).getKey());
 +            any = groupDAO.find(((GroupTO) before).getKey());
          } else if (output instanceof GroupTO) {
 -            subjectType = SubjectType.GROUP;
 -            subject = groupDAO.find(((GroupTO) output).getKey());
 +            any = groupDAO.find(((GroupTO) output).getKey());
          }
  
 -        LOG.debug("Search notification for [{}]{}", subjectType, subject);
 +        AnyType anyType = any == null ? null : any.getType();
 +        LOG.debug("Search notification for [{}]{}", anyType, any);
  
++        List<NotificationTask> notifications = new ArrayList<>();
          for (Notification notification : notificationDAO.findAll()) {
 -            LOG.debug("Notification available user about {}", notification.getUserAbout());
 -            LOG.debug("Notification available group about {}", notification.getGroupAbout());
 +            if (LOG.isDebugEnabled()) {
 +                for (AnyAbout about : notification.getAbouts()) {
 +                    LOG.debug("Notification about {} defined: {}", about.getAnyType(), about.get());
 +                }
 +            }
  
              if (notification.isActive()) {
                  String currentEvent = AuditLoggerName.buildEvent(type, category, subcategory, event, condition);
@@@ -318,18 -314,23 +319,21 @@@
                      model.put("output", output);
                      model.put("input", input);
  
 -                    if (subject instanceof User) {
 -                        model.put("user", userDataBinder.getUserTO((User) subject));
 -                    } else if (subject instanceof Group) {
 -                        model.put("group", groupDataBinder.getGroupTO((Group) subject));
 +                    if (any instanceof User) {
 +                        model.put("user", userDataBinder.getUserTO((User) any));
 +                    } else if (any instanceof Group) {
 +                        model.put("group", groupDataBinder.getGroupTO((Group) any));
                      }
  
-                     taskDAO.save(getNotificationTask(notification, any, model));
 -                    NotificationTask notificationTask = getNotificationTask(notification, subject, model);
++                    NotificationTask notificationTask = getNotificationTask(notification, any, model);
+                     notificationTask = taskDAO.save(notificationTask);
 -                    notificationList.add(notificationTask);     
++                    notifications.add(notificationTask);
                  }
              } else {
 -                LOG.debug("Notification {}, userAbout {}, groupAbout {} is deactivated, "
 -                        + "notification task will not be created", notification.getKey(),
 -                        notification.getUserAbout(), notification.getGroupAbout());
 +                LOG.debug("Notification {} is not active, task will not be created", notification.getKey());
              }
          }
 -        return notificationList;
++        return notifications;
      }
  
      private String getRecipientEmail(

http://git-wip-us.apache.org/repos/asf/syncope/blob/d8c9479d/pom.xml
----------------------------------------------------------------------


[05/21] syncope git commit: [SYNCOPE-660] Added console utilities for runtime task management - Minor fixes

Posted by il...@apache.org.
[SYNCOPE-660] Added console utilities for runtime task management - Minor fixes


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

Branch: refs/heads/SYNCOPE-666
Commit: 8106e2460b55fb3a0dfcea90540f45a1cf3a5fb7
Parents: 790704c
Author: giacomolm <gi...@hotmail.it>
Authored: Mon Jun 1 12:15:45 2015 +0200
Committer: giacomolm <gi...@hotmail.it>
Committed: Mon Jun 1 12:15:45 2015 +0200

----------------------------------------------------------------------
 .../console/pages/panels/RuntimePanel.java      | 27 +++++++++++++++++-
 .../html/repeater/data/table/JobColumn.java     | 30 +-------------------
 2 files changed, 27 insertions(+), 30 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/8106e246/console/src/main/java/org/apache/syncope/console/pages/panels/RuntimePanel.java
----------------------------------------------------------------------
diff --git a/console/src/main/java/org/apache/syncope/console/pages/panels/RuntimePanel.java b/console/src/main/java/org/apache/syncope/console/pages/panels/RuntimePanel.java
index 3bc525c..93150fc 100644
--- a/console/src/main/java/org/apache/syncope/console/pages/panels/RuntimePanel.java
+++ b/console/src/main/java/org/apache/syncope/console/pages/panels/RuntimePanel.java
@@ -23,9 +23,11 @@ import org.apache.syncope.console.wicket.ajax.markup.html.ClearIndicatingAjaxLin
 import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AbstractAjaxTimerBehavior;
 import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
 import org.apache.wicket.markup.html.panel.Fragment;
 import org.apache.wicket.model.IModel;
 import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.util.time.Duration;
 
 public class RuntimePanel extends Panel {
 
@@ -54,7 +56,7 @@ public class RuntimePanel extends Panel {
 
     }
 
-    public final void refresh() {
+    public final RuntimePanel refresh() {
         boolean currentStatus = jobRestClient.isJobRunning(jobId);
         if (currentStatus && !latestStatus) {
             setRunning();
@@ -62,6 +64,7 @@ public class RuntimePanel extends Panel {
             setNotRunning();
         }
         latestStatus = currentStatus;
+        return this;
     }
 
     public void setRunning() {
@@ -102,4 +105,26 @@ public class RuntimePanel extends Panel {
         this.add(this.timer);
     }
 
+    public void startPolling(final int seconds) {
+        AbstractAjaxTimerBehavior timer = new AbstractAjaxTimerBehavior(Duration.seconds(seconds)) {
+
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            protected void onTimer(AjaxRequestTarget target) {                
+                target.add(refresh());
+            }
+
+            @Override
+            protected void updateAjaxAttributes(AjaxRequestAttributes attributes) {
+                super.updateAjaxAttributes(attributes);
+                attributes.getExtraParameters().put("pollingTimeout", "true");
+            }
+
+        };
+
+        setTimer(timer);
+
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/8106e246/console/src/main/java/org/apache/syncope/console/wicket/extensions/markup/html/repeater/data/table/JobColumn.java
----------------------------------------------------------------------
diff --git a/console/src/main/java/org/apache/syncope/console/wicket/extensions/markup/html/repeater/data/table/JobColumn.java b/console/src/main/java/org/apache/syncope/console/wicket/extensions/markup/html/repeater/data/table/JobColumn.java
index 563e3cb..24e1ef7 100644
--- a/console/src/main/java/org/apache/syncope/console/wicket/extensions/markup/html/repeater/data/table/JobColumn.java
+++ b/console/src/main/java/org/apache/syncope/console/wicket/extensions/markup/html/repeater/data/table/JobColumn.java
@@ -23,14 +23,10 @@ import org.apache.syncope.common.to.ReportTO;
 import org.apache.syncope.console.pages.panels.RuntimePanel;
 import org.apache.syncope.console.rest.JobRestClient;
 import org.apache.wicket.PageReference;
-import org.apache.wicket.ajax.AbstractAjaxTimerBehavior;
-import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
 import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
 import org.apache.wicket.extensions.markup.html.repeater.data.table.AbstractColumn;
 import org.apache.wicket.markup.repeater.Item;
 import org.apache.wicket.model.IModel;
-import org.apache.wicket.util.time.Duration;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -63,32 +59,8 @@ public class JobColumn<T, S> extends AbstractColumn<T, S> {
         }
         if (jobId != null) {
             panel = new RuntimePanel(componentId, model, pageRef, jobId, jobRestClient);
-            startPolling(10);
+            panel.startPolling(10);
             item.add(panel);
         }
     }
-
-    public void startPolling(final int seconds) {
-        AbstractAjaxTimerBehavior timer = new AbstractAjaxTimerBehavior(Duration.seconds(seconds)) {
-
-            private static final long serialVersionUID = 1L;
-
-            @Override
-            protected void onTimer(AjaxRequestTarget target) {
-                panel.refresh();
-                target.add(panel);
-            }
-
-            @Override
-            protected void updateAjaxAttributes(AjaxRequestAttributes attributes) {
-                super.updateAjaxAttributes(attributes);
-                attributes.getExtraParameters().put("pollingTimeout", "true");
-            }
-
-        };
-
-        panel.setTimer(timer);
-
-    }
-
 }


[16/21] syncope git commit: [SYNCOPE-666] All tests are green, time to add more

Posted by il...@apache.org.
http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/AbstractTaskITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/AbstractTaskITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/AbstractTaskITCase.java
index 5dc3f5c..37bf12c 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/AbstractTaskITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/AbstractTaskITCase.java
@@ -57,7 +57,9 @@ public abstract class AbstractTaskITCase extends AbstractITCase {
 
         private final boolean dryRun;
 
-        public ThreadExec(AbstractTaskITCase test, Long taskKey, int maxWaitSeconds, boolean dryRun) {
+        public ThreadExec(
+                final AbstractTaskITCase test, final Long taskKey, final int maxWaitSeconds, final boolean dryRun) {
+
             this.test = test;
             this.taskKey = taskKey;
             this.maxWaitSeconds = maxWaitSeconds;
@@ -66,7 +68,7 @@ public abstract class AbstractTaskITCase extends AbstractITCase {
 
         @Override
         public TaskExecTO call() throws Exception {
-            return test.execSyncTask(taskKey, maxWaitSeconds, dryRun);
+            return test.execProvisioningTask(taskKey, maxWaitSeconds, dryRun);
         }
     }
 
@@ -85,7 +87,7 @@ public abstract class AbstractTaskITCase extends AbstractITCase {
         }
     }
 
-    protected TaskExecTO execSyncTask(final Long taskKey, final int maxWaitSeconds, final boolean dryRun) {
+    protected TaskExecTO execProvisioningTask(final Long taskKey, final int maxWaitSeconds, final boolean dryRun) {
         AbstractTaskTO taskTO = taskService.read(taskKey);
         assertNotNull(taskTO);
         assertNotNull(taskTO.getExecutions());
@@ -117,17 +119,17 @@ public abstract class AbstractTaskITCase extends AbstractITCase {
         return taskTO.getExecutions().get(taskTO.getExecutions().size() - 1);
     }
 
-    protected Map<Long, TaskExecTO> execSyncTasks(
+    protected Map<Long, TaskExecTO> execProvisioningTasks(
             final Set<Long> taskKeys, final int maxWaitSeconds, final boolean dryRun) throws Exception {
 
-        final ExecutorService service = Executors.newFixedThreadPool(taskKeys.size());
-        final List<Future<TaskExecTO>> futures = new ArrayList<>();
+        ExecutorService service = Executors.newFixedThreadPool(taskKeys.size());
+        List<Future<TaskExecTO>> futures = new ArrayList<>();
 
         for (Long key : taskKeys) {
             futures.add(service.submit(new ThreadExec(this, key, maxWaitSeconds, dryRun)));
         }
 
-        final Map<Long, TaskExecTO> res = new HashMap<>();
+        Map<Long, TaskExecTO> res = new HashMap<>();
 
         for (Future<TaskExecTO> future : futures) {
             TaskExecTO taskExecTO = future.get(100, TimeUnit.SECONDS);

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/CamelRouteITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/CamelRouteITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/CamelRouteITCase.java
index fcb988b..1a086e2 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/CamelRouteITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/CamelRouteITCase.java
@@ -18,12 +18,14 @@
  */
 package org.apache.syncope.fit.core.reference;
 
+import static org.apache.syncope.fit.core.reference.AbstractITCase.anyTypeClassService;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 
 import java.util.List;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.to.AnyTypeClassTO;
 import org.apache.syncope.common.lib.to.CamelRouteTO;
 import org.apache.syncope.common.lib.to.PlainSchemaTO;
 import org.apache.syncope.common.lib.to.UserTO;
@@ -147,8 +149,14 @@ public class CamelRouteITCase extends AbstractITCase {
             schemaTO.setType(AttrSchemaType.String);
             createSchema(SchemaType.PLAIN, schemaTO);
 
+            AnyTypeClassTO typeClass = new AnyTypeClassTO();
+            typeClass.setKey("camelAttribute");
+            typeClass.getPlainSchemas().add(schemaTO.getKey());
+            anyTypeClassService.create(typeClass);
+
             UserTO userTO = new UserTO();
             userTO.setRealm(SyncopeConstants.ROOT_REALM);
+            userTO.getAuxClasses().add(typeClass.getKey());
             String userId = getUUIDString() + "camelUser@syncope.apache.org";
             userTO.setUsername(userId);
             userTO.setPassword("password123");

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/ConfigurationITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/ConfigurationITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/ConfigurationITCase.java
index 7c1ca19..e311e41 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/ConfigurationITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/ConfigurationITCase.java
@@ -27,20 +27,15 @@ import static org.junit.Assert.fail;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.UnsupportedEncodingException;
-import java.util.ArrayList;
-import java.util.List;
 import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import org.apache.commons.io.IOUtils;
-import org.apache.commons.lang3.ArrayUtils;
-import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.to.AttrTO;
 import org.apache.syncope.common.lib.to.ConfTO;
 import org.apache.syncope.common.lib.to.PlainSchemaTO;
-import org.apache.syncope.common.lib.to.GroupTO;
 import org.apache.syncope.common.lib.types.AttrSchemaType;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
 import org.apache.syncope.common.lib.types.EntityViolationType;
@@ -153,91 +148,4 @@ public class ConfigurationITCase extends AbstractITCase {
             assertTrue(e.getElements().iterator().next().contains(EntityViolationType.InvalidName.name()));
         }
     }
-
-    private static String[] substringsBetween(final String str, final String open, final String close) {
-        if (str == null || StringUtils.isEmpty(open) || StringUtils.isEmpty(close)) {
-            return null;
-        }
-        final int strLen = str.length();
-        if (strLen == 0) {
-            return ArrayUtils.EMPTY_STRING_ARRAY;
-        }
-        final int closeLen = close.length();
-        final int openLen = open.length();
-        final List<String> list = new ArrayList<>();
-        int pos = 0;
-        while (pos < strLen - closeLen) {
-            int start = StringUtils.indexOfIgnoreCase(str, open, pos);
-            if (start < 0) {
-                break;
-            }
-            start += openLen;
-            final int end = StringUtils.indexOfIgnoreCase(str, close, start);
-            if (end < 0) {
-                break;
-            }
-            list.add(str.substring(start, end));
-            pos = end + closeLen;
-        }
-        if (list.isEmpty()) {
-            return null;
-        }
-        return list.toArray(new String[list.size()]);
-    }
-
-    @Test
-    public void issueSYNCOPE629() throws IOException {
-        PlainSchemaTO membershipKey = new PlainSchemaTO();
-        membershipKey.setKey("membershipKey" + getUUIDString());
-        membershipKey.setType(AttrSchemaType.String);
-        createSchema(SchemaType.PLAIN, membershipKey);
-
-        PlainSchemaTO groupKey = new PlainSchemaTO();
-        groupKey.setKey("group"
-                + "Key" + getUUIDString());
-        groupKey.setType(AttrSchemaType.String);
-        createSchema(SchemaType.PLAIN, groupKey);
-
-        GroupTO groupTO = new GroupTO();
-        groupTO.setRealm("/");
-        groupTO.setName("aGroup" + getUUIDString());
-        groupTO = createGroup(groupTO);
-
-        try {
-            Response response = configurationService.export();
-            assertNotNull(response);
-            assertEquals(Response.Status.OK.getStatusCode(), response.getStatusInfo().getStatusCode());
-            assertTrue(response.getMediaType().toString().startsWith(MediaType.TEXT_XML));
-            String contentDisposition = response.getHeaderString(HttpHeaders.CONTENT_DISPOSITION);
-            assertNotNull(contentDisposition);
-
-            Object entity = response.getEntity();
-            assertTrue(entity instanceof InputStream);
-            String configExport = IOUtils.toString((InputStream) entity, SyncopeConstants.DEFAULT_ENCODING);
-            assertFalse(configExport.isEmpty());
-            assertTrue(configExport.length() > 1000);
-
-            String[] result = substringsBetween(configExport, "<GPLAINATTRTEMPLATE", "/>");
-            assertNotNull(result);
-            boolean rattrExists = false;
-            for (String entry : result) {
-                if (entry.contains(groupKey.getKey())) {
-                    rattrExists = true;
-                }
-            }
-            assertTrue(rattrExists);
-
-            result = substringsBetween(configExport, "<MPLAINATTRTEMPLATE", "/>");
-            assertNotNull(result);
-            boolean mattrExists = false;
-            for (String entry : result) {
-                if (entry.contains(membershipKey.getKey())) {
-                    mattrExists = true;
-                }
-            }
-            assertTrue(mattrExists);
-        } finally {
-            deleteGroup(groupTO.getKey());
-        }
-    }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/ConnectorITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/ConnectorITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/ConnectorITCase.java
index 5d75e7c..2cd33a5 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/ConnectorITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/ConnectorITCase.java
@@ -273,7 +273,7 @@ public class ConnectorITCase extends AbstractITCase {
         List<ResourceTO> result = new ArrayList<>();
 
         for (ResourceTO resource : input) {
-            if (connectorKey.equals(resource.getConnectorId())) {
+            if (connectorKey.equals(resource.getConnector())) {
                 result.add(resource);
             }
         }
@@ -320,7 +320,7 @@ public class ConnectorITCase extends AbstractITCase {
         long connId = connInstanceTO.getKey();
 
         // Link resourceTO to the new connector instance.
-        resourceTO.setConnectorId(connId);
+        resourceTO.setConnector(connId);
         // ----------------------------------
 
         // ----------------------------------
@@ -639,7 +639,7 @@ public class ConnectorITCase extends AbstractITCase {
             ResourceTO resourceTO = new ResourceTO();
 
             resourceTO.setKey(resourceName);
-            resourceTO.setConnectorId(connectorTO.getKey());
+            resourceTO.setConnector(connectorTO.getKey());
 
             conf = new HashSet<>();
             endpoint.getValues().clear();

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/ExceptionMapperITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/ExceptionMapperITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/ExceptionMapperITCase.java
index e13e400..ae823e1 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/ExceptionMapperITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/ExceptionMapperITCase.java
@@ -18,6 +18,7 @@
  */
 package org.apache.syncope.fit.core.reference;
 
+import static org.apache.syncope.fit.core.reference.AbstractITCase.anyTypeClassService;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.fail;
 
@@ -27,6 +28,7 @@ import java.util.Properties;
 import org.apache.commons.io.IOUtils;
 import org.apache.syncope.common.lib.SyncopeClientCompositeException;
 import org.apache.syncope.common.lib.SyncopeConstants;
+import org.apache.syncope.common.lib.to.AnyTypeClassTO;
 import org.apache.syncope.common.lib.to.PlainSchemaTO;
 import org.apache.syncope.common.lib.to.RoleTO;
 import org.apache.syncope.common.lib.to.UserTO;
@@ -65,9 +67,15 @@ public class ExceptionMapperITCase extends AbstractITCase {
         schemaTO.setUniqueConstraint(true);
         createSchema(SchemaType.PLAIN, schemaTO);
 
+        AnyTypeClassTO typeClass = new AnyTypeClassTO();
+        typeClass.setKey("camelAttribute");
+        typeClass.getPlainSchemas().add(schemaTO.getKey());
+        anyTypeClassService.create(typeClass);
+
         // 2. create an user with mandatory attributes and unique
         UserTO userTO1 = new UserTO();
         userTO1.setRealm(SyncopeConstants.ROOT_REALM);
+        userTO1.getAuxClasses().add(typeClass.getKey());
         String userId1 = getUUIDString() + "issue654_1@syncope.apache.org";
         userTO1.setUsername(userId1);
         userTO1.setPassword("password123");
@@ -82,6 +90,7 @@ public class ExceptionMapperITCase extends AbstractITCase {
         // 3. create an other user with mandatory attributes and unique with the same value of userTO1
         UserTO userTO2 = new UserTO();
         userTO2.setRealm(SyncopeConstants.ROOT_REALM);
+        userTO2.getAuxClasses().add(typeClass.getKey());
         String userId2 = getUUIDString() + "issue654_2@syncope.apache.org";
         userTO2.setUsername(userId2);
         userTO2.setPassword("password123");

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/GroupITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/GroupITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/GroupITCase.java
index d0a4be1..391e8e7 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/GroupITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/GroupITCase.java
@@ -44,6 +44,8 @@ import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.SyncopeConstants;
 import org.apache.syncope.common.lib.mod.ReferenceMod;
 import org.apache.syncope.common.lib.mod.GroupMod;
+import org.apache.syncope.common.lib.to.AnyTypeClassTO;
+import org.apache.syncope.common.lib.to.AnyTypeTO;
 import org.apache.syncope.common.lib.to.BulkActionResult;
 import org.apache.syncope.common.lib.to.ConnObjectTO;
 import org.apache.syncope.common.lib.to.MappingItemTO;
@@ -418,6 +420,7 @@ public class GroupITCase extends AbstractITCase {
     public void deprovision() {
         GroupTO actual = createGroup(getSampleTO("deprovision"));
         assertNotNull(actual);
+        assertNotNull(actual.getKey());
 
         assertNotNull(resourceService.readConnObject(RESOURCE_NAME_LDAP, AnyTypeKind.GROUP.name(), actual.getKey()));
 
@@ -507,8 +510,8 @@ public class GroupITCase extends AbstractITCase {
     }
 
     @Test
-    public void createWithMandatorySchemaNotTemplate() {
-        // 1. create a group mandatory schema
+    public void createWithMandatorySchema() {
+        // 1. create a mandatory schema
         PlainSchemaTO badge = new PlainSchemaTO();
         badge.setKey("badge" + getUUIDString());
         badge.setMandatoryCondition("true");
@@ -521,24 +524,40 @@ public class GroupITCase extends AbstractITCase {
         assertNotNull(groupTO);
         assertFalse(groupTO.getPlainAttrMap().containsKey(badge.getKey()));
 
-        // 3. add a template for badge to the group just created - 
-        // failure since no values are provided and it is mandatory
-        GroupMod groupMod = new GroupMod();
-        groupMod.setKey(groupTO.getKey());
+        // 3. add the new mandatory schema to the default group type
+        AnyTypeTO type = anyTypeService.read(AnyTypeKind.GROUP.name());
+        String typeClassName = type.getClasses().get(0);
+        AnyTypeClassTO typeClass = anyTypeClassService.read(typeClassName);
+        typeClass.getPlainSchemas().add(badge.getKey());
+        anyTypeClassService.update(typeClassName, typeClass);
+        typeClass = anyTypeClassService.read(typeClassName);
+        assertTrue(typeClass.getPlainSchemas().contains(badge.getKey()));
 
         try {
-            updateGroup(groupMod);
-            fail();
-        } catch (SyncopeClientException e) {
-            assertEquals(ClientExceptionType.RequiredValuesMissing, e.getType());
-        }
+            // 4. update group: failure since no values are provided and it is mandatory
+            GroupMod groupMod = new GroupMod();
+            groupMod.setKey(groupTO.getKey());
+
+            try {
+                updateGroup(groupMod);
+                fail();
+            } catch (SyncopeClientException e) {
+                assertEquals(ClientExceptionType.RequiredValuesMissing, e.getType());
+            }
 
-        // 4. also add an actual attribute for badge - it will work        
-        groupMod.getPlainAttrsToUpdate().add(attrMod(badge.getKey(), "xxxxxxxxxx"));
+            // 5. also add an actual attribute for badge - it will work        
+            groupMod.getPlainAttrsToUpdate().add(attrMod(badge.getKey(), "xxxxxxxxxx"));
 
-        groupTO = updateGroup(groupMod);
-        assertNotNull(groupTO);
-        assertTrue(groupTO.getPlainAttrMap().containsKey(badge.getKey()));
+            groupTO = updateGroup(groupMod);
+            assertNotNull(groupTO);
+            assertTrue(groupTO.getPlainAttrMap().containsKey(badge.getKey()));
+        } finally {
+            // restore the original group class
+            typeClass.getPlainSchemas().remove(badge.getKey());
+            anyTypeClassService.update(typeClassName, typeClass);
+            typeClass = anyTypeClassService.read(typeClassName);
+            assertFalse(typeClass.getPlainSchemas().contains(badge.getKey()));
+        }
     }
 
     @Test

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/PlainSchemaITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/PlainSchemaITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/PlainSchemaITCase.java
index e77f343..e6e450c 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/PlainSchemaITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/PlainSchemaITCase.java
@@ -32,6 +32,7 @@ import org.apache.commons.lang3.SerializationUtils;
 import org.apache.syncope.common.lib.AnyOperations;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.mod.UserMod;
+import org.apache.syncope.common.lib.to.AnyTypeClassTO;
 import org.apache.syncope.common.lib.to.MembershipTO;
 import org.apache.syncope.common.lib.to.PlainSchemaTO;
 import org.apache.syncope.common.lib.to.UserTO;
@@ -63,8 +64,12 @@ public class PlainSchemaITCase extends AbstractITCase {
         PlainSchemaTO newPlainSchemaTO = createSchema(SchemaType.PLAIN, schemaTO);
         assertEquals(schemaTO, newPlainSchemaTO);
 
-        newPlainSchemaTO = createSchema(SchemaType.PLAIN, schemaTO);
-        assertEquals(schemaTO, newPlainSchemaTO);
+        try {
+            createSchema(SchemaType.PLAIN, schemaTO);
+            fail();
+        } catch (SyncopeClientException e) {
+            assertEquals(ClientExceptionType.EntityExists, e.getType());
+        }
     }
 
     @Test
@@ -79,8 +84,7 @@ public class PlainSchemaITCase extends AbstractITCase {
         } catch (SyncopeClientException e) {
             assertEquals(ClientExceptionType.InvalidPlainSchema, e.getType());
 
-            assertTrue(e.getElements().iterator().next().toString().
-                    contains(EntityViolationType.InvalidName.name()));
+            assertTrue(e.getElements().iterator().next().contains(EntityViolationType.InvalidName.name()));
         }
     }
 
@@ -202,7 +206,13 @@ public class PlainSchemaITCase extends AbstractITCase {
         schemaTO = createSchema(SchemaType.PLAIN, schemaTO);
         assertNotNull(schemaTO);
 
+        AnyTypeClassTO typeClass = new AnyTypeClassTO();
+        typeClass.setKey("issue258");
+        typeClass.getPlainSchemas().add(schemaTO.getKey());
+        anyTypeClassService.create(typeClass);
+
         UserTO userTO = UserITCase.getUniqueSampleTO("issue258@syncope.apache.org");
+        userTO.getAuxClasses().add(typeClass.getKey());
         userTO.getPlainAttrs().add(attrTO(schemaTO.getKey(), "1.2"));
 
         userTO = createUser(userTO);
@@ -225,7 +235,13 @@ public class PlainSchemaITCase extends AbstractITCase {
         schemaTO = createSchema(SchemaType.PLAIN, schemaTO);
         assertNotNull(schemaTO);
 
+        AnyTypeClassTO typeClass = new AnyTypeClassTO();
+        typeClass.setKey("issue259");
+        typeClass.getPlainSchemas().add(schemaTO.getKey());
+        anyTypeClassService.create(typeClass);
+
         UserTO userTO = UserITCase.getUniqueSampleTO("issue259@syncope.apache.org");
+        userTO.getAuxClasses().add(typeClass.getKey());
         userTO.getPlainAttrs().add(attrTO(schemaTO.getKey(), "1"));
         userTO = createUser(userTO);
         assertNotNull(userTO);
@@ -249,7 +265,13 @@ public class PlainSchemaITCase extends AbstractITCase {
         schemaTO = createSchema(SchemaType.PLAIN, schemaTO);
         assertNotNull(schemaTO);
 
+        AnyTypeClassTO typeClass = new AnyTypeClassTO();
+        typeClass.setKey("issue260");
+        typeClass.getPlainSchemas().add(schemaTO.getKey());
+        anyTypeClassService.create(typeClass);
+
         UserTO userTO = UserITCase.getUniqueSampleTO("issue260@syncope.apache.org");
+        userTO.getAuxClasses().add(typeClass.getKey());
         userTO.getPlainAttrs().add(attrTO(schemaTO.getKey(), "1.2"));
         userTO = createUser(userTO);
         assertNotNull(userTO);

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/PushTaskITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/PushTaskITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/PushTaskITCase.java
index 1f498cc..9a169c3 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/PushTaskITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/PushTaskITCase.java
@@ -18,6 +18,7 @@
  */
 package org.apache.syncope.fit.core.reference;
 
+import static org.apache.syncope.fit.core.reference.AbstractITCase.anyTypeClassService;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
@@ -31,6 +32,7 @@ import java.util.Set;
 import javax.ws.rs.core.Response;
 import org.apache.syncope.client.lib.SyncopeClient;
 import org.apache.syncope.common.lib.to.AbstractTaskTO;
+import org.apache.syncope.common.lib.to.AnyTypeClassTO;
 import org.apache.syncope.common.lib.to.MappingItemTO;
 import org.apache.syncope.common.lib.to.MappingTO;
 import org.apache.syncope.common.lib.to.NotificationTO;
@@ -120,12 +122,12 @@ public class PushTaskITCase extends AbstractTaskITCase {
     public void pushMatchingUnmatchingGroups() {
         assertFalse(groupService.read(3L).getResources().contains(RESOURCE_NAME_LDAP));
 
-        execSyncTask(23L, 50, false);
+        execProvisioningTask(23L, 50, false);
 
         assertNotNull(resourceService.readConnObject(RESOURCE_NAME_LDAP, AnyTypeKind.GROUP.name(), 3L));
         assertTrue(groupService.read(3L).getResources().contains(RESOURCE_NAME_LDAP));
 
-        execSyncTask(23L, 50, false);
+        execProvisioningTask(23L, 50, false);
 
         assertNotNull(resourceService.readConnObject(RESOURCE_NAME_LDAP, AnyTypeKind.GROUP.name(), 3L));
         assertFalse(groupService.read(3L).getResources().contains(RESOURCE_NAME_LDAP));
@@ -144,17 +146,17 @@ public class PushTaskITCase extends AbstractTaskITCase {
         // ------------------------------------------
         // Unmatching --> Assign --> dryRuyn
         // ------------------------------------------
-        execSyncTask(13L, 50, true);
+        execProvisioningTask(13L, 50, true);
         assertEquals(0, jdbcTemplate.queryForList("SELECT ID FROM test2 WHERE ID='vivaldi'").size());
         assertFalse(userService.read(3L).getResources().contains(RESOURCE_NAME_TESTDB2));
         // ------------------------------------------
 
-        final Set<Long> pushTaskIds = new HashSet<>();
+        Set<Long> pushTaskIds = new HashSet<>();
         pushTaskIds.add(13L);
         pushTaskIds.add(14L);
         pushTaskIds.add(15L);
         pushTaskIds.add(16L);
-        execSyncTasks(pushTaskIds, 50, false);
+        execProvisioningTasks(pushTaskIds, 50, false);
 
         // ------------------------------------------
         // Unatching --> Ignore
@@ -199,17 +201,17 @@ public class PushTaskITCase extends AbstractTaskITCase {
         // ------------------------------------------
         // Matching --> Deprovision --> dryRuyn
         // ------------------------------------------
-        execSyncTask(19L, 50, true);
+        execProvisioningTask(19L, 50, true);
         assertTrue(userService.read(1L).getResources().contains(RESOURCE_NAME_TESTDB2));
         assertEquals(1, jdbcTemplate.queryForList("SELECT ID FROM test2 WHERE ID='rossini'").size());
         // ------------------------------------------
 
-        final Set<Long> pushTaskIds = new HashSet<>();
-        pushTaskIds.add(18L);
-        pushTaskIds.add(19L);
-        pushTaskIds.add(16L);
+        Set<Long> pushTaskKeys = new HashSet<>();
+        pushTaskKeys.add(18L);
+        pushTaskKeys.add(19L);
+        pushTaskKeys.add(16L);
 
-        execSyncTasks(pushTaskIds, 50, false);
+        execProvisioningTasks(pushTaskKeys, 50, false);
 
         // ------------------------------------------
         // Matching --> Deprovision && Ignore
@@ -230,16 +232,16 @@ public class PushTaskITCase extends AbstractTaskITCase {
         // ------------------------------------------
         // Matching --> Link
         // ------------------------------------------
-        execSyncTask(20L, 50, false);
+        execProvisioningTask(20L, 50, false);
         assertTrue(userService.read(2L).getResources().contains(RESOURCE_NAME_TESTDB2));
         assertEquals(1, jdbcTemplate.queryForList("SELECT ID FROM test2 WHERE ID='verdi'").size());
         // ------------------------------------------
 
-        pushTaskIds.clear();
-        pushTaskIds.add(21L);
-        pushTaskIds.add(22L);
+        pushTaskKeys.clear();
+        pushTaskKeys.add(21L);
+        pushTaskKeys.add(22L);
 
-        execSyncTasks(pushTaskIds, 50, false);
+        execProvisioningTasks(pushTaskKeys, 50, false);
 
         // ------------------------------------------
         // Matching --> Unlink && Update
@@ -257,15 +259,21 @@ public class PushTaskITCase extends AbstractTaskITCase {
         schemaTO.setType(AttrSchemaType.String);
         schemaTO.setMandatoryCondition("true");
 
-        PlainSchemaTO newPlainSchemaTO = createSchema(SchemaType.PLAIN, schemaTO);
-        assertEquals(schemaTO, newPlainSchemaTO);
+        schemaTO = createSchema(SchemaType.PLAIN, schemaTO);
+        assertNotNull(schemaTO);
+
+        AnyTypeClassTO typeClass = new AnyTypeClassTO();
+        typeClass.setKey("SYNCOPE-598");
+        typeClass.getPlainSchemas().add(schemaTO.getKey());
+        anyTypeClassService.create(typeClass);
 
         // create a new sample group
         GroupTO groupTO = new GroupTO();
         groupTO.setName("all" + getUUIDString());
         groupTO.setRealm("/even");
+        groupTO.getAuxClasses().add(typeClass.getKey());
 
-        groupTO.getPlainAttrs().add(attrTO(newPlainSchemaTO.getKey(), "all"));
+        groupTO.getPlainAttrs().add(attrTO(schemaTO.getKey(), "all"));
 
         groupTO = createGroup(groupTO);
         assertNotNull(groupTO);
@@ -277,29 +285,28 @@ public class PushTaskITCase extends AbstractTaskITCase {
             // Create resource ad-hoc
             ResourceTO resourceTO = new ResourceTO();
             resourceTO.setKey(resourceName);
-            resourceTO.setConnectorId(105L);
+            resourceTO.setConnector(105L);
 
             ProvisionTO provisionTO = new ProvisionTO();
             provisionTO.setAnyType(AnyTypeKind.GROUP.name());
             provisionTO.setObjectClass(ObjectClass.GROUP_NAME);
             resourceTO.getProvisions().add(provisionTO);
 
-            MappingTO rmapping = new MappingTO();
-            provisionTO.setMapping(rmapping);
+            MappingTO mapping = new MappingTO();
+            provisionTO.setMapping(mapping);
 
             MappingItemTO item = new MappingItemTO();
             item.setIntMappingType(IntMappingType.GroupPlainSchema);
             item.setExtAttrName("cn");
-            item.setIntAttrName(newPlainSchemaTO.getKey());
+            item.setIntAttrName(schemaTO.getKey());
             item.setConnObjectKey(true);
             item.setPurpose(MappingPurpose.BOTH);
-            rmapping.setConnObjectKeyItem(item);
+            mapping.setConnObjectKeyItem(item);
 
-            rmapping.setConnObjectLink("'cn=' + " + newPlainSchemaTO.getKey() + " + ',ou=groups,o=isp'");
+            mapping.setConnObjectLink("'cn=' + " + schemaTO.getKey() + " + ',ou=groups,o=isp'");
 
             Response response = resourceService.create(resourceTO);
             newResourceTO = getObject(response.getLocation(), ResourceService.class, ResourceTO.class);
-
             assertNotNull(newResourceTO);
             assertNull(newResourceTO.getProvision(AnyTypeKind.USER.name()));
             assertNotNull(newResourceTO.getProvision(AnyTypeKind.GROUP.name()).getMapping());
@@ -316,11 +323,10 @@ public class PushTaskITCase extends AbstractTaskITCase {
 
             response = taskService.create(task);
             PushTaskTO push = getObject(response.getLocation(), TaskService.class, PushTaskTO.class);
-
             assertNotNull(push);
 
             // execute the new task
-            TaskExecTO pushExec = execSyncTask(push.getKey(), 50, false);
+            TaskExecTO pushExec = execProvisioningTask(push.getKey(), 50, false);
             assertTrue(PropagationTaskExecStatus.valueOf(pushExec.getStatus()).isSuccessful());
         } finally {
             groupService.delete(groupTO.getKey());
@@ -332,7 +338,7 @@ public class PushTaskITCase extends AbstractTaskITCase {
 
     @Test
     public void issueSYNCOPE648() {
-        //1. Create Push Task
+        // 1. Create Push Task
         PushTaskTO task = new PushTaskTO();
         task.setName("Test create Push");
         task.setResource(RESOURCE_NAME_LDAP);
@@ -343,8 +349,8 @@ public class PushTaskITCase extends AbstractTaskITCase {
         task.setMatchingRule(MatchingRule.IGNORE);
         task.setUnmatchingRule(UnmatchingRule.IGNORE);
 
-        final Response response = taskService.create(task);
-        final PushTaskTO actual = getObject(response.getLocation(), TaskService.class, PushTaskTO.class);
+        Response response = taskService.create(task);
+        PushTaskTO actual = getObject(response.getLocation(), TaskService.class, PushTaskTO.class);
         assertNotNull(actual);
 
         // 2. Create notification
@@ -368,7 +374,7 @@ public class PushTaskITCase extends AbstractTaskITCase {
         notification = getObject(responseNotification.getLocation(), NotificationService.class, NotificationTO.class);
         assertNotNull(notification);
 
-        execSyncTask(actual.getKey(), 50, false);
+        execProvisioningTask(actual.getKey(), 50, false);
 
         NotificationTaskTO taskTO = findNotificationTaskBySender("syncope648@syncope.apache.org");
         assertNotNull(taskTO);

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/ResourceITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/ResourceITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/ResourceITCase.java
index 2e6cf21..faf4701 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/ResourceITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/ResourceITCase.java
@@ -58,7 +58,7 @@ public class ResourceITCase extends AbstractITCase {
         ResourceTO resourceTO = new ResourceTO();
 
         resourceTO.setKey(resourceName);
-        resourceTO.setConnectorId(102L);
+        resourceTO.setConnector(102L);
 
         ProvisionTO provisionTO = new ProvisionTO();
         provisionTO.setAnyType(AnyTypeKind.USER.name());
@@ -151,7 +151,7 @@ public class ResourceITCase extends AbstractITCase {
         mapping.add(item);
 
         resourceTO.setKey(resourceName);
-        resourceTO.setConnectorId(102L);
+        resourceTO.setConnector(102L);
 
         ConnConfProperty p = new ConnConfProperty();
         ConnConfPropSchema schema = new ConnConfPropSchema();
@@ -178,7 +178,7 @@ public class ResourceITCase extends AbstractITCase {
         String resourceName = RESOURCE_NAME_CREATE_SINGLE;
         ResourceTO resourceTO = new ResourceTO();
         resourceTO.setKey(resourceName);
-        resourceTO.setConnectorId(102L);
+        resourceTO.setConnector(102L);
 
         ProvisionTO provisionTO = new ProvisionTO();
         provisionTO.setAnyType(AnyTypeKind.USER.name());
@@ -228,7 +228,7 @@ public class ResourceITCase extends AbstractITCase {
         String resourceName = RESOURCE_NAME_CREATE_WRONG;
         ResourceTO resourceTO = new ResourceTO();
         resourceTO.setKey(resourceName);
-        resourceTO.setConnectorId(102L);
+        resourceTO.setConnector(102L);
 
         ProvisionTO provisionTO = new ProvisionTO();
         provisionTO.setAnyType(AnyTypeKind.USER.name());
@@ -264,7 +264,7 @@ public class ResourceITCase extends AbstractITCase {
         String resourceName = RESOURCE_NAME_CREATE_WRONG;
         ResourceTO resourceTO = new ResourceTO();
         resourceTO.setKey(resourceName);
-        resourceTO.setConnectorId(102L);
+        resourceTO.setConnector(102L);
 
         ProvisionTO provisionTO = new ProvisionTO();
         provisionTO.setAnyType(AnyTypeKind.USER.name());
@@ -294,7 +294,7 @@ public class ResourceITCase extends AbstractITCase {
         String resourceName = "res-with-password-policy";
         ResourceTO resourceTO = new ResourceTO();
         resourceTO.setKey(resourceName);
-        resourceTO.setConnectorId(102L);
+        resourceTO.setConnector(102L);
         resourceTO.setPasswordPolicy(4L);
 
         ProvisionTO provisionTO = new ProvisionTO();
@@ -342,7 +342,7 @@ public class ResourceITCase extends AbstractITCase {
         String resourceName = RESOURCE_NAME_UPDATE;
         ResourceTO resourceTO = new ResourceTO();
         resourceTO.setKey(resourceName);
-        resourceTO.setConnectorId(101L);
+        resourceTO.setConnector(101L);
 
         ProvisionTO provisionTO = new ProvisionTO();
         provisionTO.setAnyType(AnyTypeKind.USER.name());
@@ -510,7 +510,7 @@ public class ResourceITCase extends AbstractITCase {
         assertNotNull(resource);
         assertNotNull(resource.getProvision(AnyTypeKind.USER.name()).getMapping());
 
-        resource.getProvision(AnyTypeKind.USER.name()).setMapping(new MappingTO());
+        resource.getProvision(AnyTypeKind.USER.name()).setMapping(null);
         resourceService.update(name, resource);
 
         resource = resourceService.read(name);
@@ -525,7 +525,7 @@ public class ResourceITCase extends AbstractITCase {
         ResourceTO resourceTO = new ResourceTO();
 
         resourceTO.setKey(name);
-        resourceTO.setConnectorId(105L);
+        resourceTO.setConnector(105L);
 
         ProvisionTO provisionTO = new ProvisionTO();
         provisionTO.setAnyType(AnyTypeKind.GROUP.name());
@@ -586,7 +586,7 @@ public class ResourceITCase extends AbstractITCase {
         String resourceName = RESOURCE_NAME_CREATE_NONE;
         ResourceTO resourceTO = new ResourceTO();
         resourceTO.setKey(resourceName);
-        resourceTO.setConnectorId(102L);
+        resourceTO.setConnector(102L);
 
         ProvisionTO provisionTO = new ProvisionTO();
         provisionTO.setAnyType(AnyTypeKind.USER.name());

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/SyncTaskITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/SyncTaskITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/SyncTaskITCase.java
index 479c96f..1d809ea 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/SyncTaskITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/SyncTaskITCase.java
@@ -126,7 +126,7 @@ public class SyncTaskITCase extends AbstractTaskITCase {
         assertEquals(actual.getKey(), task.getKey());
         assertEquals(actual.getJobClassName(), task.getJobClassName());
         assertEquals(userTemplate, task.getTemplates().get(AnyTypeKind.USER.name()));
-        assertEquals(groupTemplate, task.getTemplates().get(AnyTypeKind.USER.name()));
+        assertEquals(groupTemplate, task.getTemplates().get(AnyTypeKind.GROUP.name()));
     }
 
     @Test
@@ -147,6 +147,7 @@ public class SyncTaskITCase extends AbstractTaskITCase {
         inUserTO.getPlainAttrs().add(attrTO("fullname", "nome cognome"));
         inUserTO.getPlainAttrs().add(attrTO("userId", "puccini@syncope.apache.org"));
         inUserTO.getPlainAttrs().add(attrTO("email", "puccini@syncope.apache.org"));
+        inUserTO.getAuxClasses().add("csv");
         inUserTO.getDerAttrs().add(attrTO("csvuserid", null));
 
         inUserTO = createUser(inUserTO);
@@ -160,7 +161,7 @@ public class SyncTaskITCase extends AbstractTaskITCase {
                     page(1).size(1).build()).getTotalCount();
             assertNotNull(usersPre);
 
-            execSyncTask(SYNC_TASK_ID, 50, false);
+            execProvisioningTask(SYNC_TASK_ID, 50, false);
 
             // after execution of the sync task the user data should have been synced from CSV
             // and processed by user template
@@ -229,13 +230,13 @@ public class SyncTaskITCase extends AbstractTaskITCase {
             assertEquals("active", userTO.getStatus());
 
             // SYNCOPE-317
-            execSyncTask(SYNC_TASK_ID, 50, false);
+            execProvisioningTask(SYNC_TASK_ID, 50, false);
 
             final Set<Long> pushTaskIds = new HashSet<>();
             pushTaskIds.add(25L);
             pushTaskIds.add(26L);
 
-            execSyncTasks(pushTaskIds, 50, false);
+            execProvisioningTasks(pushTaskIds, 50, false);
             // Matching --> UNLINK
             assertFalse(readUser("test9").getResources().contains(RESOURCE_NAME_CSV));
             assertFalse(readUser("test7").getResources().contains(RESOURCE_NAME_CSV));
@@ -246,7 +247,7 @@ public class SyncTaskITCase extends AbstractTaskITCase {
 
     @Test
     public void dryRun() {
-        TaskExecTO execution = execSyncTask(SYNC_TASK_ID, 50, true);
+        TaskExecTO execution = execProvisioningTask(SYNC_TASK_ID, 50, true);
         assertEquals("Execution of task " + execution.getTask() + " failed with message " + execution.getMessage(),
                 "SUCCESS", execution.getStatus());
     }
@@ -254,7 +255,7 @@ public class SyncTaskITCase extends AbstractTaskITCase {
     @Test
     public void reconcileFromDB() {
         // update sync task
-        TaskExecTO execution = execSyncTask(7L, 50, false);
+        TaskExecTO execution = execProvisioningTask(7L, 50, false);
         assertNotNull(execution.getStatus());
         assertTrue(PropagationTaskExecStatus.valueOf(execution.getStatus()).isSuccessful());
 
@@ -268,7 +269,7 @@ public class SyncTaskITCase extends AbstractTaskITCase {
         jdbcTemplate.execute("UPDATE TEST SET STATUS=TRUE");
 
         // re-execute the same SyncTask: now user must be active
-        execution = execSyncTask(7L, 50, false);
+        execution = execProvisioningTask(7L, 50, false);
         assertNotNull(execution.getStatus());
         assertTrue(PropagationTaskExecStatus.valueOf(execution.getStatus()).isSuccessful());
 
@@ -312,8 +313,8 @@ public class SyncTaskITCase extends AbstractTaskITCase {
         // First of all, clear any potential conflict with existing user / group
         ldapCleanup();
 
-        // Update sync task
-        TaskExecTO execution = execSyncTask(11L, 50, false);
+        // 0. synchronize
+        TaskExecTO execution = execProvisioningTask(11L, 50, false);
 
         // 1. verify execution status
         String status = execution.getStatus();
@@ -343,19 +344,12 @@ public class SyncTaskITCase extends AbstractTaskITCase {
         // Check for SYNCOPE-123
         assertNotNull(matchingUsers.getResult().get(0).getPlainAttrMap().get("photo"));
 
-        final GroupTO groupTO = matchingGroups.getResult().iterator().next();
+        GroupTO groupTO = matchingGroups.getResult().iterator().next();
         assertNotNull(groupTO);
         assertEquals("testLDAPGroup", groupTO.getName());
         assertEquals("true", groupTO.getPlainAttrMap().get("show").getValues().get(0));
         assertEquals(matchingUsers.getResult().iterator().next().getKey(), groupTO.getUserOwner(), 0);
         assertNull(groupTO.getGroupOwner());
-
-        // 3. verify that LDAP group membership is propagated as Syncope group membership
-        PagedResult<UserTO> members = userService.search(
-                SyncopeClient.getAnySearchQueryBuilder().realm(SyncopeConstants.ROOT_REALM).
-                fiql(SyncopeClient.getUserSearchConditionBuilder().inGroups(groupTO.getKey()).query()).build());
-        assertNotNull(members);
-        assertEquals(1, members.getResult().size());
     }
 
     @Test
@@ -415,9 +409,9 @@ public class SyncTaskITCase extends AbstractTaskITCase {
             assertNotNull(actual);
             assertEquals(task.getKey(), actual.getKey());
             assertFalse(actual.getTemplates().get(AnyTypeKind.USER.name()).getResources().isEmpty());
-            assertFalse(actual.getTemplates().get(AnyTypeKind.USER.name()).getMemberships().isEmpty());
+            assertFalse(((UserTO) actual.getTemplates().get(AnyTypeKind.USER.name())).getMemberships().isEmpty());
 
-            TaskExecTO execution = execSyncTask(actual.getKey(), 50, false);
+            TaskExecTO execution = execProvisioningTask(actual.getKey(), 50, false);
             final String status = execution.getStatus();
             assertNotNull(status);
             assertTrue(PropagationTaskExecStatus.valueOf(status).isSuccessful());
@@ -436,7 +430,7 @@ public class SyncTaskITCase extends AbstractTaskITCase {
     @Test
     public void issueSYNCOPE230() {
         // 1. read SyncTask for resource-db-sync (table TESTSYNC on external H2)
-        execSyncTask(10L, 50, false);
+        execProvisioningTask(10L, 50, false);
 
         // 3. read e-mail address for user created by the SyncTask first execution
         UserTO userTO = readUser("issuesyncope230");
@@ -449,7 +443,7 @@ public class SyncTaskITCase extends AbstractTaskITCase {
         jdbcTemplate.execute("UPDATE TESTSYNC SET email='updatedSYNCOPE230@syncope.apache.org'");
 
         // 5. re-execute the SyncTask
-        execSyncTask(10L, 50, false);
+        execProvisioningTask(10L, 50, false);
 
         // 6. verify that the e-mail was updated
         userTO = readUser("issuesyncope230");
@@ -511,7 +505,7 @@ public class SyncTaskITCase extends AbstractTaskITCase {
 
         userService.update(userMod.getKey(), userMod);
 
-        execSyncTask(actual.getKey(), 50, false);
+        execProvisioningTask(actual.getKey(), 50, false);
 
         SyncTaskTO executed = taskService.read(actual.getKey());
         assertEquals(1, executed.getExecutions().size());
@@ -535,7 +529,7 @@ public class SyncTaskITCase extends AbstractTaskITCase {
             assertEquals(1, userTO.getPropagationStatusTOs().size());
             assertTrue(userTO.getPropagationStatusTOs().get(0).getStatus().isSuccessful());
 
-            TaskExecTO taskExecTO = execSyncTask(24L, 50, false);
+            TaskExecTO taskExecTO = execProvisioningTask(24L, 50, false);
 
             assertNotNull(taskExecTO.getStatus());
             assertTrue(PropagationTaskExecStatus.valueOf(taskExecTO.getStatus()).isSuccessful());
@@ -551,6 +545,7 @@ public class SyncTaskITCase extends AbstractTaskITCase {
     @Test
     public void issueSYNCOPE307() {
         UserTO userTO = UserITCase.getUniqueSampleTO("s307@apache.org");
+        userTO.getAuxClasses().add("csv");
 
         AttrTO csvuserid = new AttrTO();
         csvuserid.setSchema("csvuserid");
@@ -583,7 +578,7 @@ public class SyncTaskITCase extends AbstractTaskITCase {
         task.getTemplates().put(AnyTypeKind.USER.name(), template);
 
         taskService.update(task.getKey(), task);
-        execSyncTask(task.getKey(), 50, false);
+        execProvisioningTask(task.getKey(), 50, false);
 
         // check for sync policy
         userTO = userService.read(userTO.getKey());
@@ -640,7 +635,7 @@ public class SyncTaskITCase extends AbstractTaskITCase {
         assertEquals(actual.getKey(), syncTask.getKey());
         assertEquals(actual.getJobClassName(), syncTask.getJobClassName());
 
-        TaskExecTO execution = execSyncTask(syncTask.getKey(), 50, false);
+        TaskExecTO execution = execProvisioningTask(syncTask.getKey(), 50, false);
         final String status = execution.getStatus();
         assertNotNull(status);
         assertTrue(PropagationTaskExecStatus.valueOf(status).isSuccessful());
@@ -692,11 +687,11 @@ public class SyncTaskITCase extends AbstractTaskITCase {
 
         // 5. Update the LDAP Connector to retrieve passwords
         ResourceTO ldapResource = resourceService.read(RESOURCE_NAME_LDAP);
-        ConnInstanceTO resourceConnector = connectorService.read(ldapResource.getConnectorId());
+        ConnInstanceTO resourceConnector = connectorService.read(ldapResource.getConnector());
         ConnConfProperty property = resourceConnector.getConfigurationMap().get("retrievePasswordsWithSearch");
         property.getValues().clear();
         property.getValues().add(Boolean.TRUE);
-        connectorService.update(ldapResource.getConnectorId(), resourceConnector);
+        connectorService.update(ldapResource.getConnector(), resourceConnector);
 
         // 6. Sync the user from the resource
         SyncTaskTO syncTask = new SyncTaskTO();
@@ -717,8 +712,8 @@ public class SyncTaskITCase extends AbstractTaskITCase {
         assertEquals(actual.getKey(), syncTask.getKey());
         assertEquals(actual.getJobClassName(), syncTask.getJobClassName());
 
-        TaskExecTO execution = execSyncTask(syncTask.getKey(), 50, false);
-        final String status = execution.getStatus();
+        TaskExecTO execution = execProvisioningTask(syncTask.getKey(), 50, false);
+        String status = execution.getStatus();
         assertNotNull(status);
         assertTrue(PropagationTaskExecStatus.valueOf(status).isSuccessful());
 
@@ -731,7 +726,7 @@ public class SyncTaskITCase extends AbstractTaskITCase {
         taskService.delete(syncTask.getKey());
         property.getValues().clear();
         property.getValues().add(Boolean.FALSE);
-        connectorService.update(ldapResource.getConnectorId(), resourceConnector);
+        connectorService.update(ldapResource.getConnector(), resourceConnector);
         deleteUser(updatedUser.getKey());
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/UserITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/UserITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/UserITCase.java
index 107c953..4574b5b 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/UserITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/UserITCase.java
@@ -95,12 +95,18 @@ import org.springframework.jdbc.core.JdbcTemplate;
 @FixMethodOrder(MethodSorters.JVM)
 public class UserITCase extends AbstractITCase {
 
-    private String getStringAttribute(final ConnObjectTO connObjectTO, final String attrName) {
-        return connObjectTO.getPlainAttrMap().get(attrName).getValues().get(0);
-    }
+    private static final ThreadLocal<SimpleDateFormat> DATE_FORMAT = new ThreadLocal<SimpleDateFormat>() {
+
+        @Override
+        protected SimpleDateFormat initialValue() {
+            SimpleDateFormat sdf = new SimpleDateFormat();
+            sdf.applyPattern("yyyy-MM-dd");
+            return sdf;
+        }
+    };
 
     private boolean getBooleanAttribute(final ConnObjectTO connObjectTO, final String attrName) {
-        return Boolean.parseBoolean(getStringAttribute(connObjectTO, attrName));
+        return Boolean.parseBoolean(connObjectTO.getPlainAttrMap().get(attrName).getValues().get(0));
     }
 
     public static UserTO getUniqueSampleTO(final String email) {
@@ -120,7 +126,7 @@ public class UserITCase extends AbstractITCase {
         userTO.getPlainAttrs().add(attrTO("type", "a type"));
         userTO.getPlainAttrs().add(attrTO("userId", uid));
         userTO.getPlainAttrs().add(attrTO("email", uid));
-        userTO.getPlainAttrs().add(attrTO("loginDate", new SimpleDateFormat("yyyy-MM-dd").format(new Date())));
+        userTO.getPlainAttrs().add(attrTO("loginDate", DATE_FORMAT.get().format(new Date())));
         userTO.getDerAttrs().add(attrTO("cn", null));
         userTO.getVirAttrs().add(attrTO("virtualdata", "virtualvalue"));
         return userTO;
@@ -261,6 +267,7 @@ public class UserITCase extends AbstractITCase {
             assertEquals(ClientExceptionType.RequiredValuesMissing, e.getType());
         }
 
+        userTO.getAuxClasses().add("csv");
         userTO.getDerAttrs().add(attrTO("csvuserid", null));
 
         userTO = createUser(userTO);
@@ -655,7 +662,7 @@ public class UserITCase extends AbstractITCase {
 
         userMod.getDerAttrsToAdd().add("cn");
         userMod.getMembershipsToAdd().add(8L);
-        userMod.getMembershipsToRemove().add(userTO.getMemberships().iterator().next().getKey());
+        userMod.getMembershipsToRemove().add(userTO.getMemberships().get(0).getRightKey());
 
         userTO = updateUser(userMod);
         assertNotNull(userTO);
@@ -1102,6 +1109,7 @@ public class UserITCase extends AbstractITCase {
         userTO.getDerAttrs().clear();
         userTO.getVirAttrs().clear();
 
+        userTO.getAuxClasses().add("csv");
         userTO.getDerAttrs().add(attrTO("csvuserid", null));
 
         MembershipTO membershipTO = new MembershipTO();
@@ -1157,6 +1165,7 @@ public class UserITCase extends AbstractITCase {
         userTO.getMemberships().clear();
         userTO.getDerAttrs().clear();
         userTO.getVirAttrs().clear();
+        userTO.getAuxClasses().add("csv");
         userTO.getDerAttrs().add(attrTO("csvuserid", null));
 
         MembershipTO memb12 = new MembershipTO();
@@ -1186,7 +1195,7 @@ public class UserITCase extends AbstractITCase {
         UserMod userMod = new UserMod();
         userMod.setKey(actual.getKey());
 
-        userMod.getMembershipsToRemove().add(actual.getMemberships().get(0).getKey());
+        userMod.getMembershipsToRemove().add(actual.getMemberships().get(0).getRightKey());
 
         actual = updateUser(userMod);
         assertNotNull(actual);
@@ -1219,7 +1228,7 @@ public class UserITCase extends AbstractITCase {
         userMod = new UserMod();
         userMod.setKey(actual.getKey());
 
-        userMod.getMembershipsToRemove().add(actual.getMemberships().get(0).getKey());
+        userMod.getMembershipsToRemove().add(actual.getMemberships().get(0).getRightKey());
 
         actual = updateUser(userMod);
         assertNotNull(actual);
@@ -1490,6 +1499,7 @@ public class UserITCase extends AbstractITCase {
     @Test
     public void mappingPurpose() {
         UserTO userTO = getUniqueSampleTO("mpurpose@apache.org");
+        userTO.getAuxClasses().add("csv");
 
         AttrTO csvuserid = new AttrTO();
         csvuserid.setSchema("csvuserid");
@@ -1526,7 +1536,7 @@ public class UserITCase extends AbstractITCase {
 
     @Test
     public void bulkActions() {
-        final BulkAction bulkAction = new BulkAction();
+        BulkAction bulkAction = new BulkAction();
 
         for (int i = 0; i < 10; i++) {
             UserTO userTO = getUniqueSampleTO("bulk_" + i + "@apache.org");
@@ -1598,7 +1608,7 @@ public class UserITCase extends AbstractITCase {
         // 4. remove membership
         UserMod userMod = new UserMod();
         userMod.setKey(userTO.getKey());
-        userMod.getMembershipsToRemove().add(userTO.getMemberships().iterator().next().getKey());
+        userMod.getMembershipsToRemove().add(userTO.getMemberships().get(0).getRightKey());
 
         userTO = updateUser(userMod);
         assertTrue(userTO.getResources().contains(RESOURCE_NAME_LDAP));
@@ -1746,6 +1756,7 @@ public class UserITCase extends AbstractITCase {
         userTO.getMemberships().clear();
         userTO.getDerAttrs().clear();
         userTO.getVirAttrs().clear();
+        userTO.getAuxClasses().add("csv");
         userTO.getDerAttrs().add(attrTO("csvuserid", null));
         userTO.getResources().add(RESOURCE_NAME_CSV);
 
@@ -1772,6 +1783,7 @@ public class UserITCase extends AbstractITCase {
         userTO.getMemberships().clear();
         userTO.getDerAttrs().clear();
         userTO.getVirAttrs().clear();
+        userTO.getAuxClasses().add("csv");
         userTO.getDerAttrs().add(attrTO("csvuserid", null));
 
         UserTO actual = createUser(userTO);
@@ -1810,6 +1822,7 @@ public class UserITCase extends AbstractITCase {
         userTO.getMemberships().clear();
         userTO.getDerAttrs().clear();
         userTO.getVirAttrs().clear();
+        userTO.getAuxClasses().add("csv");
         userTO.getDerAttrs().add(attrTO("csvuserid", null));
         userTO.getResources().add(RESOURCE_NAME_CSV);
 
@@ -1841,6 +1854,7 @@ public class UserITCase extends AbstractITCase {
         userTO.getMemberships().clear();
         userTO.getDerAttrs().clear();
         userTO.getVirAttrs().clear();
+        userTO.getAuxClasses().add("csv");
         userTO.getDerAttrs().add(attrTO("csvuserid", null));
 
         UserTO actual = createUser(userTO);
@@ -1875,6 +1889,7 @@ public class UserITCase extends AbstractITCase {
         userTO.getMemberships().clear();
         userTO.getDerAttrs().clear();
         userTO.getVirAttrs().clear();
+        userTO.getAuxClasses().add("csv");
         userTO.getDerAttrs().add(attrTO("csvuserid", null));
         userTO.getResources().add(RESOURCE_NAME_CSV);
 
@@ -1906,6 +1921,7 @@ public class UserITCase extends AbstractITCase {
         userTO.getMemberships().clear();
         userTO.getDerAttrs().clear();
         userTO.getVirAttrs().clear();
+        userTO.getAuxClasses().add("csv");
         userTO.getDerAttrs().add(attrTO("csvuserid", null));
 
         UserTO actual = createUser(userTO);
@@ -1941,6 +1957,7 @@ public class UserITCase extends AbstractITCase {
         userTO.getMemberships().clear();
         userTO.getDerAttrs().clear();
         userTO.getVirAttrs().clear();
+        userTO.getAuxClasses().add("csv");
         userTO.getDerAttrs().add(attrTO("csvuserid", null));
 
         UserTO actual = createUser(userTO);
@@ -2280,6 +2297,7 @@ public class UserITCase extends AbstractITCase {
         userTO.getPlainAttrs().add(attrTO("email", "syncope391@syncope.apache.org"));
         userTO.getDerAttrs().add(attrTO("csvuserid", null));
 
+        userTO.getAuxClasses().add("csv");
         userTO.getResources().add(RESOURCE_NAME_CSV);
         userTO = createUser(userTO, false);
         assertNotNull(userTO);
@@ -2299,6 +2317,7 @@ public class UserITCase extends AbstractITCase {
         userTO.setPassword("passwordTESTNULL1");
         userTO.getDerAttrs().clear();
         userTO.getVirAttrs().clear();
+        userTO.getAuxClasses().add("csv");
         userTO.getDerAttrs().add(attrTO("csvuserid", null));
 
         userTO.getResources().add(RESOURCE_NAME_CSV);
@@ -2319,6 +2338,7 @@ public class UserITCase extends AbstractITCase {
         userTO.setPassword("passwordTESTNULL1");
         userTO.getDerAttrs().clear();
         userTO.getVirAttrs().clear();
+        userTO.getAuxClasses().add("csv");
         userTO.getDerAttrs().add(attrTO("csvuserid", null));
 
         userTO.getResources().add(RESOURCE_NAME_CSV);
@@ -2347,6 +2367,7 @@ public class UserITCase extends AbstractITCase {
             userTO.setPassword(null);
             userTO.getDerAttrs().clear();
             userTO.getVirAttrs().clear();
+            userTO.getAuxClasses().add("csv");
             userTO.getDerAttrs().add(attrTO("csvuserid", null));
 
             userTO.getResources().add(RESOURCE_NAME_CSV);
@@ -2369,11 +2390,11 @@ public class UserITCase extends AbstractITCase {
         userTO.getMemberships().clear();
         userTO.getDerAttrs().clear();
         userTO.getVirAttrs().clear();
+        userTO.getAuxClasses().add("csv");
         userTO.getDerAttrs().add(attrTO("csvuserid", null));
 
-        MembershipTO membershipTO = new MembershipTO();
-        membershipTO.setRightKey(12L);
-        userTO.getMemberships().add(membershipTO);
+        userTO.getAuxClasses().add("generic membership");
+        userTO.getPlainAttrs().add(attrTO("postalAddress", "postalAddress"));
 
         userTO.getResources().add(RESOURCE_NAME_LDAP);
 
@@ -2388,9 +2409,7 @@ public class UserITCase extends AbstractITCase {
 
         UserMod userMod = new UserMod();
         userMod.setKey(actual.getKey());
-
-        userMod.getMembershipsToAdd().add(12L);
-        userMod.getMembershipsToRemove().add(actual.getMemberships().iterator().next().getKey());
+        userMod.getPlainAttrsToUpdate().add(attrMod("postalAddress", "newPostalAddress"));
 
         actual = updateUser(userMod);
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/UserWorkflowITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/UserWorkflowITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/UserWorkflowITCase.java
index 457f66d..3bbb7e1 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/UserWorkflowITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/UserWorkflowITCase.java
@@ -74,10 +74,19 @@ public class UserWorkflowITCase extends AbstractITCase {
         assertNotNull(form.getTaskId());
         assertNull(form.getOwner());
 
-        // 3. claim task from rossini, not in group 7 (designated for approval in workflow definition): fail
-        UserWorkflowService userService2 = clientFactory.create(
-                "rossini", ADMIN_PWD).getService(UserWorkflowService.class);
+        // 3. claim task as rossini, with role 2 granting entitlement to claim forms but not in group 7,
+        // designated for approval in workflow definition: fail
+        UserTO rossini = userService.read(1L);
+        if (!rossini.getRoles().contains(2L)) {
+            UserMod userMod = new UserMod();
+            userMod.setKey(1L);
+            userMod.getRolesToAdd().add(2L);
+            rossini = updateUser(userMod);
+        }
+        assertTrue(rossini.getRoles().contains(2L));
 
+        UserWorkflowService userService2 = clientFactory.create("rossini", ADMIN_PWD).
+                getService(UserWorkflowService.class);
         try {
             userService2.claimForm(form.getTaskId());
             fail();
@@ -85,10 +94,9 @@ public class UserWorkflowITCase extends AbstractITCase {
             assertEquals(ClientExceptionType.Workflow, e.getType());
         }
 
-        // 4. claim task from bellini, in role 2
-        UserWorkflowService userService3 = clientFactory.create(
-                "bellini", ADMIN_PWD).getService(UserWorkflowService.class);
-
+        // 4. claim task from bellini, with role 2 and in group 7
+        UserWorkflowService userService3 = clientFactory.create("bellini", ADMIN_PWD).
+                getService(UserWorkflowService.class);
         form = userService3.claimForm(form.getTaskId());
         assertNotNull(form);
         assertNotNull(form.getTaskId());
@@ -237,9 +245,8 @@ public class UserWorkflowITCase extends AbstractITCase {
         assertNotNull(form);
 
         // 3. first claim ny bellini ....
-        UserWorkflowService userService3 = clientFactory.create(
-                "bellini", ADMIN_PWD).getService(UserWorkflowService.class);
-
+        UserWorkflowService userService3 = clientFactory.create("bellini", ADMIN_PWD).
+                getService(UserWorkflowService.class);
         form = userService3.claimForm(form.getTaskId());
         assertNotNull(form);
         assertNotNull(form.getTaskId());
@@ -250,7 +257,7 @@ public class UserWorkflowITCase extends AbstractITCase {
         assertNotNull(form);
 
         // 5. approve user
-        final Map<String, WorkflowFormPropertyTO> props = form.getPropertyMap();
+        Map<String, WorkflowFormPropertyTO> props = form.getPropertyMap();
         props.get("approve").setValue(Boolean.TRUE.toString());
         form.getProperties().clear();
         form.getProperties().addAll(props.values());

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/VirAttrITCase.java
----------------------------------------------------------------------
diff --git a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/VirAttrITCase.java b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/VirAttrITCase.java
index a373df5..2c2065f 100644
--- a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/VirAttrITCase.java
+++ b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/reference/VirAttrITCase.java
@@ -228,7 +228,7 @@ public class VirAttrITCase extends AbstractITCase {
         assertEquals("virattrcache", actual.getVirAttrMap().get("virtualdata").getValues().get(0));
 
         // 3. update virtual attribute directly
-        final JdbcTemplate jdbcTemplate = new JdbcTemplate(testDataSource);
+        JdbcTemplate jdbcTemplate = new JdbcTemplate(testDataSource);
 
         String value = jdbcTemplate.queryForObject(
                 "SELECT USERNAME FROM testsync WHERE ID=?", String.class, actual.getKey());
@@ -296,6 +296,7 @@ public class VirAttrITCase extends AbstractITCase {
 
             // create a new user
             UserTO userTO = UserITCase.getUniqueSampleTO("syncope397@syncope.apache.org");
+            userTO.getAuxClasses().add("csv");
             userTO.getResources().clear();
             userTO.getMemberships().clear();
             userTO.getDerAttrs().clear();
@@ -450,7 +451,7 @@ public class VirAttrITCase extends AbstractITCase {
         ResourceTO resourceTO = new ResourceTO();
 
         resourceTO.setKey(resourceName);
-        resourceTO.setConnectorId(107L);
+        resourceTO.setConnector(107L);
 
         ProvisionTO provisionTO = new ProvisionTO();
         provisionTO.setAnyType(AnyTypeKind.USER.name());
@@ -463,7 +464,7 @@ public class VirAttrITCase extends AbstractITCase {
         MappingItemTO item = new MappingItemTO();
         item.setIntAttrName("aLong");
         item.setIntMappingType(IntMappingType.UserPlainSchema);
-        item.setExtAttrName(groupName);
+        item.setExtAttrName("ID");
         item.setPurpose(MappingPurpose.PROPAGATION);
         item.setConnObjectKey(true);
         mapping.setConnObjectKeyItem(item);


[02/21] syncope git commit: [SYNCOPE-660] Merge from 1_2_X; This closes #6

Posted by il...@apache.org.
http://git-wip-us.apache.org/repos/asf/syncope/blob/34a0422a/client/old_console/src/main/java/org/apache/syncope/client/console/rest/TaskRestClient.java
----------------------------------------------------------------------
diff --cc client/old_console/src/main/java/org/apache/syncope/client/console/rest/TaskRestClient.java
index 541b5cd,0000000..c83ce88
mode 100644,000000..100644
--- a/client/old_console/src/main/java/org/apache/syncope/client/console/rest/TaskRestClient.java
+++ b/client/old_console/src/main/java/org/apache/syncope/client/console/rest/TaskRestClient.java
@@@ -1,139 -1,0 +1,191 @@@
 +/*
 + * 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.rest;
++package org.apache.syncope.console.rest;
 +
++import java.util.ArrayList;
 +import java.util.List;
- import org.apache.syncope.client.console.SyncopeSession;
- import org.apache.syncope.common.lib.to.AbstractTaskTO;
- import org.apache.syncope.common.lib.to.BulkAction;
- import org.apache.syncope.common.lib.to.BulkActionResult;
- import org.apache.syncope.common.lib.to.NotificationTaskTO;
- import org.apache.syncope.common.lib.to.PropagationTaskTO;
- import org.apache.syncope.common.lib.to.PushTaskTO;
- import org.apache.syncope.common.lib.to.SchedTaskTO;
- import org.apache.syncope.common.lib.to.SyncTaskTO;
- import org.apache.syncope.common.lib.types.TaskType;
- import org.apache.syncope.common.rest.api.service.TaskService;
++import org.apache.syncope.common.services.TaskService;
++import org.apache.syncope.common.reqres.BulkAction;
++import org.apache.syncope.common.reqres.BulkActionResult;
++import org.apache.syncope.common.wrap.JobClass;
++import org.apache.syncope.common.to.NotificationTaskTO;
++import org.apache.syncope.common.to.PropagationTaskTO;
++import org.apache.syncope.common.to.SchedTaskTO;
++import org.apache.syncope.common.wrap.SyncActionClass;
++import org.apache.syncope.common.to.SyncTaskTO;
++import org.apache.syncope.common.to.AbstractTaskTO;
++import org.apache.syncope.common.types.TaskType;
++import org.apache.syncope.common.util.CollectionWrapper;
++import org.apache.syncope.common.SyncopeClientException;
++import org.apache.syncope.common.to.PushTaskTO;
++import org.apache.syncope.common.to.TaskExecTO;
++import org.apache.syncope.common.types.JobAction;
++import org.apache.syncope.common.types.JobStatusType;
++import org.apache.syncope.common.wrap.PushActionClass;
 +import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;
 +import org.springframework.stereotype.Component;
 +
 +/**
 + * Console client for invoking Rest Tasks services.
 + */
 +@Component
- public class TaskRestClient extends BaseRestClient implements ExecutionRestClient {
++public class TaskRestClient extends JobRestClient implements ExecutionRestClient {
 +
 +    private static final long serialVersionUID = 6284485820911028843L;
 +
++    /**
++     * Return a list of job classes.
++     *
++     * @return list of classes.
++     */
 +    public List<String> getJobClasses() {
-         return SyncopeSession.get().getSyncopeTO().getTaskJobs();
++        List<JobClass> jobClasses = null;
++
++        try {
++            jobClasses = new ArrayList<JobClass>(getService(TaskService.class).getJobClasses());
++        } catch (SyncopeClientException e) {
++            LOG.error("While getting all job classes", e);
++        }
++        return CollectionWrapper.unwrap(jobClasses);
 +    }
 +
 +    public List<String> getSyncActionsClasses() {
-         return SyncopeSession.get().getSyncopeTO().getSyncActions();
++        List<SyncActionClass> actions = null;
++
++        try {
++            actions = new ArrayList<SyncActionClass>(getService(TaskService.class).getSyncActionsClasses());
++        } catch (SyncopeClientException e) {
++            LOG.error("While getting all sync actions classes", e);
++        }
++        return CollectionWrapper.unwrap(actions);
 +    }
 +
 +    public List<String> getPushActionsClasses() {
-         return SyncopeSession.get().getSyncopeTO().getPushActions();
++        List<PushActionClass> actions = null;
++
++        try {
++            actions = new ArrayList<PushActionClass>(getService(TaskService.class).getPushActionsClasses());
++        } catch (SyncopeClientException e) {
++            LOG.error("While getting all sync actions classes", e);
++        }
++        return CollectionWrapper.unwrap(actions);
 +    }
 +
 +    /**
 +     * Return the number of tasks.
 +     *
 +     * @param kind of task (propagation, sched, sync).
 +     * @return number of stored tasks.
 +     */
 +    public int count(final String kind) {
 +        return getService(TaskService.class).list(TaskType.fromString(kind), 1, 1).getTotalCount();
 +    }
 +
 +    @SuppressWarnings("unchecked")
 +    public <T extends AbstractTaskTO> List<T> list(final Class<T> reference,
 +            final int page, final int size, final SortParam<String> sort) {
 +
 +        return (List<T>) getService(TaskService.class).list(getTaskType(reference), page, size, toOrderBy(sort)).
 +                getResult();
 +    }
 +
 +    private TaskType getTaskType(final Class<?> reference) {
 +        TaskType result = null;
 +        if (PropagationTaskTO.class.equals(reference)) {
 +            result = TaskType.PROPAGATION;
 +        } else if (NotificationTaskTO.class.equals(reference)) {
 +            result = TaskType.NOTIFICATION;
 +        } else if (SchedTaskTO.class.equals(reference)) {
 +            result = TaskType.SCHEDULED;
 +        } else if (SyncTaskTO.class.equals(reference)) {
 +            result = TaskType.SYNCHRONIZATION;
 +        } else if (PushTaskTO.class.equals(reference)) {
 +            result = TaskType.PUSH;
 +        }
 +        return result;
 +    }
 +
 +    public PropagationTaskTO readPropagationTask(final Long taskId) {
 +        return getService(TaskService.class).read(taskId);
 +    }
 +
 +    public NotificationTaskTO readNotificationTask(final Long taskId) {
 +        return getService(TaskService.class).read(taskId);
 +    }
 +
 +    public <T extends SchedTaskTO> T readSchedTask(final Class<T> reference, final Long taskId) {
 +        return getService(TaskService.class).read(taskId);
 +    }
 +
 +    public void delete(final Long taskId, final Class<? extends AbstractTaskTO> taskToClass) {
 +        getService(TaskService.class).delete(taskId);
 +    }
 +
 +    @Override
 +    public void startExecution(final long taskId) {
 +        startExecution(taskId, false);
 +    }
 +
 +    public void startExecution(final long taskId, final boolean dryRun) {
 +        getService(TaskService.class).execute(taskId, dryRun);
 +    }
 +
 +    @Override
 +    public void deleteExecution(final long taskExecId) {
 +        getService(TaskService.class).deleteExecution(taskExecId);
 +    }
 +
 +    public void createSyncTask(final SyncTaskTO taskTO) {
 +        getService(TaskService.class).create(taskTO);
 +    }
 +
 +    public void createSchedTask(final SchedTaskTO taskTO) {
 +        getService(TaskService.class).create(taskTO);
 +    }
 +
 +    public void updateSchedTask(final SchedTaskTO taskTO) {
-         getService(TaskService.class).update(taskTO.getKey(), taskTO);
++        getService(TaskService.class).update(taskTO.getId(), taskTO);
 +    }
 +
 +    public void updateSyncTask(final SyncTaskTO taskTO) {
-         getService(TaskService.class).update(taskTO.getKey(), taskTO);
++        getService(TaskService.class).update(taskTO.getId(), taskTO);
 +    }
 +
 +    public BulkActionResult bulkAction(final BulkAction action) {
 +        return getService(TaskService.class).bulk(action);
 +    }
++    
++    @Override
++    public boolean isJobRunning(final long taskId){
++        for(TaskExecTO taskExecTO : getService(TaskService.class).listJobs(JobStatusType.RUNNING)){
++            if(taskExecTO.getTask()== taskId) return true;
++        }
++        return false;
++    }
++    
++    @Override
++    public void startJob(final long taskId){
++        getService(TaskService.class).actionJob(taskId, JobAction.START);
++    }
++
++    @Override
++    public void stopJob(final long taskId) {
++        getService(TaskService.class).actionJob(taskId, JobAction.STOP);
++    }
 +}

http://git-wip-us.apache.org/repos/asf/syncope/blob/34a0422a/client/old_console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/JobColumn.java
----------------------------------------------------------------------
diff --cc client/old_console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/JobColumn.java
index 0000000,0000000..ba47421
new file mode 100644
--- /dev/null
+++ b/client/old_console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/JobColumn.java
@@@ -1,0 -1,0 +1,94 @@@
++/*
++ * 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.wicket.extensions.markup.html.repeater.data.table;
++
++import org.apache.syncope.client.console.panels.RuntimePanel;
++import org.apache.syncope.client.console.rest.JobRestClient;
++import org.apache.syncope.common.to.AbstractTaskTO;
++import org.apache.syncope.common.to.ReportTO;
++import org.apache.wicket.PageReference;
++import org.apache.wicket.ajax.AbstractAjaxTimerBehavior;
++import org.apache.wicket.ajax.AjaxRequestTarget;
++import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
++import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
++import org.apache.wicket.extensions.markup.html.repeater.data.table.AbstractColumn;
++import org.apache.wicket.markup.repeater.Item;
++import org.apache.wicket.model.IModel;
++import org.apache.wicket.util.time.Duration;
++import org.slf4j.Logger;
++import org.slf4j.LoggerFactory;
++
++public class JobColumn<T, S> extends AbstractColumn<T, S> {
++
++    private static final long serialVersionUID = 7955560320949560725L;
++
++    protected static final Logger LOG = LoggerFactory.getLogger(JobColumn.class);
++
++    private final PageReference pageRef;
++
++    private RuntimePanel panel;
++
++    private final JobRestClient jobRestClient;
++
++    public JobColumn(final IModel<String> displayModel, final S sortProperty, final PageReference pageRef,
++            final JobRestClient jobRestClient) {
++        super(displayModel, sortProperty);
++        this.pageRef = pageRef;
++        this.jobRestClient = jobRestClient;
++    }
++
++    @Override
++    public void populateItem(final Item<ICellPopulator<T>> item, final String componentId, final IModel<T> model) {
++        Long jobId = null;
++        if (model.getObject() instanceof AbstractTaskTO) {
++            jobId = ((AbstractTaskTO) model.getObject()).getId();
++        } else if (model.getObject() instanceof ReportTO) {
++            jobId = ((ReportTO) model.getObject()).getId();
++        }
++        if (jobId != null) {
++            panel = new RuntimePanel(componentId, model, pageRef, jobId, jobRestClient);
++            startPolling(10);
++            item.add(panel);
++        }
++    }
++
++    public void startPolling(final int seconds) {
++        AbstractAjaxTimerBehavior timer = new AbstractAjaxTimerBehavior(Duration.seconds(seconds)) {
++
++            private static final long serialVersionUID = 1L;
++
++            @Override
++            protected void onTimer(AjaxRequestTarget target) {
++                panel.refresh();
++                target.add(panel);
++            }
++
++            @Override
++            protected void updateAjaxAttributes(AjaxRequestAttributes attributes) {
++                super.updateAjaxAttributes(attributes);
++                attributes.getExtraParameters().put("pollingTimeout", "true");
++            }
++
++        };
++
++        panel.setTimer(timer);
++
++    }
++
++}

http://git-wip-us.apache.org/repos/asf/syncope/blob/34a0422a/client/old_console/src/main/resources/org/apache/syncope/client/console/pages/Reports.html
----------------------------------------------------------------------
diff --cc client/old_console/src/main/resources/org/apache/syncope/client/console/pages/Reports.html
index 456f7a3,0000000..ff5fb37
mode 100644,000000..100644
--- a/client/old_console/src/main/resources/org/apache/syncope/client/console/pages/Reports.html
+++ b/client/old_console/src/main/resources/org/apache/syncope/client/console/pages/Reports.html
@@@ -1,58 -1,0 +1,71 @@@
 +<!--
 +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.
 +-->
 +<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
 +  <wicket:extend>
++    <script type="text/javascript">
++      window.onload = setupFunc;
 +
++      function setupFunc() {
++        Wicket.Event.subscribe('/ajax/call/beforeSend', function (attributes, jqXHR, settings) {
++          if (!jqXHR.ep || !jqXHR.ep[0] || !jqXHR.ep[0]["value"]) {
++            document.getElementById("veil").style.display = "block";
++          }
++        });
++        Wicket.Event.subscribe('/ajax/call/complete', function (attributes, jqXHR, textStatus) {
++          document.getElementById("veil").style.display = "none";
++        });
++      }
++    </script>
 +    <div id="tabs">
 +      <ul>
 +        <li class="tabs-selected"><a href="#tabs-1"><span><wicket:message key="reports"/></span></a></li>
 +        <li><a href="#tabs-2"><span><wicket:message key="audit"/></span></a></li>
 +      </ul>
 +
 +      <div id="tabs-1">
 +        <div id="users-contain" class="ui-widget" style="width:inherit;">
 +          <span wicket:id="reportContainer">
 +            <table class="ui-widget ui-widget-content table-hover" wicket:id="reportTable"/>
 +          </span>
 +          <span style="float:right">
 +            <form wicket:id="paginatorForm" style="display:inline">
 +              <label><wicket:message key="displayRows"/></label>
 +              <select class="text ui-widget-content ui-corner-all" wicket:id="rowsChooser"/>
 +            </form>
 +          </span>
 +        </div>
 +
 +        <div wicket:id="reportWin">[Show modal window for report editing]</div>
 +        <a class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only" wicket:id="createLink">
 +          <wicket:message key="create"/>
 +        </a>
 +
 +      </div>
 +
 +      <div id="tabs-2">
 +        <span wicket:id="auditContainer">
 +          <form wicket:id="auditForm">
 +            <span wicket:id="events">[event builder]</span>
 +          </form>
 +        </span>
 +      </div>
 +    </div>
 +
 +  </wicket:extend>
 +</html>

http://git-wip-us.apache.org/repos/asf/syncope/blob/34a0422a/client/old_console/src/main/resources/org/apache/syncope/client/console/pages/Tasks.html
----------------------------------------------------------------------
diff --cc client/old_console/src/main/resources/org/apache/syncope/client/console/pages/Tasks.html
index 7df418a,0000000..81c9237
mode 100644,000000..100644
--- a/client/old_console/src/main/resources/org/apache/syncope/client/console/pages/Tasks.html
+++ b/client/old_console/src/main/resources/org/apache/syncope/client/console/pages/Tasks.html
@@@ -1,46 -1,0 +1,61 @@@
 +<!--
 +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.
 +-->
 +<wicket:extend>
 +
++  <script type="text/javascript">
++    window.onload = setupFunc;
++
++    function setupFunc() {
++      Wicket.Event.subscribe('/ajax/call/beforeSend', function (attributes, jqXHR, settings) {
++        if (!jqXHR.ep || !jqXHR.ep[0] || !jqXHR.ep[0]["value"]){
++          document.getElementById("veil").style.display = "block";
++        }
++      });
++      Wicket.Event.subscribe('/ajax/call/complete', function (attributes, jqXHR, textStatus) {
++        document.getElementById("veil").style.display = "none";
++      });
++    }
++  </script>
++
 +  <div id="tabs">
 +    <ul>
 +      <li class="tabs-selected"><a href="#tabs-1"><span><wicket:message key="tab1"/></span></a></li>
 +      <li><a href="#tabs-2"><span><wicket:message key="tab2"/></span></a></li>
 +      <li><a href="#tabs-3"><span><wicket:message key="tab3"/></span></a></li>
 +      <li><a href="#tabs-4"><span><wicket:message key="tab4"/></span></a></li>
 +      <li><a href="#tabs-5"><span><wicket:message key="tab5"/></span></a></li>
 +    </ul>
 +    <div id="tabs-1">
 +      <span wicket:id="propagation">[propagation tasks]</span>
 +    </div>
 +    <div id="tabs-2">
 +      <span wicket:id="notification">[notification tasks]</span>
 +    </div>
 +    <div id="tabs-3">
 +      <span wicket:id="sched">[scheduled tasks]</span>
 +    </div>
 +    <div id="tabs-4">
 +      <span wicket:id="sync">[synchronization tasks]</span>
 +    </div>
 +    <div id="tabs-5">
 +      <span wicket:id="push">[push tasks]</span>
 +    </div>
 +  </div>
 +
 +</wicket:extend>

http://git-wip-us.apache.org/repos/asf/syncope/blob/34a0422a/client/old_console/src/main/resources/org/apache/syncope/client/console/panels/RuntimePanel.html
----------------------------------------------------------------------
diff --cc client/old_console/src/main/resources/org/apache/syncope/client/console/panels/RuntimePanel.html
index 0000000,0000000..828192c
new file mode 100644
--- /dev/null
+++ b/client/old_console/src/main/resources/org/apache/syncope/client/console/panels/RuntimePanel.html
@@@ -1,0 -1,0 +1,49 @@@
++<!--
++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.
++-->
++<html xmlns="http://www.w3.org/1999/xhtml" xmlns:wicket="http://wicket.apache.org">
++  <wicket:head>
++    <style>
++      #runtime{
++        text-align: center;
++      }
++    </style>
++  </wicket:head>
++  <wicket:panel wicket:id="runtime">
++    <div>
++      <div id="runtime">
++        <div id="runtimePanel">
++          <span wicket:id="panelStop"></span>
++          <span wicket:id="panelSpinner"></span>
++
++          <wicket:fragment wicket:id="fragmentStop">
++            <a href="#" wicket:id="stopLink"><img src="img/actions/suspend.png" alt="stop icon" title="Stop Now"/></a>
++          </wicket:fragment>
++
++          <wicket:fragment wicket:id="fragmentSpinner">
++            <img src="img/loading.gif" alt="spinner icon" title="Spinner"/>
++          </wicket:fragment>
++
++          <wicket:fragment wicket:id="emptyFragment"></wicket:fragment>
++
++        </div>
++
++      </div>
++    </div>
++  </wicket:panel>
++</html>

http://git-wip-us.apache.org/repos/asf/syncope/blob/34a0422a/core/logic/src/main/java/org/apache/syncope/core/logic/AbstractJobLogic.java
----------------------------------------------------------------------
diff --cc core/logic/src/main/java/org/apache/syncope/core/logic/AbstractJobLogic.java
index e423174,0000000..fb5648f
mode 100644,000000..100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/AbstractJobLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/AbstractJobLogic.java
@@@ -1,174 -1,0 +1,187 @@@
 +/*
 + * Licensed to the Apache Software Foundation (ASF) under one
 + * or more contributor license agreements.  See the NOTICE file
 + * distributed with this work for additional information
 + * regarding copyright ownership.  The ASF licenses this file
 + * to you under the Apache License, Version 2.0 (the
 + * "License"); you may not use this file except in compliance
 + * with the License.  You may obtain a copy of the License at
 + *
 + *   http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing,
 + * software distributed under the License is distributed on an
 + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 + * KIND, either express or implied.  See the License for the
 + * specific language governing permissions and limitations
 + * under the License.
 + */
 +package org.apache.syncope.core.logic;
 +
 +import java.util.ArrayList;
 +import java.util.List;
 +import org.apache.syncope.common.lib.AbstractBaseBean;
 +import org.apache.syncope.common.lib.to.AbstractExecTO;
 +import org.apache.syncope.common.lib.to.ReportExecTO;
 +import org.apache.syncope.common.lib.to.TaskExecTO;
 +import org.apache.syncope.common.lib.types.JobAction;
 +import org.apache.syncope.common.lib.types.JobStatusType;
 +import org.quartz.JobExecutionContext;
 +import org.quartz.JobKey;
 +import org.quartz.Scheduler;
 +import org.quartz.SchedulerException;
 +import org.quartz.Trigger;
 +import org.quartz.impl.matchers.GroupMatcher;
 +import org.springframework.beans.factory.annotation.Autowired;
 +import org.springframework.scheduling.quartz.SchedulerFactoryBean;
 +
 +abstract class AbstractJobLogic<T extends AbstractBaseBean> extends AbstractTransactionalLogic<T> {
 +
 +    @Autowired
 +    protected SchedulerFactoryBean scheduler;
 +
 +    protected abstract Long getKeyFromJobName(final JobKey jobKey);
 +
 +    private <E extends AbstractExecTO> void setTaskOrReportKey(final E jobExecTO, final Long taskOrReportKey) {
 +        if (jobExecTO instanceof TaskExecTO) {
 +            ((TaskExecTO) jobExecTO).setTask(taskOrReportKey);
 +        } else if (jobExecTO instanceof ReportExecTO) {
 +            ((ReportExecTO) jobExecTO).setReport(taskOrReportKey);
 +        }
 +    }
 +
 +    public <E extends AbstractExecTO> List<E> listJobs(final JobStatusType type, final Class<E> reference) {
 +        List<E> jobExecTOs = new ArrayList<>();
 +
 +        switch (type) {
 +            case ALL:
 +                try {
 +                    for (String groupName : scheduler.getScheduler().getJobGroupNames()) {
 +                        for (JobKey jobKey
 +                                : scheduler.getScheduler().getJobKeys(GroupMatcher.jobGroupEquals(groupName))) {
 +
 +                            Long key = getKeyFromJobName(jobKey);
 +                            if (key != null) {
 +                                List<? extends Trigger> jobTriggers = scheduler.getScheduler().getTriggersOfJob(jobKey);
 +                                if (jobTriggers.isEmpty()) {
 +                                    E jobExecTO = reference.newInstance();
 +                                    setTaskOrReportKey(jobExecTO, key);
 +                                    jobExecTO.setStatus("Not Scheduled");
 +
 +                                    jobExecTOs.add(jobExecTO);
 +                                } else {
 +                                    for (Trigger t : jobTriggers) {
 +                                        E jobExecTO = reference.newInstance();
 +                                        jobExecTO.setKey(key);
 +                                        jobExecTO.
 +                                                setStatus(scheduler.getScheduler().getTriggerState(t.getKey()).name());
 +                                        jobExecTO.setStartDate(t.getStartTime());
 +
 +                                        jobExecTOs.add(jobExecTO);
 +                                    }
 +                                }
 +                            }
 +                        }
 +                    }
 +                } catch (SchedulerException e) {
 +                    LOG.debug("Problems while retrieving all scheduled jobs", e);
 +                } catch (InstantiationException e) {
 +                    LOG.debug("Problems while instantiating {}", reference, e);
 +                } catch (IllegalAccessException e) {
 +                    LOG.debug("Problems while accessing {}", reference, e);
 +                }
 +                break;
 +
 +            case RUNNING:
 +                try {
 +                    for (JobExecutionContext jec : scheduler.getScheduler().getCurrentlyExecutingJobs()) {
 +                        Long key = getKeyFromJobName(jec.getJobDetail().getKey());
 +                        if (key != null) {
 +                            E jobExecTO = reference.newInstance();
 +                            setTaskOrReportKey(jobExecTO, key);
 +                            jobExecTO.setStatus(
 +                                    scheduler.getScheduler().getTriggerState(jec.getTrigger().getKey()).name());
 +                            jobExecTO.setStartDate(jec.getFireTime());
 +
 +                            jobExecTOs.add(jobExecTO);
 +                        }
 +                    }
 +                } catch (SchedulerException e) {
 +                    LOG.debug("Problems while retrieving all currently executing jobs", e);
 +                } catch (InstantiationException e) {
 +                    LOG.debug("Problems while instantiating {}", reference, e);
 +                } catch (IllegalAccessException e) {
 +                    LOG.debug("Problems while accessing {}", reference, e);
 +                }
 +                break;
 +
 +            case SCHEDULED:
 +                try {
 +                    for (String groupName : scheduler.getScheduler().getJobGroupNames()) {
 +                        for (JobKey jobKey
 +                                : scheduler.getScheduler().getJobKeys(GroupMatcher.jobGroupEquals(groupName))) {
 +
 +                            Long key = getKeyFromJobName(jobKey);
 +                            if (key != null) {
 +                                List<? extends Trigger> jobTriggers = scheduler.getScheduler().getTriggersOfJob(jobKey);
 +                                for (Trigger t : jobTriggers) {
 +                                    E jobExecTO = reference.newInstance();
 +                                    setTaskOrReportKey(jobExecTO, key);
 +                                    jobExecTO.setStatus(scheduler.getScheduler().getTriggerState(t.getKey()).name());
 +                                    jobExecTO.setStartDate(t.getStartTime());
 +
 +                                    jobExecTOs.add(jobExecTO);
 +                                }
 +                            }
 +                        }
 +                    }
 +                } catch (SchedulerException e) {
 +                    LOG.debug("Problems while retrieving all scheduled jobs", e);
 +                } catch (InstantiationException e) {
 +                    LOG.debug("Problems while instantiating {}", reference, e);
 +                } catch (IllegalAccessException e) {
 +                    LOG.debug("Problems while accessing {}", reference, e);
 +                }
 +                break;
 +
 +            default:
 +        }
 +        return jobExecTOs;
 +    }
 +
 +    protected void actionJob(final String jobName, final JobAction action) {
 +        if (jobName != null) {
 +            JobKey jobKey = new JobKey(jobName, Scheduler.DEFAULT_GROUP);
 +            try {
 +                if (scheduler.getScheduler().checkExists(jobKey)) {
 +                    switch (action) {
 +                        case START:
-                             scheduler.getScheduler().triggerJob(jobKey);
++                            Long currentKey = getKeyFromJobName(jobKey);
++                            boolean found = false;
++                            //Two or more equals jobs cannot be executed concurrently
++                            for (int i = 0; i < scheduler.getScheduler().getCurrentlyExecutingJobs().size() && !found;
++                                    i++) {
++                                JobExecutionContext jec = scheduler.getScheduler().getCurrentlyExecutingJobs().get(i);
++                                Long execJobKey = getKeyFromJobName(jec.getJobDetail().getKey());
++                                if (execJobKey == currentKey) {
++                                    found = true;
++                                }
++                            }
++                            if (!found) {
++                                scheduler.getScheduler().triggerJob(jobKey);
++                            }
 +                            break;
 +
 +                        case STOP:
 +                            scheduler.getScheduler().interrupt(jobKey);
 +                            break;
 +
 +                        default:
 +                    }
 +                }
 +            } catch (SchedulerException e) {
 +                LOG.debug("Problems during {} operation on job {}", action.toString(), jobName, e);
 +            }
 +        }
 +    }
 +}


[06/21] syncope git commit: [SYNCOPE-660] Merge from 1_2_X - minor fixes

Posted by il...@apache.org.
[SYNCOPE-660] Merge from 1_2_X - minor fixes


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

Branch: refs/heads/SYNCOPE-666
Commit: 4ded5ba28b77069b95d61619b6f2a97eb784a4c5
Parents: 582eeb4
Author: giacomolm <gi...@hotmail.it>
Authored: Mon Jun 1 12:17:17 2015 +0200
Committer: giacomolm <gi...@hotmail.it>
Committed: Mon Jun 1 12:17:17 2015 +0200

----------------------------------------------------------------------
 .../client/console/panels/RuntimePanel.java     | 27 ++++++++++++++++-
 .../html/repeater/data/table/JobColumn.java     | 32 ++------------------
 2 files changed, 28 insertions(+), 31 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/4ded5ba2/client/old_console/src/main/java/org/apache/syncope/client/console/panels/RuntimePanel.java
----------------------------------------------------------------------
diff --git a/client/old_console/src/main/java/org/apache/syncope/client/console/panels/RuntimePanel.java b/client/old_console/src/main/java/org/apache/syncope/client/console/panels/RuntimePanel.java
index ba15f5d..4831acd 100644
--- a/client/old_console/src/main/java/org/apache/syncope/client/console/panels/RuntimePanel.java
+++ b/client/old_console/src/main/java/org/apache/syncope/client/console/panels/RuntimePanel.java
@@ -23,9 +23,11 @@ import org.apache.syncope.client.console.wicket.ajax.markup.html.ClearIndicating
 import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AbstractAjaxTimerBehavior;
 import org.apache.wicket.ajax.AjaxRequestTarget;
+import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
 import org.apache.wicket.markup.html.panel.Fragment;
 import org.apache.wicket.model.IModel;
 import org.apache.wicket.markup.html.panel.Panel;
+import org.apache.wicket.util.time.Duration;
 
 public class RuntimePanel extends Panel {
 
@@ -54,7 +56,7 @@ public class RuntimePanel extends Panel {
 
     }
 
-    public final void refresh() {
+    public final RuntimePanel refresh() {
         boolean currentStatus = jobRestClient.isJobRunning(jobId);
         if (currentStatus && !latestStatus) {
             setRunning();
@@ -62,6 +64,7 @@ public class RuntimePanel extends Panel {
             setNotRunning();
         }
         latestStatus = currentStatus;
+        return this;
     }
 
     public void setRunning() {
@@ -102,4 +105,26 @@ public class RuntimePanel extends Panel {
         this.add(this.timer);
     }
 
+    public void startPolling(final int seconds) {
+        AbstractAjaxTimerBehavior timer = new AbstractAjaxTimerBehavior(Duration.seconds(seconds)) {
+
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            protected void onTimer(AjaxRequestTarget target) {                
+                target.add(refresh());
+            }
+
+            @Override
+            protected void updateAjaxAttributes(AjaxRequestAttributes attributes) {
+                super.updateAjaxAttributes(attributes);
+                attributes.getExtraParameters().put("pollingTimeout", "true");
+            }
+
+        };
+
+        panel.setTimer(timer);
+
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/4ded5ba2/client/old_console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/JobColumn.java
----------------------------------------------------------------------
diff --git a/client/old_console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/JobColumn.java b/client/old_console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/JobColumn.java
index 4cca6bf..70d7074 100644
--- a/client/old_console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/JobColumn.java
+++ b/client/old_console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/JobColumn.java
@@ -20,17 +20,13 @@ package org.apache.syncope.client.console.wicket.extensions.markup.html.repeater
 
 import org.apache.syncope.client.console.panels.RuntimePanel;
 import org.apache.syncope.client.console.rest.JobRestClient;
-import org.apache.syncope.common.lib.to.AbsractTaskTO;
+import org.apache.syncope.common.lib.to.AbstractTaskTO;
 import org.apache.syncope.common.lib.to.ReportTO;
 import org.apache.wicket.PageReference;
-import org.apache.wicket.ajax.AbstractAjaxTimerBehavior;
-import org.apache.wicket.ajax.AjaxRequestTarget;
-import org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
 import org.apache.wicket.extensions.markup.html.repeater.data.grid.ICellPopulator;
 import org.apache.wicket.extensions.markup.html.repeater.data.table.AbstractColumn;
 import org.apache.wicket.markup.repeater.Item;
 import org.apache.wicket.model.IModel;
-import org.apache.wicket.util.time.Duration;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -63,32 +59,8 @@ public class JobColumn<T, S> extends AbstractColumn<T, S> {
         }
         if (jobId != null) {
             panel = new RuntimePanel(componentId, model, pageRef, jobId, jobRestClient);
-            startPolling(10);
+            panel.startPolling(10);
             item.add(panel);
         }
     }
-
-    public void startPolling(final int seconds) {
-        AbstractAjaxTimerBehavior timer = new AbstractAjaxTimerBehavior(Duration.seconds(seconds)) {
-
-            private static final long serialVersionUID = 1L;
-
-            @Override
-            protected void onTimer(AjaxRequestTarget target) {
-                panel.refresh();
-                target.add(panel);
-            }
-
-            @Override
-            protected void updateAjaxAttributes(AjaxRequestAttributes attributes) {
-                super.updateAjaxAttributes(attributes);
-                attributes.getExtraParameters().put("pollingTimeout", "true");
-            }
-
-        };
-
-        panel.setTimer(timer);
-
-    }
-
 }


[11/21] syncope git commit: [SYNCOPE-674] During tasks creation, the notification manager now returns a list of notification task

Posted by il...@apache.org.
[SYNCOPE-674] During tasks creation, the notification manager now returns a list of notification task


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

Branch: refs/heads/SYNCOPE-666
Commit: 63095476598571425fdf8aa941aaa04ab7ed45a4
Parents: 8106e24
Author: giacomolm <gi...@hotmail.it>
Authored: Fri Jun 5 09:30:16 2015 +0200
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Fri Jun 5 11:50:35 2015 +0200

----------------------------------------------------------------------
 .../syncope/core/notification/NotificationManager.java   | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/63095476/core/src/main/java/org/apache/syncope/core/notification/NotificationManager.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/syncope/core/notification/NotificationManager.java b/core/src/main/java/org/apache/syncope/core/notification/NotificationManager.java
index 341a0bd..48caa54 100644
--- a/core/src/main/java/org/apache/syncope/core/notification/NotificationManager.java
+++ b/core/src/main/java/org/apache/syncope/core/notification/NotificationManager.java
@@ -262,7 +262,7 @@ public class NotificationManager {
     /**
      * Create notification tasks for each notification matching the given user id and (some of) tasks performed.
      */
-    public void createTasks(
+    public List<NotificationTask> createTasks(
             final AuditElements.EventCategoryType type,
             final String category,
             final String subcategory,
@@ -274,6 +274,7 @@ public class NotificationManager {
 
         SubjectType subjectType = null;
         AbstractSubject subject = null;
+        List<NotificationTask> notificationList = new ArrayList<NotificationTask>();
 
         if (before instanceof UserTO) {
             subjectType = SubjectType.USER;
@@ -327,15 +328,17 @@ public class NotificationManager {
                     } else if (subject instanceof SyncopeRole) {
                         model.put("role", roleDataBinder.getRoleTO((SyncopeRole) subject));
                     }
-
-                    taskDAO.save(getNotificationTask(notification, subject, model));
+                    NotificationTask notificationTask = getNotificationTask(notification, subject, model);
+                    notificationTask = taskDAO.save(notificationTask);
+                    notificationList.add(notificationTask);                    
                 }
             } else {
                 LOG.debug("Notification {}, userAbout {}, roleAbout {} is deactivated, "
                         + "notification task will not be created", notification.getId(),
                         notification.getUserAbout(), notification.getRoleAbout());
             }
-        }
+        }        
+        return notificationList;
     }
 
     private String getRecipientEmail(


[12/21] syncope git commit: Upgading izpack

Posted by il...@apache.org.
Upgading izpack


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

Branch: refs/heads/SYNCOPE-666
Commit: c03b1cfa315c01058875023ec5eaf1f2dc1a47c4
Parents: 6309547
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Wed Jun 3 15:08:08 2015 +0200
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Fri Jun 5 11:50:47 2015 +0200

----------------------------------------------------------------------
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/c03b1cfa/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index ad7601c..cbcc04f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -384,7 +384,7 @@ under the License.
     <highlightjs.version>8.0</highlightjs.version>
     <codemirror.version>3.23</codemirror.version>
 
-    <izpack.version>5.0.0-rc4</izpack.version>
+    <izpack.version>5.0.0-rc5</izpack.version>
     <maven-invoker.version>2.1.1</maven-invoker.version>
     
     <jdeb.version>1.4</jdeb.version>


[04/21] syncope git commit: [SYNCOPE-660] Merge from 1_2_X - replacing wrong packages

Posted by il...@apache.org.
[SYNCOPE-660] Merge from 1_2_X - replacing wrong packages


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

Branch: refs/heads/SYNCOPE-666
Commit: 582eeb4521e1961491cdc86c6e1aaabd4123e672
Parents: 34a0422
Author: giacomolm <gi...@hotmail.it>
Authored: Fri May 29 12:50:53 2015 +0200
Committer: giacomolm <gi...@hotmail.it>
Committed: Fri May 29 12:50:53 2015 +0200

----------------------------------------------------------------------
 .../syncope/client/console/pages/Reports.java   | 71 ++++++++--------
 .../syncope/client/console/pages/Tasks.java     | 42 +++++-----
 .../console/panels/NotificationTasks.java       | 35 ++++----
 .../client/console/panels/RuntimePanel.java     |  2 +-
 .../client/console/panels/SchedTasks.java       | 41 +++++-----
 .../client/console/panels/SyncTasksPanel.java   | 49 ++++++-----
 .../client/console/rest/ReportRestClient.java   | 22 ++---
 .../client/console/rest/TaskRestClient.java     | 85 +++++++-------------
 .../html/repeater/data/table/JobColumn.java     |  4 +-
 9 files changed, 158 insertions(+), 193 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/582eeb45/client/old_console/src/main/java/org/apache/syncope/client/console/pages/Reports.java
----------------------------------------------------------------------
diff --git a/client/old_console/src/main/java/org/apache/syncope/client/console/pages/Reports.java b/client/old_console/src/main/java/org/apache/syncope/client/console/pages/Reports.java
index 88fdf1c..ff32fef 100644
--- a/client/old_console/src/main/java/org/apache/syncope/client/console/pages/Reports.java
+++ b/client/old_console/src/main/java/org/apache/syncope/client/console/pages/Reports.java
@@ -16,31 +16,30 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.console.pages;
+package org.apache.syncope.client.console.pages;
 
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Map;
-import org.apache.syncope.common.to.EventCategoryTO;
-import org.apache.syncope.common.to.ReportTO;
-import org.apache.syncope.common.types.AuditElements.Result;
-import org.apache.syncope.common.types.AuditLoggerName;
-import org.apache.syncope.common.util.LoggerEventUtils;
-import org.apache.syncope.common.SyncopeClientException;
-import org.apache.syncope.console.commons.Constants;
-import org.apache.syncope.console.commons.PreferenceManager;
-import org.apache.syncope.console.commons.SortableDataProviderComparator;
-import org.apache.syncope.console.pages.panels.LoggerCategoryPanel;
-import org.apache.syncope.console.pages.panels.SelectedEventsPanel;
-import org.apache.syncope.console.rest.LoggerRestClient;
-import org.apache.syncope.console.wicket.ajax.markup.html.ClearIndicatingAjaxLink;
-import org.apache.syncope.console.wicket.extensions.markup.html.repeater.data.table.ActionColumn;
-import org.apache.syncope.console.wicket.extensions.markup.html.repeater.data.table.DatePropertyColumn;
-import org.apache.syncope.console.wicket.extensions.markup.html.repeater.data.table.JobColumn;
-import org.apache.syncope.console.wicket.markup.html.form.ActionLink;
-import org.apache.syncope.console.wicket.markup.html.form.ActionLinksPanel;
+import org.apache.commons.lang3.tuple.Pair;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.commons.PreferenceManager;
+import org.apache.syncope.client.console.commons.SortableDataProviderComparator;
+import org.apache.syncope.client.console.panels.LoggerCategoryPanel;
+import org.apache.syncope.client.console.panels.SelectedEventsPanel;
+import org.apache.syncope.client.console.rest.LoggerRestClient;
+import org.apache.syncope.client.console.wicket.ajax.markup.html.ClearIndicatingAjaxLink;
+import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.ActionColumn;
+import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.DatePropertyColumn;
+import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.JobColumn;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLinksPanel;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.EventCategoryTO;
+import org.apache.syncope.common.lib.to.ReportTO;
+import org.apache.syncope.common.lib.types.AuditElements.Result;
+import org.apache.syncope.common.lib.types.AuditLoggerName;
 import org.apache.wicket.Component;
 import org.apache.wicket.Page;
 import org.apache.wicket.ajax.AjaxRequestTarget;
@@ -116,8 +115,8 @@ public class Reports extends BasePage {
 
         paginatorRows = prefMan.getPaginatorRows(getRequest(), Constants.PREF_REPORT_PAGINATOR_ROWS);
 
-        List<IColumn<ReportTO, String>> columns = new ArrayList<IColumn<ReportTO, String>>();
-        columns.add(new PropertyColumn<ReportTO, String>(new ResourceModel("id"), "id", "id"));
+        List<IColumn<ReportTO, String>> columns = new ArrayList<>();
+        columns.add(new PropertyColumn<ReportTO, String>(new ResourceModel("key"), "key", "key"));
         columns.add(new PropertyColumn<ReportTO, String>(new ResourceModel("name"), "name", "name"));
         columns.add(new DatePropertyColumn<ReportTO>(new ResourceModel("lastExec"), "lastExec", "lastExec"));
         columns.add(new DatePropertyColumn<ReportTO>(new ResourceModel("nextExec"), "nextExec", "nextExec"));
@@ -166,7 +165,7 @@ public class Reports extends BasePage {
                     @Override
                     public void onClick(final AjaxRequestTarget target) {
                         try {
-                            reportRestClient.startExecution(reportTO.getId());
+                            reportRestClient.startExecution(reportTO.getKey());
                             getSession().info(getString(Constants.OPERATION_SUCCEEDED));
                         } catch (SyncopeClientException scce) {
                             error(scce.getMessage());
@@ -184,7 +183,7 @@ public class Reports extends BasePage {
                     @Override
                     public void onClick(final AjaxRequestTarget target) {
                         try {
-                            reportRestClient.delete(reportTO.getId());
+                            reportRestClient.delete(reportTO.getKey());
                             info(getString(Constants.OPERATION_SUCCEEDED));
                         } catch (SyncopeClientException scce) {
                             error(scce.getMessage());
@@ -218,8 +217,7 @@ public class Reports extends BasePage {
         });
 
         final AjaxFallbackDefaultDataTable<ReportTO, String> reportTable =
-                new AjaxFallbackDefaultDataTable<ReportTO, String>(
-                        "reportTable", columns, new ReportProvider(), paginatorRows);
+                new AjaxFallbackDefaultDataTable<>("reportTable", columns, new ReportProvider(), paginatorRows);
 
         reportContainer.add(reportTable);
         reportContainer.setOutputMarkupId(true);
@@ -253,7 +251,7 @@ public class Reports extends BasePage {
         paginatorForm.add(rowsChooser);
         add(paginatorForm);
 
-        AjaxLink createLink = new ClearIndicatingAjaxLink("createLink", getPageReference()) {
+        AjaxLink<Void> createLink = new ClearIndicatingAjaxLink<Void>("createLink", getPageReference()) {
 
             private static final long serialVersionUID = -7978723352517770644L;
 
@@ -291,11 +289,11 @@ public class Reports extends BasePage {
         final Form form = new Form("auditForm");
         auditContainer.add(form);
 
-        final List<String> events = new ArrayList<String>();
+        final List<String> events = new ArrayList<>();
 
         final List<AuditLoggerName> audits = loggerRestClient.listAudits();
         for (AuditLoggerName audit : audits) {
-            events.add(LoggerEventUtils.buildEvent(
+            events.add(AuditLoggerName.buildEvent(
                     audit.getType(),
                     audit.getCategory(),
                     audit.getSubcategory(),
@@ -303,7 +301,7 @@ public class Reports extends BasePage {
                     audit.getResult()));
         }
 
-        final ListModel<String> model = new ListModel<String>(new ArrayList<String>(events));
+        final ListModel<String> model = new ListModel<>(new ArrayList<>(events));
 
         form.add(new LoggerCategoryPanel(
                 "events", loggerRestClient.listEvents(), model, getPageReference(), "Reports") {
@@ -334,8 +332,8 @@ public class Reports extends BasePage {
 
                             for (String toBeRemoved : eventSelectionChanged.getToBeRemoved()) {
                                 if (events.contains(toBeRemoved)) {
-                                    final Map.Entry<EventCategoryTO, Result> eventCategory =
-                                    LoggerEventUtils.parseEventCategory(toBeRemoved);
+                                    Pair<EventCategoryTO, Result> eventCategory =
+                                    AuditLoggerName.parseEventCategory(toBeRemoved);
 
                                     final AuditLoggerName auditLoggerName = new AuditLoggerName(
                                             eventCategory.getKey().getType(),
@@ -352,8 +350,8 @@ public class Reports extends BasePage {
 
                             for (String toBeAdded : eventSelectionChanged.getToBeAdded()) {
                                 if (!events.contains(toBeAdded)) {
-                                    final Map.Entry<EventCategoryTO, Result> eventCategory =
-                                    LoggerEventUtils.parseEventCategory(toBeAdded);
+                                    Pair<EventCategoryTO, Result> eventCategory =
+                                    AuditLoggerName.parseEventCategory(toBeAdded);
 
                                     final AuditLoggerName auditLoggerName = new AuditLoggerName(
                                             eventCategory.getKey().getType(),
@@ -382,8 +380,8 @@ public class Reports extends BasePage {
             super();
 
             //Default sorting
-            setSort("id", SortOrder.ASCENDING);
-            comparator = new SortableDataProviderComparator<ReportTO>(this);
+            setSort("key", SortOrder.ASCENDING);
+            comparator = new SortableDataProviderComparator<>(this);
         }
 
         @Override
@@ -415,6 +413,7 @@ public class Reports extends BasePage {
             };
         }
     }
+
     /**
      * IndicatorMarkupId behaviour is embedded in Reports.html
      */

http://git-wip-us.apache.org/repos/asf/syncope/blob/582eeb45/client/old_console/src/main/java/org/apache/syncope/client/console/pages/Tasks.java
----------------------------------------------------------------------
diff --git a/client/old_console/src/main/java/org/apache/syncope/client/console/pages/Tasks.java b/client/old_console/src/main/java/org/apache/syncope/client/console/pages/Tasks.java
index 11819c6..df2a87f 100644
--- a/client/old_console/src/main/java/org/apache/syncope/client/console/pages/Tasks.java
+++ b/client/old_console/src/main/java/org/apache/syncope/client/console/pages/Tasks.java
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.console.pages;
+package org.apache.syncope.client.console.pages;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -24,19 +24,19 @@ import java.util.Collections;
 import java.util.Comparator;
 import java.util.Iterator;
 import java.util.List;
-import org.apache.syncope.common.to.SchedTaskTO;
-import org.apache.syncope.common.to.TaskExecTO;
-import org.apache.syncope.common.to.AbstractTaskTO;
-import org.apache.syncope.console.commons.SortableDataProviderComparator;
-import org.apache.syncope.console.pages.panels.AjaxDataTablePanel;
-import org.apache.syncope.console.pages.panels.NotificationTasks;
-import org.apache.syncope.console.pages.panels.PropagationTasks;
-import org.apache.syncope.console.pages.panels.SchedTasks;
-import org.apache.syncope.console.pages.panels.PushTasksPanel;
-import org.apache.syncope.console.pages.panels.SyncTasksPanel;
-import org.apache.syncope.console.rest.BaseRestClient;
-import org.apache.syncope.console.rest.TaskRestClient;
-import org.apache.syncope.console.wicket.markup.html.form.ActionLink;
+import org.apache.syncope.client.console.commons.SortableDataProviderComparator;
+import org.apache.syncope.client.console.panels.AjaxDataTablePanel;
+import org.apache.syncope.client.console.panels.NotificationTasks;
+import org.apache.syncope.client.console.panels.PropagationTasks;
+import org.apache.syncope.client.console.panels.PushTasksPanel;
+import org.apache.syncope.client.console.panels.SchedTasks;
+import org.apache.syncope.client.console.panels.SyncTasksPanel;
+import org.apache.syncope.client.console.rest.BaseRestClient;
+import org.apache.syncope.client.console.rest.TaskRestClient;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
+import org.apache.syncope.common.lib.to.AbstractTaskTO;
+import org.apache.syncope.common.lib.to.SchedTaskTO;
+import org.apache.syncope.common.lib.to.TaskExecTO;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
 import org.apache.wicket.extensions.markup.html.repeater.data.sort.SortOrder;
@@ -141,8 +141,8 @@ public class Tasks extends BasePage {
             super();
 
             //Default sorting
-            setSort("id", SortOrder.DESCENDING);
-            comparator = new SortableDataProviderComparator<T>(this);
+            setSort("key", SortOrder.DESCENDING);
+            comparator = new SortableDataProviderComparator<>(this);
             this.paginatorRows = paginatorRows;
             this.restClient = restClient;
             this.id = id;
@@ -151,7 +151,7 @@ public class Tasks extends BasePage {
 
         @Override
         public Iterator<T> iterator(final long first, final long count) {
-            final List<T> tasks = new ArrayList<T>();
+            final List<T> tasks = new ArrayList<>();
 
             final int page = ((int) first / paginatorRows);
 
@@ -184,7 +184,7 @@ public class Tasks extends BasePage {
 
         @Override
         public IModel<T> model(final T object) {
-            return new CompoundPropertyModel<T>(object);
+            return new CompoundPropertyModel<>(object);
         }
     }
 
@@ -208,7 +208,7 @@ public class Tasks extends BasePage {
             final BaseRestClient restClient) {
 
         @SuppressWarnings("unchecked")
-        final AjaxDataTablePanel<AbstractTaskTO, String> table = new AjaxDataTablePanel<AbstractTaskTO, String>(
+        final AjaxDataTablePanel<AbstractTaskTO, String> table = new AjaxDataTablePanel<>(
                 "datatable",
                 columns,
                 (ISortableDataProvider<AbstractTaskTO, String>) dataProvider,
@@ -216,7 +216,7 @@ public class Tasks extends BasePage {
                 Arrays.asList(new ActionLink.ActionType[] {
                     ActionLink.ActionType.DELETE, ActionLink.ActionType.DRYRUN, ActionLink.ActionType.EXECUTE }),
                 restClient,
-                "id",
+                "key",
                 TASKS,
                 pageRef);
 
@@ -232,8 +232,8 @@ public class Tasks extends BasePage {
      * IndicatorMarkupId behaviour is embedded in Tasks.html
      */
     @Override
+
     public String getAjaxIndicatorMarkupId() {
         return "";
     }
-
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/582eeb45/client/old_console/src/main/java/org/apache/syncope/client/console/panels/NotificationTasks.java
----------------------------------------------------------------------
diff --git a/client/old_console/src/main/java/org/apache/syncope/client/console/panels/NotificationTasks.java b/client/old_console/src/main/java/org/apache/syncope/client/console/panels/NotificationTasks.java
index 9c7b458..6449450 100644
--- a/client/old_console/src/main/java/org/apache/syncope/client/console/panels/NotificationTasks.java
+++ b/client/old_console/src/main/java/org/apache/syncope/client/console/panels/NotificationTasks.java
@@ -16,21 +16,21 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.console.pages.panels;
+package org.apache.syncope.client.console.panels;
 
 import java.util.ArrayList;
 import java.util.List;
-import org.apache.syncope.common.to.NotificationTaskTO;
-import org.apache.syncope.common.to.AbstractTaskTO;
-import org.apache.syncope.common.SyncopeClientException;
-import org.apache.syncope.console.commons.Constants;
-import org.apache.syncope.console.pages.NotificationTaskModalPage;
-import org.apache.syncope.console.pages.Tasks;
-import org.apache.syncope.console.pages.Tasks.TasksProvider;
-import org.apache.syncope.console.wicket.extensions.markup.html.repeater.data.table.ActionColumn;
-import org.apache.syncope.console.wicket.extensions.markup.html.repeater.data.table.JobColumn;
-import org.apache.syncope.console.wicket.markup.html.form.ActionLink;
-import org.apache.syncope.console.wicket.markup.html.form.ActionLinksPanel;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.pages.NotificationTaskModalPage;
+import org.apache.syncope.client.console.pages.Tasks;
+import org.apache.syncope.client.console.pages.Tasks.TasksProvider;
+import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.ActionColumn;
+import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.JobColumn;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLinksPanel;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.AbstractTaskTO;
+import org.apache.syncope.common.lib.to.NotificationTaskTO;
 import org.apache.wicket.Component;
 import org.apache.wicket.Page;
 import org.apache.wicket.PageReference;
@@ -138,10 +138,10 @@ public class NotificationTasks extends AbstractTasks {
     }
 
     private List<IColumn<AbstractTaskTO, String>> getColumns() {
-        final List<IColumn<AbstractTaskTO, String>> columns = new ArrayList<IColumn<AbstractTaskTO, String>>();
+        final List<IColumn<AbstractTaskTO, String>> columns = new ArrayList<>();
 
         columns.add(new PropertyColumn<AbstractTaskTO, String>(
-                new StringResourceModel("id", this, null), "id", "id"));
+                new StringResourceModel("key", this, null), "key", "key"));
         columns.add(new PropertyColumn<AbstractTaskTO, String>(
                 new StringResourceModel("sender", this, null), "sender", "sender"));
         columns.add(new PropertyColumn<AbstractTaskTO, String>(
@@ -152,9 +152,8 @@ public class NotificationTasks extends AbstractTasks {
                 new StringResourceModel("traceLevel", this, null), "traceLevel", "traceLevel"));
         columns.add(new PropertyColumn<AbstractTaskTO, String>(
                 new StringResourceModel("latestExecStatus", this, null), "latestExecStatus", "latestExecStatus"));
-
         columns.add(new JobColumn<AbstractTaskTO, String>(new StringResourceModel("", this, null, ""), "runtime",
-                pageRef, restClient)); 
+                pageRef, restClient));
 
         columns.add(new ActionColumn<AbstractTaskTO, String>(new StringResourceModel("actions", this, null, "")) {
 
@@ -195,7 +194,7 @@ public class NotificationTasks extends AbstractTasks {
                     @Override
                     public void onClick(final AjaxRequestTarget target) {
                         try {
-                            restClient.startExecution(taskTO.getId(), false);
+                            restClient.startExecution(taskTO.getKey(), false);
                             getSession().info(getString(Constants.OPERATION_SUCCEEDED));
                         } catch (SyncopeClientException scce) {
                             error(scce.getMessage());
@@ -213,7 +212,7 @@ public class NotificationTasks extends AbstractTasks {
                     @Override
                     public void onClick(final AjaxRequestTarget target) {
                         try {
-                            restClient.delete(taskTO.getId(), NotificationTaskTO.class);
+                            restClient.delete(taskTO.getKey(), NotificationTaskTO.class);
                             info(getString(Constants.OPERATION_SUCCEEDED));
                         } catch (SyncopeClientException scce) {
                             error(scce.getMessage());

http://git-wip-us.apache.org/repos/asf/syncope/blob/582eeb45/client/old_console/src/main/java/org/apache/syncope/client/console/panels/RuntimePanel.java
----------------------------------------------------------------------
diff --git a/client/old_console/src/main/java/org/apache/syncope/client/console/panels/RuntimePanel.java b/client/old_console/src/main/java/org/apache/syncope/client/console/panels/RuntimePanel.java
index 34e058e..ba15f5d 100644
--- a/client/old_console/src/main/java/org/apache/syncope/client/console/panels/RuntimePanel.java
+++ b/client/old_console/src/main/java/org/apache/syncope/client/console/panels/RuntimePanel.java
@@ -19,7 +19,7 @@
 package org.apache.syncope.client.console.panels;
 
 import org.apache.syncope.client.console.rest.JobRestClient;
-import org.apache.syncope.console.wicket.ajax.markup.html.ClearIndicatingAjaxLink;
+import org.apache.syncope.client.console.wicket.ajax.markup.html.ClearIndicatingAjaxLink;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AbstractAjaxTimerBehavior;
 import org.apache.wicket.ajax.AjaxRequestTarget;

http://git-wip-us.apache.org/repos/asf/syncope/blob/582eeb45/client/old_console/src/main/java/org/apache/syncope/client/console/panels/SchedTasks.java
----------------------------------------------------------------------
diff --git a/client/old_console/src/main/java/org/apache/syncope/client/console/panels/SchedTasks.java b/client/old_console/src/main/java/org/apache/syncope/client/console/panels/SchedTasks.java
index 78591a8..9a64c83 100644
--- a/client/old_console/src/main/java/org/apache/syncope/client/console/panels/SchedTasks.java
+++ b/client/old_console/src/main/java/org/apache/syncope/client/console/panels/SchedTasks.java
@@ -16,25 +16,23 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.console.pages.panels;
-
-import static org.apache.syncope.console.pages.panels.AbstractTasks.TASKS;
+package org.apache.syncope.client.console.panels;
 
 import java.util.ArrayList;
 import java.util.List;
-import org.apache.syncope.common.to.SchedTaskTO;
-import org.apache.syncope.common.to.AbstractTaskTO;
-import org.apache.syncope.common.SyncopeClientException;
-import org.apache.syncope.console.commons.Constants;
-import org.apache.syncope.console.pages.SchedTaskModalPage;
-import org.apache.syncope.console.pages.Tasks;
-import org.apache.syncope.console.pages.Tasks.TasksProvider;
-import org.apache.syncope.console.wicket.ajax.markup.html.ClearIndicatingAjaxLink;
-import org.apache.syncope.console.wicket.extensions.markup.html.repeater.data.table.ActionColumn;
-import org.apache.syncope.console.wicket.extensions.markup.html.repeater.data.table.DatePropertyColumn;
-import org.apache.syncope.console.wicket.extensions.markup.html.repeater.data.table.JobColumn;
-import org.apache.syncope.console.wicket.markup.html.form.ActionLink;
-import org.apache.syncope.console.wicket.markup.html.form.ActionLinksPanel;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.pages.SchedTaskModalPage;
+import org.apache.syncope.client.console.pages.Tasks;
+import org.apache.syncope.client.console.pages.Tasks.TasksProvider;
+import org.apache.syncope.client.console.wicket.ajax.markup.html.ClearIndicatingAjaxLink;
+import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.ActionColumn;
+import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.DatePropertyColumn;
+import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.JobColumn;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLinksPanel;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.AbstractTaskTO;
+import org.apache.syncope.common.lib.to.SchedTaskTO;
 import org.apache.wicket.Component;
 import org.apache.wicket.Page;
 import org.apache.wicket.PageReference;
@@ -156,7 +154,7 @@ public class SchedTasks extends AbstractTasks {
         final List<IColumn<AbstractTaskTO, String>> columns = new ArrayList<IColumn<AbstractTaskTO, String>>();
 
         columns.add(new PropertyColumn<AbstractTaskTO, String>(
-                new StringResourceModel("id", this, null), "id", "id"));
+                new StringResourceModel("key", this, null), "key", "key"));
         columns.add(new PropertyColumn<AbstractTaskTO, String>(
                 new StringResourceModel("name", this, null), "name", "name"));
         columns.add(new PropertyColumn<AbstractTaskTO, String>(
@@ -169,9 +167,8 @@ public class SchedTasks extends AbstractTasks {
                 new StringResourceModel("nextExec", this, null), "nextExec", "nextExec"));
         columns.add(new PropertyColumn<AbstractTaskTO, String>(
                 new StringResourceModel("latestExecStatus", this, null), "latestExecStatus", "latestExecStatus"));
-
         columns.add(new JobColumn<AbstractTaskTO, String>(new StringResourceModel("", this, null, ""), "runtime",
-                pageRef, restClient)); 
+                pageRef, restClient));
 
         columns.add(new ActionColumn<AbstractTaskTO, String>(new StringResourceModel("actions", this, null, "")) {
 
@@ -211,7 +208,7 @@ public class SchedTasks extends AbstractTasks {
                     @Override
                     public void onClick(final AjaxRequestTarget target) {
                         try {
-                            restClient.startExecution(taskTO.getId(), false);
+                            restClient.startExecution(taskTO.getKey(), false);
                             getSession().info(getString(Constants.OPERATION_SUCCEEDED));
                         } catch (SyncopeClientException scce) {
                             error(scce.getMessage());
@@ -229,7 +226,7 @@ public class SchedTasks extends AbstractTasks {
                     @Override
                     public void onClick(final AjaxRequestTarget target) {
                         try {
-                            restClient.startExecution(taskTO.getId(), true);
+                            restClient.startExecution(taskTO.getKey(), true);
                             getSession().info(getString(Constants.OPERATION_SUCCEEDED));
                         } catch (SyncopeClientException scce) {
                             error(scce.getMessage());
@@ -247,7 +244,7 @@ public class SchedTasks extends AbstractTasks {
                     @Override
                     public void onClick(final AjaxRequestTarget target) {
                         try {
-                            restClient.delete(taskTO.getId(), SchedTaskTO.class);
+                            restClient.delete(taskTO.getKey(), SchedTaskTO.class);
                             info(getString(Constants.OPERATION_SUCCEEDED));
                         } catch (SyncopeClientException scce) {
                             error(scce.getMessage());

http://git-wip-us.apache.org/repos/asf/syncope/blob/582eeb45/client/old_console/src/main/java/org/apache/syncope/client/console/panels/SyncTasksPanel.java
----------------------------------------------------------------------
diff --git a/client/old_console/src/main/java/org/apache/syncope/client/console/panels/SyncTasksPanel.java b/client/old_console/src/main/java/org/apache/syncope/client/console/panels/SyncTasksPanel.java
index 032f4e4..50d91df 100644
--- a/client/old_console/src/main/java/org/apache/syncope/client/console/panels/SyncTasksPanel.java
+++ b/client/old_console/src/main/java/org/apache/syncope/client/console/panels/SyncTasksPanel.java
@@ -16,22 +16,22 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.console.pages.panels;
+package org.apache.syncope.client.console.panels;
 
 import java.util.ArrayList;
 import java.util.List;
-import org.apache.syncope.common.SyncopeClientException;
-import org.apache.syncope.common.to.AbstractTaskTO;
-import org.apache.syncope.common.to.SyncTaskTO;
-import org.apache.syncope.console.commons.Constants;
-import org.apache.syncope.console.pages.RoleTemplateModalPage;
-import org.apache.syncope.console.pages.SyncTaskModalPage;
-import org.apache.syncope.console.pages.UserTemplateModalPage;
-import org.apache.syncope.console.wicket.extensions.markup.html.repeater.data.table.ActionColumn;
-import org.apache.syncope.console.wicket.extensions.markup.html.repeater.data.table.DatePropertyColumn;
-import org.apache.syncope.console.wicket.extensions.markup.html.repeater.data.table.JobColumn;
-import org.apache.syncope.console.wicket.markup.html.form.ActionLink;
-import org.apache.syncope.console.wicket.markup.html.form.ActionLinksPanel;
+import org.apache.syncope.client.console.commons.Constants;
+import org.apache.syncope.client.console.pages.GroupTemplateModalPage;
+import org.apache.syncope.client.console.pages.SyncTaskModalPage;
+import org.apache.syncope.client.console.pages.UserTemplateModalPage;
+import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.ActionColumn;
+import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.DatePropertyColumn;
+import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.JobColumn;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
+import org.apache.syncope.client.console.wicket.markup.html.form.ActionLinksPanel;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.AbstractTaskTO;
+import org.apache.syncope.common.lib.to.SyncTaskTO;
 import org.apache.wicket.Component;
 import org.apache.wicket.Page;
 import org.apache.wicket.PageReference;
@@ -43,7 +43,7 @@ import org.apache.wicket.model.IModel;
 import org.apache.wicket.model.Model;
 import org.apache.wicket.model.StringResourceModel;
 
-public class SyncTasksPanel extends AbstractSyncTasksPanel<SyncTaskTO> {
+public class SyncTasksPanel extends AbstractProvisioningTasksPanel<SyncTaskTO> {
 
     private static final long serialVersionUID = 53189199346016099L;
 
@@ -54,10 +54,10 @@ public class SyncTasksPanel extends AbstractSyncTasksPanel<SyncTaskTO> {
 
     @Override
     protected List<IColumn<AbstractTaskTO, String>> getColumns() {
-        final List<IColumn<AbstractTaskTO, String>> syncTaskscolumns = new ArrayList<IColumn<AbstractTaskTO, String>>();
+        final List<IColumn<AbstractTaskTO, String>> syncTaskscolumns = new ArrayList<>();
 
         syncTaskscolumns.add(new PropertyColumn<AbstractTaskTO, String>(
-                new StringResourceModel("id", this, null), "id", "id"));
+                new StringResourceModel("key", this, null), "key", "key"));
         syncTaskscolumns.add(new PropertyColumn<AbstractTaskTO, String>(
                 new StringResourceModel("name", this, null), "name", "name"));
         syncTaskscolumns.add(new PropertyColumn<AbstractTaskTO, String>(
@@ -70,9 +70,8 @@ public class SyncTasksPanel extends AbstractSyncTasksPanel<SyncTaskTO> {
                 new StringResourceModel("nextExec", this, null), "nextExec", "nextExec"));
         syncTaskscolumns.add(new PropertyColumn<AbstractTaskTO, String>(
                 new StringResourceModel("latestExecStatus", this, null), "latestExecStatus", "latestExecStatus"));
-        
-        syncTaskscolumns.add(new JobColumn<AbstractTaskTO, String>(new StringResourceModel("", this, null, ""), "runtime",
-                pageRef, restClient));        
+        syncTaskscolumns.add(new JobColumn<AbstractTaskTO, String>(new StringResourceModel("", this, null, ""),
+                "runtime", pageRef, restClient));
 
         syncTaskscolumns.add(
                 new ActionColumn<AbstractTaskTO, String>(new StringResourceModel("actions", this, null, "")) {
@@ -141,13 +140,13 @@ public class SyncTasksPanel extends AbstractSyncTasksPanel<SyncTaskTO> {
 
                                     @Override
                                     public Page createPage() {
-                                        return new RoleTemplateModalPage(pageRef, window, taskTO);
+                                        return new GroupTemplateModalPage(pageRef, window, taskTO);
                                     }
                                 });
 
                                 window.show(target);
                             }
-                        }, ActionLink.ActionType.ROLE_TEMPLATE, TASKS);
+                        }, ActionLink.ActionType.GROUP_TEMPLATE, TASKS);
 
                         panel.add(new ActionLink() {
 
@@ -156,7 +155,7 @@ public class SyncTasksPanel extends AbstractSyncTasksPanel<SyncTaskTO> {
                             @Override
                             public void onClick(final AjaxRequestTarget target) {
                                 try {
-                                    restClient.startExecution(taskTO.getId(), false);
+                                    restClient.startExecution(taskTO.getKey(), false);
                                     getSession().info(getString(Constants.OPERATION_SUCCEEDED));
                                 } catch (SyncopeClientException scce) {
                                     error(scce.getMessage());
@@ -174,7 +173,7 @@ public class SyncTasksPanel extends AbstractSyncTasksPanel<SyncTaskTO> {
                             @Override
                             public void onClick(final AjaxRequestTarget target) {
                                 try {
-                                    restClient.startExecution(taskTO.getId(), true);
+                                    restClient.startExecution(taskTO.getKey(), true);
                                     getSession().info(getString(Constants.OPERATION_SUCCEEDED));
                                 } catch (SyncopeClientException scce) {
                                     error(scce.getMessage());
@@ -192,7 +191,7 @@ public class SyncTasksPanel extends AbstractSyncTasksPanel<SyncTaskTO> {
                             @Override
                             public void onClick(final AjaxRequestTarget target) {
                                 try {
-                                    restClient.delete(taskTO.getId(), SyncTaskTO.class);
+                                    restClient.delete(taskTO.getKey(), SyncTaskTO.class);
                                     info(getString(Constants.OPERATION_SUCCEEDED));
                                 } catch (SyncopeClientException scce) {
                                     error(scce.getMessage());
@@ -206,7 +205,7 @@ public class SyncTasksPanel extends AbstractSyncTasksPanel<SyncTaskTO> {
                     }
 
                     @Override
-                    public Component getHeader(String componentId) {
+                    public Component getHeader(final String componentId) {
                         final ActionLinksPanel panel = new ActionLinksPanel(componentId, new Model(), pageRef);
 
                         panel.add(new ActionLink() {

http://git-wip-us.apache.org/repos/asf/syncope/blob/582eeb45/client/old_console/src/main/java/org/apache/syncope/client/console/rest/ReportRestClient.java
----------------------------------------------------------------------
diff --git a/client/old_console/src/main/java/org/apache/syncope/client/console/rest/ReportRestClient.java b/client/old_console/src/main/java/org/apache/syncope/client/console/rest/ReportRestClient.java
index 9b8afdb..5cfe83f 100644
--- a/client/old_console/src/main/java/org/apache/syncope/client/console/rest/ReportRestClient.java
+++ b/client/old_console/src/main/java/org/apache/syncope/client/console/rest/ReportRestClient.java
@@ -16,19 +16,18 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.console.rest;
+package org.apache.syncope.client.console.rest;
 
 import java.util.ArrayList;
 import java.util.List;
 import javax.ws.rs.core.Response;
-import org.apache.syncope.common.services.ReportService;
-import org.apache.syncope.common.to.ReportTO;
-import org.apache.syncope.common.types.ReportExecExportFormat;
-import org.apache.syncope.common.SyncopeClientException;
-import org.apache.syncope.common.to.ReportExecTO;
-import org.apache.syncope.common.types.JobAction;
-import org.apache.syncope.common.types.JobStatusType;
-import org.apache.syncope.common.wrap.ReportletConfClass;
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.ReportTO;
+import org.apache.syncope.common.lib.types.ReportExecExportFormat;
+import org.apache.syncope.common.lib.wrap.ReportletConfClass;
+import org.apache.syncope.common.lib.types.JobAction;
+import org.apache.syncope.common.lib.types.JobStatusType;
+import org.apache.syncope.common.rest.api.service.ReportService;
 import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;
 import org.springframework.stereotype.Component;
 
@@ -73,7 +72,7 @@ public class ReportRestClient extends JobRestClient implements ExecutionRestClie
     }
 
     public void update(final ReportTO reportTO) {
-        getService(ReportService.class).update(reportTO.getId(), reportTO);
+        getService(ReportService.class).update(reportTO.getKey(), reportTO);
     }
 
     /**
@@ -108,7 +107,8 @@ public class ReportRestClient extends JobRestClient implements ExecutionRestClie
     public Response exportExecutionResult(final Long executionId, final ReportExecExportFormat fmt) {
         return getService(ReportService.class).exportExecutionResult(executionId, fmt);
     }
-
+    
+    
     @Override
     public boolean isJobRunning(final long reportId) {
         for (ReportExecTO reportExecTO : getService(ReportService.class).listJobs(JobStatusType.RUNNING)) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/582eeb45/client/old_console/src/main/java/org/apache/syncope/client/console/rest/TaskRestClient.java
----------------------------------------------------------------------
diff --git a/client/old_console/src/main/java/org/apache/syncope/client/console/rest/TaskRestClient.java b/client/old_console/src/main/java/org/apache/syncope/client/console/rest/TaskRestClient.java
index c83ce88..2b09630 100644
--- a/client/old_console/src/main/java/org/apache/syncope/client/console/rest/TaskRestClient.java
+++ b/client/old_console/src/main/java/org/apache/syncope/client/console/rest/TaskRestClient.java
@@ -16,28 +16,23 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.syncope.console.rest;
+package org.apache.syncope.client.console.rest;
 
-import java.util.ArrayList;
 import java.util.List;
-import org.apache.syncope.common.services.TaskService;
-import org.apache.syncope.common.reqres.BulkAction;
-import org.apache.syncope.common.reqres.BulkActionResult;
-import org.apache.syncope.common.wrap.JobClass;
-import org.apache.syncope.common.to.NotificationTaskTO;
-import org.apache.syncope.common.to.PropagationTaskTO;
-import org.apache.syncope.common.to.SchedTaskTO;
-import org.apache.syncope.common.wrap.SyncActionClass;
-import org.apache.syncope.common.to.SyncTaskTO;
-import org.apache.syncope.common.to.AbstractTaskTO;
-import org.apache.syncope.common.types.TaskType;
-import org.apache.syncope.common.util.CollectionWrapper;
-import org.apache.syncope.common.SyncopeClientException;
-import org.apache.syncope.common.to.PushTaskTO;
-import org.apache.syncope.common.to.TaskExecTO;
-import org.apache.syncope.common.types.JobAction;
-import org.apache.syncope.common.types.JobStatusType;
-import org.apache.syncope.common.wrap.PushActionClass;
+import org.apache.syncope.client.console.SyncopeSession;
+import org.apache.syncope.common.lib.to.AbstractTaskTO;
+import org.apache.syncope.common.lib.to.BulkAction;
+import org.apache.syncope.common.lib.to.BulkActionResult;
+import org.apache.syncope.common.lib.to.NotificationTaskTO;
+import org.apache.syncope.common.lib.to.PropagationTaskTO;
+import org.apache.syncope.common.lib.to.PushTaskTO;
+import org.apache.syncope.common.lib.to.SchedTaskTO;
+import org.apache.syncope.common.lib.to.SyncTaskTO;
+import org.apache.syncope.common.lib.types.TaskType;
+import org.apache.syncope.common.lib.to.TaskExecTO;
+import org.apache.syncope.common.lib.types.JobAction;
+import org.apache.syncope.common.lib.types.JobStatusType;
+import org.apache.syncope.common.rest.api.service.TaskService;
 import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;
 import org.springframework.stereotype.Component;
 
@@ -49,42 +44,16 @@ public class TaskRestClient extends JobRestClient implements ExecutionRestClient
 
     private static final long serialVersionUID = 6284485820911028843L;
 
-    /**
-     * Return a list of job classes.
-     *
-     * @return list of classes.
-     */
     public List<String> getJobClasses() {
-        List<JobClass> jobClasses = null;
-
-        try {
-            jobClasses = new ArrayList<JobClass>(getService(TaskService.class).getJobClasses());
-        } catch (SyncopeClientException e) {
-            LOG.error("While getting all job classes", e);
-        }
-        return CollectionWrapper.unwrap(jobClasses);
+        return SyncopeSession.get().getSyncopeTO().getTaskJobs();
     }
 
     public List<String> getSyncActionsClasses() {
-        List<SyncActionClass> actions = null;
-
-        try {
-            actions = new ArrayList<SyncActionClass>(getService(TaskService.class).getSyncActionsClasses());
-        } catch (SyncopeClientException e) {
-            LOG.error("While getting all sync actions classes", e);
-        }
-        return CollectionWrapper.unwrap(actions);
+        return SyncopeSession.get().getSyncopeTO().getSyncActions();
     }
 
     public List<String> getPushActionsClasses() {
-        List<PushActionClass> actions = null;
-
-        try {
-            actions = new ArrayList<PushActionClass>(getService(TaskService.class).getPushActionsClasses());
-        } catch (SyncopeClientException e) {
-            LOG.error("While getting all sync actions classes", e);
-        }
-        return CollectionWrapper.unwrap(actions);
+        return SyncopeSession.get().getSyncopeTO().getPushActions();
     }
 
     /**
@@ -160,27 +129,29 @@ public class TaskRestClient extends JobRestClient implements ExecutionRestClient
     }
 
     public void updateSchedTask(final SchedTaskTO taskTO) {
-        getService(TaskService.class).update(taskTO.getId(), taskTO);
+        getService(TaskService.class).update(taskTO.getKey(), taskTO);
     }
 
     public void updateSyncTask(final SyncTaskTO taskTO) {
-        getService(TaskService.class).update(taskTO.getId(), taskTO);
+        getService(TaskService.class).update(taskTO.getKey(), taskTO);
     }
 
     public BulkActionResult bulkAction(final BulkAction action) {
         return getService(TaskService.class).bulk(action);
     }
-    
+
     @Override
-    public boolean isJobRunning(final long taskId){
-        for(TaskExecTO taskExecTO : getService(TaskService.class).listJobs(JobStatusType.RUNNING)){
-            if(taskExecTO.getTask()== taskId) return true;
+    public boolean isJobRunning(final long taskId) {
+        for (TaskExecTO taskExecTO : getService(TaskService.class).listJobs(JobStatusType.RUNNING)) {
+            if (taskExecTO.getTask() == taskId) {
+                return true;
+            }
         }
         return false;
     }
-    
+
     @Override
-    public void startJob(final long taskId){
+    public void startJob(final long taskId) {
         getService(TaskService.class).actionJob(taskId, JobAction.START);
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/582eeb45/client/old_console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/JobColumn.java
----------------------------------------------------------------------
diff --git a/client/old_console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/JobColumn.java b/client/old_console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/JobColumn.java
index ba47421..4cca6bf 100644
--- a/client/old_console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/JobColumn.java
+++ b/client/old_console/src/main/java/org/apache/syncope/client/console/wicket/extensions/markup/html/repeater/data/table/JobColumn.java
@@ -20,8 +20,8 @@ package org.apache.syncope.client.console.wicket.extensions.markup.html.repeater
 
 import org.apache.syncope.client.console.panels.RuntimePanel;
 import org.apache.syncope.client.console.rest.JobRestClient;
-import org.apache.syncope.common.to.AbstractTaskTO;
-import org.apache.syncope.common.to.ReportTO;
+import org.apache.syncope.common.lib.to.AbsractTaskTO;
+import org.apache.syncope.common.lib.to.ReportTO;
 import org.apache.wicket.PageReference;
 import org.apache.wicket.ajax.AbstractAjaxTimerBehavior;
 import org.apache.wicket.ajax.AjaxRequestTarget;


[07/21] syncope git commit: Upgading izpack

Posted by il...@apache.org.
Upgading izpack


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

Branch: refs/heads/SYNCOPE-666
Commit: 5dbe698d9c7ec764836b7bc15476355256fc3d66
Parents: 8106e24
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Wed Jun 3 15:08:08 2015 +0200
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Wed Jun 3 15:08:08 2015 +0200

----------------------------------------------------------------------
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/5dbe698d/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index ad7601c..cbcc04f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -384,7 +384,7 @@ under the License.
     <highlightjs.version>8.0</highlightjs.version>
     <codemirror.version>3.23</codemirror.version>
 
-    <izpack.version>5.0.0-rc4</izpack.version>
+    <izpack.version>5.0.0-rc5</izpack.version>
     <maven-invoker.version>2.1.1</maven-invoker.version>
     
     <jdeb.version>1.4</jdeb.version>


[03/21] syncope git commit: [SYNCOPE-660] Merge from 1_2_X; This closes #6

Posted by il...@apache.org.
[SYNCOPE-660] Merge from 1_2_X; This closes #6


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

Branch: refs/heads/SYNCOPE-666
Commit: 34a0422aec960f6e9bb459e69e8453bd8bf21b6f
Parents: 8ea1e6a 790704c
Author: giacomolm <gi...@hotmail.it>
Authored: Fri May 29 11:50:07 2015 +0200
Committer: giacomolm <gi...@hotmail.it>
Committed: Fri May 29 11:50:07 2015 +0200

----------------------------------------------------------------------
 .../syncope/client/console/pages/Reports.java   |  79 ++++++++------
 .../syncope/client/console/pages/Tasks.java     |  49 +++++----
 .../console/panels/NotificationTasks.java       |  34 +++---
 .../client/console/panels/RuntimePanel.java     | 105 +++++++++++++++++++
 .../client/console/panels/SchedTasks.java       |  40 ++++---
 .../client/console/panels/SyncTasksPanel.java   |  49 +++++----
 .../client/console/rest/JobRestClient.java      |  31 ++++++
 .../client/console/rest/ReportRestClient.java   |  39 +++++--
 .../client/console/rest/TaskRestClient.java     |  88 ++++++++++++----
 .../html/repeater/data/table/JobColumn.java     |  94 +++++++++++++++++
 .../syncope/client/console/pages/Reports.html   |  13 +++
 .../syncope/client/console/pages/Tasks.html     |  15 +++
 .../client/console/panels/RuntimePanel.html     |  49 +++++++++
 .../syncope/core/logic/AbstractJobLogic.java    |  15 ++-
 14 files changed, 566 insertions(+), 134 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/34a0422a/client/old_console/src/main/java/org/apache/syncope/client/console/pages/Reports.java
----------------------------------------------------------------------
diff --cc client/old_console/src/main/java/org/apache/syncope/client/console/pages/Reports.java
index e484701,0000000..88fdf1c
mode 100644,000000..100644
--- a/client/old_console/src/main/java/org/apache/syncope/client/console/pages/Reports.java
+++ b/client/old_console/src/main/java/org/apache/syncope/client/console/pages/Reports.java
@@@ -1,412 -1,0 +1,425 @@@
 +/*
 + * 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.pages;
++package org.apache.syncope.console.pages;
 +
 +import java.util.ArrayList;
 +import java.util.Collections;
 +import java.util.Iterator;
 +import java.util.List;
- import org.apache.commons.lang3.tuple.Pair;
- import org.apache.syncope.client.console.commons.Constants;
- import org.apache.syncope.client.console.commons.PreferenceManager;
- import org.apache.syncope.client.console.commons.SortableDataProviderComparator;
- import org.apache.syncope.client.console.panels.LoggerCategoryPanel;
- import org.apache.syncope.client.console.panels.SelectedEventsPanel;
- import org.apache.syncope.client.console.rest.LoggerRestClient;
- import org.apache.syncope.client.console.wicket.ajax.markup.html.ClearIndicatingAjaxLink;
- import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.ActionColumn;
- import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.DatePropertyColumn;
- import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
- import org.apache.syncope.client.console.wicket.markup.html.form.ActionLinksPanel;
- import org.apache.syncope.common.lib.SyncopeClientException;
- import org.apache.syncope.common.lib.to.EventCategoryTO;
- import org.apache.syncope.common.lib.to.ReportTO;
- import org.apache.syncope.common.lib.types.AuditElements.Result;
- import org.apache.syncope.common.lib.types.AuditLoggerName;
++import java.util.Map;
++import org.apache.syncope.common.to.EventCategoryTO;
++import org.apache.syncope.common.to.ReportTO;
++import org.apache.syncope.common.types.AuditElements.Result;
++import org.apache.syncope.common.types.AuditLoggerName;
++import org.apache.syncope.common.util.LoggerEventUtils;
++import org.apache.syncope.common.SyncopeClientException;
++import org.apache.syncope.console.commons.Constants;
++import org.apache.syncope.console.commons.PreferenceManager;
++import org.apache.syncope.console.commons.SortableDataProviderComparator;
++import org.apache.syncope.console.pages.panels.LoggerCategoryPanel;
++import org.apache.syncope.console.pages.panels.SelectedEventsPanel;
++import org.apache.syncope.console.rest.LoggerRestClient;
++import org.apache.syncope.console.wicket.ajax.markup.html.ClearIndicatingAjaxLink;
++import org.apache.syncope.console.wicket.extensions.markup.html.repeater.data.table.ActionColumn;
++import org.apache.syncope.console.wicket.extensions.markup.html.repeater.data.table.DatePropertyColumn;
++import org.apache.syncope.console.wicket.extensions.markup.html.repeater.data.table.JobColumn;
++import org.apache.syncope.console.wicket.markup.html.form.ActionLink;
++import org.apache.syncope.console.wicket.markup.html.form.ActionLinksPanel;
 +import org.apache.wicket.Component;
 +import org.apache.wicket.Page;
 +import org.apache.wicket.ajax.AjaxRequestTarget;
 +import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
 +import org.apache.wicket.ajax.markup.html.AjaxLink;
 +import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
 +import org.apache.wicket.event.IEvent;
 +import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
 +import org.apache.wicket.extensions.ajax.markup.html.repeater.data.table.AjaxFallbackDefaultDataTable;
 +import org.apache.wicket.extensions.markup.html.repeater.data.sort.SortOrder;
 +import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
 +import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
 +import org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider;
 +import org.apache.wicket.markup.html.WebMarkupContainer;
 +import org.apache.wicket.markup.html.form.DropDownChoice;
 +import org.apache.wicket.markup.html.form.Form;
 +import org.apache.wicket.model.AbstractReadOnlyModel;
 +import org.apache.wicket.model.IModel;
 +import org.apache.wicket.model.Model;
 +import org.apache.wicket.model.PropertyModel;
 +import org.apache.wicket.model.ResourceModel;
++import org.apache.wicket.model.StringResourceModel;
 +import org.apache.wicket.model.util.ListModel;
 +import org.apache.wicket.request.mapper.parameter.PageParameters;
 +import org.apache.wicket.spring.injection.annot.SpringBean;
 +import org.springframework.util.CollectionUtils;
 +
 +/**
 + * Auditing and Reporting.
 + */
 +public class Reports extends BasePage {
 +
 +    private static final long serialVersionUID = -2071214196989178694L;
 +
 +    private static final int WIN_HEIGHT = 500;
 +
 +    private static final int WIN_WIDTH = 700;
 +
 +    @SpringBean
 +    private LoggerRestClient loggerRestClient;
 +
 +    @SpringBean
 +    private PreferenceManager prefMan;
 +
 +    private WebMarkupContainer reportContainer;
 +
 +    private WebMarkupContainer auditContainer;
 +
 +    private int paginatorRows;
 +
 +    private final ModalWindow window;
 +
 +    public Reports(final PageParameters parameters) {
 +        super(parameters);
 +
 +        window = new ModalWindow("reportWin");
 +        window.setCssClassName(ModalWindow.CSS_CLASS_GRAY);
 +        window.setInitialHeight(WIN_HEIGHT);
 +        window.setInitialWidth(WIN_WIDTH);
 +        window.setCookieName("view-report-win");
 +        add(window);
 +
 +        setupReport();
 +        setupAudit();
 +    }
 +
 +    private void setupReport() {
 +        reportContainer = new WebMarkupContainer("reportContainer");
 +        setWindowClosedCallback(window, reportContainer);
 +
 +        MetaDataRoleAuthorizationStrategy.authorize(reportContainer, RENDER,
 +                xmlRolesReader.getEntitlement("Reports", "list"));
 +
 +        paginatorRows = prefMan.getPaginatorRows(getRequest(), Constants.PREF_REPORT_PAGINATOR_ROWS);
 +
-         List<IColumn<ReportTO, String>> columns = new ArrayList<>();
-         columns.add(new PropertyColumn<ReportTO, String>(new ResourceModel("key"), "key", "key"));
++        List<IColumn<ReportTO, String>> columns = new ArrayList<IColumn<ReportTO, String>>();
++        columns.add(new PropertyColumn<ReportTO, String>(new ResourceModel("id"), "id", "id"));
 +        columns.add(new PropertyColumn<ReportTO, String>(new ResourceModel("name"), "name", "name"));
 +        columns.add(new DatePropertyColumn<ReportTO>(new ResourceModel("lastExec"), "lastExec", "lastExec"));
 +        columns.add(new DatePropertyColumn<ReportTO>(new ResourceModel("nextExec"), "nextExec", "nextExec"));
 +        columns.add(new DatePropertyColumn<ReportTO>(new ResourceModel("startDate"), "startDate", "startDate"));
 +        columns.add(new DatePropertyColumn<ReportTO>(new ResourceModel("endDate"), "endDate", "endDate"));
 +        columns.add(new PropertyColumn<ReportTO, String>(
 +                new ResourceModel("latestExecStatus"), "latestExecStatus", "latestExecStatus"));
++        columns.add(new JobColumn<ReportTO, String>(new StringResourceModel("", this, null, ""), "runtime",
++                getPageReference(), reportRestClient));
 +        columns.add(new ActionColumn<ReportTO, String>(new ResourceModel("actions", "")) {
 +
 +            private static final long serialVersionUID = 2054811145491901166L;
 +
 +            @Override
 +            public ActionLinksPanel getActions(final String componentId, final IModel<ReportTO> model) {
 +
 +                final ReportTO reportTO = model.getObject();
 +
 +                final ActionLinksPanel panel = new ActionLinksPanel(componentId, model, getPageReference());
 +
 +                panel.add(new ActionLink() {
 +
 +                    private static final long serialVersionUID = -3722207913631435501L;
 +
 +                    @Override
 +                    public void onClick(final AjaxRequestTarget target) {
 +
 +                        window.setPageCreator(new ModalWindow.PageCreator() {
 +
 +                            private static final long serialVersionUID = -7834632442532690940L;
 +
 +                            @Override
 +                            public Page createPage() {
 +                                return new ReportModalPage(window, reportTO, Reports.this.getPageReference());
 +                            }
 +                        });
 +
 +                        window.show(target);
 +                    }
 +                }, ActionLink.ActionType.EDIT, "Reports");
 +
 +                panel.add(new ActionLink() {
 +
 +                    private static final long serialVersionUID = -3722207913631435501L;
 +
 +                    @Override
 +                    public void onClick(final AjaxRequestTarget target) {
 +                        try {
-                             reportRestClient.startExecution(reportTO.getKey());
++                            reportRestClient.startExecution(reportTO.getId());
 +                            getSession().info(getString(Constants.OPERATION_SUCCEEDED));
 +                        } catch (SyncopeClientException scce) {
 +                            error(scce.getMessage());
 +                        }
 +
 +                        feedbackPanel.refresh(target);
 +                        target.add(reportContainer);
 +                    }
 +                }, ActionLink.ActionType.EXECUTE, "Reports");
 +
 +                panel.add(new ActionLink() {
 +
 +                    private static final long serialVersionUID = -3722207913631435501L;
 +
 +                    @Override
 +                    public void onClick(final AjaxRequestTarget target) {
 +                        try {
-                             reportRestClient.delete(reportTO.getKey());
++                            reportRestClient.delete(reportTO.getId());
 +                            info(getString(Constants.OPERATION_SUCCEEDED));
 +                        } catch (SyncopeClientException scce) {
 +                            error(scce.getMessage());
 +                        }
 +                        target.add(reportContainer);
 +                        feedbackPanel.refresh(target);
 +                    }
 +                }, ActionLink.ActionType.DELETE, "Reports");
 +
 +                return panel;
 +            }
 +
 +            @Override
 +            public Component getHeader(final String componentId) {
 +                final ActionLinksPanel panel = new ActionLinksPanel(componentId, new Model(), getPageReference());
 +
 +                panel.add(new ActionLink() {
 +
 +                    private static final long serialVersionUID = -7978723352517770644L;
 +
 +                    @Override
 +                    public void onClick(final AjaxRequestTarget target) {
 +                        if (target != null) {
 +                            target.add(reportContainer);
 +                        }
 +                    }
 +                }, ActionLink.ActionType.RELOAD, TASKS, "list");
 +
 +                return panel;
 +            }
 +        });
 +
 +        final AjaxFallbackDefaultDataTable<ReportTO, String> reportTable =
-                 new AjaxFallbackDefaultDataTable<>("reportTable", columns, new ReportProvider(), paginatorRows);
++                new AjaxFallbackDefaultDataTable<ReportTO, String>(
++                        "reportTable", columns, new ReportProvider(), paginatorRows);
 +
 +        reportContainer.add(reportTable);
 +        reportContainer.setOutputMarkupId(true);
 +
 +        add(reportContainer);
 +
 +        @SuppressWarnings("rawtypes")
 +        Form paginatorForm = new Form("paginatorForm");
 +
 +        MetaDataRoleAuthorizationStrategy.authorize(paginatorForm, RENDER,
 +                xmlRolesReader.getEntitlement("Reports", "list"));
 +
 +        @SuppressWarnings({ "unchecked", "rawtypes" })
 +        final DropDownChoice rowsChooser = new DropDownChoice("rowsChooser", new PropertyModel(this, "paginatorRows"),
 +                prefMan.getPaginatorChoices());
 +
 +        rowsChooser.add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
 +
 +            private static final long serialVersionUID = -1107858522700306810L;
 +
 +            @Override
 +            protected void onUpdate(final AjaxRequestTarget target) {
 +                prefMan.set(getRequest(), getResponse(), Constants.PREF_REPORT_PAGINATOR_ROWS,
 +                        String.valueOf(paginatorRows));
 +                reportTable.setItemsPerPage(paginatorRows);
 +
 +                target.add(reportContainer);
 +            }
 +        });
 +
 +        paginatorForm.add(rowsChooser);
 +        add(paginatorForm);
 +
-         AjaxLink<Void> createLink = new ClearIndicatingAjaxLink<Void>("createLink", getPageReference()) {
++        AjaxLink createLink = new ClearIndicatingAjaxLink("createLink", getPageReference()) {
 +
 +            private static final long serialVersionUID = -7978723352517770644L;
 +
 +            @Override
 +            protected void onClickInternal(final AjaxRequestTarget target) {
 +                window.setPageCreator(new ModalWindow.PageCreator() {
 +
 +                    private static final long serialVersionUID = -7834632442532690940L;
 +
 +                    @Override
 +                    public Page createPage() {
 +                        return new ReportModalPage(window, new ReportTO(), Reports.this.getPageReference());
 +                    }
 +                });
 +
 +                window.show(target);
 +            }
 +        };
 +
 +        MetaDataRoleAuthorizationStrategy.authorize(createLink, RENDER, xmlRolesReader.getEntitlement("Reports",
 +                "create"));
 +
 +        add(createLink);
 +    }
 +
 +    @SuppressWarnings("rawtypes")
 +    private void setupAudit() {
 +        auditContainer = new WebMarkupContainer("auditContainer");
 +        auditContainer.setOutputMarkupId(true);
 +        add(auditContainer);
 +
 +        MetaDataRoleAuthorizationStrategy.authorize(
 +                auditContainer, RENDER, xmlRolesReader.getEntitlement("Audit", "list"));
 +
 +        final Form form = new Form("auditForm");
 +        auditContainer.add(form);
 +
-         final List<String> events = new ArrayList<>();
++        final List<String> events = new ArrayList<String>();
 +
 +        final List<AuditLoggerName> audits = loggerRestClient.listAudits();
 +        for (AuditLoggerName audit : audits) {
-             events.add(AuditLoggerName.buildEvent(
++            events.add(LoggerEventUtils.buildEvent(
 +                    audit.getType(),
 +                    audit.getCategory(),
 +                    audit.getSubcategory(),
 +                    audit.getEvent(),
 +                    audit.getResult()));
 +        }
 +
-         final ListModel<String> model = new ListModel<>(new ArrayList<>(events));
++        final ListModel<String> model = new ListModel<String>(new ArrayList<String>(events));
 +
 +        form.add(new LoggerCategoryPanel(
 +                "events", loggerRestClient.listEvents(), model, getPageReference(), "Reports") {
 +
 +                    private static final long serialVersionUID = 6113164334533550277L;
 +
 +                    @Override
 +                    protected String[] getListRoles() {
 +                        return new String[] {
 +                            xmlRolesReader.getEntitlement("Audit", "list")
 +                        };
 +                    }
 +
 +                    @Override
 +                    protected String[] getChangeRoles() {
 +                        return new String[] {
 +                            xmlRolesReader.getEntitlement("Audit", "enable"),
 +                            xmlRolesReader.getEntitlement("Audit", "disable")
 +                        };
 +                    }
 +
 +                    @Override
 +                    public void onEventAction(final IEvent<?> event) {
 +                        if (event.getPayload() instanceof SelectedEventsPanel.EventSelectionChanged) {
 +
 +                            final SelectedEventsPanel.EventSelectionChanged eventSelectionChanged =
 +                            (SelectedEventsPanel.EventSelectionChanged) event.getPayload();
 +
 +                            for (String toBeRemoved : eventSelectionChanged.getToBeRemoved()) {
 +                                if (events.contains(toBeRemoved)) {
-                                     Pair<EventCategoryTO, Result> eventCategory =
-                                     AuditLoggerName.parseEventCategory(toBeRemoved);
++                                    final Map.Entry<EventCategoryTO, Result> eventCategory =
++                                    LoggerEventUtils.parseEventCategory(toBeRemoved);
 +
 +                                    final AuditLoggerName auditLoggerName = new AuditLoggerName(
 +                                            eventCategory.getKey().getType(),
 +                                            eventCategory.getKey().getCategory(),
 +                                            eventCategory.getKey().getSubcategory(),
 +                                            CollectionUtils.isEmpty(eventCategory.getKey().getEvents())
 +                                                    ? null : eventCategory.getKey().getEvents().iterator().next(),
 +                                            eventCategory.getValue());
 +
 +                                    loggerRestClient.disableAudit(auditLoggerName);
 +                                    events.remove(toBeRemoved);
 +                                }
 +                            }
 +
 +                            for (String toBeAdded : eventSelectionChanged.getToBeAdded()) {
 +                                if (!events.contains(toBeAdded)) {
-                                     Pair<EventCategoryTO, Result> eventCategory =
-                                     AuditLoggerName.parseEventCategory(toBeAdded);
++                                    final Map.Entry<EventCategoryTO, Result> eventCategory =
++                                    LoggerEventUtils.parseEventCategory(toBeAdded);
 +
 +                                    final AuditLoggerName auditLoggerName = new AuditLoggerName(
 +                                            eventCategory.getKey().getType(),
 +                                            eventCategory.getKey().getCategory(),
 +                                            eventCategory.getKey().getSubcategory(),
 +                                            CollectionUtils.isEmpty(eventCategory.getKey().getEvents())
 +                                                    ? null : eventCategory.getKey().getEvents().iterator().next(),
 +                                            eventCategory.getValue());
 +
 +                                    loggerRestClient.enableAudit(auditLoggerName);
 +                                    events.add(toBeAdded);
 +                                }
 +                            }
 +                        }
 +                    }
 +                });
 +    }
 +
 +    private class ReportProvider extends SortableDataProvider<ReportTO, String> {
 +
 +        private static final long serialVersionUID = -2311716167583335852L;
 +
 +        private final SortableDataProviderComparator<ReportTO> comparator;
 +
 +        public ReportProvider() {
 +            super();
 +
 +            //Default sorting
-             setSort("key", SortOrder.ASCENDING);
-             comparator = new SortableDataProviderComparator<>(this);
++            setSort("id", SortOrder.ASCENDING);
++            comparator = new SortableDataProviderComparator<ReportTO>(this);
 +        }
 +
 +        @Override
 +        public Iterator<ReportTO> iterator(final long first, final long count) {
 +            final int page = ((int) first / paginatorRows);
 +
 +            final List<ReportTO> list =
 +                    reportRestClient.list((page < 0 ? 0 : page) + 1, paginatorRows, getSort());
 +            Collections.sort(list, comparator);
 +            return list.iterator();
 +        }
 +
 +        @Override
 +        public long size() {
 +            return reportRestClient.count();
 +        }
 +
 +        @Override
 +        public IModel<ReportTO> model(final ReportTO configuration) {
 +
 +            return new AbstractReadOnlyModel<ReportTO>() {
 +
 +                private static final long serialVersionUID = 4921104837546595602L;
 +
 +                @Override
 +                public ReportTO getObject() {
 +                    return configuration;
 +                }
 +            };
 +        }
 +    }
++    /**
++     * IndicatorMarkupId behaviour is embedded in Reports.html
++     */
++    @Override
++    public String getAjaxIndicatorMarkupId() {
++        return "";
++    }
 +}

http://git-wip-us.apache.org/repos/asf/syncope/blob/34a0422a/client/old_console/src/main/java/org/apache/syncope/client/console/pages/Tasks.java
----------------------------------------------------------------------
diff --cc client/old_console/src/main/java/org/apache/syncope/client/console/pages/Tasks.java
index 296c365,0000000..11819c6
mode 100644,000000..100644
--- a/client/old_console/src/main/java/org/apache/syncope/client/console/pages/Tasks.java
+++ b/client/old_console/src/main/java/org/apache/syncope/client/console/pages/Tasks.java
@@@ -1,230 -1,0 +1,239 @@@
 +/*
 + * 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.pages;
++package org.apache.syncope.console.pages;
 +
 +import java.util.ArrayList;
 +import java.util.Arrays;
 +import java.util.Collections;
 +import java.util.Comparator;
 +import java.util.Iterator;
 +import java.util.List;
- import org.apache.syncope.client.console.commons.SortableDataProviderComparator;
- import org.apache.syncope.client.console.panels.AjaxDataTablePanel;
- import org.apache.syncope.client.console.panels.NotificationTasks;
- import org.apache.syncope.client.console.panels.PropagationTasks;
- import org.apache.syncope.client.console.panels.PushTasksPanel;
- import org.apache.syncope.client.console.panels.SchedTasks;
- import org.apache.syncope.client.console.panels.SyncTasksPanel;
- import org.apache.syncope.client.console.rest.BaseRestClient;
- import org.apache.syncope.client.console.rest.TaskRestClient;
- import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
- import org.apache.syncope.common.lib.to.AbstractTaskTO;
- import org.apache.syncope.common.lib.to.SchedTaskTO;
- import org.apache.syncope.common.lib.to.TaskExecTO;
++import org.apache.syncope.common.to.SchedTaskTO;
++import org.apache.syncope.common.to.TaskExecTO;
++import org.apache.syncope.common.to.AbstractTaskTO;
++import org.apache.syncope.console.commons.SortableDataProviderComparator;
++import org.apache.syncope.console.pages.panels.AjaxDataTablePanel;
++import org.apache.syncope.console.pages.panels.NotificationTasks;
++import org.apache.syncope.console.pages.panels.PropagationTasks;
++import org.apache.syncope.console.pages.panels.SchedTasks;
++import org.apache.syncope.console.pages.panels.PushTasksPanel;
++import org.apache.syncope.console.pages.panels.SyncTasksPanel;
++import org.apache.syncope.console.rest.BaseRestClient;
++import org.apache.syncope.console.rest.TaskRestClient;
++import org.apache.syncope.console.wicket.markup.html.form.ActionLink;
 +import org.apache.wicket.PageReference;
 +import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
 +import org.apache.wicket.extensions.markup.html.repeater.data.sort.SortOrder;
 +import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
 +import org.apache.wicket.extensions.markup.html.repeater.data.table.ISortableDataProvider;
 +import org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider;
 +import org.apache.wicket.markup.html.WebMarkupContainer;
 +import org.apache.wicket.model.AbstractReadOnlyModel;
 +import org.apache.wicket.model.CompoundPropertyModel;
 +import org.apache.wicket.model.IModel;
 +
 +public class Tasks extends BasePage {
 +
 +    private static final long serialVersionUID = 5289215853622289061L;
 +
 +    public Tasks() {
 +        super();
 +
 +        add(new PropagationTasks("propagation", getPageReference()));
 +        add(new NotificationTasks("notification", getPageReference()));
 +        add(new SchedTasks("sched", getPageReference()));
 +        add(new SyncTasksPanel("sync", getPageReference()));
 +        add(new PushTasksPanel("push", getPageReference()));
 +
 +        getPageReference();
 +    }
 +
 +    @Override
 +    public void setWindowClosedCallback(final ModalWindow window, final WebMarkupContainer container) {
 +
 +        super.setWindowClosedCallback(window, container);
 +    }
 +
 +    public static class TaskExecutionsProvider extends SortableDataProvider<TaskExecTO, String> {
 +
 +        private static final long serialVersionUID = -5401263348984206145L;
 +
 +        private SortableDataProviderComparator<TaskExecTO> comparator;
 +
 +        private AbstractTaskTO taskTO;
 +
 +        public TaskExecutionsProvider(final AbstractTaskTO taskTO) {
 +            super();
 +
 +            //Default sorting
 +            this.taskTO = taskTO;
 +            setSort("startDate", SortOrder.DESCENDING);
 +            comparator = new SortableDataProviderComparator<TaskExecTO>(this);
 +        }
 +
 +        @Override
 +        public Iterator<TaskExecTO> iterator(final long first, final long count) {
 +
 +            List<TaskExecTO> list = getTaskDB();
 +
 +            Collections.sort(list, comparator);
 +
 +            return list.subList((int) first, (int) first + (int) count).iterator();
 +        }
 +
 +        @Override
 +        public long size() {
 +            return getTaskDB().size();
 +        }
 +
 +        @Override
 +        public IModel<TaskExecTO> model(final TaskExecTO taskExecution) {
 +
 +            return new AbstractReadOnlyModel<TaskExecTO>() {
 +
 +                private static final long serialVersionUID = 7485475149862342421L;
 +
 +                @Override
 +                public TaskExecTO getObject() {
 +                    return taskExecution;
 +                }
 +            };
 +        }
 +
 +        public List<TaskExecTO> getTaskDB() {
 +            return taskTO.getExecutions();
 +        }
 +    }
 +
 +    public static class TasksProvider<T extends AbstractTaskTO> extends SortableDataProvider<T, String> {
 +
 +        private static final long serialVersionUID = -20112718133295756L;
 +
 +        private SortableDataProviderComparator<T> comparator;
 +
 +        private TaskRestClient restClient;
 +
 +        private int paginatorRows;
 +
 +        private String id;
 +
 +        private Class<T> reference;
 +
 +        public TasksProvider(
 +                final TaskRestClient restClient, final int paginatorRows, final String id, final Class<T> reference) {
 +
 +            super();
 +
 +            //Default sorting
-             setSort("key", SortOrder.DESCENDING);
-             comparator = new SortableDataProviderComparator<>(this);
++            setSort("id", SortOrder.DESCENDING);
++            comparator = new SortableDataProviderComparator<T>(this);
 +            this.paginatorRows = paginatorRows;
 +            this.restClient = restClient;
 +            this.id = id;
 +            this.reference = reference;
 +        }
 +
 +        @Override
 +        public Iterator<T> iterator(final long first, final long count) {
-             final List<T> tasks = new ArrayList<>();
++            final List<T> tasks = new ArrayList<T>();
 +
 +            final int page = ((int) first / paginatorRows);
 +
 +            for (T task : restClient.list(reference, (page < 0 ? 0 : page) + 1, paginatorRows, getSort())) {
 +                if (task instanceof SchedTaskTO && ((SchedTaskTO) task).getLastExec() == null
 +                        && task.getExecutions() != null && !task.getExecutions().isEmpty()) {
 +
 +                    Collections.sort(task.getExecutions(), new Comparator<TaskExecTO>() {
 +
 +                        @Override
 +                        public int compare(final TaskExecTO left, final TaskExecTO right) {
 +                            return left.getStartDate().compareTo(right.getStartDate());
 +                        }
 +                    });
 +
 +                    ((SchedTaskTO) task).setLastExec(task.getExecutions().get(task.getExecutions().size() - 1).
 +                            getStartDate());
 +                }
 +                tasks.add(task);
 +            }
 +
 +            Collections.sort(tasks, comparator);
 +            return tasks.iterator();
 +        }
 +
 +        @Override
 +        public long size() {
 +            return restClient.count(id);
 +        }
 +
 +        @Override
 +        public IModel<T> model(final T object) {
-             return new CompoundPropertyModel<>(object);
++            return new CompoundPropertyModel<T>(object);
 +        }
 +    }
 +
 +    /**
 +     * Update task table.
 +     *
 +     * @param columns columns.
 +     * @param dataProvider data provider.
 +     * @param container container.
 +     * @param currentPage current page index.
 +     * @param pageRef page reference
 +     * @param restClient syncope base rest client
 +     * @return data table.
 +     */
 +    public static AjaxDataTablePanel<AbstractTaskTO, String> updateTaskTable(
 +            final List<IColumn<AbstractTaskTO, String>> columns,
 +            final TasksProvider<? extends AbstractTaskTO> dataProvider,
 +            final WebMarkupContainer container,
 +            final int currentPage,
 +            final PageReference pageRef,
 +            final BaseRestClient restClient) {
 +
 +        @SuppressWarnings("unchecked")
-         final AjaxDataTablePanel<AbstractTaskTO, String> table = new AjaxDataTablePanel<>(
++        final AjaxDataTablePanel<AbstractTaskTO, String> table = new AjaxDataTablePanel<AbstractTaskTO, String>(
 +                "datatable",
 +                columns,
 +                (ISortableDataProvider<AbstractTaskTO, String>) dataProvider,
 +                dataProvider.paginatorRows,
 +                Arrays.asList(new ActionLink.ActionType[] {
 +                    ActionLink.ActionType.DELETE, ActionLink.ActionType.DRYRUN, ActionLink.ActionType.EXECUTE }),
 +                restClient,
-                 "key",
++                "id",
 +                TASKS,
 +                pageRef);
 +
 +        table.setCurrentPage(currentPage);
 +        table.setOutputMarkupId(true);
 +
 +        container.addOrReplace(table);
 +
 +        return table;
 +    }
++
++    /**
++     * IndicatorMarkupId behaviour is embedded in Tasks.html
++     */
++    @Override
++    public String getAjaxIndicatorMarkupId() {
++        return "";
++    }
++
 +}

http://git-wip-us.apache.org/repos/asf/syncope/blob/34a0422a/client/old_console/src/main/java/org/apache/syncope/client/console/panels/NotificationTasks.java
----------------------------------------------------------------------
diff --cc client/old_console/src/main/java/org/apache/syncope/client/console/panels/NotificationTasks.java
index d7f52e1,0000000..9c7b458
mode 100644,000000..100644
--- a/client/old_console/src/main/java/org/apache/syncope/client/console/panels/NotificationTasks.java
+++ b/client/old_console/src/main/java/org/apache/syncope/client/console/panels/NotificationTasks.java
@@@ -1,254 -1,0 +1,258 @@@
 +/*
 + * 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.panels;
++package org.apache.syncope.console.pages.panels;
 +
 +import java.util.ArrayList;
 +import java.util.List;
- import org.apache.syncope.client.console.commons.Constants;
- import org.apache.syncope.client.console.pages.NotificationTaskModalPage;
- import org.apache.syncope.client.console.pages.Tasks;
- import org.apache.syncope.client.console.pages.Tasks.TasksProvider;
- import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.ActionColumn;
- import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
- import org.apache.syncope.client.console.wicket.markup.html.form.ActionLinksPanel;
- import org.apache.syncope.common.lib.SyncopeClientException;
- import org.apache.syncope.common.lib.to.AbstractTaskTO;
- import org.apache.syncope.common.lib.to.NotificationTaskTO;
++import org.apache.syncope.common.to.NotificationTaskTO;
++import org.apache.syncope.common.to.AbstractTaskTO;
++import org.apache.syncope.common.SyncopeClientException;
++import org.apache.syncope.console.commons.Constants;
++import org.apache.syncope.console.pages.NotificationTaskModalPage;
++import org.apache.syncope.console.pages.Tasks;
++import org.apache.syncope.console.pages.Tasks.TasksProvider;
++import org.apache.syncope.console.wicket.extensions.markup.html.repeater.data.table.ActionColumn;
++import org.apache.syncope.console.wicket.extensions.markup.html.repeater.data.table.JobColumn;
++import org.apache.syncope.console.wicket.markup.html.form.ActionLink;
++import org.apache.syncope.console.wicket.markup.html.form.ActionLinksPanel;
 +import org.apache.wicket.Component;
 +import org.apache.wicket.Page;
 +import org.apache.wicket.PageReference;
 +import org.apache.wicket.ajax.AjaxRequestTarget;
 +import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
 +import org.apache.wicket.event.IEvent;
 +import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
 +import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
 +import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
 +import org.apache.wicket.markup.html.WebMarkupContainer;
 +import org.apache.wicket.markup.html.form.DropDownChoice;
 +import org.apache.wicket.markup.html.form.Form;
 +import org.apache.wicket.model.IModel;
 +import org.apache.wicket.model.Model;
 +import org.apache.wicket.model.PropertyModel;
 +import org.apache.wicket.model.StringResourceModel;
 +import org.apache.wicket.request.http.WebResponse;
 +
 +public class NotificationTasks extends AbstractTasks {
 +
 +    private static final long serialVersionUID = 4984337552918213290L;
 +
 +    private int paginatorRows;
 +
 +    private WebMarkupContainer container;
 +
 +    private boolean operationResult = false;
 +
 +    private ModalWindow window;
 +
 +    private AjaxDataTablePanel<AbstractTaskTO, String> table;
 +
 +    public NotificationTasks(final String id, final PageReference pageRef) {
 +        super(id, pageRef);
 +
 +        container = new WebMarkupContainer("container");
 +        container.setOutputMarkupId(true);
 +        add(container);
 +
 +        add(window = new ModalWindow("taskWin"));
 +
 +        paginatorRows = prefMan.getPaginatorRows(getWebRequest(), Constants.PREF_NOTIFICATION_TASKS_PAGINATOR_ROWS);
 +
 +        table = Tasks.updateTaskTable(
 +                getColumns(),
 +                new TasksProvider<NotificationTaskTO>(restClient, paginatorRows, getId(), NotificationTaskTO.class),
 +                container,
 +                0,
 +                pageRef,
 +                restClient);
 +
 +        container.add(table);
 +
 +        window.setWindowClosedCallback(new ModalWindow.WindowClosedCallback() {
 +
 +            private static final long serialVersionUID = 8804221891699487139L;
 +
 +            @Override
 +            public void onClose(final AjaxRequestTarget target) {
 +                target.add(container);
 +                if (operationResult) {
 +                    info(getString(Constants.OPERATION_SUCCEEDED));
 +                    target.add(getPage().get(Constants.FEEDBACK));
 +                    operationResult = false;
 +                }
 +            }
 +        });
 +
 +        window.setCssClassName(ModalWindow.CSS_CLASS_GRAY);
 +        window.setInitialHeight(WIN_HEIGHT);
 +        window.setInitialWidth(WIN_WIDTH);
 +        window.setCookieName(VIEW_TASK_WIN_COOKIE_NAME);
 +
 +        @SuppressWarnings("rawtypes")
 +        final Form paginatorForm = new Form("PaginatorForm");
 +
 +        @SuppressWarnings({ "unchecked", "rawtypes" })
 +        final DropDownChoice rowsChooser = new DropDownChoice("rowsChooser", new PropertyModel(this, "paginatorRows"),
 +                prefMan.getPaginatorChoices());
 +
 +        rowsChooser.add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
 +
 +            private static final long serialVersionUID = -1107858522700306810L;
 +
 +            @Override
 +            protected void onUpdate(final AjaxRequestTarget target) {
 +                prefMan.set(getWebRequest(), (WebResponse) getResponse(),
 +                        Constants.PREF_NOTIFICATION_TASKS_PAGINATOR_ROWS, String.valueOf(paginatorRows));
 +
 +                table = Tasks.updateTaskTable(
 +                        getColumns(),
 +                        new TasksProvider<NotificationTaskTO>(restClient, paginatorRows, getId(),
 +                                NotificationTaskTO.class),
 +                        container,
 +                        table == null ? 0 : (int) table.getCurrentPage(),
 +                        pageRef,
 +                        restClient);
 +
 +                target.add(container);
 +            }
 +        });
 +
 +        paginatorForm.add(rowsChooser);
 +        add(paginatorForm);
 +    }
 +
 +    private List<IColumn<AbstractTaskTO, String>> getColumns() {
-         final List<IColumn<AbstractTaskTO, String>> columns = new ArrayList<>();
++        final List<IColumn<AbstractTaskTO, String>> columns = new ArrayList<IColumn<AbstractTaskTO, String>>();
 +
 +        columns.add(new PropertyColumn<AbstractTaskTO, String>(
-                 new StringResourceModel("key", this, null), "key", "key"));
++                new StringResourceModel("id", this, null), "id", "id"));
 +        columns.add(new PropertyColumn<AbstractTaskTO, String>(
 +                new StringResourceModel("sender", this, null), "sender", "sender"));
 +        columns.add(new PropertyColumn<AbstractTaskTO, String>(
 +                new StringResourceModel("recipients", this, null), "recipients", "recipients"));
 +        columns.add(new PropertyColumn<AbstractTaskTO, String>(
 +                new StringResourceModel("subject", this, null), "subject", "subject"));
 +        columns.add(new PropertyColumn<AbstractTaskTO, String>(
 +                new StringResourceModel("traceLevel", this, null), "traceLevel", "traceLevel"));
 +        columns.add(new PropertyColumn<AbstractTaskTO, String>(
 +                new StringResourceModel("latestExecStatus", this, null), "latestExecStatus", "latestExecStatus"));
 +
++        columns.add(new JobColumn<AbstractTaskTO, String>(new StringResourceModel("", this, null, ""), "runtime",
++                pageRef, restClient)); 
++
 +        columns.add(new ActionColumn<AbstractTaskTO, String>(new StringResourceModel("actions", this, null, "")) {
 +
 +            private static final long serialVersionUID = 2054811145491901166L;
 +
 +            @Override
 +            public ActionLinksPanel getActions(final String componentId, final IModel<AbstractTaskTO> model) {
 +
 +                final AbstractTaskTO taskTO = model.getObject();
 +
 +                final ActionLinksPanel panel = new ActionLinksPanel(componentId, model, pageRef);
 +
 +                panel.add(new ActionLink() {
 +
 +                    private static final long serialVersionUID = -3722207913631435501L;
 +
 +                    @Override
 +                    public void onClick(final AjaxRequestTarget target) {
 +
 +                        window.setPageCreator(new ModalWindow.PageCreator() {
 +
 +                            private static final long serialVersionUID = -7834632442532690940L;
 +
 +                            @Override
 +                            public Page createPage() {
 +                                return new NotificationTaskModalPage(taskTO);
 +                            }
 +                        });
 +
 +                        window.show(target);
 +                    }
 +                }, ActionLink.ActionType.EDIT, TASKS);
 +
 +                panel.add(new ActionLink() {
 +
 +                    private static final long serialVersionUID = -3722207913631435501L;
 +
 +                    @Override
 +                    public void onClick(final AjaxRequestTarget target) {
 +                        try {
-                             restClient.startExecution(taskTO.getKey(), false);
++                            restClient.startExecution(taskTO.getId(), false);
 +                            getSession().info(getString(Constants.OPERATION_SUCCEEDED));
 +                        } catch (SyncopeClientException scce) {
 +                            error(scce.getMessage());
 +                        }
 +
 +                        ((NotificationPanel) getPage().get(Constants.FEEDBACK)).refresh(target);
 +                        target.add(container);
 +                    }
 +                }, ActionLink.ActionType.EXECUTE, TASKS);
 +
 +                panel.add(new ActionLink() {
 +
 +                    private static final long serialVersionUID = -3722207913631435501L;
 +
 +                    @Override
 +                    public void onClick(final AjaxRequestTarget target) {
 +                        try {
-                             restClient.delete(taskTO.getKey(), NotificationTaskTO.class);
++                            restClient.delete(taskTO.getId(), NotificationTaskTO.class);
 +                            info(getString(Constants.OPERATION_SUCCEEDED));
 +                        } catch (SyncopeClientException scce) {
 +                            error(scce.getMessage());
 +                        }
 +                        target.add(container);
 +                        ((NotificationPanel) getPage().get(Constants.FEEDBACK)).refresh(target);
 +                    }
 +                }, ActionLink.ActionType.DELETE, TASKS);
 +
 +                return panel;
 +            }
 +
 +            @Override
 +            public Component getHeader(String componentId) {
 +                final ActionLinksPanel panel = new ActionLinksPanel(componentId, new Model(), pageRef);
 +
 +                panel.add(new ActionLink() {
 +
 +                    private static final long serialVersionUID = -7978723352517770644L;
 +
 +                    @Override
 +                    public void onClick(final AjaxRequestTarget target) {
 +                        if (target != null) {
 +                            target.add(table);
 +                        }
 +                    }
 +                }, ActionLink.ActionType.RELOAD, TASKS, "list");
 +
 +                return panel;
 +            }
 +        });
 +
 +        return columns;
 +    }
 +
 +    @Override
 +    public void onEvent(final IEvent<?> event) {
 +        if (event.getPayload() instanceof AbstractSearchResultPanel.EventDataWrapper) {
 +            ((AbstractSearchResultPanel.EventDataWrapper) event.getPayload()).getTarget().add(container);
 +        }
 +    }
 +}

http://git-wip-us.apache.org/repos/asf/syncope/blob/34a0422a/client/old_console/src/main/java/org/apache/syncope/client/console/panels/RuntimePanel.java
----------------------------------------------------------------------
diff --cc client/old_console/src/main/java/org/apache/syncope/client/console/panels/RuntimePanel.java
index 0000000,0000000..34e058e
new file mode 100644
--- /dev/null
+++ b/client/old_console/src/main/java/org/apache/syncope/client/console/panels/RuntimePanel.java
@@@ -1,0 -1,0 +1,105 @@@
++/*
++ * 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.panels;
++
++import org.apache.syncope.client.console.rest.JobRestClient;
++import org.apache.syncope.console.wicket.ajax.markup.html.ClearIndicatingAjaxLink;
++import org.apache.wicket.PageReference;
++import org.apache.wicket.ajax.AbstractAjaxTimerBehavior;
++import org.apache.wicket.ajax.AjaxRequestTarget;
++import org.apache.wicket.markup.html.panel.Fragment;
++import org.apache.wicket.model.IModel;
++import org.apache.wicket.markup.html.panel.Panel;
++
++public class RuntimePanel extends Panel {
++
++    private static final long serialVersionUID = -9002724127542172464L;
++
++    private boolean latestStatus;
++
++    private Fragment fragmentStop, fragmentSpinner;
++
++    public AbstractAjaxTimerBehavior timer;
++
++    private final PageReference pageRef;
++
++    private final long jobId;
++
++    private final JobRestClient jobRestClient;
++
++    public RuntimePanel(final String componentId, final IModel<?> model, final PageReference pageRef, final long jobId,
++            final JobRestClient jobRestClient) {
++        super(componentId, model);
++        this.pageRef = pageRef;
++        this.jobId = jobId;
++        this.jobRestClient = jobRestClient;
++        latestStatus = false;
++        this.refresh();
++
++    }
++
++    public final void refresh() {
++        boolean currentStatus = jobRestClient.isJobRunning(jobId);
++        if (currentStatus && !latestStatus) {
++            setRunning();
++        } else if (!currentStatus) {
++            setNotRunning();
++        }
++        latestStatus = currentStatus;
++    }
++
++    public void setRunning() {
++        fragmentStop = new Fragment("panelStop", "fragmentStop", this);
++        fragmentStop.addOrReplace(new ClearIndicatingAjaxLink<Void>("stopLink", pageRef) {
++
++            private static final long serialVersionUID = -7978723352517770644L;
++
++            @Override
++            protected void onClickInternal(final AjaxRequestTarget target) {
++                jobRestClient.stopJob(jobId);
++                this.setEnabled(false);
++                target.add(this);
++            }
++
++            @Override
++            public String getAjaxIndicatorMarkupId() {
++                return "";
++            }
++        });
++        addOrReplace(fragmentStop);
++        fragmentSpinner = new Fragment("panelSpinner", "fragmentSpinner", this);
++        addOrReplace(fragmentSpinner);
++    }
++
++    public void setNotRunning() {
++        fragmentStop = new Fragment("panelStop", "emptyFragment", this);
++        addOrReplace(fragmentStop);
++        fragmentSpinner = new Fragment("panelSpinner", "emptyFragment", this);
++        addOrReplace(fragmentSpinner);
++    }
++
++    public void setTimer(AbstractAjaxTimerBehavior timer) {
++        if (this.timer != null) {
++            remove(this.timer);
++        }
++        this.timer = timer;
++        this.add(this.timer);
++    }
++
++}

http://git-wip-us.apache.org/repos/asf/syncope/blob/34a0422a/client/old_console/src/main/java/org/apache/syncope/client/console/panels/SchedTasks.java
----------------------------------------------------------------------
diff --cc client/old_console/src/main/java/org/apache/syncope/client/console/panels/SchedTasks.java
index 205bfa5,0000000..78591a8
mode 100644,000000..100644
--- a/client/old_console/src/main/java/org/apache/syncope/client/console/panels/SchedTasks.java
+++ b/client/old_console/src/main/java/org/apache/syncope/client/console/panels/SchedTasks.java
@@@ -1,286 -1,0 +1,292 @@@
 +/*
 + * 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.panels;
++package org.apache.syncope.console.pages.panels;
++
++import static org.apache.syncope.console.pages.panels.AbstractTasks.TASKS;
 +
 +import java.util.ArrayList;
 +import java.util.List;
- import org.apache.syncope.client.console.commons.Constants;
- import org.apache.syncope.client.console.pages.SchedTaskModalPage;
- import org.apache.syncope.client.console.pages.Tasks;
- import org.apache.syncope.client.console.pages.Tasks.TasksProvider;
- import org.apache.syncope.client.console.wicket.ajax.markup.html.ClearIndicatingAjaxLink;
- import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.ActionColumn;
- import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.DatePropertyColumn;
- import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
- import org.apache.syncope.client.console.wicket.markup.html.form.ActionLinksPanel;
- import org.apache.syncope.common.lib.SyncopeClientException;
- import org.apache.syncope.common.lib.to.AbstractTaskTO;
- import org.apache.syncope.common.lib.to.SchedTaskTO;
++import org.apache.syncope.common.to.SchedTaskTO;
++import org.apache.syncope.common.to.AbstractTaskTO;
++import org.apache.syncope.common.SyncopeClientException;
++import org.apache.syncope.console.commons.Constants;
++import org.apache.syncope.console.pages.SchedTaskModalPage;
++import org.apache.syncope.console.pages.Tasks;
++import org.apache.syncope.console.pages.Tasks.TasksProvider;
++import org.apache.syncope.console.wicket.ajax.markup.html.ClearIndicatingAjaxLink;
++import org.apache.syncope.console.wicket.extensions.markup.html.repeater.data.table.ActionColumn;
++import org.apache.syncope.console.wicket.extensions.markup.html.repeater.data.table.DatePropertyColumn;
++import org.apache.syncope.console.wicket.extensions.markup.html.repeater.data.table.JobColumn;
++import org.apache.syncope.console.wicket.markup.html.form.ActionLink;
++import org.apache.syncope.console.wicket.markup.html.form.ActionLinksPanel;
 +import org.apache.wicket.Component;
 +import org.apache.wicket.Page;
 +import org.apache.wicket.PageReference;
 +import org.apache.wicket.ajax.AjaxRequestTarget;
 +import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
 +import org.apache.wicket.ajax.markup.html.AjaxLink;
 +import org.apache.wicket.authroles.authorization.strategies.role.metadata.MetaDataRoleAuthorizationStrategy;
 +import org.apache.wicket.event.IEvent;
 +import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
 +import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
 +import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
 +import org.apache.wicket.markup.html.WebMarkupContainer;
 +import org.apache.wicket.markup.html.form.DropDownChoice;
 +import org.apache.wicket.markup.html.form.Form;
 +import org.apache.wicket.model.IModel;
 +import org.apache.wicket.model.Model;
 +import org.apache.wicket.model.PropertyModel;
 +import org.apache.wicket.model.StringResourceModel;
 +import org.apache.wicket.request.http.WebResponse;
 +
 +public class SchedTasks extends AbstractTasks {
 +
 +    private static final long serialVersionUID = 525486152284253354L;
 +
 +    private int paginatorRows;
 +
 +    private WebMarkupContainer container;
 +
 +    private ModalWindow window;
 +
 +    private AjaxDataTablePanel<AbstractTaskTO, String> table;
 +
 +    public SchedTasks(final String id, final PageReference pageRef) {
 +        super(id, pageRef);
 +
 +        container = new WebMarkupContainer("container");
 +        container.setOutputMarkupId(true);
 +        add(container);
 +
 +        window = new ModalWindow("taskWin");
 +        window.setCssClassName(ModalWindow.CSS_CLASS_GRAY);
 +        window.setInitialHeight(WIN_HEIGHT);
 +        window.setInitialWidth(WIN_WIDTH);
 +        window.setCookieName(VIEW_TASK_WIN_COOKIE_NAME);
 +        add(window);
 +
 +        ((Tasks) pageRef.getPage()).setWindowClosedCallback(window, container);
 +
 +        paginatorRows = prefMan.getPaginatorRows(getWebRequest(), Constants.PREF_SCHED_TASKS_PAGINATOR_ROWS);
 +
 +        table = Tasks.updateTaskTable(
 +                getColumns(),
 +                new TasksProvider<SchedTaskTO>(restClient, paginatorRows, getId(), SchedTaskTO.class),
 +                container,
 +                0,
 +                pageRef,
 +                restClient);
 +
 +        container.add(table);
 +
 +        @SuppressWarnings("rawtypes")
 +        Form paginatorForm = new Form("PaginatorForm");
 +
 +        @SuppressWarnings({ "unchecked", "rawtypes" })
 +        final DropDownChoice rowsChooser = new DropDownChoice("rowsChooser", new PropertyModel(this, "paginatorRows"),
 +                prefMan.getPaginatorChoices());
 +
 +        rowsChooser.add(new AjaxFormComponentUpdatingBehavior(Constants.ON_CHANGE) {
 +
 +            private static final long serialVersionUID = -1107858522700306810L;
 +
 +            @Override
 +            protected void onUpdate(final AjaxRequestTarget target) {
 +                prefMan.set(getWebRequest(), (WebResponse) getResponse(), Constants.PREF_SCHED_TASKS_PAGINATOR_ROWS,
 +                        String.valueOf(paginatorRows));
 +
 +                table = Tasks.updateTaskTable(
 +                        getColumns(),
 +                        new TasksProvider<SchedTaskTO>(restClient, paginatorRows, getId(), SchedTaskTO.class),
 +                        container,
 +                        table == null ? 0 : (int) table.getCurrentPage(),
 +                        pageRef,
 +                        restClient);
 +
 +                target.add(container);
 +            }
 +        });
 +
 +        paginatorForm.add(rowsChooser);
 +        add(paginatorForm);
 +
 +        AjaxLink createLink = new ClearIndicatingAjaxLink("createLink", pageRef) {
 +
 +            private static final long serialVersionUID = -7978723352517770644L;
 +
 +            @Override
 +            protected void onClickInternal(final AjaxRequestTarget target) {
 +                window.setPageCreator(new ModalWindow.PageCreator() {
 +
 +                    private static final long serialVersionUID = -7834632442532690940L;
 +
 +                    @Override
 +                    public Page createPage() {
 +                        return new SchedTaskModalPage(window, new SchedTaskTO(), pageRef);
 +                    }
 +                });
 +
 +                window.show(target);
 +            }
 +        };
 +
 +        MetaDataRoleAuthorizationStrategy.authorize(
 +                createLink, RENDER, xmlRolesReader.getEntitlement(TASKS, "create"));
 +
 +        add(createLink);
 +    }
 +
 +    private List<IColumn<AbstractTaskTO, String>> getColumns() {
 +        final List<IColumn<AbstractTaskTO, String>> columns = new ArrayList<IColumn<AbstractTaskTO, String>>();
 +
 +        columns.add(new PropertyColumn<AbstractTaskTO, String>(
-                 new StringResourceModel("key", this, null), "key", "key"));
++                new StringResourceModel("id", this, null), "id", "id"));
 +        columns.add(new PropertyColumn<AbstractTaskTO, String>(
 +                new StringResourceModel("name", this, null), "name", "name"));
 +        columns.add(new PropertyColumn<AbstractTaskTO, String>(
 +                new StringResourceModel("description", this, null), "description", "description"));
 +        columns.add(new PropertyColumn<AbstractTaskTO, String>(
 +                new StringResourceModel("class", this, null), "jobClassName", "jobClassName"));
 +        columns.add(new DatePropertyColumn<AbstractTaskTO>(
 +                new StringResourceModel("lastExec", this, null), "lastExec", "lastExec"));
 +        columns.add(new DatePropertyColumn<AbstractTaskTO>(
 +                new StringResourceModel("nextExec", this, null), "nextExec", "nextExec"));
 +        columns.add(new PropertyColumn<AbstractTaskTO, String>(
 +                new StringResourceModel("latestExecStatus", this, null), "latestExecStatus", "latestExecStatus"));
 +
++        columns.add(new JobColumn<AbstractTaskTO, String>(new StringResourceModel("", this, null, ""), "runtime",
++                pageRef, restClient)); 
++
 +        columns.add(new ActionColumn<AbstractTaskTO, String>(new StringResourceModel("actions", this, null, "")) {
 +
 +            private static final long serialVersionUID = 2054811145491901166L;
 +
 +            @Override
 +            public ActionLinksPanel getActions(final String componentId, final IModel<AbstractTaskTO> model) {
 +
 +                final SchedTaskTO taskTO = (SchedTaskTO) model.getObject();
 +
 +                final ActionLinksPanel panel = new ActionLinksPanel(componentId, model, pageRef);
 +
 +                panel.add(new ActionLink() {
 +
 +                    private static final long serialVersionUID = -3722207913631435501L;
 +
 +                    @Override
 +                    public void onClick(final AjaxRequestTarget target) {
 +                        window.setPageCreator(new ModalWindow.PageCreator() {
 +
 +                            private static final long serialVersionUID = -7834632442532690940L;
 +
 +                            @Override
 +                            public Page createPage() {
 +                                return new SchedTaskModalPage(window, taskTO, pageRef);
 +                            }
 +                        });
 +
 +                        window.show(target);
 +                    }
 +                }, ActionLink.ActionType.EDIT, TASKS);
 +
 +                panel.add(new ActionLink() {
 +
 +                    private static final long serialVersionUID = -3722207913631435501L;
 +
 +                    @Override
 +                    public void onClick(final AjaxRequestTarget target) {
 +                        try {
-                             restClient.startExecution(taskTO.getKey(), false);
++                            restClient.startExecution(taskTO.getId(), false);
 +                            getSession().info(getString(Constants.OPERATION_SUCCEEDED));
 +                        } catch (SyncopeClientException scce) {
 +                            error(scce.getMessage());
 +                        }
 +
 +                        ((NotificationPanel) getPage().get(Constants.FEEDBACK)).refresh(target);
 +                        target.add(container);
 +                    }
 +                }, ActionLink.ActionType.EXECUTE, TASKS);
 +
 +                panel.add(new ActionLink() {
 +
 +                    private static final long serialVersionUID = -3722207913631435501L;
 +
 +                    @Override
 +                    public void onClick(final AjaxRequestTarget target) {
 +                        try {
-                             restClient.startExecution(taskTO.getKey(), true);
++                            restClient.startExecution(taskTO.getId(), true);
 +                            getSession().info(getString(Constants.OPERATION_SUCCEEDED));
 +                        } catch (SyncopeClientException scce) {
 +                            error(scce.getMessage());
 +                        }
 +
 +                        ((NotificationPanel) getPage().get(Constants.FEEDBACK)).refresh(target);
 +                        target.add(container);
 +                    }
 +                }, ActionLink.ActionType.DRYRUN, TASKS);
 +
 +                panel.add(new ActionLink() {
 +
 +                    private static final long serialVersionUID = -3722207913631435501L;
 +
 +                    @Override
 +                    public void onClick(final AjaxRequestTarget target) {
 +                        try {
-                             restClient.delete(taskTO.getKey(), SchedTaskTO.class);
++                            restClient.delete(taskTO.getId(), SchedTaskTO.class);
 +                            info(getString(Constants.OPERATION_SUCCEEDED));
 +                        } catch (SyncopeClientException scce) {
 +                            error(scce.getMessage());
 +                        }
 +                        target.add(container);
 +                        ((NotificationPanel) getPage().get(Constants.FEEDBACK)).refresh(target);
 +                    }
 +                }, ActionLink.ActionType.DELETE, TASKS);
 +
 +                return panel;
 +            }
 +
 +            @Override
 +            public Component getHeader(final String componentId) {
 +                @SuppressWarnings("rawtypes")
 +                final ActionLinksPanel panel = new ActionLinksPanel(componentId, new Model(), pageRef);
 +
 +                panel.add(new ActionLink() {
 +
 +                    private static final long serialVersionUID = -7978723352517770644L;
 +
 +                    @Override
 +                    public void onClick(final AjaxRequestTarget target) {
 +                        if (target != null) {
 +                            target.add(table);
 +                        }
 +                    }
 +                }, ActionLink.ActionType.RELOAD, TASKS, "list");
 +
 +                return panel;
 +            }
 +        });
 +        return columns;
 +    }
 +
 +    @Override
 +    public void onEvent(final IEvent<?> event) {
 +        if (event.getPayload() instanceof AbstractSearchResultPanel.EventDataWrapper) {
 +            ((AbstractSearchResultPanel.EventDataWrapper) event.getPayload()).getTarget().add(container);
 +        }
 +    }
 +}

http://git-wip-us.apache.org/repos/asf/syncope/blob/34a0422a/client/old_console/src/main/java/org/apache/syncope/client/console/panels/SyncTasksPanel.java
----------------------------------------------------------------------
diff --cc client/old_console/src/main/java/org/apache/syncope/client/console/panels/SyncTasksPanel.java
index 5561716,0000000..032f4e4
mode 100644,000000..100644
--- a/client/old_console/src/main/java/org/apache/syncope/client/console/panels/SyncTasksPanel.java
+++ b/client/old_console/src/main/java/org/apache/syncope/client/console/panels/SyncTasksPanel.java
@@@ -1,225 -1,0 +1,230 @@@
 +/*
 + * 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.panels;
++package org.apache.syncope.console.pages.panels;
 +
 +import java.util.ArrayList;
 +import java.util.List;
- import org.apache.syncope.client.console.commons.Constants;
- import org.apache.syncope.client.console.pages.GroupTemplateModalPage;
- import org.apache.syncope.client.console.pages.SyncTaskModalPage;
- import org.apache.syncope.client.console.pages.UserTemplateModalPage;
- import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.ActionColumn;
- import org.apache.syncope.client.console.wicket.extensions.markup.html.repeater.data.table.DatePropertyColumn;
- import org.apache.syncope.client.console.wicket.markup.html.form.ActionLink;
- import org.apache.syncope.client.console.wicket.markup.html.form.ActionLinksPanel;
- import org.apache.syncope.common.lib.SyncopeClientException;
- import org.apache.syncope.common.lib.to.AbstractTaskTO;
- import org.apache.syncope.common.lib.to.SyncTaskTO;
++import org.apache.syncope.common.SyncopeClientException;
++import org.apache.syncope.common.to.AbstractTaskTO;
++import org.apache.syncope.common.to.SyncTaskTO;
++import org.apache.syncope.console.commons.Constants;
++import org.apache.syncope.console.pages.RoleTemplateModalPage;
++import org.apache.syncope.console.pages.SyncTaskModalPage;
++import org.apache.syncope.console.pages.UserTemplateModalPage;
++import org.apache.syncope.console.wicket.extensions.markup.html.repeater.data.table.ActionColumn;
++import org.apache.syncope.console.wicket.extensions.markup.html.repeater.data.table.DatePropertyColumn;
++import org.apache.syncope.console.wicket.extensions.markup.html.repeater.data.table.JobColumn;
++import org.apache.syncope.console.wicket.markup.html.form.ActionLink;
++import org.apache.syncope.console.wicket.markup.html.form.ActionLinksPanel;
 +import org.apache.wicket.Component;
 +import org.apache.wicket.Page;
 +import org.apache.wicket.PageReference;
 +import org.apache.wicket.ajax.AjaxRequestTarget;
 +import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
 +import org.apache.wicket.extensions.markup.html.repeater.data.table.IColumn;
 +import org.apache.wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
 +import org.apache.wicket.model.IModel;
 +import org.apache.wicket.model.Model;
 +import org.apache.wicket.model.StringResourceModel;
 +
- public class SyncTasksPanel extends AbstractProvisioningTasksPanel<SyncTaskTO> {
++public class SyncTasksPanel extends AbstractSyncTasksPanel<SyncTaskTO> {
 +
 +    private static final long serialVersionUID = 53189199346016099L;
 +
 +    public SyncTasksPanel(final String id, final PageReference pageRef) {
 +        super(id, pageRef, SyncTaskTO.class);
 +        initTasksTable();
 +    }
 +
 +    @Override
 +    protected List<IColumn<AbstractTaskTO, String>> getColumns() {
-         final List<IColumn<AbstractTaskTO, String>> syncTaskscolumns = new ArrayList<>();
++        final List<IColumn<AbstractTaskTO, String>> syncTaskscolumns = new ArrayList<IColumn<AbstractTaskTO, String>>();
 +
 +        syncTaskscolumns.add(new PropertyColumn<AbstractTaskTO, String>(
-                 new StringResourceModel("key", this, null), "key", "key"));
++                new StringResourceModel("id", this, null), "id", "id"));
 +        syncTaskscolumns.add(new PropertyColumn<AbstractTaskTO, String>(
 +                new StringResourceModel("name", this, null), "name", "name"));
 +        syncTaskscolumns.add(new PropertyColumn<AbstractTaskTO, String>(
 +                new StringResourceModel("description", this, null), "description", "description"));
 +        syncTaskscolumns.add(new PropertyColumn<AbstractTaskTO, String>(
 +                new StringResourceModel("resourceName", this, null), "resource", "resource"));
 +        syncTaskscolumns.add(new DatePropertyColumn<AbstractTaskTO>(
 +                new StringResourceModel("lastExec", this, null), "lastExec", "lastExec"));
 +        syncTaskscolumns.add(new DatePropertyColumn<AbstractTaskTO>(
 +                new StringResourceModel("nextExec", this, null), "nextExec", "nextExec"));
 +        syncTaskscolumns.add(new PropertyColumn<AbstractTaskTO, String>(
 +                new StringResourceModel("latestExecStatus", this, null), "latestExecStatus", "latestExecStatus"));
++        
++        syncTaskscolumns.add(new JobColumn<AbstractTaskTO, String>(new StringResourceModel("", this, null, ""), "runtime",
++                pageRef, restClient));        
 +
-         syncTaskscolumns.add(new ActionColumn<AbstractTaskTO, String>(new StringResourceModel("actions", this, null, "")) {
++        syncTaskscolumns.add(
++                new ActionColumn<AbstractTaskTO, String>(new StringResourceModel("actions", this, null, "")) {
 +
 +                    private static final long serialVersionUID = 2054811145491901166L;
 +
 +                    @Override
 +                    public ActionLinksPanel getActions(final String componentId, final IModel<AbstractTaskTO> model) {
 +
 +                        final SyncTaskTO taskTO = (SyncTaskTO) model.getObject();
 +
 +                        final ActionLinksPanel panel = new ActionLinksPanel(componentId, model, pageRef);
 +
 +                        panel.add(new ActionLink() {
 +
 +                            private static final long serialVersionUID = -3722207913631435501L;
 +
 +                            @Override
 +                            public void onClick(final AjaxRequestTarget target) {
 +
 +                                window.setPageCreator(new ModalWindow.PageCreator() {
 +
 +                                    private static final long serialVersionUID = -7834632442532690940L;
 +
 +                                    @Override
 +                                    public Page createPage() {
 +                                        return new SyncTaskModalPage(window, taskTO, pageRef);
 +                                    }
 +                                });
 +
 +                                window.show(target);
 +                            }
 +                        }, ActionLink.ActionType.EDIT, TASKS);
 +
 +                        panel.add(new ActionLink() {
 +
 +                            private static final long serialVersionUID = -3722207913631435501L;
 +
 +                            @Override
 +                            public void onClick(final AjaxRequestTarget target) {
 +
 +                                window.setPageCreator(new ModalWindow.PageCreator() {
 +
 +                                    private static final long serialVersionUID = -7834632442532690940L;
 +
 +                                    @Override
 +                                    public Page createPage() {
 +                                        return new UserTemplateModalPage(pageRef, window, taskTO);
 +                                    }
 +                                });
 +
 +                                window.show(target);
 +                            }
 +                        }, ActionLink.ActionType.USER_TEMPLATE, TASKS);
 +
 +                        panel.add(new ActionLink() {
 +
 +                            private static final long serialVersionUID = -3722207913631435501L;
 +
 +                            @Override
 +                            public void onClick(final AjaxRequestTarget target) {
 +
 +                                window.setPageCreator(new ModalWindow.PageCreator() {
 +
 +                                    private static final long serialVersionUID = -7834632442532690940L;
 +
 +                                    @Override
 +                                    public Page createPage() {
-                                         return new GroupTemplateModalPage(pageRef, window, taskTO);
++                                        return new RoleTemplateModalPage(pageRef, window, taskTO);
 +                                    }
 +                                });
 +
 +                                window.show(target);
 +                            }
-                         }, ActionLink.ActionType.GROUP_TEMPLATE, TASKS);
++                        }, ActionLink.ActionType.ROLE_TEMPLATE, TASKS);
 +
 +                        panel.add(new ActionLink() {
 +
 +                            private static final long serialVersionUID = -3722207913631435501L;
 +
 +                            @Override
 +                            public void onClick(final AjaxRequestTarget target) {
 +                                try {
-                                     restClient.startExecution(taskTO.getKey(), false);
++                                    restClient.startExecution(taskTO.getId(), false);
 +                                    getSession().info(getString(Constants.OPERATION_SUCCEEDED));
 +                                } catch (SyncopeClientException scce) {
 +                                    error(scce.getMessage());
 +                                }
 +
 +                                target.add(container);
 +                                ((NotificationPanel) getPage().get(Constants.FEEDBACK)).refresh(target);
 +                            }
 +                        }, ActionLink.ActionType.EXECUTE, TASKS);
 +
 +                        panel.add(new ActionLink() {
 +
 +                            private static final long serialVersionUID = -3722207913631435501L;
 +
 +                            @Override
 +                            public void onClick(final AjaxRequestTarget target) {
 +                                try {
-                                     restClient.startExecution(taskTO.getKey(), true);
++                                    restClient.startExecution(taskTO.getId(), true);
 +                                    getSession().info(getString(Constants.OPERATION_SUCCEEDED));
 +                                } catch (SyncopeClientException scce) {
 +                                    error(scce.getMessage());
 +                                }
 +
 +                                target.add(container);
 +                                ((NotificationPanel) getPage().get(Constants.FEEDBACK)).refresh(target);
 +                            }
 +                        }, ActionLink.ActionType.DRYRUN, TASKS);
 +
 +                        panel.add(new ActionLink() {
 +
 +                            private static final long serialVersionUID = -3722207913631435501L;
 +
 +                            @Override
 +                            public void onClick(final AjaxRequestTarget target) {
 +                                try {
-                                     restClient.delete(taskTO.getKey(), SyncTaskTO.class);
++                                    restClient.delete(taskTO.getId(), SyncTaskTO.class);
 +                                    info(getString(Constants.OPERATION_SUCCEEDED));
 +                                } catch (SyncopeClientException scce) {
 +                                    error(scce.getMessage());
 +                                }
 +                                target.add(container);
 +                                ((NotificationPanel) getPage().get(Constants.FEEDBACK)).refresh(target);
 +                            }
 +                        }, ActionLink.ActionType.DELETE, TASKS);
 +
 +                        return panel;
 +                    }
 +
 +                    @Override
-                     public Component getHeader(final String componentId) {
++                    public Component getHeader(String componentId) {
 +                        final ActionLinksPanel panel = new ActionLinksPanel(componentId, new Model(), pageRef);
 +
 +                        panel.add(new ActionLink() {
 +
 +                            private static final long serialVersionUID = -7978723352517770644L;
 +
 +                            @Override
 +                            public void onClick(final AjaxRequestTarget target) {
 +                                if (target != null) {
 +                                    target.add(table);
 +                                }
 +                            }
 +                        }, ActionLink.ActionType.RELOAD, TASKS, "list");
 +
 +                        return panel;
 +                    }
 +                });
 +
 +        return syncTaskscolumns;
 +    }
 +}

http://git-wip-us.apache.org/repos/asf/syncope/blob/34a0422a/client/old_console/src/main/java/org/apache/syncope/client/console/rest/JobRestClient.java
----------------------------------------------------------------------
diff --cc client/old_console/src/main/java/org/apache/syncope/client/console/rest/JobRestClient.java
index 0000000,0000000..0634658
new file mode 100644
--- /dev/null
+++ b/client/old_console/src/main/java/org/apache/syncope/client/console/rest/JobRestClient.java
@@@ -1,0 -1,0 +1,31 @@@
++/*
++ * 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.rest;
++
++import org.springframework.stereotype.Component;
++
++@Component
++public abstract class JobRestClient extends BaseRestClient{
++
++    public abstract boolean isJobRunning(final long id);
++
++    public abstract void startJob(final long id);
++
++    public abstract void stopJob(final long id);
++}

http://git-wip-us.apache.org/repos/asf/syncope/blob/34a0422a/client/old_console/src/main/java/org/apache/syncope/client/console/rest/ReportRestClient.java
----------------------------------------------------------------------
diff --cc client/old_console/src/main/java/org/apache/syncope/client/console/rest/ReportRestClient.java
index 81b58ac,0000000..9b8afdb
mode 100644,000000..100644
--- a/client/old_console/src/main/java/org/apache/syncope/client/console/rest/ReportRestClient.java
+++ b/client/old_console/src/main/java/org/apache/syncope/client/console/rest/ReportRestClient.java
@@@ -1,108 -1,0 +1,131 @@@
 +/*
 + * 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.rest;
++package org.apache.syncope.console.rest;
 +
 +import java.util.ArrayList;
 +import java.util.List;
 +import javax.ws.rs.core.Response;
- import org.apache.syncope.common.lib.SyncopeClientException;
- import org.apache.syncope.common.lib.to.ReportTO;
- import org.apache.syncope.common.lib.types.ReportExecExportFormat;
- import org.apache.syncope.common.lib.wrap.ReportletConfClass;
- import org.apache.syncope.common.rest.api.service.ReportService;
++import org.apache.syncope.common.services.ReportService;
++import org.apache.syncope.common.to.ReportTO;
++import org.apache.syncope.common.types.ReportExecExportFormat;
++import org.apache.syncope.common.SyncopeClientException;
++import org.apache.syncope.common.to.ReportExecTO;
++import org.apache.syncope.common.types.JobAction;
++import org.apache.syncope.common.types.JobStatusType;
++import org.apache.syncope.common.wrap.ReportletConfClass;
 +import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;
 +import org.springframework.stereotype.Component;
 +
 +@Component
- public class ReportRestClient extends BaseRestClient implements ExecutionRestClient {
++public class ReportRestClient extends JobRestClient implements ExecutionRestClient {
 +
 +    private static final long serialVersionUID = 1644689667998953604L;
 +
 +    public List<String> getReportletConfClasses() {
 +        List<String> result = new ArrayList<String>();
 +
 +        try {
 +            List<ReportletConfClass> reportletConfClasses = getService(ReportService.class).getReportletConfClasses();
 +            for (ReportletConfClass clazz : reportletConfClasses) {
 +                result.add(clazz.getElement());
 +            }
 +        } catch (SyncopeClientException e) {
 +            LOG.error("While getting available reportlet classes", e);
 +        }
 +
 +        return result;
 +    }
 +
 +    public ReportTO read(final Long reportId) {
 +        return getService(ReportService.class).read(reportId);
 +    }
 +
 +    public List<ReportTO> list() {
 +        return getService(ReportService.class).list().getResult();
 +    }
 +
 +    public List<ReportTO> list(final int page, final int size, final SortParam<String> sort) {
 +        return getService(ReportService.class).list(page, size, toOrderBy(sort)).getResult();
 +    }
 +
 +    public int count() {
 +        return getService(ReportService.class).list(1, 1).getTotalCount();
 +    }
 +
 +    public void create(final ReportTO reportTO) {
 +        getService(ReportService.class).create(reportTO);
 +    }
 +
 +    public void update(final ReportTO reportTO) {
-         getService(ReportService.class).update(reportTO.getKey(), reportTO);
++        getService(ReportService.class).update(reportTO.getId(), reportTO);
 +    }
 +
 +    /**
 +     * Delete specified report.
 +     *
 +     * @param reportId report to delete
 +     */
 +    public void delete(final Long reportId) {
 +        getService(ReportService.class).delete(reportId);
 +    }
 +
 +    /**
 +     * Start execution for the specified report.
 +     *
 +     * @param reportId report id
 +     */
 +    @Override
 +    public void startExecution(final long reportId) {
 +        getService(ReportService.class).execute(reportId);
 +    }
 +
 +    /**
 +     * Delete specified report execution.
 +     *
 +     * @param reportExecId report execution id
 +     */
 +    @Override
 +    public void deleteExecution(final long reportExecId) {
 +        getService(ReportService.class).deleteExecution(reportExecId);
 +    }
 +
 +    public Response exportExecutionResult(final Long executionId, final ReportExecExportFormat fmt) {
 +        return getService(ReportService.class).exportExecutionResult(executionId, fmt);
 +    }
++
++    @Override
++    public boolean isJobRunning(final long reportId) {
++        for (ReportExecTO reportExecTO : getService(ReportService.class).listJobs(JobStatusType.RUNNING)) {
++            if (reportExecTO.getReport() == reportId) {
++                return true;
++            }
++        }
++        return false;
++    }
++
++    @Override
++    public void startJob(final long reportId) {
++        getService(ReportService.class).actionJob(reportId, JobAction.START);
++    }
++
++    @Override
++    public void stopJob(final long reportId) {
++        getService(ReportService.class).actionJob(reportId, JobAction.STOP);
++    }
 +}


[20/21] syncope git commit: [SYNCOPE-666] All tests are green, time to add more

Posted by il...@apache.org.
http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeClassLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeClassLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeClassLogic.java
new file mode 100644
index 0000000..8747631
--- /dev/null
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeClassLogic.java
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.logic;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.Transformer;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.to.AnyTypeClassTO;
+import org.apache.syncope.common.lib.types.Entitlement;
+import org.apache.syncope.core.persistence.api.dao.NotFoundException;
+import org.apache.syncope.core.persistence.api.dao.AnyTypeClassDAO;
+import org.apache.syncope.core.persistence.api.entity.AnyTypeClass;
+import org.apache.syncope.core.provisioning.api.data.AnyTypeClassDataBinder;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.stereotype.Component;
+
+@Component
+public class AnyTypeClassLogic extends AbstractTransactionalLogic<AnyTypeClassTO> {
+
+    @Autowired
+    private AnyTypeClassDataBinder binder;
+
+    @Autowired
+    private AnyTypeClassDAO anyTypeDAO;
+
+    @PreAuthorize("hasRole('" + Entitlement.ANYTYPECLASS_READ + "')")
+    public AnyTypeClassTO read(final String key) {
+        AnyTypeClass anyType = anyTypeDAO.find(key);
+        if (anyType == null) {
+            LOG.error("Could not find anyType '" + key + "'");
+
+            throw new NotFoundException(String.valueOf(key));
+        }
+
+        return binder.getAnyTypeClassTO(anyType);
+    }
+
+    @PreAuthorize("hasRole('" + Entitlement.ANYTYPECLASS_LIST + "')")
+    public List<AnyTypeClassTO> list() {
+        return CollectionUtils.collect(anyTypeDAO.findAll(), new Transformer<AnyTypeClass, AnyTypeClassTO>() {
+
+            @Override
+            public AnyTypeClassTO transform(final AnyTypeClass input) {
+                return binder.getAnyTypeClassTO(input);
+            }
+        }, new ArrayList<AnyTypeClassTO>());
+    }
+
+    @PreAuthorize("hasRole('" + Entitlement.ANYTYPECLASS_CREATE + "')")
+    public AnyTypeClassTO create(final AnyTypeClassTO anyTypeTO) {
+        return binder.getAnyTypeClassTO(anyTypeDAO.save(binder.create(anyTypeTO)));
+    }
+
+    @PreAuthorize("hasRole('" + Entitlement.ANYTYPECLASS_UPDATE + "')")
+    public AnyTypeClassTO update(final AnyTypeClassTO anyTypeTO) {
+        AnyTypeClass anyType = anyTypeDAO.find(anyTypeTO.getKey());
+        if (anyType == null) {
+            LOG.error("Could not find anyType '" + anyTypeTO.getKey() + "'");
+            throw new NotFoundException(String.valueOf(anyTypeTO.getKey()));
+        }
+
+        binder.update(anyType, anyTypeTO);
+        anyType = anyTypeDAO.save(anyType);
+
+        return binder.getAnyTypeClassTO(anyType);
+    }
+
+    @PreAuthorize("hasRole('" + Entitlement.ANYTYPECLASS_DELETE + "')")
+    public AnyTypeClassTO delete(final String key) {
+        AnyTypeClass anyType = anyTypeDAO.find(key);
+        if (anyType == null) {
+            LOG.error("Could not find anyType '" + key + "'");
+
+            throw new NotFoundException(String.valueOf(key));
+        }
+
+        AnyTypeClassTO deleted = binder.getAnyTypeClassTO(anyType);
+        anyTypeDAO.delete(key);
+        return deleted;
+    }
+
+    @Override
+    protected AnyTypeClassTO resolveReference(final Method method, final Object... args)
+            throws UnresolvedReferenceException {
+
+        String key = null;
+
+        if (ArrayUtils.isNotEmpty(args)) {
+            for (int i = 0; key == null && i < args.length; i++) {
+                if (args[i] instanceof Long) {
+                    key = (String) args[i];
+                } else if (args[i] instanceof AnyTypeClassTO) {
+                    key = ((AnyTypeClassTO) args[i]).getKey();
+                }
+            }
+        }
+
+        if (StringUtils.isNotBlank(key)) {
+            try {
+                return binder.getAnyTypeClassTO(anyTypeDAO.find(key));
+            } catch (Throwable ignore) {
+                LOG.debug("Unresolved reference", ignore);
+                throw new UnresolvedReferenceException(ignore);
+            }
+        }
+
+        throw new UnresolvedReferenceException();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeLogic.java
new file mode 100644
index 0000000..93af622
--- /dev/null
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/AnyTypeLogic.java
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.logic;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.Transformer;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.syncope.common.lib.to.AnyTypeTO;
+import org.apache.syncope.common.lib.types.Entitlement;
+import org.apache.syncope.core.persistence.api.dao.NotFoundException;
+import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
+import org.apache.syncope.core.persistence.api.entity.AnyType;
+import org.apache.syncope.core.provisioning.api.data.AnyTypeDataBinder;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.stereotype.Component;
+
+@Component
+public class AnyTypeLogic extends AbstractTransactionalLogic<AnyTypeTO> {
+
+    @Autowired
+    private AnyTypeDataBinder binder;
+
+    @Autowired
+    private AnyTypeDAO anyTypeDAO;
+
+    @PreAuthorize("hasRole('" + Entitlement.ANYTYPE_READ + "')")
+    public AnyTypeTO read(final String key) {
+        AnyType anyType = anyTypeDAO.find(key);
+        if (anyType == null) {
+            LOG.error("Could not find anyType '" + key + "'");
+
+            throw new NotFoundException(String.valueOf(key));
+        }
+
+        return binder.getAnyTypeTO(anyType);
+    }
+
+    @PreAuthorize("hasRole('" + Entitlement.ANYTYPE_LIST + "')")
+    public List<AnyTypeTO> list() {
+        return CollectionUtils.collect(anyTypeDAO.findAll(), new Transformer<AnyType, AnyTypeTO>() {
+
+            @Override
+            public AnyTypeTO transform(final AnyType input) {
+                return binder.getAnyTypeTO(input);
+            }
+        }, new ArrayList<AnyTypeTO>());
+    }
+
+    @PreAuthorize("hasRole('" + Entitlement.ANYTYPE_CREATE + "')")
+    public AnyTypeTO create(final AnyTypeTO anyTypeTO) {
+        return binder.getAnyTypeTO(anyTypeDAO.save(binder.create(anyTypeTO)));
+    }
+
+    @PreAuthorize("hasRole('" + Entitlement.ANYTYPE_UPDATE + "')")
+    public AnyTypeTO update(final AnyTypeTO anyTypeTO) {
+        AnyType anyType = anyTypeDAO.find(anyTypeTO.getKey());
+        if (anyType == null) {
+            LOG.error("Could not find anyType '" + anyTypeTO.getKey() + "'");
+            throw new NotFoundException(String.valueOf(anyTypeTO.getKey()));
+        }
+
+        binder.update(anyType, anyTypeTO);
+        anyType = anyTypeDAO.save(anyType);
+
+        return binder.getAnyTypeTO(anyType);
+    }
+
+    @PreAuthorize("hasRole('" + Entitlement.ANYTYPE_DELETE + "')")
+    public AnyTypeTO delete(final String key) {
+        AnyType anyType = anyTypeDAO.find(key);
+        if (anyType == null) {
+            LOG.error("Could not find anyType '" + key + "'");
+
+            throw new NotFoundException(String.valueOf(key));
+        }
+
+        AnyTypeTO deleted = binder.getAnyTypeTO(anyType);
+        anyTypeDAO.delete(key);
+        return deleted;
+    }
+
+    @Override
+    protected AnyTypeTO resolveReference(final Method method, final Object... args)
+            throws UnresolvedReferenceException {
+
+        String key = null;
+
+        if (ArrayUtils.isNotEmpty(args)) {
+            for (int i = 0; key == null && i < args.length; i++) {
+                if (args[i] instanceof Long) {
+                    key = (String) args[i];
+                } else if (args[i] instanceof AnyTypeTO) {
+                    key = ((AnyTypeTO) args[i]).getKey();
+                }
+            }
+        }
+
+        if (StringUtils.isNotBlank(key)) {
+            try {
+                return binder.getAnyTypeTO(anyTypeDAO.find(key));
+            } catch (Throwable ignore) {
+                LOG.debug("Unresolved reference", ignore);
+                throw new UnresolvedReferenceException(ignore);
+            }
+        }
+
+        throw new UnresolvedReferenceException();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/logic/src/main/java/org/apache/syncope/core/logic/LogicInvocationHandler.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/LogicInvocationHandler.java b/core/logic/src/main/java/org/apache/syncope/core/logic/LogicInvocationHandler.java
index 968a34c..77ff7b5 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/LogicInvocationHandler.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/LogicInvocationHandler.java
@@ -34,9 +34,6 @@ import org.springframework.beans.factory.annotation.Autowired;
 @Aspect
 public class LogicInvocationHandler {
 
-    /**
-     * Logger.
-     */
     private static final Logger LOG = LoggerFactory.getLogger(LogicInvocationHandler.class);
 
     @Autowired
@@ -47,16 +44,16 @@ public class LogicInvocationHandler {
 
     @Around("execution(* org.apache.syncope.core.logic.AbstractLogic+.*(..))")
     public Object around(final ProceedingJoinPoint joinPoint) throws Throwable {
-        final Class<?> clazz = joinPoint.getTarget().getClass();
+        Class<?> clazz = joinPoint.getTarget().getClass();
 
-        final Object[] input = joinPoint.getArgs();
+        Object[] input = joinPoint.getArgs();
 
-        final String category = clazz.getSimpleName();
+        String category = clazz.getSimpleName();
 
-        final MethodSignature ms = (MethodSignature) joinPoint.getSignature();
+        MethodSignature ms = (MethodSignature) joinPoint.getSignature();
         Method method = ms.getMethod();
 
-        final String event = joinPoint.getSignature().getName();
+        String event = joinPoint.getSignature().getName();
 
         AuditElements.Result result = null;
         Object output = null;

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/logic/src/main/java/org/apache/syncope/core/logic/ResourceLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/ResourceLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/ResourceLogic.java
index 073150b..863af12 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/ResourceLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/ResourceLogic.java
@@ -217,7 +217,7 @@ public class ResourceLogic extends AbstractTransactionalLogic<ResourceTO> {
                 connector.getOperationOptions(attrUtils.getMappingItems(provision, MappingPurpose.BOTH)));
         if (connectorObject == null) {
             throw new NotFoundException("Object " + connObjectKeyValue + " with class " + provision.getObjectClass()
-                    + "not found on resource " + resourceKey);
+                    + " not found on resource " + resourceKey);
         }
 
         final Set<Attribute> attributes = connectorObject.getAttributes();

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/logic/src/main/java/org/apache/syncope/core/logic/UserLogic.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/UserLogic.java b/core/logic/src/main/java/org/apache/syncope/core/logic/UserLogic.java
index 37acf19..4ecab47 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/UserLogic.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/UserLogic.java
@@ -50,12 +50,12 @@ import org.apache.syncope.core.provisioning.api.UserProvisioningManager;
 import org.apache.syncope.core.provisioning.api.data.UserDataBinder;
 import org.apache.syncope.core.provisioning.api.propagation.PropagationManager;
 import org.apache.syncope.core.provisioning.api.propagation.PropagationTaskExecutor;
-import org.apache.syncope.core.provisioning.java.VirAttrHandler;
 import org.apache.syncope.core.misc.security.AuthContextUtils;
 import org.apache.syncope.core.misc.security.UnauthorizedException;
 import org.apache.syncope.core.misc.serialization.POJOHelper;
 import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
 import org.apache.syncope.core.provisioning.api.AnyTransformer;
+import org.apache.syncope.core.provisioning.api.VirAttrHandler;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.stereotype.Component;
@@ -205,7 +205,7 @@ public class UserLogic extends AbstractAnyLogic<UserTO, UserMod> {
 
         Map.Entry<Long, List<PropagationStatus>> created = provisioningManager.create(actual, storePassword);
 
-        final UserTO savedTO = binder.getUserTO(created.getKey());
+        UserTO savedTO = binder.getUserTO(created.getKey());
         savedTO.getPropagationStatusTOs().addAll(created.getValue());
         return savedTO;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/logic/src/main/java/org/apache/syncope/core/logic/init/JobInstanceLoaderImpl.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/init/JobInstanceLoaderImpl.java b/core/logic/src/main/java/org/apache/syncope/core/logic/init/JobInstanceLoaderImpl.java
index 106ed36..6a8289a 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/init/JobInstanceLoaderImpl.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/init/JobInstanceLoaderImpl.java
@@ -57,6 +57,7 @@ import org.quartz.impl.JobDetailImpl;
 import org.quartz.impl.triggers.CronTriggerImpl;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.BeanCreationException;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.support.AbstractBeanDefinition;
 import org.springframework.scheduling.quartz.SchedulerFactoryBean;
@@ -126,6 +127,30 @@ public class JobInstanceLoaderImpl implements JobInstanceLoader, SyncopeLoader {
         }
     }
 
+    private Job createSpringBean(final Class<?> jobClass) {
+        Job jobInstance = null;
+        for (int i = 0; i < 5 && jobInstance == null; i++) {
+            LOG.debug("{} attempt to create Spring bean for {}", i, jobClass);
+            try {
+                jobInstance = (Job) ApplicationContextProvider.getBeanFactory().
+                        createBean(jobClass, AbstractBeanDefinition.AUTOWIRE_BY_TYPE, false);
+                LOG.debug("{} attempt to create Spring bean for {} succeeded", i, jobClass);
+            } catch (BeanCreationException e) {
+                LOG.error("Could not create Spring bean for {}", jobClass, e);
+                try {
+                    Thread.sleep(1000);
+                } catch (final InterruptedException ex) {
+                    // ignore
+                }
+            }
+        }
+        if (jobInstance == null) {
+            throw new NotFoundException("Spring bean for " + jobClass);
+        }
+
+        return jobInstance;
+    }
+
     @SuppressWarnings("unchecked")
     @Override
     public void registerJob(final Task task, final String jobClassName, final String cronExpression)
@@ -137,8 +162,8 @@ public class JobInstanceLoaderImpl implements JobInstanceLoader, SyncopeLoader {
         } else if (PushJob.class.equals(jobClass)) {
             jobClass = PushJobImpl.class;
         }
-        Job jobInstance = (Job) ApplicationContextProvider.getBeanFactory().
-                createBean(jobClass, AbstractBeanDefinition.AUTOWIRE_BY_TYPE, false);
+
+        Job jobInstance = createSpringBean(jobClass);
         if (jobInstance instanceof TaskJob) {
             ((TaskJob) jobInstance).setTaskId(task.getKey());
         }
@@ -151,10 +176,8 @@ public class JobInstanceLoaderImpl implements JobInstanceLoader, SyncopeLoader {
                 try {
                     Class<?> actionsClass = Class.forName(className);
 
-                    final SyncActions syncActions =
-                            (SyncActions) ApplicationContextProvider.getBeanFactory().
+                    SyncActions syncActions = (SyncActions) ApplicationContextProvider.getBeanFactory().
                             createBean(actionsClass, AbstractBeanDefinition.AUTOWIRE_BY_TYPE, true);
-
                     actions.add(syncActions);
                 } catch (Exception e) {
                     LOG.info("Class '{}' not found", className, e);
@@ -182,8 +205,7 @@ public class JobInstanceLoaderImpl implements JobInstanceLoader, SyncopeLoader {
 
     @Override
     public void registerJob(final Report report) throws SchedulerException, ParseException {
-        Job jobInstance = (Job) ApplicationContextProvider.getBeanFactory().
-                createBean(ReportJob.class, AbstractBeanDefinition.AUTOWIRE_BY_TYPE, false);
+        Job jobInstance = createSpringBean(ReportJob.class);
         ((ReportJob) jobInstance).setReportKey(report.getKey());
 
         registerJob(JobNamer.getJobName(report), jobInstance, report.getCronExpression());

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/logic/src/main/java/org/apache/syncope/core/logic/report/UserReportlet.java
----------------------------------------------------------------------
diff --git a/core/logic/src/main/java/org/apache/syncope/core/logic/report/UserReportlet.java b/core/logic/src/main/java/org/apache/syncope/core/logic/report/UserReportlet.java
index b4087a7..b05c4e6 100644
--- a/core/logic/src/main/java/org/apache/syncope/core/logic/report/UserReportlet.java
+++ b/core/logic/src/main/java/org/apache/syncope/core/logic/report/UserReportlet.java
@@ -29,6 +29,7 @@ import org.apache.syncope.common.lib.report.UserReportletConf.Feature;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.to.AttrTO;
 import org.apache.syncope.common.lib.to.MembershipTO;
+import org.apache.syncope.common.lib.to.RelationshipTO;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.core.persistence.api.dao.UserDAO;
@@ -38,6 +39,8 @@ import org.apache.syncope.core.misc.search.SearchCondConverter;
 import org.apache.syncope.core.misc.DataFormat;
 import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
 import org.apache.syncope.core.persistence.api.entity.user.UMembership;
+import org.apache.syncope.core.persistence.api.entity.user.URelationship;
+import org.apache.syncope.core.provisioning.api.data.AnyObjectDataBinder;
 import org.apache.syncope.core.provisioning.api.data.GroupDataBinder;
 import org.apache.syncope.core.provisioning.api.data.UserDataBinder;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -62,6 +65,9 @@ public class UserReportlet extends AbstractReportlet<UserReportletConf> {
     @Autowired
     private GroupDataBinder groupDataBinder;
 
+    @Autowired
+    private AnyObjectDataBinder anyObjectDataBinder;
+
     private List<User> getPagedUsers(final int page) {
         List<User> result;
 
@@ -264,14 +270,39 @@ public class UserReportlet extends AbstractReportlet<UserReportletConf> {
 
             doExtractAttributes(handler, userTO, conf.getPlainAttrs(), conf.getDerAttrs(), conf.getVirAttrs());
 
+            if (conf.getFeatures().contains(Feature.relationships)) {
+                handler.startElement("", "", "relationships", null);
+
+                for (RelationshipTO rel : userTO.getRelationships()) {
+                    atts.clear();
+
+                    atts.addAttribute("", "", "anyObjectKey",
+                            ReportXMLConst.XSD_LONG, String.valueOf(rel.getRightKey()));
+                    handler.startElement("", "", "relationship", atts);
+
+                    if (conf.getFeatures().contains(Feature.resources)) {
+                        URelationship actualRel = user.getRelationship(rel.getRightKey());
+                        if (actualRel == null) {
+                            LOG.warn("Unexpected: cannot find relationship for any object {} for user {}",
+                                    rel.getRightKey(), user);
+                        } else {
+                            doExtractResources(handler, anyObjectDataBinder.getAnyObjectTO(actualRel.getRightEnd()));
+                        }
+                    }
+
+                    handler.endElement("", "", "relationship");
+                }
+
+                handler.endElement("", "", "relationships");
+            }
             if (conf.getFeatures().contains(Feature.memberships)) {
                 handler.startElement("", "", "memberships", null);
 
                 for (MembershipTO memb : userTO.getMemberships()) {
                     atts.clear();
 
-                    atts.addAttribute("", "", "id", ReportXMLConst.XSD_LONG, String.valueOf(memb.getKey()));
-                    atts.addAttribute("", "", "groupId", ReportXMLConst.XSD_LONG, String.valueOf(memb.getRightKey()));
+                    atts.addAttribute("", "", "groupKey",
+                            ReportXMLConst.XSD_LONG, String.valueOf(memb.getRightKey()));
                     atts.addAttribute("", "", "groupName", ReportXMLConst.XSD_STRING, String.
                             valueOf(memb.getGroupName()));
                     handler.startElement("", "", "membership", atts);
@@ -279,8 +310,8 @@ public class UserReportlet extends AbstractReportlet<UserReportletConf> {
                     if (conf.getFeatures().contains(Feature.resources)) {
                         UMembership actualMemb = user.getMembership(memb.getRightKey());
                         if (actualMemb == null) {
-                            LOG.warn("Unexpected: cannot find membership for group {} for user {}", memb.getRightKey(),
-                                    user);
+                            LOG.warn("Unexpected: cannot find membership for group {} for user {}",
+                                    memb.getRightKey(), user);
                         } else {
                             doExtractResources(handler, groupDataBinder.getGroupTO(actualMemb.getRightEnd()));
                         }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/misc/src/main/java/org/apache/syncope/core/misc/ConnObjectUtils.java
----------------------------------------------------------------------
diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/ConnObjectUtils.java b/core/misc/src/main/java/org/apache/syncope/core/misc/ConnObjectUtils.java
index 279ef77..766c5cf 100644
--- a/core/misc/src/main/java/org/apache/syncope/core/misc/ConnObjectUtils.java
+++ b/core/misc/src/main/java/org/apache/syncope/core/misc/ConnObjectUtils.java
@@ -25,23 +25,21 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
-import org.apache.commons.collections4.CollectionUtils;
-import org.apache.commons.collections4.Predicate;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.AnyOperations;
 import org.apache.syncope.common.lib.mod.AnyMod;
+import org.apache.syncope.common.lib.to.AnyObjectTO;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.to.AttrTO;
 import org.apache.syncope.common.lib.to.ConnObjectTO;
 import org.apache.syncope.common.lib.to.GroupTO;
+import org.apache.syncope.common.lib.to.MembershipTO;
+import org.apache.syncope.common.lib.to.RelationshipTO;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.AttrSchemaType;
-import org.apache.syncope.common.lib.types.IntMappingType;
 import org.apache.syncope.common.lib.types.MappingPurpose;
 import org.apache.syncope.common.lib.types.PasswordPolicySpec;
 import org.apache.syncope.core.persistence.api.attrvalue.validation.ParsingValidationException;
@@ -54,24 +52,13 @@ import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
 import org.apache.syncope.core.persistence.api.entity.PlainAttrValue;
 import org.apache.syncope.core.persistence.api.entity.PlainSchema;
-import org.apache.syncope.core.persistence.api.entity.VirAttr;
 import org.apache.syncope.core.persistence.api.entity.group.Group;
 import org.apache.syncope.core.persistence.api.entity.task.SyncTask;
 import org.apache.syncope.core.persistence.api.entity.user.User;
-import org.apache.syncope.core.provisioning.api.Connector;
-import org.apache.syncope.core.provisioning.api.ConnectorFactory;
-import org.apache.syncope.core.provisioning.api.cache.VirAttrCache;
-import org.apache.syncope.core.provisioning.api.cache.VirAttrCacheValue;
 import org.apache.syncope.core.misc.security.Encryptor;
-import org.apache.syncope.core.misc.spring.ApplicationContextProvider;
 import org.apache.syncope.core.misc.jexl.JexlUtils;
-import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
 import org.apache.syncope.core.persistence.api.dao.RealmDAO;
-import org.apache.syncope.core.persistence.api.entity.Any;
-import org.apache.syncope.core.persistence.api.entity.AnyType;
-import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
 import org.apache.syncope.core.persistence.api.entity.Realm;
-import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
 import org.apache.syncope.core.persistence.api.entity.resource.Provision;
 import org.apache.syncope.core.persistence.api.entity.task.AnyTemplate;
 import org.identityconnectors.common.Base64;
@@ -79,12 +66,9 @@ import org.identityconnectors.common.security.GuardedByteArray;
 import org.identityconnectors.common.security.GuardedString;
 import org.identityconnectors.framework.common.objects.Attribute;
 import org.identityconnectors.framework.common.objects.ConnectorObject;
-import org.identityconnectors.framework.common.objects.OperationOptions;
-import org.identityconnectors.framework.common.objects.Uid;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.ConfigurableApplicationContext;
 import org.springframework.stereotype.Component;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -100,9 +84,6 @@ public class ConnObjectUtils {
     private UserDAO userDAO;
 
     @Autowired
-    private AnyObjectDAO anyObjectDAO;
-
-    @Autowired
     private GroupDAO groupDAO;
 
     @Autowired
@@ -114,18 +95,9 @@ public class ConnObjectUtils {
     @Autowired
     private PasswordGenerator pwdGen;
 
-    @Autowired
-    private AnyUtilsFactory anyUtilsFactory;
-
     private final Encryptor encryptor = Encryptor.getInstance();
 
     /**
-     * Virtual attribute cache.
-     */
-    @Autowired
-    private VirAttrCache virAttrCache;
-
-    /**
      * Build a UserTO / GroupTO / AnyObjectTO out of connector object attributes and schema mapping.
      *
      * @param obj connector object
@@ -213,6 +185,8 @@ public class ConnObjectUtils {
             return (T) AnyOperations.diff(((UserTO) updated), ((UserTO) original), true);
         } else if (AnyTypeKind.GROUP == anyUtils.getAnyTypeKind()) {
             return (T) AnyOperations.diff(((GroupTO) updated), ((GroupTO) original), true);
+        } else if (AnyTypeKind.ANY_OBJECT == anyUtils.getAnyTypeKind()) {
+            return (T) AnyOperations.diff(((AnyObjectTO) updated), ((AnyObjectTO) original), true);
         }
 
         return null;
@@ -348,12 +322,14 @@ public class ConnObjectUtils {
         AnyTemplate anyTypeTemplate = syncTask.getTemplate(provision.getAnyType());
         if (anyTypeTemplate != null) {
             AnyTO template = anyTypeTemplate.get();
+            fillFromTemplate(anyTO, template);
 
-            if (template.getRealm() != null) {
-                anyTO.setRealm(template.getRealm());
-            }
-
-            if (template instanceof UserTO) {
+            if (template instanceof AnyObjectTO) {
+                fillRelationshipsFromTemplate(((AnyObjectTO) anyTO).getRelationshipMap(),
+                        ((AnyObjectTO) anyTO).getRelationships(), ((AnyObjectTO) template).getRelationships());
+                fillMembershipsFromTemplate(((AnyObjectTO) anyTO).getMembershipMap(),
+                        ((AnyObjectTO) anyTO).getMemberships(), ((AnyObjectTO) template).getMemberships());
+            } else if (template instanceof UserTO) {
                 if (StringUtils.isNotBlank(((UserTO) template).getUsername())) {
                     String evaluated = JexlUtils.evaluate(((UserTO) template).getUsername(), anyTO);
                     if (StringUtils.isNotBlank(evaluated)) {
@@ -367,8 +343,12 @@ public class ConnObjectUtils {
                         ((UserTO) anyTO).setPassword(evaluated);
                     }
                 }
-            }
-            if (template instanceof GroupTO) {
+
+                fillRelationshipsFromTemplate(((UserTO) anyTO).getRelationshipMap(),
+                        ((UserTO) anyTO).getRelationships(), ((UserTO) template).getRelationships());
+                fillMembershipsFromTemplate(((UserTO) anyTO).getMembershipMap(),
+                        ((UserTO) anyTO).getMemberships(), ((UserTO) template).getMemberships());
+            } else if (template instanceof GroupTO) {
                 if (StringUtils.isNotBlank(((GroupTO) template).getName())) {
                     String evaluated = JexlUtils.evaluate(((GroupTO) template).getName(), anyTO);
                     if (StringUtils.isNotBlank(evaluated)) {
@@ -389,12 +369,6 @@ public class ConnObjectUtils {
                     }
                 }
             }
-
-            fillFromTemplate(anyTO, template);
-
-            for (String resource : template.getResources()) {
-                anyTO.getResources().add(resource);
-            }
         }
 
         return anyTO;
@@ -467,171 +441,34 @@ public class ConnObjectUtils {
         return connObjectTO;
     }
 
-    /**
-     * Query connected external resources for values to populated virtual attributes associated with the given owner.
-     *
-     * @param any any object
-     */
-    public void retrieveVirAttrValues(final Any<?, ?, ?> any) {
-        ConfigurableApplicationContext context = ApplicationContextProvider.getApplicationContext();
-        ConnectorFactory connFactory = context.getBean(ConnectorFactory.class);
-
-        IntMappingType type = any.getType().getKind() == AnyTypeKind.USER
-                ? IntMappingType.UserVirtualSchema
-                : any.getType().getKind() == AnyTypeKind.GROUP
-                        ? IntMappingType.GroupVirtualSchema
-                        : IntMappingType.AnyVirtualSchema;
-
-        Map<String, ConnectorObject> resources = new HashMap<>();
-
-        // -----------------------
-        // Retrieve virtual attribute values if and only if they have not been retrieved yet
-        // -----------------------
-        for (VirAttr<?> virAttr : any.getVirAttrs()) {
-            // reset value set
-            if (virAttr.getValues().isEmpty()) {
-                retrieveVirAttrValue(any, virAttr, type, resources, connFactory);
-            }
-        }
-        // -----------------------
-    }
-
-    private void retrieveVirAttrValue(
-            final Any<?, ?, ?> any,
-            final VirAttr<?> virAttr,
-            final IntMappingType type,
-            final Map<String, ConnectorObject> externalResources,
-            final ConnectorFactory connFactory) {
-
-        String schemaName = virAttr.getSchema().getKey();
-        VirAttrCacheValue virAttrCacheValue = virAttrCache.get(any.getType().getKey(), any.getKey(), schemaName);
-
-        LOG.debug("Retrieve values for virtual attribute {} ({})", schemaName, type);
-
-        if (virAttrCache.isValidEntry(virAttrCacheValue)) {
-            // cached ...
-            LOG.debug("Values found in cache {}", virAttrCacheValue);
-            virAttr.getValues().clear();
-            virAttr.getValues().addAll(new ArrayList<>(virAttrCacheValue.getValues()));
-        } else {
-            // not cached ...
-            LOG.debug("Need one or more remote connections");
-
-            VirAttrCacheValue toBeCached = new VirAttrCacheValue();
-
-            AnyUtils anyUtils = anyUtilsFactory.getInstance(any);
-            Collection<ExternalResource> targetResources = getTargetResources(virAttr, type, anyUtils, any.getType());
-
-            for (ExternalResource resource : targetResources) {
-                Provision provision = resource.getProvision(any.getType());
-                LOG.debug("Search values into {},{}", resource, provision);
-
-                if (provision != null) {
-                    try {
-                        List<MappingItem> mappings = anyUtils.getMappingItems(provision, MappingPurpose.BOTH);
-
-                        ConnectorObject connectorObject;
-                        if (externalResources.containsKey(resource.getKey())) {
-                            connectorObject = externalResources.get(resource.getKey());
-                        } else {
-                            LOG.debug("Perform connection to {}", resource.getKey());
-                            String connObjectKey = anyUtils.getConnObjectKeyItem(provision) == null
-                                    ? null
-                                    : MappingUtils.getConnObjectKeyValue(any, provision);
-
-                            if (StringUtils.isBlank(connObjectKey)) {
-                                throw new IllegalArgumentException("No ConnObjectKey found for " + resource.getKey());
-                            }
-
-                            Connector connector = connFactory.getConnector(resource);
-
-                            OperationOptions oo =
-                                    connector.getOperationOptions(MappingUtils.getMatchingMappingItems(mappings, type));
-
-                            connectorObject =
-                                    connector.getObject(provision.getObjectClass(), new Uid(connObjectKey), oo);
-                            externalResources.put(resource.getKey(), connectorObject);
-                        }
-
-                        if (connectorObject != null) {
-                            // ask for searched virtual attribute value
-                            Collection<MappingItem> virAttrMappings =
-                                    MappingUtils.getMatchingMappingItems(mappings, schemaName, type);
-
-                            // the same virtual attribute could be mapped with one or more external attribute 
-                            for (MappingItem mapping : virAttrMappings) {
-                                Attribute attribute = connectorObject.getAttributeByName(mapping.getExtAttrName());
-
-                                if (attribute != null && attribute.getValue() != null) {
-                                    for (Object obj : attribute.getValue()) {
-                                        if (obj != null) {
-                                            virAttr.getValues().add(obj.toString());
-                                        }
-                                    }
-                                }
-                            }
-
-                            toBeCached.setResourceValues(resource.getKey(), new HashSet<>(virAttr.getValues()));
+    private AttrTO evaluateAttrFromTemplate(final AnyTO anyTO, final AttrTO template) {
+        AttrTO result = new AttrTO();
+        result.setSchema(template.getSchema());
 
-                            LOG.debug("Retrieved values {}", virAttr.getValues());
-                        }
-                    } catch (Exception e) {
-                        LOG.error("Error reading connector object from {}", resource.getKey(), e);
-
-                        if (virAttrCacheValue != null) {
-                            toBeCached.forceExpiring();
-                            LOG.debug("Search for a cached value (even expired!) ...");
-                            final Set<String> cachedValues = virAttrCacheValue.getValues(resource.getKey());
-                            if (cachedValues != null) {
-                                LOG.debug("Use cached value {}", cachedValues);
-                                virAttr.getValues().addAll(cachedValues);
-                                toBeCached.setResourceValues(resource.getKey(), new HashSet<>(cachedValues));
-                            }
-                        }
-                    }
+        if (template.getValues() != null && !template.getValues().isEmpty()) {
+            for (String value : template.getValues()) {
+                String evaluated = JexlUtils.evaluate(value, anyTO);
+                if (StringUtils.isNotBlank(evaluated)) {
+                    result.getValues().add(evaluated);
                 }
             }
-
-            virAttrCache.put(any.getType().getKey(), any.getKey(), schemaName, toBeCached);
         }
-    }
-
-    private Collection<ExternalResource> getTargetResources(
-            final VirAttr<?> attr, final IntMappingType type, final AnyUtils anyUtils, final AnyType anyType) {
-
-        Iterable<? extends ExternalResource> iterable = attr.getOwner() instanceof User
-                ? userDAO.findAllResources((User) attr.getOwner())
-                : attr.getOwner() instanceof AnyObject
-                        ? anyObjectDAO.findAllResources((AnyObject) attr.getOwner())
-                        : attr.getOwner() instanceof Group
-                                ? ((Group) attr.getOwner()).getResources()
-                                : Collections.<ExternalResource>emptySet();
-        return getTargetResources(attr, type, anyUtils, iterable, anyType);
-    }
-
-    private Collection<ExternalResource> getTargetResources(final VirAttr<?> attr, final IntMappingType type,
-            final AnyUtils anyUtils, final Iterable<? extends ExternalResource> ownerResources, final AnyType anyType) {
-
-        return CollectionUtils.select(ownerResources, new Predicate<ExternalResource>() {
 
-            @Override
-            public boolean evaluate(final ExternalResource resource) {
-                return resource.getProvision(anyType) != null
-                        && !MappingUtils.getMatchingMappingItems(
-                                anyUtils.getMappingItems(resource.getProvision(anyType), MappingPurpose.BOTH),
-                                attr.getSchema().getKey(), type).isEmpty();
-            }
-        });
+        return result;
     }
 
     private void fillFromTemplate(final AnyTO anyTO, final AnyTO template) {
+        if (template.getRealm() != null) {
+            anyTO.setRealm(template.getRealm());
+        }
+
         Map<String, AttrTO> currentAttrMap = anyTO.getPlainAttrMap();
-        for (AttrTO templateAttr : template.getPlainAttrs()) {
-            if (templateAttr.getValues() != null && !templateAttr.getValues().isEmpty()
-                    && (!currentAttrMap.containsKey(templateAttr.getSchema())
-                    || currentAttrMap.get(templateAttr.getSchema()).getValues().isEmpty())) {
+        for (AttrTO templatePlainAttr : template.getPlainAttrs()) {
+            if (!templatePlainAttr.getValues().isEmpty()
+                    && (!currentAttrMap.containsKey(templatePlainAttr.getSchema())
+                    || currentAttrMap.get(templatePlainAttr.getSchema()).getValues().isEmpty())) {
 
-                anyTO.getPlainAttrs().add(evaluateAttrTemplate(anyTO, templateAttr));
+                anyTO.getPlainAttrs().add(evaluateAttrFromTemplate(anyTO, templatePlainAttr));
             }
         }
 
@@ -644,29 +481,39 @@ public class ConnObjectUtils {
 
         currentAttrMap = anyTO.getVirAttrMap();
         for (AttrTO templateVirAttr : template.getVirAttrs()) {
-            if (templateVirAttr.getValues() != null && !templateVirAttr.getValues().isEmpty()
+            if (!templateVirAttr.getValues().isEmpty()
                     && (!currentAttrMap.containsKey(templateVirAttr.getSchema())
                     || currentAttrMap.get(templateVirAttr.getSchema()).getValues().isEmpty())) {
 
-                anyTO.getVirAttrs().add(evaluateAttrTemplate(anyTO, templateVirAttr));
+                anyTO.getVirAttrs().add(evaluateAttrFromTemplate(anyTO, templateVirAttr));
             }
         }
+
+        for (String resource : template.getResources()) {
+            anyTO.getResources().add(resource);
+        }
+
+        anyTO.getAuxClasses().addAll(template.getAuxClasses());
     }
 
-    private AttrTO evaluateAttrTemplate(final AnyTO anyTO, final AttrTO template) {
-        AttrTO result = new AttrTO();
-        result.setSchema(template.getSchema());
+    private void fillRelationshipsFromTemplate(final Map<Long, RelationshipTO> anyRelMap,
+            final List<RelationshipTO> anyRels, final List<RelationshipTO> templateRels) {
 
-        if (template.getValues() != null && !template.getValues().isEmpty()) {
-            for (String value : template.getValues()) {
-                String evaluated = JexlUtils.evaluate(value, anyTO);
-                if (StringUtils.isNotBlank(evaluated)) {
-                    result.getValues().add(evaluated);
-                }
+        for (RelationshipTO memb : templateRels) {
+            if (!anyRelMap.containsKey(memb.getRightKey())) {
+                anyRels.add(memb);
             }
         }
+    }
 
-        return result;
+    private void fillMembershipsFromTemplate(final Map<Long, MembershipTO> anyMembMap,
+            final List<MembershipTO> anyMembs, final List<MembershipTO> templateMembs) {
+
+        for (MembershipTO memb : templateMembs) {
+            if (!anyMembMap.containsKey(memb.getRightKey())) {
+                anyMembs.add(memb);
+            }
+        }
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/misc/src/main/java/org/apache/syncope/core/misc/MappingUtils.java
----------------------------------------------------------------------
diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/MappingUtils.java b/core/misc/src/main/java/org/apache/syncope/core/misc/MappingUtils.java
index a1931c1..2efae81 100644
--- a/core/misc/src/main/java/org/apache/syncope/core/misc/MappingUtils.java
+++ b/core/misc/src/main/java/org/apache/syncope/core/misc/MappingUtils.java
@@ -64,6 +64,7 @@ import org.apache.syncope.core.persistence.api.entity.Any;
 import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
 import org.apache.syncope.core.persistence.api.entity.resource.Mapping;
 import org.apache.syncope.core.persistence.api.entity.resource.Provision;
+import org.apache.syncope.core.provisioning.api.VirAttrHandler;
 import org.identityconnectors.framework.common.FrameworkUtil;
 import org.identityconnectors.framework.common.objects.Attribute;
 import org.identityconnectors.framework.common.objects.AttributeBuilder;
@@ -230,7 +231,7 @@ public final class MappingUtils {
 
         ConfigurableApplicationContext context = ApplicationContextProvider.getApplicationContext();
         AnyUtilsFactory anyUtilsFactory = context.getBean(AnyUtilsFactory.class);
-        ConnObjectUtils connObjectUtils = context.getBean(ConnObjectUtils.class);
+        VirAttrHandler virAttrHandler = context.getBean(VirAttrHandler.class);
 
         switch (mapItem.getIntMappingType().getAnyTypeKind()) {
             case USER:
@@ -243,7 +244,7 @@ public final class MappingUtils {
                 if (any instanceof User) {
                     UserDAO userDAO = context.getBean(UserDAO.class);
                     for (Group group : userDAO.findAllGroups((User) any)) {
-                        connObjectUtils.retrieveVirAttrValues(group);
+                        virAttrHandler.retrieveVirAttrValues(group);
                         anys.add(group);
                     }
                 } else if (any instanceof Group) {
@@ -266,7 +267,7 @@ public final class MappingUtils {
         PlainSchema schema = null;
         boolean readOnlyVirSchema = false;
         AttrSchemaType schemaType;
-        final Pair<String, Attribute> result;
+        Pair<String, Attribute> result;
 
         switch (mapItem.getIntMappingType()) {
             case UserPlainSchema:
@@ -290,7 +291,7 @@ public final class MappingUtils {
                 schemaType = AttrSchemaType.String;
         }
 
-        final String extAttrName = mapItem.getExtAttrName();
+        String extAttrName = mapItem.getExtAttrName();
 
         LOG.debug("Define mapping for: "
                 + "\n* ExtAttrName " + extAttrName
@@ -389,7 +390,7 @@ public final class MappingUtils {
         if (StringUtils.isNotBlank(anyUtils.getConnObjectLink(provision))) {
             final JexlContext jexlContext = new MapContext();
             JexlUtils.addFieldsToContext(any, jexlContext);
-            JexlUtils.addAttrsToContext(any.getPlainAttrs(), jexlContext);
+            JexlUtils.addPlainAttrsToContext(any.getPlainAttrs(), jexlContext);
             JexlUtils.addDerAttrsToContext(any.getDerAttrs(), any.getPlainAttrs(), jexlContext);
             evalConnObjectLink = JexlUtils.evaluate(anyUtils.getConnObjectLink(provision), jexlContext);
         }
@@ -443,6 +444,8 @@ public final class MappingUtils {
 
         EntityFactory entityFactory =
                 ApplicationContextProvider.getApplicationContext().getBean(EntityFactory.class);
+        AnyUtilsFactory anyUtilsFactory =
+                ApplicationContextProvider.getApplicationContext().getBean(AnyUtilsFactory.class);
         List<PlainAttrValue> values = new ArrayList<>();
         PlainAttrValue attrValue;
         switch (mappingItem.getIntMappingType()) {
@@ -472,6 +475,7 @@ public final class MappingUtils {
             case GroupVirtualSchema:
             case AnyVirtualSchema:
                 for (Any<?, ?, ?> any : anys) {
+                    AnyUtils anyUtils = anyUtilsFactory.getInstance(any);
                     VirAttr<?> virAttr = any.getVirAttr(mappingItem.getIntAttrName());
                     if (virAttr != null) {
                         if (vAttrsToBeRemoved != null && vAttrsToBeUpdated != null) {
@@ -488,7 +492,7 @@ public final class MappingUtils {
                         }
                         if (virAttr.getValues() != null) {
                             for (String value : virAttr.getValues()) {
-                                attrValue = entityFactory.newEntity(UPlainAttrValue.class);
+                                attrValue = anyUtils.newPlainAttrValue();
                                 attrValue.setStringValue(value);
                                 values.add(attrValue);
                             }
@@ -508,11 +512,10 @@ public final class MappingUtils {
             case GroupDerivedSchema:
             case AnyDerivedSchema:
                 for (Any<?, ?, ?> any : anys) {
+                    AnyUtils anyUtils = anyUtilsFactory.getInstance(any);
                     DerAttr<?> derAttr = any.getDerAttr(mappingItem.getIntAttrName());
                     if (derAttr != null) {
-                        attrValue = any instanceof Group
-                                ? entityFactory.newEntity(GPlainAttrValue.class)
-                                : entityFactory.newEntity(UPlainAttrValue.class);
+                        attrValue = anyUtils.newPlainAttrValue();
                         attrValue.setStringValue(derAttr.getValue(any.getPlainAttrs()));
                         values.add(attrValue);
                     }
@@ -529,7 +532,8 @@ public final class MappingUtils {
             case GroupId:
             case AnyId:
                 for (Any<?, ?, ?> any : anys) {
-                    attrValue = entityFactory.newEntity(UPlainAttrValue.class);
+                    AnyUtils anyUtils = anyUtilsFactory.getInstance(any);
+                    attrValue = anyUtils.newPlainAttrValue();
                     attrValue.setStringValue(any.getKey().toString());
                     values.add(attrValue);
                 }
@@ -600,7 +604,6 @@ public final class MappingUtils {
      * @return connObjectKey internal value
      */
     public static String getConnObjectKeyValue(final Any<?, ?, ?> any, final Provision provision) {
-
         List<PlainAttrValue> values = getIntValues(provision, provision.getMapping().getConnObjectKeyItem(),
                 Collections.<Any<?, ?, ?>>singletonList(any), null, null);
         return values == null || values.isEmpty()

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/misc/src/main/java/org/apache/syncope/core/misc/jexl/JexlUtils.java
----------------------------------------------------------------------
diff --git a/core/misc/src/main/java/org/apache/syncope/core/misc/jexl/JexlUtils.java b/core/misc/src/main/java/org/apache/syncope/core/misc/jexl/JexlUtils.java
index 83e98ec..9aad079 100644
--- a/core/misc/src/main/java/org/apache/syncope/core/misc/jexl/JexlUtils.java
+++ b/core/misc/src/main/java/org/apache/syncope/core/misc/jexl/JexlUtils.java
@@ -146,7 +146,7 @@ public final class JexlUtils {
         return context;
     }
 
-    public static JexlContext addAttrsToContext(final Collection<? extends PlainAttr<?>> attrs,
+    public static JexlContext addPlainAttrsToContext(final Collection<? extends PlainAttr<?>> attrs,
             final JexlContext jexlContext) {
 
         JexlContext context = jexlContext == null
@@ -215,11 +215,9 @@ public final class JexlUtils {
         return context;
     }
 
-    public static boolean evaluateMandatoryCondition(
-            final String mandatoryCondition, final Any<?, ?, ?> any) {
-
+    public static boolean evaluateMandatoryCondition(final String mandatoryCondition, final Any<?, ?, ?> any) {
         JexlContext jexlContext = new MapContext();
-        addAttrsToContext(any.getPlainAttrs(), jexlContext);
+        addPlainAttrsToContext(any.getPlainAttrs(), jexlContext);
         addDerAttrsToContext(any.getDerAttrs(), any.getPlainAttrs(), jexlContext);
         addVirAttrsToContext(any.getVirAttrs(), jexlContext);
 
@@ -229,8 +227,8 @@ public final class JexlUtils {
     public static String evaluate(final String expression,
             final Any<?, ?, ?> any, final Collection<? extends PlainAttr<?>> attributes) {
 
-        final JexlContext jexlContext = new MapContext();
-        JexlUtils.addAttrsToContext(attributes, jexlContext);
+        JexlContext jexlContext = new MapContext();
+        JexlUtils.addPlainAttrsToContext(attributes, jexlContext);
         JexlUtils.addFieldsToContext(any, jexlContext);
 
         // Evaluate expression using the context prepared before

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/UnallowedSchemaException.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/UnallowedSchemaException.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/UnallowedSchemaException.java
new file mode 100644
index 0000000..04f67dd
--- /dev/null
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/dao/UnallowedSchemaException.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.persistence.api.dao;
+
+public class UnallowedSchemaException extends RuntimeException {
+
+    private static final long serialVersionUID = -9206535191442808016L;
+
+    public UnallowedSchemaException(final String schemaName) {
+        super(schemaName + " not allowed");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/anyobject/AnyObject.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/anyobject/AnyObject.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/anyobject/AnyObject.java
index ddb047e..19d0f6b 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/anyobject/AnyObject.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/anyobject/AnyObject.java
@@ -27,7 +27,7 @@ public interface AnyObject extends Any<APlainAttr, ADerAttr, AVirAttr> {
 
     boolean remove(ARelationship relationship);
 
-    ARelationship getRelationship(AnyObject rightEnd);
+    ARelationship getRelationship(Long relationshipKey);
 
     List<? extends ARelationship> getRelationships();
 
@@ -35,7 +35,7 @@ public interface AnyObject extends Any<APlainAttr, ADerAttr, AVirAttr> {
 
     boolean remove(AMembership membership);
 
-    AMembership getMembership(Long groupKey);
+    AMembership getMembership(Long membershipKey);
 
     List<? extends AMembership> getMemberships();
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/task/ProvisioningTask.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/task/ProvisioningTask.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/task/ProvisioningTask.java
index e1b9a5e..296de84 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/task/ProvisioningTask.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/task/ProvisioningTask.java
@@ -18,7 +18,7 @@
  */
 package org.apache.syncope.core.persistence.api.entity.task;
 
-import java.util.List;
+import java.util.Set;
 import org.apache.syncope.common.lib.types.MatchingRule;
 import org.apache.syncope.common.lib.types.UnmatchingRule;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
@@ -29,7 +29,7 @@ public interface ProvisioningTask extends SchedTask {
 
     void setResource(ExternalResource resource);
 
-    List<String> getActionsClassNames();
+    Set<String> getActionsClassNames();
 
     MatchingRule getMatchingRule();
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/user/User.java
----------------------------------------------------------------------
diff --git a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/user/User.java b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/user/User.java
index d896984..f02c555 100644
--- a/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/user/User.java
+++ b/core/persistence-api/src/main/java/org/apache/syncope/core/persistence/api/entity/user/User.java
@@ -23,7 +23,6 @@ import java.util.List;
 import org.apache.syncope.common.lib.types.CipherAlgorithm;
 import org.apache.syncope.core.persistence.api.entity.Any;
 import org.apache.syncope.core.persistence.api.entity.Role;
-import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
 
 public interface User extends Any<UPlainAttr, UDerAttr, UVirAttr> {
 
@@ -133,7 +132,7 @@ public interface User extends Any<UPlainAttr, UDerAttr, UVirAttr> {
 
     boolean remove(URelationship relationship);
 
-    URelationship getRelationship(AnyObject rightEnd);
+    URelationship getRelationship(Long anyObjectKey);
 
     List<? extends URelationship> getRelationships();
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractAnyDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractAnyDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractAnyDAO.java
index 3448737..ef2161e 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractAnyDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/AbstractAnyDAO.java
@@ -89,7 +89,8 @@ public abstract class AbstractAnyDAO<A extends Any<?, ?, ?>> extends AbstractDAO
 
         A any = find(key);
         if (any == null) {
-            throw new NotFoundException("Any " + key);
+            throw new NotFoundException(StringUtils.substringBefore(
+                    StringUtils.substringAfter(getClass().getSimpleName(), "JPA"), "DAO") + " " + key);
         }
 
         securityChecks(any);

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADerSchemaDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADerSchemaDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADerSchemaDAO.java
index a849ef5..18b6636 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADerSchemaDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPADerSchemaDAO.java
@@ -102,7 +102,9 @@ public class JPADerSchemaDAO extends AbstractDAO<DerSchema, String> implements D
             resourceDAO.deleteMapping(key, anyUtils.derIntMappingType());
         }
 
-        schema.getAnyTypeClass().remove(schema);
+        if (schema.getAnyTypeClass() != null) {
+            schema.getAnyTypeClass().remove(schema);
+        }
 
         entityManager.remove(schema);
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPlainSchemaDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPlainSchemaDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPlainSchemaDAO.java
index 50865c3..c3c94ce 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPlainSchemaDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAPlainSchemaDAO.java
@@ -102,7 +102,9 @@ public class JPAPlainSchemaDAO extends AbstractDAO<PlainSchema, String> implemen
             resourceDAO.deleteMapping(key, anyUtils.plainIntMappingType());
         }
 
-        schema.getAnyTypeClass().remove(schema);
+        if (schema.getAnyTypeClass() != null) {
+            schema.getAnyTypeClass().remove(schema);
+        }
 
         entityManager.remove(schema);
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAVirSchemaDAO.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAVirSchemaDAO.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAVirSchemaDAO.java
index cc4ffe4..dae6afc 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAVirSchemaDAO.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/dao/JPAVirSchemaDAO.java
@@ -102,7 +102,9 @@ public class JPAVirSchemaDAO extends AbstractDAO<VirSchema, String> implements V
             resourceDAO.deleteMapping(key, anyUtils.virIntMappingType());
         }
 
-        schema.getAnyTypeClass().remove(schema);
+        if (schema.getAnyTypeClass() != null) {
+            schema.getAnyTypeClass().remove(schema);
+        }
 
         entityManager.remove(schema);
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractAttr.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractAttr.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractAttr.java
index 914bd02..ec37649 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractAttr.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractAttr.java
@@ -20,6 +20,7 @@ package org.apache.syncope.core.persistence.jpa.entity;
 
 import java.util.Collections;
 import java.util.Set;
+import org.apache.syncope.core.persistence.api.dao.UnallowedSchemaException;
 import org.apache.syncope.core.persistence.api.entity.Any;
 import org.apache.syncope.core.persistence.api.entity.Attr;
 import org.apache.syncope.core.persistence.api.entity.DerSchema;
@@ -53,7 +54,7 @@ public abstract class AbstractAttr<S extends Schema, O extends Any<?, ?, ?>>
         }
 
         if (!getAllowedSchemas(getOwner()).contains(schema)) {
-            throw new IllegalArgumentException(schema + " not allowed for this instance");
+            throw new UnallowedSchemaException(schema.getKey());
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractDerAttr.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractDerAttr.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractDerAttr.java
index fba234d..4500a4e 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractDerAttr.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractDerAttr.java
@@ -21,9 +21,6 @@ package org.apache.syncope.core.persistence.jpa.entity;
 import java.util.Collection;
 import javax.persistence.Column;
 import javax.persistence.FetchType;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import javax.persistence.Id;
 import javax.persistence.ManyToOne;
 import javax.persistence.MappedSuperclass;
 import org.apache.syncope.core.persistence.api.entity.DerAttr;
@@ -38,20 +35,11 @@ public abstract class AbstractDerAttr<O extends Any<?, ?, ?>>
 
     private static final long serialVersionUID = 4740924251090424771L;
 
-    @Id
-    @GeneratedValue(strategy = GenerationType.AUTO)
-    protected Long id;
-
     @ManyToOne(fetch = FetchType.EAGER)
     @Column(name = "schema_name")
     private JPADerSchema schema;
 
     @Override
-    public Long getKey() {
-        return id;
-    }
-
-    @Override
     public DerSchema getSchema() {
         return schema;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractVirAttr.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractVirAttr.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractVirAttr.java
index 946b09b..aebc8da 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractVirAttr.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/AbstractVirAttr.java
@@ -22,9 +22,6 @@ import java.util.ArrayList;
 import java.util.List;
 import javax.persistence.Column;
 import javax.persistence.FetchType;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import javax.persistence.Id;
 import javax.persistence.ManyToOne;
 import javax.persistence.MappedSuperclass;
 import javax.persistence.Transient;
@@ -38,10 +35,6 @@ public abstract class AbstractVirAttr<O extends Any<?, ?, ?>>
 
     private static final long serialVersionUID = 5023204776925954907L;
 
-    @Id
-    @GeneratedValue(strategy = GenerationType.AUTO)
-    protected Long id;
-
     @Transient
     protected List<String> values = new ArrayList<>();
 
@@ -50,11 +43,6 @@ public abstract class AbstractVirAttr<O extends Any<?, ?, ?>>
     private JPAVirSchema schema;
 
     @Override
-    public Long getKey() {
-        return id;
-    }
-
-    @Override
     public List<String> getValues() {
         return values;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAADerAttr.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAADerAttr.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAADerAttr.java
index abd6676..1525de9 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAADerAttr.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAADerAttr.java
@@ -19,6 +19,7 @@
 package org.apache.syncope.core.persistence.jpa.entity.anyobject;
 
 import javax.persistence.Entity;
+import javax.persistence.Id;
 import javax.persistence.ManyToOne;
 import javax.persistence.Table;
 import org.apache.syncope.core.persistence.api.entity.anyobject.ADerAttr;
@@ -33,10 +34,18 @@ public class JPAADerAttr extends AbstractDerAttr<AnyObject> implements ADerAttr
 
     public static final String TABLE = "ADerAttr";
 
+    @Id
+    private Long id;
+
     @ManyToOne
     private JPAAnyObject owner;
 
     @Override
+    public Long getKey() {
+        return id;
+    }
+
+    @Override
     public AnyObject getOwner() {
         return owner;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAVirAttr.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAVirAttr.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAVirAttr.java
index 7469799..62e2ea5 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAVirAttr.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAVirAttr.java
@@ -19,6 +19,7 @@
 package org.apache.syncope.core.persistence.jpa.entity.anyobject;
 
 import javax.persistence.Entity;
+import javax.persistence.Id;
 import javax.persistence.ManyToOne;
 import javax.persistence.Table;
 import org.apache.syncope.core.persistence.api.entity.anyobject.AVirAttr;
@@ -33,10 +34,18 @@ public class JPAAVirAttr extends AbstractVirAttr<AnyObject> implements AVirAttr
 
     public static final String TABLE = "AVirAttr";
 
+    @Id
+    private Long id;
+
     @ManyToOne
     private JPAAnyObject owner;
 
     @Override
+    public Long getKey() {
+        return id;
+    }
+
+    @Override
     public AnyObject getOwner() {
         return owner;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAnyObject.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAnyObject.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAnyObject.java
index 6442c2d..a8e842b 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAnyObject.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/anyobject/JPAAnyObject.java
@@ -198,12 +198,12 @@ public class JPAAnyObject extends AbstractAny<APlainAttr, ADerAttr, AVirAttr> im
     }
 
     @Override
-    public ARelationship getRelationship(final AnyObject rightEnd) {
+    public ARelationship getRelationship(final Long anyObjectKey) {
         return CollectionUtils.find(getRelationships(), new Predicate<ARelationship>() {
 
             @Override
             public boolean evaluate(final ARelationship relationship) {
-                return rightEnd != null && rightEnd.equals(relationship.getRightEnd());
+                return anyObjectKey != null && anyObjectKey.equals(relationship.getRightEnd().getKey());
             }
         });
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGDerAttr.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGDerAttr.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGDerAttr.java
index 46fc1cd..73911f8 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGDerAttr.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGDerAttr.java
@@ -19,6 +19,7 @@
 package org.apache.syncope.core.persistence.jpa.entity.group;
 
 import javax.persistence.Entity;
+import javax.persistence.Id;
 import javax.persistence.ManyToOne;
 import javax.persistence.Table;
 import org.apache.syncope.core.persistence.api.entity.group.GDerAttr;
@@ -33,10 +34,18 @@ public class JPAGDerAttr extends AbstractDerAttr<Group> implements GDerAttr {
 
     public static final String TABLE = "GDerAttr";
 
+    @Id
+    private Long id;
+
     @ManyToOne
     private JPAGroup owner;
 
     @Override
+    public Long getKey() {
+        return id;
+    }
+
+    @Override
     public Group getOwner() {
         return owner;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGVirAttr.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGVirAttr.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGVirAttr.java
index 302e056..47b8886 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGVirAttr.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/group/JPAGVirAttr.java
@@ -19,6 +19,7 @@
 package org.apache.syncope.core.persistence.jpa.entity.group;
 
 import javax.persistence.Entity;
+import javax.persistence.Id;
 import javax.persistence.ManyToOne;
 import javax.persistence.Table;
 import org.apache.syncope.core.persistence.api.entity.group.GVirAttr;
@@ -33,10 +34,18 @@ public class JPAGVirAttr extends AbstractVirAttr<Group> implements GVirAttr {
 
     public static final String TABLE = "GVirAttr";
 
+    @Id
+    private Long id;
+
     @ManyToOne
     private JPAGroup owner;
 
     @Override
+    public Long getKey() {
+        return id;
+    }
+
+    @Override
     public Group getOwner() {
         return owner;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAAnyTemplate.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAAnyTemplate.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAAnyTemplate.java
index d90f605..7af8491 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAAnyTemplate.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAAnyTemplate.java
@@ -87,7 +87,9 @@ public class JPAAnyTemplate extends AbstractEntity<Long> implements AnyTemplate
                 ? anyType == null
                         ? null
                         : new JPAAnyUtilsFactory().getInstance(anyType.getKind()).newAnyTO()
-                : POJOHelper.deserialize(template, AnyTO.class);
+                : anyType == null
+                        ? null
+                        : POJOHelper.deserialize(template, anyType.getKind().getToClass());
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPAPushTask.java
----------------------------------------------------------------------
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 07e6f00..0592a9d 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
@@ -19,7 +19,9 @@
 package org.apache.syncope.core.persistence.jpa.entity.task;
 
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 import javax.persistence.CascadeType;
 import javax.persistence.CollectionTable;
 import javax.persistence.Column;
@@ -48,7 +50,7 @@ public class JPAPushTask extends AbstractProvisioningTask implements PushTask {
     @CollectionTable(name = "PushTask_actionsClassNames",
             joinColumns =
             @JoinColumn(name = "pushTask_id", referencedColumnName = "id"))
-    private List<String> actionsClassNames = new ArrayList<>();
+    private Set<String> actionsClassNames = new HashSet<>();
 
     @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "pushTask")
     private List<JPAAnyFilter> filters = new ArrayList<>();
@@ -61,7 +63,7 @@ public class JPAPushTask extends AbstractProvisioningTask implements PushTask {
     }
 
     @Override
-    public List<String> getActionsClassNames() {
+    public Set<String> getActionsClassNames() {
         return actionsClassNames;
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPASyncTask.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPASyncTask.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPASyncTask.java
index 0106a65..41eb4ea 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPASyncTask.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/task/JPASyncTask.java
@@ -19,7 +19,9 @@
 package org.apache.syncope.core.persistence.jpa.entity.task;
 
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 import javax.persistence.Basic;
 import javax.persistence.CascadeType;
 import javax.persistence.CollectionTable;
@@ -57,7 +59,7 @@ public class JPASyncTask extends AbstractProvisioningTask implements SyncTask {
     @CollectionTable(name = "SyncTask_actionsClassNames",
             joinColumns =
             @JoinColumn(name = "syncTask_id", referencedColumnName = "id"))
-    private List<String> actionsClassNames = new ArrayList<>();
+    private Set<String> actionsClassNames = new HashSet<>();
 
     @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.EAGER, mappedBy = "syncTask")
     private List<JPAAnyTemplate> templates = new ArrayList<>();
@@ -86,7 +88,7 @@ public class JPASyncTask extends AbstractProvisioningTask implements SyncTask {
     }
 
     @Override
-    public List<String> getActionsClassNames() {
+    public Set<String> getActionsClassNames() {
         return actionsClassNames;
     }
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUDerAttr.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUDerAttr.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUDerAttr.java
index 90bee1b..754fd59 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUDerAttr.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUDerAttr.java
@@ -19,6 +19,7 @@
 package org.apache.syncope.core.persistence.jpa.entity.user;
 
 import javax.persistence.Entity;
+import javax.persistence.Id;
 import javax.persistence.ManyToOne;
 import javax.persistence.Table;
 import org.apache.syncope.core.persistence.api.entity.user.UDerAttr;
@@ -33,10 +34,18 @@ public class JPAUDerAttr extends AbstractDerAttr<User> implements UDerAttr {
 
     public static final String TABLE = "UDerAttr";
 
+    @Id
+    private Long id;
+
     @ManyToOne
     private JPAUser owner;
 
     @Override
+    public Long getKey() {
+        return id;
+    }
+
+    @Override
     public User getOwner() {
         return owner;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUPlainAttr.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUPlainAttr.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUPlainAttr.java
index 56898d4..50ce967 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUPlainAttr.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUPlainAttr.java
@@ -45,9 +45,6 @@ public class JPAUPlainAttr extends AbstractPlainAttr<User> implements UPlainAttr
 
     public static final String TABLE = "UPlainAttr";
 
-    /**
-     * Auto-generated id for this table.
-     */
     @Id
     private Long id;
 

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUVirAttr.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUVirAttr.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUVirAttr.java
index 52a168e..a6931ce 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUVirAttr.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUVirAttr.java
@@ -19,6 +19,7 @@
 package org.apache.syncope.core.persistence.jpa.entity.user;
 
 import javax.persistence.Entity;
+import javax.persistence.Id;
 import javax.persistence.ManyToOne;
 import javax.persistence.Table;
 import org.apache.syncope.core.persistence.api.entity.user.UVirAttr;
@@ -33,10 +34,18 @@ public class JPAUVirAttr extends AbstractVirAttr<User> implements UVirAttr {
 
     public static final String TABLE = "UVirAttr";
 
+    @Id
+    private Long id;
+
     @ManyToOne
     private JPAUser owner;
 
     @Override
+    public Long getKey() {
+        return id;
+    }
+
+    @Override
     public User getOwner() {
         return owner;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUser.java
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUser.java b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUser.java
index f9c0c81..06d8f04 100644
--- a/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUser.java
+++ b/core/persistence-jpa/src/main/java/org/apache/syncope/core/persistence/jpa/entity/user/JPAUser.java
@@ -65,7 +65,6 @@ import org.apache.syncope.core.persistence.api.dao.AnyTypeDAO;
 import org.apache.syncope.core.persistence.api.entity.AnyType;
 import org.apache.syncope.core.persistence.api.entity.AnyTypeClass;
 import org.apache.syncope.core.persistence.api.entity.Role;
-import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
 import org.apache.syncope.core.persistence.api.entity.user.UMembership;
 import org.apache.syncope.core.persistence.api.entity.user.URelationship;
 import org.apache.syncope.core.persistence.jpa.entity.AbstractAny;
@@ -538,12 +537,12 @@ public class JPAUser extends AbstractAny<UPlainAttr, UDerAttr, UVirAttr> impleme
     }
 
     @Override
-    public URelationship getRelationship(final AnyObject rightEnd) {
+    public URelationship getRelationship(final Long anyObjectKey) {
         return CollectionUtils.find(getRelationships(), new Predicate<URelationship>() {
 
             @Override
             public boolean evaluate(final URelationship relationship) {
-                return rightEnd != null && rightEnd.equals(relationship.getRightEnd());
+                return anyObjectKey != null && anyObjectKey.equals(relationship.getRightEnd().getKey());
             }
         });
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/persistence-jpa/src/main/resources/META-INF/spring-orm-oracle.xml
----------------------------------------------------------------------
diff --git a/core/persistence-jpa/src/main/resources/META-INF/spring-orm-oracle.xml b/core/persistence-jpa/src/main/resources/META-INF/spring-orm-oracle.xml
index c592c31..a75e4b6 100644
--- a/core/persistence-jpa/src/main/resources/META-INF/spring-orm-oracle.xml
+++ b/core/persistence-jpa/src/main/resources/META-INF/spring-orm-oracle.xml
@@ -312,6 +312,56 @@ under the License.
     </attributes>
   </entity>
 
+  <entity class="org.apache.syncope.core.persistence.jpa.entity.anyobject.JPAADerAttr">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_ADerAttr" strategy="TABLE"/>
+        <table-generator name="SEQ_ADerAttr" pk-column-value="SEQ_ADerAttr" initial-value="1000"/>
+      </id>
+    </attributes>
+  </entity>
+  <entity class="org.apache.syncope.core.persistence.jpa.entity.user.JPAUDerAttr">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_UDerAttr" strategy="TABLE"/>
+        <table-generator name="SEQ_UDerAttr" pk-column-value="SEQ_UDerAttr" initial-value="1000"/>
+      </id>
+    </attributes>
+  </entity>
+  <entity class="org.apache.syncope.core.persistence.jpa.entity.group.JPAGDerAttr">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_GDerAttr" strategy="TABLE"/>
+        <table-generator name="SEQ_GDerAttr" pk-column-value="SEQ_GDerAttr" initial-value="1000"/>
+      </id>
+    </attributes>
+  </entity>
+
+  <entity class="org.apache.syncope.core.persistence.jpa.entity.anyobject.JPAAVirAttr">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_AVirAttr" strategy="TABLE"/>
+        <table-generator name="SEQ_AVirAttr" pk-column-value="SEQ_AVirAttr" initial-value="1000"/>
+      </id>
+    </attributes>
+  </entity>
+  <entity class="org.apache.syncope.core.persistence.jpa.entity.user.JPAUVirAttr">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_UVirAttr" strategy="TABLE"/>
+        <table-generator name="SEQ_UVirAttr" pk-column-value="SEQ_UVirAttr" initial-value="1000"/>
+      </id>
+    </attributes>
+  </entity>
+  <entity class="org.apache.syncope.core.persistence.jpa.entity.group.JPAGVirAttr">
+    <attributes>
+      <id name="id">
+        <generated-value generator="SEQ_GVirAttr" strategy="TABLE"/>
+        <table-generator name="SEQ_GVirAttr" pk-column-value="SEQ_GVirAttr" initial-value="1000"/>
+      </id>
+    </attributes>
+  </entity>
+
   <entity class="org.apache.syncope.core.persistence.jpa.entity.task.JPAAnyTemplate">
     <attributes>
       <id name="id">


[18/21] syncope git commit: [SYNCOPE-666] All tests are green, time to add more

Posted by il...@apache.org.
http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java
index fb01aa4..4a8a35b 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AbstractAnyDataBinder.java
@@ -18,14 +18,17 @@
  */
 package org.apache.syncope.core.provisioning.java.data;
 
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.Transformer;
+import org.apache.commons.lang3.ArrayUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.SyncopeClientCompositeException;
 import org.apache.syncope.common.lib.SyncopeClientException;
@@ -33,6 +36,8 @@ import org.apache.syncope.common.lib.mod.AnyMod;
 import org.apache.syncope.common.lib.mod.AttrMod;
 import org.apache.syncope.common.lib.to.AnyTO;
 import org.apache.syncope.common.lib.to.AttrTO;
+import org.apache.syncope.common.lib.to.MembershipTO;
+import org.apache.syncope.common.lib.to.RelationshipTO;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
 import org.apache.syncope.common.lib.types.IntMappingType;
 import org.apache.syncope.common.lib.types.MappingPurpose;
@@ -60,21 +65,25 @@ import org.apache.syncope.core.persistence.api.entity.VirSchema;
 import org.apache.syncope.core.persistence.api.entity.group.Group;
 import org.apache.syncope.common.lib.types.PropagationByResource;
 import org.apache.syncope.core.misc.ConnObjectUtils;
-import org.apache.syncope.core.provisioning.java.VirAttrHandler;
 import org.apache.syncope.core.misc.MappingUtils;
 import org.apache.syncope.core.misc.jexl.JexlUtils;
 import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
+import org.apache.syncope.core.persistence.api.dao.AnyTypeClassDAO;
 import org.apache.syncope.core.persistence.api.dao.NotFoundException;
 import org.apache.syncope.core.persistence.api.dao.RealmDAO;
 import org.apache.syncope.core.persistence.api.entity.Any;
+import org.apache.syncope.core.persistence.api.entity.AnyTypeClass;
 import org.apache.syncope.core.persistence.api.entity.AnyUtils;
 import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
+import org.apache.syncope.core.persistence.api.entity.Membership;
 import org.apache.syncope.core.persistence.api.entity.Realm;
+import org.apache.syncope.core.persistence.api.entity.Relationship;
 import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
 import org.apache.syncope.core.persistence.api.entity.resource.ExternalResource;
 import org.apache.syncope.core.persistence.api.entity.resource.MappingItem;
 import org.apache.syncope.core.persistence.api.entity.resource.Provision;
 import org.apache.syncope.core.persistence.api.entity.user.User;
+import org.apache.syncope.core.provisioning.api.VirAttrHandler;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -83,10 +92,18 @@ abstract class AbstractAnyDataBinder {
 
     protected static final Logger LOG = LoggerFactory.getLogger(AbstractAnyDataBinder.class);
 
+    private static final IntMappingType[] FOR_MANDATORY = new IntMappingType[] {
+        IntMappingType.AnyPlainSchema, IntMappingType.AnyDerivedSchema,
+        IntMappingType.UserPlainSchema, IntMappingType.UserDerivedSchema,
+        IntMappingType.GroupPlainSchema, IntMappingType.GroupDerivedSchema };
+
     @Autowired
     protected RealmDAO realmDAO;
 
     @Autowired
+    protected AnyTypeClassDAO anyTypeClassDAO;
+
+    @Autowired
     protected AnyObjectDAO anyObjectDAO;
 
     @Autowired
@@ -129,7 +146,7 @@ abstract class AbstractAnyDataBinder {
     protected AnyUtilsFactory anyUtilsFactory;
 
     @Autowired
-    protected VirAttrHandler virtAttrHander;
+    protected VirAttrHandler virAttrHander;
 
     @Autowired
     protected ConnObjectUtils connObjectUtils;
@@ -138,7 +155,7 @@ abstract class AbstractAnyDataBinder {
         if (StringUtils.isNotBlank(anyMod.getRealm())) {
             Realm newRealm = realmDAO.find(anyMod.getRealm());
             if (newRealm == null) {
-                LOG.warn("Invalid realm specified: {}, ignoring", anyMod.getRealm());
+                LOG.debug("Invalid realm specified: {}, ignoring", anyMod.getRealm());
             } else {
                 any.setRealm(newRealm);
             }
@@ -155,7 +172,6 @@ abstract class AbstractAnyDataBinder {
                 LOG.debug("Ignoring invalid schema {}", schemaName);
             } else if (schema.isReadonly()) {
                 schema = null;
-
                 LOG.debug("Ignoring readonly schema {}", schemaName);
             }
         }
@@ -175,7 +191,7 @@ abstract class AbstractAnyDataBinder {
         return schema;
     }
 
-    protected void fillAttribute(final List<String> values, final AnyUtils anyUtils,
+    private void fillAttribute(final List<String> values, final AnyUtils anyUtils,
             final PlainSchema schema, final PlainAttr<?> attr, final SyncopeClientException invalidValues) {
 
         // if schema is multivalue, all values are considered for addition;
@@ -201,54 +217,57 @@ abstract class AbstractAnyDataBinder {
         }
     }
 
-    private boolean evaluateMandatoryCondition(final AnyUtils anyUtils, final ExternalResource resource,
-            final Any<?, ?, ?> any, final String intAttrName, final IntMappingType intMappingType) {
+    private List<String> evaluateMandatoryCondition(final Provision provision, final Any<?, ?, ?> any) {
+        List<String> missingAttrNames = new ArrayList<>();
+
+        if (provision != null) {
+            for (MappingItem item : provision.getMapping().getItems()) {
+                if (ArrayUtils.contains(FOR_MANDATORY, item.getIntMappingType())
+                        && (item.getPurpose() == MappingPurpose.PROPAGATION
+                        || item.getPurpose() == MappingPurpose.BOTH)) {
 
-        boolean result = false;
+                    List<PlainAttrValue> values = MappingUtils.getIntValues(
+                            provision, item, Collections.<Any<?, ?, ?>>singletonList(any), null, null);
+                    if ((values == null || values.isEmpty())
+                            && JexlUtils.evaluateMandatoryCondition(item.getMandatoryCondition(), any)) {
 
-        Collection<MappingItem> mappings = MappingUtils.getMatchingMappingItems(
-                anyUtils.getMappingItems(resource.getProvision(any.getType()), MappingPurpose.PROPAGATION),
-                intAttrName, intMappingType);
-        for (Iterator<MappingItem> itor = mappings.iterator(); itor.hasNext() && !result;) {
-            MappingItem mapping = itor.next();
-            result |= JexlUtils.evaluateMandatoryCondition(mapping.getMandatoryCondition(), any);
+                        missingAttrNames.add(item.getIntAttrName());
+                    }
+                }
+            }
         }
 
-        return result;
+        return missingAttrNames;
     }
 
-    private boolean evaluateMandatoryCondition(final AnyUtils anyUtils,
-            final Any<?, ?, ?> any, final String intAttrName, final IntMappingType intMappingType) {
+    private SyncopeClientException checkMandatoryOnResources(
+            final Any<?, ?, ?> any, final Set<ExternalResource> resources) {
 
-        boolean result = false;
+        SyncopeClientException reqValMissing = SyncopeClientException.build(ClientExceptionType.RequiredValuesMissing);
 
-        Iterable<? extends ExternalResource> iterable = any instanceof User
-                ? userDAO.findAllResources((User) any)
-                : any instanceof Group
-                        ? ((Group) any).getResources()
-                        : Collections.<ExternalResource>emptySet();
-
-        for (Iterator<? extends ExternalResource> itor = iterable.iterator(); itor.hasNext() && !result;) {
-            ExternalResource resource = itor.next();
-            if (resource.isEnforceMandatoryCondition()) {
-                result |= evaluateMandatoryCondition(
-                        anyUtils, resource, any, intAttrName, intMappingType);
+        for (ExternalResource resource : resources) {
+            Provision provision = resource.getProvision(any.getType());
+            if (resource.isEnforceMandatoryCondition() && provision != null) {
+                List<String> missingAttrNames = evaluateMandatoryCondition(provision, any);
+                if (!missingAttrNames.isEmpty()) {
+                    LOG.error("Mandatory schemas {} not provided with values", missingAttrNames);
+
+                    reqValMissing.getElements().addAll(missingAttrNames);
+                }
             }
         }
 
-        return result;
+        return reqValMissing;
     }
 
-    private SyncopeClientException checkMandatory(final AnyUtils anyUtils, final Any<?, ?, ?> any) {
+    private SyncopeClientException checkMandatory(final Any<?, ?, ?> any) {
         SyncopeClientException reqValMissing = SyncopeClientException.build(ClientExceptionType.RequiredValuesMissing);
 
         // Check if there is some mandatory schema defined for which no value has been provided
         for (PlainSchema schema : any.getAllowedPlainSchemas()) {
             if (any.getPlainAttr(schema.getKey()) == null
                     && !schema.isReadonly()
-                    && (JexlUtils.evaluateMandatoryCondition(schema.getMandatoryCondition(), any)
-                    || evaluateMandatoryCondition(anyUtils, any, schema.getKey(),
-                            anyUtils.plainIntMappingType()))) {
+                    && (JexlUtils.evaluateMandatoryCondition(schema.getMandatoryCondition(), any))) {
 
                 LOG.error("Mandatory schema " + schema.getKey() + " not provided with values");
 
@@ -256,30 +275,21 @@ abstract class AbstractAnyDataBinder {
             }
         }
 
-        for (DerSchema derSchema : any.getAllowedDerSchemas()) {
-            if (any.getDerAttr(derSchema.getKey()) == null
-                    && evaluateMandatoryCondition(anyUtils, any, derSchema.getKey(),
-                            anyUtils.derIntMappingType())) {
-
-                LOG.error("Mandatory derived schema " + derSchema.getKey() + " does not evaluate to any value");
-
-                reqValMissing.getElements().add(derSchema.getKey());
-            }
-        }
-
-        for (VirSchema virSchema : any.getAllowedVirSchemas()) {
-            if (any.getVirAttr(virSchema.getKey()) == null
-                    && !virSchema.isReadonly()
-                    && evaluateMandatoryCondition(anyUtils, any, virSchema.getKey(),
-                            anyUtils.virIntMappingType())) {
+        return reqValMissing;
+    }
 
-                LOG.error("Mandatory virtual schema " + virSchema.getKey() + " not provided with values");
+    private Set<ExternalResource> getAllResources(final Any<?, ?, ?> any) {
+        Set<ExternalResource> resources = new HashSet<>();
 
-                reqValMissing.getElements().add(virSchema.getKey());
-            }
+        if (any instanceof User) {
+            resources.addAll(userDAO.findAllResources((User) any));
+        } else if (any instanceof Group) {
+            resources.addAll(((Group) any).getResources());
+        } else if (any instanceof AnyObject) {
+            resources.addAll(anyObjectDAO.findAllResources((AnyObject) any));
         }
 
-        return reqValMissing;
+        return resources;
     }
 
     @SuppressWarnings({ "unchecked", "rawtypes" })
@@ -288,9 +298,29 @@ abstract class AbstractAnyDataBinder {
 
         PropagationByResource propByRes = new PropagationByResource();
 
+        // 1. anyTypeClass to be removed
+        for (String className : anyMod.getAuxClassesToRemove()) {
+            AnyTypeClass auxClass = anyTypeClassDAO.find(className);
+            if (auxClass == null) {
+                LOG.debug("Invalid " + AnyTypeClass.class.getSimpleName() + "{}, ignoring...", auxClass);
+            } else {
+                any.remove(auxClass);
+            }
+        }
+
+        // 2. anyTypeClass to be added
+        for (String className : anyMod.getAuxClassesToAdd()) {
+            AnyTypeClass auxClass = anyTypeClassDAO.find(className);
+            if (auxClass == null) {
+                LOG.debug("Invalid " + AnyTypeClass.class.getSimpleName() + "{}, ignoring...", auxClass);
+            } else {
+                any.add(auxClass);
+            }
+        }
+
         SyncopeClientException invalidValues = SyncopeClientException.build(ClientExceptionType.InvalidValues);
 
-        // 1. resources to be removed
+        // 3. resources to be removed
         for (String resourceToBeRemoved : anyMod.getResourcesToRemove()) {
             ExternalResource resource = resourceDAO.find(resourceToBeRemoved);
             if (resource != null) {
@@ -301,7 +331,7 @@ abstract class AbstractAnyDataBinder {
 
         LOG.debug("Resources to be removed:\n{}", propByRes);
 
-        // 2. resources to be added
+        // 4. resources to be added
         for (String resourceToBeAdded : anyMod.getResourcesToAdd()) {
             ExternalResource resource = resourceDAO.find(resourceToBeAdded);
             if (resource != null) {
@@ -312,16 +342,9 @@ abstract class AbstractAnyDataBinder {
 
         LOG.debug("Resources to be added:\n{}", propByRes);
 
-        Set<ExternalResource> externalResources = new HashSet<>();
-        if (any instanceof User) {
-            externalResources.addAll(userDAO.findAllResources((User) any));
-        } else if (any instanceof Group) {
-            externalResources.addAll(((Group) any).getResources());
-        } else if (any instanceof AnyObject) {
-            externalResources.addAll(anyObjectDAO.findAllResources((AnyObject) any));
-        }
+        Set<ExternalResource> resources = getAllResources(any);
 
-        // 3. attributes to be removed
+        // 5. attributes to be removed
         for (String attributeToBeRemoved : anyMod.getPlainAttrsToRemove()) {
             PlainSchema schema = getPlainSchema(attributeToBeRemoved);
             if (schema != null) {
@@ -344,7 +367,7 @@ abstract class AbstractAnyDataBinder {
                     }
                 }
 
-                for (ExternalResource resource : externalResources) {
+                for (ExternalResource resource : resources) {
                     for (MappingItem mapItem : anyUtils.getMappingItems(
                             resource.getProvision(any.getType()), MappingPurpose.PROPAGATION)) {
 
@@ -364,7 +387,7 @@ abstract class AbstractAnyDataBinder {
 
         LOG.debug("Attributes to be removed:\n{}", propByRes);
 
-        // 4. attributes to be updated
+        // 6. attributes to be updated
         for (AttrMod attributeMod : anyMod.getPlainAttrsToUpdate()) {
             PlainSchema schema = getPlainSchema(attributeMod.getSchema());
             PlainAttr attr = null;
@@ -372,19 +395,15 @@ abstract class AbstractAnyDataBinder {
                 attr = any.getPlainAttr(schema.getKey());
                 if (attr == null) {
                     attr = anyUtils.newPlainAttr();
+                    attr.setOwner(any);
                     attr.setSchema(schema);
-                    if (attr.getSchema() == null) {
-                        LOG.debug("Ignoring {} because no valid schema or template was found", attributeMod);
-                    } else {
-                        attr.setOwner(any);
-                        any.add(attr);
-                    }
+                    any.add(attr);
                 }
             }
 
             if (schema != null && attr != null && attr.getSchema() != null) {
-                virtAttrHander.updateOnResourcesIfMappingMatches(any, anyUtils, schema.getKey(),
-                        externalResources, anyUtils.plainIntMappingType(), propByRes);
+                virAttrHander.updateOnResourcesIfMappingMatches(any, anyUtils, schema.getKey(),
+                        resources, anyUtils.plainIntMappingType(), propByRes);
 
                 // 1.1 remove values
                 Set<Long> valuesToBeRemoved = new HashSet<>();
@@ -429,7 +448,7 @@ abstract class AbstractAnyDataBinder {
 
         LOG.debug("Attributes to be updated:\n{}", propByRes);
 
-        // 5. derived attributes to be removed
+        // 7. derived attributes to be removed
         for (String derAttrToBeRemoved : anyMod.getDerAttrsToRemove()) {
             DerSchema derSchema = getDerSchema(derAttrToBeRemoved);
             if (derSchema != null) {
@@ -440,7 +459,7 @@ abstract class AbstractAnyDataBinder {
                     derAttrDAO.delete(derAttr);
                 }
 
-                for (ExternalResource resource : externalResources) {
+                for (ExternalResource resource : resources) {
                     for (MappingItem mapItem : anyUtils.getMappingItems(
                             resource.getProvision(any.getType()), MappingPurpose.PROPAGATION)) {
 
@@ -463,19 +482,18 @@ abstract class AbstractAnyDataBinder {
 
         LOG.debug("Derived attributes to be removed:\n{}", propByRes);
 
-        // 6. derived attributes to be added
+        // 8. derived attributes to be added
         for (String derAttrToBeAdded : anyMod.getDerAttrsToAdd()) {
             DerSchema derSchema = getDerSchema(derAttrToBeAdded);
             if (derSchema != null) {
-                virtAttrHander.updateOnResourcesIfMappingMatches(any, anyUtils, derSchema.getKey(),
-                        externalResources, anyUtils.derIntMappingType(), propByRes);
+                virAttrHander.updateOnResourcesIfMappingMatches(any, anyUtils, derSchema.getKey(),
+                        resources, anyUtils.derIntMappingType(), propByRes);
 
-                DerAttr derAttr = anyUtils.newDerAttr();
-                derAttr.setSchema(derSchema);
-                if (derAttr.getSchema() == null) {
-                    LOG.debug("Ignoring {} because no valid schema or template was found", derAttrToBeAdded);
-                } else {
+                DerAttr derAttr = any.getDerAttr(derSchema.getKey());
+                if (derAttr == null) {
+                    derAttr = anyUtils.newDerAttr();
                     derAttr.setOwner(any);
+                    derAttr.setSchema(derSchema);
                     any.add(derAttr);
                 }
             }
@@ -483,8 +501,11 @@ abstract class AbstractAnyDataBinder {
 
         LOG.debug("Derived attributes to be added:\n{}", propByRes);
 
-        // Finally, check if mandatory values are missing
-        SyncopeClientException requiredValuesMissing = checkMandatory(anyUtils, any);
+        SyncopeClientException requiredValuesMissing = checkMandatory(any);
+        if (!requiredValuesMissing.isEmpty()) {
+            scce.addException(requiredValuesMissing);
+        }
+        requiredValuesMissing = checkMandatoryOnResources(any, resources);
         if (!requiredValuesMissing.isEmpty()) {
             scce.addException(requiredValuesMissing);
         }
@@ -501,6 +522,17 @@ abstract class AbstractAnyDataBinder {
     protected void fill(final Any any, final AnyTO anyTO,
             final AnyUtils anyUtils, final SyncopeClientCompositeException scce) {
 
+        // 0. aux classes
+        any.getAuxClasses().clear();
+        for (String className : anyTO.getAuxClasses()) {
+            AnyTypeClass auxClass = anyTypeClassDAO.find(className);
+            if (auxClass == null) {
+                LOG.debug("Invalid " + AnyTypeClass.class.getSimpleName() + "{}, ignoring...", auxClass);
+            } else {
+                any.add(auxClass);
+            }
+        }
+
         // 1. attributes
         SyncopeClientException invalidValues = SyncopeClientException.build(ClientExceptionType.InvalidValues);
 
@@ -508,7 +540,6 @@ abstract class AbstractAnyDataBinder {
         for (AttrTO attributeTO : anyTO.getPlainAttrs()) {
             if (attributeTO.getValues() != null && !attributeTO.getValues().isEmpty()) {
                 PlainSchema schema = getPlainSchema(attributeTO.getSchema());
-
                 if (schema != null) {
                     PlainAttr attr = any.getPlainAttr(schema.getKey());
                     if (attr == null) {
@@ -534,7 +565,6 @@ abstract class AbstractAnyDataBinder {
         // 2. derived attributes
         for (AttrTO attributeTO : anyTO.getDerAttrs()) {
             DerSchema derSchema = getDerSchema(attributeTO.getSchema());
-
             if (derSchema != null) {
                 DerAttr derAttr = anyUtils.newDerAttr();
                 derAttr.setOwner(any);
@@ -545,8 +575,7 @@ abstract class AbstractAnyDataBinder {
 
         // 3. virtual attributes
         for (AttrTO vattrTO : anyTO.getVirAttrs()) {
-            VirSchema virSchema = virtAttrHander.getVirSchema(vattrTO.getSchema());
-
+            VirSchema virSchema = virAttrHander.getVirSchema(vattrTO.getSchema());
             if (virSchema != null) {
                 VirAttr virAttr = anyUtils.newVirAttr();
                 virAttr.setOwner(any);
@@ -555,27 +584,32 @@ abstract class AbstractAnyDataBinder {
             }
         }
 
-        virtAttrHander.fillVirtual(any, anyTO.getVirAttrs(), anyUtils);
+        SyncopeClientException requiredValuesMissing = checkMandatory(any);
+        if (!requiredValuesMissing.isEmpty()) {
+            scce.addException(requiredValuesMissing);
+        }
+
+        virAttrHander.fillVirtual(any, anyTO.getVirAttrs());
 
         // 4. realm & resources
         Realm realm = realmDAO.find(anyTO.getRealm());
         if (realm == null) {
             SyncopeClientException noRealm = SyncopeClientException.build(ClientExceptionType.InvalidRealm);
-            noRealm.getElements().add(
-                    "Invalid or null realm specified: " + anyTO.getRealm());
+            noRealm.getElements().add("Invalid or null realm specified: " + anyTO.getRealm());
             scce.addException(noRealm);
         }
         any.setRealm(realm);
 
         for (String resourceName : anyTO.getResources()) {
             ExternalResource resource = resourceDAO.find(resourceName);
-
-            if (resource != null) {
+            if (resource == null) {
+                LOG.debug("Invalid " + ExternalResource.class.getSimpleName() + "{}, ignoring...", resourceName);
+            } else {
                 any.add(resource);
             }
         }
 
-        SyncopeClientException requiredValuesMissing = checkMandatory(anyUtils, any);
+        requiredValuesMissing = checkMandatoryOnResources(any, getAllResources(any));
         if (!requiredValuesMissing.isEmpty()) {
             scce.addException(requiredValuesMissing);
         }
@@ -588,11 +622,22 @@ abstract class AbstractAnyDataBinder {
 
     protected void fillTO(final AnyTO anyTO,
             final String realmFullPath,
+            final Collection<? extends AnyTypeClass> auxClasses,
             final Collection<? extends PlainAttr<?>> attrs,
             final Collection<? extends DerAttr<?>> derAttrs,
             final Collection<? extends VirAttr<?>> virAttrs,
             final Collection<? extends ExternalResource> resources) {
 
+        anyTO.setRealm(realmFullPath);
+
+        CollectionUtils.collect(auxClasses, new Transformer<AnyTypeClass, String>() {
+
+            @Override
+            public String transform(final AnyTypeClass role) {
+                return role.getKey();
+            }
+        }, anyTO.getAuxClasses());
+
         AttrTO attributeTO;
         for (PlainAttr<?> attr : attrs) {
             attributeTO = new AttrTO();
@@ -621,12 +666,29 @@ abstract class AbstractAnyDataBinder {
             anyTO.getVirAttrs().add(attributeTO);
         }
 
-        anyTO.setRealm(realmFullPath);
         for (ExternalResource resource : resources) {
             anyTO.getResources().add(resource.getKey());
         }
     }
 
+    protected RelationshipTO getRelationshipTO(final Relationship<? extends Any<?, ?, ?>, AnyObject> relationship) {
+        RelationshipTO relationshipTO = new RelationshipTO();
+        relationshipTO.setLeftKey(relationship.getLeftEnd().getKey());
+        relationshipTO.setLeftType(relationship.getLeftEnd().getType().getKey());
+        relationshipTO.setRightKey(relationship.getRightEnd().getKey());
+        relationshipTO.setRightType(relationship.getRightEnd().getType().getKey());
+        return relationshipTO;
+    }
+
+    protected MembershipTO getMembershipTO(final Membership<? extends Any<?, ?, ?>> membership) {
+        MembershipTO membershipTO = new MembershipTO();
+        membershipTO.setLeftKey(membership.getLeftEnd().getKey());
+        membershipTO.setLeftType(membership.getLeftEnd().getType().getKey());
+        membershipTO.setRightKey(membership.getRightEnd().getKey());
+        membershipTO.setGroupName(membership.getRightEnd().getName());
+        return membershipTO;
+    }
+
     protected Map<String, String> getConnObjectKeys(final Any<?, ?, ?> any) {
         Map<String, String> connObjectKeys = new HashMap<>();
 
@@ -637,7 +699,7 @@ abstract class AbstractAnyDataBinder {
                         : ((Group) any).getResources();
         for (ExternalResource resource : iterable) {
             Provision provision = resource.getProvision(any.getType());
-            if (provision.getMapping() != null) {
+            if (provision != null && provision.getMapping() != null) {
                 MappingItem connObjectKeyItem = anyUtilsFactory.getInstance(any).getConnObjectKeyItem(provision);
                 if (connObjectKeyItem == null) {
                     throw new NotFoundException(

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyObjectDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyObjectDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyObjectDataBinderImpl.java
index eb7586d..462a488 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyObjectDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyObjectDataBinderImpl.java
@@ -31,11 +31,13 @@ import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.mod.AnyObjectMod;
 import org.apache.syncope.common.lib.to.AnyObjectTO;
 import org.apache.syncope.common.lib.to.MembershipTO;
+import org.apache.syncope.common.lib.to.RelationshipTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.PropagationByResource;
 import org.apache.syncope.common.lib.types.ResourceOperation;
 import org.apache.syncope.core.misc.spring.BeanUtils;
 import org.apache.syncope.core.persistence.api.entity.anyobject.AMembership;
+import org.apache.syncope.core.persistence.api.entity.anyobject.ARelationship;
 import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
 import org.apache.syncope.core.persistence.api.entity.group.Group;
 import org.apache.syncope.core.provisioning.api.data.AnyObjectDataBinder;
@@ -47,7 +49,8 @@ import org.springframework.transaction.annotation.Transactional;
 public class AnyObjectDataBinderImpl extends AbstractAnyDataBinder implements AnyObjectDataBinder {
 
     private static final String[] IGNORE_PROPERTIES = {
-        "realm", "memberships", "plainAttrs", "derAttrs", "virAttrs", "resources"
+        "type", "realm", "auxClasses", "relationships", "memberships", "dynGroups",
+        "plainAttrs", "derAttrs", "virAttrs", "resources"
     };
 
     @Transactional(readOnly = true)
@@ -62,20 +65,29 @@ public class AnyObjectDataBinderImpl extends AbstractAnyDataBinder implements An
 
         BeanUtils.copyProperties(anyObject, anyObjectTO, IGNORE_PROPERTIES);
 
-        connObjectUtils.retrieveVirAttrValues(anyObject);
-        fillTO(anyObjectTO, anyObject.getRealm().getFullPath(),
+        virAttrHander.retrieveVirAttrValues(anyObject);
+        fillTO(anyObjectTO, anyObject.getRealm().getFullPath(), anyObject.getAuxClasses(),
                 anyObject.getPlainAttrs(), anyObject.getDerAttrs(), anyObject.getVirAttrs(),
                 anyObjectDAO.findAllResources(anyObject));
 
-        for (AMembership membership : anyObject.getMemberships()) {
-            MembershipTO membershipTO = new MembershipTO();
+        // relationships
+        CollectionUtils.collect(anyObject.getRelationships(), new Transformer<ARelationship, RelationshipTO>() {
 
-            membershipTO.setKey(membership.getKey());
-            membershipTO.setRightKey(membership.getRightEnd().getKey());
-            membershipTO.setGroupName(membership.getRightEnd().getName());
+            @Override
+            public RelationshipTO transform(final ARelationship relationship) {
+                return AnyObjectDataBinderImpl.this.getRelationshipTO(relationship);
+            }
 
-            anyObjectTO.getMemberships().add(membershipTO);
-        }
+        }, anyObjectTO.getRelationships());
+
+        // memberships
+        CollectionUtils.collect(anyObject.getMemberships(), new Transformer<AMembership, MembershipTO>() {
+
+            @Override
+            public MembershipTO transform(final AMembership membership) {
+                return AnyObjectDataBinderImpl.this.getMembershipTO(membership);
+            }
+        }, anyObjectTO.getMemberships());
 
         // dynamic memberships
         CollectionUtils.collect(anyObjectDAO.findDynGroupMemberships(anyObject), new Transformer<Group, Long>() {
@@ -93,6 +105,29 @@ public class AnyObjectDataBinderImpl extends AbstractAnyDataBinder implements An
     public void create(final AnyObject anyObject, final AnyObjectTO anyObjectTO) {
         SyncopeClientCompositeException scce = SyncopeClientException.buildComposite();
 
+        // relationships
+        for (RelationshipTO relationshipTO : anyObjectTO.getRelationships()) {
+            AnyObject otherEnd = anyObjectDAO.find(relationshipTO.getRightKey());
+
+            if (otherEnd == null) {
+                if (LOG.isDebugEnabled()) {
+                    LOG.debug("Ignoring invalid anyObject " + relationshipTO.getRightKey());
+                }
+            } else {
+                ARelationship relationship = null;
+                if (anyObject.getKey() != null) {
+                    relationship = anyObject.getRelationship(otherEnd.getKey());
+                }
+                if (relationship == null) {
+                    relationship = entityFactory.newEntity(ARelationship.class);
+                    relationship.setRightEnd(otherEnd);
+                    relationship.setLeftEnd(anyObject);
+
+                    anyObject.add(relationship);
+                }
+            }
+        }
+
         // memberships
         for (MembershipTO membershipTO : anyObjectTO.getMemberships()) {
             Group group = groupDAO.find(membershipTO.getRightKey());
@@ -137,11 +172,44 @@ public class AnyObjectDataBinderImpl extends AbstractAnyDataBinder implements An
         // attributes, derived attributes, virtual attributes and resources
         propByRes.merge(fill(anyObject, anyObjectMod, anyUtilsFactory.getInstance(AnyTypeKind.ANY_OBJECT), scce));
 
-        // store the group ids of membership required to be added
-        Set<Long> membershipToBeAddedGroupKeys = new HashSet<>(anyObjectMod.getMembershipsToAdd());
+        Set<String> toBeDeprovisioned = new HashSet<>();
+        Set<String> toBeProvisioned = new HashSet<>();
+
+        // relationships to be removed
+        for (Long anyObjectKey : anyObjectMod.getRelationshipsToRemove()) {
+            LOG.debug("Relationship to be removed for any object {}", anyObjectKey);
+
+            ARelationship relationship = anyObject.getRelationship(anyObjectKey);
+            if (relationship == null) {
+                LOG.warn("Invalid anyObject key specified for relationship to be removed: {}", anyObjectKey);
+            } else {
+                if (!anyObjectMod.getRelationshipsToAdd().contains(anyObjectKey)) {
+                    anyObject.remove(relationship);
+                    toBeDeprovisioned.addAll(relationship.getRightEnd().getResourceNames());
+                }
+            }
+        }
+
+        // relationships to be added
+        for (Long anyObjectKey : anyObjectMod.getRelationshipsToAdd()) {
+            LOG.debug("Relationship to be added for any object {}", anyObjectKey);
+
+            AnyObject otherEnd = anyObjectDAO.find(anyObjectKey);
+            if (otherEnd == null) {
+                LOG.debug("Ignoring invalid any object {}", anyObjectKey);
+            } else {
+                ARelationship relationship = anyObject.getRelationship(otherEnd.getKey());
+                if (relationship == null) {
+                    relationship = entityFactory.newEntity(ARelationship.class);
+                    relationship.setRightEnd(otherEnd);
+                    relationship.setLeftEnd(anyObject);
+
+                    anyObject.add(relationship);
 
-        final Set<String> toBeDeprovisioned = new HashSet<>();
-        final Set<String> toBeProvisioned = new HashSet<>();
+                    toBeProvisioned.addAll(otherEnd.getResourceNames());
+                }
+            }
+        }
 
         // memberships to be removed
         for (Long groupKey : anyObjectMod.getMembershipsToRemove()) {
@@ -151,9 +219,8 @@ public class AnyObjectDataBinderImpl extends AbstractAnyDataBinder implements An
             if (membership == null) {
                 LOG.warn("Invalid group key specified for membership to be removed: {}", groupKey);
             } else {
-                if (membershipToBeAddedGroupKeys.contains(membership.getRightEnd().getKey())) {
+                if (!anyObjectMod.getMembershipsToAdd().contains(groupKey)) {
                     anyObject.remove(membership);
-                } else {
                     toBeDeprovisioned.addAll(membership.getRightEnd().getResourceNames());
                 }
             }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyTypeClassDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyTypeClassDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyTypeClassDataBinderImpl.java
new file mode 100644
index 0000000..5917190
--- /dev/null
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyTypeClassDataBinderImpl.java
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.provisioning.java.data;
+
+import org.apache.syncope.common.lib.to.AnyTypeClassTO;
+import org.apache.syncope.core.persistence.api.dao.DerSchemaDAO;
+import org.apache.syncope.core.persistence.api.dao.PlainSchemaDAO;
+import org.apache.syncope.core.persistence.api.dao.VirSchemaDAO;
+import org.apache.syncope.core.persistence.api.entity.EntityFactory;
+import org.apache.syncope.core.persistence.api.entity.AnyTypeClass;
+import org.apache.syncope.core.persistence.api.entity.DerSchema;
+import org.apache.syncope.core.persistence.api.entity.PlainSchema;
+import org.apache.syncope.core.persistence.api.entity.VirSchema;
+import org.apache.syncope.core.provisioning.api.data.AnyTypeClassDataBinder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class AnyTypeClassDataBinderImpl implements AnyTypeClassDataBinder {
+
+    private static final Logger LOG = LoggerFactory.getLogger(AnyTypeClassDataBinder.class);
+
+    @Autowired
+    private PlainSchemaDAO plainSchemaDAO;
+
+    @Autowired
+    private DerSchemaDAO derSchemaDAO;
+
+    @Autowired
+    private VirSchemaDAO virSchemaDAO;
+
+    @Autowired
+    private EntityFactory entityFactory;
+
+    @Override
+    public AnyTypeClass create(final AnyTypeClassTO anyTypeClassTO) {
+        AnyTypeClass anyTypeClass = entityFactory.newEntity(AnyTypeClass.class);
+        update(anyTypeClass, anyTypeClassTO);
+        return anyTypeClass;
+    }
+
+    @Override
+    public void update(final AnyTypeClass anyTypeClass, final AnyTypeClassTO anyTypeClassTO) {
+        if (anyTypeClass.getKey() == null) {
+            anyTypeClass.setKey(anyTypeClassTO.getKey());
+        }
+
+        anyTypeClass.getPlainSchemas().clear();
+        for (String schemaName : anyTypeClassTO.getPlainSchemas()) {
+            PlainSchema schema = plainSchemaDAO.find(schemaName);
+            if (schema == null) {
+                LOG.debug("Invalid " + PlainSchema.class.getSimpleName() + "{}, ignoring...", schemaName);
+            } else {
+                anyTypeClass.add(schema);
+            }
+        }
+
+        anyTypeClass.getDerSchemas().clear();
+        for (String schemaName : anyTypeClassTO.getDerSchemas()) {
+            DerSchema schema = derSchemaDAO.find(schemaName);
+            if (schema == null) {
+                LOG.debug("Invalid " + DerSchema.class.getSimpleName() + "{}, ignoring...", schemaName);
+            } else {
+                anyTypeClass.add(schema);
+            }
+        }
+
+        anyTypeClass.getVirSchemas().clear();
+        for (String schemaName : anyTypeClassTO.getVirSchemas()) {
+            VirSchema schema = virSchemaDAO.find(schemaName);
+            if (schema == null) {
+                LOG.debug("Invalid " + VirSchema.class.getSimpleName() + "{}, ignoring...", schemaName);
+            } else {
+                anyTypeClass.add(schema);
+            }
+        }
+    }
+
+    @Override
+    public AnyTypeClassTO getAnyTypeClassTO(final AnyTypeClass anyTypeClass) {
+        AnyTypeClassTO anyTypeClassTO = new AnyTypeClassTO();
+
+        anyTypeClassTO.setKey(anyTypeClass.getKey());
+        for (PlainSchema schema : anyTypeClass.getPlainSchemas()) {
+            anyTypeClassTO.getPlainSchemas().add(schema.getKey());
+        }
+        for (DerSchema schema : anyTypeClass.getDerSchemas()) {
+            anyTypeClassTO.getDerSchemas().add(schema.getKey());
+        }
+        for (VirSchema schema : anyTypeClass.getVirSchemas()) {
+            anyTypeClassTO.getVirSchemas().add(schema.getKey());
+        }
+
+        return anyTypeClassTO;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyTypeDataBinderImpl.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..0e85d3a
--- /dev/null
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/AnyTypeDataBinderImpl.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.core.provisioning.java.data;
+
+import org.apache.syncope.common.lib.SyncopeClientException;
+import org.apache.syncope.common.lib.to.AnyTypeTO;
+import org.apache.syncope.common.lib.types.ClientExceptionType;
+import org.apache.syncope.core.persistence.api.dao.AnyTypeClassDAO;
+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.data.AnyTypeDataBinder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class AnyTypeDataBinderImpl implements AnyTypeDataBinder {
+
+    private static final Logger LOG = LoggerFactory.getLogger(AnyTypeDataBinder.class);
+
+    @Autowired
+    private AnyTypeClassDAO anyTypeClassDAO;
+
+    @Autowired
+    private EntityFactory entityFactory;
+
+    @Override
+    public AnyType create(final AnyTypeTO anyTypeTO) {
+        AnyType anyType = entityFactory.newEntity(AnyType.class);
+        update(anyType, anyTypeTO);
+        return anyType;
+    }
+
+    @Override
+    public void update(final AnyType anyType, final AnyTypeTO anyTypeTO) {
+        if (anyType.getKey() == null) {
+            anyType.setKey(anyTypeTO.getKey());
+        }
+        if (anyType.getKind() == null) {
+            anyType.setKind(anyTypeTO.getKind());
+        }
+        if (anyType.getKind() != anyTypeTO.getKind()) {
+            SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidAnyType);
+            sce.getElements().add("AnyTypeKind cannot be changed");
+            throw sce;
+        }
+
+        anyType.getClasses().clear();
+        for (String anyTypeClassName : anyTypeTO.getClasses()) {
+            AnyTypeClass anyTypeClass = anyTypeClassDAO.find(anyTypeClassName);
+            if (anyTypeClass == null) {
+                LOG.debug("Invalid " + AnyTypeClass.class.getSimpleName() + "{}, ignoring...", anyTypeClassName);
+            } else {
+                anyType.add(anyTypeClass);
+            }
+        }
+    }
+
+    @Override
+    public AnyTypeTO getAnyTypeTO(final AnyType anyType) {
+        AnyTypeTO anyTypeTO = new AnyTypeTO();
+
+        anyTypeTO.setKey(anyType.getKey());
+        anyTypeTO.setKind(anyType.getKind());
+        for (AnyTypeClass anyTypeClass : anyType.getClasses()) {
+            anyTypeTO.getClasses().add(anyTypeClass.getKey());
+        }
+
+        return anyTypeTO;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ConfigurationDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ConfigurationDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ConfigurationDataBinderImpl.java
index fe5668d..3cf65fd 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ConfigurationDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ConfigurationDataBinderImpl.java
@@ -47,8 +47,8 @@ public class ConfigurationDataBinderImpl extends AbstractAnyDataBinder implement
         ConfTO confTO = new ConfTO();
         confTO.setKey(conf.getKey());
 
-        fillTO(confTO, null, conf.getPlainAttrs(),
-                conf.getDerAttrs(), conf.getVirAttrs(), Collections.<ExternalResource>emptySet());
+        fillTO(confTO, null, conf.getAuxClasses(),
+                conf.getPlainAttrs(), conf.getDerAttrs(), conf.getVirAttrs(), Collections.<ExternalResource>emptySet());
 
         return confTO;
     }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/GroupDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/GroupDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/GroupDataBinderImpl.java
index a900e70..a393fda 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/GroupDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/GroupDataBinderImpl.java
@@ -105,7 +105,7 @@ public class GroupDataBinderImpl extends AbstractAnyDataBinder implements GroupD
         if (groupTO.getADynMembershipCond() != null) {
             setDynMembership(group, AnyTypeKind.ANY_OBJECT, groupTO.getADynMembershipCond());
         }
-        if (groupTO.getADynMembershipCond() != null) {
+        if (groupTO.getUDynMembershipCond() != null) {
             setDynMembership(group, AnyTypeKind.USER, groupTO.getUDynMembershipCond());
         }
 
@@ -188,7 +188,7 @@ public class GroupDataBinderImpl extends AbstractAnyDataBinder implements GroupD
     @Transactional(readOnly = true)
     @Override
     public GroupTO getGroupTO(final Group group) {
-        connObjectUtils.retrieveVirAttrValues(group);
+        virAttrHander.retrieveVirAttrValues(group);
 
         GroupTO groupTO = new GroupTO();
 
@@ -208,7 +208,7 @@ public class GroupDataBinderImpl extends AbstractAnyDataBinder implements GroupD
             groupTO.setGroupOwner(group.getGroupOwner().getKey());
         }
 
-        fillTO(groupTO, group.getRealm().getFullPath(),
+        fillTO(groupTO, group.getRealm().getFullPath(), group.getAuxClasses(),
                 group.getPlainAttrs(), group.getDerAttrs(), group.getVirAttrs(), group.getResources());
 
         if (group.getADynMembership() != null) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/NotificationDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/NotificationDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/NotificationDataBinderImpl.java
index eec346e..0d7ee47 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/NotificationDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/NotificationDataBinderImpl.java
@@ -19,6 +19,8 @@
 package org.apache.syncope.core.provisioning.java.data;
 
 import java.util.Map;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.Predicate;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.core.provisioning.api.data.NotificationDataBinder;
 import org.apache.syncope.common.lib.to.NotificationTO;
@@ -72,23 +74,35 @@ public class NotificationDataBinderImpl implements NotificationDataBinder {
     @Override
     public void update(final Notification notification, final NotificationTO notificationTO) {
         BeanUtils.copyProperties(notificationTO, notification, IGNORE_PROPERTIES);
+        notification.setRecipients(notificationTO.getRecipients());
 
-        notification.getAbouts().clear();
+        // 1. add or update all (valid) abouts from TO
         for (Map.Entry<String, String> entry : notificationTO.getAbouts().entrySet()) {
             if (StringUtils.isNotBlank(entry.getValue())) {
                 AnyType anyType = anyTypeDAO.find(entry.getKey());
                 if (anyType == null) {
-                    LOG.warn("Invalid AnyType {} specified, ignoring...", entry.getKey());
+                    LOG.debug("Invalid AnyType {} specified, ignoring...", entry.getKey());
                 } else {
-                    AnyAbout about = entityFactory.newEntity(AnyAbout.class);
-                    about.setAnyType(anyType);
-                    about.setNotification(notification);
-
-                    notification.add(about);
+                    AnyAbout about = notification.getAbout(anyType);
+                    if (about == null) {
+                        about = entityFactory.newEntity(AnyAbout.class);
+                        about.setAnyType(anyType);
+                        about.setNotification(notification);
+
+                        notification.add(about);
+                    }
+                    about.set(entry.getValue());
                 }
             }
         }
 
-        notification.setRecipients(notificationTO.getRecipients());
+        // 2. remove all abouts not contained in the TO
+        CollectionUtils.filter(notification.getAbouts(), new Predicate<AnyAbout>() {
+
+            @Override
+            public boolean evaluate(final AnyAbout anyAbout) {
+                return notificationTO.getAbouts().containsKey(anyAbout.getAnyType().getKey());
+            }
+        });
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
index 20b3c58..cb8f979 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/ResourceDataBinderImpl.java
@@ -22,6 +22,8 @@ import org.apache.syncope.core.provisioning.api.data.ResourceDataBinder;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.Set;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.Predicate;
 import org.apache.commons.lang3.SerializationUtils;
 import org.apache.syncope.common.lib.SyncopeClientCompositeException;
 import org.apache.syncope.common.lib.SyncopeClientException;
@@ -89,8 +91,8 @@ public class ResourceDataBinderImpl implements ResourceDataBinder {
 
         resource.setKey(resourceTO.getKey());
 
-        if (resourceTO.getConnectorId() != null) {
-            ConnInstance connector = connInstanceDAO.find(resourceTO.getConnectorId());
+        if (resourceTO.getConnector() != null) {
+            ConnInstance connector = connInstanceDAO.find(resourceTO.getConnector());
             resource.setConnector(connector);
 
             if (!connector.getResources().contains(resource)) {
@@ -108,10 +110,11 @@ public class ResourceDataBinderImpl implements ResourceDataBinder {
 
         resource.setPropagationMode(resourceTO.getPropagationMode());
 
+        // 1. add or update all (valid) provisions from TO
         for (ProvisionTO provisionTO : resourceTO.getProvisions()) {
             AnyType anyType = anyTypeDAO.find(provisionTO.getAnyType());
             if (anyType == null) {
-                LOG.warn("Invalid type specified {}, ignoring...", provisionTO.getAnyType());
+                LOG.debug("Invalid AnyType specified {}, ignoring...", provisionTO.getAnyType());
             } else {
                 Provision provision = resource.getProvision(anyType);
                 if (provision == null) {
@@ -135,14 +138,28 @@ public class ResourceDataBinderImpl implements ResourceDataBinder {
                 if (provisionTO.getMapping() == null) {
                     provision.setMapping(null);
                 } else {
-                    Mapping mapping = entityFactory.newEntity(Mapping.class);
-                    mapping.setProvision(provision);
-                    provision.setMapping(mapping);
+                    Mapping mapping = provision.getMapping();
+                    if (mapping == null) {
+                        mapping = entityFactory.newEntity(Mapping.class);
+                        mapping.setProvision(provision);
+                        provision.setMapping(mapping);
+                    } else {
+                        mapping.getItems().clear();
+                    }
                     populateMapping(provisionTO.getMapping(), mapping, entityFactory.newEntity(MappingItem.class));
                 }
             }
         }
 
+        // 2. remove all abouts not contained in the TO
+        CollectionUtils.filter(resource.getProvisions(), new Predicate<Provision>() {
+
+            @Override
+            public boolean evaluate(final Provision provision) {
+                return resourceTO.getProvision(provision.getAnyType().getKey()) != null;
+            }
+        });
+
         resource.setCreateTraceLevel(resourceTO.getCreateTraceLevel());
         resource.setUpdateTraceLevel(resourceTO.getUpdateTraceLevel());
         resource.setDeleteTraceLevel(resourceTO.getDeleteTraceLevel());
@@ -207,8 +224,7 @@ public class ResourceDataBinderImpl implements ResourceDataBinder {
             }
         }
 
-        // Throw composite exception if there is at least one element set
-        // in the composing exceptions
+        // Throw composite exception if there is at least one element set in the composing exceptions
         if (!requiredValuesMissing.isEmpty()) {
             scce.addException(requiredValuesMissing);
         }
@@ -234,9 +250,9 @@ public class ResourceDataBinderImpl implements ResourceDataBinder {
 
     @Override
     public ConnInstance getConnInstance(final ResourceTO resourceTO) {
-        ConnInstance connInstance = connInstanceDAO.find(resourceTO.getConnectorId());
+        ConnInstance connInstance = connInstanceDAO.find(resourceTO.getConnector());
         if (connInstance == null) {
-            throw new NotFoundException("Connector '" + resourceTO.getConnectorId() + "'");
+            throw new NotFoundException("Connector '" + resourceTO.getConnector() + "'");
         }
 
         final ConnInstance connInstanceClone = SerializationUtils.clone(connInstance);
@@ -279,7 +295,7 @@ public class ResourceDataBinderImpl implements ResourceDataBinder {
         // set the connector instance
         ConnInstance connector = resource.getConnector();
 
-        resourceTO.setConnectorId(connector == null ? null : connector.getKey());
+        resourceTO.setConnector(connector == null ? null : connector.getKey());
         resourceTO.setConnectorDisplayName(connector == null ? null : connector.getDisplayName());
 
         // set the provision information
@@ -295,6 +311,8 @@ public class ResourceDataBinderImpl implements ResourceDataBinder {
                 provisionTO.setMapping(mappingTO);
                 populateMappingTO(provision.getMapping(), mappingTO);
             }
+
+            resourceTO.getProvisions().add(provisionTO);
         }
 
         resourceTO.setEnforceMandatoryCondition(resource.isEnforceMandatoryCondition());

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/RoleDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/RoleDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/RoleDataBinderImpl.java
index b286043..124bb7f 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/RoleDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/RoleDataBinderImpl.java
@@ -84,7 +84,7 @@ public class RoleDataBinderImpl implements RoleDataBinder {
         for (String realmFullPath : roleTO.getRealms()) {
             Realm realm = realmDAO.find(realmFullPath);
             if (realm == null) {
-                LOG.warn("Invalid realm full path {}, ignoring", realmFullPath);
+                LOG.debug("Invalid realm full path {}, ignoring", realmFullPath);
             } else {
                 role.addRealm(realm);
             }

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SchemaDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SchemaDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SchemaDataBinderImpl.java
index e44198b..f20a265 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SchemaDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/SchemaDataBinderImpl.java
@@ -70,7 +70,7 @@ public class SchemaDataBinderImpl implements SchemaDataBinder {
         boolean hasAttrs = false;
         for (AnyTypeKind anyTypeKind : AnyTypeKind.values()) {
             AnyUtils anyUtils = anyUtilsFactory.getInstance(anyTypeKind);
-            hasAttrs &= schemaDAO.findAttrs(schema, anyUtils.plainAttrClass()).isEmpty();
+            hasAttrs |= schemaDAO.findAttrs(schema, anyUtils.plainAttrClass()).isEmpty();
         }
 
         if (hasAttrs) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/TaskDataBinderImpl.java
----------------------------------------------------------------------
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 c25b3ed..762cca5 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
@@ -19,6 +19,8 @@
 package org.apache.syncope.core.provisioning.java.data;
 
 import java.util.Map;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.Predicate;
 import org.apache.syncope.core.provisioning.api.data.TaskDataBinder;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.syncope.common.lib.SyncopeClientException;
@@ -72,13 +74,10 @@ import org.springframework.stereotype.Component;
 @Component
 public class TaskDataBinderImpl implements TaskDataBinder {
 
-    /**
-     * Logger.
-     */
     private static final Logger LOG = LoggerFactory.getLogger(TaskDataBinder.class);
 
     private static final String[] IGNORE_TASK_PROPERTIES = {
-        "destinationRealm", "executions", "resource", "matchingRule", "unmatchingRule" };
+        "destinationRealm", "templates", "filters", "executions", "resource", "matchingRule", "unmatchingRule" };
 
     private static final String[] IGNORE_TASK_EXECUTION_PROPERTIES = { "key", "task" };
 
@@ -100,40 +99,82 @@ public class TaskDataBinderImpl implements TaskDataBinder {
     @Autowired
     private SchedulerFactoryBean scheduler;
 
-    private void checkJexl(final AnyTO anyTO, final SyncopeClientException sce) {
-        for (AttrTO attrTO : anyTO.getPlainAttrs()) {
-            if (!attrTO.getValues().isEmpty() && !JexlUtils.isExpressionValid(attrTO.getValues().get(0))) {
-                sce.getElements().add("Invalid JEXL: " + attrTO.getValues().get(0));
+    private void checkTemplateJEXL(final SyncTaskTO syncTaskTO) {
+        SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidSyncTask);
+
+        for (Map.Entry<String, AnyTO> entry : syncTaskTO.getTemplates().entrySet()) {
+            for (AttrTO attrTO : entry.getValue().getPlainAttrs()) {
+                if (!attrTO.getValues().isEmpty() && !JexlUtils.isExpressionValid(attrTO.getValues().get(0))) {
+                    sce.getElements().add("Invalid JEXL: " + attrTO.getValues().get(0));
+                }
+            }
+
+            for (AttrTO attrTO : entry.getValue().getVirAttrs()) {
+                if (!attrTO.getValues().isEmpty() && !JexlUtils.isExpressionValid(attrTO.getValues().get(0))) {
+                    sce.getElements().add("Invalid JEXL: " + attrTO.getValues().get(0));
+                }
             }
-        }
 
-        for (AttrTO attrTO : anyTO.getVirAttrs()) {
-            if (!attrTO.getValues().isEmpty() && !JexlUtils.isExpressionValid(attrTO.getValues().get(0))) {
-                sce.getElements().add("Invalid JEXL: " + attrTO.getValues().get(0));
+            if (entry.getValue() instanceof UserTO) {
+                UserTO template = (UserTO) entry.getValue();
+                if (StringUtils.isNotBlank(template.getUsername())
+                        && !JexlUtils.isExpressionValid(template.getUsername())) {
+
+                    sce.getElements().add("Invalid JEXL: " + template.getUsername());
+                }
+                if (StringUtils.isNotBlank(template.getPassword())
+                        && !JexlUtils.isExpressionValid(template.getPassword())) {
+
+                    sce.getElements().add("Invalid JEXL: " + template.getPassword());
+                }
+            } else if (entry.getValue() instanceof GroupTO) {
+                GroupTO template = (GroupTO) entry.getValue();
+                if (StringUtils.isNotBlank(template.getName())
+                        && !JexlUtils.isExpressionValid(template.getName())) {
+
+                    sce.getElements().add("Invalid JEXL: " + template.getName());
+                }
             }
         }
+
+        if (!sce.isEmpty()) {
+            throw sce;
+        }
     }
 
     private void fill(final ProvisioningTask task, final AbstractProvisioningTaskTO taskTO) {
         if (task instanceof PushTask && taskTO instanceof PushTaskTO) {
-            PushTask pushTask = (PushTask) task;
-            PushTaskTO pushTaskTO = (PushTaskTO) taskTO;
-
-            for (Map.Entry<String, String> entry : pushTaskTO.getFilters().entrySet()) {
-                AnyFilter filter = entityFactory.newEntity(AnyFilter.class);
-                filter.setAnyType(anyTypeDAO.find(entry.getKey()));
-                filter.set(entry.getValue());
-
-                filter.setPushTask(pushTask);
-                pushTask.add(filter);
-            }
+            final PushTask pushTask = (PushTask) task;
+            final PushTaskTO pushTaskTO = (PushTaskTO) taskTO;
 
             pushTask.setMatchingRule(pushTaskTO.getMatchingRule() == null
                     ? MatchingRule.LINK : pushTaskTO.getMatchingRule());
-
             pushTask.setUnmatchingRule(pushTaskTO.getUnmatchingRule() == null
                     ? UnmatchingRule.ASSIGN : pushTaskTO.getUnmatchingRule());
 
+            for (Map.Entry<String, String> entry : pushTaskTO.getFilters().entrySet()) {
+                AnyType type = anyTypeDAO.find(entry.getKey());
+                if (type == null) {
+                    LOG.debug("Invalid AnyType {} specified, ignoring...", entry.getKey());
+                } else {
+                    AnyFilter filter = pushTask.getFilter(type);
+                    if (filter == null) {
+                        filter = entityFactory.newEntity(AnyFilter.class);
+                        filter.setAnyType(anyTypeDAO.find(entry.getKey()));
+                        filter.setPushTask(pushTask);
+                        pushTask.add(filter);
+                    }
+                    filter.set(entry.getValue());
+                }
+            }
+            // remove all filters not contained in the TO
+            CollectionUtils.filter(pushTask.getFilters(), new Predicate<AnyFilter>() {
+
+                @Override
+                public boolean evaluate(final AnyFilter anyFilter) {
+                    return pushTaskTO.getFilters().containsKey(anyFilter.getAnyType().getKey());
+                }
+            });
         } else if (task instanceof SyncTask && taskTO instanceof SyncTaskTO) {
             final SyncTask syncTask = (SyncTask) task;
             final SyncTaskTO syncTaskTO = (SyncTaskTO) taskTO;
@@ -142,52 +183,35 @@ public class TaskDataBinderImpl implements TaskDataBinder {
 
             syncTask.setMatchingRule(syncTaskTO.getMatchingRule() == null
                     ? MatchingRule.UPDATE : syncTaskTO.getMatchingRule());
-
             syncTask.setUnmatchingRule(syncTaskTO.getUnmatchingRule() == null
                     ? UnmatchingRule.PROVISION : syncTaskTO.getUnmatchingRule());
 
-            SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.InvalidSyncTask);
-            // 1. validate JEXL expressions in user and group templates
+            // validate JEXL expressions from templates and proceed if fine
+            checkTemplateJEXL(syncTaskTO);
             for (Map.Entry<String, AnyTO> entry : syncTaskTO.getTemplates().entrySet()) {
-                checkJexl(entry.getValue(), sce);
-
-                if (entry.getValue() instanceof UserTO) {
-                    UserTO template = (UserTO) entry.getValue();
-                    if (StringUtils.isNotBlank(template.getUsername())
-                            && !JexlUtils.isExpressionValid(template.getUsername())) {
-
-                        sce.getElements().add("Invalid JEXL: " + template.getUsername());
-                    }
-                    if (StringUtils.isNotBlank(template.getPassword())
-                            && !JexlUtils.isExpressionValid(template.getPassword())) {
-
-                        sce.getElements().add("Invalid JEXL: " + template.getPassword());
-                    }
-                } else if (entry.getValue() instanceof GroupTO) {
-                    GroupTO template = (GroupTO) entry.getValue();
-                    if (StringUtils.isNotBlank(template.getName())
-                            && !JexlUtils.isExpressionValid(template.getName())) {
-
-                        sce.getElements().add("Invalid JEXL: " + template.getName());
+                AnyType type = anyTypeDAO.find(entry.getKey());
+                if (type == null) {
+                    LOG.debug("Invalid AnyType {} specified, ignoring...", entry.getKey());
+                } else {
+                    AnyTemplate anyTemplate = syncTask.getTemplate(type);
+                    if (anyTemplate == null) {
+                        anyTemplate = entityFactory.newEntity(AnyTemplate.class);
+                        anyTemplate.setAnyType(type);
+                        anyTemplate.setSyncTask(syncTask);
+
+                        syncTask.add(anyTemplate);
                     }
+                    anyTemplate.set(entry.getValue());
                 }
             }
-            if (!sce.isEmpty()) {
-                throw sce;
-            }
+            // remove all templates not contained in the TO
+            CollectionUtils.filter(syncTask.getTemplates(), new Predicate<AnyTemplate>() {
 
-            // 2. all JEXL expressions are valid: accept user and group templates
-            for (Map.Entry<String, AnyTO> entry : syncTaskTO.getTemplates().entrySet()) {
-                AnyType type = anyTypeDAO.find(entry.getKey());
-                if (type != null) {
-                    AnyTemplate anyTemplate = entityFactory.newEntity(AnyTemplate.class);
-                    anyTemplate.setAnyType(type);
-                    anyTemplate.set(entry.getValue());
-                    anyTemplate.setSyncTask(syncTask);
-
-                    syncTask.add(anyTemplate);
+                @Override
+                public boolean evaluate(final AnyTemplate anyTemplate) {
+                    return syncTaskTO.getTemplates().containsKey(anyTemplate.getAnyType().getKey());
                 }
-            }
+            });
 
             syncTask.setFullReconciliation(syncTaskTO.isFullReconciliation());
         }
@@ -197,18 +221,13 @@ public class TaskDataBinderImpl implements TaskDataBinder {
         task.setPerformUpdate(taskTO.isPerformUpdate());
         task.setPerformDelete(taskTO.isPerformDelete());
         task.setSyncStatus(taskTO.isSyncStatus());
-        task.getActionsClassNames()
-                .clear();
-        task.getActionsClassNames()
-                .addAll(taskTO.getActionsClassNames());
+        task.getActionsClassNames().clear();
+        task.getActionsClassNames().addAll(taskTO.getActionsClassNames());
     }
 
     @Override
-    public SchedTask createSchedTask(final SchedTaskTO taskTO,
-            final TaskUtils taskUtils
-    ) {
-        final Class<? extends AbstractTaskTO> taskTOClass = taskUtils.taskTOClass();
-
+    public SchedTask createSchedTask(final SchedTaskTO taskTO, final TaskUtils taskUtils) {
+        Class<? extends AbstractTaskTO> taskTOClass = taskUtils.taskTOClass();
         if (taskTOClass == null || !taskTOClass.equals(taskTO.getClass())) {
             throw new IllegalArgumentException(
                     String.format("taskUtils is type %s but task is not: %s", taskTOClass, taskTO.getClass()));
@@ -222,7 +241,7 @@ public class TaskDataBinderImpl implements TaskDataBinder {
         if (taskUtils.getType() == TaskType.SCHEDULED) {
             task.setJobClassName(taskTO.getJobClassName());
         } else if (taskTO instanceof AbstractProvisioningTaskTO) {
-            final AbstractProvisioningTaskTO provisioningTaskTO = (AbstractProvisioningTaskTO) taskTO;
+            AbstractProvisioningTaskTO provisioningTaskTO = (AbstractProvisioningTaskTO) taskTO;
 
             ExternalResource resource = resourceDAO.find(provisioningTaskTO.getResource());
             if (resource == null) {
@@ -237,10 +256,7 @@ public class TaskDataBinderImpl implements TaskDataBinder {
     }
 
     @Override
-    public void updateSchedTask(final SchedTask task,
-            final SchedTaskTO taskTO,
-            final TaskUtils taskUtils
-    ) {
+    public void updateSchedTask(final SchedTask task, final SchedTaskTO taskTO, final TaskUtils taskUtils) {
         Class<? extends Task> taskClass = taskUtils.taskClass();
         Class<? extends AbstractTaskTO> taskTOClass = taskUtils.taskTOClass();
 
@@ -268,8 +284,7 @@ public class TaskDataBinderImpl implements TaskDataBinder {
     }
 
     @Override
-    public TaskExecTO getTaskExecTO(final TaskExec execution
-    ) {
+    public TaskExecTO getTaskExecTO(final TaskExec execution) {
         TaskExecTO executionTO = new TaskExecTO();
         BeanUtils.copyProperties(execution, executionTO, IGNORE_TASK_EXECUTION_PROPERTIES);
 
@@ -347,6 +362,10 @@ public class TaskDataBinderImpl implements TaskDataBinder {
                         ? MatchingRule.UPDATE : ((SyncTask) task).getMatchingRule());
                 ((SyncTaskTO) taskTO).setUnmatchingRule(((SyncTask) task).getUnmatchingRule() == null
                         ? UnmatchingRule.PROVISION : ((SyncTask) task).getUnmatchingRule());
+
+                for (AnyTemplate template : ((SyncTask) task).getTemplates()) {
+                    ((SyncTaskTO) taskTO).getTemplates().put(template.getAnyType().getKey(), template.get());
+                }
                 break;
 
             case PUSH:
@@ -362,6 +381,10 @@ public class TaskDataBinderImpl implements TaskDataBinder {
                         ? MatchingRule.LINK : ((PushTask) task).getMatchingRule());
                 ((PushTaskTO) taskTO).setUnmatchingRule(((PushTask) task).getUnmatchingRule() == null
                         ? UnmatchingRule.ASSIGN : ((PushTask) task).getUnmatchingRule());
+
+                for (AnyFilter filter : ((PushTask) task).getFilters()) {
+                    ((PushTaskTO) taskTO).getFilters().put(filter.getAnyType().getKey(), filter.get());
+                }
                 break;
 
             case NOTIFICATION:

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
index 54d10bc..6c5e0d6 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/data/UserDataBinderImpl.java
@@ -32,6 +32,7 @@ import org.apache.syncope.common.lib.SyncopeClientCompositeException;
 import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.mod.UserMod;
 import org.apache.syncope.common.lib.to.MembershipTO;
+import org.apache.syncope.common.lib.to.RelationshipTO;
 import org.apache.syncope.common.lib.to.UserTO;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.CipherAlgorithm;
@@ -49,7 +50,9 @@ import org.apache.syncope.core.misc.security.Encryptor;
 import org.apache.syncope.core.misc.spring.BeanUtils;
 import org.apache.syncope.core.persistence.api.dao.RoleDAO;
 import org.apache.syncope.core.persistence.api.entity.Role;
+import org.apache.syncope.core.persistence.api.entity.anyobject.AnyObject;
 import org.apache.syncope.core.persistence.api.entity.user.UMembership;
+import org.apache.syncope.core.persistence.api.entity.user.URelationship;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 import org.springframework.transaction.annotation.Transactional;
@@ -58,9 +61,9 @@ import org.springframework.transaction.annotation.Transactional;
 @Transactional(rollbackFor = { Throwable.class })
 public class UserDataBinderImpl extends AbstractAnyDataBinder implements UserDataBinder {
 
-    private static final String[] IGNORE_USER_PROPERTIES = {
-        "realm", "roles", "memberships", "plainAttrs", "derAttrs", "virAttrs", "resources",
-        "securityQuestion", "securityAnswer"
+    private static final String[] IGNORE_PROPERTIES = {
+        "type", "realm", "auxClasses", "roles", "dynRoles", "relationships", "memberships", "dynGroups",
+        "plainAttrs", "derAttrs", "virAttrs", "resources", "securityQuestion", "securityAnswer"
     };
 
     @Autowired
@@ -144,6 +147,29 @@ public class UserDataBinderImpl extends AbstractAnyDataBinder implements UserDat
             }
         }
 
+        // relationships
+        for (RelationshipTO relationshipTO : userTO.getRelationships()) {
+            AnyObject anyObject = anyObjectDAO.find(relationshipTO.getRightKey());
+
+            if (anyObject == null) {
+                if (LOG.isDebugEnabled()) {
+                    LOG.debug("Ignoring invalid anyObject " + relationshipTO.getRightKey());
+                }
+            } else {
+                URelationship relationship = null;
+                if (user.getKey() != null) {
+                    relationship = user.getRelationship(anyObject.getKey());
+                }
+                if (relationship == null) {
+                    relationship = entityFactory.newEntity(URelationship.class);
+                    relationship.setRightEnd(anyObject);
+                    relationship.setLeftEnd(user);
+
+                    user.add(relationship);
+                }
+            }
+        }
+
         // memberships
         for (MembershipTO membershipTO : userTO.getMemberships()) {
             Group group = groupDAO.find(membershipTO.getRightKey());
@@ -266,11 +292,44 @@ public class UserDataBinderImpl extends AbstractAnyDataBinder implements UserDat
         // attributes, derived attributes, virtual attributes and resources
         propByRes.merge(fill(user, userMod, anyUtilsFactory.getInstance(AnyTypeKind.USER), scce));
 
-        // store the group ids of membership required to be added
-        Set<Long> membershipToBeAddedGroupKeys = new HashSet<>(userMod.getMembershipsToAdd());
+        Set<String> toBeDeprovisioned = new HashSet<>();
+        Set<String> toBeProvisioned = new HashSet<>();
+
+        // relationships to be removed
+        for (Long anyObjectKey : userMod.getRelationshipsToRemove()) {
+            LOG.debug("Relationship to be removed for any object {}", anyObjectKey);
+
+            URelationship relationship = user.getRelationship(anyObjectKey);
+            if (relationship == null) {
+                LOG.warn("Invalid anyObject key specified for relationship to be removed: {}", anyObjectKey);
+            } else {
+                if (!userMod.getRelationshipsToAdd().contains(anyObjectKey)) {
+                    user.remove(relationship);
+                    toBeDeprovisioned.addAll(relationship.getRightEnd().getResourceNames());
+                }
+            }
+        }
+
+        // relationships to be added
+        for (Long anyObjectKey : userMod.getRelationshipsToAdd()) {
+            LOG.debug("Relationship to be added for any object {}", anyObjectKey);
+
+            AnyObject otherEnd = anyObjectDAO.find(anyObjectKey);
+            if (otherEnd == null) {
+                LOG.debug("Ignoring invalid any object {}", anyObjectKey);
+            } else {
+                URelationship relationship = user.getRelationship(otherEnd.getKey());
+                if (relationship == null) {
+                    relationship = entityFactory.newEntity(URelationship.class);
+                    relationship.setRightEnd(otherEnd);
+                    relationship.setLeftEnd(user);
+
+                    user.add(relationship);
 
-        final Set<String> toBeDeprovisioned = new HashSet<>();
-        final Set<String> toBeProvisioned = new HashSet<>();
+                    toBeProvisioned.addAll(otherEnd.getResourceNames());
+                }
+            }
+        }
 
         // memberships to be removed
         for (Long groupKey : userMod.getMembershipsToRemove()) {
@@ -278,11 +337,10 @@ public class UserDataBinderImpl extends AbstractAnyDataBinder implements UserDat
 
             UMembership membership = user.getMembership(groupKey);
             if (membership == null) {
-                LOG.warn("Invalid group key specified for membership to be removed: {}", groupKey);
+                LOG.debug("Invalid group key specified for membership to be removed: {}", groupKey);
             } else {
-                if (membershipToBeAddedGroupKeys.contains(membership.getRightEnd().getKey())) {
+                if (!userMod.getMembershipsToAdd().contains(groupKey)) {
                     user.remove(membership);
-                } else {
                     toBeDeprovisioned.addAll(membership.getRightEnd().getResourceNames());
                 }
             }
@@ -312,10 +370,8 @@ public class UserDataBinderImpl extends AbstractAnyDataBinder implements UserDat
         propByRes.addAll(ResourceOperation.DELETE, toBeDeprovisioned);
         propByRes.addAll(ResourceOperation.UPDATE, toBeProvisioned);
 
-        /**
-         * In case of new memberships all the current resources have to be updated in order to propagate new group and
-         * membership attribute values.
-         */
+        // In case of new memberships all current resources need to be updated in order to propagate new group
+        // attribute values.
         if (!toBeDeprovisioned.isEmpty() || !toBeProvisioned.isEmpty()) {
             currentResources.removeAll(toBeDeprovisioned);
             propByRes.addAll(ResourceOperation.UPDATE, currentResources);
@@ -340,25 +396,43 @@ public class UserDataBinderImpl extends AbstractAnyDataBinder implements UserDat
     public UserTO getUserTO(final User user) {
         UserTO userTO = new UserTO();
 
-        BeanUtils.copyProperties(user, userTO, IGNORE_USER_PROPERTIES);
+        BeanUtils.copyProperties(user, userTO, IGNORE_PROPERTIES);
 
         if (user.getSecurityQuestion() != null) {
             userTO.setSecurityQuestion(user.getSecurityQuestion().getKey());
         }
 
-        connObjectUtils.retrieveVirAttrValues(user);
-        fillTO(userTO, user.getRealm().getFullPath(),
+        virAttrHander.retrieveVirAttrValues(user);
+        fillTO(userTO, user.getRealm().getFullPath(), user.getAuxClasses(),
                 user.getPlainAttrs(), user.getDerAttrs(), user.getVirAttrs(), userDAO.findAllResources(user));
 
-        for (UMembership membership : user.getMemberships()) {
-            MembershipTO membershipTO = new MembershipTO();
+        // roles
+        CollectionUtils.collect(user.getRoles(), new Transformer<Role, Long>() {
+
+            @Override
+            public Long transform(final Role role) {
+                return role.getKey();
+            }
+        }, userTO.getRoles());
+
+        // relationships
+        CollectionUtils.collect(user.getRelationships(), new Transformer<URelationship, RelationshipTO>() {
 
-            membershipTO.setKey(membership.getKey());
-            membershipTO.setRightKey(membership.getRightEnd().getKey());
-            membershipTO.setGroupName(membership.getRightEnd().getName());
+            @Override
+            public RelationshipTO transform(final URelationship relationship) {
+                return UserDataBinderImpl.this.getRelationshipTO(relationship);
+            }
 
-            userTO.getMemberships().add(membershipTO);
-        }
+        }, userTO.getRelationships());
+
+        // memberships
+        CollectionUtils.collect(user.getMemberships(), new Transformer<UMembership, MembershipTO>() {
+
+            @Override
+            public MembershipTO transform(final UMembership membership) {
+                return UserDataBinderImpl.this.getMembershipTO(membership);
+            }
+        }, userTO.getMemberships());
 
         // dynamic memberships
         CollectionUtils.collect(userDAO.findDynRoleMemberships(user), new Transformer<Role, Long>() {

http://git-wip-us.apache.org/repos/asf/syncope/blob/dd88efbd/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/NotificationManagerImpl.java
----------------------------------------------------------------------
diff --git a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/NotificationManagerImpl.java b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/NotificationManagerImpl.java
index a0469a2..cdc540c 100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/NotificationManagerImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/NotificationManagerImpl.java
@@ -54,14 +54,13 @@ import org.apache.syncope.core.persistence.api.entity.user.UVirAttr;
 import org.apache.syncope.core.persistence.api.entity.user.User;
 import org.apache.syncope.core.provisioning.api.data.GroupDataBinder;
 import org.apache.syncope.core.provisioning.api.data.UserDataBinder;
-import org.apache.syncope.core.misc.ConnObjectUtils;
 import org.apache.syncope.core.misc.search.SearchCondConverter;
 import org.apache.syncope.core.persistence.api.dao.AnyObjectDAO;
 import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
 import org.apache.syncope.core.persistence.api.entity.Any;
 import org.apache.syncope.core.persistence.api.entity.AnyAbout;
 import org.apache.syncope.core.persistence.api.entity.AnyType;
-import org.apache.syncope.core.persistence.api.entity.AnyUtilsFactory;
+import org.apache.syncope.core.provisioning.api.VirAttrHandler;
 import org.apache.velocity.VelocityContext;
 import org.apache.velocity.app.VelocityEngine;
 import org.apache.velocity.context.Context;
@@ -143,7 +142,7 @@ public class NotificationManagerImpl implements NotificationManager {
     private ToolManager velocityToolManager;
 
     @Autowired
-    private ConnObjectUtils connObjectUtils;
+    private VirAttrHandler virAttrHander;
 
     @Autowired
     private UserDataBinder userDataBinder;
@@ -154,9 +153,6 @@ public class NotificationManagerImpl implements NotificationManager {
     @Autowired
     private EntityFactory entityFactory;
 
-    @Autowired
-    private AnyUtilsFactory anyUtilsFactory;
-
     @Transactional(readOnly = true)
     @Override
     public long getMaxRetries() {
@@ -177,10 +173,10 @@ public class NotificationManagerImpl implements NotificationManager {
             final Map<String, Object> model) {
 
         if (any != null) {
-            connObjectUtils.retrieveVirAttrValues(any);
+            virAttrHander.retrieveVirAttrValues(any);
         }
 
-        final List<User> recipients = new ArrayList<>();
+        List<User> recipients = new ArrayList<>();
 
         if (notification.getRecipients() != null) {
             recipients.addAll(searchDAO.<User>search(SyncopeConstants.FULL_ADMIN_REALMS,
@@ -192,10 +188,10 @@ public class NotificationManagerImpl implements NotificationManager {
             recipients.add((User) any);
         }
 
-        final Set<String> recipientEmails = new HashSet<>();
-        final List<UserTO> recipientTOs = new ArrayList<>(recipients.size());
+        Set<String> recipientEmails = new HashSet<>();
+        List<UserTO> recipientTOs = new ArrayList<>(recipients.size());
         for (User recipient : recipients) {
-            connObjectUtils.retrieveVirAttrValues(recipient);
+            virAttrHander.retrieveVirAttrValues(recipient);
 
             String email = getRecipientEmail(notification.getRecipientAttrType(),
                     notification.getRecipientAttrName(), recipient);


[13/21] syncope git commit: Updating maven-assembly-plugin and selenium

Posted by il...@apache.org.
Updating maven-assembly-plugin and selenium


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

Branch: refs/heads/SYNCOPE-666
Commit: 632acda501c989d2f5620968412500923f0ee88c
Parents: c03b1cf
Author: Francesco Chicchiriccò <il...@apache.org>
Authored: Fri Jun 5 14:50:14 2015 +0200
Committer: Francesco Chicchiriccò <il...@apache.org>
Committed: Fri Jun 5 14:50:14 2015 +0200

----------------------------------------------------------------------
 pom.xml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/632acda5/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index cbcc04f..441f906 100644
--- a/pom.xml
+++ b/pom.xml
@@ -369,7 +369,7 @@ under the License.
     <disruptor.version>3.3.2</disruptor.version>
 
     <junit.version>4.11</junit.version>
-    <selenium.version>2.45.0</selenium.version>
+    <selenium.version>2.46.0</selenium.version>
 
     <apacheds.version>1.5.7</apacheds.version>
     
@@ -1245,7 +1245,7 @@ under the License.
         <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-assembly-plugin</artifactId>
-          <version>2.5.4</version>
+          <version>2.5.5</version>
         </plugin>
         <plugin>
           <groupId>org.eclipse.m2e</groupId>


[10/21] syncope git commit: [SYNCOPE-667] Merge from 1_2_X

Posted by il...@apache.org.
[SYNCOPE-667] Merge from 1_2_X


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

Branch: refs/heads/SYNCOPE-666
Commit: 2f028924d52d5cb48595aa7e5056c20aeadb4945
Parents: 8cc3ffc 18394d3
Author: giacomolm <gi...@hotmail.it>
Authored: Fri Jun 5 09:40:35 2015 +0200
Committer: giacomolm <gi...@hotmail.it>
Committed: Fri Jun 5 09:40:35 2015 +0200

----------------------------------------------------------------------
 .../provisioning/api/notification/NotificationManager.java   | 4 +++-
 .../java/notification/NotificationManagerImpl.java           | 8 ++++++--
 2 files changed, 9 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/2f028924/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/notification/NotificationManager.java
----------------------------------------------------------------------
diff --cc core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/notification/NotificationManager.java
index 391ab29,0000000..cb41d8c
mode 100644,000000..100644
--- a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/notification/NotificationManager.java
+++ b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/notification/NotificationManager.java
@@@ -1,64 -1,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.core.provisioning.api.notification;
 +
++import java.util.List;
 +import org.apache.syncope.common.lib.types.AuditElements;
++import org.apache.syncope.core.persistence.api.entity.task.NotificationTask;
 +import org.apache.syncope.core.persistence.api.entity.task.TaskExec;
 +
 +/**
 + * Create notification tasks that will be executed by NotificationJob.
 + *
 + * @see org.apache.syncope.core.persistence.api.entity.task.NotificationTask
 + */
 +public interface NotificationManager {
 +
 +    /**
 +     * Count the number of task executions of a given task with a given status.
 +     *
 +     * @param taskId task id
 +     * @param status status
 +     * @return number of task executions
 +     */
 +    long countExecutionsWithStatus(final Long taskId, final String status);
 +
 +    /**
 +     * Create notification tasks for each notification matching the given user id and (some of) tasks performed.
 +     */
-     void createTasks(AuditElements.EventCategoryType type, String category, String subcategory,
++    List<NotificationTask> createTasks(AuditElements.EventCategoryType type, String category, String subcategory,
 +            String event, AuditElements.Result condition, Object before, Object output, Object... input);
 +
 +    long getMaxRetries();
 +
 +    /**
 +     * Set execution state of NotificationTask with provided id.
 +     *
 +     * @param taskId task to be updated
 +     * @param executed execution state
 +     */
 +    void setTaskExecuted(final Long taskId, final boolean executed);
 +
 +    /**
 +     * Store execution of a NotificationTask.
 +     *
 +     * @param execution task execution.
 +     * @return merged task execution.
 +     */
 +    TaskExec storeExec(final TaskExec execution);
 +
 +}

http://git-wip-us.apache.org/repos/asf/syncope/blob/2f028924/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/NotificationManagerImpl.java
----------------------------------------------------------------------
diff --cc core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/NotificationManagerImpl.java
index 7153529,0000000..900abc7
mode 100644,000000..100644
--- a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/NotificationManagerImpl.java
+++ b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/notification/NotificationManagerImpl.java
@@@ -1,410 -1,0 +1,414 @@@
 +/*
 + * Licensed to the Apache Software Foundation (ASF) under one
 + * or more contributor license agreements.  See the NOTICE file
 + * distributed with this work for additional information
 + * regarding copyright ownership.  The ASF licenses this file
 + * to you under the Apache License, Version 2.0 (the
 + * "License"); you may not use this file except in compliance
 + * with the License.  You may obtain a copy of the License at
 + *
 + *   http://www.apache.org/licenses/LICENSE-2.0
 + *
 + * Unless required by applicable law or agreed to in writing,
 + * software distributed under the License is distributed on an
 + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 + * KIND, either express or implied.  See the License for the
 + * specific language governing permissions and limitations
 + * under the License.
 + */
 +package org.apache.syncope.core.provisioning.java.notification;
 +
 +import org.apache.syncope.core.provisioning.api.notification.NotificationManager;
 +import java.io.StringWriter;
 +import java.util.ArrayList;
 +import java.util.Collections;
 +import java.util.HashMap;
 +import java.util.HashSet;
 +import java.util.List;
 +import java.util.Map;
 +import java.util.Set;
 +import org.apache.syncope.common.lib.SyncopeConstants;
 +import org.apache.syncope.common.lib.to.GroupTO;
 +import org.apache.syncope.common.lib.to.UserTO;
 +import org.apache.syncope.common.lib.types.AttributableType;
 +import org.apache.syncope.common.lib.types.AuditElements;
 +import org.apache.syncope.common.lib.types.AuditElements.Result;
 +import org.apache.syncope.common.lib.types.AuditLoggerName;
 +import org.apache.syncope.common.lib.types.IntMappingType;
 +import org.apache.syncope.common.lib.types.SubjectType;
 +import org.apache.syncope.common.lib.CollectionUtils2;
 +import org.apache.syncope.core.persistence.api.dao.ConfDAO;
 +import org.apache.syncope.core.persistence.api.dao.NotificationDAO;
 +import org.apache.syncope.core.persistence.api.dao.GroupDAO;
 +import org.apache.syncope.core.persistence.api.dao.SubjectSearchDAO;
 +import org.apache.syncope.core.persistence.api.dao.TaskDAO;
 +import org.apache.syncope.core.persistence.api.dao.UserDAO;
 +import org.apache.syncope.core.persistence.api.dao.search.OrderByClause;
 +import org.apache.syncope.core.persistence.api.entity.Attributable;
 +import org.apache.syncope.core.persistence.api.entity.AttributableUtilsFactory;
 +import org.apache.syncope.core.persistence.api.entity.EntityFactory;
 +import org.apache.syncope.core.persistence.api.entity.Notification;
 +import org.apache.syncope.core.persistence.api.entity.PlainAttr;
 +import org.apache.syncope.core.persistence.api.entity.Subject;
 +import org.apache.syncope.core.persistence.api.entity.group.Group;
 +import org.apache.syncope.core.persistence.api.entity.task.NotificationTask;
 +import org.apache.syncope.core.persistence.api.entity.task.TaskExec;
 +import org.apache.syncope.core.persistence.api.entity.user.UDerAttr;
 +import org.apache.syncope.core.persistence.api.entity.user.UPlainAttr;
 +import org.apache.syncope.core.persistence.api.entity.user.UVirAttr;
 +import org.apache.syncope.core.persistence.api.entity.user.User;
 +import org.apache.syncope.core.provisioning.api.data.GroupDataBinder;
 +import org.apache.syncope.core.provisioning.api.data.UserDataBinder;
 +import org.apache.syncope.core.misc.ConnObjectUtils;
 +import org.apache.syncope.core.misc.search.SearchCondConverter;
 +import org.apache.velocity.VelocityContext;
 +import org.apache.velocity.app.VelocityEngine;
 +import org.apache.velocity.context.Context;
 +import org.apache.velocity.exception.VelocityException;
 +import org.apache.velocity.tools.ToolManager;
 +import org.slf4j.Logger;
 +import org.slf4j.LoggerFactory;
 +import org.springframework.beans.factory.annotation.Autowired;
 +import org.springframework.stereotype.Component;
 +import org.springframework.transaction.annotation.Transactional;
 +
 +@Component
 +@Transactional(rollbackFor = { Throwable.class })
 +public class NotificationManagerImpl implements NotificationManager {
 +
 +    /**
 +     * Logger.
 +     */
 +    private static final Logger LOG = LoggerFactory.getLogger(NotificationManager.class);
 +
 +    public static final String MAIL_TEMPLATES = "mailTemplates/";
 +
 +    public static final String MAIL_TEMPLATE_HTML_SUFFIX = ".html.vm";
 +
 +    public static final String MAIL_TEMPLATE_TEXT_SUFFIX = ".txt.vm";
 +
 +    /**
 +     * Notification DAO.
 +     */
 +    @Autowired
 +    private NotificationDAO notificationDAO;
 +
 +    /**
 +     * Configuration DAO.
 +     */
 +    @Autowired
 +    private ConfDAO confDAO;
 +
 +    /**
 +     * User DAO.
 +     */
 +    @Autowired
 +    private UserDAO userDAO;
 +
 +    /**
 +     * Group DAO.
 +     */
 +    @Autowired
 +    private GroupDAO groupDAO;
 +
 +    /**
 +     * User Search DAO.
 +     */
 +    @Autowired
 +    private SubjectSearchDAO searchDAO;
 +
 +    /**
 +     * Task DAO.
 +     */
 +    @Autowired
 +    private TaskDAO taskDAO;
 +
 +    /**
 +     * Velocity template engine.
 +     */
 +    @Autowired
 +    private VelocityEngine velocityEngine;
 +
 +    /**
 +     * Velocity tool manager.
 +     */
 +    @Autowired
 +    private ToolManager velocityToolManager;
 +
 +    @Autowired
 +    private ConnObjectUtils connObjectUtils;
 +
 +    @Autowired
 +    private UserDataBinder userDataBinder;
 +
 +    @Autowired
 +    private GroupDataBinder groupDataBinder;
 +
 +    @Autowired
 +    private EntityFactory entityFactory;
 +
 +    @Autowired
 +    private AttributableUtilsFactory attrUtilsFactory;
 +
 +    @Transactional(readOnly = true)
 +    @Override
 +    public long getMaxRetries() {
 +        return confDAO.find("notification.maxRetries", "0").getValues().get(0).getLongValue();
 +    }
 +
 +    /**
 +     * Create a notification task.
 +     *
 +     * @param notification notification to take as model
 +     * @param attributable the user this task is about
 +     * @param model Velocity model
 +     * @return notification task, fully populated
 +     */
 +    private NotificationTask getNotificationTask(
 +            final Notification notification,
 +            final Attributable<?, ?, ?> attributable,
 +            final Map<String, Object> model) {
 +
 +        if (attributable != null) {
 +            connObjectUtils.retrieveVirAttrValues(attributable,
 +                    attrUtilsFactory.getInstance(
 +                            attributable instanceof User ? AttributableType.USER : AttributableType.GROUP));
 +        }
 +
 +        final List<User> recipients = new ArrayList<>();
 +
 +        if (notification.getRecipients() != null) {
 +            recipients.addAll(searchDAO.<User>search(SyncopeConstants.FULL_ADMIN_REALMS,
 +                    SearchCondConverter.convert(notification.getRecipients()),
 +                    Collections.<OrderByClause>emptyList(), SubjectType.USER));
 +        }
 +
 +        if (notification.isSelfAsRecipient() && attributable instanceof User) {
 +            recipients.add((User) attributable);
 +        }
 +
 +        final Set<String> recipientEmails = new HashSet<>();
 +        final List<UserTO> recipientTOs = new ArrayList<>(recipients.size());
 +        for (User recipient : recipients) {
 +            connObjectUtils.retrieveVirAttrValues(recipient, attrUtilsFactory.getInstance(AttributableType.USER));
 +
 +            String email = getRecipientEmail(notification.getRecipientAttrType(),
 +                    notification.getRecipientAttrName(), recipient);
 +            if (email == null) {
 +                LOG.warn("{} cannot be notified: {} not found", recipient, notification.getRecipientAttrName());
 +            } else {
 +                recipientEmails.add(email);
 +                recipientTOs.add(userDataBinder.getUserTO(recipient));
 +            }
 +        }
 +
 +        if (notification.getStaticRecipients() != null) {
 +            recipientEmails.addAll(notification.getStaticRecipients());
 +        }
 +
 +        model.put("recipients", recipientTOs);
 +        model.put("syncopeConf", this.findAllSyncopeConfs());
 +        model.put("events", notification.getEvents());
 +
 +        NotificationTask task = entityFactory.newEntity(NotificationTask.class);
 +        task.setTraceLevel(notification.getTraceLevel());
 +        task.getRecipients().addAll(recipientEmails);
 +        task.setSender(notification.getSender());
 +        task.setSubject(notification.getSubject());
 +
 +        String htmlBody = mergeTemplateIntoString(
 +                MAIL_TEMPLATES + notification.getTemplate() + MAIL_TEMPLATE_HTML_SUFFIX, model);
 +        String textBody = mergeTemplateIntoString(
 +                MAIL_TEMPLATES + notification.getTemplate() + MAIL_TEMPLATE_TEXT_SUFFIX, model);
 +
 +        task.setHtmlBody(htmlBody);
 +        task.setTextBody(textBody);
 +
 +        return task;
 +    }
 +
 +    private String mergeTemplateIntoString(final String templateLocation, final Map<String, Object> model) {
 +        StringWriter result = new StringWriter();
 +        try {
 +            Context velocityContext = createVelocityContext(model);
 +            velocityEngine.mergeTemplate(templateLocation, SyncopeConstants.DEFAULT_ENCODING, velocityContext, result);
 +        } catch (VelocityException e) {
 +            LOG.error("Could not get mail body", e);
 +        } catch (RuntimeException e) {
 +            // ensure same behaviour as by using Spring VelocityEngineUtils.mergeTemplateIntoString()
 +            throw e;
 +        } catch (Exception e) {
 +            LOG.error("Could not get mail body", e);
 +        }
 +
 +        return result.toString();
 +    }
 +
 +    /**
 +     * Create a Velocity Context for the given model, to be passed to the template for merging.
 +     *
 +     * @param model Velocity model
 +     * @return Velocity context
 +     */
 +    protected Context createVelocityContext(final Map<String, Object> model) {
 +        Context toolContext = velocityToolManager.createContext();
 +        return new VelocityContext(model, toolContext);
 +    }
 +
 +    @Override
-     public void createTasks(
++    public List<NotificationTask> createTasks(
 +            final AuditElements.EventCategoryType type,
 +            final String category,
 +            final String subcategory,
 +            final String event,
 +            final Result condition,
 +            final Object before,
 +            final Object output,
 +            final Object... input) {
 +
 +        SubjectType subjectType = null;
 +        Subject<?, ?, ?> subject = null;
++        List<NotificationTask> notificationList = new ArrayList<NotificationTask>();
 +
 +        if (before instanceof UserTO) {
 +            subjectType = SubjectType.USER;
 +            subject = userDAO.find(((UserTO) before).getKey());
 +        } else if (output instanceof UserTO) {
 +            subjectType = SubjectType.USER;
 +            subject = userDAO.find(((UserTO) output).getKey());
 +        } else if (before instanceof GroupTO) {
 +            subjectType = SubjectType.GROUP;
 +            subject = groupDAO.find(((GroupTO) before).getKey());
 +        } else if (output instanceof GroupTO) {
 +            subjectType = SubjectType.GROUP;
 +            subject = groupDAO.find(((GroupTO) output).getKey());
 +        }
 +
 +        LOG.debug("Search notification for [{}]{}", subjectType, subject);
 +
 +        for (Notification notification : notificationDAO.findAll()) {
 +            LOG.debug("Notification available user about {}", notification.getUserAbout());
 +            LOG.debug("Notification available group about {}", notification.getGroupAbout());
 +
 +            if (notification.isActive()) {
 +                String currentEvent = AuditLoggerName.buildEvent(type, category, subcategory, event, condition);
 +                if (!notification.getEvents().contains(currentEvent)) {
 +                    LOG.debug("No events found about {}", subject);
 +                } else if (subjectType == null || subject == null
 +                        || (subjectType == SubjectType.USER && (notification.getUserAbout() == null
 +                        || searchDAO.matches(subject,
 +                                SearchCondConverter.convert(notification.getUserAbout()), subjectType)))
 +                        || subjectType == SubjectType.GROUP && (notification.getGroupAbout() == null
 +                        || searchDAO.matches(subject,
 +                                SearchCondConverter.convert(notification.getGroupAbout()), subjectType))) {
 +
 +                    LOG.debug("Creating notification task for event {} about {}", currentEvent, subject);
 +
 +                    final Map<String, Object> model = new HashMap<>();
 +                    model.put("type", type);
 +                    model.put("category", category);
 +                    model.put("subcategory", subcategory);
 +                    model.put("event", event);
 +                    model.put("condition", condition);
 +                    model.put("before", before);
 +                    model.put("output", output);
 +                    model.put("input", input);
 +
 +                    if (subject instanceof User) {
 +                        model.put("user", userDataBinder.getUserTO((User) subject));
 +                    } else if (subject instanceof Group) {
 +                        model.put("group", groupDataBinder.getGroupTO((Group) subject));
 +                    }
 +
-                     taskDAO.save(getNotificationTask(notification, subject, model));
++                    NotificationTask notificationTask = getNotificationTask(notification, subject, model);
++                    notificationTask = taskDAO.save(notificationTask);
++                    notificationList.add(notificationTask);     
 +                }
 +            } else {
 +                LOG.debug("Notification {}, userAbout {}, groupAbout {} is deactivated, "
 +                        + "notification task will not be created", notification.getKey(),
 +                        notification.getUserAbout(), notification.getGroupAbout());
 +            }
 +        }
++        return notificationList;
 +    }
 +
 +    private String getRecipientEmail(
 +            final IntMappingType recipientAttrType, final String recipientAttrName, final User user) {
 +
 +        String email = null;
 +
 +        switch (recipientAttrType) {
 +            case Username:
 +                email = user.getUsername();
 +                break;
 +
 +            case UserPlainSchema:
 +                UPlainAttr attr = user.getPlainAttr(recipientAttrName);
 +                if (attr != null) {
 +                    email = CollectionUtils2.getFirstOrNull(attr.getValuesAsStrings());
 +                }
 +                break;
 +
 +            case UserDerivedSchema:
 +                UDerAttr derAttr = user.getDerAttr(recipientAttrName);
 +                if (derAttr != null) {
 +                    email = derAttr.getValue(user.getPlainAttrs());
 +                }
 +                break;
 +
 +            case UserVirtualSchema:
 +                UVirAttr virAttr = user.getVirAttr(recipientAttrName);
 +                if (virAttr != null) {
 +                    email = CollectionUtils2.getFirstOrNull(virAttr.getValues());
 +                }
 +                break;
 +
 +            default:
 +        }
 +
 +        return email;
 +    }
 +
 +    @Override
 +    public TaskExec storeExec(final TaskExec execution) {
 +        NotificationTask task = taskDAO.find(execution.getTask().getKey());
 +        task.addExec(execution);
 +        task.setExecuted(true);
 +        taskDAO.save(task);
 +        // this flush call is needed to generate a value for the execution id
 +        taskDAO.flush();
 +        return execution;
 +    }
 +
 +    @Override
 +    public void setTaskExecuted(final Long taskId, final boolean executed) {
 +        NotificationTask task = taskDAO.find(taskId);
 +        task.setExecuted(executed);
 +        taskDAO.save(task);
 +    }
 +
 +    @Override
 +    public long countExecutionsWithStatus(final Long taskId, final String status) {
 +        NotificationTask task = taskDAO.find(taskId);
 +        long count = 0;
 +        for (TaskExec taskExec : task.getExecs()) {
 +            if (status == null) {
 +                if (taskExec.getStatus() == null) {
 +                    count++;
 +                }
 +            } else if (status.equals(taskExec.getStatus())) {
 +                count++;
 +            }
 +        }
 +        return count;
 +    }
 +
 +    protected Map<String, String> findAllSyncopeConfs() {
 +        Map<String, String> syncopeConfMap = new HashMap<>();
 +        for (PlainAttr attr : confDAO.get().getPlainAttrs()) {
 +            syncopeConfMap.put(attr.getSchema().getKey(), attr.getValuesAsStrings().get(0));
 +        }
 +        return syncopeConfMap;
 +    }
 +}