com.evolveum.midpoint.wf.impl.processors.primary.user.AddAccountAssignmentAspect.java Source code

Java tutorial

Introduction

Here is the source code for com.evolveum.midpoint.wf.impl.processors.primary.user.AddAccountAssignmentAspect.java

Source

/*
 * 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.user;

import com.confluxsys.idmp.common.model.EntityInfo;
import com.confluxsys.idmp.connector.pset.lookup.AttributeLookupService;
import com.confluxsys.idmp.model.AttributeLookupValueInfo;
import com.confluxsys.idmp.model.PlatformObjectMetadataInfo;
import com.confluxsys.idmp.platformobject.*;

import com.confluxsys.idmp.platformobject.MetadataType;
import com.evolveum.midpoint.model.api.context.ModelContext;
import com.evolveum.midpoint.model.api.context.ModelElementContext;
import com.evolveum.midpoint.model.impl.lens.LensContext;
import com.evolveum.midpoint.prism.*;
import com.evolveum.midpoint.prism.delta.ChangeType;
import com.evolveum.midpoint.prism.delta.ContainerDelta;
import com.evolveum.midpoint.prism.delta.ItemDelta;
import com.evolveum.midpoint.prism.delta.ObjectDelta;
import com.evolveum.midpoint.prism.path.ItemPath;
import com.evolveum.midpoint.prism.xnode.PrimitiveXNode;
import com.evolveum.midpoint.prism.xnode.XNode;

import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.task.api.Task;

import com.evolveum.midpoint.util.exception.ObjectNotFoundException;
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.addrole.AddRoleVariableNames;
import com.evolveum.midpoint.wf.impl.processes.common.SpringApplicationContextHolder;
import com.evolveum.midpoint.wf.impl.processes.itemApproval.ApprovalRequest;
import com.evolveum.midpoint.wf.impl.processes.itemApproval.ApprovalRequestImpl;
import com.evolveum.midpoint.wf.impl.processes.itemApproval.ItemApprovalProcessInterface;
import com.evolveum.midpoint.wf.impl.processes.itemApproval.ProcessVariableNames;
import com.evolveum.midpoint.wf.impl.processors.primary.PcpChildJobCreationInstruction;
import com.evolveum.midpoint.wf.impl.processors.primary.PrimaryChangeProcessor;
import com.evolveum.midpoint.wf.impl.processors.primary.aspect.BasePrimaryChangeAspect;
import com.evolveum.midpoint.wf.impl.util.MiscDataUtil;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;
import com.evolveum.midpoint.xml.ns.model.workflow.common_forms_3.AccountApprovalFormType;
import com.evolveum.midpoint.xml.ns.model.workflow.common_forms_3.QuestionFormType;

import com.evolveum.prism.xml.ns._public.types_3.RawType;

import org.apache.commons.lang.Validate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import javax.xml.bind.JAXBElement;
import javax.xml.datatype.XMLGregorianCalendar;

import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * Created by Dharmendra on 1/20/2015.
 */
@Component
public class AddAccountAssignmentAspect extends BasePrimaryChangeAspect {

    ChangeTypeEnum changeType = ChangeTypeEnum.MODIFY;

    private enum ChangeTypeEnum {
        ADD("creation"), DELETE("deletion"), MODIFY("modification");
        private String change;

        private ChangeTypeEnum(String s) {
            this.change = s;
        }

        public String getChangeTypeString() {
            return change;
        }
    }

    private static final Trace LOGGER = TraceManager.getTrace(AddAccountAssignmentAspect.class);

    @Autowired
    private PrismContext prismContext;

    @Autowired
    private ItemApprovalProcessInterface itemApprovalProcessInterface;

    //region ------------------------------------------------------------ Things that execute on request arrival

    @Override
    public List<PcpChildJobCreationInstruction> prepareJobCreationInstructions(ModelContext<?> modelContext,
            ObjectDelta<? extends ObjectType> change, Task taskFromModel, OperationResult result)
            throws SchemaException {

        List<ApprovalRequest<AssignmentType>> approvalRequestList = getAssignmentToApproveList(change, modelContext,
                result, taskFromModel);
        if (approvalRequestList == null || approvalRequestList.isEmpty()) {
            return null;
        } else {
            return prepareJobCreateInstructions(modelContext, taskFromModel, result, approvalRequestList);
        }
    }

