WSF
ScenarioAnalyzerUtilities.hpp
Go to the documentation of this file.
1// ****************************************************************************
2// CUI
3//
4// The Advanced Framework for Simulation, Integration, and Modeling (AFSIM)
5//
6// The use, dissemination or disclosure of data in this file is subject to
7// limitation or restriction. See accompanying README and LICENSE for details.
8// ****************************************************************************
9/*******************************************************************************
10*
11* File: ScenarioAnalyzerUtilities.hpp
12*
13* Classification: UNCLASSIFIED
14*
15* Details:
16*
17* Contract Number:
18* Contractor Name: Radiance Technologies
19* Address: 350 Wynn Drive
20* Huntsville, AL 35805
21*
22* Abstract:
23*
24*******************************************************************************/
25
26#ifndef SCENARIO_ANALYZER_UTILITIES_HPP
27#define SCENARIO_ANALYZER_UTILITIES_HPP
28
29#include "wsf_scenario_analyzer_lib_export.h"
30
31#include <functional>
32#include <string>
33#include <vector>
34
36#include "WsfCommUtil.hpp"
37#include "WsfCommXmtrRcvr.hpp"
38#include "WsfCommandChain.hpp"
39#include "WsfExternalLinks.hpp"
40#include "WsfGroupManager.hpp"
41#include "WsfInternalLinks.hpp"
43#include "WsfPlatform.hpp"
44#include "WsfPlatformPart.hpp"
45#include "WsfProcessor.hpp"
47#include "WsfStringId.hpp"
50
51class WsfApplication;
54namespace wsf
55{
56namespace comm
57{
58class Comm;
59}
60}
61
62
63// plug-in interface
65
66using PlatformCheck = std::function<bool(WsfPlatform*)>;
67using Messages = std::vector<ScenarioAnalyzerMessage>;
68
69// Templated function for running a check.
70// Expects a function pointer that will add any error/warning messages to "Messages"
71// and return true/false if there were no errors/warnings.
72//
73// Should be called by all check functions;
74template<typename TFunc>
75WSF_SCENARIO_ANALYZER_LIB_EXPORT Messages runSuiteCheck(const std::string& aSuiteName,
76 const std::string& aCheckName,
78 WsfSimulation& aSimulation,
79 TFunc aFunction,
80 bool aWriteFlag = true)
81{
82 Messages messages;
83
85 message.SetSuiteName(aSuiteName);
86 message.SetCheckName(aCheckName);
87 message.SetSeverity(aSeverity);
88
89 if (aFunction(aSimulation, messages, message))
90 {
91 message.SetSuccessful();
92 messages.push_back(message);
93 }
94
95 if (aWriteFlag)
96 {
97 for (const auto& m : messages)
98 {
99 m.Write();
100 }
101 }
102
103 return messages;
104}
105
106// Utilities for identifying platforms and platforms parts linked in various ways to a source platform or platform part
107template<typename T>
109template<typename T>
110std::vector<T*> getInternallyLinkedPlatformParts(WsfPlatformPart* origin, std::vector<WsfPlatformPart*>& visited);
111
112template<typename T>
113extern std::vector<T*> getLinkedAndReachablePlatformParts(WsfPlatformPart* origin, const std::vector<std::string>& ignoreExternalLinks, bool follow);
114template<typename T>
115extern std::vector<T*> getLinkedAndReachablePlatformParts(WsfPlatformPart* origin);
116
117template<typename T>
118extern std::vector<T*> getLinkedAndReachablePlatformParts(
119 WsfPlatformPart* origin,
120 std::vector<WsfPlatform*>& visitedPlatforms,
121 std::vector<wsf::comm::Comm*>& visitedComms,
122 const std::vector<std::string>& ignoreOrFollowExternalLinks,
123 bool follow);
124
125template<typename T>
126extern std::vector<T*> getLinkedAndReachablePlatformParts(
127 wsf::ExternalLinks& links,
128 WsfPlatform* platform,
129 std::vector<WsfPlatform*>& visitedPlatforms,
130 std::vector<wsf::comm::Comm*>& visitedComms,
131 const std::vector<std::string>& ignoreOrFollowExternalLinks,
132 bool follow);
133
134
135// Utilities for navigating and performing checks on command chains
136WSF_SCENARIO_ANALYZER_LIB_EXPORT WsfPlatform* getTopCommander(WsfStringId commandChainName, WsfPlatform* platform);
137WSF_SCENARIO_ANALYZER_LIB_EXPORT bool checkUpCommandChain(WsfPlatform* platform, PlatformCheck check);
138WSF_SCENARIO_ANALYZER_LIB_EXPORT bool checkUpCommandChain(WsfPlatform* platform, PlatformCheck check, WsfStringId commandChainName);
139WSF_SCENARIO_ANALYZER_LIB_EXPORT bool checkDownCommandChain(WsfPlatform* platform, PlatformCheck check);
140WSF_SCENARIO_ANALYZER_LIB_EXPORT bool checkDownCommandChain(WsfPlatform* platform, PlatformCheck check, WsfStringId commandChainName);
141WSF_SCENARIO_ANALYZER_LIB_EXPORT bool checkFullCommandChain(WsfPlatform* platform, PlatformCheck check);
142
143// Convert a list of ScenarioAnalyzerMessages to Array<ScenarioAnalyzerMessage>
144WSF_SCENARIO_ANALYZER_LIB_EXPORT void ConvertMessagesToScript(const Messages& aMessages,
145 UtScriptData& aReturnVal,
146 UtScriptContext& aContext,
147 UtScriptClass* aReturnClassPtr);
148
149template<typename T>
150std::vector<T*> getAllPartsDownCommandChain(WsfPlatform* platform);
151template<typename T>
152std::vector<T*> getAllPartsDownCommandChain(WsfPlatform* platform, WsfStringId commandChainName);
153
154// Returns a vector of pointers to all WsfPlatformParts of type T that are (1) on the same platform as platformPart
155// (2) are connected to platformPart by an internal link coming from platformPart.
156template<typename T>
158{
159 std::vector<WsfPlatformPart*> visited;
160 return getInternallyLinkedPlatformParts<T>(platformPart, visited);
161}
162
163// Helper function for getInternallyLinkedPlatformParts(WsfPlatformPart*)
164template<typename T>
165std::vector<T*> getInternallyLinkedPlatformParts(WsfPlatformPart* platformPart, std::vector<WsfPlatformPart*>& visited)
166{
167 std::vector<T*> linkedPlatformParts;
168 visited.push_back(platformPart);
169
170 WsfInternalLinks& internalLinks = platformPart->GetInternalLinks();
171 unsigned internalLinksCount = internalLinks.GetRecipientCount();
172 for (unsigned int i = 0; i != internalLinksCount; ++i)
173 {
174 WsfPlatformPart* recipient = internalLinks.GetRecipientEntry(i);
175 // Don't check or recurse on this recipient if it has already been visited.
176 if (recipient && find(visited.begin(), visited.end(), recipient) == visited.end())
177 {
178 auto tPtr = dynamic_cast<T*>(recipient);
179 if (tPtr != nullptr)
180 {
181 linkedPlatformParts.push_back(tPtr);
182 }
183 // Whether or not recipient matches the specified type, recursively check its internal links
184 std::vector<T*> indirectlyLinked = getInternallyLinkedPlatformParts<T>(recipient, visited);
185 linkedPlatformParts.insert(linkedPlatformParts.end(), indirectlyLinked.begin(), indirectlyLinked.end());
186 }
187 }
188 return linkedPlatformParts;
189}
190
191// Returns a vector of pointers to all platform parts of type T on platform or any of its subordinates on any command chain.
192template<typename T>
193std::vector<T*> getAllPartsDownCommandChain(WsfPlatform* platform)
194{
195 std::vector<T*> results;
196 // First, check for any parts of type T on the origin platform that pass the check
197 unsigned partCount = platform->GetComponentCount<WsfPlatformPart>();
198 for (unsigned i = 0; i != partCount; ++i)
199 {
200 auto part = dynamic_cast<T*>(platform->GetComponentEntry<WsfPlatformPart>(i));
201 if (part != nullptr)
202 {
203 results.push_back(part);
204 }
205 }
206
207 // Then, check subordiantes
208 unsigned chainCount = platform->GetComponentCount<WsfCommandChain>();
209 for (unsigned j = 0; j < chainCount; ++j)
210 {
211 std::vector<WsfPlatform*> subordinates = platform->GetComponentEntry<WsfCommandChain>(j)->GetSubordinates();
212 for (auto s : subordinates)
213 {
214 if (s != nullptr)
215 {
216 std::vector<T*> subResults = getAllPartsDownCommandChain<T>(s);
217 results.insert(results.end(), subResults.begin(), subResults.end());
218 }
219 }
220 }
221
222 std::sort(results.begin(), results.end(), [](T * a, T * b)
223 {
224 return (a->GetPlatform()->GetNameId() < b->GetPlatform()->GetNameId()) ||
225 (a->GetPlatform()->GetNameId() == b->GetPlatform()->GetNameId() && a->GetNameId() < b->GetNameId());
226 });
227 typename std::vector<T*>::iterator end = std::unique(results.begin(), results.end(), [](T * a, T * b) { return a->GetNameId() == b->GetNameId(); });
228 std::vector<T*> uniqueResults(results.begin(), end);
229 return uniqueResults;
230}
231
232// Returns a vector of pointers to all platform parts of type T on platform or any of its subordinates on the specified command chain.
233template<typename T>
234std::vector<T*> getAllPartsDownCommandChain(WsfPlatform* platform, WsfStringId commandChainName)
235{
236 std::vector<T*> results;
237 // First, check for any parts of type T on the origin platform that pass the check
238 unsigned partCount = platform->GetComponentCount<WsfPlatformPart>();
239 for (unsigned i = 0; i != partCount; ++i)
240 {
241 auto part = dynamic_cast<T*>(platform->GetComponentEntry<WsfPlatformPart>(i));
242 if (part != nullptr)
243 {
244 results.push_back(part);
245 }
246 }
247
248 // Then, check subordiantes
249 WsfCommandChain* commandChain = platform->GetComponent<WsfCommandChain>(commandChainName);
250 if (commandChain)
251 {
252 std::vector<WsfPlatform*> subordinates = commandChain->GetSubordinates();
253 for (auto s : subordinates)
254 {
255 if (s != nullptr)
256 {
257 std::vector<T*> subResults = getAllPartsDownCommandChain<T>(s, commandChainName);
258 results.insert(results.end(), subResults.begin(), subResults.end());
259 }
260 }
261 }
262 return results;
263}
264
265template<typename T>
267{
268 std::vector<std::string> ignoreOrFollowExternalLinks;
269 return getLinkedAndReachablePlatformParts<T>(origin, ignoreOrFollowExternalLinks, false);
270}
271
272
273template<typename T>
274std::vector<T*> getLinkedAndReachablePlatformParts(WsfPlatformPart* origin, const std::vector<std::string>& ignoreOrFollowExternalLinks, bool follow)
275{
276 std::vector<WsfPlatform*> visitedPlatforms;
277 std::vector<wsf::comm::Comm*> visitedComms;
278 return getLinkedAndReachablePlatformParts<T>(origin, visitedPlatforms, visitedComms, ignoreOrFollowExternalLinks, follow);
279}
280
281
282template<typename T>
284 WsfPlatformPart* origin,
285 std::vector<WsfPlatform*>& visitedPlatforms,
286 std::vector<wsf::comm::Comm*>& visitedComms,
287 const std::vector<std::string>& ignoreOrFollowExternalLinks,
288 bool follow)
289{
290 WsfPlatform* platform = origin->GetPlatform();
291 if (std::find(visitedPlatforms.begin(), visitedPlatforms.end(), platform) == visitedPlatforms.end() &&
292 std::find(visitedComms.begin(), visitedComms.end(), origin) == visitedComms.end())
293 {
294 // For now, we're not going to keep track of visited platforms - keeping track of visited comms is enough to avoid
295 // getting stuck in cycles, and occasionally we may need to visit a platform more than once to find a linked
296 // and reachable platform part. We may want to change this back eventually.
297 //visitedPlatforms.push_back(platform);
298
299 // Start with platform parts of type T to which origin has internal links
300 std::vector<T*> linkedAndReachableParts = getInternallyLinkedPlatformParts<T>(origin);
301
302 // If origin itself has external links, follow those links, even if origin is of a type listed in ignoreExternalLinks.
303 if (dynamic_cast<WsfLinkedProcessor*>(origin))
304 {
305 wsf::ExternalLinks& links = static_cast<WsfLinkedProcessor*>(origin)->GetExternalLinks();
306 std::vector<T*> results = getLinkedAndReachablePlatformParts<T>(links, origin->GetPlatform(), visitedPlatforms, visitedComms, ignoreOrFollowExternalLinks, follow);
307 linkedAndReachableParts.reserve(linkedAndReachableParts.size() + results.size());
308 linkedAndReachableParts.insert(linkedAndReachableParts.end(), results.begin(), results.end());
309 }
310 else if (dynamic_cast<WsfScriptProcessor*>(origin))
311 {
312 wsf::ExternalLinks& links = static_cast<WsfScriptProcessor*>(origin)->GetExternalLinks();
313 std::vector<T*> results = getLinkedAndReachablePlatformParts<T>(links, origin->GetPlatform(), visitedPlatforms, visitedComms, ignoreOrFollowExternalLinks, follow);
314 linkedAndReachableParts.reserve(linkedAndReachableParts.size() + results.size());
315 linkedAndReachableParts.insert(linkedAndReachableParts.end(), results.begin(), results.end());
316 }
317
318 // Linked processors and script processors may have external links used to communicate with other platforms:
319 // Find all sets of external links that origin has access to via internal links. (E.g., origin has an internal
320 // link to a WsfLinkedProcessor, which has external links to other platforms.) Ignore external links from
321 // script processors or linked processors of a type named in ignoreExternalLinks.
322 std::vector<WsfLinkedProcessor*> linkedProcessors = getInternallyLinkedPlatformParts<WsfLinkedProcessor>(origin);
323 std::vector<WsfScriptProcessor*> scriptProcessors = getInternallyLinkedPlatformParts<WsfScriptProcessor>(origin);
324
325 // If follow == true, ONLY follow external links from processor types listed in ignoreOrFollowExternalLinks.
326 // So, assume that we will NOT consider a processor type unless we see it in ignoreOrFollowExternalLinks.
327 // If follow == false, we'll follow external links from all processor types EXCEPT those listed in ignoreOrFollowExternalLinks.
328 // So, assume that we WILL consider a processor type unless we see it in the vector of type names.
329 for (WsfLinkedProcessor* lp : linkedProcessors)
330 {
331 bool considerLP = !follow;
332 for (const std::string& type : ignoreOrFollowExternalLinks)
333 {
334 if (lp->IsA_TypeOf(type))
335 {
336 considerLP = !considerLP;
337 break;
338 }
339 }
340 if (considerLP)
341 {
342 wsf::ExternalLinks& links = lp->GetExternalLinks();
343 std::vector<T*> results = getLinkedAndReachablePlatformParts<T>(links, origin->GetPlatform(), visitedPlatforms, visitedComms, ignoreOrFollowExternalLinks, follow);
344 linkedAndReachableParts.reserve(linkedAndReachableParts.size() + results.size());
345 linkedAndReachableParts.insert(linkedAndReachableParts.end(), results.begin(), results.end());
346 }
347 }
348 for (WsfScriptProcessor* sp : scriptProcessors)
349 {
350 bool considerSP = !follow;
351 for (const std::string& type : ignoreOrFollowExternalLinks)
352 {
353 if (sp->IsA_TypeOf(type))
354 {
355 considerSP = !considerSP;
356 break;
357 }
358 }
359 if (considerSP)
360 {
361 wsf::ExternalLinks& links = sp->GetExternalLinks();
362 std::vector<T*> results = getLinkedAndReachablePlatformParts<T>(links, origin->GetPlatform(), visitedPlatforms, visitedComms, ignoreOrFollowExternalLinks, follow);
363 linkedAndReachableParts.reserve(linkedAndReachableParts.size() + results.size());
364 linkedAndReachableParts.insert(linkedAndReachableParts.end(), results.begin(), results.end());
365 }
366 }
367 return linkedAndReachableParts;
368 }
369 else // Platform has already been visited
370 {
371 return std::vector<T*>();
372 }
373}
374
375template<typename T>
377 wsf::ExternalLinks& links,
378 WsfPlatform* sourcePlatform,
379 std::vector<WsfPlatform*>& visitedPlatforms,
380 std::vector<wsf::comm::Comm*>& visitedComms,
381 const std::vector<std::string>& ignoreOrFollowExternalLinks,
382 bool follow)
383{
384 std::vector<T*> linkedAndReachablePlatformParts;
385 if (sourcePlatform)
386 {
387 wsf::comm::NetworkManager* networkManager = sourcePlatform->GetSimulation()->GetCommNetworkManager();
388
389 for (size_t i = 0, count = links.GetLinkCount(); i != count; ++i)
390 {
392 wsf::comm::Comm* xmtr = link.GetXmtr();
393 if (xmtr)
394 {
395 wsf::comm::Address xmtrAddress = link.GetXmtr()->GetAddress();
396
397 //std::cout << "Source platform: " << sourcePlatform->GetName() << ", xmtr: " << link.GetXmtr()->GetName() << std::endl;
398
399 std::vector<wsf::comm::Address> recipientAddresses = link.GetRecipients();
400 for (const wsf::comm::Address& rcvrAddress : recipientAddresses)
401 {
402 //std::cout << "Checking for path to comm " << networkManager->GetComm(rcvrAddress)->GetName() << std::endl;
403 if (networkManager->PathExists(xmtrAddress, rcvrAddress))
404 {
405 wsf::comm::Comm* rcvr = networkManager->GetComm(rcvrAddress);
406 //std::cout << "Destination platform: " << rcvrComm->GetPlatform()->GetName() << ", rcvr: " << rcvrComm->GetName() << std::endl;
407 if (rcvr)
408 {
409 visitedComms.push_back(xmtr);
410 auto results = getLinkedAndReachablePlatformParts<T>(rcvr, visitedPlatforms, visitedComms, ignoreOrFollowExternalLinks, follow);
411 visitedComms.push_back(rcvr);
412 linkedAndReachablePlatformParts.reserve(linkedAndReachablePlatformParts.size() + results.size());
413 linkedAndReachablePlatformParts.insert(linkedAndReachablePlatformParts.end(), results.begin(), results.end());
414 }
415 }
416 }
417 }
418 }
419 }
420 return linkedAndReachablePlatformParts;
421}
422
423
424
425#endif
std::vector< T * > getInternallyLinkedPlatformParts(WsfPlatformPart *origin)
Definition ScenarioAnalyzerUtilities.hpp:157
std::function< bool(WsfPlatform *)> PlatformCheck
Definition ScenarioAnalyzerUtilities.hpp:66
WSF_SCENARIO_ANALYZER_LIB_EXPORT bool checkDownCommandChain(WsfPlatform *platform, PlatformCheck check)
Definition ScenarioAnalyzerUtilities.cpp:183
WSF_SCENARIO_ANALYZER_LIB_EXPORT WsfPlatform * getTopCommander(WsfStringId commandChainName, WsfPlatform *platform)
Definition ScenarioAnalyzerUtilities.cpp:58
std::vector< T * > getAllPartsDownCommandChain(WsfPlatform *platform)
Definition ScenarioAnalyzerUtilities.hpp:193
std::vector< T * > getLinkedAndReachablePlatformParts(WsfPlatformPart *origin, const std::vector< std::string > &ignoreExternalLinks, bool follow)
Definition ScenarioAnalyzerUtilities.hpp:274
WSF_SCENARIO_ANALYZER_LIB_EXPORT bool checkFullCommandChain(WsfPlatform *platform, PlatformCheck check)
Definition ScenarioAnalyzerUtilities.cpp:291
WSF_SCENARIO_ANALYZER_LIB_EXPORT void ConvertMessagesToScript(const Messages &aMessages, UtScriptData &aReturnVal, UtScriptContext &aContext, UtScriptClass *aReturnClassPtr)
Definition ScenarioAnalyzerUtilities.cpp:734
WSF_SCENARIO_ANALYZER_LIB_EXPORT Messages runSuiteCheck(const std::string &aSuiteName, const std::string &aCheckName, ScenarioAnalyzerMessage::SeverityLevel aSeverity, WsfSimulation &aSimulation, TFunc aFunction, bool aWriteFlag=true)
Definition ScenarioAnalyzerUtilities.hpp:75
WSF_SCENARIO_ANALYZER_LIB_EXPORT bool checkUpCommandChain(WsfPlatform *platform, PlatformCheck check)
Definition ScenarioAnalyzerUtilities.cpp:72
std::vector< ScenarioAnalyzerMessage > Messages
Definition ScenarioAnalyzerUtilities.hpp:67
void RegisterUtilsScriptTypes(WsfApplication &application)
Definition ScenarioAnalyzerUtilities.cpp:749
WsfComponentListT< T >::Iterator end(const WsfComponentListT< T > &aList)
Definition WsfComponentList.hpp:546
ut::script::Data UtScriptData
Definition WsfScriptContext.hpp:47
UtStringId WsfStringId
WsfStringId – the same thing as UtStringId.
Definition WsfStringId.hpp:23
Class for Scenario Analyzer messages that provides simple message building and writing.
Definition ScenarioAnalyzerMessage.hpp:40
void SetSuccessful()
Set default details and type for a successful message.
Definition ScenarioAnalyzerMessage.cpp:114
void SetCheckName(const std::string &aCheckName)
Definition ScenarioAnalyzerMessage.hpp:80
SeverityLevel
Definition ScenarioAnalyzerMessage.hpp:44
void SetSuiteName(const std::string &aSuiteName)
Definition ScenarioAnalyzerMessage.hpp:79
void SetSeverity(SeverityLevel aSeverityLevel)
Definition ScenarioAnalyzerMessage.hpp:83
Definition WsfApplication.hpp:45
Definition WsfBMSensorsManager.hpp:50
Definition WsfBattleManager.hpp:61
Definition WsfCommandChain.hpp:36
PlatformList & GetSubordinates()
Definition WsfCommandChain.hpp:93
T * GetComponentEntry(unsigned int aEntry) const
Definition WsfComponentList.hpp:154
unsigned int GetComponentCount(int aRole) const
Definition WsfComponentList.cpp:71
T * GetComponent() const
Definition WsfComponentList.hpp:116
A linked processor is a processor with both internal links (see WsfInternalLinks) and external links ...
Definition WsfLinkedProcessor.hpp:24
Definition WsfPlatformPart.hpp:61
WsfInternalLinks & GetInternalLinks()
Return the internal links for this part.
Definition WsfPlatformPart.hpp:208
WsfPlatform * GetPlatform() const
Definition WsfPlatformPart.hpp:107
Platforms represent a entity within the simulation.
Definition WsfPlatform.hpp:115
WsfSimulation * GetSimulation() const
If the platform is a member of a simulation, this is the containing simulation.
Definition WsfPlatform.hpp:323
Definition WsfScriptProcessor.hpp:43
The main controller for a simulation.
Definition WsfSimulation.hpp:109
wsf::comm::NetworkManager * GetCommNetworkManager() const
Definition WsfSimulation.hpp:450
Definition WsfCommAddress.hpp:57
Definition WsfComm.hpp:43
const Address & GetAddress() const
Definition WsfComm.hpp:184
Definition WsfCommNetworkManager.hpp:44
Comm * GetComm(const Address &aAddress) const
Provides Comm object for an Address.
Definition WsfCommNetworkManager.cpp:561
bool PathExists(const Address &aSourceAddress, const Address &aDestinationAddress) const
Simple check of pathing from source to destination.
Definition WsfCommNetworkManager.cpp:1635
Definition WsfComm.cpp:34
Function definitions for those who need run-time access to the version.
Definition WsfComm.cpp:32
Copyrights Multiple, All Rights Reserved