/jbpm-flow/src/main/java/org/jbpm/workflow/core/node/Split.java

https://github.com/mariofusco/jbpm · Java · 187 lines · 121 code · 25 blank · 41 comment · 32 complexity · 3eea2d586e8dcd8c3353230f8b13f08a 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.core.node;
  17. import java.util.Collections;
  18. import java.util.Map;
  19. import org.jbpm.workflow.core.Constraint;
  20. import org.jbpm.workflow.core.impl.ConnectionRef;
  21. import org.jbpm.workflow.core.impl.NodeImpl;
  22. import org.kie.api.definition.process.Connection;
  23. /**
  24. * Default implementation of a split node.
  25. *
  26. * @author <a href="mailto:kris_verlaenen@hotmail.com">Kris Verlaenen</a>
  27. */
  28. public class Split extends NodeImpl implements Constrainable {
  29. public static final int TYPE_UNDEFINED = 0;
  30. /**
  31. * All outgoing connections of a split of this type are triggered
  32. * when its incoming connection has been triggered. A split of this
  33. * type should have no constraints linked to any of its outgoing
  34. * connections.
  35. */
  36. public static final int TYPE_AND = 1;
  37. /**
  38. * Exactly one outgoing connection of a split of this type is triggered
  39. * when its incoming connection has been triggered. Which connection
  40. * is based on the constraints associated with each of the connections:
  41. * the connection with the highest priority whose constraint is satisfied
  42. * is triggered.
  43. */
  44. public static final int TYPE_XOR = 2;
  45. /**
  46. * One or multiple outgoing connections of a split of this type are
  47. * triggered when its incoming connection has been triggered. Which
  48. * connections is based on the constraints associated with each of the
  49. * connections: all connections whose constraint is satisfied are
  50. * triggered.
  51. */
  52. public static final int TYPE_OR = 3;
  53. public static final int TYPE_XAND = 4;
  54. private static final long serialVersionUID = 510l;
  55. private int type;
  56. // private Map<ConnectionRef, Constraint> constraints = new HashMap<ConnectionRef, Constraint>();
  57. public Split() {
  58. this.type = TYPE_UNDEFINED;
  59. }
  60. public Split(final int type) {
  61. this.type = type;
  62. }
  63. public void setType(final int type) {
  64. this.type = type;
  65. }
  66. public int getType() {
  67. return this.type;
  68. }
  69. public boolean isDefault(final Connection connection) {
  70. if ( connection == null ) {
  71. throw new IllegalArgumentException( "connection is null" );
  72. }
  73. if ( this.type == TYPE_OR || this.type == TYPE_XOR ) {
  74. ConnectionRef ref = new ConnectionRef(connection.getTo().getId(), connection.getToType());
  75. Constraint constraint = this.constraints.get(ref);
  76. String defaultConnection = (String) getMetaData().get("Default");
  77. String connectionId = (String) connection.getMetaData().get("UniqueId");
  78. if (constraint != null) {
  79. return constraint.isDefault();
  80. } else if (constraint == null && connectionId.equals(defaultConnection)) {
  81. return true;
  82. } else {
  83. return false;
  84. }
  85. }
  86. throw new UnsupportedOperationException( "Constraints are " +
  87. "only supported with XOR or OR split types, not with: " + getType() );
  88. }
  89. public Constraint getConstraint(final Connection connection) {
  90. if ( connection == null ) {
  91. throw new IllegalArgumentException( "connection is null" );
  92. }
  93. if ( this.type == TYPE_OR || this.type == TYPE_XOR ) {
  94. ConnectionRef ref = new ConnectionRef(connection.getTo().getId(), connection.getToType());
  95. return this.constraints.get(ref);
  96. }
  97. throw new UnsupportedOperationException( "Constraints are " +
  98. "only supported with XOR or OR split types, not with: " + getType() );
  99. }
  100. public Constraint internalGetConstraint(final ConnectionRef ref) {
  101. return this.constraints.get(ref);
  102. }
  103. public void setConstraint(final Connection connection,
  104. final Constraint constraint) {
  105. if ( this.type == TYPE_OR || this.type == TYPE_XOR ) {
  106. if ( connection == null ) {
  107. throw new IllegalArgumentException( "connection is null" );
  108. }
  109. if (!getDefaultOutgoingConnections().contains(connection)) {
  110. throw new IllegalArgumentException("connection is unknown:" + connection);
  111. }
  112. addConstraint(
  113. new ConnectionRef(connection.getTo().getId(), connection.getToType()),
  114. constraint);
  115. } else {
  116. throw new UnsupportedOperationException( "Constraints are " +
  117. "only supported with XOR or OR split types, not with type:" + getType() );
  118. }
  119. }
  120. public void addConstraint(ConnectionRef connectionRef, Constraint constraint) {
  121. if (connectionRef == null) {
  122. throw new IllegalArgumentException(
  123. "A split node only accepts constraints linked to a connection");
  124. }
  125. this.constraints.put(connectionRef, constraint);
  126. }
  127. public Map<ConnectionRef, Constraint> getConstraints() {
  128. return Collections.unmodifiableMap( this.constraints );
  129. }
  130. public void validateAddIncomingConnection(final String type, final Connection connection) {
  131. super.validateAddIncomingConnection(type, connection);
  132. if (!org.jbpm.workflow.core.Node.CONNECTION_DEFAULT_TYPE.equals(type)) {
  133. throw new IllegalArgumentException(
  134. "This type of node [" + connection.getTo().getMetaData().get("UniqueId") + ", " + connection.getTo().getName()
  135. + "] only accepts default incoming connection type!");
  136. }
  137. if (!getIncomingConnections(org.jbpm.workflow.core.Node.CONNECTION_DEFAULT_TYPE).isEmpty()) {
  138. throw new IllegalArgumentException(
  139. "This type of node [" + connection.getTo().getMetaData().get("UniqueId") + ", " + connection.getTo().getName()
  140. + "] cannot have more than one incoming connection!");
  141. }
  142. }
  143. public void validateAddOutgoingConnection(final String type, final Connection connection) {
  144. super.validateAddOutgoingConnection(type, connection);
  145. if (!org.jbpm.workflow.core.Node.CONNECTION_DEFAULT_TYPE.equals(type)) {
  146. throw new IllegalArgumentException(
  147. "This type of node [" + connection.getFrom().getMetaData().get("UniqueId") + ", " + connection.getFrom().getName()
  148. + "] only accepts default outgoing connection type!");
  149. }
  150. }
  151. public void removeOutgoingConnection(final String type, final Connection connection) {
  152. super.removeOutgoingConnection(type, connection);
  153. removeConstraint(connection);
  154. }
  155. public void removeConstraint(Connection connection) {
  156. ConnectionRef ref = new ConnectionRef(connection.getTo().getId(), connection.getToType());
  157. internalRemoveConstraint(ref);
  158. }
  159. public void internalRemoveConstraint(ConnectionRef ref) {
  160. this.constraints.remove(ref);
  161. }
  162. }