/*
* 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.prism.PrismContext;
import com.evolveum.midpoint.prism.query.AndFilter;
import com.evolveum.midpoint.prism.query.InOidFilter;
import com.evolveum.midpoint.prism.query.ObjectFilter;
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.GetOperationOptions;
import com.evolveum.midpoint.schema.SelectorOptions;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.security.api.MidPointPrincipal;
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.exception.SecurityViolationException;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import com.evolveum.midpoint.wf.util.QueryUtils;
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import java.util.*;
import static com.evolveum.midpoint.xml.ns._public.common.common_3.AbstractWorkItemOutputType.F_OUTCOME;
import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationCaseType.F_WORK_ITEM;
import static com.evolveum.midpoint.xml.ns._public.common.common_3.AccessCertificationWorkItemType.*;
/**
* @author mederly
*/
@Component
public class AccCertQueryHelper {
private static final transient Trace LOGGER = TraceManager.getTrace(AccCertQueryHelper.class);
@Autowired private PrismContext prismContext;
@Autowired protected AccCertGeneralHelper helper;
@Autowired @Qualifier("cacheRepositoryService")
private RepositoryService repositoryService;
// public because of certification tests
public List<AccessCertificationCaseType> searchCases(String campaignOid, ObjectQuery query,
Collection<SelectorOptions<GetOperationOptions>> options, OperationResult result) throws SchemaException {
ObjectQuery newQuery;
InOidFilter inOidFilter = InOidFilter.createOwnerHasOidIn(campaignOid);
newQuery = replaceFilter(query, inOidFilter);
return repositoryService.searchContainers(AccessCertificationCaseType.class, newQuery, options, result);
}
private ObjectQuery replaceFilter(ObjectQuery query, ObjectFilter newFilter) {
ObjectQuery newQuery;
if (query == null) {
newQuery = ObjectQuery.createObjectQuery(newFilter);
} else {
newQuery = query.clone();
if (query.getFilter() == null) {
newQuery.setFilter(newFilter);
} else {
newQuery.setFilter(AndFilter.createAnd(query.getFilter(), newFilter));
}
}
return newQuery;
}
// public because of testing
// principal == null => take all work items
public List<AccessCertificationWorkItemType> searchOpenWorkItems(ObjectQuery baseWorkItemsQuery, MidPointPrincipal principal,
boolean notDecidedOnly, Collection<SelectorOptions<GetOperationOptions>> options, OperationResult result)
throws SchemaException, ObjectNotFoundException {
// enhance filter with reviewerRef + enabled
ObjectQuery newQuery;
ObjectFilter reviewerAndEnabledFilter = getReviewerAndEnabledFilterForWI(principal);
ObjectFilter filterToAdd;
if (notDecidedOnly) {
ObjectFilter noResponseFilter = QueryBuilder.queryFor(AccessCertificationWorkItemType.class, prismContext)
.item(F_OUTPUT, F_OUTCOME).isNull()
.buildFilter();
filterToAdd = AndFilter.createAnd(reviewerAndEnabledFilter, noResponseFilter);
} else {
filterToAdd = reviewerAndEnabledFilter;
}
newQuery = replaceFilter(baseWorkItemsQuery, filterToAdd);
// retrieve cases, filtered
List<AccessCertificationWorkItemType> workItems = repositoryService.searchContainers(AccessCertificationWorkItemType.class, newQuery, options, result);
// // campaigns already loaded
// Map<String,AccessCertificationCampaignType> campaigns = new HashMap<>();
//
// // add campaignRef
// for (AccessCertificationWorkItemType workItem : workItems) {
// if (workItem.getCampaignRef() == null) {
// LOGGER.warn("AccessCertificationCaseType {} has no campaignRef -- skipping it", workItem);
// continue;
// }
// // obtain campaign object
// String campaignOid = workItem.getCampaignRef().getOid();
// AccessCertificationCampaignType campaign = campaigns.get(campaignOid);
// if (campaign == null) {
// campaign = repositoryService.getObject(AccessCertificationCampaignType.class, campaignOid, null, result).asObjectable(); // TODO error checking
// campaigns.put(campaignOid, campaign);
// }
//
// PrismObject<AccessCertificationCampaignType> campaignObject = campaign.asPrismObject();
// ObjectReferenceType campaignRef = ObjectTypeUtil.createObjectRef(campaignObject);
// workItem.setCampaignRef(campaignRef);
// workItem.getCampaignRef().asReferenceValue().setObject(campaignObject); // has to be done AFTER setCampaignRef in order to preserve the value!
// }
return workItems;
}
private ObjectFilter getReviewerAndEnabledFilter(String reviewerOid) throws SchemaException {
return QueryBuilder.queryFor(AccessCertificationCaseType.class, prismContext)
.exists(F_WORK_ITEM)
.block()
.item(F_ASSIGNEE_REF).ref(reviewerOid, UserType.COMPLEX_TYPE)
.and().item(F_CLOSE_TIMESTAMP).isNull()
.endBlock()
.buildFilter();
}
private ObjectFilter getReviewerAndEnabledFilterForWI(MidPointPrincipal principal) throws SchemaException {
if (principal != null) {
return QueryUtils.filterForAssignees(
QueryBuilder.queryFor(AccessCertificationWorkItemType.class, prismContext),
principal,
OtherPrivilegesLimitationType.F_CERTIFICATION_WORK_ITEMS)
.and().item(F_CLOSE_TIMESTAMP).isNull()
.buildFilter();
} else {
return QueryBuilder.queryFor(AccessCertificationWorkItemType.class, prismContext)
.item(F_CLOSE_TIMESTAMP).isNull()
.buildFilter();
}
}
// TODO get work items for reviewer/campaign
public List<AccessCertificationCaseType> getCasesForReviewer(AccessCertificationCampaignType campaign,
String reviewerOid, Task task, OperationResult result) throws SchemaException {
ObjectFilter filter = getReviewerAndEnabledFilter(reviewerOid);
return searchCases(campaign.getOid(), ObjectQuery.createObjectQuery(filter), null, result);
}
public AccessCertificationCaseType getCase(String campaignOid, long caseId, Task task, OperationResult result) throws SchemaException, SecurityViolationException {
ObjectFilter filter = AndFilter.createAnd(
InOidFilter.createOwnerHasOidIn(campaignOid),
InOidFilter.createInOid(String.valueOf(caseId))
);
ObjectQuery query = ObjectQuery.createObjectQuery(filter);
List<AccessCertificationCaseType> caseList = repositoryService.searchContainers(AccessCertificationCaseType.class, query, null, result);
if (caseList.isEmpty()) {
return null;
} else if (caseList.size() == 1) {
return caseList.get(0);
} else {
throw new IllegalStateException("More than one certification case with ID " + caseId + " in campaign " + campaignOid);
}
}
public List<AccessCertificationCaseType> selectOpenCasesForReviewer(List<AccessCertificationCaseType> caseList, String reviewerOid) {
List<AccessCertificationCaseType> rv = new ArrayList<>();
cases: for (AccessCertificationCaseType aCase : caseList) {
for (AccessCertificationWorkItemType workItem : aCase.getWorkItem()) {
if (workItem.getCloseTimestamp() == null) {
for (ObjectReferenceType reviewerRef : workItem.getAssigneeRef()) {
if (reviewerOid.equals(reviewerRef.getOid())) {
rv.add(aCase.clone());
continue cases;
}
}
}
}
}
return rv;
}
}