Skip to content

Commit

Permalink
Cleaning up certification outcome computation behavior. Plus a couple…
Browse files Browse the repository at this point in the history
… of other fixes. Work in progress.
  • Loading branch information
mederly committed Feb 4, 2016
1 parent 8f64eb0 commit f9020b0
Show file tree
Hide file tree
Showing 26 changed files with 1,424 additions and 759 deletions.
Expand Up @@ -41,6 +41,7 @@

import javax.xml.namespace.QName;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

/**
Expand Down Expand Up @@ -209,6 +210,12 @@ public S_ItemEntry replace(Object... realValues) {
return this;
}

@Override
public S_ItemEntry replace(Collection<PrismValue> values) {
currentDelta.setValuesToReplace(values);
return this;
}

@Override
public S_ItemEntry replace(PrismValue... values) {
currentDelta.setValuesToReplace(values);
Expand Down
Expand Up @@ -18,6 +18,8 @@

import com.evolveum.midpoint.prism.PrismValue;

import java.util.Collection;

/**
* @author mederly
*/
Expand All @@ -29,5 +31,6 @@ public interface S_ValuesEntry {
S_ItemEntry delete(PrismValue... values);
S_ItemEntry replace(Object... realValues);
S_ItemEntry replace(PrismValue... values);
S_ItemEntry replace(Collection<PrismValue> values); // TODO

}
Expand Up @@ -34,6 +34,7 @@
import java.util.List;

import static com.evolveum.midpoint.prism.PrismConstants.T_PARENT;
import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationResponseType.NO_RESPONSE;