    private List<ApprovalRequest<AssignmentType>> getAssignmentToApproveList(
            ObjectDelta<? extends ObjectType> change, ModelContext<?> modelContext, OperationResult result,
            Task taskFromModel) {

        List<ApprovalRequest<AssignmentType>> approvalRequestList = new ArrayList<ApprovalRequest<AssignmentType>>();

        /*
         * We either add a user; then the list of roles to be added is given by the assignment property,
         * or we modify a user; then the list of roles is given by the assignment property modification.
         */

        if (change.getChangeType() == ChangeType.ADD) {

            PrismObject<?> prismToAdd = change.getObjectToAdd();
            UserType user = (UserType) prismToAdd.asObjectable();

            if (LOGGER.isTraceEnabled()) {
                LOGGER.trace("Role-related assignments in user add delta (" + user.getAssignment().size() + "): ");
            }

            // in the following we look for assignments of roles that should be approved

            Iterator<AssignmentType> assignmentTypeIterator = user.getAssignment().iterator();
            while (assignmentTypeIterator.hasNext()) {
                AssignmentType a = assignmentTypeIterator.next();

                ObjectType objectType = primaryChangeAspectHelper.resolveAccountObjectRef(a, result);
                if (objectType != null && objectType instanceof ResourceType) {
                    ResourceType resource = (ResourceType) objectType;
                    boolean approvalRequired = shouldResourceBeApproved(resource, ChangeType.ADD, modelContext,
                            taskFromModel, result);
                    if (approvalRequired) {
                        AttributeLookupValueInfo applicationInfo = this.getApplicationInfo(a);
                        AssignmentType aCopy = a.clone();
                        PrismContainerValue.copyDefinition(aCopy, a);
                        aCopy.setTarget(resource);
                        approvalRequestList.add(createApprovalRequest(aCopy, resource, applicationInfo));
                        changeType = ChangeTypeEnum.ADD;
                        assignmentTypeIterator.remove();
                    }
                }
            }

        } else if (change.getChangeType() == ChangeType.MODIFY) {

            Iterator<? extends ItemDelta> deltaIterator = change.getModifications().iterator();

            // are any 'sensitive' roles assigned?

            while (deltaIterator.hasNext()) {
                ItemDelta delta = deltaIterator.next();
                if (UserType.F_ASSIGNMENT.equals(delta.getElementName())
                        && ((delta.getValuesToAdd() != null && !delta.getValuesToAdd().isEmpty())
                                || (delta.getValuesToDelete() != null && !delta.getValuesToDelete().isEmpty()))) { // todo: what if assignments are modified?
                    if (delta.getValuesToAdd() != null && !delta.getValuesToAdd().isEmpty()) {
                        Iterator valueIterator = delta.getValuesToAdd().iterator();
                        while (valueIterator.hasNext()) {
                            Object o = valueIterator.next();
                            if (LOGGER.isTraceEnabled()) {
                                LOGGER.trace("Assignment to add = " + ((PrismContainerValue) o).debugDump());
                            }
                            PrismContainerValue<AssignmentType> at = (PrismContainerValue<AssignmentType>) o;
                            AssignmentType a = at.asContainerable();

                            ObjectType objectType = primaryChangeAspectHelper.resolveAccountObjectRef(a, result);
                            if (objectType != null && objectType instanceof ResourceType) {
                                ResourceType resource = (ResourceType) objectType;
                                boolean approvalRequired = shouldResourceBeApproved(resource, ChangeType.ADD,
                                        modelContext, taskFromModel, result);
                                if (approvalRequired) {
                                    AttributeLookupValueInfo applicationInfo = this.getApplicationInfo(a);
                                    AssignmentType aCopy = a.clone();
                                    PrismContainerValue.copyDefinition(aCopy, a);
                                    aCopy.setTarget(resource);
                                    approvalRequestList
                                            .add(createApprovalRequest(aCopy, resource, applicationInfo));
                                    changeType = ChangeTypeEnum.ADD;
                                    valueIterator.remove();
                                }
                            }
                        }
                        if (delta.getValuesToAdd().isEmpty()) { // empty set of values to add is an illegal state
                            delta.resetValuesToAdd();
                            if (delta.getValuesToReplace() == null && delta.getValuesToDelete() == null) {
                                deltaIterator.remove();
                            }
                        }
                    } else if (delta.getValuesToDelete() != null && !delta.getValuesToDelete().isEmpty()) {
                        Iterator valueIterator = delta.getValuesToDelete().iterator();
                        while (valueIterator.hasNext()) {
                            Object o = valueIterator.next();
                            if (LOGGER.isTraceEnabled()) {
                                LOGGER.trace("Assignment to delete = " + ((PrismContainerValue) o).debugDump());
                            }
                            PrismContainerValue<AssignmentType> at = (PrismContainerValue<AssignmentType>) o;
                            AssignmentType a = at.asContainerable();

                            ObjectType objectType = primaryChangeAspectHelper.resolveAccountObjectRef(a, result);
                            if (objectType != null && objectType instanceof ResourceType) {
                                ResourceType resource = (ResourceType) objectType;
                                boolean approvalRequired = shouldResourceBeApproved(resource, ChangeType.DELETE,
                                        modelContext, taskFromModel, result);
                                if (approvalRequired) {
                                    //                                    ApplicationInfo applicationInfo = this.getApplicationInfo(a);
                                    AssignmentType aCopy = a.clone();
                                    PrismContainerValue.copyDefinition(aCopy, a);
                                    aCopy.setTarget(resource);
                                    approvalRequestList
                                            .add(createAccountDeleteApprovalRequest(aCopy, resource, modelContext));
                                    changeType = ChangeTypeEnum.DELETE;
                                    valueIterator.remove();
                                }
                            }
                        }
                        if (delta.getValuesToDelete().isEmpty()) {
                            if (delta.getValuesToReplace() == null && delta.getValuesToAdd() == null) {
                                deltaIterator.remove();
                            }
                        }
                    }

                }
            }
        } else {
            return null;
        }
        return approvalRequestList;
    }

