/*
* JBoss, Home of Professional Open Source
* Copyright 2012, 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.protocol.internal.aggregator;
import java.util.logging.Logger;
import org.savara.protocol.internal.aggregator.LocalProtocolUnit.ActivityCursor;
import org.savara.protocol.model.util.ChoiceUtil;
import org.scribble.common.model.Annotation;
import org.scribble.protocol.model.Activity;
import org.scribble.protocol.model.Block;
import org.scribble.protocol.model.Choice;
import org.scribble.protocol.model.Interaction;
import org.scribble.protocol.model.Introduces;
import org.scribble.protocol.model.MessageSignature;
import org.scribble.protocol.model.ParameterDefinition;
import org.scribble.protocol.model.ProtocolModel;
import org.scribble.protocol.model.Repeat;
import org.scribble.protocol.model.Role;
public class GlobalProtocolUnit {
private static final Logger LOG=Logger.getLogger(GlobalProtocolUnit.class.getName());
private Container _container=null;
private ProtocolModel _model=null;
public GlobalProtocolUnit(ProtocolModel model) {
_model = model;
_container = new Container(model.getProtocol().getBlock());
}
public void process(Activity send, ActivityCursor sendCursor,
Activity receive, ActivityCursor receiveCursor) {
Container container=sendCursor.getContainer();
if (container == null) {
container = receiveCursor.getContainer();
if (container == null) {
sendCursor.setContainer(_container);
receiveCursor.setContainer(_container);
container = _container;
} else {
sendCursor.setContainer(container);
}
} else if (receiveCursor.getContainer() == null) {
receiveCursor.setContainer(container);
}
if (send instanceof Interaction && receive instanceof Interaction) {
Interaction interaction=createInteraction((Interaction)send, (Interaction)receive);
container.add(interaction);
} else if (send instanceof Choice && receive instanceof Choice) {
Choice choice=new Choice();
choice.setRole(new Role(((Choice)send).getRole()));
container.add(choice);
// Create a container for each send path, and associate a
// cursor from the local projection with the container
for (Block sendb : ((Choice)send).getPaths()) {
Block newblock=new Block();
Container newcontainer=container.createContainer(newblock);
choice.getPaths().add(newblock);
ActivityCursor sendChildCursor=sendCursor.createCursor(sendb);
sendChildCursor.setContainer(newcontainer);
}
// Just create a cursor for each choice path, but don't assign a
// container yet, as we don't know which order the paths will
// be processed. They will become attached to a container when
// the first 'send' match is made.
for (Block recvb : ((Choice)receive).getPaths()) {
receiveCursor.createCursor(recvb);
}
}
}
public void process(Activity individual, ActivityCursor individualCursor) {
Container container=individualCursor.getContainer();
if (container == null) {
individualCursor.setContainer(_container);
container = _container;
}
// Check if receive activity from client
if (individual instanceof Interaction) {
Interaction interaction=createInteraction(
individualCursor.getRole(),
(Interaction)individual);
container.add(interaction);
} else if (individual instanceof Introduces) {
Introduces introduces=new Introduces((Introduces)individual);
// TODO: Temporary - need to add to specific path
container.add(introduces);
// Check if process model has an initial role
if (_model.getProtocol().getParameterDefinitions().size() == 0) {
ParameterDefinition pd=new ParameterDefinition();
pd.setName(introduces.getIntroducer().getName());
_model.getProtocol().getParameterDefinitions().add(pd);
}
} else if (individual instanceof Choice) {
if (ChoiceUtil.isDecisionMaker((Choice)individual)) {
Choice choice=new Choice();
choice.setRole(new Role(((Choice)individual).getRole()));
container.add(choice);
// Create a container for each send path, and associate a
// cursor from the local projection with the container
for (Block sendb : ((Choice)individual).getPaths()) {
Block newblock=new Block();
Container newcontainer=container.createContainer(newblock);
choice.getPaths().add(newblock);
ActivityCursor sendChildCursor=individualCursor.createCursor(sendb);
sendChildCursor.setContainer(newcontainer);
}
} else {
// Just create a cursor for each choice path, but don't assign a
// container yet, as we don't know which order the paths will
// be processed. They will become attached to a container when
// the first 'send' match is made.
// (Comment copied from matched process() above)
for (Block recvb : ((Choice)individual).getPaths()) {
individualCursor.createCursor(recvb);
}
}
}
}
public void processRepetition(java.util.Collection<ActivityCursor> cursors) {
// Find container
Container container=null;
for (ActivityCursor cursor : cursors) {
if (container == null) {
container = cursor.getContainer();
} else if (cursor.getContainer() != null &&
container != cursor.getContainer()) {
LOG.severe("Repeat cursors have different containers");
}
}
if (container == null) {
container = _container;
}
Repeat repeat=new Repeat();
container.add(repeat);
Block newblock=new Block();
Container newcontainer=container.createContainer(newblock);
repeat.setBlock(newblock);
for (ActivityCursor cursor : cursors) {
ActivityCursor repeatCursor=cursor.createCursor(((Repeat)cursor.peek()).getBlock());
repeatCursor.setContainer(newcontainer);
}
}
protected Interaction createInteraction(Interaction send, Interaction receive) {
Interaction ret=new Interaction();
ret.setMessageSignature(new MessageSignature(send.getMessageSignature()));
ret.setFromRole(new Role(receive.getFromRole()));
for (Role r : send.getToRoles()) {
ret.getToRoles().add(new Role(r));
}
// Copy send annotations
for (Annotation an : send.getAnnotations()) {
if (an instanceof org.savara.common.model.annotation.Annotation) {
Annotation copy=new org.savara.common.model.annotation.Annotation(
(org.savara.common.model.annotation.Annotation)an);
ret.getAnnotations().add(copy);
}
}
// Merge annotations from receive??? Not for now.
//for (Annotation an : receive.getAnnotations()) {
//}
return(ret);
}
protected Interaction createInteraction(Role role, Interaction interaction) {
Interaction ret=new Interaction();
ret.setMessageSignature(new MessageSignature(interaction.getMessageSignature()));
if (interaction.getFromRole() != null) {
ret.setFromRole(new Role(interaction.getFromRole()));
ret.getToRoles().add(role);
} else {
ret.setFromRole(role);
for (Role r : interaction.getToRoles()) {
ret.getToRoles().add(new Role(r));
}
}
// Copy send annotations
for (Annotation an : interaction.getAnnotations()) {
if (an instanceof org.savara.common.model.annotation.Annotation) {
Annotation copy=new org.savara.common.model.annotation.Annotation(
(org.savara.common.model.annotation.Annotation)an);
ret.getAnnotations().add(copy);
}
}
return(ret);
}
public class Container {
private Block _block=null;
private java.util.List<Container> _children=new java.util.Vector<Container>();
public Container(Block b) {
_block = b;
}
public void add(Activity act) {
//if (_children.size() > 0) {
// TODO: Do we need to add activity to children instead???
//LOG.severe("NOT YET SUPPORTED: Adding activity '"+act+"' when children are defined");
//} else {
_block.add(act);
//}
}
public Container createContainer(Block b) {
Container ret=new Container(b);
_children.add(ret);
return(ret);
}
public void remove(Container c) {
_children.remove(c);
}
}
}