com.evolveum.midpoint.certification.impl.AccCertReviewersHelper.java Source code

Java tutorial

Introduction

Here is the source code for com.evolveum.midpoint.certification.impl.AccCertReviewersHelper.java

Source

/*
 * Copyright (c) 2010-2017 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.certification.impl;

import com.evolveum.midpoint.repo.common.expression.ExpressionVariables;
import com.evolveum.midpoint.model.api.expr.OrgStructFunctions;
import com.evolveum.midpoint.model.impl.expr.ExpressionEnvironment;
import com.evolveum.midpoint.model.impl.expr.ModelExpressionThreadLocalHolder;
import com.evolveum.midpoint.prism.PrismContext;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.PrismReferenceValue;
import com.evolveum.midpoint.prism.query.ObjectQuery;
import com.evolveum.midpoint.prism.query.builder.QueryBuilder;
import com.evolveum.midpoint.repo.api.RepositoryService;
import com.evolveum.midpoint.schema.constants.ExpressionConstants;
import com.evolveum.midpoint.schema.constants.SchemaConstants;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.schema.util.CertCampaignTypeUtil;
import com.evolveum.midpoint.schema.util.ObjectTypeUtil;
import com.evolveum.midpoint.schema.util.ResourceTypeUtil;
import com.evolveum.midpoint.task.api.Task;
import com.evolveum.midpoint.util.QNameUtil;
import com.evolveum.midpoint.util.exception.*;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import javax.xml.namespace.QName;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author mederly
 */
@Component
public class AccCertReviewersHelper {

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

    @Autowired
    @Qualifier("cacheRepositoryService")
    private RepositoryService repositoryService;

    @Autowired
    private OrgStructFunctions orgStructFunctions;
    @Autowired
    private PrismContext prismContext;
    @Autowired
    private AccCertExpressionHelper expressionHelper;

    public AccessCertificationReviewerSpecificationType findReviewersSpecification(
            AccessCertificationCampaignType campaign, int stage, Task task, OperationResult result) {
        AccessCertificationStageDefinitionType stageDef = CertCampaignTypeUtil.findStageDefinition(campaign, stage);
        return stageDef.getReviewerSpecification();
    }

    public List<ObjectReferenceType> getReviewersForCase(AccessCertificationCaseType _case,
            AccessCertificationCampaignType campaign, AccessCertificationReviewerSpecificationType reviewerSpec,
            Task task, OperationResult result) throws SchemaException, ObjectNotFoundException {
        if (reviewerSpec == null) {
            return Collections.emptyList(); // TODO issue a warning here?
        }

        List<ObjectReferenceType> reviewers = new ArrayList<>();
        if (Boolean.TRUE.equals(reviewerSpec.isUseTargetOwner())) {
            cloneAndMerge(reviewers, getTargetObjectOwners(_case, task, result));
        }
        if (Boolean.TRUE.equals(reviewerSpec.isUseTargetApprover())) {
            cloneAndMerge(reviewers, getTargetObjectApprovers(_case, task, result));
        }
        if (Boolean.TRUE.equals(reviewerSpec.isUseObjectOwner())) {
            cloneAndMerge(reviewers, getObjectOwners(_case, task, result));
        }
        if (Boolean.TRUE.equals(reviewerSpec.isUseObjectApprover())) {
            cloneAndMerge(reviewers, getObjectApprovers(_case, task, result));
        }
        if (reviewerSpec.getUseObjectManager() != null) {
            cloneAndMerge(reviewers, getObjectManagers(_case, reviewerSpec.getUseObjectManager(), task, result));
        }
        for (ExpressionType reviewerExpression : reviewerSpec.getReviewerExpression()) {
            ExpressionVariables variables = new ExpressionVariables();
            variables.addVariableDefinition(ExpressionConstants.VAR_CERTIFICATION_CASE, _case);
            variables.addVariableDefinition(ExpressionConstants.VAR_CAMPAIGN, campaign);
            variables.addVariableDefinition(ExpressionConstants.VAR_REVIEWER_SPECIFICATION, reviewerSpec);
            List<ObjectReferenceType> refList = expressionHelper.evaluateRefExpressionChecked(reviewerExpression,
                    variables, "reviewer expression", task, result);
            cloneAndMerge(reviewers, refList);
        }
        resolveRoleReviewers(reviewers, task, result);
        if (reviewers.isEmpty()) {
            cloneAndMerge(reviewers, reviewerSpec.getDefaultReviewerRef());
        }
        cloneAndMerge(reviewers, reviewerSpec.getAdditionalReviewerRef());
        resolveRoleReviewers(reviewers, task, result);

        return reviewers;
    }