    public ApprovalRequest<AssignmentType> createAccountDeleteApprovalRequest(AssignmentType assignment,
            ResourceType resource, ModelContext<?> modelContext) {

        ModelElementContext<? extends ObjectType> fc = modelContext.getFocusContext();
        PrismObject<? extends ObjectType> prism = fc.getObjectNew() != null ? fc.getObjectNew() : fc.getObjectOld();
        if (prism == null) {
            throw new IllegalStateException("No object (new or old) in model context");
        }
        ObjectType object = prism.asObjectable();
        String beneficiaryOid = object.getOid();

        ObjectReferenceType approverRefObj = new ObjectReferenceType();
        approverRefObj.setDescription("Approval by role members");
        approverRefObj.setType(UserType.COMPLEX_TYPE);
        approverRefObj.setOid(beneficiaryOid);
        List<ObjectReferenceType> approverRefs = new ArrayList<ObjectReferenceType>();
        approverRefs.add(approverRefObj);

        return new ApprovalRequestImpl(assignment, null, approverRefs, null, null, prismContext);

    }

    private AttributeLookupValueInfo getApplicationInfo(AssignmentType a) {

        if (a == null) {
            throw new IllegalArgumentException("Invalid parameter: " + a);
        }
        ConstructionType construction = a.getConstruction();
        List<ResourceAttributeDefinitionType> attrs = construction.getAttribute();
        for (ResourceAttributeDefinitionType attr : attrs) {
            String attrName = attr.getRef().getLocalPart();
            if (attrName.equals("psetApplication")) {
                List<JAXBElement<?>> values = attr.getOutbound().getExpression().getExpressionEvaluator();

                JAXBElement<?> firstElement = values.iterator().next();
                RawType val = (RawType) firstElement.getValue();
                XNode xnode = val.getXnode();
                if (xnode instanceof PrimitiveXNode) {
                    PrimitiveXNode pxNode = (PrimitiveXNode) xnode;
                    if (pxNode.getValue() != null) {
                        Object applicationId = pxNode.getValue();
                        LOGGER.info("Application id found: " + applicationId);

                        ApplicationContext idmpApplicationContext = SpringApplicationContextHolder
                                .getApplicationContext();
                        AttributeLookupService metadataManager = (AttributeLookupService) idmpApplicationContext
                                .getBean("attributeLookupService");
                        AttributeLookupValueInfo appInfo = metadataManager.getLoookupValueInfo("UnixPermissionSet",
                                MetadataType.Application.getMetaString(),
                                new Integer(String.valueOf(applicationId)));

                        /*                      EntityInfo info = appInfo.getOwner().getOwnerInfo();
                                              LOGGER.info("App Owner: " + info.getIdentifier());*/
                        return appInfo;
                    }
                }
            }
        }

        return null;
    }