/**
* @author mederly
Expand All @@ -49,6 +50,10 @@ public static AccessCertificationStageType getCurrentStage(AccessCertificationCa
return null;
}

public static AccessCertificationStageDefinitionType getCurrentStageDefinition(AccessCertificationCampaignType campaign) {
return findStageDefinition(campaign, campaign.getStageNumber());
}

public static AccessCertificationStageDefinitionType findStageDefinition(AccessCertificationCampaignType campaign, int stageNumber) {
for (AccessCertificationStageDefinitionType stage : campaign.getStageDefinition()) {
if (stage.getNumber() == stageNumber) {
Expand Down Expand Up @@ -174,7 +179,7 @@ public static int getUnansweredCases(List<AccessCertificationCaseType> caseList,
if (decision.getStageNumber() != aCase.getCurrentStageNumber()) {
continue;
}
if (decision.getResponse() != null && decision.getResponse() != AccessCertificationResponseType.NO_RESPONSE) {
if (decision.getResponse() != null && decision.getResponse() != NO_RESPONSE) {
continue;
}
done = false;
Expand All @@ -188,10 +193,10 @@ public static int getUnansweredCases(List<AccessCertificationCaseType> caseList,
}

public static int getPercentComplete(List<AccessCertificationCaseType> caseList, int campaignStageNumber, AccessCertificationCampaignStateType state) {
int active = getActiveCases(caseList, campaignStageNumber, state);
if (active > 0) {
int cases = caseList.size();
if (cases > 0) {
int unanswered = getUnansweredCases(caseList, campaignStageNumber, state);
return 100 * (active - unanswered) / active;
return 100 * (cases - unanswered) / cases;
} else {
return 100;
}
Expand All @@ -200,6 +205,9 @@ public static int getPercentComplete(List<AccessCertificationCaseType> caseList,
public static Date getReviewedTimestamp(List<AccessCertificationDecisionType> decisions) {
Date lastDate = null;
for (AccessCertificationDecisionType decision : decisions) {
if (isEmpty(decision)) {
continue;
}
Date decisionDate = XmlTypeConverter.toDate(decision.getTimestamp());
if (lastDate == null || decisionDate.after(lastDate)) {
lastDate = decisionDate;
Expand All @@ -208,10 +216,14 @@ public static Date getReviewedTimestamp(List<AccessCertificationDecisionType> de
return lastDate;
}

protected static boolean isEmpty(AccessCertificationDecisionType decision) {
return (decision.getResponse() == null || decision.getResponse() == NO_RESPONSE) && StringUtils.isEmpty(decision.getComment());
}

public static List<ObjectReferenceType> getReviewedBy(List<AccessCertificationDecisionType> decisions) {
List<ObjectReferenceType> rv = new ArrayList<>();
for (AccessCertificationDecisionType decision : decisions) {
if (decision.getResponse() == null && StringUtils.isEmpty(decision.getComment())) {
if (isEmpty(decision)) {
continue;
}
rv.add(decision.getReviewerRef());
Expand Down
134 changes: 105 additions & 29 deletions infra/schema/src/main/resources/xml/ns/public/common/common-3.xsd
Expand Up @@ -12286,6 +12286,14 @@
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="reviewStrategy" type="tns:AccessCertificationCaseReviewStrategyType" minOccurs="0">
<xsd:annotation>
<xsd:documentation>
Strategy used to compute review outcome for a given case, based on results of individual stages,
along with instructions when a case review advances from a stage to next one.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="lastCampaignIdUsed" type="xsd:int" minOccurs="0">
<xsd:annotation>
<xsd:documentation>
Expand Down Expand Up @@ -12405,6 +12413,37 @@
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="outcomeStrategy" type="tns:AccessCertificationCaseOutcomeStrategyType" minOccurs="0">
<xsd:annotation>
<xsd:documentation>
How to determine outcome of the approval process (e.g. if multiple reviewers are present)?
Default is oneAcceptAccepts.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="outcomeIfNoReviewers" type="tns:AccessCertificationResponseType" minOccurs="0">
<xsd:annotation>
<xsd:documentation>
What is the outcome if no reviewers are available? (This is not the same situation as if some reviewers were computed but none of them responded!)
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="stopReviewOn" type="tns:AccessCertificationResponseType" minOccurs="0" maxOccurs="unbounded">
<xsd:annotation>
<xsd:documentation>
What decisions stop the case from advancing to the next stage?
If neither stopReviewOn nor advanceToNextStageOn is used, a default (defined at the campaign level) is used.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="advanceToNextStageOn" type="tns:AccessCertificationResponseType" minOccurs="0" maxOccurs="unbounded">
<xsd:annotation>
<xsd:documentation>
What decisions make the case to advance to the next stage?
If neither stopReviewOn nor advanceToNextStageOn is used, a default (defined at the campaign level) is used.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
</xsd:complexType>

Expand Down Expand Up @@ -12506,13 +12545,6 @@
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
<xsd:element name="approvalStrategy" type="tns:AccessCertificationApprovalStrategyType" minOccurs="0">
<xsd:annotation>
<xsd:documentation>
How to determine outcome of the approval process (e.g. if multiple reviewers are present)?
</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
</xsd:complexType>

Expand Down Expand Up @@ -12574,6 +12606,14 @@
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="reviewStrategy" type="tns:AccessCertificationCaseReviewStrategyType" minOccurs="0">
<xsd:annotation>
<xsd:documentation>
Strategy used to compute review outcome for a given case, based on results of individual stages,
along with instructions when a case review advances from a stage to next one.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="start" type="xsd:dateTime" minOccurs="0">
<xsd:annotation>
<xsd:documentation>
Expand Down Expand Up @@ -12927,10 +12967,10 @@
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="currentResponse" type="tns:AccessCertificationResponseType" minOccurs="0" maxOccurs="1">
<xsd:element name="currentOutcome" type="tns:AccessCertificationResponseType" minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:documentation>
Currently valid response, relevant to the current stage. It is recomputed on each reviewer's
Currently valid outcome, relevant to the current stage. It is recomputed on each reviewer's
response based on defined algorithms. If the case is not transferred into the next stage,
the value of this item stays as it is.
</xsd:documentation>
Expand All @@ -12940,7 +12980,7 @@
<xsd:annotation>
<xsd:documentation>
The number of current stage in which this case is.
E.g. currentResponse relates to the currentStage.
E.g. currentOutcome relates to the currentStage.
Case is "enabled" for a current campaign stage if and only if case.currentStage == campaign.stageNumber.

When opening a campaign stage, case's currentStage either advances (if it is transferred to stage being opened)
Expand All @@ -12949,21 +12989,14 @@
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<!--<xsd:element name="currentApprovalStrategy" type="tns:AccessCertificationApprovalStrategyType" minOccurs="0" maxOccurs="1">
<xsd:element name="completedStageOutcome" type="tns:AccessCertificationCaseStageOutcomeType" minOccurs="0" maxOccurs="unbounded">
<xsd:annotation>
<xsd:documentation>
How the response is computed from individual reviewers' decisions.
Outcomes of stages that are already completed.
</xsd:documentation>
</xsd:annotation>
</xsd:element>-->
<!--<xsd:element name="enabled" type="xsd:boolean" minOccurs="1" maxOccurs="1">-->
<!--<xsd:annotation>-->
<!--<xsd:documentation>-->
<!--Is the case enabled for the current stage? E.g. cases that have been marked as "remove" in a given stage-->
<!--may be disabled for later stages.-->
<!--</xsd:documentation>-->
<!--</xsd:annotation>-->
<!--</xsd:element>-->
</xsd:element>

<xsd:element name="remediedTimestamp" type="xsd:dateTime" minOccurs="0">
<xsd:annotation>
<xsd:documentation>
Expand Down Expand Up @@ -12995,6 +13028,19 @@
</xsd:complexType>
<xsd:element name="accessCertificationCase" type="tns:AccessCertificationCaseType"/>

<xsd:complexType name="AccessCertificationCaseStageOutcomeType">
<xsd:annotation>
<xsd:appinfo>
<a:container/>
</xsd:appinfo>
</xsd:annotation>
<xsd:sequence>
<xsd:element name="stageNumber" type="xsd:int" minOccurs="1" />
<xsd:element name="outcome" type="tns:AccessCertificationResponseType" minOccurs="1" />
</xsd:sequence>
<xsd:attribute name="id" type="xsd:long" use="optional"/>
</xsd:complexType>

<xsd:complexType name="AccessCertificationAssignmentCaseType">
<xsd:annotation>
<xsd:appinfo>
Expand Down Expand Up @@ -13155,20 +13201,50 @@
</xsd:restriction>
</xsd:simpleType>

<xsd:simpleType name="AccessCertificationApprovalStrategyType">
<xsd:complexType name="AccessCertificationCaseReviewStrategyType">
<xsd:sequence>
<xsd:element name="outcomeStrategy" type="tns:AccessCertificationCaseOutcomeStrategyType" minOccurs="0">
<xsd:annotation>
<xsd:documentation>
Strategy used to compute review outcome for a given case, based on results of individual stages.
Default is oneDenyDenies.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="stopReviewOn" type="tns:AccessCertificationResponseType" minOccurs="0" maxOccurs="unbounded">
<xsd:annotation>
<xsd:documentation>
What decisions stop the case from advancing to the next stage?
If neither stopReviewOn nor advanceToNextStageOn is used, a default (defined by the outcomeStrategy) is used.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="advanceToNextStageOn" type="tns:AccessCertificationResponseType" minOccurs="0" maxOccurs="unbounded">
<xsd:annotation>
<xsd:documentation>
What decisions make the case to advance to the next stage?
If neither stopReviewOn nor advanceToNextStageOn is used, a default (defined by the outcomeStrategy) is used.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
</xsd:complexType>

<xsd:simpleType name="AccessCertificationCaseOutcomeStrategyType">
<xsd:annotation>
<xsd:documentation>
An enumeration that defines possible strategies for approval result computation.
An enumeration that defines possible strategies for case outcome (approval) computation - currently both at the stage and campaign level.
(In the future, these uses might be split.)
</xsd:documentation>
</xsd:annotation>
<xsd:restriction base="xsd:string">
<xsd:enumeration value="oneApprovalApproves">
<xsd:enumeration value="oneAcceptAccepts">
<xsd:annotation>
<xsd:documentation>
If at least one reviewer approves, the result is "APPROVED" regardless of the other votes.
</xsd:documentation>
<xsd:appinfo>
<jaxb:typesafeEnumMember name="ONE_APPROVAL_APPROVES"/>
<jaxb:typesafeEnumMember name="ONE_ACCEPT_ACCEPTS"/>
</xsd:appinfo>
</xsd:annotation>
</xsd:enumeration>
Expand All @@ -13183,24 +13259,24 @@
</xsd:appinfo>
</xsd:annotation>
</xsd:enumeration>
<xsd:enumeration value="approvedIfNotDenied">
<xsd:enumeration value="acceptedIfNotDenied">
<xsd:annotation>
<xsd:documentation>
Approved if none of the reviewers denies (either via revoke or reduce).
So e.g. if nobody says anything, the case is approved.
</xsd:documentation>
<xsd:appinfo>
<jaxb:typesafeEnumMember name="APPROVED_IF_NOT_DENIED"/>
<jaxb:typesafeEnumMember name="ACCEPTED_IF_NOT_DENIED"/>
</xsd:appinfo>
</xsd:annotation>
</xsd:enumeration>
<xsd:enumeration value="allMustApprove">
<xsd:enumeration value="allMustAccept">
<xsd:annotation>
<xsd:documentation>
All reviewers must approve, i.e. no revoke, reduce, noResponse is acceptable.
</xsd:documentation>
<xsd:appinfo>
<jaxb:typesafeEnumMember name="ALL_MUST_APPROVE"/>
<jaxb:typesafeEnumMember name="ALL_MUST_ACCEPT"/>
</xsd:appinfo>
</xsd:annotation>
</xsd:enumeration>
Expand Down

0 comments on commit f9020b0

Please sign in to comment.