/*
* Copyright (c) 2010-2015 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.objects;
import com.evolveum.midpoint.model.api.context.ModelContext;
import com.evolveum.midpoint.model.impl.lens.LensFocusContext;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.delta.ChangeType;
import com.evolveum.midpoint.prism.delta.ObjectDelta;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.schema.util.OidUtil;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import com.evolveum.midpoint.wf.impl.processes.itemApproval.ApprovalRequest;
import com.evolveum.midpoint.wf.impl.processes.itemApproval.ApprovalRequestImpl;
import com.evolveum.midpoint.schema.ObjectTreeDeltas;
import com.evolveum.midpoint.wf.impl.processors.primary.ModelInvocationContext;
import com.evolveum.midpoint.wf.impl.processors.primary.PcpChildWfTaskCreationInstruction;
import com.evolveum.midpoint.wf.impl.processors.primary.aspect.BasePrimaryChangeAspect;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;
import org.apache.commons.lang.Validate;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* Change aspect that manages addition of an object.
*
* @author mederly
*/
public abstract class AddObjectAspect<T extends ObjectType> extends BasePrimaryChangeAspect {
private static final Trace LOGGER = TraceManager.getTrace(AddObjectAspect.class);
//region ------------------------------------------------------------ Things that execute on request arrival
protected abstract Class<T> getObjectClass();
protected abstract String getObjectLabel(T object);
@NotNull
@Override
public List<PcpChildWfTaskCreationInstruction> prepareTasks(@NotNull ObjectTreeDeltas objectTreeDeltas,
ModelInvocationContext ctx, @NotNull OperationResult result) throws SchemaException {
PcpAspectConfigurationType config = primaryChangeAspectHelper.getPcpAspectConfigurationType(ctx.wfConfiguration, this);
if (config == null) {
return Collections.emptyList(); // this should not occur (because this aspect is not enabled by default), but check it just to be sure
}
if (!primaryChangeAspectHelper.isRelatedToType(ctx.modelContext, getObjectClass()) || objectTreeDeltas.getFocusChange() == null) {
return Collections.emptyList();
}
List<ApprovalRequest<T>> approvalRequestList = getApprovalRequests(ctx.modelContext, config,
objectTreeDeltas.getFocusChange(), ctx.taskFromModel, result);
if (approvalRequestList == null || approvalRequestList.isEmpty()) {
return Collections.emptyList();
}
return prepareJobCreateInstructions(ctx.modelContext, ctx.taskFromModel, result, approvalRequestList);
}
private List<ApprovalRequest<T>> getApprovalRequests(ModelContext<?> modelContext, PcpAspectConfigurationType config,
ObjectDelta<? extends ObjectType> change, Task taskFromModel, OperationResult result) {
if (change.getChangeType() != ChangeType.ADD) {
return null;
}
T objectType = (T) change.getObjectToAdd().asObjectable().clone();
if (objectType.getOid() == null) {
String newOid = OidUtil.generateOid();
objectType.setOid(newOid);
((LensFocusContext<?>) modelContext.getFocusContext()).setOid(newOid);
}
change.setObjectToAdd(null); // make the change empty
return Arrays.asList(createApprovalRequest(config, objectType, modelContext, taskFromModel, result));
}
// creates an approval request for a given role create request
private ApprovalRequest<T> createApprovalRequest(PcpAspectConfigurationType config, T objectType,
ModelContext<?> modelContext, Task taskFromModel, OperationResult result) {
ApprovalRequest<T> request = new ApprovalRequestImpl<>(objectType, config, prismContext);
approvalSchemaHelper.prepareSchema(request.getApprovalSchemaType(), createRelationResolver(objectType, result),
createReferenceResolver(modelContext, taskFromModel, result));
return request;
}
private List<PcpChildWfTaskCreationInstruction> prepareJobCreateInstructions(ModelContext<?> modelContext, Task taskFromModel, OperationResult result,
List<ApprovalRequest<T>> approvalRequestList) throws SchemaException {
List<PcpChildWfTaskCreationInstruction> instructions = new ArrayList<>();
for (ApprovalRequest<T> approvalRequest : approvalRequestList) { // there should be just one
LOGGER.trace("Approval request = {}", approvalRequest);
T objectToAdd = approvalRequest.getItemToApprove();
Validate.notNull(objectToAdd);
String objectLabel = getObjectLabel(objectToAdd);
PrismObject<UserType> requester = baseModelInvocationProcessingHelper.getRequester(taskFromModel, result);
String approvalTaskName = "Approve creating " + objectLabel;
// create a JobCreateInstruction for a given change processor (primaryChangeProcessor in this case)
PcpChildWfTaskCreationInstruction instruction =
PcpChildWfTaskCreationInstruction.createItemApprovalInstruction(
getChangeProcessor(), approvalTaskName,
approvalRequest.getApprovalSchemaType(), null);
// set some common task/process attributes
instruction.prepareCommonAttributes(this, modelContext, requester);
// prepare and set the delta that has to be approved
ObjectDelta<? extends ObjectType> delta = assignmentToDelta(modelContext);
instruction.setDeltasToProcess(delta);
instruction.setObjectRef(modelContext, result);
instruction.setTargetRef(null, result);
// set the names of midPoint task and activiti process instance
String andExecuting = instruction.isExecuteApprovedChangeImmediately() ? "and execution " : "";
instruction.setTaskName("Approval " + andExecuting + "of creation of " + objectLabel);
instruction.setProcessInstanceName("Creating " + objectLabel);
// setup general item approval process
itemApprovalProcessInterface.prepareStartInstruction(instruction);
instructions.add(instruction);
}
return instructions;
}
private ObjectDelta<? extends ObjectType> assignmentToDelta(ModelContext<? extends ObjectType> modelContext) {
return modelContext.getFocusContext().getPrimaryDelta();
}
//endregion
//region ------------------------------------------------------------ Things that execute when item is being approved
//endregion
}