    private boolean shouldResourceBeApproved(ResourceType resource, ChangeType changeType,
            ModelContext<?> modelContext, Task taskFromModel, OperationResult result) {
        //TODO get permission set application oid from configuration hardcoded for now.
        if (resource.getOid().equals("PermissionSet-resource")
                || resource.getOid().equals("Windows-PermissionSet-resource")) {
            if (changeType.equals(ChangeType.ADD)) {
                return true;
            } else if (changeType.equals(ChangeType.DELETE)) {
                PrismObject<UserType> requester = primaryChangeAspectHelper.getRequester(taskFromModel, result);
                UserType requesterUser = requester.asObjectable();
                String beneficiary = MiscDataUtil.getFocusObjectName(modelContext);

                if (!beneficiary.equals(requesterUser.getName().getOrig())) {
                    return true;
                }
            }
        }
        return false;
    }

    // creates an approval request for a given resource  assignment
    private ApprovalRequest<AssignmentType> createApprovalRequest(AssignmentType a, ResourceType resource,
            AttributeLookupValueInfo appInfo) {

        ApprovalSchemaType appSchema = new ApprovalSchemaType();
        appSchema.setName("Approval Schema for Permission Set Create");
        appSchema.setDescription("Two level approval: First by application owner then Security Audit Role");
        //set first level : application owner
        ApprovalLevelType appOwnerLevel = new ApprovalLevelType();
        appSchema.getLevel().add(appOwnerLevel);
        appOwnerLevel.setName("Approval By Application Owner");
        appOwnerLevel
                .setDescription("At this level Application owner will approve the permission set change request");
        //set owner reference
        ObjectReferenceType appOwnerRef = new ObjectReferenceType();
        appOwnerLevel.getApproverRef().add(appOwnerRef);
        appOwnerRef.setDescription("Approval By Application Owner");
        EntityInfo ownerInfo = appInfo.getOwner().getOwnerInfo();
        if (ownerInfo.getEntityType().equals("User")) {
            appOwnerRef.setType(UserType.COMPLEX_TYPE);
        } else if (ownerInfo.getEntityType().equals("Role")) {
            appOwnerRef.setType(RoleType.COMPLEX_TYPE);
        } else {
            throw new IllegalStateException("Invalid owner entity type: " + ownerInfo.getEntityType());
        }
        appOwnerRef.setOid(ownerInfo.getIdentifier().toString());

        ApprovalLevelType auditTeamLevel = new ApprovalLevelType();
        appSchema.getLevel().add(auditTeamLevel);
        auditTeamLevel.setName("Approval By Security Audit Team");
        auditTeamLevel.setDescription(
                "At this level Member of Security Audit Team will approve the changes in Permission set");

        ObjectReferenceType auditRoleRef = new ObjectReferenceType();
        auditTeamLevel.getApproverRef().add(auditRoleRef);
        auditRoleRef.setDescription("Approval By Security Audit Role Members");
        auditRoleRef.setType(RoleType.COMPLEX_TYPE);
        auditRoleRef.setOid("9df8e4f6-0f70-4fa1-ba0e-6a04463bf391");//TODO get security audit role detail  from config .hardcoded for now

        return new ApprovalRequestImpl(a, appSchema, null, null, null, prismContext);
    }

