package com.evolveum.midpoint.model.impl.sync;
import java.util.Collections;
import java.util.List;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.evolveum.midpoint.model.api.ModelService;
import com.evolveum.midpoint.model.impl.ModelConstants;
import com.evolveum.midpoint.model.impl.util.AbstractSearchIterativeResultHandler;
import com.evolveum.midpoint.model.impl.util.AbstractSearchIterativeTaskHandler;
import com.evolveum.midpoint.prism.PrismContext;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.PrismProperty;
import com.evolveum.midpoint.prism.delta.ObjectDelta;
import com.evolveum.midpoint.prism.query.ObjectQuery;
import com.evolveum.midpoint.schema.DeltaConvertor;
import com.evolveum.midpoint.schema.constants.SchemaConstants;
import com.evolveum.midpoint.schema.result.OperationConstants;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.task.api.TaskCategory;
import com.evolveum.midpoint.task.api.TaskManager;
import com.evolveum.midpoint.task.api.TaskRunResult;
import com.evolveum.midpoint.util.exception.CommonException;
import com.evolveum.midpoint.util.exception.CommunicationException;
import com.evolveum.midpoint.util.exception.ConfigurationException;
import com.evolveum.midpoint.util.exception.ExpressionEvaluationException;
import com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException;
import com.evolveum.midpoint.util.exception.ObjectNotFoundException;
import com.evolveum.midpoint.util.exception.PolicyViolationException;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.util.exception.SecurityViolationException;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import com.evolveum.midpoint.xml.ns._public.common.common_3.FocusType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.UserType;
import com.evolveum.prism.xml.ns._public.types_3.ObjectDeltaType;
@Component
public class ExecuteChangesTaskHandler extends AbstractSearchIterativeTaskHandler<FocusType, AbstractSearchIterativeResultHandler<FocusType>> {
public static final String HANDLER_URI = ModelConstants.NS_SYNCHRONIZATION_TASK_PREFIX + "/execute/handler-3";
@Autowired
private TaskManager taskManager;
@Autowired
private PrismContext prismContext;
@Autowired
private ModelService model;
private static final transient Trace LOGGER = TraceManager.getTrace(ExecuteChangesTaskHandler.class);
public ExecuteChangesTaskHandler() {
super("Execute", OperationConstants.EXECUTE);
setLogFinishInfo(true);
}
@PostConstruct
private void initialize() {
taskManager.registerHandler(HANDLER_URI, this);
}
@Override
protected ObjectQuery createQuery(AbstractSearchIterativeResultHandler<FocusType> handler, TaskRunResult runResult, Task task, OperationResult opResult) throws SchemaException {
return createQueryFromTask(handler, runResult, task, opResult);
}
protected Class<? extends ObjectType> getType(Task task) {
return getTypeFromTask(task, UserType.class);
}
@Override
protected AbstractSearchIterativeResultHandler<FocusType> createHandler(TaskRunResult runResult, final Task coordinatorTask,
OperationResult opResult) {
AbstractSearchIterativeResultHandler<FocusType> handler = new AbstractSearchIterativeResultHandler<FocusType>(
coordinatorTask, ExecuteChangesTaskHandler.class.getName(), "execute", "execute task", taskManager) {
@Override
protected boolean handleObject(PrismObject<FocusType> object, Task workerTask, OperationResult result) throws CommonException {
executeChange(object, coordinatorTask, workerTask, result);
return true;
}
};
handler.setStopOnError(false);
return handler;
}
private <T extends ObjectType> void executeChange(PrismObject<T> focalObject, Task coordinatorTask, Task task, OperationResult result) throws SchemaException,
ObjectNotFoundException, ExpressionEvaluationException, CommunicationException, ObjectAlreadyExistsException,
ConfigurationException, PolicyViolationException, SecurityViolationException {
LOGGER.trace("Recomputing object {}", focalObject);
ObjectDelta<T> delta = createDeltaFromTask(coordinatorTask);
if (delta == null) {
throw new IllegalStateException("No delta in the task");
}
delta.setOid(focalObject.getOid());
if (focalObject.getCompileTimeClass() != null) {
delta.setObjectTypeClass(focalObject.getCompileTimeClass());
}
prismContext.adopt(delta);
model.executeChanges(Collections.singletonList(delta), getExecuteOptionsFromTask(task), task, result);
LOGGER.trace("Execute changes {} for object {}: {}", delta, focalObject, result.getStatus());
}
private <T extends ObjectType> ObjectDelta<T> createDeltaFromTask(Task task) throws SchemaException {
PrismProperty<ObjectDeltaType> objectDeltaType = task.getExtensionProperty(SchemaConstants.MODEL_EXTENSION_OBJECT_DELTA);
if (objectDeltaType != null && objectDeltaType.getRealValue() != null) {
return DeltaConvertor.createObjectDelta(objectDeltaType.getRealValue(), prismContext);
} else {
return null;
}
}
@Override
public String getCategoryName(Task task) {
return TaskCategory.EXECUTE_CHANGES;
}
@Override
public List<String> getCategoryNames() {
return null;
}
}