    private void resolveRoleReviewers(List<ObjectReferenceType> reviewers, Task task, OperationResult result)
            throws SchemaException {
        List<ObjectReferenceType> resolved = new ArrayList<>();
        for (Iterator<ObjectReferenceType> iterator = reviewers.iterator(); iterator.hasNext();) {
            ObjectReferenceType reviewer = iterator.next();
            if (QNameUtil.match(reviewer.getType(), RoleType.COMPLEX_TYPE)
                    || QNameUtil.match(reviewer.getType(), OrgType.COMPLEX_TYPE)
                    || QNameUtil.match(reviewer.getType(), ServiceType.COMPLEX_TYPE)) {
                iterator.remove();
                resolved.addAll(getMembers(reviewer, task, result));
            }
        }
        for (ObjectReferenceType ref : resolved) {
            if (!containsOid(reviewers, ref.getOid())) {
                reviewers.add(ref);
            }
        }
    }

    private List<ObjectReferenceType> getMembers(ObjectReferenceType abstractRoleRef, Task task,
            OperationResult result) throws SchemaException {
        ObjectQuery query = QueryBuilder.queryFor(UserType.class, prismContext).item(UserType.F_ROLE_MEMBERSHIP_REF)
                .ref(abstractRoleRef.getOid()).build();
        return repositoryService.searchObjects(UserType.class, query, null, result).stream()
                .map(obj -> ObjectTypeUtil.createObjectRef(obj)).collect(Collectors.toList());
    }

    private void cloneAndMerge(List<ObjectReferenceType> reviewers, Collection<ObjectReferenceType> newReviewers) {
        if (newReviewers == null) {
            return;
        }
        for (ObjectReferenceType newReviewer : newReviewers) {
            if (!containsOid(reviewers, newReviewer.getOid())) {
                reviewers.add(newReviewer.clone());
            }
        }
    }

    private boolean containsOid(List<ObjectReferenceType> reviewers, String oid) {
        for (ObjectReferenceType reviewer : reviewers) {
            if (reviewer.getOid().equals(oid)) {
                return true;
            }
        }
        return false;
    }

    private Collection<ObjectReferenceType> getObjectManagers(AccessCertificationCaseType _case,
            ManagerSearchType managerSearch, Task task, OperationResult result)
            throws ObjectNotFoundException, SchemaException {
        ModelExpressionThreadLocalHolder.pushExpressionEnvironment(new ExpressionEnvironment<>(task, result));
        try {
            ObjectReferenceType objectRef = _case.getObjectRef();
            ObjectType object = resolveReference(objectRef, ObjectType.class, result);

            String orgType = managerSearch.getOrgType();
            boolean allowSelf = Boolean.TRUE.equals(managerSearch.isAllowSelf());
            Collection<UserType> managers;
            if (object instanceof UserType) {
                managers = orgStructFunctions.getManagers((UserType) object, orgType, allowSelf, true);
            } else if (object instanceof OrgType) {
                // TODO more elaborate behavior; eliminate unneeded resolveReference above
                managers = orgStructFunctions.getManagersOfOrg(object.getOid(), true);
            } else if (object instanceof RoleType || object instanceof ServiceType) {
                // TODO implement
                managers = new HashSet<>();
            } else {
                // TODO warning?
                managers = new HashSet<>();
            }
            List<ObjectReferenceType> retval = new ArrayList<>(managers.size());
            for (UserType manager : managers) {
                retval.add(ObjectTypeUtil.createObjectRef(manager));
            }
            return retval;
        } catch (SecurityViolationException e) {
            // never occurs, as preAuthorized is TRUE above
            throw new IllegalStateException("Impossible has happened: " + e.getMessage(), e);
        } finally {
            ModelExpressionThreadLocalHolder.popExpressionEnvironment();
        }
    }

