/*
* Copyright (c) 2010-2013 Evolveum
*
* 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.
*/
package com.evolveum.midpoint.wf.impl.processors.primary;
/**
* @author mederly
*/
import com.evolveum.midpoint.model.api.context.ModelContext;
import com.evolveum.midpoint.model.impl.lens.LensContext;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.task.api.*;
import com.evolveum.midpoint.util.JAXBUtil;
import com.evolveum.midpoint.util.exception.*;
import com.evolveum.midpoint.util.logging.LoggingUtils;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import com.evolveum.midpoint.wf.impl.tasks.WfTask;
import com.evolveum.midpoint.wf.impl.tasks.WfTaskController;
import com.evolveum.midpoint.wf.impl.tasks.WfTaskUtil;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.xml.namespace.QName;
import java.util.List;
/**
* This handler propagates object OID of newly added object to dependent tasks.
* (Quite a hack for now.)
*
* @author mederly
*/
@Component
public class WfPropagateTaskObjectReferenceTaskHandler implements TaskHandler {
// should be available only within the context of primary change processor
static final String HANDLER_URI = "http://midpoint.evolveum.com/xml/ns/public/workflow/propagate-task-object-reference/handler-3";
private static final Trace LOGGER = TraceManager.getTrace(WfPropagateTaskObjectReferenceTaskHandler.class);
//region Spring beans and initialization
@Autowired
private TaskManager taskManager;
@Autowired
private WfTaskController wfTaskController;
@Autowired
private WfTaskUtil wfTaskUtil;
@PostConstruct
public void init() {
LOGGER.trace("Registering with taskManager as a handler for " + HANDLER_URI);
taskManager.registerHandler(HANDLER_URI, this);
}
//endregion
//region Body
@Override
public TaskRunResult run(Task task) {
TaskRunResult.TaskRunResultStatus status = TaskRunResult.TaskRunResultStatus.FINISHED;
OperationResult result = task.getResult().createSubresult(WfPropagateTaskObjectReferenceTaskHandler.class + ".run");
WfTask wfTask = wfTaskController.recreateWfTask(task);
LOGGER.trace("WfPropagateTaskObjectReferenceTaskHandler starting... job = {}", wfTask);
ModelContext modelContext;
try {
modelContext = wfTask.retrieveModelContext(result);
if (modelContext == null) {
throw new IllegalStateException("There's no model context in the task; job = " + wfTask);
}
} catch (SchemaException e) {
return reportException("Couldn't retrieve model context from job " + wfTask, task, result, e);
} catch (ObjectNotFoundException e) {
return reportException("Couldn't retrieve model context from job " + wfTask, task, result, e);
} catch (CommunicationException e) {
return reportException("Couldn't retrieve model context from job " + wfTask, task, result, TaskRunResult.TaskRunResultStatus.TEMPORARY_ERROR, e);
} catch (ConfigurationException e) {
return reportException("Couldn't retrieve model context from job " + wfTask, task, result, e);
}
String oid = ((LensContext) modelContext).getFocusContext().getOid();
if (oid == null) {
LOGGER.warn("No object OID in job " + wfTask);
} else {
Class typeClass = ((LensContext) modelContext).getFocusContext().getObjectTypeClass();
QName type = typeClass != null ? JAXBUtil.getTypeQName(typeClass) : null;
if (type == null) {
LOGGER.warn("Unknown type of object " + oid + " in task " + task);
} else {
ObjectReferenceType objectReferenceType = new ObjectReferenceType();
objectReferenceType.setType(type);
objectReferenceType.setOid(oid);
if (task.getObjectRef() == null) {
task.setObjectRef(objectReferenceType);
} else {
LOGGER.warn("object reference in task " + task + " is already set, although it shouldn't be");
}
List<WfTask> dependents;
try {
dependents = wfTask.listDependents(result);
dependents.add(wfTask.getParentJob(result));
} catch (SchemaException e) {
return reportException("Couldn't get dependents from job " + wfTask, task, result, e);
} catch (ObjectNotFoundException e) {
return reportException("Couldn't get dependents from job " + wfTask, task, result, e);
}
for (WfTask dependent : dependents) {
if (dependent.getTask().getObjectRef() == null) {
try {
dependent.getTask().setObjectRefImmediate(objectReferenceType, result);
} catch (ObjectNotFoundException e) {
// note we DO NOT return, because we want to set all references we can
reportException("Couldn't set object reference on job " + dependent, task, result, e);
} catch (SchemaException e) {
reportException("Couldn't set object reference on job " + dependent, task, result, e);
} catch (ObjectAlreadyExistsException e) {
reportException("Couldn't set object reference on job " + dependent, task, result, e);
}
} else {
LOGGER.warn("object reference in job " + dependent + " is already set, although it shouldn't be");
}
}
}
}
result.computeStatusIfUnknown();
TaskRunResult runResult = new TaskRunResult();
runResult.setRunResultStatus(status);
runResult.setOperationResult(task.getResult());
return runResult;
}
private TaskRunResult reportException(String message, Task task, OperationResult result, Throwable cause) {
return reportException(message, task, result, TaskRunResult.TaskRunResultStatus.PERMANENT_ERROR, cause);
}
private TaskRunResult reportException(String message, Task task, OperationResult result, TaskRunResult.TaskRunResultStatus status, Throwable cause) {
LoggingUtils.logUnexpectedException(LOGGER, message, cause);
result.recordFatalError(message, cause);
TaskRunResult runResult = new TaskRunResult();
runResult.setRunResultStatus(status);
runResult.setOperationResult(task.getResult());
return runResult;
}
//endregion
//region Other task handler stuff
@Override
public Long heartbeat(Task task) {
return null; // null - as *not* to record progress (which would overwrite operationResult!)
}
@Override
public void refreshStatus(Task task) {
}
@Override
public String getCategoryName(Task task) {
return TaskCategory.WORKFLOW;
}
@Override
public List<String> getCategoryNames() {
return null; //To change body of implemented methods use File | Settings | File Templates.
}
//endregion
}