xref: /openbmc/phosphor-objmgr/src/handler.cpp (revision d884cdf76957a2fce6c92d4c8bf0954c7a533998)
1aba14d3dSWilly Tu #include "handler.hpp"
2aba14d3dSWilly Tu 
3aba14d3dSWilly Tu #include "types.hpp"
4aba14d3dSWilly Tu 
5aba14d3dSWilly Tu #include <xyz/openbmc_project/Common/error.hpp>
6aba14d3dSWilly Tu 
7aba14d3dSWilly Tu #include <algorithm>
8aba14d3dSWilly Tu #include <string>
958881d0bSWilly Tu #include <unordered_set>
10aba14d3dSWilly Tu #include <utility>
11aba14d3dSWilly Tu #include <vector>
12aba14d3dSWilly Tu 
addObjectMapResult(std::vector<InterfaceMapType::value_type> & objectMap,const std::string & objectPath,const ConnectionNames::value_type & interfaceMap)13aba14d3dSWilly Tu void addObjectMapResult(std::vector<InterfaceMapType::value_type>& objectMap,
14aba14d3dSWilly Tu                         const std::string& objectPath,
15aba14d3dSWilly Tu                         const ConnectionNames::value_type& interfaceMap)
16aba14d3dSWilly Tu {
17aba14d3dSWilly Tu     // Adds an object path/service name/interface list entry to
18aba14d3dSWilly Tu     // the results of GetSubTree and GetAncestors.
19aba14d3dSWilly Tu     // If an entry for the object path already exists, just add the
20aba14d3dSWilly Tu     // service name and interfaces to that entry, otherwise create
21aba14d3dSWilly Tu     // a new entry.
2247b68cbcSPatrick Williams     auto entry = std::find_if(
2347b68cbcSPatrick Williams         objectMap.begin(), objectMap.end(),
2447b68cbcSPatrick Williams         [&objectPath](const auto& i) { return objectPath == i.first; });
25aba14d3dSWilly Tu 
26aba14d3dSWilly Tu     if (entry != objectMap.end())
27aba14d3dSWilly Tu     {
28aba14d3dSWilly Tu         entry->second.emplace(interfaceMap);
29aba14d3dSWilly Tu     }
30aba14d3dSWilly Tu     else
31aba14d3dSWilly Tu     {
32aba14d3dSWilly Tu         InterfaceMapType::value_type object;
33aba14d3dSWilly Tu         object.first = objectPath;
34aba14d3dSWilly Tu         object.second.emplace(interfaceMap);
35aba14d3dSWilly Tu         objectMap.push_back(object);
36aba14d3dSWilly Tu     }
37aba14d3dSWilly Tu }
38aba14d3dSWilly Tu 
getAncestors(const InterfaceMapType & interfaceMap,std::string reqPath,std::vector<std::string> & interfaces)39*d884cdf7SPatrick Williams std::vector<InterfaceMapType::value_type> getAncestors(
40*d884cdf7SPatrick Williams     const InterfaceMapType& interfaceMap, std::string reqPath,
41aba14d3dSWilly Tu     std::vector<std::string>& interfaces)
42aba14d3dSWilly Tu {
43aba14d3dSWilly Tu     // Interfaces need to be sorted for intersect to function
44aba14d3dSWilly Tu     std::sort(interfaces.begin(), interfaces.end());
45aba14d3dSWilly Tu 
46aba14d3dSWilly Tu     if (reqPath.ends_with("/"))
47aba14d3dSWilly Tu     {
48aba14d3dSWilly Tu         reqPath.pop_back();
49aba14d3dSWilly Tu     }
50aba14d3dSWilly Tu     if (!reqPath.empty() && interfaceMap.find(reqPath) == interfaceMap.end())
51aba14d3dSWilly Tu     {
52aba14d3dSWilly Tu         throw sdbusplus::xyz::openbmc_project::Common::Error::
53aba14d3dSWilly Tu             ResourceNotFound();
54aba14d3dSWilly Tu     }
55aba14d3dSWilly Tu 
56aba14d3dSWilly Tu     std::vector<InterfaceMapType::value_type> ret;
57aba14d3dSWilly Tu     for (const auto& objectPath : interfaceMap)
58aba14d3dSWilly Tu     {
59aba14d3dSWilly Tu         const auto& thisPath = objectPath.first;
60aba14d3dSWilly Tu 
61aba14d3dSWilly Tu         if (reqPath == thisPath)
62aba14d3dSWilly Tu         {
63aba14d3dSWilly Tu             continue;
64aba14d3dSWilly Tu         }
65aba14d3dSWilly Tu 
66aba14d3dSWilly Tu         if (reqPath.starts_with(thisPath))
67aba14d3dSWilly Tu         {
68aba14d3dSWilly Tu             if (interfaces.empty())
69aba14d3dSWilly Tu             {
70aba14d3dSWilly Tu                 ret.emplace_back(objectPath);
71aba14d3dSWilly Tu             }
72aba14d3dSWilly Tu             else
73aba14d3dSWilly Tu             {
74aba14d3dSWilly Tu                 for (const auto& interfaceMap : objectPath.second)
75aba14d3dSWilly Tu                 {
76aba14d3dSWilly Tu                     std::vector<std::string> output(std::min(
77aba14d3dSWilly Tu                         interfaces.size(), interfaceMap.second.size()));
78aba14d3dSWilly Tu                     // Return iterator points at the first output elemtn,
79aba14d3dSWilly Tu                     // meaning that there are no intersections.
809052ebd3SPatrick Williams                     if (std::set_intersection(
819052ebd3SPatrick Williams                             interfaces.begin(), interfaces.end(),
82aba14d3dSWilly Tu                             interfaceMap.second.begin(),
839052ebd3SPatrick Williams                             interfaceMap.second.end(), output.begin()) !=
849052ebd3SPatrick Williams                         output.begin())
85aba14d3dSWilly Tu                     {
86aba14d3dSWilly Tu                         addObjectMapResult(ret, thisPath, interfaceMap);
87aba14d3dSWilly Tu                     }
88aba14d3dSWilly Tu                 }
89aba14d3dSWilly Tu             }
90aba14d3dSWilly Tu         }
91aba14d3dSWilly Tu     }
92aba14d3dSWilly Tu 
93aba14d3dSWilly Tu     return ret;
94aba14d3dSWilly Tu }
95aba14d3dSWilly Tu 
getObject(const InterfaceMapType & interfaceMap,const std::string & path,std::vector<std::string> & interfaces)96aba14d3dSWilly Tu ConnectionNames getObject(const InterfaceMapType& interfaceMap,
97aba14d3dSWilly Tu                           const std::string& path,
98aba14d3dSWilly Tu                           std::vector<std::string>& interfaces)
99aba14d3dSWilly Tu {
100aba14d3dSWilly Tu     ConnectionNames results;
101aba14d3dSWilly Tu 
102aba14d3dSWilly Tu     // Interfaces need to be sorted for intersect to function
103aba14d3dSWilly Tu     std::sort(interfaces.begin(), interfaces.end());
104aba14d3dSWilly Tu     auto pathRef = interfaceMap.find(path);
105aba14d3dSWilly Tu     if (pathRef == interfaceMap.end())
106aba14d3dSWilly Tu     {
107aba14d3dSWilly Tu         throw sdbusplus::xyz::openbmc_project::Common::Error::
108aba14d3dSWilly Tu             ResourceNotFound();
109aba14d3dSWilly Tu     }
110aba14d3dSWilly Tu     if (interfaces.empty())
111aba14d3dSWilly Tu     {
112aba14d3dSWilly Tu         return pathRef->second;
113aba14d3dSWilly Tu     }
114aba14d3dSWilly Tu     for (const auto& interfaceMap : pathRef->second)
115aba14d3dSWilly Tu     {
116aba14d3dSWilly Tu         std::vector<std::string> output(
117aba14d3dSWilly Tu             std::min(interfaces.size(), interfaceMap.second.size()));
118aba14d3dSWilly Tu         // Return iterator points at the first output elemtn,
119aba14d3dSWilly Tu         // meaning that there are no intersections.
120aba14d3dSWilly Tu         if (std::set_intersection(interfaces.begin(), interfaces.end(),
121aba14d3dSWilly Tu                                   interfaceMap.second.begin(),
1229052ebd3SPatrick Williams                                   interfaceMap.second.end(), output.begin()) !=
1239052ebd3SPatrick Williams             output.begin())
124aba14d3dSWilly Tu         {
125aba14d3dSWilly Tu             results.emplace(interfaceMap.first, interfaceMap.second);
126aba14d3dSWilly Tu         }
127aba14d3dSWilly Tu     }
128aba14d3dSWilly Tu 
129aba14d3dSWilly Tu     if (results.empty())
130aba14d3dSWilly Tu     {
131aba14d3dSWilly Tu         throw sdbusplus::xyz::openbmc_project::Common::Error::
132aba14d3dSWilly Tu             ResourceNotFound();
133aba14d3dSWilly Tu     }
134aba14d3dSWilly Tu 
135aba14d3dSWilly Tu     return results;
136aba14d3dSWilly Tu }
137aba14d3dSWilly Tu 
getSubTree(const InterfaceMapType & interfaceMap,std::string reqPath,int32_t depth,std::vector<std::string> & interfaces)138*d884cdf7SPatrick Williams std::vector<InterfaceMapType::value_type> getSubTree(
139*d884cdf7SPatrick Williams     const InterfaceMapType& interfaceMap, std::string reqPath, int32_t depth,
140*d884cdf7SPatrick Williams     std::vector<std::string>& interfaces)
141aba14d3dSWilly Tu {
142aba14d3dSWilly Tu     if (depth <= 0)
143aba14d3dSWilly Tu     {
144aba14d3dSWilly Tu         depth = std::numeric_limits<int32_t>::max();
145aba14d3dSWilly Tu     }
146aba14d3dSWilly Tu     // Interfaces need to be sorted for intersect to function
147aba14d3dSWilly Tu     std::sort(interfaces.begin(), interfaces.end());
148aba14d3dSWilly Tu 
149aba14d3dSWilly Tu     // reqPath is now guaranteed to have a trailing "/" while reqPathStripped
150aba14d3dSWilly Tu     // will be guaranteed not to have a trailing "/"
151aba14d3dSWilly Tu     if (!reqPath.ends_with("/"))
152aba14d3dSWilly Tu     {
153aba14d3dSWilly Tu         reqPath += "/";
154aba14d3dSWilly Tu     }
155aba14d3dSWilly Tu     std::string_view reqPathStripped =
156aba14d3dSWilly Tu         std::string_view(reqPath).substr(0, reqPath.size() - 1);
157aba14d3dSWilly Tu 
158aba14d3dSWilly Tu     if (!reqPathStripped.empty() &&
159aba14d3dSWilly Tu         interfaceMap.find(reqPathStripped) == interfaceMap.end())
160aba14d3dSWilly Tu     {
161aba14d3dSWilly Tu         throw sdbusplus::xyz::openbmc_project::Common::Error::
162aba14d3dSWilly Tu             ResourceNotFound();
163aba14d3dSWilly Tu     }
164aba14d3dSWilly Tu 
165aba14d3dSWilly Tu     std::vector<InterfaceMapType::value_type> ret;
166aba14d3dSWilly Tu     for (const auto& objectPath : interfaceMap)
167aba14d3dSWilly Tu     {
168aba14d3dSWilly Tu         const auto& thisPath = objectPath.first;
169aba14d3dSWilly Tu 
170aba14d3dSWilly Tu         // Skip exact match on stripped search term
171aba14d3dSWilly Tu         if (thisPath == reqPathStripped)
172aba14d3dSWilly Tu         {
173aba14d3dSWilly Tu             continue;
174aba14d3dSWilly Tu         }
175aba14d3dSWilly Tu 
176aba14d3dSWilly Tu         if (thisPath.starts_with(reqPath))
177aba14d3dSWilly Tu         {
178aba14d3dSWilly Tu             // count the number of slashes past the stripped search term
179aba14d3dSWilly Tu             int32_t thisDepth = std::count(
180aba14d3dSWilly Tu                 thisPath.begin() + reqPathStripped.size(), thisPath.end(), '/');
181aba14d3dSWilly Tu             if (thisDepth <= depth)
182aba14d3dSWilly Tu             {
183aba14d3dSWilly Tu                 for (const auto& interfaceMap : objectPath.second)
184aba14d3dSWilly Tu                 {
185aba14d3dSWilly Tu                     std::vector<std::string> output(std::min(
186aba14d3dSWilly Tu                         interfaces.size(), interfaceMap.second.size()));
187aba14d3dSWilly Tu                     // Return iterator points at the first output elemtn,
188aba14d3dSWilly Tu                     // meaning that there are no intersections.
189aba14d3dSWilly Tu                     if (std::set_intersection(
190aba14d3dSWilly Tu                             interfaces.begin(), interfaces.end(),
191aba14d3dSWilly Tu                             interfaceMap.second.begin(),
192aba14d3dSWilly Tu                             interfaceMap.second.end(),
193aba14d3dSWilly Tu                             output.begin()) != output.begin() ||
194aba14d3dSWilly Tu                         interfaces.empty())
195aba14d3dSWilly Tu                     {
196aba14d3dSWilly Tu                         addObjectMapResult(ret, thisPath, interfaceMap);
197aba14d3dSWilly Tu                     }
198aba14d3dSWilly Tu                 }
199aba14d3dSWilly Tu             }
200aba14d3dSWilly Tu         }
201aba14d3dSWilly Tu     }
202aba14d3dSWilly Tu 
203aba14d3dSWilly Tu     return ret;
204aba14d3dSWilly Tu }
205aba14d3dSWilly Tu 
getSubTreePaths(const InterfaceMapType & interfaceMap,std::string reqPath,int32_t depth,std::vector<std::string> & interfaces)206*d884cdf7SPatrick Williams std::vector<std::string> getSubTreePaths(const InterfaceMapType& interfaceMap,
207*d884cdf7SPatrick Williams                                          std::string reqPath, int32_t depth,
208*d884cdf7SPatrick Williams                                          std::vector<std::string>& interfaces)
209aba14d3dSWilly Tu {
210aba14d3dSWilly Tu     if (depth <= 0)
211aba14d3dSWilly Tu     {
212aba14d3dSWilly Tu         depth = std::numeric_limits<int32_t>::max();
213aba14d3dSWilly Tu     }
214aba14d3dSWilly Tu     // Interfaces need to be sorted for intersect to function
215aba14d3dSWilly Tu     std::sort(interfaces.begin(), interfaces.end());
216aba14d3dSWilly Tu 
217aba14d3dSWilly Tu     // reqPath is now guaranteed to have a trailing "/" while reqPathStripped
218aba14d3dSWilly Tu     // will be guaranteed not to have a trailing "/"
219aba14d3dSWilly Tu     if (!reqPath.ends_with("/"))
220aba14d3dSWilly Tu     {
221aba14d3dSWilly Tu         reqPath += "/";
222aba14d3dSWilly Tu     }
223aba14d3dSWilly Tu     std::string_view reqPathStripped =
224aba14d3dSWilly Tu         std::string_view(reqPath).substr(0, reqPath.size() - 1);
225aba14d3dSWilly Tu 
226aba14d3dSWilly Tu     if (!reqPathStripped.empty() &&
227aba14d3dSWilly Tu         interfaceMap.find(reqPathStripped) == interfaceMap.end())
228aba14d3dSWilly Tu     {
229aba14d3dSWilly Tu         throw sdbusplus::xyz::openbmc_project::Common::Error::
230aba14d3dSWilly Tu             ResourceNotFound();
231aba14d3dSWilly Tu     }
232aba14d3dSWilly Tu 
233aba14d3dSWilly Tu     std::vector<std::string> ret;
234aba14d3dSWilly Tu     for (const auto& objectPath : interfaceMap)
235aba14d3dSWilly Tu     {
236aba14d3dSWilly Tu         const auto& thisPath = objectPath.first;
237aba14d3dSWilly Tu 
238aba14d3dSWilly Tu         // Skip exact match on stripped search term
239aba14d3dSWilly Tu         if (thisPath == reqPathStripped)
240aba14d3dSWilly Tu         {
241aba14d3dSWilly Tu             continue;
242aba14d3dSWilly Tu         }
243aba14d3dSWilly Tu 
244aba14d3dSWilly Tu         if (thisPath.starts_with(reqPath))
245aba14d3dSWilly Tu         {
246aba14d3dSWilly Tu             // count the number of slashes past the stripped search term
247aba14d3dSWilly Tu             int thisDepth = std::count(
248aba14d3dSWilly Tu                 thisPath.begin() + reqPathStripped.size(), thisPath.end(), '/');
249aba14d3dSWilly Tu             if (thisDepth <= depth)
250aba14d3dSWilly Tu             {
251aba14d3dSWilly Tu                 bool add = interfaces.empty();
252aba14d3dSWilly Tu                 for (const auto& interfaceMap : objectPath.second)
253aba14d3dSWilly Tu                 {
254aba14d3dSWilly Tu                     std::vector<std::string> output(std::min(
255aba14d3dSWilly Tu                         interfaces.size(), interfaceMap.second.size()));
256aba14d3dSWilly Tu                     // Return iterator points at the first output elemtn,
257aba14d3dSWilly Tu                     // meaning that there are no intersections.
2589052ebd3SPatrick Williams                     if (std::set_intersection(
2599052ebd3SPatrick Williams                             interfaces.begin(), interfaces.end(),
260aba14d3dSWilly Tu                             interfaceMap.second.begin(),
2619052ebd3SPatrick Williams                             interfaceMap.second.end(), output.begin()) !=
2629052ebd3SPatrick Williams                         output.begin())
263aba14d3dSWilly Tu                     {
264aba14d3dSWilly Tu                         add = true;
265aba14d3dSWilly Tu                         break;
266aba14d3dSWilly Tu                     }
267aba14d3dSWilly Tu                 }
268aba14d3dSWilly Tu                 if (add)
269aba14d3dSWilly Tu                 {
270aba14d3dSWilly Tu                     // TODO(ed) this is a copy
271aba14d3dSWilly Tu                     ret.emplace_back(thisPath);
272aba14d3dSWilly Tu                 }
273aba14d3dSWilly Tu             }
274aba14d3dSWilly Tu         }
275aba14d3dSWilly Tu     }
276aba14d3dSWilly Tu 
277aba14d3dSWilly Tu     return ret;
278aba14d3dSWilly Tu }
27958881d0bSWilly Tu 
getAssociatedSubTree(const InterfaceMapType & interfaceMap,const AssociationMaps & associationMaps,const sdbusplus::message::object_path & associationPath,const sdbusplus::message::object_path & reqPath,int32_t depth,std::vector<std::string> & interfaces)2809052ebd3SPatrick Williams std::vector<InterfaceMapType::value_type> getAssociatedSubTree(
2819052ebd3SPatrick Williams     const InterfaceMapType& interfaceMap,
28258881d0bSWilly Tu     const AssociationMaps& associationMaps,
28358881d0bSWilly Tu     const sdbusplus::message::object_path& associationPath,
2849052ebd3SPatrick Williams     const sdbusplus::message::object_path& reqPath, int32_t depth,
2859052ebd3SPatrick Williams     std::vector<std::string>& interfaces)
28658881d0bSWilly Tu {
28758881d0bSWilly Tu     auto findEndpoint = associationMaps.ifaces.find(associationPath.str);
28858881d0bSWilly Tu     if (findEndpoint == associationMaps.ifaces.end())
28958881d0bSWilly Tu     {
29058881d0bSWilly Tu         return {};
29158881d0bSWilly Tu     }
29258881d0bSWilly Tu     const std::vector<std::string>& association =
29358881d0bSWilly Tu         std::get<endpointsPos>(findEndpoint->second);
29458881d0bSWilly Tu     std::unordered_set<std::string> associationSet(association.begin(),
29558881d0bSWilly Tu                                                    association.end());
2968c25006cSPatrick Williams     const std::vector<InterfaceMapType::value_type> interfacePairs =
29758881d0bSWilly Tu         getSubTree(interfaceMap, reqPath, depth, interfaces);
29858881d0bSWilly Tu 
29958881d0bSWilly Tu     std::vector<InterfaceMapType::value_type> output;
30058881d0bSWilly Tu     for (const InterfaceMapType::value_type& interfacePair : interfacePairs)
30158881d0bSWilly Tu     {
30258881d0bSWilly Tu         if (associationSet.contains(interfacePair.first))
30358881d0bSWilly Tu         {
30458881d0bSWilly Tu             output.emplace_back(interfacePair);
30558881d0bSWilly Tu         }
30658881d0bSWilly Tu     }
30758881d0bSWilly Tu     return output;
30858881d0bSWilly Tu }
30958881d0bSWilly Tu 
getAssociatedSubTreePaths(const InterfaceMapType & interfaceMap,const AssociationMaps & associationMaps,const sdbusplus::message::object_path & associationPath,const sdbusplus::message::object_path & reqPath,int32_t depth,std::vector<std::string> & interfaces)31058881d0bSWilly Tu std::vector<std::string> getAssociatedSubTreePaths(
31158881d0bSWilly Tu     const InterfaceMapType& interfaceMap,
31258881d0bSWilly Tu     const AssociationMaps& associationMaps,
31358881d0bSWilly Tu     const sdbusplus::message::object_path& associationPath,
31458881d0bSWilly Tu     const sdbusplus::message::object_path& reqPath, int32_t depth,
31558881d0bSWilly Tu     std::vector<std::string>& interfaces)
31658881d0bSWilly Tu {
31758881d0bSWilly Tu     auto findEndpoint = associationMaps.ifaces.find(associationPath.str);
31858881d0bSWilly Tu     if (findEndpoint == associationMaps.ifaces.end())
31958881d0bSWilly Tu     {
32058881d0bSWilly Tu         return {};
32158881d0bSWilly Tu     }
32258881d0bSWilly Tu     const std::vector<std::string>& association =
32358881d0bSWilly Tu         std::get<endpointsPos>(findEndpoint->second);
32458881d0bSWilly Tu     std::unordered_set<std::string> associationSet(association.begin(),
32558881d0bSWilly Tu                                                    association.end());
3268c25006cSPatrick Williams     const std::vector<std::string> paths =
32758881d0bSWilly Tu         getSubTreePaths(interfaceMap, reqPath, depth, interfaces);
32858881d0bSWilly Tu 
32958881d0bSWilly Tu     std::vector<std::string> output;
33058881d0bSWilly Tu     for (const auto& path : paths)
33158881d0bSWilly Tu     {
33258881d0bSWilly Tu         if (associationSet.contains(path))
33358881d0bSWilly Tu         {
33458881d0bSWilly Tu             output.emplace_back(path);
33558881d0bSWilly Tu         }
33658881d0bSWilly Tu     }
33758881d0bSWilly Tu     return output;
33858881d0bSWilly Tu }
339c363323eSLakshmi Yadlapati 
340c363323eSLakshmi Yadlapati // This function works like getSubTreePaths() but only matching id with
341c363323eSLakshmi Yadlapati // the leaf-name instead of full path.
getSubTreePathsById(const InterfaceMapType & interfaceMap,const std::string & id,const std::string & objectPath,std::vector<std::string> & interfaces)342c363323eSLakshmi Yadlapati std::vector<std::string> getSubTreePathsById(
343c363323eSLakshmi Yadlapati     const InterfaceMapType& interfaceMap, const std::string& id,
344c363323eSLakshmi Yadlapati     const std::string& objectPath, std::vector<std::string>& interfaces)
345c363323eSLakshmi Yadlapati {
346c363323eSLakshmi Yadlapati     std::sort(interfaces.begin(), interfaces.end());
347c363323eSLakshmi Yadlapati 
348c363323eSLakshmi Yadlapati     std::string localObjectPath = objectPath;
349c363323eSLakshmi Yadlapati 
350c363323eSLakshmi Yadlapati     if (!localObjectPath.ends_with("/"))
351c363323eSLakshmi Yadlapati     {
352c363323eSLakshmi Yadlapati         localObjectPath += "/";
353c363323eSLakshmi Yadlapati     }
354c363323eSLakshmi Yadlapati     std::string_view objectPathStripped =
355c363323eSLakshmi Yadlapati         std::string_view(localObjectPath).substr(0, localObjectPath.size() - 1);
356c363323eSLakshmi Yadlapati 
357c363323eSLakshmi Yadlapati     if (!objectPathStripped.empty() &&
358c363323eSLakshmi Yadlapati         interfaceMap.find(objectPathStripped) == interfaceMap.end())
359c363323eSLakshmi Yadlapati     {
360c363323eSLakshmi Yadlapati         throw sdbusplus::xyz::openbmc_project::Common::Error::
361c363323eSLakshmi Yadlapati             ResourceNotFound();
362c363323eSLakshmi Yadlapati     }
363c363323eSLakshmi Yadlapati 
364c363323eSLakshmi Yadlapati     std::vector<std::string> output;
365c363323eSLakshmi Yadlapati     for (const auto& path : interfaceMap)
366c363323eSLakshmi Yadlapati     {
367c363323eSLakshmi Yadlapati         const auto& thisPath = path.first;
368c363323eSLakshmi Yadlapati 
369c363323eSLakshmi Yadlapati         // Skip exact match on stripped search term or
370c363323eSLakshmi Yadlapati         // the path does not end with the id
371c363323eSLakshmi Yadlapati         if (thisPath == objectPathStripped || !thisPath.ends_with("/" + id))
372c363323eSLakshmi Yadlapati         {
373c363323eSLakshmi Yadlapati             continue;
374c363323eSLakshmi Yadlapati         }
375c363323eSLakshmi Yadlapati 
376c363323eSLakshmi Yadlapati         if (thisPath.starts_with(objectPath))
377c363323eSLakshmi Yadlapati         {
378c363323eSLakshmi Yadlapati             for (const auto& interfaceMap : path.second)
379c363323eSLakshmi Yadlapati             {
380c363323eSLakshmi Yadlapati                 std::vector<std::string> tempoutput(
381c363323eSLakshmi Yadlapati                     std::min(interfaces.size(), interfaceMap.second.size()));
382c363323eSLakshmi Yadlapati                 if (std::set_intersection(
383c363323eSLakshmi Yadlapati                         interfaces.begin(), interfaces.end(),
384c363323eSLakshmi Yadlapati                         interfaceMap.second.begin(), interfaceMap.second.end(),
385c363323eSLakshmi Yadlapati                         tempoutput.begin()) != tempoutput.begin())
386c363323eSLakshmi Yadlapati                 {
387c363323eSLakshmi Yadlapati                     output.emplace_back(thisPath);
388c363323eSLakshmi Yadlapati                     break;
389c363323eSLakshmi Yadlapati                 }
390c363323eSLakshmi Yadlapati             }
391c363323eSLakshmi Yadlapati         }
392c363323eSLakshmi Yadlapati     }
393c363323eSLakshmi Yadlapati     return output;
394c363323eSLakshmi Yadlapati }
395c363323eSLakshmi Yadlapati 
getAssociatedSubTreeById(const InterfaceMapType & interfaceMap,const AssociationMaps & associationMaps,const std::string & id,const std::string & objectPath,std::vector<std::string> & subtreeInterfaces,const std::string & association,std::vector<std::string> & endpointInterfaces)396c363323eSLakshmi Yadlapati std::vector<InterfaceMapType::value_type> getAssociatedSubTreeById(
397c363323eSLakshmi Yadlapati     const InterfaceMapType& interfaceMap,
398c363323eSLakshmi Yadlapati     const AssociationMaps& associationMaps, const std::string& id,
399c363323eSLakshmi Yadlapati     const std::string& objectPath, std::vector<std::string>& subtreeInterfaces,
400c363323eSLakshmi Yadlapati     const std::string& association,
401c363323eSLakshmi Yadlapati     std::vector<std::string>& endpointInterfaces)
402c363323eSLakshmi Yadlapati {
403c363323eSLakshmi Yadlapati     std::vector<std::string> subtreePaths =
404c363323eSLakshmi Yadlapati         getSubTreePathsById(interfaceMap, id, objectPath, subtreeInterfaces);
405c363323eSLakshmi Yadlapati 
406c363323eSLakshmi Yadlapati     std::vector<InterfaceMapType::value_type> output;
407c363323eSLakshmi Yadlapati     for (const auto& subtreePath : subtreePaths)
408c363323eSLakshmi Yadlapati     {
409c363323eSLakshmi Yadlapati         // Form the association path
410c363323eSLakshmi Yadlapati         std::string associationPathStr = subtreePath + "/" + association;
411c363323eSLakshmi Yadlapati         sdbusplus::message::object_path associationPath(associationPathStr);
412c363323eSLakshmi Yadlapati 
413c363323eSLakshmi Yadlapati         auto associatedSubTree =
414c363323eSLakshmi Yadlapati             getAssociatedSubTree(interfaceMap, associationMaps, associationPath,
415c363323eSLakshmi Yadlapati                                  objectPath, 0, endpointInterfaces);
416c363323eSLakshmi Yadlapati 
417c363323eSLakshmi Yadlapati         output.insert(output.end(), associatedSubTree.begin(),
418c363323eSLakshmi Yadlapati                       associatedSubTree.end());
419c363323eSLakshmi Yadlapati     }
420c363323eSLakshmi Yadlapati     return output;
421c363323eSLakshmi Yadlapati }
422c363323eSLakshmi Yadlapati 
getAssociatedSubTreePathsById(const InterfaceMapType & interfaceMap,const AssociationMaps & associationMaps,const std::string & id,const std::string & objectPath,std::vector<std::string> & subtreeInterfaces,const std::string & association,std::vector<std::string> & endpointInterfaces)423c363323eSLakshmi Yadlapati std::vector<std::string> getAssociatedSubTreePathsById(
424c363323eSLakshmi Yadlapati     const InterfaceMapType& interfaceMap,
425c363323eSLakshmi Yadlapati     const AssociationMaps& associationMaps, const std::string& id,
426c363323eSLakshmi Yadlapati     const std::string& objectPath, std::vector<std::string>& subtreeInterfaces,
427c363323eSLakshmi Yadlapati     const std::string& association,
428c363323eSLakshmi Yadlapati     std::vector<std::string>& endpointInterfaces)
429c363323eSLakshmi Yadlapati {
430c363323eSLakshmi Yadlapati     std::vector<std::string> subtreePaths =
431c363323eSLakshmi Yadlapati         getSubTreePathsById(interfaceMap, id, objectPath, subtreeInterfaces);
432c363323eSLakshmi Yadlapati     std::vector<std::string> output;
433c363323eSLakshmi Yadlapati     for (const auto& subtreePath : subtreePaths)
434c363323eSLakshmi Yadlapati     {
435c363323eSLakshmi Yadlapati         // Form the association path
436c363323eSLakshmi Yadlapati         std::string associationPathStr = subtreePath + "/" + association;
437c363323eSLakshmi Yadlapati         sdbusplus::message::object_path associationPath(associationPathStr);
438c363323eSLakshmi Yadlapati 
439c363323eSLakshmi Yadlapati         auto associatedSubTree = getAssociatedSubTreePaths(
440c363323eSLakshmi Yadlapati             interfaceMap, associationMaps, associationPath, objectPath, 0,
441c363323eSLakshmi Yadlapati             endpointInterfaces);
442c363323eSLakshmi Yadlapati 
443c363323eSLakshmi Yadlapati         output.insert(output.end(), associatedSubTree.begin(),
444c363323eSLakshmi Yadlapati                       associatedSubTree.end());
445c363323eSLakshmi Yadlapati     }
446c363323eSLakshmi Yadlapati 
447c363323eSLakshmi Yadlapati     return output;
448c363323eSLakshmi Yadlapati }
449