Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2021 Project CHIP Authors
4 : * All rights reserved.
5 : *
6 : * Licensed under the Apache License, Version 2.0 (the "License");
7 : * you may not use this file except in compliance with the License.
8 : * You may obtain a copy of the License at
9 : *
10 : * http://www.apache.org/licenses/LICENSE-2.0
11 : *
12 : * Unless required by applicable law or agreed to in writing, software
13 : * distributed under the License is distributed on an "AS IS" BASIS,
14 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 : * See the License for the specific language governing permissions and
16 : * limitations under the License.
17 : */
18 : #pragma once
19 :
20 : #include <app/AttributePathParams.h>
21 : #include <app/ConcreteAttributePath.h>
22 : #include <app/data-model-provider/Provider.h>
23 : #include <lib/support/LinkedList.h>
24 :
25 : namespace chip {
26 : namespace app {
27 :
28 : /**
29 : * AttributePathExpandIterator is used to iterate over a linked list of AttributePathParams-s.
30 : * The AttributePathExpandIterator is copiable, however, the given cluster info must be valid when calling Next().
31 : *
32 : * AttributePathExpandIterator will expand attribute paths with wildcards, and only emit existing paths for
33 : * AttributePathParams with wildcards. For AttributePathParams with a concrete path (i.e. does not contain wildcards),
34 : * AttributePathExpandIterator will emit them as-is.
35 : *
36 : * The typical use of AttributePathExpandIterator may look like:
37 : * ConcreteAttributePath path;
38 : * for (AttributePathExpandIterator iterator(AttributePathParams); iterator.Get(path); iterator.Next()) {...}
39 : *
40 : * The iterator does not copy the given AttributePathParams. The given AttributePathParams must remain valid when using the
41 : * iterator. If the set of endpoints, clusters, or attributes that are supported changes, AttributePathExpandIterator must be
42 : * reinitialized.
43 : *
44 : * A initialized iterator will return the first valid path, no need to call Next() before calling Get() for the first time.
45 : *
46 : * Note: Next() and Get() are two separate operations by design since a possible call of this iterator might be:
47 : * - Get()
48 : * - Chunk full, return
49 : * - In a new chunk, Get()
50 : *
51 : * TODO: The AttributePathParams may support a group id, the iterator should be able to call group data provider to expand the group
52 : * id.
53 : */
54 : class AttributePathExpandIterator
55 : {
56 : public:
57 : AttributePathExpandIterator(DataModel::Provider * provider, SingleLinkedListNode<AttributePathParams> * attributePath);
58 :
59 : /**
60 : * Proceed the iterator to the next attribute path in the given cluster info.
61 : *
62 : * Returns false if AttributePathExpandIteratorDataModeDataModel has exhausted all paths in the given AttributePathParams list.
63 : */
64 : bool Next();
65 :
66 : /**
67 : * Fills the aPath with the path the iterator currently points to.
68 : * Returns false if the iterator is not pointing to a valid path (i.e. it has exhausted the cluster info).
69 : */
70 6672 : bool Get(ConcreteAttributePath & aPath)
71 : {
72 6672 : aPath = mOutputPath;
73 6672 : return (mpAttributePath != nullptr);
74 : }
75 :
76 : /**
77 : * Reset the iterator to the beginning of current cluster if we are in the middle of expanding a wildcard attribute id for some
78 : * cluster.
79 : *
80 : * When attributes are changed in the middle of expanding a wildcard attribute, we need to reset the iterator, to provide the
81 : * client with a consistent state of the cluster.
82 : */
83 : void ResetCurrentCluster();
84 :
85 : /** Start iterating over the given `paths` */
86 1992 : inline void ResetTo(SingleLinkedListNode<AttributePathParams> * paths)
87 : {
88 1992 : *this = AttributePathExpandIterator(mDataModelProvider, paths);
89 1992 : }
90 :
91 : private:
92 : DataModel::Provider * mDataModelProvider;
93 : SingleLinkedListNode<AttributePathParams> * mpAttributePath;
94 : ConcreteAttributePath mOutputPath;
95 :
96 : /// Move to the next endpoint/cluster/attribute triplet that is valid given
97 : /// the current mOutputPath and mpAttributePath
98 : ///
99 : /// returns true if such a next value was found.
100 : bool AdvanceOutputPath();
101 :
102 : /// Get the next attribute ID in mOutputPath(endpoint/cluster) if one is available.
103 : /// Will start from the beginning if current mOutputPath.mAttributeId is kInvalidAttributeId
104 : ///
105 : /// Respects path expansion/values in mpAttributePath
106 : ///
107 : /// Handles Global attributes (which are returned at the end)
108 : std::optional<AttributeId> NextAttributeId();
109 :
110 : /// Get the next cluster ID in mOutputPath(endpoint) if one is available.
111 : /// Will start from the beginning if current mOutputPath.mClusterId is kInvalidClusterId
112 : ///
113 : /// Respects path expansion/values in mpAttributePath
114 : std::optional<ClusterId> NextClusterId();
115 :
116 : /// Get the next endpoint ID in mOutputPath if one is available.
117 : /// Will start from the beginning if current mOutputPath.mEndpointId is kInvalidEndpointId
118 : ///
119 : /// Respects path expansion/values in mpAttributePath
120 : std::optional<ClusterId> NextEndpointId();
121 :
122 : /// Checks if the given attributeId is valid for the current mOutputPath(endpoint/cluster)
123 : ///
124 : /// Meaning that it is known to the data model OR it is a always-there global attribute.
125 : bool IsValidAttributeId(AttributeId attributeId);
126 : };
127 :
128 : } // namespace app
129 : } // namespace chip
|