Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JBPM-5370 - Administration service for processes and tasks - services… #642

Merged
merged 1 commit into from
Oct 26, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* Copyright 2016 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.
* 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 org.jbpm.process.instance.command;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;

import org.jbpm.process.instance.timer.TimerInstance;

@XmlRootElement(name = "relative-update-timer-command")
@XmlAccessorType(XmlAccessType.NONE)
public class RelativeUpdateTimerCommand extends UpdateTimerCommand {

private static final long serialVersionUID = -8252686458877022330L;

public RelativeUpdateTimerCommand(long processInstanceId, String timerName, long delay) {
this(processInstanceId, timerName, delay, 0, 0);
}

public RelativeUpdateTimerCommand(long processInstanceId, String timerName, long period, int repeatLimit) {
this(processInstanceId, timerName, 0, period, repeatLimit);
}

public RelativeUpdateTimerCommand(long processInstanceId, String timerName, long delay, long period, int repeatLimit) {
super(processInstanceId, timerName, delay, period, repeatLimit);
}

public RelativeUpdateTimerCommand(long processInstanceId, long timerId, long period, int repeatLimit) {
super(processInstanceId, timerId, period, repeatLimit);
}

public RelativeUpdateTimerCommand(long processInstanceId, long timerId, long delay, long period, int repeatLimit) {
super(processInstanceId, timerId, delay, period, repeatLimit);
}

public RelativeUpdateTimerCommand(long processInstanceId, long timerId, long delay) {
super(processInstanceId, timerId, delay);
}

protected long calculateDelay(long delay, TimerInstance timer) {
return delay * 1000;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,32 +38,39 @@
import org.kie.api.runtime.process.NodeInstance;
import org.kie.internal.command.Context;
import org.kie.internal.command.ProcessInstanceIdCommand;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@XmlRootElement(name = "update-timer-command")
@XmlAccessorType(XmlAccessType.NONE)
public class UpdateTimerCommand implements GenericCommand<Void>, ProcessInstanceIdCommand {

private static final long serialVersionUID = -8252686458877022330L;
private static final Logger logger = LoggerFactory.getLogger(UpdateTimerCommand.class);

@XmlElement
@XmlSchemaType(name = "long")
private long processInstanceId;
protected long processInstanceId;

@XmlElement
@XmlSchemaType(name = "long")
protected long timerId;

@XmlElement
@XmlSchemaType(name = "string")
private String timerName;
protected String timerName;

@XmlElement
@XmlSchemaType(name = "long")
private long delay;
protected long delay;

@XmlElement
@XmlSchemaType(name = "long")
private long period;
protected long period;

@XmlElement
@XmlSchemaType(name = "int")
private int repeatLimit;
protected int repeatLimit;

public UpdateTimerCommand(long processInstanceId, String timerName, long delay) {
this(processInstanceId, timerName, delay, 0, 0);
Expand All @@ -76,64 +83,68 @@ public UpdateTimerCommand(long processInstanceId, String timerName, long period,
public UpdateTimerCommand(long processInstanceId, String timerName, long delay, long period, int repeatLimit) {
this.processInstanceId = processInstanceId;
this.timerName = timerName;
this.timerId = -1;
this.delay = delay;
this.period = period;
this.repeatLimit = repeatLimit;
}

public UpdateTimerCommand(long processInstanceId, long timerId, long delay) {
this(processInstanceId, timerId, delay, 0, 0);
}

public UpdateTimerCommand(long processInstanceId, long timerId, long period, int repeatLimit) {
this(processInstanceId, timerId, 0, period, repeatLimit);
}

public UpdateTimerCommand(long processInstanceId, long timerId, long delay, long period, int repeatLimit) {
this.processInstanceId = processInstanceId;
this.timerId = timerId;
this.delay = delay;
this.period = period;
this.repeatLimit = repeatLimit;
}

@Override
public Void execute(Context context) {
logger.debug("About to cancel timer in process instance {} by name '{}' or id {}", processInstanceId, timerName, timerId);
KieSession kieSession = ((KnowledgeCommandContext) context).getKieSession();
TimerManager tm = getTimerManager(kieSession);

RuleFlowProcessInstance wfp = (RuleFlowProcessInstance) kieSession.getProcessInstance(processInstanceId);

if (wfp == null) {
throw new IllegalArgumentException("Process instance with id " + processInstanceId + " not found");
}
for (NodeInstance nodeInstance : wfp.getNodeInstances()) {
if (nodeInstance instanceof TimerNodeInstance) {
TimerNodeInstance tni = (TimerNodeInstance) nodeInstance;
if (tni.getNodeName().equals(timerName)) {
if (tni.getNodeName().equals(timerName) || tni.getTimerId() == timerId) {
TimerInstance timer = tm.getTimerMap().get(tni.getTimerId());

tm.cancelTimer(timer.getTimerId());
TimerInstance newTimer = new TimerInstance();

if (delay != 0) {
long diff = System.currentTimeMillis() - timer.getActivated().getTime();
newTimer.setDelay(delay * 1000 - diff);
}
newTimer.setPeriod(period);
newTimer.setRepeatLimit(repeatLimit);
newTimer.setTimerId(timer.getTimerId());
tm.registerTimer(newTimer, wfp);


TimerInstance newTimer = rescheduleTimer(timer, tm);
logger.debug("New timer {} about to be registered", newTimer);
tm.registerTimer(newTimer, wfp);
tni.internalSetTimerId(newTimer.getId());
logger.debug("New timer {} successfully registered", newTimer);

break;
}
} else if (nodeInstance instanceof StateBasedNodeInstance) {
StateBasedNodeInstance sbni = (StateBasedNodeInstance) nodeInstance;

if (sbni.getNodeName().equals(timerName)) {
List<Long> timerList = sbni.getTimerInstances();
List<Long> timerList = sbni.getTimerInstances();
if (sbni.getNodeName().equals(timerName) || timerList.contains(timerId)) {

if (timerList != null && timerList.size() == 1) {
TimerInstance timer = tm.getTimerMap().get(timerList.get(0));

tm.cancelTimer(timer.getTimerId());
TimerInstance newTimer = new TimerInstance();

if (delay != 0) {
long diff = System.currentTimeMillis() - timer.getActivated().getTime();
newTimer.setDelay(delay * 1000 - diff);
}
newTimer.setPeriod(period);
newTimer.setRepeatLimit(repeatLimit);
newTimer.setTimerId(timer.getTimerId());
tm.registerTimer(newTimer, wfp);

TimerInstance newTimer = rescheduleTimer(timer, tm);
logger.debug("New timer {} about to be registered", newTimer);
tm.registerTimer(newTimer, wfp);
timerList.clear();
timerList.add(newTimer.getId());

sbni.internalSetTimerInstances(timerList);
logger.debug("New timer {} successfully registered", newTimer);

}
break;
Expand All @@ -153,7 +164,7 @@ public Long getProcessInstanceId() {
return processInstanceId;
}

private TimerManager getTimerManager(KieSession ksession) {
protected TimerManager getTimerManager(KieSession ksession) {
KieSession internal = ksession;
if (ksession instanceof CommandBasedStatefulKnowledgeSession) {
internal = ((KnowledgeCommandContext) ((CommandBasedStatefulKnowledgeSession) ksession).getCommandService().getContext()).getKieSession();
Expand All @@ -166,4 +177,25 @@ public String toString() {
return "processInstance.updateTimer(" + timerName + ", " + delay + ", " + period + ", " + repeatLimit + ");";
}

protected long calculateDelay(long delay, TimerInstance timer) {
long diff = System.currentTimeMillis() - timer.getActivated().getTime();
return delay * 1000 - diff;
}

protected TimerInstance rescheduleTimer(TimerInstance timer, TimerManager tm) {
logger.debug("Found timer {} that is going to be canceled", timer);
tm.cancelTimer(timer.getTimerId());
logger.debug("Timer {} canceled successfully", timer);

TimerInstance newTimer = new TimerInstance();

if (delay != 0) {
newTimer.setDelay(calculateDelay(delay, timer));
}
newTimer.setPeriod(period);
newTimer.setRepeatLimit(repeatLimit);
newTimer.setTimerId(timer.getTimerId());

return newTimer;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@

import org.kie.api.definition.process.Node;
import org.kie.api.definition.process.NodeContainer;

import java.util.ArrayList;
import java.util.List;

import org.jbpm.process.core.impl.ProcessImpl;
import org.jbpm.workflow.core.WorkflowProcess;

Expand All @@ -43,7 +47,7 @@ protected NodeContainer createNodeContainer() {

public Node[] getNodes() {
return nodeContainer.getNodes();
}
}

public Node getNode(final long id) {
return nodeContainer.getNode(id);
Expand Down Expand Up @@ -95,4 +99,21 @@ public Integer getProcessType() {
return PROCESS_TYPE;
}

public List<Node> getNodesRecursively() {
List<Node> nodes = new ArrayList<>();

processNodeContainer(nodeContainer, nodes);

return nodes;
}

protected void processNodeContainer(org.jbpm.workflow.core.NodeContainer nodeContainer, List<Node> nodes) {

for (Node node : nodeContainer.getNodes()){
nodes.add(node);
if (node instanceof org.jbpm.workflow.core.NodeContainer) {
processNodeContainer((org.jbpm.workflow.core.NodeContainer) node, nodes);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@ public void triggerNode(long nodeId) {
org.jbpm.workflow.instance.NodeInstance nodeInstance = (org.jbpm.workflow.instance.NodeInstance)
((org.jbpm.workflow.instance.NodeInstanceContainer) getNodeInstanceContainer())
.getNodeInstance(getNode().getNodeContainer().getNode(nodeId));
triggerNodeInstance(nodeInstance, null);
triggerNodeInstance(nodeInstance, org.jbpm.workflow.core.Node.CONNECTION_DEFAULT_TYPE);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mswiderski what is the reason for changing this? I would expect the argument to indicate why the node was triggered, in this case the node is triggered explicitly by the user, not through an incoming connection, so wouldn't null be more adequate (to distinguish from incoming connection)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@krisv the reason is that some of the NodeInstances (e.g. SubProcessNodeInstance or TimerNodeInstance) throw exception if the connection is different than the default. So instead of fixing all the node instance to check if it's null I thought it's better to simply provide the default connection when retriggering.

}

public Context resolveContext(String contextId, Object param) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,14 @@ protected List<String> filterGroups(List<String> groups) {
}

return groups;
}

protected boolean isBusinessAdmin(String userId, List<OrganizationalEntity> businessAdmins, TaskContext context) {
List<String> usersGroup = context.getUserGroupCallback().getGroupsForUser(userId, null, null);
usersGroup.add(userId);

return businessAdmins.stream().anyMatch(oe -> usersGroup.contains(oe.getId()));

}

@Override
Expand Down