diff options
Diffstat (limited to 'src/plugins/capabilities')
25 files changed, 2120 insertions, 0 deletions
diff --git a/src/plugins/capabilities/CapabilitiesFactory.cpp b/src/plugins/capabilities/CapabilitiesFactory.cpp new file mode 100644 index 0000000..7a65842 --- /dev/null +++ b/src/plugins/capabilities/CapabilitiesFactory.cpp @@ -0,0 +1,71 @@ +/* + * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0/ + * + * or in the "license" file accompanying this file. This file 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. + */ + +#include "capabilities/CapabilitiesFactory.h" + +#include "capabilities/communication/include/PhoneControlCapability.h" +#include "capabilities/guimetadata/include/GuiMetadataCapability.h" +#include "capabilities/navigation/include/NavigationCapability.h" +#include "capabilities/playbackcontroller/include/PlaybackControllerCapability.h" + +static string TAG = "vshlcapabilities::core::CapabilitiesFactory"; + +namespace vshlcapabilities { +namespace capabilities { + +// Create CapabilitiesFactory +std::unique_ptr<CapabilitiesFactory> CapabilitiesFactory::create( + shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger) { + auto capabilitiesFactory = std::unique_ptr<CapabilitiesFactory>(new CapabilitiesFactory(logger)); + return capabilitiesFactory; +} + +CapabilitiesFactory::CapabilitiesFactory( + shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger) { + mLogger = logger; +} + +std::shared_ptr<common::interfaces::ICapability> CapabilitiesFactory::getGuiMetadata() { + if (!mGuiMetadata) { + mGuiMetadata = vshlcapabilities::capabilities::guimetadata::GuiMetadata::create(mLogger); + } + return mGuiMetadata; +} + +std::shared_ptr<common::interfaces::ICapability> CapabilitiesFactory::getPhoneControl() { + if (!mPhoneControl) { + mPhoneControl = vshlcapabilities::capabilities::phonecontrol::PhoneControl::create(mLogger); + } + return mPhoneControl; +} + +std::shared_ptr<common::interfaces::ICapability> CapabilitiesFactory::getNavigation( + ) { + if (!mNavigation) { + mNavigation = vshlcapabilities::capabilities::navigation::Navigation::create(mLogger); + } + return mNavigation; +} + +std::shared_ptr<common::interfaces::ICapability> CapabilitiesFactory::getPlaybackController( + ) { + if (!mPlaybackController) { + mPlaybackController = vshlcapabilities::capabilities::playbackcontroller::PlaybackController::create(mLogger); + } + return mPlaybackController; +} + +} // namespace capabilities +} // namespace vshl
\ No newline at end of file diff --git a/src/plugins/capabilities/CapabilitiesFactory.h b/src/plugins/capabilities/CapabilitiesFactory.h new file mode 100644 index 0000000..b97fcfe --- /dev/null +++ b/src/plugins/capabilities/CapabilitiesFactory.h @@ -0,0 +1,69 @@ +/* + * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0/ + * + * or in the "license" file accompanying this file. This file 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. + */ +#ifndef VSHL_CAPABILITIES_CAPABILITIESFACTORY_H_ +#define VSHL_CAPABILITIES_CAPABILITIESFACTORY_H_ + +#include <memory> + +#include "interfaces/capabilities/ICapability.h" +#include "interfaces/utilities/logging/ILogger.h" + +using namespace std; + +namespace vshlcapabilities { +namespace capabilities { +/* + * Factory for creating different capability objects. + */ +class CapabilitiesFactory { +public: + // Create CapabilitiesFactory + static std::unique_ptr<CapabilitiesFactory> create( + shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger); + + // GUI Metadata capability + std::shared_ptr<common::interfaces::ICapability> getGuiMetadata(); + + // Phone call control capability + std::shared_ptr<common::interfaces::ICapability> getPhoneControl(); + + // Navigation capability + std::shared_ptr<common::interfaces::ICapability> getNavigation(); + + // PLaybackcontroller capability + std::shared_ptr<common::interfaces::ICapability> getPlaybackController(); + + // Destructor + ~CapabilitiesFactory() = default; + +private: + // Constructor + CapabilitiesFactory( + shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger); + + // Capabilities + shared_ptr<vshlcapabilities::common::interfaces::ICapability> mGuiMetadata; + shared_ptr<vshlcapabilities::common::interfaces::ICapability> mPhoneControl; + shared_ptr<vshlcapabilities::common::interfaces::ICapability> mNavigation; + shared_ptr<vshlcapabilities::common::interfaces::ICapability> mPlaybackController; + + // Logger + shared_ptr<vshlcapabilities::common::interfaces::ILogger> mLogger; +}; + +} // namespace capabilities +} // namespace vshl + +#endif // VSHL_CAPABILITIES_CAPABILITIESFACTORY_H_ diff --git a/src/plugins/capabilities/CapabilityMessagingService.cpp b/src/plugins/capabilities/CapabilityMessagingService.cpp new file mode 100644 index 0000000..8dd6e26 --- /dev/null +++ b/src/plugins/capabilities/CapabilityMessagingService.cpp @@ -0,0 +1,117 @@ +/* + * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0/ + * + * or in the "license" file accompanying this file. This file 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. + */ +#include "capabilities/CapabilityMessagingService.h" + +#include "capabilities/core/include/PublisherForwarder.h" +#include "capabilities/core/include/SubscriberForwarder.h" + +static string TAG = "vshlcapabilities::capabilities::CapabilityMessagingService"; + +using Level = vshlcapabilities::common::interfaces::ILogger::Level; + +namespace vshlcapabilities { +namespace capabilities { + +// Create a CapabilityMessagingService. +unique_ptr<CapabilityMessagingService> CapabilityMessagingService::create( + shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger, + shared_ptr<vshlcapabilities::common::interfaces::IAFBApi> afbApi) { + if (logger == nullptr) { + return nullptr; + } + + if (afbApi == nullptr) { + logger->log(Level::ERROR, TAG, "Failed to create CapabilityMessagingService: AFB API null"); + return nullptr; + } + + auto capabilityMessageService = + std::unique_ptr<CapabilityMessagingService>(new CapabilityMessagingService(logger, afbApi)); + return capabilityMessageService; +} + +CapabilityMessagingService::~CapabilityMessagingService() { + mMessageChannelsMap.clear(); +} + +CapabilityMessagingService::CapabilityMessagingService( + shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger, + shared_ptr<vshlcapabilities::common::interfaces::IAFBApi> afbApi) : + mAfbApi(afbApi), + mLogger(logger) { +} + +// Subscribe to capability specific messages. +bool CapabilityMessagingService::subscribe( + vshlcapabilities::common::interfaces::IAFBRequest& request, + shared_ptr<common::interfaces::ICapability> capability, + const string action) { + auto capabilityName = capability->getName(); + + if (capabilityName.empty()) { + mLogger->log(Level::ERROR, TAG, "Failed to subscribe to message. Invalid input."); + return false; + } + + auto messageChannel = getMessageChannel(capability); + return messageChannel->subscribe(request, action); +} + +// Publish capability messages. +bool CapabilityMessagingService::publish( + shared_ptr<common::interfaces::ICapability> capability, + const string action, + json_object* payload) { + auto capabilityName = capability->getName(); + + if (capabilityName.empty()) { + mLogger->log(Level::ERROR, TAG, "Failed to publish message. Invalid input."); + return false; + } + + auto messageChannelIt = mMessageChannelsMap.find(capabilityName); + if (messageChannelIt == mMessageChannelsMap.end()) { + mLogger->log( + Level::ERROR, + TAG, + "No one subscribed for a message of capability. " + capabilityName); + return false; + } + + return messageChannelIt->second->publish(action, payload); +} + +shared_ptr<vshlcapabilities::capabilities::core::MessageChannel> CapabilityMessagingService::getMessageChannel( + shared_ptr<common::interfaces::ICapability> capability) { + auto capabilityName = capability->getName(); + + if (capabilityName.empty()) { + mLogger->log(Level::ERROR, TAG, "Failed to create message channel. Invalid input."); + return nullptr; + } + + auto messageChannelIt = mMessageChannelsMap.find(capabilityName); + if (messageChannelIt == mMessageChannelsMap.end()) { + mLogger->log(Level::INFO, TAG, "Creating new message channel for capability: " + capabilityName); + auto messageChannel = vshlcapabilities::capabilities::core::MessageChannel::create(mLogger, mAfbApi, capability); + mMessageChannelsMap.insert(make_pair(capabilityName, messageChannel)); + return messageChannel; + } + + return messageChannelIt->second; +} + +} // namespace capabilities +} // namespace vshl diff --git a/src/plugins/capabilities/CapabilityMessagingService.h b/src/plugins/capabilities/CapabilityMessagingService.h new file mode 100644 index 0000000..79edfa8 --- /dev/null +++ b/src/plugins/capabilities/CapabilityMessagingService.h @@ -0,0 +1,82 @@ +/* + * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0/ + * + * or in the "license" file accompanying this file. This file 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. + */ +#ifndef VSHL_CAPABILITIES_CAPABILITYMESSAGINGSERVICE_H_ +#define VSHL_CAPABILITIES_CAPABILITYMESSAGINGSERVICE_H_ + +#include <memory> +#include <string> +#include <unordered_map> + +#include "capabilities/core/include/MessageChannel.h" +#include "interfaces/afb/IAFBApi.h" +#include "interfaces/capabilities/ICapability.h" +#include "interfaces/utilities/logging/ILogger.h" + +using namespace std; + +namespace vshlcapabilities { +namespace capabilities { +/* + * This hosts service APIs that clients can use to subscribe and + * forward capability messages. Each capability has a name and + * direction (upstream/downstream). Upstream messages are from + * voiceagents to Apps and downstream messages are Apps to voiceagents. + * This class will use a factory to create publisher and subcribers for + * each capability and create assiociations between them. + */ +class CapabilityMessagingService { +public: + // Create a CapabilityMessagingService. + static std::unique_ptr<CapabilityMessagingService> + create(shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger, + shared_ptr<vshlcapabilities::common::interfaces::IAFBApi> afbApi); + + // Subscribe to capability specific messages. + bool subscribe(vshlcapabilities::common::interfaces::IAFBRequest &request, + shared_ptr<common::interfaces::ICapability> capability, + const string action); + + // Publish capability messages. + bool publish(shared_ptr<common::interfaces::ICapability> capability, + const string action, json_object* payload); + + // Destructor + ~CapabilityMessagingService(); + +private: + // Constructor + CapabilityMessagingService( + shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger, + shared_ptr<vshlcapabilities::common::interfaces::IAFBApi> afbApi); + + // Binding API reference + shared_ptr<vshlcapabilities::common::interfaces::IAFBApi> mAfbApi; + + // Create a message channel for the capability. + shared_ptr<vshlcapabilities::capabilities::core::MessageChannel> + getMessageChannel(shared_ptr<common::interfaces::ICapability> capability); + + // Map of capabilities to message channels. + unordered_map<string, shared_ptr<vshlcapabilities::capabilities::core::MessageChannel>> + mMessageChannelsMap; + + // Logger + shared_ptr<vshlcapabilities::common::interfaces::ILogger> mLogger; +}; + +} // namespace capabilities +} // namespace vshl + +#endif // VSHL_CAPABILITIES_CAPABILITYMESSAGINGSERVICE_H_ diff --git a/src/plugins/capabilities/communication/include/PhoneControlCapability.h b/src/plugins/capabilities/communication/include/PhoneControlCapability.h new file mode 100644 index 0000000..87dc339 --- /dev/null +++ b/src/plugins/capabilities/communication/include/PhoneControlCapability.h @@ -0,0 +1,57 @@ +/* + * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0/ + * + * or in the "license" file accompanying this file. This file 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. + */ + +#ifndef VSHL_CAPABILITIES_PHONECONTROL_CAPABILITY_H_ +#define VSHL_CAPABILITIES_PHONECONTROL_CAPABILITY_H_ + +#include <memory> + +#include "interfaces/capabilities/ICapability.h" +#include "interfaces/utilities/logging/ILogger.h" + +namespace vshlcapabilities { +namespace capabilities { +namespace phonecontrol { + +/* + * PhoneControl capability. Calls are initiated in the endpoint. + */ +class PhoneControl : public common::interfaces::ICapability { +public: + // Create a PhoneControl. + static std::shared_ptr<PhoneControl> create( + shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger); + + ~PhoneControl() = default; + +protected: + string getName() const override; + + list<string> getUpstreamMessages() const override; + + list<string> getDownstreamMessages() const override; + +private: + PhoneControl( + shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger); + + shared_ptr<vshlcapabilities::common::interfaces::ILogger> mLogger; +}; + +} // namespace phonecontrol +} // namespace capabilities +} // namespace vshl + +#endif // VSHL_CAPABILITIES_PHONECONTROL_CAPABILITY_H_ diff --git a/src/plugins/capabilities/communication/include/PhoneControlMessages.h b/src/plugins/capabilities/communication/include/PhoneControlMessages.h new file mode 100644 index 0000000..23d2fae --- /dev/null +++ b/src/plugins/capabilities/communication/include/PhoneControlMessages.h @@ -0,0 +1,208 @@ +/* + * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0/ + * + * or in the "license" file accompanying this file. This file 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. + */ +#ifndef VSHL_CAPABILITIES_PHONECONTROL_MESSAGES_H_ +#define VSHL_CAPABILITIES_PHONECONTROL_MESSAGES_H_ + +#include <list> +#include <string> + +using namespace std; + +namespace vshlcapabilities { +namespace capabilities { +namespace phonecontrol { + +static string NAME = "phonecontrol"; + +/* + ****************************************************************************************************** + * Supported actions from VA -> APPS + ****************************************************************************************************** + */ + +/* Dial message sent from VA to app handling the calling. + * + * payload: + * { + * "callId": "{{STRING}}", + * "callee": { + * "details": "{{STRING}}", + * "defaultAddress": { + * "protocol": "{{STRING}}", + * "format": "{{STRING}}", + * "value": "{{STRING}}" + * }, + * "alternativeAddresses": [{ + * "protocol": "{{STRING}}", + * "format": "{{STRING}}", + * "value": {{STRING}} + * }] + * } + * } + * } + * + * callId (required): A unique identifier for the call + * callee (required): The destination of the outgoing call + * callee.details (optional): Descriptive information about the callee + * callee.defaultAddress (required): The default address to use for calling the callee + * callee.alternativeAddresses (optional): An array of alternate addresses for the existing callee + * address.protocol (required): The protocol for this address of the callee (e.g. PSTN, SIP, H323, etc.) + * address.format (optional): The format for this address of the callee (e.g. E.164, E.163, E.123, DIN5008, etc.) + * address.value (required): The address of the callee. + * + */ +static string PHONECONTROL_DIAL = "dial"; +/** + * Notifies the platform implementation to redial the last called phone number. + * + * After returning @c true, if no stored number is available to be redialed, @c PhoneCallController::callFailed with + * @c CallError::NO_NUMBER_FOR_REDIAL should be called. + * + * @param [in] payload Details of the redial request in structured JSON format. See the following + * payload: + * { + * "callId": "{{STRING}}" + * } + * @li callId (required): A unique identifier for the call + * + * @return @c true if the platform implementation successfully handled the call + */ +static string PHONECONTROL_REDIAL = "redial"; +/** + * Notifies the platform implementation to answer an inbound call + * + * @param [in] payload Details of the answer request in structured JSON format. See the following + * payload: + * { + * "callId": "{{STRING}}", + * } + * @li callId (required): The unique identifier for the call to answer + */ +static string PHONECONTROL_ANSWER = "answer"; +/** + * Notifies the platform implementation to end an ongoing call or stop inbound or outbound call setup + * + * @param [in] payload Details of the stop request in structured JSON format. See the following + * payload: + * { + * "callId": "{{STRING}}" + * } + * @li callId (required): The unique identifier for the call to be stopped + */ +static string PHONECONTROL_STOP = "stop"; +/** + * Notifies the platform implementation to send a DTMF signal to the calling device + * + * @param [in] payload Details of the DTMF request in structured JSON format. See the following + * payload: + * { + * "callId": "{{STRING}}", + * "signal": "{{STRING}}" + * } + * @li callId (required): The unique identifier for the call + * @li signal (required): The DTMF string to be sent to the calling device associated with the callId + */ +static string PHONECONTROL_SEND_DTMF = "send_dtmf"; + +/* + ****************************************************************************************************** + * Supported actions from Apps -> VA + ****************************************************************************************************** + */ + +/* + * App notifies the voiceagents of a change in connection state of a calling device. + * + * payload: + * { + * "state" : "{{STRING}}" // CONNECTED or DISCONNECTED + * } + */ +static string PHONECONTROL_CONNECTIONSTATE_CHANGED = "connection_state_changed"; +/* + * App notifies the voiceagents that call is activated + * + * callId must match the one that is sent by VA with DIAL message above. + * + * payload: + * { + * "callId" : "{{STRING}}" + * "state" : "{{STRING}}" // IDLE, ACTIVE, TRYING, INBOUND_RINGING, OUTBOUND_RINGING, INVITED + * } + */ +static string PHONECONTROL_CALL_STATE_CHANGED = "call_state_changed"; +/* + * App notifies the voiceagents of an error in initiating or maintaining a + * call on a calling device + * + * callId must match the one that is sent by VA with DIAL message above. + * error: below status codes. + * 4xx: Validation failure for the input from the DIAL message + * 500: Internal error on the platform unrelated to the cellular network + * 503: Error on the platform related to the cellular network + * + * payload : + * { + * "callId" : "{{STRING}}" + * "error" : "{{STRING}}" + * } + */ +static string PHONECONTROL_CALL_FAILED = "call_failed"; +/** + * App notifies the voiceagents that a caller id was received for an inbound call + * payload : + * { + * "callId" : "{{STRING}}" + * "callerId" : "{{STRING}}" + * } + * + * @param [in] callId The unique identifier for the call associated with the callId + * @param [in] callerId The caller's identifier or phone number + */ +static string PHONECONTROL_CALLERID_RECEIVED = "caller_id_received"; + +/** + * Notifies the Engine that sending the DTMF signal succeeded. + * payload : + * { + * "callId" : "{{STRING}}" + * } + * @param [in] callId The unique identifier for the associated call + * + * PhoneCallController::sendDTMF + */ +static string PHONECONTROL_SEND_DTMF_SUCCEEDED = "send_dtmf_succeeded"; + +// List of actions that are delivered from VA -> Apps +static list<string> PHONECONTROL_UPSTREAM_ACTIONS = { + PHONECONTROL_DIAL, + PHONECONTROL_REDIAL, + PHONECONTROL_ANSWER, + PHONECONTROL_STOP, + PHONECONTROL_SEND_DTMF +}; + +// List of actions that are delivered from Apps -> VA +static list<string> PHONECONTROL_DOWNSTREAM_ACTIONS = {PHONECONTROL_CONNECTIONSTATE_CHANGED, + PHONECONTROL_CALL_STATE_CHANGED, + PHONECONTROL_CALL_FAILED, + PHONECONTROL_CALLERID_RECEIVED, + PHONECONTROL_SEND_DTMF_SUCCEEDED}; + +} // namespace phonecontrol +} // namespace capabilities +} // namespace vshl + +#endif // VSHL_CAPABILITIES_PHONECONTROL_MESSAGES_H_ diff --git a/src/plugins/capabilities/communication/src/PhoneControlCapability.cpp b/src/plugins/capabilities/communication/src/PhoneControlCapability.cpp new file mode 100644 index 0000000..75296bf --- /dev/null +++ b/src/plugins/capabilities/communication/src/PhoneControlCapability.cpp @@ -0,0 +1,52 @@ +/* + * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0/ + * + * or in the "license" file accompanying this file. This file 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. + */ +#include "capabilities/communication/include/PhoneControlCapability.h" +#include "capabilities/communication/include/PhoneControlMessages.h" + +const string TAG = "vshlcapabilities::capabilities::phonecontrol"; + +using Level = vshlcapabilities::common::interfaces::ILogger::Level; + +namespace vshlcapabilities { +namespace capabilities { +namespace phonecontrol { + +// Create a phonecontrol. +shared_ptr<PhoneControl> PhoneControl::create( + shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger) { + auto phonecontrol = std::shared_ptr<PhoneControl>(new PhoneControl(logger)); + return phonecontrol; +} + +PhoneControl::PhoneControl( + shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger) { + mLogger = logger; +} + +string PhoneControl::getName() const { + return NAME; +} + +list<string> PhoneControl::getUpstreamMessages() const { + return PHONECONTROL_UPSTREAM_ACTIONS; +} + +list<string> PhoneControl::getDownstreamMessages() const { + return PHONECONTROL_DOWNSTREAM_ACTIONS; +} + +} // namespace phonecontrol +} // namespace capabilities +} // namespace vshl diff --git a/src/plugins/capabilities/core/include/MessageChannel.h b/src/plugins/capabilities/core/include/MessageChannel.h new file mode 100644 index 0000000..79e4eab --- /dev/null +++ b/src/plugins/capabilities/core/include/MessageChannel.h @@ -0,0 +1,68 @@ +/* + * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0/ + * + * or in the "license" file accompanying this file. This file 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. + */ +#ifndef VSHL_CAPABILITIES_CORE_MESSAGECHANNEL_H_ +#define VSHL_CAPABILITIES_CORE_MESSAGECHANNEL_H_ + +#include <memory> + +#include "capabilities/core/include/PublisherForwarder.h" +#include "capabilities/core/include/SubscriberForwarder.h" +#include "interfaces/afb/IAFBApi.h" +#include "interfaces/capabilities/ICapability.h" +#include "interfaces/utilities/logging/ILogger.h" + +using namespace std; + +namespace vshlcapabilities { +namespace capabilities { +namespace core { +/* + * MessageChannel has one end as publisher forwarder and the other end + * as subscriber forwarder. + */ +class MessageChannel { +public: + // Create a MessageChannel. + static std::shared_ptr<MessageChannel> + create(shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger, + shared_ptr<vshlcapabilities::common::interfaces::IAFBApi> afbApi, + shared_ptr<vshlcapabilities::common::interfaces::ICapability> capability); + + // Sends the message + bool publish(const string action, json_object* payload); + + // Subscribe + bool subscribe(vshlcapabilities::common::interfaces::IAFBRequest &request, + const string action); + + // Destructor + virtual ~MessageChannel() = default; + +private: + // Constructor + MessageChannel(shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger, + shared_ptr<vshlcapabilities::common::interfaces::IAFBApi> afbApi, + shared_ptr<vshlcapabilities::common::interfaces::ICapability> capability); + + // Forwarders + shared_ptr<PublisherForwarder> mPublisherForwarder; + shared_ptr<SubscriberForwarder> mSubscriberForwarder; +}; + +} // namespace core +} // namespace capabilities +} // namespace vshl + +#endif // VSHL_CAPABILITIES_CORE_MESSAGECHANNEL_H_ diff --git a/src/plugins/capabilities/core/include/PublisherForwarder.h b/src/plugins/capabilities/core/include/PublisherForwarder.h new file mode 100644 index 0000000..01e9523 --- /dev/null +++ b/src/plugins/capabilities/core/include/PublisherForwarder.h @@ -0,0 +1,73 @@ +/* + * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0/ + * + * or in the "license" file accompanying this file. This file 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. + */ +#ifndef VSHL_CAPABILITIES_CORE_PUBLISHERFORWARDER_H_ +#define VSHL_CAPABILITIES_CORE_PUBLISHERFORWARDER_H_ + +#include <memory> + +#include "capabilities/core/include/SubscriberForwarder.h" + +#include "interfaces/afb/IAFBApi.h" +#include "interfaces/capabilities/ICapability.h" +#include "interfaces/utilities/logging/ILogger.h" + +using namespace std; + +namespace vshlcapabilities { +namespace capabilities { +namespace core { +/* + * This class is responsible for forwarding the messages to be published + * to subscriber forwarder. Subscriber forwarder will deliver the messages + * as AFB Events to all the subscribed clients. + * There is one PublisherForwarder and one SubscriberForwarder per capability. + */ +class PublisherForwarder { +public: + // Create a PublisherForwarder. + static std::shared_ptr<PublisherForwarder> create( + shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger, + shared_ptr<vshlcapabilities::common::interfaces::ICapability> capability); + + // Connect a subscriber forwarder to this publisher forwarder + void setSubscriberForwarder(shared_ptr<SubscriberForwarder> subscriberForwarder); + + // Forward message to the subscriber forwarder + bool forwardMessage(const string action, json_object* payload); + + // Destructor + ~PublisherForwarder(); + +private: + // Constructor + PublisherForwarder( + shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger, + shared_ptr<vshlcapabilities::common::interfaces::ICapability> capability); + + // Subscriber forwarder connected to this publisher forwarder. + shared_ptr<SubscriberForwarder> mSubscriberForwarder; + + // Capability + shared_ptr<vshlcapabilities::common::interfaces::ICapability> mCapability; + + // Logger + shared_ptr<vshlcapabilities::common::interfaces::ILogger> mLogger; +}; + +} // namespace core +} // namespace capabilities +} // namespace vshl + +#endif // VSHL_CAPABILITIES_CORE_PUBLISHERFORWARDER_H_ diff --git a/src/plugins/capabilities/core/include/SubscriberForwarder.h b/src/plugins/capabilities/core/include/SubscriberForwarder.h new file mode 100644 index 0000000..ac469b3 --- /dev/null +++ b/src/plugins/capabilities/core/include/SubscriberForwarder.h @@ -0,0 +1,84 @@ +/* + * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0/ + * + * or in the "license" file accompanying this file. This file 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. + */ +#ifndef VSHL_CAPABILITIES_CORE_SUBSCRIBERFORWARDER_H_ +#define VSHL_CAPABILITIES_CORE_SUBSCRIBERFORWARDER_H_ + +#include <memory> +#include <string> +#include <unordered_map> + +#include "interfaces/afb/IAFBApi.h" +#include "interfaces/capabilities/ICapability.h" +#include "interfaces/utilities/logging/ILogger.h" + +using namespace std; + +namespace vshlcapabilities { +namespace capabilities { +namespace core { +/* + * This class is responsible for forwarding the messages publishing + * to the actual clients using AFB. + */ +class SubscriberForwarder { +public: + // Create a SubscriberForwarder. + static std::shared_ptr<SubscriberForwarder> + create(shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger, + shared_ptr<vshlcapabilities::common::interfaces::IAFBApi> afbApi, + shared_ptr<vshlcapabilities::common::interfaces::ICapability> capability); + + // Publish a capability message to the actual client. + bool forwardMessage(const string action, json_object* payload); + + // Subscribe + bool subscribe(vshlcapabilities::common::interfaces::IAFBRequest &request, + const string action); + + // Destructor + ~SubscriberForwarder(); + +private: + // Constructor + SubscriberForwarder( + shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger, + shared_ptr<vshlcapabilities::common::interfaces::IAFBApi> afbApi, + shared_ptr<vshlcapabilities::common::interfaces::ICapability> capability); + + // Creates both upstream and downstream events + void createEvents(); + + // Binding API reference + shared_ptr<vshlcapabilities::common::interfaces::IAFBApi> mAfbApi; + + // Capability + shared_ptr<vshlcapabilities::common::interfaces::ICapability> mCapability; + + // Maps of capability action events to its corresponding Event object. + // Event name maps to Action Name + unordered_map<string, shared_ptr<common::interfaces::IAFBApi::IAFBEvent>> + mUpstreamEventsMap; + unordered_map<string, shared_ptr<common::interfaces::IAFBApi::IAFBEvent>> + mDownstreamEventsMap; + + // Logger + shared_ptr<vshlcapabilities::common::interfaces::ILogger> mLogger; +}; + +} // namespace core +} // namespace capabilities +} // namespace vshl + +#endif // VSHL_CAPABILITIES_CORE_SUBSCRIBERFORWARDER_H_ diff --git a/src/plugins/capabilities/core/src/MessageChannel.cpp b/src/plugins/capabilities/core/src/MessageChannel.cpp new file mode 100644 index 0000000..f4e55dd --- /dev/null +++ b/src/plugins/capabilities/core/src/MessageChannel.cpp @@ -0,0 +1,51 @@ +/* + * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0/ + * + * or in the "license" file accompanying this file. This file 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. + */ +#include "capabilities/core/include/MessageChannel.h" + +namespace vshlcapabilities { +namespace capabilities { +namespace core { + +// Create a MessageChannel. +std::shared_ptr<MessageChannel> MessageChannel::create( + shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger, + shared_ptr<vshlcapabilities::common::interfaces::IAFBApi> api, + shared_ptr<vshlcapabilities::common::interfaces::ICapability> capability) { + auto messageChannel = std::shared_ptr<MessageChannel>(new MessageChannel(logger, api, capability)); + return messageChannel; +} + +MessageChannel::MessageChannel( + shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger, + shared_ptr<vshlcapabilities::common::interfaces::IAFBApi> api, + shared_ptr<vshlcapabilities::common::interfaces::ICapability> capability) { + // Subscriber forwarder + mSubscriberForwarder = SubscriberForwarder::create(logger, api, capability); + // Publisher forwarder + mPublisherForwarder = PublisherForwarder::create(logger, capability); + mPublisherForwarder->setSubscriberForwarder(mSubscriberForwarder); +} + +bool MessageChannel::publish(const string action, json_object* payload) { + return mPublisherForwarder->forwardMessage(action, payload); +} + +bool MessageChannel::subscribe(vshlcapabilities::common::interfaces::IAFBRequest& request, const string action) { + return mSubscriberForwarder->subscribe(request, action); +} + +} // namespace core +} // namespace capabilities +} // namespace vshl diff --git a/src/plugins/capabilities/core/src/PublisherForwarder.cpp b/src/plugins/capabilities/core/src/PublisherForwarder.cpp new file mode 100644 index 0000000..8f8f542 --- /dev/null +++ b/src/plugins/capabilities/core/src/PublisherForwarder.cpp @@ -0,0 +1,69 @@ +/* + * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0/ + * + * or in the "license" file accompanying this file. This file 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. + */ +#include "capabilities/core/include/PublisherForwarder.h" + +static string TAG = "vshlcapabilities::capabilities::PublisherForwarder"; + +using Level = vshlcapabilities::common::interfaces::ILogger::Level; + +namespace vshlcapabilities { +namespace capabilities { +namespace core { + +// Create a PublisherForwarder. +std::shared_ptr<PublisherForwarder> PublisherForwarder::create( + shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger, + shared_ptr<vshlcapabilities::common::interfaces::ICapability> capability) { + if (logger == nullptr) { + return nullptr; + } + + if (capability == nullptr) { + logger->log(Level::ERROR, TAG, "Failed to create PublisherForwarder: Capability null"); + return nullptr; + } + + auto publisherForwarder = std::shared_ptr<PublisherForwarder>(new PublisherForwarder(logger, capability)); + return publisherForwarder; +} + +// Constructor +PublisherForwarder::PublisherForwarder( + shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger, + shared_ptr<vshlcapabilities::common::interfaces::ICapability> capability) { + mCapability = capability; + mLogger = logger; +} + +// Destructor +PublisherForwarder::~PublisherForwarder() { +} + +void PublisherForwarder::setSubscriberForwarder(shared_ptr<SubscriberForwarder> subscriberForwarder) { + mSubscriberForwarder = subscriberForwarder; +} + +bool PublisherForwarder::forwardMessage(const string action, json_object* payload) { + if (!mSubscriberForwarder) { + mLogger->log(Level::ERROR, TAG, "Failed to forward message for capability: " + mCapability->getName()); + return false; + } + + return mSubscriberForwarder->forwardMessage(action, payload); +} + +} // namespace core +} // namespace capabilities +} // namespace vshl diff --git a/src/plugins/capabilities/core/src/SubscriberForwarder.cpp b/src/plugins/capabilities/core/src/SubscriberForwarder.cpp new file mode 100644 index 0000000..970dbf0 --- /dev/null +++ b/src/plugins/capabilities/core/src/SubscriberForwarder.cpp @@ -0,0 +1,139 @@ +/* + * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0/ + * + * or in the "license" file accompanying this file. This file 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. + */ +#include "capabilities/core/include/SubscriberForwarder.h" + +static string TAG = "vshlcapabilities::capabilities::SubscriberForwarder"; + +using Level = vshlcapabilities::common::interfaces::ILogger::Level; + +namespace vshlcapabilities { +namespace capabilities { +namespace core { + +// Create a SubscriberForwarder. +std::shared_ptr<SubscriberForwarder> SubscriberForwarder::create( + shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger, + shared_ptr<vshlcapabilities::common::interfaces::IAFBApi> afbApi, + shared_ptr<vshlcapabilities::common::interfaces::ICapability> capability) { + if (logger == nullptr) { + return nullptr; + } + + if (afbApi == nullptr) { + logger->log(Level::ERROR, TAG, "Failed to create SubscriberForwarder: AFB API null"); + return nullptr; + } + + if (capability == nullptr) { + logger->log(Level::ERROR, TAG, "Failed to create SubscriberForwarder: Capability null"); + return nullptr; + } + + auto subscriberForwarder = + std::shared_ptr<SubscriberForwarder>(new SubscriberForwarder(logger, afbApi, capability)); + return subscriberForwarder; +} + +SubscriberForwarder::SubscriberForwarder( + shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger, + shared_ptr<vshlcapabilities::common::interfaces::IAFBApi> afbApi, + shared_ptr<vshlcapabilities::common::interfaces::ICapability> capability) : + mAfbApi(afbApi), + mLogger(logger), + mCapability(capability) { + createEvents(); +} + +SubscriberForwarder::~SubscriberForwarder() { + mUpstreamEventsMap.clear(); + mDownstreamEventsMap.clear(); +} + +void SubscriberForwarder::createEvents() { + if (!mCapability) { + mLogger->log(Level::NOTICE, TAG, "Create Events failed. No capability assigned."); + return; + } + + // Upstream events + auto upstreamEvents = mCapability->getUpstreamMessages(); + for (auto upstreamEventName : upstreamEvents) { + auto it = mUpstreamEventsMap.find(upstreamEventName); + if (it == mUpstreamEventsMap.end() && mAfbApi) { + // create a new event and add it to the map. + shared_ptr<common::interfaces::IAFBApi::IAFBEvent> event = mAfbApi->createEvent(upstreamEventName); + if (event == nullptr) { + mLogger->log(Level::ERROR, TAG, "Failed to create upstream event: " + upstreamEventName); + } else { + mUpstreamEventsMap.insert(make_pair(upstreamEventName, event)); + } + } + } + + // Downstream events + auto downstreamEvents = mCapability->getDownstreamMessages(); + for (auto downstreamEventName : downstreamEvents) { + auto it = mDownstreamEventsMap.find(downstreamEventName); + if (it == mDownstreamEventsMap.end() && mAfbApi) { + // create a new event and add it to the map. + shared_ptr<common::interfaces::IAFBApi::IAFBEvent> event = mAfbApi->createEvent(downstreamEventName); + if (event == nullptr) { + mLogger->log(Level::ERROR, TAG, "Failed to create downstream event: " + downstreamEventName); + } else { + mDownstreamEventsMap.insert(make_pair(downstreamEventName, event)); + } + } + } +} + +bool SubscriberForwarder::forwardMessage(const string action, json_object* payload) { + auto upstreamEventIt = mUpstreamEventsMap.find(action); + if (upstreamEventIt != mUpstreamEventsMap.end()) { + mLogger->log(Level::NOTICE, TAG, "Publishing upstream event: " + action); + upstreamEventIt->second->publishEvent(payload); + return true; + } + + auto downstreamEventIt = mDownstreamEventsMap.find(action); + if (downstreamEventIt != mDownstreamEventsMap.end()) { + mLogger->log(Level::NOTICE, TAG, "Publishing downstream event: " + action); + downstreamEventIt->second->publishEvent(payload); + return true; + } + + mLogger->log(Level::NOTICE, TAG, "Failed to publish upstream event: " + action); + return false; +} + +bool SubscriberForwarder::subscribe(vshlcapabilities::common::interfaces::IAFBRequest& request, const string action) { + auto upstreamEventIt = mUpstreamEventsMap.find(action); + if (upstreamEventIt != mUpstreamEventsMap.end()) { + mLogger->log(Level::NOTICE, TAG, "Subscribing to upstream event: " + action); + return upstreamEventIt->second->subscribe(request); + } + + auto downstreamEventIt = mDownstreamEventsMap.find(action); + if (downstreamEventIt != mDownstreamEventsMap.end()) { + mLogger->log(Level::NOTICE, TAG, "Subscribing to downstream event: " + action); + return downstreamEventIt->second->subscribe(request); + } + + mLogger->log(Level::NOTICE, TAG, "Failed to subscribe to upstream event: " + action); + return false; +} + +} // namespace core +} // namespace capabilities +} // namespace vshl diff --git a/src/plugins/capabilities/guimetadata/include/GuiMetadataCapability.h b/src/plugins/capabilities/guimetadata/include/GuiMetadataCapability.h new file mode 100644 index 0000000..ecaf09f --- /dev/null +++ b/src/plugins/capabilities/guimetadata/include/GuiMetadataCapability.h @@ -0,0 +1,57 @@ +/* + * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0/ + * + * or in the "license" file accompanying this file. This file 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. + */ + +#ifndef VSHL_CAPABILITIES_GUIMETADATA_CAPABILITY_H_ +#define VSHL_CAPABILITIES_GUIMETADATA_CAPABILITY_H_ + +#include <memory> + +#include "interfaces/capabilities/ICapability.h" +#include "interfaces/utilities/logging/ILogger.h" + +namespace vshlcapabilities { +namespace capabilities { +namespace guimetadata { + +/* + * GuiMetadata capability + */ +class GuiMetadata : public common::interfaces::ICapability { +public: + // Create a GuiMetadata. + static std::shared_ptr<GuiMetadata> create( + shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger); + + ~GuiMetadata() = default; + +protected: + string getName() const override; + + list<string> getUpstreamMessages() const override; + + list<string> getDownstreamMessages() const override; + +private: + GuiMetadata( + shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger); + + shared_ptr<vshlcapabilities::common::interfaces::ILogger> mLogger; +}; + +} // namespace guimetadata +} // namespace capabilities +} // namespace vshl + +#endif // VSHL_CAPABILITIES_GUIMETADATA_CAPABILITY_H_ diff --git a/src/plugins/capabilities/guimetadata/include/GuiMetadataMessages.h b/src/plugins/capabilities/guimetadata/include/GuiMetadataMessages.h new file mode 100644 index 0000000..07f4725 --- /dev/null +++ b/src/plugins/capabilities/guimetadata/include/GuiMetadataMessages.h @@ -0,0 +1,59 @@ +/* + * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0/ + * + * or in the "license" file accompanying this file. This file 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. + */ +#ifndef VSHL_CAPABILITIES_GUIMETADATA_ACTIONS_H_ +#define VSHL_CAPABILITIES_GUIMETADATA_ACTIONS_H_ + +#include <list> +#include <string> + +using namespace std; + +namespace vshlcapabilities { +namespace capabilities { +namespace guimetadata { + +static string NAME = "guimetadata"; + +/* + ****************************************************************************************************** + * Supported actions from VA -> APPS + ****************************************************************************************************** + */ +static string GUIMETADATA_RENDER_TEMPLATE = "render_template"; +static string GUIMETADATA_CLEAR_TEMPLATE = "clear_template"; +static string GUIMETADATA_RENDER_PLAYER_INFO = "render_player_info"; +static string GUIMETADATA_CLEAR_PLAYER_INFO = "clear_player_info"; + + +// List of actions that are delivered from VA -> Apps +static list<string> GUIMETADATA_UPSTREAM_ACTIONS = {GUIMETADATA_RENDER_TEMPLATE, + GUIMETADATA_CLEAR_TEMPLATE, + GUIMETADATA_RENDER_PLAYER_INFO, + GUIMETADATA_CLEAR_PLAYER_INFO}; + +/* + ****************************************************************************************************** + * Supported actions from APPS -> VA + ****************************************************************************************************** + */ + +// List of actions that are delivered from Apps -> VA +static list<string> GUIMETADATA_DOWNSTREAM_ACTIONS = {}; + +} // namespace guimetadata +} // namespace capabilities +} // namespace vshl + +#endif // VSHL_CAPABILITIES_GUIMETADATA_ACTIONS_H_ diff --git a/src/plugins/capabilities/guimetadata/src/GuiMetadataCapability.cpp b/src/plugins/capabilities/guimetadata/src/GuiMetadataCapability.cpp new file mode 100644 index 0000000..df90c91 --- /dev/null +++ b/src/plugins/capabilities/guimetadata/src/GuiMetadataCapability.cpp @@ -0,0 +1,52 @@ +/* + * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0/ + * + * or in the "license" file accompanying this file. This file 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. + */ +#include "capabilities/guimetadata/include/GuiMetadataCapability.h" +#include "capabilities/guimetadata/include/GuiMetadataMessages.h" + +const string TAG = "vshlcapabilities::capabilities::guimetadata"; + +using Level = vshlcapabilities::common::interfaces::ILogger::Level; + +namespace vshlcapabilities { +namespace capabilities { +namespace guimetadata { + +// Create a GuiMetadata. +shared_ptr<GuiMetadata> GuiMetadata::create( + shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger) { + auto guiMetadata = std::shared_ptr<GuiMetadata>(new GuiMetadata(logger)); + return guiMetadata; +} + +GuiMetadata::GuiMetadata( + shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger) { + mLogger = logger; +} + +string GuiMetadata::getName() const { + return NAME; +} + +list<string> GuiMetadata::getUpstreamMessages() const { + return GUIMETADATA_UPSTREAM_ACTIONS; +} + +list<string> GuiMetadata::getDownstreamMessages() const { + return GUIMETADATA_DOWNSTREAM_ACTIONS; +} + +} // namespace guimetadata +} // namespace capabilities +} // namespace vshl diff --git a/src/plugins/capabilities/navigation/include/NavigationCapability.h b/src/plugins/capabilities/navigation/include/NavigationCapability.h new file mode 100644 index 0000000..bb055a8 --- /dev/null +++ b/src/plugins/capabilities/navigation/include/NavigationCapability.h @@ -0,0 +1,57 @@ +/* + * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0/ + * + * or in the "license" file accompanying this file. This file 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. + */ + +#ifndef VSHL_CAPABILITIES_NAVIGATION_CAPABILITY_H_ +#define VSHL_CAPABILITIES_NAVIGATION_CAPABILITY_H_ + +#include <memory> + +#include "interfaces/capabilities/ICapability.h" +#include "interfaces/utilities/logging/ILogger.h" + +namespace vshlcapabilities { +namespace capabilities { +namespace navigation { + +/* + * Navigation capability + */ +class Navigation : public common::interfaces::ICapability { +public: + // Create a Navigation. + static std::shared_ptr<Navigation> create( + shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger); + + ~Navigation() = default; + +protected: + string getName() const override; + + list<string> getUpstreamMessages() const override; + + list<string> getDownstreamMessages() const override; + +private: + Navigation( + shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger); + + shared_ptr<vshlcapabilities::common::interfaces::ILogger> mLogger; +}; + +} // namespace navigation +} // namespace capabilities +} // namespace vshl + +#endif // VSHL_CAPABILITIES_NAVIGATION_CAPABILITY_H_ diff --git a/src/plugins/capabilities/navigation/include/NavigationMessages.h b/src/plugins/capabilities/navigation/include/NavigationMessages.h new file mode 100644 index 0000000..00c0c65 --- /dev/null +++ b/src/plugins/capabilities/navigation/include/NavigationMessages.h @@ -0,0 +1,56 @@ +/* + * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0/ + * + * or in the "license" file accompanying this file. This file 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. + */ +#ifndef VSHL_CAPABILITIES_NAVIGATION_ACTIONS_H_ +#define VSHL_CAPABILITIES_NAVIGATION_ACTIONS_H_ + +#include <list> +#include <string> + +using namespace std; + +namespace vshlcapabilities { +namespace capabilities { +namespace navigation { + +static string NAME = "navigation"; + +/* + ****************************************************************************************************** + * Supported actions from VA -> APPS + ****************************************************************************************************** + */ +static string NAVIGATION_SET_DESTINATION = "set_destination"; +static string NAVIGATION_CANCEL = "cancel_navigation"; + +// Supported actions from Apps -> VA + +// List of actions that are delivered from VA -> Apps +static list<string> NAVIGATION_UPSTREAM_ACTIONS = { + NAVIGATION_SET_DESTINATION, + NAVIGATION_CANCEL, +}; + +/* + ****************************************************************************************************** + * Supported actions from APPS -> VA + ****************************************************************************************************** + */ +static list<string> NAVIGATION_DOWNSTREAM_ACTIONS = {}; + +} // namespace navigation +} // namespace capabilities +} // namespace vshl + +#endif // VSHL_CAPABILITIES_NAVIGATION_ACTIONS_H_ diff --git a/src/plugins/capabilities/navigation/src/NavigationCapability.cpp b/src/plugins/capabilities/navigation/src/NavigationCapability.cpp new file mode 100644 index 0000000..e1c6cda --- /dev/null +++ b/src/plugins/capabilities/navigation/src/NavigationCapability.cpp @@ -0,0 +1,52 @@ +/* + * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0/ + * + * or in the "license" file accompanying this file. This file 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. + */ +#include "capabilities/navigation/include/NavigationCapability.h" +#include "capabilities/navigation/include/NavigationMessages.h" + +const string TAG = "vshlcapabilities::capabilities::navigation"; + +using Level = vshlcapabilities::common::interfaces::ILogger::Level; + +namespace vshlcapabilities { +namespace capabilities { +namespace navigation { + +// Create a Navigation. +shared_ptr<Navigation> Navigation::create( + shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger) { + auto navigation = std::shared_ptr<Navigation>(new Navigation(logger)); + return navigation; +} + +Navigation::Navigation( + shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger) { + mLogger = logger; +} + +string Navigation::getName() const { + return NAME; +} + +list<string> Navigation::getUpstreamMessages() const { + return NAVIGATION_UPSTREAM_ACTIONS; +} + +list<string> Navigation::getDownstreamMessages() const { + return NAVIGATION_DOWNSTREAM_ACTIONS; +} + +} // namespace navigation +} // namespace capabilities +} // namespace vshl diff --git a/src/plugins/capabilities/playbackcontroller/include/PlaybackControllerCapability.h b/src/plugins/capabilities/playbackcontroller/include/PlaybackControllerCapability.h new file mode 100644 index 0000000..e80b213 --- /dev/null +++ b/src/plugins/capabilities/playbackcontroller/include/PlaybackControllerCapability.h @@ -0,0 +1,57 @@ +/* + * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0/ + * + * or in the "license" file accompanying this file. This file 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. + */ + +#ifndef VSHL_CAPABILITIES_PLAYBACKCONTROLLER_CAPABILITY_H_ +#define VSHL_CAPABILITIES_PLAYBACKCONTROLLER_CAPABILITY_H_ + +#include <memory> + +#include "interfaces/capabilities/ICapability.h" +#include "interfaces/utilities/logging/ILogger.h" + +namespace vshlcapabilities { +namespace capabilities { +namespace playbackcontroller { + +/* + * PlaybackController capability. Calls are initiated in the endpoint. + */ +class PlaybackController : public common::interfaces::ICapability { +public: + // Create a PlaybackController. + static std::shared_ptr<PlaybackController> create( + shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger); + + ~PlaybackController() = default; + +protected: + string getName() const override; + + list<string> getUpstreamMessages() const override; + + list<string> getDownstreamMessages() const override; + +private: + PlaybackController( + shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger); + + shared_ptr<vshlcapabilities::common::interfaces::ILogger> mLogger; +}; + +} // namespace playbackcontroller +} // namespace capabilities +} // namespace vshl + +#endif // VSHL_CAPABILITIES_PLAYBACKCONTROLLER_CAPABILITY_H_ diff --git a/src/plugins/capabilities/playbackcontroller/include/PlaybackControllerMessages.h b/src/plugins/capabilities/playbackcontroller/include/PlaybackControllerMessages.h new file mode 100644 index 0000000..224b8dd --- /dev/null +++ b/src/plugins/capabilities/playbackcontroller/include/PlaybackControllerMessages.h @@ -0,0 +1,64 @@ +/* + * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0/ + * + * or in the "license" file accompanying this file. This file 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. + */ +#ifndef VSHL_CAPABILITIES_PLAYBACKCONTROLLER_MESSAGES_H_ +#define VSHL_CAPABILITIES_PLAYBACKCONTROLLER_MESSAGES_H_ + +#include <list> +#include <string> + +using namespace std; + +namespace vshlcapabilities { +namespace capabilities { +namespace playbackcontroller { + +static string NAME = "playbackcontroller"; + +/* + ****************************************************************************************************** + * Supported actions from APPS -> VA + ****************************************************************************************************** + */ +// List of actions that are delivered from VA -> Apps +static list<string> PLAYBACKCONTROLLER_UPSTREAM_ACTIONS = { + +}; + + +/* + ****************************************************************************************************** + * Supported actions from VA -> APPS + ****************************************************************************************************** + */ +// List of actions that are delivered from Apps -> VA +/* + * payload : + * { + * "button" : "{{STRING}}" // play, pause, next, previous, skip-forward, skip-backward + * } + * @param [in] button Button pressed by the user. + * + */ +static string PLAYBACKCONTROLLER_BUTTONPRESSED = "button_pressed"; + +static list<string> PLAYBACKCONTROLLER_DOWNSTREAM_ACTIONS = { + PLAYBACKCONTROLLER_BUTTONPRESSED +}; + +} // namespace playbackcontroller +} // namespace capabilities +} // namespace vshl + +#endif // VSHL_CAPABILITIES_PLAYBACKCONTROLLER_MESSAGES_H_ diff --git a/src/plugins/capabilities/playbackcontroller/src/PlaybackControllerCapability.cpp b/src/plugins/capabilities/playbackcontroller/src/PlaybackControllerCapability.cpp new file mode 100644 index 0000000..a5abbed --- /dev/null +++ b/src/plugins/capabilities/playbackcontroller/src/PlaybackControllerCapability.cpp @@ -0,0 +1,52 @@ +/* + * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0/ + * + * or in the "license" file accompanying this file. This file 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. + */ +#include "capabilities/playbackcontroller/include/PlaybackControllerCapability.h" +#include "capabilities/playbackcontroller/include/PlaybackControllerMessages.h" + +const string TAG = "vshlcapabilities::capabilities::playbackcontroller"; + +using Level = vshlcapabilities::common::interfaces::ILogger::Level; + +namespace vshlcapabilities { +namespace capabilities { +namespace playbackcontroller { + +// Create a playbackcontroller. +shared_ptr<PlaybackController> PlaybackController::create( + shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger) { + auto playbackcontroller = std::shared_ptr<PlaybackController>(new PlaybackController(logger)); + return playbackcontroller; +} + +PlaybackController::PlaybackController( + shared_ptr<vshlcapabilities::common::interfaces::ILogger> logger) { + mLogger = logger; +} + +string PlaybackController::getName() const { + return NAME; +} + +list<string> PlaybackController::getUpstreamMessages() const { + return PLAYBACKCONTROLLER_UPSTREAM_ACTIONS; +} + +list<string> PlaybackController::getDownstreamMessages() const { + return PLAYBACKCONTROLLER_DOWNSTREAM_ACTIONS; +} + +} // namespace playbackcontroller +} // namespace capabilities +} // namespace vshl diff --git a/src/plugins/capabilities/test/CapabilityMessagingServiceTest.cpp b/src/plugins/capabilities/test/CapabilityMessagingServiceTest.cpp new file mode 100644 index 0000000..5d3971d --- /dev/null +++ b/src/plugins/capabilities/test/CapabilityMessagingServiceTest.cpp @@ -0,0 +1,96 @@ +/* + * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0/ + * + * or in the "license" file accompanying this file. This file 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. + */ +#include <gtest/gtest.h> + +#include "capabilities/CapabilityMessagingService.h" + +#include "test/common/ConsoleLogger.h" +#include "test/mocks/AFBApiMock.h" +#include "test/mocks/AFBEventMock.h" +#include "test/mocks/AFBRequestMock.h" +#include "test/mocks/CapabilityMock.h" + +using namespace vshlcapabilities::common::interfaces; +using namespace vshlcapabilities::capabilities; +using namespace vshlcapabilities::test::common; + +namespace vshlcapabilities { +namespace test { + +class CapabilityMessagingServiceTest : public ::testing::Test { +protected: + void SetUp() override { + mConsoleLogger = std::make_shared<ConsoleLogger>(); + mAfbApi = std::make_shared<::testing::NiceMock<AFBApiMock>>(); + } + + std::shared_ptr<::testing::NiceMock<AFBApiMock>> mAfbApi; + std::shared_ptr<ConsoleLogger> mConsoleLogger; +}; + +TEST_F(CapabilityMessagingServiceTest, failsInitializationOnInvalidParams) { + auto service = CapabilityMessagingService::create(mConsoleLogger, nullptr); + ASSERT_EQ(service, nullptr); + + service = CapabilityMessagingService::create(nullptr, mAfbApi); + ASSERT_EQ(service, nullptr); +} + +TEST_F(CapabilityMessagingServiceTest, initializesSuccessfully) { + auto service = CapabilityMessagingService::create(mConsoleLogger, mAfbApi); + ASSERT_NE(service, nullptr); +} + +TEST_F(CapabilityMessagingServiceTest, canSubscribeAndPublishCapabilityEvents) { + auto service = CapabilityMessagingService::create(mConsoleLogger, mAfbApi); + + auto capability = std::make_shared<::testing::NiceMock<CapabilityMock>>(); + std::list<std::string> upstreamEvents({"up-ev1", "up-ev2"}); + std::list<std::string> downstreamEvents({"down-ev1", "down-ev2"}); + std::string capabilityName = "weather"; + + ON_CALL(*capability, getName()).WillByDefault(::testing::Return(capabilityName)); + ON_CALL(*capability, getUpstreamMessages()).WillByDefault(::testing::Return(upstreamEvents)); + ON_CALL(*capability, getDownstreamMessages()).WillByDefault(::testing::Return(downstreamEvents)); + + // We don't care if and how many times subscribe method is called on event. + std::shared_ptr<AFBEventMock> mockEvent(new ::testing::NiceMock<AFBEventMock>()); + ON_CALL(*mockEvent, subscribe(::testing::_)).WillByDefault(::testing::Return(true)); + ON_CALL(*mockEvent, publishEvent(::testing::_)).WillByDefault(::testing::Return(true)); + auto eventCreator = [mockEvent](const std::string& eventName) -> std::shared_ptr<IAFBApi::IAFBEvent> { + mockEvent->setName(eventName); + return mockEvent; + }; + + ON_CALL(*mAfbApi, createEvent(::testing::_)).WillByDefault(::testing::Invoke(eventCreator)); + + auto request = std::make_shared<::testing::StrictMock<AFBRequestMock>>(); + std::string payload = "The answer to life the universe and everything = 42"; + + bool result = service->publish(capability, *upstreamEvents.begin(), payload); + ASSERT_FALSE(result); // Without subscribing to the event. Publish should fail. + + result = service->subscribe(*request, capability, *upstreamEvents.begin()); + ASSERT_TRUE(result); + + result = service->subscribe(*request, capability, *downstreamEvents.begin()); + ASSERT_TRUE(result); + + result = service->publish(capability, *downstreamEvents.begin(), payload); + ASSERT_TRUE(result); +} + +} // namespace test +} // namespace vshl
\ No newline at end of file diff --git a/src/plugins/capabilities/test/PublisherForwarderTest.cpp b/src/plugins/capabilities/test/PublisherForwarderTest.cpp new file mode 100644 index 0000000..8fb499c --- /dev/null +++ b/src/plugins/capabilities/test/PublisherForwarderTest.cpp @@ -0,0 +1,116 @@ +/* + * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0/ + * + * or in the "license" file accompanying this file. This file 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. + */ +#include <gtest/gtest.h> + +#include "capabilities/core/include/PublisherForwarder.h" +#include "capabilities/core/include/SubscriberForwarder.h" + +#include "test/common/ConsoleLogger.h" +#include "test/mocks/AFBApiMock.h" +#include "test/mocks/AFBEventMock.h" +#include "test/mocks/CapabilityMock.h" + +using namespace vshlcapabilities::common::interfaces; +using namespace vshlcapabilities::capabilities::core; +using namespace vshlcapabilities::test::common; + +namespace vshlcapabilities { +namespace test { + +class PublisherForwarderTest : public ::testing::Test { +protected: + void SetUp() override { + mConsoleLogger = std::make_shared<ConsoleLogger>(); + mAfbApi = std::make_shared<::testing::StrictMock<AFBApiMock>>(); + + mEventCreatorFn = [](const std::string& eventName) -> std::shared_ptr<IAFBApi::IAFBEvent> { + std::shared_ptr<AFBEventMock> mockEvent(new ::testing::StrictMock<AFBEventMock>()); + mockEvent->setName(eventName); + return mockEvent; + }; + } + + std::shared_ptr<SubscriberForwarder> createSubscriberForwarder( + std::shared_ptr<::testing::StrictMock<CapabilityMock>> capability) { + EXPECT_CALL(*capability, getUpstreamMessages()).Times(1); + EXPECT_CALL(*capability, getDownstreamMessages()).Times(1); + + return SubscriberForwarder::create(mConsoleLogger, mAfbApi, capability); + } + + std::shared_ptr<PublisherForwarder> createPublisherForwarder( + std::shared_ptr<::testing::StrictMock<CapabilityMock>> capability) { + return PublisherForwarder::create(mConsoleLogger, capability); + } + + std::shared_ptr<::testing::StrictMock<AFBApiMock>> mAfbApi; + std::shared_ptr<ConsoleLogger> mConsoleLogger; + std::function<std::shared_ptr<IAFBApi::IAFBEvent>(const std::string&)> mEventCreatorFn; + std::shared_ptr<::testing::StrictMock<AFBEventMock>> mAfbEventMock; +}; + +TEST_F(PublisherForwarderTest, failsInitializationOnInvalidParams) { + auto capability = std::make_shared<::testing::StrictMock<CapabilityMock>>(); + + auto forwarder = PublisherForwarder::create(mConsoleLogger, nullptr); + ASSERT_EQ(forwarder, nullptr); + + forwarder = PublisherForwarder::create(nullptr, capability); + ASSERT_EQ(forwarder, nullptr); +} + +TEST_F(PublisherForwarderTest, initializesCorrectly) { + auto capability = std::make_shared<::testing::StrictMock<CapabilityMock>>(); + auto forwarder = createPublisherForwarder(capability); + + ASSERT_NE(forwarder, nullptr); +} + +TEST_F(PublisherForwarderTest, canForwardMessages) { + std::shared_ptr<AFBEventMock> mockEvent(new ::testing::StrictMock<AFBEventMock>()); + ON_CALL(*mockEvent, publishEvent(::testing::_)).WillByDefault(::testing::Return(true)); + EXPECT_CALL(*mockEvent, publishEvent(::testing::_)).Times(4); + auto eventCreator = [mockEvent](const std::string& eventName) -> std::shared_ptr<IAFBApi::IAFBEvent> { + return mockEvent; + }; + + ON_CALL(*mAfbApi, createEvent(::testing::_)).WillByDefault(::testing::Invoke(eventCreator)); + EXPECT_CALL(*mAfbApi, createEvent(::testing::_)).Times(4); + + auto capability = std::make_shared<::testing::StrictMock<CapabilityMock>>(); + std::list<std::string> upstreamEvents({"up-ev1", "up-ev2"}); + std::list<std::string> downstreamEvents({"down-ev1", "down-ev2"}); + ON_CALL(*capability, getUpstreamMessages()).WillByDefault(::testing::Return(upstreamEvents)); + ON_CALL(*capability, getDownstreamMessages()).WillByDefault(::testing::Return(downstreamEvents)); + + auto publisherForwarder = createPublisherForwarder(capability); + ASSERT_NE(publisherForwarder, nullptr); + + auto subscriberForwarder = createSubscriberForwarder(capability); + ASSERT_NE(subscriberForwarder, nullptr); + + std::string payload = "The answer to life the universe and everything = 42"; + publisherForwarder->setSubscriberForwarder(subscriberForwarder); + + auto itCapability = downstreamEvents.begin(); + ASSERT_TRUE(publisherForwarder->forwardMessage(*itCapability++, payload)); + ASSERT_TRUE(publisherForwarder->forwardMessage(*itCapability++, payload)); + itCapability = upstreamEvents.begin(); + ASSERT_TRUE(publisherForwarder->forwardMessage(*itCapability++, payload)); + ASSERT_TRUE(publisherForwarder->forwardMessage(*itCapability++, payload)); +} + +} // namespace test +} // namespace vshl
\ No newline at end of file diff --git a/src/plugins/capabilities/test/SubscriberForwarderTest.cpp b/src/plugins/capabilities/test/SubscriberForwarderTest.cpp new file mode 100644 index 0000000..c3d72de --- /dev/null +++ b/src/plugins/capabilities/test/SubscriberForwarderTest.cpp @@ -0,0 +1,262 @@ +/* + * Copyright 2018-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"). + * You may not use this file except in compliance with the License. + * A copy of the License is located at + * + * http://aws.amazon.com/apache2.0/ + * + * or in the "license" file accompanying this file. This file 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. + */ +#include <gtest/gtest.h> + +#include "capabilities/core/include/SubscriberForwarder.h" + +#include "test/common/ConsoleLogger.h" +#include "test/mocks/AFBApiMock.h" +#include "test/mocks/AFBEventMock.h" +#include "test/mocks/AFBRequestMock.h" +#include "test/mocks/CapabilityMock.h" + +using namespace vshlcapabilities::common::interfaces; +using namespace vshlcapabilities::capabilities::core; +using namespace vshlcapabilities::test::common; + +namespace vshlcapabilities { +namespace test { + +class SubscriberForwarderTest : public ::testing::Test { +protected: + void SetUp() override { + mConsoleLogger = std::make_shared<ConsoleLogger>(); + mAfbApi = std::make_shared<::testing::StrictMock<AFBApiMock>>(); + + mEventCreatorFn = [](const std::string& eventName) -> std::shared_ptr<IAFBApi::IAFBEvent> { + std::shared_ptr<AFBEventMock> mockEvent(new ::testing::StrictMock<AFBEventMock>()); + mockEvent->setName(eventName); + return mockEvent; + }; + } + + std::shared_ptr<SubscriberForwarder> createSubscriberForwarder( + std::shared_ptr<::testing::StrictMock<CapabilityMock>> capability) { + EXPECT_CALL(*capability, getUpstreamMessages()).Times(1); + EXPECT_CALL(*capability, getDownstreamMessages()).Times(1); + + return SubscriberForwarder::create(mConsoleLogger, mAfbApi, capability); + } + + std::shared_ptr<::testing::StrictMock<AFBApiMock>> mAfbApi; + std::shared_ptr<ConsoleLogger> mConsoleLogger; + std::function<std::shared_ptr<IAFBApi::IAFBEvent>(const std::string&)> mEventCreatorFn; + std::shared_ptr<::testing::StrictMock<AFBEventMock>> mAfbEventMock; +}; + +TEST_F(SubscriberForwarderTest, failsInitializationOnInvalidParams) { + auto capability = std::make_shared<::testing::StrictMock<CapabilityMock>>(); + + auto forwarder = SubscriberForwarder::create(mConsoleLogger, mAfbApi, nullptr); + ASSERT_EQ(forwarder, nullptr); + + forwarder = SubscriberForwarder::create(mConsoleLogger, nullptr, capability); + ASSERT_EQ(forwarder, nullptr); + + forwarder = SubscriberForwarder::create(nullptr, mAfbApi, capability); + ASSERT_EQ(forwarder, nullptr); +} + +TEST_F(SubscriberForwarderTest, initializesCorrectly) { + auto capability = std::make_shared<::testing::StrictMock<CapabilityMock>>(); + auto forwarder = createSubscriberForwarder(capability); + + ASSERT_NE(forwarder, nullptr); +} + +TEST_F(SubscriberForwarderTest, createsEventsOnInitialization) { + ON_CALL(*mAfbApi, createEvent(::testing::_)).WillByDefault(::testing::Invoke(mEventCreatorFn)); + + std::list<std::string> upstreamEvents({"up-ev1", "up-ev2"}); + std::list<std::string> downstreamEvents({"down-ev1", "down-ev2"}); + + auto capability = std::make_shared<::testing::StrictMock<CapabilityMock>>(); + ON_CALL(*capability, getUpstreamMessages()).WillByDefault(::testing::Return(upstreamEvents)); + ON_CALL(*capability, getDownstreamMessages()).WillByDefault(::testing::Return(downstreamEvents)); + + auto itCapability = upstreamEvents.begin(); + EXPECT_CALL(*mAfbApi, createEvent(*itCapability)).Times(1); + itCapability++; + EXPECT_CALL(*mAfbApi, createEvent(*itCapability)).Times(1); + + itCapability = downstreamEvents.begin(); + EXPECT_CALL(*mAfbApi, createEvent(*itCapability)).Times(1); + itCapability++; + EXPECT_CALL(*mAfbApi, createEvent(*itCapability)).Times(1); + + auto forwarder = createSubscriberForwarder(capability); + ASSERT_NE(forwarder, nullptr); +} + +TEST_F(SubscriberForwarderTest, canNotSubscribeToNonExistentEvents) { + ON_CALL(*mAfbApi, createEvent(::testing::_)).WillByDefault(::testing::Invoke(mEventCreatorFn)); + EXPECT_CALL(*mAfbApi, createEvent(::testing::_)).Times(4); + + std::list<std::string> upstreamEvents({"up-ev1", "up-ev2"}); + std::list<std::string> downstreamEvents({"down-ev1", "down-ev2"}); + + auto capability = std::make_shared<::testing::StrictMock<CapabilityMock>>(); + ON_CALL(*capability, getUpstreamMessages()).WillByDefault(::testing::Return(upstreamEvents)); + ON_CALL(*capability, getDownstreamMessages()).WillByDefault(::testing::Return(downstreamEvents)); + + auto forwarder = createSubscriberForwarder(capability); + ASSERT_NE(forwarder, nullptr); + + auto nonExistentEvents = std::list<std::string>({"non", "existent", "events"}); + auto itCapability = nonExistentEvents.begin(); + auto request = std::make_shared<::testing::StrictMock<AFBRequestMock>>(); + ASSERT_FALSE(forwarder->subscribe(*request, *itCapability++)); + ASSERT_FALSE(forwarder->subscribe(*request, *itCapability++)); + ASSERT_FALSE(forwarder->subscribe(*request, *itCapability++)); +} + +TEST_F(SubscriberForwarderTest, canNotSubscribeOnEventCreationFailure) { + // Fail the event creation and return null event. + ON_CALL(*mAfbApi, createEvent(::testing::_)).WillByDefault(::testing::Return(nullptr)); + EXPECT_CALL(*mAfbApi, createEvent(::testing::_)).Times(4); + + std::list<std::string> upstreamEvents({"up-ev1", "up-ev2"}); + std::list<std::string> downstreamEvents({"down-ev1", "down-ev2"}); + + auto capability = std::make_shared<::testing::StrictMock<CapabilityMock>>(); + ON_CALL(*capability, getUpstreamMessages()).WillByDefault(::testing::Return(upstreamEvents)); + ON_CALL(*capability, getDownstreamMessages()).WillByDefault(::testing::Return(downstreamEvents)); + + auto forwarder = createSubscriberForwarder(capability); + ASSERT_NE(forwarder, nullptr); + + auto itCapability = downstreamEvents.begin(); + auto request = std::make_shared<::testing::StrictMock<AFBRequestMock>>(); + std::string payload = "The answer to life the universe and everything = 42"; + ASSERT_FALSE(forwarder->subscribe(*request, *itCapability++)); + ASSERT_FALSE(forwarder->subscribe(*request, *itCapability++)); + itCapability = upstreamEvents.begin(); + ASSERT_FALSE(forwarder->subscribe(*request, *itCapability++)); + ASSERT_FALSE(forwarder->subscribe(*request, *itCapability++)); +} + +TEST_F(SubscriberForwarderTest, canSubscribeToEvents) { + std::shared_ptr<AFBEventMock> mockEvent(new ::testing::StrictMock<AFBEventMock>()); + ON_CALL(*mockEvent, subscribe(::testing::_)).WillByDefault(::testing::Return(true)); + EXPECT_CALL(*mockEvent, subscribe(::testing::_)).Times(4); + auto eventCreator = [mockEvent](const std::string& eventName) -> std::shared_ptr<IAFBApi::IAFBEvent> { + return mockEvent; + }; + + ON_CALL(*mAfbApi, createEvent(::testing::_)).WillByDefault(::testing::Invoke(eventCreator)); + EXPECT_CALL(*mAfbApi, createEvent(::testing::_)).Times(4); + + std::list<std::string> upstreamEvents({"up-ev1", "up-ev2"}); + std::list<std::string> downstreamEvents({"down-ev1", "down-ev2"}); + + auto capability = std::make_shared<::testing::StrictMock<CapabilityMock>>(); + ON_CALL(*capability, getUpstreamMessages()).WillByDefault(::testing::Return(upstreamEvents)); + ON_CALL(*capability, getDownstreamMessages()).WillByDefault(::testing::Return(downstreamEvents)); + + auto forwarder = createSubscriberForwarder(capability); + ASSERT_NE(forwarder, nullptr); + + auto itCapability = downstreamEvents.begin(); + auto request = std::make_shared<::testing::StrictMock<AFBRequestMock>>(); + ASSERT_TRUE(forwarder->subscribe(*request, *itCapability++)); + ASSERT_TRUE(forwarder->subscribe(*request, *itCapability)); + itCapability = upstreamEvents.begin(); + ASSERT_TRUE(forwarder->subscribe(*request, *itCapability++)); + ASSERT_TRUE(forwarder->subscribe(*request, *itCapability)); +} + +TEST_F(SubscriberForwarderTest, canNotPublishNonExistentEvents) { + std::shared_ptr<AFBEventMock> mockEvent(new ::testing::StrictMock<AFBEventMock>()); + EXPECT_CALL(*mockEvent, publishEvent(::testing::_)).Times(0); + auto eventCreator = [mockEvent](const std::string& eventName) -> std::shared_ptr<IAFBApi::IAFBEvent> { + return mockEvent; + }; + + ON_CALL(*mAfbApi, createEvent(::testing::_)).WillByDefault(::testing::Invoke(eventCreator)); + EXPECT_CALL(*mAfbApi, createEvent(::testing::_)).Times(4); + + std::list<std::string> upstreamEvents({"up-ev1", "up-ev2"}); + std::list<std::string> downstreamEvents({"down-ev1", "down-ev2"}); + + auto capability = std::make_shared<::testing::StrictMock<CapabilityMock>>(); + ON_CALL(*capability, getUpstreamMessages()).WillByDefault(::testing::Return(upstreamEvents)); + ON_CALL(*capability, getDownstreamMessages()).WillByDefault(::testing::Return(downstreamEvents)); + + auto forwarder = createSubscriberForwarder(capability); + ASSERT_NE(forwarder, nullptr); + + auto nonExistentEvents = std::list<std::string>({"non", "existent", "events"}); + auto itCapability = nonExistentEvents.begin(); + ASSERT_FALSE(forwarder->forwardMessage(*itCapability++, "My-Payload")); + ASSERT_FALSE(forwarder->forwardMessage(*itCapability++, "My-Payload")); + ASSERT_FALSE(forwarder->forwardMessage(*itCapability++, "My-Payload")); +} + +TEST_F(SubscriberForwarderTest, canNotPublishOnEventCreationFailure) { + // Fail the event creation and return null event. + ON_CALL(*mAfbApi, createEvent(::testing::_)).WillByDefault(::testing::Return(nullptr)); + EXPECT_CALL(*mAfbApi, createEvent(::testing::_)).Times(4); + + std::list<std::string> upstreamEvents({"up-ev1", "up-ev2"}); + std::list<std::string> downstreamEvents({"down-ev1", "down-ev2"}); + + auto capability = std::make_shared<::testing::StrictMock<CapabilityMock>>(); + ON_CALL(*capability, getUpstreamMessages()).WillByDefault(::testing::Return(upstreamEvents)); + ON_CALL(*capability, getDownstreamMessages()).WillByDefault(::testing::Return(downstreamEvents)); + + auto forwarder = createSubscriberForwarder(capability); + ASSERT_NE(forwarder, nullptr); + + auto itCapability = downstreamEvents.begin(); + std::string payload = "The answer to life the universe and everything = 42"; + ASSERT_FALSE(forwarder->forwardMessage(*itCapability++, payload)); + ASSERT_FALSE(forwarder->forwardMessage(*itCapability++, payload)); + itCapability = upstreamEvents.begin(); + ASSERT_FALSE(forwarder->forwardMessage(*itCapability++, payload)); + ASSERT_FALSE(forwarder->forwardMessage(*itCapability++, payload)); +} + +TEST_F(SubscriberForwarderTest, canPublishEvents) { + std::shared_ptr<AFBEventMock> mockEvent(new ::testing::StrictMock<AFBEventMock>()); + ON_CALL(*mockEvent, publishEvent(::testing::_)).WillByDefault(::testing::Return(true)); + EXPECT_CALL(*mockEvent, publishEvent(::testing::_)).Times(4); + auto eventCreator = [mockEvent](const std::string& eventName) -> std::shared_ptr<IAFBApi::IAFBEvent> { + return mockEvent; + }; + + ON_CALL(*mAfbApi, createEvent(::testing::_)).WillByDefault(::testing::Invoke(eventCreator)); + EXPECT_CALL(*mAfbApi, createEvent(::testing::_)).Times(4); + + std::list<std::string> upstreamEvents({"up-ev1", "up-ev2"}); + std::list<std::string> downstreamEvents({"down-ev1", "down-ev2"}); + + auto capability = std::make_shared<::testing::StrictMock<CapabilityMock>>(); + ON_CALL(*capability, getUpstreamMessages()).WillByDefault(::testing::Return(upstreamEvents)); + ON_CALL(*capability, getDownstreamMessages()).WillByDefault(::testing::Return(downstreamEvents)); + + auto forwarder = createSubscriberForwarder(capability); + ASSERT_NE(forwarder, nullptr); + + auto itCapability = downstreamEvents.begin(); + std::string payload = "The answer to life the universe and everything = 42"; + ASSERT_TRUE(forwarder->forwardMessage(*itCapability++, payload)); + ASSERT_TRUE(forwarder->forwardMessage(*itCapability++, payload)); + itCapability = upstreamEvents.begin(); + ASSERT_TRUE(forwarder->forwardMessage(*itCapability++, payload)); + ASSERT_TRUE(forwarder->forwardMessage(*itCapability++, payload)); +} + +} // namespace test +} // namespace vshl
\ No newline at end of file |