/jbpm-flow/src/main/java/org/jbpm/workflow/instance/node/JoinInstance.java

https://github.com/michelpohle/jbpm · Java · 162 lines · 125 code · 14 blank · 23 comment · 29 complexity · 9810b178fb10561efcf05dcdfac4be25 MD5 · raw file

  1. /**
  2. * Copyright 2005 JBoss Inc
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package org.jbpm.workflow.instance.node;
  17. import java.util.HashMap;
  18. import java.util.Map;
  19. import org.drools.definition.process.Connection;
  20. import org.drools.runtime.process.NodeInstance;
  21. import org.jbpm.process.core.context.variable.VariableScope;
  22. import org.jbpm.process.instance.context.variable.VariableScopeInstance;
  23. import org.jbpm.workflow.core.node.Join;
  24. import org.jbpm.workflow.instance.impl.NodeInstanceImpl;
  25. /**
  26. * Runtime counterpart of a join node.
  27. *
  28. * @author <a href="mailto:kris_verlaenen@hotmail.com">Kris Verlaenen</a>
  29. */
  30. public class JoinInstance extends NodeInstanceImpl {
  31. private static final long serialVersionUID = 510l;
  32. private Map<Long, Integer> triggers = new HashMap<Long, Integer>();
  33. protected Join getJoin() {
  34. return (Join) getNode();
  35. }
  36. public void internalTrigger(final NodeInstance from, String type) {
  37. if (!org.jbpm.workflow.core.Node.CONNECTION_DEFAULT_TYPE.equals(type)) {
  38. throw new IllegalArgumentException(
  39. "An ActionNode only accepts default incoming connections!");
  40. }
  41. final Join join = getJoin();
  42. switch ( join.getType() ) {
  43. case Join.TYPE_XOR :
  44. triggerCompleted();
  45. break;
  46. case Join.TYPE_AND :
  47. Integer count = (Integer) this.triggers.get( from.getNodeId() );
  48. if ( count == null ) {
  49. this.triggers.put( from.getNodeId(),
  50. 1 );
  51. } else {
  52. this.triggers.put( from.getNodeId(),
  53. count.intValue() + 1 );
  54. }
  55. if (checkAllActivated()) {
  56. decreaseAllTriggers();
  57. triggerCompleted();
  58. }
  59. break;
  60. case Join.TYPE_DISCRIMINATOR :
  61. boolean triggerCompleted = triggers.isEmpty();
  62. triggers.put( from.getNodeId(), new Integer( 1 ) );
  63. if (checkAllActivated()) {
  64. resetAllTriggers();
  65. }
  66. if (triggerCompleted) {
  67. triggerCompleted();
  68. }
  69. break;
  70. case Join.TYPE_N_OF_M :
  71. count = (Integer) this.triggers.get( from.getNodeId() );
  72. if ( count == null ) {
  73. this.triggers.put( from.getNodeId(),
  74. 1 );
  75. } else {
  76. this.triggers.put( from.getNodeId(),
  77. count.intValue() + 1 );
  78. }
  79. int counter = 0;
  80. for (final Connection connection: getJoin().getDefaultIncomingConnections()) {
  81. if ( this.triggers.get( connection.getFrom().getId() ) != null ) {
  82. counter++;
  83. }
  84. }
  85. String n = join.getN();
  86. Integer number = null;
  87. if (n.startsWith("#{") && n.endsWith("}")) {
  88. n = n.substring(2, n.length() - 1);
  89. VariableScopeInstance variableScopeInstance = (VariableScopeInstance)
  90. resolveContextInstance(VariableScope.VARIABLE_SCOPE, n);
  91. if (variableScopeInstance == null) {
  92. throw new IllegalArgumentException(
  93. "Could not find variable " + n + " when executing join.");
  94. }
  95. Object value = variableScopeInstance.getVariable(n);
  96. if (value instanceof Number) {
  97. number = ((Number) value).intValue();
  98. } else {
  99. throw new IllegalArgumentException(
  100. "Variable " + n + " did not return a number when executing join: " + value);
  101. }
  102. } else {
  103. number = new Integer(n);
  104. }
  105. if (counter >= number) {
  106. resetAllTriggers();
  107. triggerCompleted();
  108. }
  109. break;
  110. default :
  111. throw new IllegalArgumentException( "Illegal join type " + join.getType() );
  112. }
  113. }
  114. private boolean checkAllActivated() {
  115. // check whether all parent nodes have been triggered
  116. for (final Connection connection: getJoin().getDefaultIncomingConnections()) {
  117. if ( this.triggers.get( connection.getFrom().getId() ) == null ) {
  118. return false;
  119. }
  120. }
  121. return true;
  122. }
  123. private void decreaseAllTriggers() {
  124. // decrease trigger count for all incoming connections
  125. for (final Connection connection: getJoin().getDefaultIncomingConnections()) {
  126. final Integer count = (Integer) this.triggers.get( connection.getFrom().getId() );
  127. if ( count.intValue() == 1 ) {
  128. this.triggers.remove( connection.getFrom().getId() );
  129. } else {
  130. this.triggers.put( connection.getFrom().getId(),
  131. count.intValue() - 1 );
  132. }
  133. }
  134. }
  135. private void resetAllTriggers() {
  136. triggers.clear();
  137. }
  138. public void triggerCompleted() {
  139. // join nodes are only removed from the container when they contain no more state
  140. triggerCompleted(org.jbpm.workflow.core.Node.CONNECTION_DEFAULT_TYPE, triggers.isEmpty());
  141. }
  142. public Map<Long, Integer> getTriggers() {
  143. return triggers;
  144. }
  145. public void internalSetTriggers(Map<Long, Integer> triggers) {
  146. this.triggers = triggers;
  147. }
  148. }