[SYNCOPE-1299] Reworking REST service definition to allow more flexibility

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

Branch: refs/heads/master
Commit: 44a5e1da7adf8aa6519fea8410b82ea0ac6b425e
Parents: 24f7899
Author: Francesco Chicchiriccò <ilgro...@apache.org>
Authored: Fri Apr 13 11:14:56 2018 +0200
Committer: Francesco Chicchiriccò <ilgro...@apache.org>
Committed: Fri Apr 13 11:53:15 2018 +0200

----------------------------------------------------------------------
 .../common/lib/to/ReconciliationRequest.java    | 100 -------------------
 .../common/lib/types/ReconciliationAction.java  |  28 ------
 .../rest/api/service/ReconciliationService.java |  40 +++++++-
 .../syncope/core/logic/ReconciliationLogic.java |  73 ++++++++------
 .../api/pushpull/SyncopeSinglePullExecutor.java |   4 +-
 .../api/pushpull/SyncopeSinglePushExecutor.java |   3 +-
 .../pushpull/AbstractSyncopeResultHandler.java  |   1 +
 .../java/pushpull/SinglePullJobDelegate.java    |  44 ++++++--
 .../java/pushpull/SinglePushJobDelegate.java    |  16 +--
 .../cxf/service/ReconciliationServiceImpl.java  |  32 +++++-
 .../syncope/fit/core/ReconciliationITCase.java  |  24 ++---
 11 files changed, 165 insertions(+), 200 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/syncope/blob/44a5e1da/common/lib/src/main/java/org/apache/syncope/common/lib/to/ReconciliationRequest.java
----------------------------------------------------------------------
diff --git 
a/common/lib/src/main/java/org/apache/syncope/common/lib/to/ReconciliationRequest.java
 
