protected void doHandle()

in core/provisioning-java/src/main/java/org/apache/syncope/core/provisioning/java/pushpull/AbstractPushResultHandler.java [293:551]


    protected void doHandle(final Any any, final Provision provision) throws JobExecutionException {
        ProvisioningReport result = new ProvisioningReport();
        profile.getResults().add(result);

        result.setKey(any.getKey());
        result.setAnyType(any.getType().getKey());
        result.setName(getName(any));

        LOG.debug("Pushing {} with key {} towards {}",
                any.getType().getKind(), any.getKey(), profile.getTask().getResource());

        // Try to read remote object BEFORE any actual operation
        Set<String> moreAttrsToGet = new HashSet<>();
        profile.getActions().forEach(action -> moreAttrsToGet.addAll(action.moreAttrsToGet(profile, any)));
        List<ConnectorObject> connObjs = outboundMatcher.match(
                profile.getConnector(),
                any,
                profile.getTask().getResource(),
                provision,
                Optional.of(moreAttrsToGet.toArray(String[]::new)));
        LOG.debug("Match(es) found for {} as {}: {}", any, provision.getObjectClass(), connObjs);

        if (connObjs.size() > 1) {
            switch (profile.getConflictResolutionAction()) {
                case IGNORE:
                    throw new IgnoreProvisionException("More than one match found for "
                            + any.getKey() + ": " + connObjs);

                case FIRSTMATCH:
                    connObjs = connObjs.subList(0, 1);
                    break;

                case LASTMATCH:
                    connObjs = connObjs.subList(connObjs.size() - 1, connObjs.size());
                    break;

                default:
            }
        }
        ConnectorObject beforeObj = connObjs.isEmpty() ? null : connObjs.getFirst();

        if (profile.isDryRun()) {
            if (beforeObj == null) {
                result.setOperation(toResourceOperation(profile.getTask().getUnmatchingRule()));
            } else {
                result.setOperation(toResourceOperation(profile.getTask().getMatchingRule()));
            }
            result.setStatus(ProvisioningReport.Status.SUCCESS);
        } else {
            String operation = beforeObj == null
                    ? UnmatchingRule.toOp(profile.getTask().getUnmatchingRule())
                    : MatchingRule.toOp(profile.getTask().getMatchingRule());

            boolean notificationsAvailable = notificationManager.notificationsAvailable(
                    AuthContextUtils.getDomain(),
                    OpEvent.CategoryType.PUSH,
                    any.getType().getKind().name(),
                    profile.getTask().getResource().getKey(),
                    operation);
            boolean auditRequested = auditManager.auditRequested(
                    AuthContextUtils.getDomain(),
                    AuthContextUtils.getUsername(),
                    OpEvent.CategoryType.PUSH,
                    any.getType().getKind().name(),
                    profile.getTask().getResource().getKey(),
                    operation);

            Object output = null;
            OpEvent.Outcome resultStatus = null;

            Boolean enable = any instanceof User user && profile.getTask().isSyncStatus()
                    ? BooleanUtils.negate(user.isSuspended())
                    : null;
            try {
                if (beforeObj == null) {
                    result.setOperation(toResourceOperation(profile.getTask().getUnmatchingRule()));

                    switch (profile.getTask().getUnmatchingRule()) {
                        case ASSIGN -> {
                            for (PushActions action : profile.getActions()) {
                                action.beforeAssign(profile, any);
                            }

                            if (!profile.getTask().isPerformCreate()) {
                                LOG.debug("PushTask not configured for create");
                                result.setStatus(ProvisioningReport.Status.IGNORE);
                            } else {
                                assign(any, enable, result);
                            }
                        }

                        case PROVISION -> {
                            for (PushActions action : profile.getActions()) {
                                action.beforeProvision(profile, any);
                            }

                            if (!profile.getTask().isPerformCreate()) {
                                LOG.debug("PushTask not configured for create");
                                result.setStatus(ProvisioningReport.Status.IGNORE);
                            } else {
                                provision(any, enable, result);
                            }
                        }

                        case UNLINK -> {
                            for (PushActions action : profile.getActions()) {
                                action.beforeUnlink(profile, any);
                            }

                            if (!profile.getTask().isPerformUpdate()) {
                                LOG.debug("PushTask not configured for update");
                                result.setStatus(ProvisioningReport.Status.IGNORE);
                            } else {
                                link(any, true, result);
                            }
                        }

                        case IGNORE -> {
                            LOG.debug("Ignored any: {}", any);
                            result.setStatus(ProvisioningReport.Status.IGNORE);
                        }

                        default -> {
                        }
                    }
                    // do nothing
                } else {
                    result.setOperation(toResourceOperation(profile.getTask().getMatchingRule()));

                    switch (profile.getTask().getMatchingRule()) {
                        case UPDATE -> {
                            for (PushActions action : profile.getActions()) {
                                action.beforeUpdate(profile, any);
                            }
                            if (!profile.getTask().isPerformUpdate()) {
                                LOG.debug("PushTask not configured for update");
                                result.setStatus(ProvisioningReport.Status.IGNORE);
                            } else {
                                update(any, enable, beforeObj, result);
                            }
                        }

                        case DEPROVISION -> {
                            for (PushActions action : profile.getActions()) {
                                action.beforeDeprovision(profile, any);
                            }

                            if (!profile.getTask().isPerformDelete()) {
                                LOG.debug("PushTask not configured for delete");
                                result.setStatus(ProvisioningReport.Status.IGNORE);
                            } else {
                                deprovision(any, beforeObj, result);
                            }
                        }

                        case UNASSIGN -> {
                            for (PushActions action : profile.getActions()) {
                                action.beforeUnassign(profile, any);
                            }

                            if (!profile.getTask().isPerformDelete()) {
                                LOG.debug("PushTask not configured for delete");
                                result.setStatus(ProvisioningReport.Status.IGNORE);
                            } else {
                                unassign(any, beforeObj, result);
                            }
                        }

                        case LINK -> {
                            for (PushActions action : profile.getActions()) {
                                action.beforeLink(profile, any);
                            }

                            if (!profile.getTask().isPerformUpdate()) {
                                LOG.debug("PushTask not configured for update");
                                result.setStatus(ProvisioningReport.Status.IGNORE);
                            } else {
                                link(any, false, result);
                            }
                        }

                        case UNLINK -> {
                            for (PushActions action : profile.getActions()) {
                                action.beforeUnlink(profile, any);
                            }

                            if (!profile.getTask().isPerformUpdate()) {
                                LOG.debug("PushTask not configured for update");
                                result.setStatus(ProvisioningReport.Status.IGNORE);
                            } else {
                                link(any, true, result);
                            }
                        }

                        case IGNORE -> {
                            LOG.debug("Ignored any: {}", any);
                            result.setStatus(ProvisioningReport.Status.IGNORE);
                        }

                        default -> {
                        }
                    }
                    // do nothing
                }

                for (PushActions action : profile.getActions()) {
                    action.after(profile, any, result);
                }

                if (result.getStatus() == null) {
                    result.setStatus(ProvisioningReport.Status.SUCCESS);
                }

                if (notificationsAvailable || auditRequested) {
                    resultStatus = OpEvent.Outcome.SUCCESS;
                    output = outboundMatcher.match(
                            profile.getConnector(),
                            any,
                            profile.getTask().getResource(),
                            provision,
                            Optional.of(moreAttrsToGet.toArray(String[]::new)));
                }
            } catch (IgnoreProvisionException e) {
                throw e;
            } catch (Exception e) {
                result.setStatus(ProvisioningReport.Status.FAILURE);
                result.setMessage(ExceptionUtils.getRootCauseMessage(e));

                if (notificationsAvailable || auditRequested) {
                    resultStatus = OpEvent.Outcome.FAILURE;
                    output = e;
                }

                LOG.warn("Error pushing {} towards {}", any, profile.getTask().getResource(), e);

                for (PushActions action : profile.getActions()) {
                    action.onError(profile, any, result, e);
                }

                throw new JobExecutionException(e);
            } finally {
                if (notificationsAvailable || auditRequested) {
                    Map<String, Object> jobMap = new HashMap<>();
                    jobMap.put(AfterHandlingEvent.JOBMAP_KEY, new AfterHandlingEvent(
                            AuthContextUtils.getDomain(),
                            AuthContextUtils.getWho(),
                            OpEvent.CategoryType.PUSH,
                            any.getType().getKind().name(),
                            profile.getTask().getResource().getKey(),
                            operation,
                            resultStatus,
                            beforeObj,
                            output,
                            any));
                    AfterHandlingJob.schedule(scheduler, jobMap);
                }
            }
        }
    }