/* * 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.certification.impl; import com.evolveum.midpoint.certification.api.OutcomeUtils; import com.evolveum.midpoint.certification.impl.outcomeStrategies.OutcomeStrategy; import com.evolveum.midpoint.certification.impl.outcomeStrategies.ResponsesSummary; import com.evolveum.midpoint.schema.util.CertCampaignTypeUtil; import com.evolveum.midpoint.schema.util.WorkItemTypeUtil; 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.lang3.ObjectUtils; import org.springframework.stereotype.Component; import java.util.*; import java.util.stream.Collectors; import static com.evolveum.midpoint.schema.util.ObjectTypeUtil.toShortString; import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseOutcomeStrategyType.ALL_MUST_ACCEPT; import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseOutcomeStrategyType.ONE_ACCEPT_ACCEPTS; import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationResponseType.NO_RESPONSE; /** * @author mederly */ @Component public class AccCertResponseComputationHelper { private static final transient Trace LOGGER = TraceManager.getTrace(AccCertResponseComputationHelper.class); public static final AccessCertificationCaseOutcomeStrategyType DEFAULT_CASE_STAGE_OUTCOME_STRATEGY = ONE_ACCEPT_ACCEPTS; public static final AccessCertificationCaseOutcomeStrategyType DEFAULT_CASE_OVERALL_OUTCOME_STRATEGY = ALL_MUST_ACCEPT; Map<AccessCertificationCaseOutcomeStrategyType, OutcomeStrategy> outcomeStrategyMap = new HashMap<>(); public void registerOutcomeStrategy(AccessCertificationCaseOutcomeStrategyType strategyName, OutcomeStrategy strategy) { outcomeStrategyMap.put(strategyName, strategy); } private OutcomeStrategy getOutcomeStrategy(AccessCertificationCaseOutcomeStrategyType outcomeStrategy) { OutcomeStrategy strategyImpl = outcomeStrategyMap.get(outcomeStrategy); if (strategyImpl == null) { throw new IllegalStateException("Unknown/unsupported outcome strategy " + outcomeStrategy); } return strategyImpl; } // should be the case enabled in the following stage? public boolean computeEnabled(AccessCertificationCampaignType campaign, AccessCertificationCaseType _case, List<AccessCertificationResponseType> outcomesToStopOn) { if (_case.getStageNumber() != campaign.getStageNumber()) { return false; // it is not enabled in the current stage at all } AccessCertificationResponseType currentOutcome = OutcomeUtils.fromUri(_case.getCurrentStageOutcome()); if (currentOutcome == null) { currentOutcome = NO_RESPONSE; } return !outcomesToStopOn.contains(currentOutcome); } public List<AccessCertificationResponseType> getOutcomesToStopOn(AccessCertificationCampaignType campaign) { final List<AccessCertificationResponseType> rv; AccessCertificationStageDefinitionType stageDefinition = CertCampaignTypeUtil.getCurrentStageDefinition(campaign); if (!stageDefinition.getStopReviewOn().isEmpty() || !stageDefinition.getAdvanceToNextStageOn().isEmpty()) { rv = CertCampaignTypeUtil.getOutcomesToStopOn(stageDefinition.getStopReviewOn(), stageDefinition.getAdvanceToNextStageOn()); } else { final AccessCertificationCaseReviewStrategyType reviewStrategy = campaign.getReviewStrategy(); if (reviewStrategy != null && (!reviewStrategy.getStopReviewOn().isEmpty() || !reviewStrategy.getAdvanceToNextStageOn().isEmpty())) { rv = CertCampaignTypeUtil.getOutcomesToStopOn(reviewStrategy.getStopReviewOn(), reviewStrategy.getAdvanceToNextStageOn()); } else { final OutcomeStrategy outcomeStrategy = getOverallOutcomeStrategy(campaign); rv = outcomeStrategy.getOutcomesToStopOn(); } } if (LOGGER.isTraceEnabled()) { LOGGER.trace("Outcomes to stop on for campaign {}, stage {}: {}", toShortString(campaign), campaign.getStageNumber(), rv); } return rv; } private OutcomeStrategy getOverallOutcomeStrategy(AccessCertificationCampaignType campaign) { final AccessCertificationCaseOutcomeStrategyType strategyName; if (campaign.getReviewStrategy() != null && campaign.getReviewStrategy().getOutcomeStrategy() != null) { strategyName = campaign.getReviewStrategy().getOutcomeStrategy(); } else { strategyName = DEFAULT_CASE_OVERALL_OUTCOME_STRATEGY; } if (LOGGER.isTraceEnabled()) { LOGGER.trace("Outcome strategy for {} is {}", toShortString(campaign), strategyName); } return getOutcomeStrategy(strategyName); } public AccessCertificationResponseType computeOutcomeForStage(AccessCertificationCaseType _case, AccessCertificationCampaignType campaign, int stageNunber) { List<AccessCertificationResponseType> allResponses = getResponses(_case, stageNunber); return computeResponseForStageInternal(allResponses, _case, campaign, stageNunber); } // allResponses must include null ones (i.e. not provided) private AccessCertificationResponseType computeResponseForStageInternal( List<AccessCertificationResponseType> allResponses, AccessCertificationCaseType _case, AccessCertificationCampaignType campaign, int stageNumber) { AccessCertificationStageDefinitionType stageDef = CertCampaignTypeUtil.findStageDefinition(campaign, stageNumber); AccessCertificationCaseOutcomeStrategyType outcomeStrategy = ObjectUtils.defaultIfNull(stageDef.getOutcomeStrategy(), DEFAULT_CASE_STAGE_OUTCOME_STRATEGY); OutcomeStrategy strategyImpl = getOutcomeStrategy(outcomeStrategy); if (allResponses.isEmpty()) { return stageDef.getOutcomeIfNoReviewers(); } else { ResponsesSummary summary = summarize(allResponses); // TODO eventually merge extraction and summarizing return strategyImpl.computeOutcome(summary); } } private List<AccessCertificationResponseType> getResponses(AccessCertificationCaseType _case, int stageNumber) { return _case.getWorkItem().stream() .filter(wi -> wi.getStageNumber() == stageNumber) .map(wi -> ObjectUtils.defaultIfNull( OutcomeUtils.fromUri(WorkItemTypeUtil.getOutcome(wi)), AccessCertificationResponseType.NO_RESPONSE)) .collect(Collectors.toList()); } private ResponsesSummary summarize(List<AccessCertificationResponseType> responses) { ResponsesSummary summary = new ResponsesSummary(); for (AccessCertificationResponseType response : responses) { if (response == null) { summary.add(NO_RESPONSE); } else { summary.add(response); } } return summary; } public AccessCertificationResponseType computeOverallOutcome(AccessCertificationCaseType aCase, AccessCertificationCampaignType campaign) { final OutcomeStrategy strategy = getOverallOutcomeStrategy(campaign); return strategy.computeOutcome(summarize(OutcomeUtils.fromUri(CertCampaignTypeUtil.getOutcomesFromCompletedStages(aCase)))); } // aCase contains outcomes from stages 1..N-1. Outcome from stage N is in currentStageOutcome AccessCertificationResponseType computeOverallOutcome(AccessCertificationCaseType aCase, AccessCertificationCampaignType campaign, String currentStageOutcome) { return computeOverallOutcome(aCase, campaign, OutcomeUtils.fromUri(currentStageOutcome)); } AccessCertificationResponseType computeOverallOutcome(AccessCertificationCaseType aCase, AccessCertificationCampaignType campaign, AccessCertificationResponseType currentStageOutcome) { final OutcomeStrategy strategy = getOverallOutcomeStrategy(campaign); final List<AccessCertificationResponseType> stageOutcomes = new ArrayList<>(); stageOutcomes.addAll(OutcomeUtils.fromUri(CertCampaignTypeUtil.getOutcomesFromCompletedStages(aCase))); stageOutcomes.add(currentStageOutcome); return strategy.computeOutcome(summarize(stageOutcomes)); } }