Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Convert attributes to iterators ... conversion now fully done and uni…
Browse files Browse the repository at this point in the history
…t tests pass
andreilitvin committed Dec 19, 2024
1 parent a813df9 commit 74b9e29
Showing 13 changed files with 248 additions and 284 deletions.
53 changes: 33 additions & 20 deletions src/app/AttributePathExpandIterator.cpp
Original file line number Diff line number Diff line change
@@ -20,6 +20,7 @@

#include <app/GlobalAttributes.h>
#include <lib/support/CodeUtils.h>
#include <optional>

using namespace chip::app::DataModel;

@@ -47,31 +48,26 @@ bool AttributePathExpandIterator::IsValidAttributeId(AttributeId attributeId)
break;
}

const ConcreteAttributePath attributePath(mOutputPath.mEndpointId, mOutputPath.mClusterId, attributeId);
return mDataModelProvider->GetAttributeInfo(attributePath).has_value();
return mDataModelProvider->GetAttributes(mOutputPath)->SeekTo(attributeId);
}

std::optional<AttributeId> AttributePathExpandIterator::NextAttributeId()
std::optional<AttributeId> AttributePathExpandIterator::NextAttributeId(SearchSession & session)
{
if (mOutputPath.mAttributeId == kInvalidAttributeId)
{
if (mpAttributePath->mValue.HasWildcardAttributeId())
{
AttributeEntry entry = mDataModelProvider->FirstAttribute(mOutputPath);
return entry.IsValid() //
? entry.path.mAttributeId //
: Clusters::Globals::Attributes::GeneratedCommandList::Id; //
}

// We allow fixed attribute IDs if and only if they are valid:
// - they may be GLOBAL attributes OR
// - they are valid attributes for this cluster
if (IsValidAttributeId(mpAttributePath->mValue.mAttributeId))
if (!mpAttributePath->mValue.HasWildcardAttributeId())
{
// We allow fixed attribute IDs if and only if they are valid:
// - they may be GLOBAL attributes OR
// - they are valid attributes for this cluster
if (!IsValidAttributeId(mpAttributePath->mValue.mAttributeId))
{
return std::nullopt;
}
return mpAttributePath->mValue.mAttributeId;
}

return std::nullopt;
session.attributes = mDataModelProvider->GetAttributes(mOutputPath);
}

// advance the existing attribute id if it can be advanced
@@ -95,10 +91,10 @@ std::optional<AttributeId> AttributePathExpandIterator::NextAttributeId()
return std::nullopt;
}

AttributeEntry entry = mDataModelProvider->NextAttribute(mOutputPath);
if (entry.IsValid())
auto id = session.attributes->Next();
if (id.has_value())
{
return entry.path.mAttributeId;
return *id;
}

// Finished the data model, start with global attributes
@@ -156,6 +152,23 @@ AttributePathExpandIterator::SearchSession AttributePathExpandIterator::PrepareS
}
}

if ((mOutputPath.mEndpointId != kInvalidEndpointId) && (mOutputPath.mClusterId != kInvalidClusterId))
{
session.attributes = mDataModelProvider->GetAttributes(mOutputPath);
if (mOutputPath.mAttributeId != kInvalidAttributeId)
{
// we are already positioned on a specific cluster, so start from there
if (!session.attributes->SeekTo(mOutputPath.mAttributeId))
{
ChipLogError(InteractionModel,
"Attribute id " ChipLogFormatMEI " is not valid anymore (in " ChipLogFormatMEI "/" ChipLogFormatMEI
")",
ChipLogValueMEI(mOutputPath.mAttributeId), ChipLogValueMEI(mOutputPath.mEndpointId),
ChipLogValueMEI(mOutputPath.mClusterId));
}
}
}

return session;
}

