|  | /* | 
|  | * Copyright 2023 Google LLC | 
|  | * | 
|  | * 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. | 
|  | */ | 
|  |  | 
|  | #include "subscription.h" | 
|  |  | 
|  | #include <functional> | 
|  | #include <string> | 
|  | #include <utility> | 
|  |  | 
|  | #include "absl/container/flat_hash_map.h" | 
|  | #include "absl/container/flat_hash_set.h" | 
|  | #include "absl/hash/hash.h" | 
|  | #include "absl/status/status.h" | 
|  | #include "absl/status/statusor.h" | 
|  | #include "absl/strings/string_view.h" | 
|  | #include "absl/time/time.h" | 
|  | #include "nlohmann/json.hpp" | 
|  |  | 
|  | namespace ecclesia { | 
|  |  | 
|  | // EventSourceId definitions | 
|  |  | 
|  | nlohmann::json EventSourceId::ToJSON() const { | 
|  | nlohmann::json json; | 
|  | json["key"] = key; | 
|  | switch (type) { | 
|  | case Type::kDbusObjects: | 
|  | json["type"] = "kDbusObjects"; | 
|  | break; | 
|  | case Type::kSocketIO: | 
|  | json["type"] = "kSocketIO"; | 
|  | break; | 
|  | case Type::kFileIO: | 
|  | json["type"] = "kFileIO"; | 
|  | break; | 
|  | } | 
|  | return json; | 
|  | } | 
|  |  | 
|  | std::string EventSourceId::ToString() const { return this->ToJSON().dump(); } | 
|  |  | 
|  | // EventId definitions. | 
|  |  | 
|  | EventId::EventId(const SubscriptionId& subscription_id_in, | 
|  | const EventSourceId& source_id_in, absl::Time timestamp_in) | 
|  | : source_id(source_id_in), | 
|  | timestamp(timestamp_in), | 
|  | subscription_id(subscription_id_in), | 
|  | redfish_event_id( | 
|  | absl::HashOf(timestamp_in, source_id_in, subscription_id_in)) {} | 
|  |  | 
|  | nlohmann::json EventId::ToJSON() const { | 
|  | nlohmann::json json; | 
|  | json["source_id"] = source_id.ToJSON(); | 
|  | json["timestamp"] = | 
|  | absl::FormatTime(absl::RFC3339_full, timestamp, absl::UTCTimeZone()); | 
|  | json["uuid"] = redfish_event_id; | 
|  | return json; | 
|  | } | 
|  |  | 
|  | std::string EventId::ToString() const { return this->ToJSON().dump(); } | 
|  |  | 
|  | // SubscriptionContext definitions. | 
|  |  | 
|  | SubscriptionContext::SubscriptionContext( | 
|  | const SubscriptionId& subscription_id_in, | 
|  | const absl::flat_hash_map<EventSourceId, absl::flat_hash_set<std::string>>& | 
|  | event_source_to_uris_in, | 
|  | absl::flat_hash_map<std::string, Trigger> id_to_triggers_in, | 
|  | std::function<void(const nlohmann::json&)>&& on_event_callback_in) | 
|  | : subscription_id(subscription_id_in), | 
|  | event_source_to_uri(event_source_to_uris_in), | 
|  | id_to_triggers(std::move(id_to_triggers_in)), | 
|  | on_event_callback(std::move(on_event_callback_in)) {} | 
|  |  | 
|  | // Trigger definitions. | 
|  |  | 
|  | absl::StatusOr<Trigger> Trigger::Create(const nlohmann::json& trigger_json) { | 
|  | // Check if json is valid. | 
|  | if (trigger_json.is_discarded()) { | 
|  | return absl::InvalidArgumentError("Trigger json is discarded"); | 
|  | } | 
|  |  | 
|  | // Parse the JSON data | 
|  | auto find_id = trigger_json.find("Id"); | 
|  | if (find_id == trigger_json.end()) { | 
|  | return absl::InvalidArgumentError("Trigger Id not populated"); | 
|  | } | 
|  | // Extract trigger information from the JSON data | 
|  | const std::string id = find_id->get<std::string>(); | 
|  |  | 
|  | auto find_origin_resources = trigger_json.find("OriginResources"); | 
|  | if (find_origin_resources == trigger_json.end()) { | 
|  | return absl::InvalidArgumentError("Origin resources not populated"); | 
|  | } | 
|  |  | 
|  | absl::flat_hash_set<std::string> origin_resources; | 
|  | for (const auto& origin_resource : *find_origin_resources) { | 
|  | origin_resources.insert(origin_resource["@odata.id"].get<std::string>()); | 
|  | } | 
|  |  | 
|  | std::string predicate; | 
|  | bool event_mask = false; | 
|  |  | 
|  | auto find_predicate = trigger_json.find("Predicate"); | 
|  | if (find_predicate != trigger_json.end()) { | 
|  | predicate = *find_predicate; | 
|  | } else { | 
|  | // If predicate is not provided, this trigger will be used to poll data. | 
|  | // TODO(rahulkpr): Handle the polling case after adding trigger associations | 
|  | event_mask = true; | 
|  | } | 
|  |  | 
|  | // Create a Trigger object with the extracted information | 
|  | Trigger trigger(id, std::move(origin_resources), predicate, event_mask); | 
|  |  | 
|  | return trigger; | 
|  | } | 
|  |  | 
|  | Trigger::Trigger(absl::string_view id_in, | 
|  | absl::flat_hash_set<std::string> origin_resources_in, | 
|  | absl::string_view predicate_in, bool mask_in) | 
|  | : id(id_in), | 
|  | origin_resources(std::move(origin_resources_in)), | 
|  | predicate(predicate_in), | 
|  | mask(mask_in) {} | 
|  |  | 
|  | nlohmann::json Trigger::ToJSON() const { | 
|  | nlohmann::json json; | 
|  |  | 
|  | // Create json array and store all origin_resources | 
|  | nlohmann::json& origin_resources_json = json["origin_resources"]; | 
|  | origin_resources_json = nlohmann::json::array(); | 
|  | origin_resources_json.insert_iterator(origin_resources_json.end(), | 
|  | origin_resources.begin(), | 
|  | origin_resources.end()); | 
|  | json["predicate"] = predicate; | 
|  | json["mask"] = mask; | 
|  | return json; | 
|  | } | 
|  |  | 
|  | std::string Trigger::ToString() const { return this->ToJSON().dump(); } | 
|  |  | 
|  | }  // namespace ecclesia |