/* * Copyright 2012 Research Studios Austria Forschungsges.m.b.H. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package won.bot.framework.eventbot.action.impl.wonmessage.execCommand; import won.bot.framework.eventbot.EventListenerContext; import won.bot.framework.eventbot.action.BaseEventBotAction; import won.bot.framework.eventbot.action.EventBotActionUtils; import won.bot.framework.eventbot.event.ConnectionSpecificEvent; import won.bot.framework.eventbot.event.Event; import won.bot.framework.eventbot.event.NeedSpecificEvent; import won.bot.framework.eventbot.event.RemoteNeedSpecificEvent; import won.bot.framework.eventbot.event.impl.command.MessageCommandEvent; import won.bot.framework.eventbot.event.impl.command.MessageCommandFailureEvent; import won.bot.framework.eventbot.event.impl.command.MessageCommandSuccessEvent; import won.bot.framework.eventbot.event.impl.wonmessage.FailureResponseEvent; import won.bot.framework.eventbot.event.impl.wonmessage.SuccessResponseEvent; import won.bot.framework.eventbot.listener.EventListener; import won.protocol.exception.WonMessageBuilderException; import won.protocol.message.WonMessage; import won.protocol.util.WonRdfUtils; /** * Action executing a MessageCommandEvent and publishing MessageCommandSuccess and MessageCommandFailure * events indicating how well sending that message worked. * * The optional constructor parameter <code>messageIsSentToRemoteNode</code>, which defaults to true is used * to determine if response listeners for a response from the remote node are to be registered */ public abstract class ExecuteSendMessageCommandAction<T extends MessageCommandEvent> extends BaseEventBotAction { private boolean messageIsSentToRemoteNode = true; protected ExecuteSendMessageCommandAction(EventListenerContext eventListenerContext, boolean messageIsSentToRemoteNode) { super(eventListenerContext); this.messageIsSentToRemoteNode = messageIsSentToRemoteNode; } public ExecuteSendMessageCommandAction(final EventListenerContext eventListenerContext) { this(eventListenerContext, true); } /** * Constructs the message via <code>createWonMessage</code> and registers a listener for the response from the * local WoN node and, if <code>messageIsSenttoRemoteNode</code> is true, a listener for the response from the * remote WoN node. * @param event * @param executingListener */ @Override public final void doRun(Event event, EventListener executingListener) { try { T messageCommandEvent = (T) event; //create the message WonMessage message = createWonMessage(messageCommandEvent); if (message == null) { //assume that the implementation class handles logging and error event creation. return; } //register listeners for the ResponseMessage generated by the own WoN node EventBotActionUtils.makeAndSubscribeResponseListener(message, responseEvent -> { if (responseEvent instanceof SuccessResponseEvent) { SuccessResponseEvent successEvent = (SuccessResponseEvent) responseEvent; logger.debug(makeLogMessageString(event) + " succeeded on local WoN node"); Event eventToPublish = createLocalNodeSuccessEvent(messageCommandEvent, message, successEvent); if (eventToPublish != null) { getEventListenerContext().getEventBus().publish(eventToPublish); } } }, responseEvent -> { if (responseEvent instanceof FailureResponseEvent) { FailureResponseEvent failureEvent = (FailureResponseEvent) responseEvent; logger.info(makeLogMessageString(event) + " failed on local WoN node with message: {}", WonRdfUtils.MessageUtils.getTextMessage(((FailureResponseEvent) responseEvent).getFailureMessage())); Event eventToPublish = createLocalNodeFailureEvent(messageCommandEvent, message, failureEvent); if (eventToPublish != null) { getEventListenerContext().getEventBus().publish(eventToPublish); } } } , getEventListenerContext()); //register listeners for the ResponseMessage generated by the remote WoN node if (messageIsSentToRemoteNode) { EventBotActionUtils.makeAndSubscribeRemoteResponseListener(message, responseEvent -> { if (responseEvent instanceof SuccessResponseEvent) { SuccessResponseEvent successEvent = (SuccessResponseEvent) responseEvent; logger.debug(makeLogMessageString(event) + " succeeded on remote WoN node"); Event eventToPublish = createRemoteNodeSuccessEvent(messageCommandEvent, message, successEvent); if (eventToPublish != null) { getEventListenerContext().getEventBus().publish(eventToPublish); } } }, responseEvent -> { if (responseEvent instanceof FailureResponseEvent) { FailureResponseEvent failureEvent = (FailureResponseEvent) responseEvent; logger.info(makeLogMessageString(event) + " failed on remote WoN node with message: {}", WonRdfUtils.MessageUtils.getTextMessage(((FailureResponseEvent) responseEvent).getFailureMessage())); Event eventToPublish = createRemoteNodeFailureEvent(messageCommandEvent, message, failureEvent); if (eventToPublish != null) { getEventListenerContext().getEventBus().publish(eventToPublish); } } } , getEventListenerContext()); } //send the message getEventListenerContext().getWonMessageSender().sendWonMessage(message); if (logger.isDebugEnabled()) { logger.debug(makeLogMessageString(event)); } } catch (Exception e) { logger.warn("error executing messageCommandEvent: ", e); } } /** * Implementations can choose to return null here if they do not want an event published. */ protected abstract MessageCommandFailureEvent createRemoteNodeFailureEvent(T originalCommand, WonMessage messageSent, FailureResponseEvent failureResponseEvent); /** * Implementations can choose to return null here if they do not want an event published. */ protected abstract MessageCommandSuccessEvent createRemoteNodeSuccessEvent(T originalCommand, WonMessage messageSent, SuccessResponseEvent successResponseEvent); /** * Implementations can choose to return null here if they do not want an event published. */ protected abstract MessageCommandFailureEvent createLocalNodeFailureEvent(T originalCommand, WonMessage messageSent, FailureResponseEvent failureResponseEvent); /** * Implementations can choose to return null here if they do not want an event published. */ protected abstract MessageCommandSuccessEvent createLocalNodeSuccessEvent(T originalCommand, WonMessage messageSent, SuccessResponseEvent successResponseEvent); /** * Implementations must return a valid WoNMessage here or perform adequate logging and publish an MessageCommandFailureEvent and return null. */ protected abstract WonMessage createWonMessage(T messageCommandEvent) throws WonMessageBuilderException; private String makeLogMessageString(Event event) { StringBuilder sb = new StringBuilder(); MessageCommandEvent messageCommandEvent = (MessageCommandEvent) event; sb.append("sending message of type ") .append(messageCommandEvent.getWonMessageType()); if (event instanceof NeedSpecificEvent) { sb.append(" on behalf of need ") .append(((NeedSpecificEvent) event).getNeedURI()); } if (event instanceof RemoteNeedSpecificEvent) { sb.append(" to need ") .append(((RemoteNeedSpecificEvent) event).getRemoteNeedURI()); } if (event instanceof ConnectionSpecificEvent) { sb.append (" in connection " ) .append(((ConnectionSpecificEvent)event).getConnectionURI()); } return sb.toString(); } }