Skip to content

Commit

Permalink
[RTE] API version selection/resolution may be incorrect #1124 (#691) (#…
Browse files Browse the repository at this point in the history
…1130)

* [RTE] API version selection/resolution may be incorrect #1124

Co-authored-by: Evgueni Driouk <[email protected]>
  • Loading branch information
grasci-arm and Evgueni Driouk authored Sep 22, 2023
1 parent dd3b619 commit e1674e6
Show file tree
Hide file tree
Showing 18 changed files with 417 additions and 125 deletions.
5 changes: 3 additions & 2 deletions libs/rtemodel/include/RteComponent.h
Original file line number Diff line number Diff line change
Expand Up @@ -431,7 +431,7 @@ class RteApiContainer : public RteItem
RteItem* CreateItem(const std::string& tag) override;
};


typedef std::map<std::string, RteApi*, VersionCmp::Greater > RteApiMap;
typedef std::map<std::string, RteComponent*> RteComponentMap;
typedef std::map<std::string, RteComponent*, VersionCmp::Greater> RteComponentVersionMap;
typedef std::list<RteComponent*> RteComponentList;
Expand Down Expand Up @@ -637,9 +637,10 @@ class RteComponentAggregate : public RteComponentContainer
/**
* @brief checks if the aggregate contains at least one component whose attributes match those in the supplied map
* @param attributes map of key-value pairs to match against component attributes
* @param bRespectVersion flag to consider Cversion and Capiversion attributes, default is true
* @return true if at least one component has all attributes found in the supplied map
*/
bool MatchComponentAttributes(const std::map<std::string, std::string>& attributes) const override;
bool MatchComponentAttributes(const std::map<std::string, std::string>& attributes, bool bRespectVersion = true) const override;

/**
* @brief get short component aggregate display name to use in a tree view
Expand Down
6 changes: 4 additions & 2 deletions libs/rtemodel/include/RteItem.h
Original file line number Diff line number Diff line change
Expand Up @@ -553,16 +553,18 @@ class RteItem : public XmlTreeItem<RteItem>
/**
* @brief checks if the item contains all attributes matching those in the supplied map
* @param attributes map of key-value pairs to match against component attributes
* @param bRespectVersion flag to consider Cversion and Capiversion attributes, default is true
* @return true if the item has all attributes found in the supplied map
*/
virtual bool MatchComponentAttributes(const std::map<std::string, std::string>& attributes) const;
virtual bool MatchComponentAttributes(const std::map<std::string, std::string>& attributes, bool bRespectVersion = true) const;

/**
* @brief check if the item matches supplied API attributes
* @param attributes collection of 'C' (API) attributes
* @param bRespectVersion flag to consider Capiversion attribute, default is true
* @return true if the item matches supplied API attributes
*/
virtual bool MatchApiAttributes(const std::map<std::string, std::string>& attributes) const;
virtual bool MatchApiAttributes(const std::map<std::string, std::string>& attributes, bool bRespectVersion = true) const;

/**
* @brief check if given collection of attributes contains the same values for "Dname", "Pname" and "Dvendor"
Expand Down
28 changes: 25 additions & 3 deletions libs/rtemodel/include/RteModel.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,19 +198,33 @@ class RteModel : public RteItem
*/
RteComponent* FindComponents(const RteItem& item, std::list<RteComponent*>& components) const override;

/**
* @brief find first component matching supplied attributes
* @param item reference to RteItem containing component attributes to match
* @return pointer to first component found if any, null otherwise
*/
RteComponent* FindFirstComponent(const RteItem& item) const;

/**
* @brief check if this object has no children
* @return true if this object has no children
*/
bool IsEmpty() const override { return m_children.size() == 0; }

/**
* @brief getter for component by given component ID
* @brief getter for component by given unique component ID
* @param uniqueID component ID
* @return RteComponent pointer
*/
RteComponent* GetComponent(const std::string& uniqueID) const;

