/*
* This file is part of the WfMOpen project.
* Copyright (C) 2001-2003 Danet GmbH (www.danet.de), GS-AN.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* $Id: Receiver.java 2368 2007-05-03 21:58:25Z mlipp $
*
* $Log$
* Revision 1.2 2006/09/29 12:32:13 drmlipp
* Consistently using WfMOpen as projct name now.
*
* Revision 1.1.1.2 2004/08/18 15:17:38 drmlipp
* Update to 1.2
*
* Revision 1.8 2004/04/12 19:33:52 lipp
* Clarified application invocation interface.
*
* Revision 1.7 2004/03/20 21:08:44 lipp
* Added access to requesting processes' channels.
*
* Revision 1.6 2004/02/25 12:06:06 lipp
* Added some debugging info.
*
* Revision 1.5 2004/02/13 08:25:29 lipp
* Changed channel message data type to Map which is more appropriate.
*
* Revision 1.4 2004/02/06 10:25:46 lipp
* Finshed Receiver.
*
* Revision 1.3 2004/01/30 14:36:30 lipp
* Partial implementation of message receipt.
*
* Revision 1.2 2003/10/07 15:49:53 lipp
* Completed transmission sequence to activity.
*
* Revision 1.1 2003/10/06 20:43:22 lipp
* Continuing channel communication.
*
*/
package de.danet.an.workflow.tools.chabacc;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.rmi.RemoteException;
import de.danet.an.util.CollectionsUtil;
import de.danet.an.workflow.omgcore.CannotCompleteException;
import de.danet.an.workflow.omgcore.InvalidDataException;
import de.danet.an.workflow.api.Activity;
import de.danet.an.workflow.api.DefaultProcessData;
import de.danet.an.workflow.api.FormalParameter;
import de.danet.an.workflow.apix.ExtActivity;
import de.danet.an.workflow.apix.ExtProcess;
import de.danet.an.workflow.spis.aii.ApplicationNotStoppedException;
import de.danet.an.workflow.spis.aii.CannotExecuteException;
import de.danet.an.workflow.spis.aii.ToolAgent;
/**
* This class provides a tool that receives messages from a
* channel. The first argument must be of type string and identifies
* the channel.
*
* @author <a href="mailto:lipp@danet.de">Michael Lipp</a>
* @version $Revision: 2368 $
*/
public class Receiver implements ToolAgent {
private static final org.apache.commons.logging.Log logger
= org.apache.commons.logging.LogFactory.getLog(Receiver.class);
private Integer listenerIndex = null;
/**
* Creates an instance of <code>Receiver</code>
* with all attributes initialized to default values.
*/
public Receiver () {
}
/**
* Normally, the Receiver listens for data on a channel of the
* process it is invoked in. It is, however, also possible to send
* the data in a channel of its requesters. See the user manual
* for details.
* @param index used to determine the listener process, see
* user manual
*/
public void setListenerIndex (String index) {
listenerIndex = new Integer (index);
}
// Implementation of de.danet.an.workflow.spis.aii.ToolAgent
/* Comment copied from interface. */
public void invoke
(Activity activity, FormalParameter[] formalParameter, Map map)
throws CannotExecuteException, RemoteException {
String channel = (String)map.get(formalParameter[0].id());
if (logger.isDebugEnabled ()) {
logger.debug (activity + " wants message from channel " + channel);
}
ExtProcess proc
= (listenerIndex == null
? (ExtProcess)activity.container() : getListener (activity));
Map recvd = proc.lookForMessage (channel);
if (recvd == null) {
if (logger.isDebugEnabled ()) {
logger.debug
(activity + " waits for message on channel " + channel);
}
((ExtActivity)activity).waitOnChannel(proc.key(), channel);
return;
}
if (logger.isDebugEnabled ()) {
logger.debug
(activity + " found message "
+ CollectionsUtil.toString(recvd) + " on channel " + channel);
}
try {
activity.setResult (new DefaultProcessData (recvd));
activity.complete ();
} catch (CannotCompleteException e) {
logger.error
(activity + " receiving from channel "
+ "but cannot be completed?!: " + e.getMessage (), e);
throw new CannotExecuteException
("Receiving activity cannot be completed");
} catch (InvalidDataException e) {
logger.warn
(activity + " received invalid data from channel "
+ channel + ": " + e.getMessage (), e);
throw new CannotExecuteException (e.getMessage ());
}
}
private ExtProcess getListener (Activity act)
throws CannotExecuteException, RemoteException {
ExtProcess proc = (ExtProcess)act.container();
if (listenerIndex.intValue() > 0) {
for (int i = listenerIndex.intValue(); i > 0; i--) {
proc = (ExtProcess)proc.requestingProcess();
if (proc == null) {
throw new CannotExecuteException
(act + " does not have " + listenerIndex
+ " requesting anchestors");
}
}
} else {
List procs = new ArrayList ();
while (true) {
procs.add (0, proc);
proc = (ExtProcess)proc.requestingProcess();
if (proc == null) {
break;
}
}
try {
proc = (ExtProcess)procs.get (-listenerIndex.intValue());
} catch (IndexOutOfBoundsException e) {
throw new CannotExecuteException
("Subflow depth from root of " + act
+ " is less than " + -listenerIndex.intValue());
}
}
return proc;
}
/* Comment copied from interface. */
public void terminate(Activity activity)
throws ApplicationNotStoppedException {
}
}