@@ -212,7 +225,7 @@ bool AttributePathExpandIterator::AdvanceOutputPath(SearchSession & session)
if (mOutputPath.mClusterId != kInvalidClusterId)
{

std::optional<AttributeId> nextAttribute = NextAttributeId();
std::optional<AttributeId> nextAttribute = NextAttributeId(session);
if (nextAttribute.has_value())
{
mOutputPath.mAttributeId = *nextAttribute;
3 changes: 2 additions & 1 deletion src/app/AttributePathExpandIterator.h
Original file line number Diff line number Diff line change
@@ -68,6 +68,7 @@ class AttributePathExpandIterator
{
std::unique_ptr<DataModel::MetaDataIterator<EndpointId, DataModel::EndpointInfo>> endpoints;
std::unique_ptr<DataModel::MetaDataIterator<ClusterId, DataModel::ClusterInfo>> clusters;
std::unique_ptr<DataModel::MetaDataIterator<AttributeId, DataModel::AttributeInfo>> attributes;
};

/**
@@ -140,7 +141,7 @@ class AttributePathExpandIterator
/// Respects path expansion/values in mpAttributePath
///
/// Handles Global attributes (which are returned at the end)
std::optional<AttributeId> NextAttributeId();
std::optional<AttributeId> NextAttributeId(SearchSession & session);

/// Get the next cluster ID in mOutputPath(endpoint) if one is available.
/// Will start from the beginning if current mOutputPath.mClusterId is kInvalidClusterId
2 changes: 1 addition & 1 deletion src/app/InteractionModelEngine.cpp
Original file line number Diff line number Diff line change
@@ -1565,7 +1565,7 @@ CHIP_ERROR InteractionModelEngine::PushFrontAttributePathList(SingleLinkedListNo

bool InteractionModelEngine::IsExistentAttributePath(const ConcreteAttributePath & path)
{
return GetDataModelProvider()->GetAttributeInfo(path).has_value();
return GetDataModelProvider()->GetAttributes(path)->SeekTo(path.mAttributeId);
}

void InteractionModelEngine::RemoveDuplicateConcreteAttributePath(SingleLinkedListNode<AttributePathParams> *& aAttributePaths)
8 changes: 7 additions & 1 deletion src/app/WriteHandler.cpp
Original file line number Diff line number Diff line change
@@ -110,7 +110,13 @@ std::optional<bool> WriteHandler::IsListAttributePath(const ConcreteAttributePat
return std::nullopt;
}

auto info = mDataModelProvider->GetAttributeInfo(path);
auto attributes = mDataModelProvider->GetAttributes(path);
if (!attributes->SeekTo(path.mAttributeId))
{
return std::nullopt;
}

auto info = attributes->GetMetadata();
if (!info.has_value())
{
return std::nullopt;
12 changes: 1 addition & 11 deletions src/app/data-model-provider/MetadataTypes.h
Original file line number Diff line number Diff line change
@@ -210,17 +210,7 @@ class ProviderMetadataTree
virtual std::unique_ptr<ElementIterator<CommandId>> GetGeneratedCommands(ConcreteClusterPath clusterPath) = 0;
virtual std::unique_ptr<MetaDataIterator<CommandId, CommandInfo>> GetAcceptedCommands(ConcreteClusterPath clusterPath) = 0;
virtual std::unique_ptr<MetaDataIterator<ClusterId, ClusterInfo>> GetServerClusters(EndpointId endpointId) = 0;

virtual std::unique_ptr<MetaDataIterator<AttributeId, AttributeInfo>> GetAttributes(ConcreteClusterPath clusterPath)
{
return std::make_unique<NullMetadataIterator<AttributeId, AttributeInfo>>();
}

// Attribute iteration and accessors provide cluster-level access over
// attributes
virtual AttributeEntry FirstAttribute(const ConcreteClusterPath & cluster) = 0;
virtual AttributeEntry NextAttribute(const ConcreteAttributePath & before) = 0;
virtual std::optional<AttributeInfo> GetAttributeInfo(const ConcreteAttributePath & path) = 0;
virtual std::unique_ptr<MetaDataIterator<AttributeId, AttributeInfo>> GetAttributes(ConcreteClusterPath clusterPath) = 0;

/// Workaround function to report attribute change.
///
8 changes: 7 additions & 1 deletion src/app/reporting/Engine.cpp
Original file line number Diff line number Diff line change
@@ -77,7 +77,13 @@ std::optional<CHIP_ERROR> ValidateReadAttributeACL(DataModel::Provider * dataMod
.requestType = RequestType::kAttributeReadRequest,
.entityId = path.mAttributeId };

std::optional<DataModel::AttributeInfo> info = dataModel->GetAttributeInfo(path);
std::optional<DataModel::AttributeInfo> info;

auto attributes = dataModel->GetAttributes(path);
if (attributes->SeekTo(path.mAttributeId))
{
info = attributes->GetMetadata();
}

// If the attribute exists, we know whether it is readable (readPrivilege has value)
// and what the required access privilege is. However for attributes missing from the metatada
15 changes: 3 additions & 12 deletions src/app/tests/test-interaction-model-api.cpp
Original file line number Diff line number Diff line change
@@ -176,19 +176,10 @@ TestImCustomDataModel::GetServerClusters(EndpointId endpointId)
return CodegenDataModelProviderInstance(nullptr /* delegate */)->GetServerClusters(endpointId);
}