    protected List<ObjectReferenceType> getTargetObjectOwners(AccessCertificationCaseType _case, Task task,
            OperationResult result) throws SchemaException, ObjectNotFoundException {
        if (_case.getTargetRef() == null) {
            return null;
        }
        ObjectType target = resolveReference(_case.getTargetRef(), ObjectType.class, result);
        if (target instanceof AbstractRoleType) {
            return getAssignees((AbstractRoleType) target, SchemaConstants.ORG_OWNER, task, result);
        } else if (target instanceof ResourceType) {
            return ResourceTypeUtil.getOwnerRef((ResourceType) target);
        } else {
            return null;
        }
    }

    private List<ObjectReferenceType> getAssignees(AbstractRoleType role, QName relation, Task task,
            OperationResult result) throws SchemaException {
        List<ObjectReferenceType> rv = new ArrayList<>();
        if (SchemaConstants.ORG_OWNER.equals(relation)) {
            CollectionUtils.addIgnoreNull(rv, role.getOwnerRef());
        } else if (SchemaConstants.ORG_APPROVER.equals(relation)) {
            rv.addAll(role.getApproverRef());
        } else {
            throw new AssertionError(relation);
        }
        // TODO in theory, we could look for approvers/owners of UserType, right?
        PrismReferenceValue ref = new PrismReferenceValue(role.getOid());
        ref.setRelation(relation);
        ObjectQuery query = QueryBuilder.queryFor(FocusType.class, prismContext)
                .item(FocusType.F_ROLE_MEMBERSHIP_REF).ref(ref).build();
        List<PrismObject<FocusType>> assignees = repositoryService.searchObjects(FocusType.class, query, null,
                result);
        LOGGER.trace("Looking for '{}' of {} using {}: found: {}", relation.getLocalPart(), role, query, assignees);
        assignees.forEach(o -> rv.add(ObjectTypeUtil.createObjectRef(o)));
        return rv;
    }

    protected List<ObjectReferenceType> getObjectOwners(AccessCertificationCaseType _case, Task task,
            OperationResult result) throws SchemaException, ObjectNotFoundException {
        if (_case.getObjectRef() == null) {
            return null;
        }
        ObjectType object = resolveReference(_case.getObjectRef(), ObjectType.class, result);
        if (object instanceof AbstractRoleType) {
            return getAssignees((AbstractRoleType) object, SchemaConstants.ORG_OWNER, task, result);
        } else {
            return null;
        }
    }

    private Collection<ObjectReferenceType> getTargetObjectApprovers(AccessCertificationCaseType _case, Task task,
            OperationResult result) throws SchemaException, ObjectNotFoundException {
        if (_case.getTargetRef() == null) {
            return null;
        }
        ObjectType target = resolveReference(_case.getTargetRef(), ObjectType.class, result);
        if (target instanceof AbstractRoleType) {
            return getAssignees((AbstractRoleType) target, SchemaConstants.ORG_APPROVER, task, result);
        } else if (target instanceof ResourceType) {
            return ResourceTypeUtil.getApproverRef((ResourceType) target);
        } else {
            return null;
        }
    }

    private Collection<ObjectReferenceType> getObjectApprovers(AccessCertificationCaseType _case, Task task,
            OperationResult result) throws SchemaException, ObjectNotFoundException {
        if (_case.getObjectRef() == null) {
            return null;
        }
        ObjectType object = resolveReference(_case.getObjectRef(), ObjectType.class, result);
        if (object instanceof AbstractRoleType) {
            return getAssignees((AbstractRoleType) object, SchemaConstants.ORG_APPROVER, task, result);
        } else {
            return null;
        }
    }

    private ObjectType resolveReference(ObjectReferenceType objectRef,
            Class<? extends ObjectType> defaultObjectTypeClass, OperationResult result)
            throws SchemaException, ObjectNotFoundException {
        final Class<? extends ObjectType> objectTypeClass;
        if (objectRef.getType() != null) {
            objectTypeClass = (Class<? extends ObjectType>) prismContext.getSchemaRegistry()
                    .getCompileTimeClassForObjectType(objectRef.getType());
            if (objectTypeClass == null) {
                throw new SchemaException("No object class found for " + objectRef.getType());
            }
        } else {
            objectTypeClass = defaultObjectTypeClass;
        }
        PrismObject<? extends ObjectType> object = repositoryService.getObject(objectTypeClass, objectRef.getOid(),
                null, result);
        return object.asObjectable();
    }

}