/**
* @brief getter for component by given component ID
* @param id component ID with oe without version
* @return RteComponent pointer
*/
RteComponent* FindComponent(const std::string& id) const;

/**
* @brief getter for component by given RteComponentInstance and version to be matched
* @param ci given RteComponentInstance object
Expand Down Expand Up @@ -239,11 +253,19 @@ class RteModel : public RteItem
*/
RteApi* GetApi(const std::string& id) const;

/**
* @brief get latest available API version
* @param id API ID (can be with or without version)
* @return RteApi pointer
*/
RteApi* GetLatestApi(const std::string& id) const;


/**
* @brief getter for collection of APIs
* @return collection of api ID mapped to RteApi object pointer
*/
const std::map<std::string, RteApi* >& GetApiList() const { return m_apiList; }
const RteApiMap& GetApiList() const { return m_apiList; }

/**
* @brief getter for bundles
Expand Down Expand Up @@ -544,7 +566,7 @@ class RteModel : public RteItem
RteCallback* m_callback; // pointer to callback

// components, APIs, taxonomy
std::map<std::string, RteApi* > m_apiList; // collection of available APIs
RteApiMap m_apiList; // collection of available APIs
RteComponentMap m_componentList; // full collection of unique components
std::map<std::string, RteItem*> m_taxonomy; // collection of standard Class descriptions
RteBundleMap m_bundles; // collection of available bundles
Expand Down
38 changes: 21 additions & 17 deletions libs/rtemodel/src/RteComponent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,24 +119,28 @@ size_t RteComponent::GetFileCount() const
return m_files ? m_files->GetChildCount() : 0;
}


RteItem::ConditionResult RteComponent::GetConditionResult(RteConditionContext* context) const
{
ConditionResult result = RteItem::GetConditionResult(context);
if (result < INSTALLED)
return result;
RteTarget* target = context->GetTarget();
RteApi* api = GetApi(target, false);
if (api && api->IsExclusive()) {
RteItem::ConditionResult apiRes = IsApiAvailable(target);
if (apiRes < FULFILLED) {
return apiRes;
} else if(apiRes == FULFILLED) { // api exists
RteApi* thisApi = GetApi(target, true); // no need to check for NULL
set<RteComponent*> components;
target->GetComponentsForApi(api, components, true);
if (components.size() > 1)
return CONFLICT;
apiRes = target->GetComponentsForApi(thisApi, components, true);
if (apiRes == CONFLICT) {
return apiRes;
}
}
return result;
}



const string& RteComponent::GetVendorString() const
{
if (IsApi())
Expand Down Expand Up @@ -277,18 +281,18 @@ RteItem::ConditionResult RteComponent::IsApiAvailable(RteTarget* target) const
if (!HasApi(target)) {
return IGNORED;
}
RteApi* api = target->GetApi(GetApiID(false));
RteApi* api = GetApi(target, true);
if (api) {
return FULFILLED;
}
api = GetApi(target, false);
if (!api) {
return MISSING_API;
}
string availableApiVersion = api->GetApiVersionString();
if (availableApiVersion.empty())
if (api->GetApiVersionString().empty()) {
return FULFILLED; // API without version - deprecated case that we still need to support
string requiredApiVersion = GetApiVersionString();
if (!requiredApiVersion.empty() && VersionCmp::RangeCompare(availableApiVersion, requiredApiVersion) < 0) {
return MISSING_API_VERSION;
}
return FULFILLED;
return MISSING_API_VERSION;
}


Expand Down Expand Up @@ -392,7 +396,7 @@ string RteApi::GetFullDisplayName() const

string RteApi::GetComponentUniqueID() const
{
return GetApiID(false); // api ID is always without version (the latest is used)
return GetApiID(true);
}

string RteApi::GetComponentID(bool withVersion) const
Expand Down Expand Up @@ -459,20 +463,20 @@ bool RteComponentAggregate::SetSelected(int nSel)
return false;
}

bool RteComponentAggregate::MatchComponentAttributes(const map<string, string>& attributes) const
bool RteComponentAggregate::MatchComponentAttributes(const map<string, string>& attributes, bool bRespectVersion) const
{
if (!m_components.empty()) {
for (auto itvar = m_components.begin(); itvar != m_components.end(); itvar++) {
const RteComponentVersionMap& versionMap = itvar->second;
for (auto it = versionMap.begin(); it != versionMap.end(); it++) {
RteComponent* c = it->second;
if (c && c->MatchComponentAttributes(attributes))
if (c && c->MatchComponentAttributes(attributes, bRespectVersion))
return true;
}
}
return false;
} else if (m_instance)
return m_instance->MatchComponentAttributes(attributes);
return m_instance->MatchComponentAttributes(attributes, bRespectVersion);
return false;
}

Expand Down
3 changes: 3 additions & 0 deletions libs/rtemodel/src/RteCondition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -706,6 +706,9 @@ string RteDependencyResult::GetMessageText() const
case RteItem::MISSING_API:
message = "API is missing";
break;
case RteItem::MISSING_API_VERSION:
message = "API with required or compatible version is missing";
break;
case RteItem::CONFLICT:
message = "Conflict, select exactly one component from list";
break;
Expand Down
17 changes: 8 additions & 9 deletions libs/rtemodel/src/RteItem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ const std::string& RteItem::ConditionResultToString(RteItem::ConditionResult res
"INCOMPATIBLE", // incompatible component is selected
"INCOMPATIBLE_VERSION", // incompatible version of component is selected
"INCOMPATIBLE_VARIANT", // incompatible variant of component is selected
"CONFLICT", // more than one exclusive component selected
"CONFLICT", // several exclusive or incompatible components are selected
"INSTALLED", // matching component is installed, but not selectable because not in active bundle
"SELECTABLE", // matching component is installed, but not selected
"FULFILLED", // required component selected or no dependency exists
Expand Down Expand Up @@ -159,16 +159,15 @@ string RteItem::GetDependencyExpressionID() const
string RteItem::GetComponentID(bool withVersion) const // to use in filtered list
{
if (IsApi()) {
withVersion = false; // api ID is always without version (the latest is used)
return GetApiID(false);
return GetApiID(withVersion);
}
return ConstructComponentID(withVersion);
}

string RteItem::GetComponentUniqueID() const
{
if (IsApi()) {
return GetApiID(false); // api ID is always without version (the latest is used)
return GetApiID(true);
}
string id = ConstructComponentID(true);
id += RteConstants::OBRACE_STR;
Expand Down Expand Up @@ -602,7 +601,7 @@ bool RteItem::MatchComponent(const RteItem& item) const
}


bool RteItem::MatchComponentAttributes(const map<string, string>& attributes) const
bool RteItem::MatchComponentAttributes(const map<string, string>& attributes, bool bRespectVersion) const
{
if (attributes.empty()) // no limiting attributes
return true;
Expand All @@ -621,7 +620,7 @@ bool RteItem::MatchComponentAttributes(const map<string, string>& attributes) co
return false;
}
if (a == "Cversion" || a == "Capiversion") { // version of this component should match supplied version range
int verCompareResult = VersionCmp::RangeCompare(it->second, v);
int verCompareResult = bRespectVersion? VersionCmp::CompatibleRangeCompare(it->second, v) : 0;
if (verCompareResult != 0)
return false;
} else {
Expand All @@ -633,7 +632,7 @@ bool RteItem::MatchComponentAttributes(const map<string, string>& attributes) co
}


bool RteItem::MatchApiAttributes(const map<string, string>& attributes) const
bool RteItem::MatchApiAttributes(const map<string, string>& attributes, bool bRespectVersion) const
{
if (attributes.empty())
return false;
Expand All @@ -644,10 +643,10 @@ bool RteItem::MatchApiAttributes(const map<string, string>& attributes) const
if (!a.empty() && a[0] == 'C' && a != "Cvendor") {
const string& v = itm->second;
ita = attributes.find(a);
if (a == "Capiversion") { // version of this api should be >= supplied version
if (a == "Capiversion") { // version of this api should be >= supplied version, but less than next major
if (ita == attributes.end())
continue; // version is not set => accept any
if (VersionCmp::RangeCompare(v, ita->second) != 0) // this version is within supplied range
if (bRespectVersion && VersionCmp::CompatibleRangeCompare(v, ita->second) != 0) // this version is within supplied range
return false;
} else {
if (ita == attributes.end()) // no api attribute in supplied map
Expand Down
61 changes: 45 additions & 16 deletions libs/rtemodel/src/RteModel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
#include "CprjFile.h"

#include "RteFsUtils.h"
#include "RteConstants.h"

#include "XMLTree.h"

using namespace std;
Expand All @@ -28,6 +30,7 @@ RteModel::RteModel(RteItem* parent, PackageState packageState) :
RteItem(parent),
m_packageState(packageState),
m_callback(NULL),
m_apiList(VersionCmp::Greater(RteConstants::PREFIX_CVERSION_CHAR)),
m_bUseDeviceTree(true),
m_filterContext(NULL)
{
Expand Down Expand Up @@ -215,6 +218,12 @@ RteComponent* RteModel::FindComponents(const RteItem& item, std::list<RteCompone
return components.empty()? nullptr : *(components.begin());
}

RteComponent* RteModel::FindFirstComponent(const RteItem& item) const
{
std::list<RteComponent*> components;
return FindComponents(item, components);
}

RteComponent* RteModel::GetComponent(const string& uniqueID) const
{
// look in the APIs
Expand All @@ -231,19 +240,23 @@ RteComponent* RteModel::GetComponent(const string& uniqueID) const
return NULL;
}

RteComponent* RteModel::FindComponent(const std::string& id) const
{
bool withVersion = id.find(RteConstants::PREFIX_CVERSION_CHAR) != string::npos;
for (auto [_, c] : m_componentList) {
if (c->GetComponentID(withVersion) == id) {
return c;
}
}
return nullptr;
}

RteComponent* RteModel::GetComponent(RteComponentInstance* ci, bool matchVersion) const
{
if (ci->IsApi() || matchVersion)
if (ci->IsApi() || matchVersion) {
return GetComponent(ci->GetID());

string id = ci->GetComponentID(false);

for (auto it = m_componentList.begin(); it != m_componentList.end(); it++) {
RteComponent* c = it->second;
if (c->GetComponentID(false) == id)
return c;
}
return NULL;
return FindComponent(ci->GetComponentID(false));
}


Expand All @@ -255,25 +268,41 @@ RteApi* RteModel::GetApi(const map<string, string>& componentAttributes) const
if (a && a->MatchApiAttributes(componentAttributes))
return a;
}
return NULL;
return nullptr;
}

RteApi* RteModel::GetApi(const string& id) const
{
map<string, RteApi*>::const_iterator it = m_apiList.find(id);
if (it != m_apiList.end()) {
RteApi* a = it->second;
return a;
if (id.find(RteConstants::PREFIX_CVERSION_CHAR) != string::npos) {
auto it = m_apiList.find(id);
if (it != m_apiList.end()) {
RteApi* api = it->second;
return api;
}
return nullptr;
}
return NULL;
return GetLatestApi(id);
}

RteApi* RteModel::GetLatestApi(const string& id) const
{
string commonId = RteUtils::GetPrefix(id, RteConstants::PREFIX_CVERSION_CHAR);
// get highest API version
for (auto [key, api] : m_apiList) {
if (RteUtils::GetPrefix(key, RteConstants::PREFIX_CVERSION_CHAR) == commonId) {
return api;
}
}
return nullptr;
}


RteBundle* RteModel::GetBundle(const string& id) const
{
auto it = m_bundles.find(id);
if (it != m_bundles.end())
return it->second;
return NULL;
return nullptr;
}

RteBundle* RteModel::GetLatestBundle(const string& id) const
Expand Down
Loading

0 comments on commit e1674e6

Please sign in to comment.