AttributeEntry TestImCustomDataModel::FirstAttribute(const ConcreteClusterPath & cluster)
std::unique_ptr<DataModel::MetaDataIterator<AttributeId, DataModel::AttributeInfo>>
TestImCustomDataModel::GetAttributes(ConcreteClusterPath clusterPath)
{
return CodegenDataModelProviderInstance(nullptr /* delegate */)->FirstAttribute(cluster);
}

AttributeEntry TestImCustomDataModel::NextAttribute(const ConcreteAttributePath & before)
{
return CodegenDataModelProviderInstance(nullptr /* delegate */)->NextAttribute(before);
}

std::optional<AttributeInfo> TestImCustomDataModel::GetAttributeInfo(const ConcreteAttributePath & path)
{
return CodegenDataModelProviderInstance(nullptr /* delegate */)->GetAttributeInfo(path);
return CodegenDataModelProviderInstance(nullptr /* delegate */)->GetAttributes(clusterPath);
}

} // namespace app
5 changes: 2 additions & 3 deletions src/app/tests/test-interaction-model-api.h
Original file line number Diff line number Diff line change
@@ -117,10 +117,9 @@ class TestImCustomDataModel : public DataModel::Provider
GetAcceptedCommands(ConcreteClusterPath clusterPath) override;
std::unique_ptr<DataModel::MetaDataIterator<ClusterId, DataModel::ClusterInfo>>
GetServerClusters(EndpointId endpointId) override;
std::unique_ptr<DataModel::MetaDataIterator<AttributeId, DataModel::AttributeInfo>>
GetAttributes(ConcreteClusterPath clusterPath) override;

DataModel::AttributeEntry FirstAttribute(const ConcreteClusterPath & cluster) override;
DataModel::AttributeEntry NextAttribute(const ConcreteAttributePath & before) override;
std::optional<DataModel::AttributeInfo> GetAttributeInfo(const ConcreteAttributePath & path) override;
void Temporary_ReportAttributeChanged(const AttributePathParams & path) override {}

// NULL implementations
15 changes: 3 additions & 12 deletions src/controller/tests/data_model/DataModelFixtures.cpp
Original file line number Diff line number Diff line change
@@ -503,19 +503,10 @@ std::unique_ptr<MetaDataIterator<CommandId, CommandInfo>> CustomDataModel::GetAc
return CodegenDataModelProviderInstance(nullptr /* delegate */)->GetAcceptedCommands(clusterPath);
}

AttributeEntry CustomDataModel::FirstAttribute(const ConcreteClusterPath & cluster)
std::unique_ptr<DataModel::MetaDataIterator<AttributeId, DataModel::AttributeInfo>>
CustomDataModel::GetAttributes(ConcreteClusterPath clusterPath)
{
return CodegenDataModelProviderInstance(nullptr /* delegate */)->FirstAttribute(cluster);
}

AttributeEntry CustomDataModel::NextAttribute(const ConcreteAttributePath & before)
{
return CodegenDataModelProviderInstance(nullptr /* delegate */)->NextAttribute(before);
}

std::optional<AttributeInfo> CustomDataModel::GetAttributeInfo(const ConcreteAttributePath & path)
{
return CodegenDataModelProviderInstance(nullptr /* delegate */)->GetAttributeInfo(path);
return CodegenDataModelProviderInstance(nullptr /* delegate */)->GetAttributes(clusterPath);
}

} // namespace app
5 changes: 2 additions & 3 deletions src/controller/tests/data_model/DataModelFixtures.h
Original file line number Diff line number Diff line change
@@ -129,10 +129,9 @@ class CustomDataModel : public DataModel::Provider
GetAcceptedCommands(ConcreteClusterPath clusterPath) override;
std::unique_ptr<DataModel::MetaDataIterator<ClusterId, DataModel::ClusterInfo>>
GetServerClusters(EndpointId endpointId) override;
std::unique_ptr<DataModel::MetaDataIterator<AttributeId, DataModel::AttributeInfo>>
GetAttributes(ConcreteClusterPath clusterPath) override;

DataModel::AttributeEntry FirstAttribute(const ConcreteClusterPath & cluster) override;
DataModel::AttributeEntry NextAttribute(const ConcreteAttributePath & before) override;
std::optional<DataModel::AttributeInfo> GetAttributeInfo(const ConcreteAttributePath & path) override;
void Temporary_ReportAttributeChanged(const AttributePathParams & path) override {}

// NULL implementations
Loading

0 comments on commit 74b9e29

Please sign in to comment.