/*
* Copyright 2017 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*
* 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 org.jbpm.services.task.assignment.impl.strategy;
import java.util.Collection;
import java.util.Date;
import java.util.Set;
import java.util.TreeSet;
import org.drools.core.ClassObjectFilter;
import org.kie.api.KieServices;
import org.kie.api.builder.KieScanner;
import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.rule.QueryResults;
import org.kie.api.task.TaskContext;
import org.kie.api.task.model.Task;
import org.kie.internal.task.api.assignment.Assignment;
import org.kie.internal.task.api.assignment.AssignmentStrategy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class BusinessRuleAssignmentStrategy implements AssignmentStrategy {
private static final Logger logger = LoggerFactory.getLogger(BusinessRuleAssignmentStrategy.class);
private static final String IDENTIFIER = "BusinessRule";
private boolean active = IDENTIFIER.equals(System.getProperty("org.jbpm.task.assignment.strategy"));
private String releaseId = System.getProperty("org.jbpm.task.assignment.rules.releaseId");
private String scannerInterval = System.getProperty("org.jbpm.task.assignment.rules.scan");
private KieServices kieServices = KieServices.Factory.get();
private KieContainer kieContainer;
private KieScanner kieScanner;
public BusinessRuleAssignmentStrategy() {
if (active) {
if (releaseId == null) {
throw new IllegalArgumentException("BusinessRule assignment strategy requires release id to be given via system property 'org.jbpm.task.assignment.rules.releaseId'");
}
String[] gav = releaseId.split(":");
logger.debug("Creating KieContainer for {} to be used for task assignments", releaseId);
this.kieContainer = kieServices.newKieContainer(kieServices.newReleaseId(gav[0], gav[1], gav[2]));
if (scannerInterval != null) {
Long pollingInterval = Long.parseLong(scannerInterval);
logger.debug("Scanner to be enabled for {} container with polling interval set to {}", kieContainer, pollingInterval);
this.kieScanner = this.kieServices.newKieScanner(kieContainer);
this.kieScanner.start(pollingInterval);
logger.debug("Scanner for container {} started at {}", kieContainer, new Date());
}
}
}
@Override
public String getIdentifier() {
return IDENTIFIER;
}
@SuppressWarnings("unchecked")
@Override
public Assignment apply(Task task, TaskContext context, String excludedUser) {
if (!active) {
logger.debug("{} strategy is not active", this);
return null;
}
logger.debug("Using rules to assign actual owner to task {}", task);
KieSession kieSession = this.kieContainer.newKieSession();
try {
context.loadTaskVariables(task);
kieSession.insert(task);
kieSession.fireAllRules();
Set<Assignment> assignments = new TreeSet<>();
String queryName = System.getProperty("org.jbpm.task.assignment.rules.query");
if (queryName != null) {
logger.debug("Query {} is going to be used to retrieve results from working memory", queryName);
QueryResults results = kieSession.getQueryResults(queryName);
results.forEach(row ->
assignments.add((Assignment)row.get("assignment")));
} else {
logger.debug("No query defined, retrieving all facts of type Assignment");
Collection<Assignment> results = (Collection<Assignment>) kieSession.getObjects(new ClassObjectFilter(Assignment.class));
assignments.addAll(results);
}
logger.debug("Rule evaluation completed with selected assignments of {}", assignments);
if (assignments.isEmpty()) {
logger.debug("No assignments found by BusinessRule strategy");
return null;
}
Assignment selected = assignments.iterator().next();
logger.debug("Selected assignment is {} for task {}", selected, task);
return selected;
} finally {
kieSession.dispose();
logger.debug("KieSession in BusinessRule disposed");
}
}
@Override
public String toString() {
return "BusinessRuleAssignmentStrategy [releaseId=" + releaseId + "]";
}
}