/*
* JBoss, Home of Professional Open Source
* Copyright 2008-12, Red Hat Middleware LLC, and others contributors as indicated
* by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.savara.bpmn2.internal.generation.components;
import org.savara.bpmn2.internal.generation.BPMN2GenerationException;
import org.savara.bpmn2.model.TServiceTask;
import org.scribble.protocol.model.Interaction;
/**
* This class represents a selection of states within a
* BPMN state machine.
*
*/
public class ServiceInvocationActivity extends AbstractBPMNActivity {
private boolean _completed=false;
private ServiceTaskActivity _serviceTaskState=null;
private BPMNActivity _junctionState=null;
private java.util.Map<BPMNActivity, BoundaryEvent> _faults=
new java.util.HashMap<BPMNActivity, BoundaryEvent>();
/**
* This constructor initializes the choice state.
*
* @param choice The choice
* @param parent The parent BPMN state
* @param model The BPMN model
*/
public ServiceInvocationActivity(Interaction request, BPMNActivity parent,
org.savara.bpmn2.internal.generation.BPMN2ModelFactory model,
org.savara.bpmn2.internal.generation.BPMN2NotationFactory notation)
throws BPMN2GenerationException {
super(parent, model, notation);
initialize(request);
}
/**
* This method performs the initialization of the
* choice state.
*
* @param elem The choice
* @throws BPMN2GenerationException Failed to initialize
*/
protected void initialize(Interaction req) throws BPMN2GenerationException {
// Create choice state
_serviceTaskState = new ServiceTaskActivity(req, this,
getModelFactory(), getNotationFactory());
}
/**
* {@inheritDoc}
*/
protected void addChildState(BPMNActivity child) {
// Only create a junction if a sequence being created, which indicates a choice
// following the initial send
if (_junctionState == null && child instanceof SequenceActivity) {
// Create junction state
Object junctionState=getModelFactory().createEventBasedXORGateway(getContainer(), true);
_junctionState = new JunctionActivity(junctionState, this,
getModelFactory(), getNotationFactory());
}
super.addChildState(child);
}
public TServiceTask getServiceTask() {
return(_serviceTaskState.getServiceTask());
}
public void register(BPMNActivity act, BoundaryEvent be) {
_faults.put(act, be);
}
/**
* This method indicates that the BPMN state for the
* child nodes is complete.
*
*/
public void childrenComplete() {
if (_completed == false) {
// Move the junction state to the end of the list
if (getChildStates().remove(_junctionState)) {
getChildStates().add(_junctionState);
}
if (_junctionState == null) {
java.util.List<BPMNActivity> children=new java.util.Vector<BPMNActivity>();
while (getChildStates().size() > 1) {
BPMNActivity act=(BPMNActivity)getChildStates().get(1);
// Move to the parent of the service invocation activity
getChildStates().remove(1);
children.add(act);
}
if (children.size() > 0) {
promote(children, (AbstractBPMNActivity)getParent(), this);
}
setWidth(_serviceTaskState.getWidth());
setHeight(_serviceTaskState.getHeight());
} else {
int width=_serviceTaskState.getWidth()+_junctionState.getWidth()+
(2 * HORIZONTAL_GAP);
int height=0;
// Join the child state vertex with transitions
int maxwidth=0;
BPMNActivity normalPath=null;
for (int i=1; i < getChildStates().size()-1; i++) {
BPMNActivity umls=(BPMNActivity)getChildStates().get(i);
if (!_faults.containsKey(umls) && i > 1) {
normalPath = umls;
}
height += umls.getHeight();
if (i != 1) {
height += VERTICAL_GAP;
}
if (umls.getWidth() > maxwidth) {
maxwidth = umls.getWidth();
}
}
if (normalPath != null) {
// Move normal path to be first
getChildStates().remove(normalPath);
getChildStates().add(1, normalPath);
}
width += maxwidth;
if (height < _serviceTaskState.getHeight()) {
height = _serviceTaskState.getHeight();
}
if (height < _junctionState.getHeight()) {
height = _junctionState.getHeight();
}
setWidth(width);
setHeight(height);
adjustWidth(width);
}
_completed = true;
}
}
public void calculatePosition(int x, int y) {
int cury=y;
int midy=y+(getHeight()/2);
setX(x);
setY(y);
int boundaryCount=0;
for (int i=1; i < getChildStates().size()-1; i++) {
BPMNActivity act=(BPMNActivity)getChildStates().get(i);
act.calculatePosition(x+_serviceTaskState.getWidth()+HORIZONTAL_GAP, cury);
cury += (act.getHeight()+VERTICAL_GAP);
BoundaryEvent be=_faults.get(act);
if (be != null) {
be.calculatePosition(x+(30*boundaryCount++), midy+(_serviceTaskState.getHeight()/2)-15);
}
}
_serviceTaskState.calculatePosition(x, midy-(_serviceTaskState.getHeight()/2));
if (_junctionState != null) {
_junctionState.calculatePosition(x+getWidth()-
_junctionState.getWidth(),
midy-(_junctionState.getHeight()/2));
}
}
/**
* This method returns the start node for the activites
* represented by this BPMN activity implementation.
*
* @return The starting node
*/
public Object getStartNode() {
return(_serviceTaskState.getStartNode());
}
/**
* This method returns the end node for the activities
* represented by this BPMN activity implementation.
*
* @return The ending node
*/
public Object getEndNode() {
return(_junctionState == null ? _serviceTaskState.getEndNode() : _junctionState.getEndNode());
}
/**
* This method returns the start state.
*
* @return The start state
*/
public BPMNActivity getStartState() {
return(_serviceTaskState);
}
/**
* This method returns the end state.
*
* @return The end state
*/
public BPMNActivity getEndState() {
return(_junctionState == null ? _serviceTaskState : _junctionState);
}
public void adjustWidth(int width) {
if (_junctionState == null) {
setWidth(width);
} else {
int extrawidth=_serviceTaskState.getWidth()+_junctionState.getWidth()+
(2 * HORIZONTAL_GAP);
setWidth(width);
// Adjust child widths
for (int i=1; i < getChildStates().size()-1; i++) {
BPMNActivity umls=(BPMNActivity)getChildStates().get(i);
umls.adjustWidth(width-extrawidth);
}
}
}
public void draw(Object parent) {
// Construct notation
for (int i=0; i < getChildStates().size(); i++) {
BPMNActivity act=(BPMNActivity)getChildStates().get(i);
act.draw(parent);
}
if (_junctionState != null) {
// Construct sequence links
for (int i=1; i < getChildStates().size(); i++) {
BPMNActivity act=(BPMNActivity)getChildStates().get(i);
if (act != _junctionState) {
BoundaryEvent be=_faults.get(act);
if (be != null) {
be.draw(parent);
if (act.getStartState() != null) {
be.transitionTo(act, null, parent);
} else {
be.transitionTo(_junctionState, null, parent);
}
} else {
if (act.getStartState() != null) {
getStartState().transitionTo(act, null, parent);
} else {
getStartState().transitionTo(_junctionState, null, parent);
}
}
if (act.getEndState() != null) {
act.getEndState().transitionTo(_junctionState, null, parent);
}
}
}
}
}
}