    // approvalRequestList should contain de-referenced roles and approvalRequests that have prismContext set
    private List<PcpChildJobCreationInstruction> prepareJobCreateInstructions(ModelContext<?> modelContext,
            Task taskFromModel, OperationResult result, List<ApprovalRequest<AssignmentType>> approvalRequestList)
            throws SchemaException {
        List<PcpChildJobCreationInstruction> instructions = new ArrayList<>();

        String beneficiaryUsername = MiscDataUtil.getFocusObjectName(modelContext);

        for (ApprovalRequest<AssignmentType> approvalRequest : approvalRequestList) {

            assert (approvalRequest.getPrismContext() != null);

            if (LOGGER.isTraceEnabled()) {
                LOGGER.trace("Approval request = " + approvalRequest);
            }

            AssignmentType assignmentType = approvalRequest.getItemToApprove();
            String permissionSetDisplayName = this.getPermissionSetDisplayName(assignmentType);
            ResourceType res = (ResourceType) assignmentType.getTarget();
            LOGGER.info("kind: " + assignmentType.getConstruction().getKind());
            if (assignmentType.getConstruction().getKind() == null) {
                assignmentType.getConstruction().setKind(ShadowKindType.ACCOUNT);
            }
            assignmentType.setTarget(null); // we must remove the target object  in order to avoid problems with deserialization
            assignmentType.setTargetRef(null);// we must remove targetRef as account assignment does not supports it
            ((ApprovalRequestImpl<AssignmentType>) approvalRequest).setItemToApprove(assignmentType); // set the modified value back

            Validate.notNull(res);
            Validate.notNull(res.getName());
            String resourceName = res.getName().getOrig();

            String objectOid = primaryChangeAspectHelper.getObjectOid(modelContext);
            PrismObject<UserType> requester = primaryChangeAspectHelper.getRequester(taskFromModel, result);

            // create a JobCreateInstruction for a given change processor (primaryChangeProcessor in this case)
            PcpChildJobCreationInstruction instruction = PcpChildJobCreationInstruction
                    .createInstruction(getChangeProcessor());

            // set some common task/process attributes
            instruction.prepareCommonAttributes(this, modelContext, objectOid, requester);

            // prepare and set the delta that has to be approved
            ObjectDelta<? extends ObjectType> delta = assignmentToDelta(modelContext, approvalRequest, objectOid);
            instruction.setDeltaProcessAndTaskVariables(delta);

            String ownerStr = changeType.equals(ChangeTypeEnum.ADD) ? " to be owned by " + beneficiaryUsername : "";
            String taskName = "Approve " + changeType.getChangeTypeString() + " of permission set "
                    + permissionSetDisplayName + ownerStr;
            instruction.setTaskName(taskName);
            instruction.setProcessInstanceName(
                    "Approval request for " + changeType.getChangeTypeString() + " of permission set");

            // setup general item approval process
            itemApprovalProcessInterface.prepareStartInstruction(instruction, approvalRequest, taskName);

            // set some aspect-specific variables
            instruction.addProcessVariable(AddRoleVariableNames.USER_NAME, beneficiaryUsername);

            instructions.add(instruction);
        }
        return instructions;
    }

    private String getPermissionSetDisplayName(AssignmentType a) {

        if (a == null) {
            throw new IllegalArgumentException("Invalid parameter: " + a);
        }
        ConstructionType construction = a.getConstruction();
        List<ResourceAttributeDefinitionType> attrs = construction.getAttribute();
        for (ResourceAttributeDefinitionType attr : attrs) {
            String attrName = attr.getRef().getLocalPart();
            if (attrName.equals("psetDisplayName")) {
                List<JAXBElement<?>> values = attr.getOutbound().getExpression().getExpressionEvaluator();

                JAXBElement<?> firstElement = values.iterator().next();
                RawType val = (RawType) firstElement.getValue();
                XNode xnode = val.getXnode();
                PrimitiveXNode pxNode = (PrimitiveXNode) xnode;
                return String.valueOf(pxNode.getValue());
            } else {
                continue;
            }
        }
        return null;
    }

    private ObjectDelta<? extends ObjectType> assignmentToDelta(ModelContext<?> modelContext,
            ApprovalRequest<AssignmentType> approvalRequest, String objectOid) {
        PrismObject<UserType> user = (PrismObject<UserType>) modelContext.getFocusContext().getObjectNew();
        PrismContainerDefinition<AssignmentType> prismContainerDefinition = user.getDefinition()
                .findContainerDefinition(UserType.F_ASSIGNMENT);

        ItemDelta<PrismContainerValue<AssignmentType>> accountDelta = new ContainerDelta<>(new ItemPath(),
                UserType.F_ASSIGNMENT, prismContainerDefinition, prismContext);
        PrismContainerValue<AssignmentType> assignmentValue = approvalRequest.getItemToApprove()
                .asPrismContainerValue().clone();
        if (this.changeType.equals(ChangeTypeEnum.DELETE)) {
            accountDelta.addValuesToDelete(assignmentValue);
        } else {
            accountDelta.addValueToAdd(assignmentValue);
        }

        return ObjectDelta.createModifyDelta(objectOid != null ? objectOid : PrimaryChangeProcessor.UNKNOWN_OID,
                accountDelta, UserType.class, ((LensContext) modelContext).getPrismContext());
    }

    /*    private boolean shouldRoleBeApproved(AbstractRoleType role) {
    return !role.getApproverRef().isEmpty() || !role.getApproverExpression().isEmpty() || role.getApprovalSchema() != null;
        }*/
    //endregion

    //region ------------------------------------------------------------ Things that execute when item is being approved

