package won.bot.impl; import won.bot.framework.bot.base.EventBot; import won.bot.framework.bot.context.ParticipantCoordinatorBotContextWrapper; import won.bot.framework.eventbot.EventListenerContext; import won.bot.framework.eventbot.action.impl.facet.TwoPhaseCommitDeactivateOnCloseAction; import won.bot.framework.eventbot.action.impl.lifecycle.SignalWorkDoneAction; import won.bot.framework.eventbot.action.impl.needlifecycle.CreateNeedWithFacetsAction; import won.bot.framework.eventbot.action.impl.needlifecycle.DeactivateAllNeedsOfListAction; import won.bot.framework.eventbot.action.impl.wonmessage.ConnectFromListToListAction; import won.bot.framework.eventbot.action.impl.wonmessage.OpenConnectionAction; import won.bot.framework.eventbot.bus.EventBus; import won.bot.framework.eventbot.event.impl.lifecycle.ActEvent; import won.bot.framework.eventbot.event.impl.listener.FinishedEvent; import won.bot.framework.eventbot.event.impl.needlifecycle.NeedCreatedEvent; import won.bot.framework.eventbot.event.impl.needlifecycle.NeedDeactivatedEvent; import won.bot.framework.eventbot.event.impl.wonmessage.CloseFromOtherNeedEvent; import won.bot.framework.eventbot.event.impl.wonmessage.ConnectFromOtherNeedEvent; import won.bot.framework.eventbot.filter.impl.FinishedEventFilter; import won.bot.framework.eventbot.filter.impl.NeedUriInNamedListFilter; import won.bot.framework.eventbot.listener.BaseEventListener; import won.bot.framework.eventbot.listener.impl.ActionOnEventListener; import won.bot.framework.eventbot.listener.impl.ActionOnceAfterNEventsListener; import won.bot.framework.eventbot.listener.impl.WaitForNEventsListener; import won.protocol.model.FacetType; /** * User: Danijel * Date: 15.5.14. */ public class StandardTwoPhaseCommitBot extends EventBot{ protected final int noOfNeeds = 10; private static final long MILLIS_BETWEEN_MESSAGES = 100; //we use protected members so we can extend the class and //access the listeners for unit test assertions and stats // //we use BaseEventListener as their types so we can access the generic //functionality offered by that class protected BaseEventListener needConnector; protected BaseEventListener autoOpener; protected BaseEventListener participantDeactivator; protected BaseEventListener workDoneSignaller; protected BaseEventListener creationWaiter; protected BaseEventListener coordinatorDeactivator; protected BaseEventListener participantNeedCreator; protected BaseEventListener coordinatorNeedCreator; @Override protected void initializeEventListeners() { EventListenerContext ctx = getEventListenerContext(); EventBus bus = getEventBus(); ParticipantCoordinatorBotContextWrapper botContextWrapper = (ParticipantCoordinatorBotContextWrapper) getBotContextWrapper(); //create needs every trigger execution until noOfNeeds are created this.participantNeedCreator = new ActionOnEventListener( ctx, "participantCreator", new CreateNeedWithFacetsAction(ctx, botContextWrapper.getParticipantListName(), FacetType.ParticipantFacet.getURI()), noOfNeeds - 1 ); bus.subscribe(ActEvent.class, this.participantNeedCreator); //when done, create one coordinator need this.coordinatorNeedCreator = new ActionOnEventListener( ctx, "coordinatorCreator", new FinishedEventFilter(participantNeedCreator), new CreateNeedWithFacetsAction(ctx, botContextWrapper.getCoordinatorListName(), FacetType.CoordinatorFacet.getURI()), 1 ); bus.subscribe(FinishedEvent.class, this.coordinatorNeedCreator); //wait for N NeedCreatedEvents creationWaiter = new WaitForNEventsListener(ctx, noOfNeeds); bus.subscribe(NeedCreatedEvent.class, creationWaiter); //when done, connect the participants to the coordinator this.needConnector = new ActionOnEventListener( ctx, "needConnector", new FinishedEventFilter(creationWaiter), new ConnectFromListToListAction(ctx, botContextWrapper.getCoordinatorListName(), botContextWrapper.getParticipantListName(), FacetType.CoordinatorFacet.getURI(), FacetType.ParticipantFacet.getURI(), MILLIS_BETWEEN_MESSAGES, "Hi!"), 1); bus.subscribe(FinishedEvent.class, this.needConnector); //add a listener that is informed of the connect/open events and that auto-opens //subscribe it to: // * connect events - so it responds with open // * open events - so it responds with open (if the open received was the first open, and we still need to accept the connection) this.autoOpener = new ActionOnEventListener(ctx,new NeedUriInNamedListFilter(ctx, botContextWrapper.getParticipantListName()), new OpenConnectionAction(ctx, "Hi!")); bus.subscribe(ConnectFromOtherNeedEvent.class, this.autoOpener); //after the last connect event, all connections are closed! this.participantDeactivator = new ActionOnEventListener( ctx, "participantDeactivator", new NeedUriInNamedListFilter(ctx, botContextWrapper.getParticipantListName()), new TwoPhaseCommitDeactivateOnCloseAction (ctx), noOfNeeds-1); bus.subscribe(CloseFromOtherNeedEvent.class, this.participantDeactivator); coordinatorDeactivator = new ActionOnEventListener(ctx, "coordinatorDeactivator", new FinishedEventFilter(participantDeactivator), new DeactivateAllNeedsOfListAction(ctx, botContextWrapper.getCoordinatorListName()), 1); bus.subscribe(FinishedEvent.class, coordinatorDeactivator); //add a listener that counts two NeedDeactivatedEvents and then tells the //framework that the bot's work is done this.workDoneSignaller = new ActionOnceAfterNEventsListener( ctx, noOfNeeds, new SignalWorkDoneAction(ctx) ); bus.subscribe(NeedDeactivatedEvent.class, this.workDoneSignaller); } }