b/common/lib/src/main/java/org/apache/syncope/common/lib/to/ReconciliationRequest.java
deleted file mode 100644
index 2ebf699..0000000
--- 
a/common/lib/src/main/java/org/apache/syncope/common/lib/to/ReconciliationRequest.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.common.lib.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 org.apache.syncope.common.lib.AbstractBaseBean;
-import org.apache.syncope.common.lib.types.AnyTypeKind;
-import org.apache.syncope.common.lib.types.ReconciliationAction;
-
-public class ReconciliationRequest extends AbstractBaseBean {
-
-    private static final long serialVersionUID = -2592156800185957182L;
-
-    private AnyTypeKind anyTypeKind;
-
-    private String anyKey;
-
-    private String resourceKey;
-
-    private ReconciliationAction action;
-
-    private boolean remediation;
-
-    private final List<String> actions = new ArrayList<>();
-
-    @JsonProperty(required = true)
-    @XmlElement(required = true)
-    public AnyTypeKind getAnyTypeKind() {
-        return anyTypeKind;
-    }
-
-    public void setAnyTypeKind(final AnyTypeKind anyTypeKind) {
-        this.anyTypeKind = anyTypeKind;
-    }
-
-    @JsonProperty(required = true)
-    @XmlElement(required = true)
-    public String getAnyKey() {
-        return anyKey;
-    }
-
-    public void setAnyKey(final String anyKey) {
-        this.anyKey = anyKey;
-    }
-
-    @JsonProperty(required = true)
-    @XmlElement(required = true)
-    public String getResourceKey() {
-        return resourceKey;
-    }
-
-    public void setResourceKey(final String resourceKey) {
-        this.resourceKey = resourceKey;
-    }
-
-    @JsonProperty(required = true)
-    @XmlElement(required = true)
-    public ReconciliationAction getAction() {
-        return action;
-    }
-
-    public void setAction(final ReconciliationAction action) {
-        this.action = action;
-    }
-
-    public boolean isRemediation() {
-        return remediation;
-    }
-
-    public void setRemediation(final boolean remediation) {
-        this.remediation = remediation;
-    }
-
-    @XmlElementWrapper(name = "actions")
-    @XmlElement(name = "action")
-    @JsonProperty("actions")
-    public List<String> getActions() {
-        return actions;
-    }
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/44a5e1da/common/lib/src/main/java/org/apache/syncope/common/lib/types/ReconciliationAction.java
----------------------------------------------------------------------
diff --git 
a/common/lib/src/main/java/org/apache/syncope/common/lib/types/ReconciliationAction.java
 
b/common/lib/src/main/java/org/apache/syncope/common/lib/types/ReconciliationAction.java
deleted file mode 100644
index 19b68c2..0000000
--- 
a/common/lib/src/main/java/org/apache/syncope/common/lib/types/ReconciliationAction.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.syncope.common.lib.types;
-
-import javax.xml.bind.annotation.XmlEnum;
-
-@XmlEnum
-public enum ReconciliationAction {
-    PUSH,
-    PULL
-
-}

http://git-wip-us.apache.org/repos/asf/syncope/blob/44a5e1da/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/ReconciliationService.java
----------------------------------------------------------------------
diff --git 
a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/ReconciliationService.java
 
b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/ReconciliationService.java
index 77eb840..068f840 100644
--- 
a/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/ReconciliationService.java
+++ 
b/common/rest-api/src/main/java/org/apache/syncope/common/rest/api/service/ReconciliationService.java
@@ -32,7 +32,8 @@ import javax.ws.rs.Produces;
 import javax.ws.rs.QueryParam;
 import javax.ws.rs.core.MediaType;
 import org.apache.syncope.common.lib.SyncopeConstants;
-import org.apache.syncope.common.lib.to.ReconciliationRequest;
+import org.apache.syncope.common.lib.to.PullTaskTO;
+import org.apache.syncope.common.lib.to.PushTaskTO;
 import org.apache.syncope.common.lib.to.ReconciliationStatus;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 
@@ -64,15 +65,44 @@ public interface ReconciliationService extends JAXRSService 
{
             @NotNull @QueryParam("resourceKey") String resourceKey);
 
     /**
-     * Perform the required reconciliation action (PUSH or PULL) to the given 
user, group or any object and
-     * External Resource.
+     * Pushes the given user, group or any object in Syncope onto the External 
Resource.
      *
-     * @param request reconciliation request
+     * @param anyTypeKind anyTypeKind
+     * @param anyKey user, group or any object: if value looks like a UUID 
then it is interpreted as key, otherwise as
+     * a (user)name
+     * @param resourceKey resource key
+     * @param pushTask push specification
      */
     @ApiResponses(
             @ApiResponse(responseCode = "204", description = "Operation was 
successful"))
     @POST
+    @Path("push")
     @Consumes({ MediaType.APPLICATION_JSON, SyncopeConstants.APPLICATION_YAML, 
MediaType.APPLICATION_XML })
     @Produces({ MediaType.APPLICATION_JSON, SyncopeConstants.APPLICATION_YAML, 
MediaType.APPLICATION_XML })
-    void reconcile(@NotNull ReconciliationRequest request);
+    void push(
+            @NotNull @QueryParam("anyTypeKind") AnyTypeKind anyTypeKind,
+            @NotNull @QueryParam("anyKey") String anyKey,
+            @NotNull @QueryParam("resourceKey") String resourceKey,
+            @NotNull PushTaskTO pushTask);
+
+    /**
+     * Pulls the given user, group or any object from the External Resource 
into Syncope.
+     *
+     * @param anyTypeKind anyTypeKind
+     * @param anyKey user, group or any object: if value looks like a UUID 
then it is interpreted as key, otherwise as
+     * a (user)name
+     * @param resourceKey resource key
+     * @param pullTask pull specification
+     */
+    @ApiResponses(
+            @ApiResponse(responseCode = "204", description = "Operation was 
successful"))
+    @POST
+    @Path("pull")
+    @Consumes({ MediaType.APPLICATION_JSON, SyncopeConstants.APPLICATION_YAML, 
MediaType.APPLICATION_XML })
+    @Produces({ MediaType.APPLICATION_JSON, SyncopeConstants.APPLICATION_YAML, 
MediaType.APPLICATION_XML })
+    void pull(
+            @NotNull @QueryParam("anyTypeKind") AnyTypeKind anyTypeKind,
+            @NotNull @QueryParam("anyKey") String anyKey,
+            @NotNull @QueryParam("resourceKey") String resourceKey,
+            @NotNull PullTaskTO pullTask);
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/44a5e1da/core/logic/src/main/java/org/apache/syncope/core/logic/ReconciliationLogic.java
----------------------------------------------------------------------
diff --git 
a/core/logic/src/main/java/org/apache/syncope/core/logic/ReconciliationLogic.java
 
b/core/logic/src/main/java/org/apache/syncope/core/logic/ReconciliationLogic.java
index a36c159..a686215 100644
--- 
a/core/logic/src/main/java/org/apache/syncope/core/logic/ReconciliationLogic.java
+++ 
b/core/logic/src/main/java/org/apache/syncope/core/logic/ReconciliationLogic.java
@@ -29,14 +29,14 @@ import org.apache.syncope.common.lib.SyncopeClientException;
 import org.apache.syncope.common.lib.collections.IteratorChain;
 import org.apache.syncope.common.lib.to.AttrTO;
 import org.apache.syncope.common.lib.to.ConnObjectTO;
-import org.apache.syncope.common.lib.to.ReconciliationRequest;
+import org.apache.syncope.common.lib.to.PullTaskTO;
+import org.apache.syncope.common.lib.to.PushTaskTO;
 import org.apache.syncope.common.lib.to.ReconciliationStatus;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.lib.types.ClientExceptionType;
 import org.apache.syncope.common.lib.types.StandardEntitlement;
 import org.apache.syncope.core.persistence.api.dao.ExternalResourceDAO;
 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.dao.VirSchemaDAO;
 import org.apache.syncope.core.persistence.api.entity.Any;
 import org.apache.syncope.core.persistence.api.entity.AnyUtils;
@@ -76,9 +76,6 @@ public class ReconciliationLogic extends 
AbstractTransactionalLogic<AbstractBase
     private VirSchemaDAO virSchemaDAO;
 
     @Autowired
-    private RealmDAO realmDAO;
-
-    @Autowired
     private MappingManager mappingManager;
 
     @Autowired
@@ -180,38 +177,52 @@ public class ReconciliationLogic extends 
AbstractTransactionalLogic<AbstractBase
     }
 
     @PreAuthorize("hasRole('" + StandardEntitlement.TASK_EXECUTE + "')")
-    public void reconcile(final ReconciliationRequest request) {
-        Pair<Any<?>, Provision> init = init(request.getAnyTypeKind(), 
request.getAnyKey(), request.getResourceKey());
+    public void push(
+            final AnyTypeKind anyTypeKind,
+            final String anyKey,
+            final String resourceKey,
+            final PushTaskTO pushTask) {
+
+        Pair<Any<?>, Provision> init = init(anyTypeKind, anyKey, resourceKey);
 
         SyncopeClientException sce = 
SyncopeClientException.build(ClientExceptionType.Reconciliation);
         try {
-            List<ProvisioningReport> results = null;
-            switch (request.getAction()) {
-                case PUSH:
-                    results = singlePushExecutor.push(
-                            init.getRight(),
-                            
connFactory.getConnector(init.getRight().getResource()),
-                            init.getLeft(),
-                            request.getActions());
-                    break;
-
-                case PULL:
-                    results = singlePullExecutor.pull(
-                            init.getRight(),
-                            
connFactory.getConnector(init.getRight().getResource()),
-                            
init.getRight().getMapping().getConnObjectKeyItem().get().getExtAttrName(),
-                            
mappingManager.getConnObjectKeyValue(init.getLeft(), init.getRight()).get(),
-                            
realmDAO.findByFullPath(init.getLeft().getRealm().getFullPath()),
-                            request.isRemediation(),
-                            request.getActions());
-                    break;
-
-                default:
+            List<ProvisioningReport> results = singlePushExecutor.push(
+                    init.getRight(),
+                    connFactory.getConnector(init.getRight().getResource()),
+                    init.getLeft(),
+                    pushTask);
+            if (!results.isEmpty() && results.get(0).getStatus() == 
ProvisioningReport.Status.FAILURE) {
+                sce.getElements().add(results.get(0).getMessage());
             }
+        } catch (JobExecutionException e) {
+            sce.getElements().add(e.getMessage());
+        }
+
+        if (!sce.isEmpty()) {
+            throw sce;
+        }
+    }
 
-            if (results != null && !results.isEmpty()
-                    && results.get(0).getStatus() == 
ProvisioningReport.Status.FAILURE) {
+    @PreAuthorize("hasRole('" + StandardEntitlement.TASK_EXECUTE + "')")
+    public void pull(
+            final AnyTypeKind anyTypeKind,
+            final String anyKey,
+            final String resourceKey,
+            final PullTaskTO pullTask) {
 
+        Pair<Any<?>, Provision> init = init(anyTypeKind, anyKey, resourceKey);
+
+        SyncopeClientException sce = 
SyncopeClientException.build(ClientExceptionType.Reconciliation);
+        try {
+            List<ProvisioningReport> results = singlePullExecutor.pull(
+                    init.getRight(),
+                    connFactory.getConnector(init.getRight().getResource()),
+                    
init.getRight().getMapping().getConnObjectKeyItem().get().getExtAttrName(),
+                    mappingManager.getConnObjectKeyValue(init.getLeft(), 
init.getRight()).get(),
+                    init.getLeft().getRealm(),
+                    pullTask);
+            if (!results.isEmpty() && results.get(0).getStatus() == 
ProvisioningReport.Status.FAILURE) {
                 sce.getElements().add(results.get(0).getMessage());
             }
         } catch (JobExecutionException e) {

http://git-wip-us.apache.org/repos/asf/syncope/blob/44a5e1da/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/SyncopeSinglePullExecutor.java
----------------------------------------------------------------------
diff --git 
a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/SyncopeSinglePullExecutor.java
 
b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/SyncopeSinglePullExecutor.java
index bbf8430..000ee45 100644
--- 
a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/SyncopeSinglePullExecutor.java
+++ 
b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/SyncopeSinglePullExecutor.java
@@ -19,6 +19,7 @@
 package org.apache.syncope.core.provisioning.api.pushpull;
 
 import java.util.List;
+import org.apache.syncope.common.lib.to.PullTaskTO;
 import org.apache.syncope.core.persistence.api.entity.Realm;
 import org.apache.syncope.core.persistence.api.entity.resource.Provision;
 import org.apache.syncope.core.provisioning.api.Connector;
@@ -32,6 +33,5 @@ public interface SyncopeSinglePullExecutor {
             String connObjectKey,
             String connObjectValue,
             Realm realm,
-            boolean remediation,
-            List<String> actions) throws JobExecutionException;
+            PullTaskTO pullTaskTO) throws JobExecutionException;
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/44a5e1da/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/SyncopeSinglePushExecutor.java
----------------------------------------------------------------------
diff --git 
a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/SyncopeSinglePushExecutor.java
 
b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/SyncopeSinglePushExecutor.java
index 9068301..a8256cd 100644
--- 
a/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/SyncopeSinglePushExecutor.java
+++ 
b/core/provisioning-api/src/main/java/org/apache/syncope/core/provisioning/api/pushpull/SyncopeSinglePushExecutor.java
@@ -19,6 +19,7 @@
 package org.apache.syncope.core.provisioning.api.pushpull;
 
 import java.util.List;
+import org.apache.syncope.common.lib.to.PushTaskTO;
 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.Connector;
@@ -30,5 +31,5 @@ public interface SyncopeSinglePushExecutor {
             Provision provision,
             Connector connector,
             Any<?> any,
-            List<String> actions) throws JobExecutionException;
+            PushTaskTO pushTaskTO) throws JobExecutionException;
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/44a5e1da/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractSyncopeResultHandler.java
----------------------------------------------------------------------
diff --git 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractSyncopeResultHandler.java
 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractSyncopeResultHandler.java
index 76bfe3e..53c4258 100644
--- 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractSyncopeResultHandler.java
+++ 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractSyncopeResultHandler.java
@@ -69,6 +69,7 @@ public abstract class AbstractSyncopeResultHandler<T extends 
ProvisioningTask, A
     @Autowired
     protected PropagationTaskExecutor taskExecutor;
 
+    @Autowired
     protected AnyObjectWorkflowAdapter awfAdapter;
 
     /**

http://git-wip-us.apache.org/repos/asf/syncope/blob/44a5e1da/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/SinglePullJobDelegate.java
----------------------------------------------------------------------
diff --git 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/SinglePullJobDelegate.java
 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/SinglePullJobDelegate.java
index f4f57b4..bb410f9 100644
--- 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/SinglePullJobDelegate.java
+++ 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/SinglePullJobDelegate.java
@@ -24,6 +24,8 @@ import java.util.List;
 import java.util.Set;
 import java.util.stream.Collectors;
 import org.apache.syncope.common.lib.collections.IteratorChain;
+import org.apache.syncope.common.lib.to.PullTaskTO;
+import org.apache.syncope.common.lib.types.ClientExceptionType;
 import org.apache.syncope.common.lib.types.ConflictResolutionAction;
 import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.common.lib.types.MatchingRule;
@@ -31,9 +33,11 @@ import org.apache.syncope.common.lib.types.PullMode;
 import org.apache.syncope.common.lib.types.UnmatchingRule;
 import org.apache.syncope.core.persistence.api.dao.ImplementationDAO;
 import org.apache.syncope.core.persistence.api.entity.Implementation;
+import org.apache.syncope.core.persistence.api.entity.AnyType;
 import org.apache.syncope.core.persistence.api.entity.Realm;
 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.task.AnyTemplatePullTask;
 import org.apache.syncope.core.persistence.api.entity.task.PullTask;
 import org.apache.syncope.core.provisioning.api.Connector;
 import 
org.apache.syncope.core.provisioning.api.pushpull.GroupPullResultHandler;
@@ -45,6 +49,7 @@ import 
org.apache.syncope.core.provisioning.api.pushpull.SyncopePullResultHandle
 import 
org.apache.syncope.core.provisioning.api.pushpull.SyncopeSinglePullExecutor;
 import org.apache.syncope.core.provisioning.java.utils.MappingUtils;
 import org.apache.syncope.core.spring.ImplementationManager;
+import org.apache.syncope.core.provisioning.java.utils.TemplateUtils;
 import org.identityconnectors.framework.common.objects.AttributeBuilder;
 import org.identityconnectors.framework.common.objects.OperationOptions;
 import org.identityconnectors.framework.common.objects.filter.Filter;
@@ -59,6 +64,9 @@ public class SinglePullJobDelegate extends PullJobDelegate 
implements SyncopeSin
     @Autowired
     private ImplementationDAO implementationDAO;
 
+    @Autowired
+    private TemplateUtils templateUtils;
+
     @Override
     public List<ProvisioningReport> pull(
             final Provision provision,
@@ -66,13 +74,12 @@ public class SinglePullJobDelegate extends PullJobDelegate 
implements SyncopeSin
             final String connObjectKey,
             final String connObjectValue,
             final Realm realm,
-            final boolean remediation,
-            final List<String> actionKeys) throws JobExecutionException {
+            final PullTaskTO pullTaskTO) throws JobExecutionException {
 
         LOG.debug("Executing pull on {}", provision.getResource());
 
         List<PullActions> actions = new ArrayList<>();
-        actionKeys.forEach(key -> {
+        pullTaskTO.getActions().forEach(key -> {
             Implementation impl = implementationDAO.find(key);
             if (impl == null || impl.getType() != 
ImplementationType.PULL_ACTIONS) {
                 LOG.debug("Invalid " + Implementation.class.getSimpleName() + 
" {}, ignoring...", key);
@@ -95,13 +102,34 @@ public class SinglePullJobDelegate extends PullJobDelegate 
implements SyncopeSin
 
             PullTask pullTask = entityFactory.newEntity(PullTask.class);
             pullTask.setResource(provision.getResource());
-            pullTask.setMatchingRule(MatchingRule.UPDATE);
-            pullTask.setUnmatchingRule(UnmatchingRule.PROVISION);
+            pullTask.setMatchingRule(pullTaskTO.getMatchingRule() == null
+                    ? MatchingRule.UPDATE : pullTaskTO.getMatchingRule());
+            pullTask.setUnmatchingRule(pullTaskTO.getUnmatchingRule() == null
+                    ? UnmatchingRule.PROVISION : 
pullTaskTO.getUnmatchingRule());
             pullTask.setPullMode(PullMode.FILTERED_RECONCILIATION);
-            pullTask.setPerformCreate(true);
-            pullTask.setPerformUpdate(true);
-            pullTask.setRemediation(remediation);
+            pullTask.setPerformCreate(pullTaskTO.isPerformCreate());
+            pullTask.setPerformUpdate(pullTaskTO.isPerformUpdate());
+            pullTask.setPerformDelete(pullTaskTO.isPerformDelete());
             pullTask.setDestinationRealm(realm);
+            pullTask.setRemediation(pullTaskTO.isRemediation());
+            // validate JEXL expressions from templates and proceed if fine
+            templateUtils.check(pullTaskTO.getTemplates(), 
ClientExceptionType.InvalidPullTask);
+            pullTaskTO.getTemplates().forEach((type, template) -> {
+                AnyType anyType = anyTypeDAO.find(type);
+                if (anyType == null) {
+                    LOG.debug("Invalid AnyType {} specified, ignoring...", 
type);
+                } else {
+                    AnyTemplatePullTask anyTemplate = 
pullTask.getTemplate(anyType).orElse(null);
+                    if (anyTemplate == null) {
+                        anyTemplate = 
entityFactory.newEntity(AnyTemplatePullTask.class);
+                        anyTemplate.setAnyType(anyType);
+                        anyTemplate.setPullTask(pullTask);
+
+                        pullTask.add(anyTemplate);
+                    }
+                    anyTemplate.set(template);
+                }
+            });
 
             profile = new ProvisioningProfile<>(connector, pullTask);
             profile.setDryRun(false);

http://git-wip-us.apache.org/repos/asf/syncope/blob/44a5e1da/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/SinglePushJobDelegate.java
----------------------------------------------------------------------
diff --git 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/SinglePushJobDelegate.java
 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/SinglePushJobDelegate.java
index 76bdc16..90b8f08 100644
--- 
a/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/SinglePushJobDelegate.java
+++ 
b/core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/SinglePushJobDelegate.java
@@ -21,6 +21,7 @@ package org.apache.syncope.core.provisioning.java.pushpull;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import org.apache.syncope.common.lib.to.PushTaskTO;
 import org.apache.syncope.common.lib.types.ImplementationType;
 import org.apache.syncope.common.lib.types.MatchingRule;
 import org.apache.syncope.common.lib.types.UnmatchingRule;
@@ -51,12 +52,12 @@ public class SinglePushJobDelegate extends PushJobDelegate 
implements SyncopeSin
             final Provision provision,
             final Connector connector,
             final Any<?> any,
-            final List<String> actionKeys) throws JobExecutionException {
+            final PushTaskTO pushTaskTO) throws JobExecutionException {
 
         LOG.debug("Executing push on {}", provision.getResource());
 
         List<PushActions> actions = new ArrayList<>();
-        actionKeys.forEach(key -> {
+        pushTaskTO.getActions().forEach(key -> {
             Implementation impl = implementationDAO.find(key);
             if (impl == null || impl.getType() != 
ImplementationType.PUSH_ACTIONS) {
                 LOG.debug("Invalid " + Implementation.class.getSimpleName() + 
" {}, ignoring...", key);
@@ -72,10 +73,13 @@ public class SinglePushJobDelegate extends PushJobDelegate 
implements SyncopeSin
         try {
             PushTask pushTask = entityFactory.newEntity(PushTask.class);
             pushTask.setResource(provision.getResource());
-            pushTask.setMatchingRule(MatchingRule.UPDATE);
-            pushTask.setUnmatchingRule(UnmatchingRule.PROVISION);
-            pushTask.setPerformCreate(true);
-            pushTask.setPerformUpdate(true);
+            pushTask.setMatchingRule(pushTaskTO.getMatchingRule() == null
+                    ? MatchingRule.LINK : pushTaskTO.getMatchingRule());
+            pushTask.setUnmatchingRule(pushTaskTO.getUnmatchingRule() == null
+                    ? UnmatchingRule.ASSIGN : pushTaskTO.getUnmatchingRule());
+            pushTask.setPerformCreate(pushTaskTO.isPerformCreate());
+            pushTask.setPerformUpdate(pushTaskTO.isPerformUpdate());
+            pushTask.setPerformDelete(pushTaskTO.isPerformDelete());
 
             profile = new ProvisioningProfile<>(connector, pushTask);
             profile.getActions().addAll(actions);

http://git-wip-us.apache.org/repos/asf/syncope/blob/44a5e1da/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ReconciliationServiceImpl.java
----------------------------------------------------------------------
diff --git 
a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ReconciliationServiceImpl.java
 
b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ReconciliationServiceImpl.java
index 80d89d5..ad460cb 100644
--- 
a/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ReconciliationServiceImpl.java
+++ 
b/core/rest-cxf/src/main/java/org/apache/syncope/core/rest/cxf/service/ReconciliationServiceImpl.java
@@ -18,7 +18,8 @@
  */
 package org.apache.syncope.core.rest.cxf.service;
 
-import org.apache.syncope.common.lib.to.ReconciliationRequest;
+import org.apache.syncope.common.lib.to.PullTaskTO;
+import org.apache.syncope.common.lib.to.PushTaskTO;
 import org.apache.syncope.common.lib.to.ReconciliationStatus;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
 import org.apache.syncope.common.rest.api.service.ReconciliationService;
@@ -45,9 +46,30 @@ public class ReconciliationServiceImpl extends 
AbstractServiceImpl implements Re
     }
 
     @Override
-    public void reconcile(final ReconciliationRequest request) {
-        request.setAnyKey(
-                
getActualKey(anyUtilsFactory.getInstance(request.getAnyTypeKind()).dao(), 
request.getAnyKey()));
-        logic.reconcile(request);
+    public void push(
+            final AnyTypeKind anyTypeKind,
+            final String anyKey,
+            final String resourceKey,
+            final PushTaskTO pushTask) {
+
+        logic.push(
+                anyTypeKind,
+                getActualKey(anyUtilsFactory.getInstance(anyTypeKind).dao(), 
anyKey),
+                resourceKey,
+                pushTask);
+    }
+
+    @Override
+    public void pull(
+            final AnyTypeKind anyTypeKind,
+            final String anyKey,
+            final String resourceKey,
+            final PullTaskTO pullTask) {
+
+        logic.pull(
+                anyTypeKind,
+                getActualKey(anyUtilsFactory.getInstance(anyTypeKind).dao(), 
anyKey),
+                resourceKey,
+                pullTask);
     }
 }

http://git-wip-us.apache.org/repos/asf/syncope/blob/44a5e1da/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ReconciliationITCase.java
----------------------------------------------------------------------
diff --git 
a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ReconciliationITCase.java
 
b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ReconciliationITCase.java
index 172e69c..703799f 100644
--- 
a/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ReconciliationITCase.java
+++ 
b/fit/core-reference/src/test/java/org/apache/syncope/fit/core/ReconciliationITCase.java
@@ -28,10 +28,11 @@ import java.util.Date;
 import javax.sql.DataSource;
 import org.apache.syncope.common.lib.to.AnyObjectTO;
 import org.apache.syncope.common.lib.to.AttrTO;
-import org.apache.syncope.common.lib.to.ReconciliationRequest;
+import org.apache.syncope.common.lib.to.PullTaskTO;
+import org.apache.syncope.common.lib.to.PushTaskTO;
 import org.apache.syncope.common.lib.to.ReconciliationStatus;
 import org.apache.syncope.common.lib.types.AnyTypeKind;
-import org.apache.syncope.common.lib.types.ReconciliationAction;
+import org.apache.syncope.common.lib.types.UnmatchingRule;
 import org.apache.syncope.fit.AbstractITCase;
 import org.identityconnectors.framework.common.objects.OperationalAttributes;
 import org.junit.jupiter.api.Test;
@@ -66,12 +67,10 @@ public class ReconciliationITCase extends AbstractITCase {
         assertNull(status.getOnResource());
 
         // 4. push
-        ReconciliationRequest request = new ReconciliationRequest();
-        request.setAction(ReconciliationAction.PUSH);
-        request.setAnyKey(printer.getKey());
-        request.setAnyTypeKind(AnyTypeKind.ANY_OBJECT);
-        request.setResourceKey("resource-db-scripted");
-        reconciliationService.reconcile(request);
+        PushTaskTO pushTask = new PushTaskTO();
+        pushTask.setPerformCreate(true);
+        pushTask.setUnmatchingRule(UnmatchingRule.PROVISION);
+        reconciliationService.push(AnyTypeKind.ANY_OBJECT, printer.getKey(), 
"resource-db-scripted", pushTask);
 
         // 5. verify that printer is now propagated
         assertEquals(1, jdbcTemplate.queryForList(
@@ -119,12 +118,9 @@ public class ReconciliationITCase extends AbstractITCase {
         assertNotEquals(status.getOnSyncope().getAttr("LOCATION"), 
status.getOnResource().getAttr("LOCATION"));
 
         // 4. pull
-        ReconciliationRequest request = new ReconciliationRequest();
-        request.setAction(ReconciliationAction.PULL);
-        request.setAnyKey(printer.getKey());
-        request.setAnyTypeKind(AnyTypeKind.ANY_OBJECT);
-        request.setResourceKey("resource-db-scripted");
-        reconciliationService.reconcile(request);
+        PullTaskTO pullTask = new PullTaskTO();
+        pullTask.setPerformUpdate(true);
+        reconciliationService.pull(AnyTypeKind.ANY_OBJECT, printer.getName(), 
"resource-db-scripted", pullTask);
 
         // 5. verify reconciliation result (and resource is still not assigned)
         printer = anyObjectService.read(printer.getKey());

Reply via email to