    @Override
    public PrismObject<? extends QuestionFormType> prepareQuestionForm(org.activiti.engine.task.Task task,
            Map<String, Object> variables, OperationResult result) throws SchemaException, ObjectNotFoundException {

        if (LOGGER.isTraceEnabled()) {
            LOGGER.trace("getRequestSpecific starting: execution id " + task.getExecutionId() + ", pid "
                    + task.getProcessInstanceId() + ", variables = " + variables);
        }

        PrismObjectDefinition<AccountApprovalFormType> formDefinition = prismContext.getSchemaRegistry()
                .findObjectDefinitionByType(AccountApprovalFormType.COMPLEX_TYPE);
        PrismObject<AccountApprovalFormType> formPrism = formDefinition.instantiate();
        AccountApprovalFormType form = formPrism.asObjectable();

        form.setUser((String) variables.get(AddRoleVariableNames.USER_NAME));

        // todo check type compatibility
        ApprovalRequest request = (ApprovalRequest) variables.get(ProcessVariableNames.APPROVAL_REQUEST);
        request.setPrismContext(prismContext);
        Validate.notNull(request, "Approval request is not present among process variables");

        AssignmentType assignment = (AssignmentType) request.getItemToApprove();
        Validate.notNull(assignment, "Approval request does not contain as assignment");

        ObjectReferenceType resRef = assignment.getConstruction().getResourceRef();

        Validate.notNull(resRef, "Approval request does not contain resource reference");
        String resOid = resRef.getOid();
        Validate.notNull(resOid, "Approval request does not contain resource OID");

        ResourceType resource;
        try {
            resource = repositoryService.getObject(ResourceType.class, resOid, null, result).asObjectable();
        } catch (ObjectNotFoundException e) {
            throw new ObjectNotFoundException("Role with OID " + resOid + " does not exist anymore.");
        } catch (SchemaException e) {
            throw new SchemaException("Couldn't get role with OID " + resOid + " because of schema exception.");
        }

        form.setResource(resource.getName() == null ? resource.getOid() : resource.getName().getOrig()); // ==null should not occur
        form.setRequesterComment(assignment.getDescription());
        form.setTimeInterval(formatTimeIntervalBrief(assignment));

        if (LOGGER.isTraceEnabled()) {
            LOGGER.trace("Resulting prism object instance = " + formPrism.debugDump());
        }
        return formPrism;
    }

    public static String formatTimeIntervalBrief(AssignmentType assignment) {
        StringBuilder sb = new StringBuilder();
        if (assignment != null && assignment.getActivation() != null
                && (assignment.getActivation().getValidFrom() != null
                        || assignment.getActivation().getValidTo() != null)) {
            if (assignment.getActivation().getValidFrom() != null
                    && assignment.getActivation().getValidTo() != null) {
                sb.append(formatTime(assignment.getActivation().getValidFrom()));
                sb.append("-");
                sb.append(formatTime(assignment.getActivation().getValidTo()));
            } else if (assignment.getActivation().getValidFrom() != null) {
                sb.append("from ");
                sb.append(formatTime(assignment.getActivation().getValidFrom()));
            } else {
                sb.append("to ");
                sb.append(formatTime(assignment.getActivation().getValidTo()));
            }
        }
        return sb.toString();
    }

    private static String formatTime(XMLGregorianCalendar time) {
        DateFormat formatter = DateFormat.getDateInstance();
        return formatter.format(time.toGregorianCalendar().getTime());
    }

    @Override
    public PrismObject<? extends ObjectType> prepareRelatedObject(org.activiti.engine.task.Task task,
            Map<String, Object> variables, OperationResult result) throws SchemaException, ObjectNotFoundException {

        ApprovalRequest<AssignmentType> approvalRequest = (ApprovalRequest<AssignmentType>) variables
                .get(ProcessVariableNames.APPROVAL_REQUEST);
        approvalRequest.setPrismContext(prismContext);
        if (approvalRequest == null) {
            throw new IllegalStateException("No approval request in activiti task " + task);
        }
        String oid = approvalRequest.getItemToApprove().getConstruction().getResourceRef().getOid();
        PrismObject object = repositoryService.getObject(ResourceType.class, oid, null, result);
        ResourceType res = (ResourceType) object.asObjectable();
        ConnectorType connector = repositoryService
                .getObject(ConnectorType.class, res.getConnectorRef().getOid(), null, result).asObjectable();
        res.setConnector(connector);
        return object;
    }

    //endregion
}