final AbstractSubject toBeHandled = getSubject(subject.getId());
final AttributableUtil attrUtil = AttributableUtil.getInstance(toBeHandled);
final SyncResult result = new SyncResult();
profile.getResults().add(result);
result.setId(toBeHandled.getId());
result.setSubjectType(attrUtil.getType());
result.setName(getName(toBeHandled));
final Boolean enabled = toBeHandled instanceof SyncopeUser && profile.getSyncTask().isSyncStatus()
? ((SyncopeUser) toBeHandled).isSuspended() ? Boolean.FALSE : Boolean.TRUE
: null;
LOG.debug("Propagating {} with ID {} towards {}",
attrUtil.getType(), toBeHandled.getId(), profile.getSyncTask().getResource());
Object output = null;
Result resultStatus = null;
ConnectorObject beforeObj = null;
String operation = null;
// Try to read remote object (user / group) BEFORE any actual operation
final String accountId = MappingUtil.getAccountIdValue(
subject, profile.getSyncTask().getResource(), getMapping().getAccountIdItem());
beforeObj = getRemoteObject(accountId);
Boolean status = profile.getSyncTask().isSyncStatus() ? enabled : null;
if (profile.isDryRun()) {
if (beforeObj == null) {
result.setOperation(getResourceOperation(profile.getSyncTask().getUnmatchingRule()));
} else {
result.setOperation(getResourceOperation(profile.getSyncTask().getMatchingRule()));
}
result.setStatus(SyncResult.Status.SUCCESS);
} else {
try {
if (beforeObj == null) {
operation = profile.getSyncTask().getUnmatchingRule().name().toLowerCase();
result.setOperation(getResourceOperation(profile.getSyncTask().getUnmatchingRule()));
switch (profile.getSyncTask().getUnmatchingRule()) {
case ASSIGN:
for (PushActions action : profile.getActions()) {
action.beforeAssign(this.getProfile(), toBeHandled);
}
if (!profile.getSyncTask().isPerformCreate()) {
LOG.debug("PushTask not configured for create");
} else {
assign(toBeHandled, status);
}
break;
case PROVISION:
for (PushActions action : profile.getActions()) {
action.beforeProvision(this.getProfile(), toBeHandled);
}
if (!profile.getSyncTask().isPerformCreate()) {
LOG.debug("PushTask not configured for create");
} else {
provision(toBeHandled, status);
}
break;
case UNLINK:
for (PushActions action : profile.getActions()) {
action.beforeUnlink(this.getProfile(), toBeHandled);
}
if (!profile.getSyncTask().isPerformUpdate()) {
LOG.debug("PushTask not configured for update");
} else {
link(toBeHandled, true);
}
break;
default:
// do nothing
}
} else {
operation = profile.getSyncTask().getMatchingRule().name().toLowerCase();
result.setOperation(getResourceOperation(profile.getSyncTask().getMatchingRule()));
switch (profile.getSyncTask().getMatchingRule()) {
case UPDATE:
for (PushActions action : profile.getActions()) {
action.beforeUpdate(this.getProfile(), toBeHandled);
}
if (!profile.getSyncTask().isPerformUpdate()) {
LOG.debug("PushTask not configured for update");
} else {
update(toBeHandled, status);
}
break;
case DEPROVISION:
for (PushActions action : profile.getActions()) {
action.beforeDeprovision(this.getProfile(), toBeHandled);
}
if (!profile.getSyncTask().isPerformDelete()) {
LOG.debug("PushTask not configured for delete");
} else {
deprovision(toBeHandled);
}
break;
case UNASSIGN:
for (PushActions action : profile.getActions()) {
action.beforeUnassign(this.getProfile(), toBeHandled);
}
if (!profile.getSyncTask().isPerformDelete()) {
LOG.debug("PushTask not configured for delete");
} else {
unassign(toBeHandled);
}
break;
case LINK:
for (PushActions action : profile.getActions()) {
action.beforeLink(this.getProfile(), toBeHandled);
}
if (!profile.getSyncTask().isPerformUpdate()) {
LOG.debug("PushTask not configured for update");
} else {
link(toBeHandled, false);
}
break;
case UNLINK:
for (PushActions action : profile.getActions()) {
action.beforeUnlink(this.getProfile(), toBeHandled);
}
if (!profile.getSyncTask().isPerformUpdate()) {
LOG.debug("PushTask not configured for update");
} else {
link(toBeHandled, true);
}
break;
default:
// do nothing
}
}
for (PushActions action : profile.getActions()) {
action.after(this.getProfile(), toBeHandled, result);
}
result.setStatus(SyncResult.Status.SUCCESS);
resultStatus = AuditElements.Result.SUCCESS;
output = getRemoteObject(accountId);
} catch (Exception e) {
result.setStatus(SyncResult.Status.FAILURE);
result.setMessage(ExceptionUtils.getRootCauseMessage(e));
resultStatus = AuditElements.Result.FAILURE;
output = e;
LOG.warn("Error pushing {} towards {}", toBeHandled, profile.getSyncTask().getResource(), e);
throw new JobExecutionException(e);