blob: 5022e170bc401bcd8836164ec92c13e83430478a [file] [log] [blame]
/*
*
* Copyright (c) 2016-2017 Nest Labs, Inc.
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file
* This file forms the crux of the TDM layer (trait data management), providing
* various classes that manage and process data as it applies to traits and their
* associated schemas.
*
*/
#ifndef _WEAVE_DATA_MANAGEMENT_TRAIT_DATA_CURRENT_H
#define _WEAVE_DATA_MANAGEMENT_TRAIT_DATA_CURRENT_H
#include <Weave/Profiles/data-management/Current/WdmManagedNamespace.h>
#include <Weave/Core/WeaveCore.h>
#include <Weave/Core/WeaveMessageLayer.h>
#include <Weave/Profiles/ProfileCommon.h>
#include <Weave/Support/CodeUtils.h>
#include <Weave/Profiles/data-management/MessageDef.h>
namespace nl {
namespace Weave {
namespace Profiles {
namespace WeaveMakeManagedNamespaceIdentifier(DataManagement, kWeaveManagedNamespaceDesignation_Current) {
/*
* A PropertyPathHandle is a unique 32-bit numerical hash of a WDM path relative to the root of a trait instance. It has two parts to it:
* - A lower 16-bit number that maps to the static portion of the schema.
* - Where the lower 16-bits refer to a path within a dictionary element, an upper 16-bit number is present that represents the dictionary key associated with that element.
* If the lower 16-bits refer to a non dictionary element, then the upper 16-bits should be 0.
*
* Some characteristics:
* - Every trait has its own property path handle space.
* - Every unique WDM sub-path path will have a similarly unique PropertyPathHandle.
* - PropertyPathHandles are auto-generated (done by hand for now) by a trait compiler from IDL and is represented as an enumerant list in the corresponding trait's header file.
* - With this construct, application logic never has to deal with WDM paths directly. Rather, their interactions with WDM are conducted exclusively through these handles.
* - There are two reserved values for path handles that have specific meaning:
* - 0 indicates a 'NULL' handle
* - 1 indicates a handle that points to the root of the trait instance.
*
*/
typedef uint32_t PropertyPathHandle;
typedef uint16_t PropertySchemaHandle;
typedef uint16_t PropertyDictionaryKey;
/* Reserved property path handles that have special meaning */
enum {
kNullPropertyPathHandle = 0,
kRootPropertyPathHandle = 1
};
inline PropertyPathHandle CreatePropertyPathHandle(PropertySchemaHandle aPropertyPathSchemaId, PropertyDictionaryKey aPropertyPathDictionaryKey = 0) {
return (((uint32_t)aPropertyPathDictionaryKey << 16) | aPropertyPathSchemaId);
}
inline PropertySchemaHandle GetPropertySchemaHandle(PropertyPathHandle aHandle) {
return (aHandle & 0xffff);
}
inline PropertyDictionaryKey GetPropertyDictionaryKey(PropertyPathHandle aHandle) {
return (aHandle >> 16);
}
inline bool IsRootPropertyPathHandle(PropertyPathHandle aHandle) {
return (aHandle == kRootPropertyPathHandle);
}
inline bool IsNullPropertyPathHandle(PropertyPathHandle aHandle) {
return (aHandle == kNullPropertyPathHandle);
}
/*
* @class TraitSchemaEngine
*
* @brief The schema engine takes schema information associated with a particular trait and provides facilities to parse and translate that into a form usable by the WDM machinery.
* This includes converting from PathHandles to WDM paths (and vice versa), methods to interpret/query the schema itself and methods to help read/write out data to/from TLV given a handle.
*
* The schema itself is stored in tabular form, sufficiently described to allow for generic parsing/composition of WDM paths/data for any given trait. These tables are what will be the
* eventual output of 'code-gen' (The term itself being somewhat misleading given the absence of any generated code :P)
*/
class TraitSchemaEngine
{
public:
/* Provides information about a particular path handle including its parent property schema handle,
* its context tag and its name.
*/
struct PropertyInfo {
PropertySchemaHandle mParentHandle;
uint8_t mContextTag;
};
/**
* @brief
* The main schema structure that houses the schema information.
*/
struct Schema {
uint32_t mProfileId; //< The ID of the trait profile.
const PropertyInfo *mSchemaHandleTbl; //< A pointer to the schema handle table, which provides parent info and context tags for each schema handle.
uint32_t mNumSchemaHandleEntries; //< The number of schema handles in this trait.
uint32_t mTreeDepth; //< The max depth of this schema.
uint8_t *mIsDictionaryBitfield; //< A bitfield indicating whether each schema handle is a dictionary or not.
uint8_t *mIsOptionalBitfield; //< A bitfield indicating whether each schema handle is optional or not.
uint8_t *mIsImplementedBitfield; //< A bitfield indicating whether each optional schema handle is implemented or not.
uint8_t *mIsNullableBitfield; //< A bitfield indicating whether each schema handle is nullable or not.
uint8_t *mIsEphemeralBitfield; //< A bitfield indicating whether each schema handle is ephemeral or not.
};
/* While traits can have deep nested structures (which can include dictionaries), application logic is only expected to provide getters/setters for 'leaf' nodes in the schema. If one can visualize a
* schema as a tree (a directed graph where you can have at most one parent for any given node) where branches indicate the presence of a nested structure, then this analogy fits in quite nicely.
*/
class IDataSinkDelegate
{
public:
enum DataSinkEventType {
/* Start of replacement of an entire dictionary */
kDataSinkEvent_DictionaryReplaceBegin,
/* End of replacement of an entire dictionary */
kDataSinkEvent_DictionaryReplaceEnd,
/* Start of modification or addition of a dictionary item */
kDataSinkEvent_DictionaryItemModifyBegin,
/* End of modification or addition of a dictionary item */
kDataSinkEvent_DictionaryItemModifyEnd,
};
/**
* Given a path handle to a leaf node and a TLV reader, set the leaf data in the callee.
*
* @retval #WEAVE_NO_ERROR On success.
* @retval other Was unable to read out data from the reader.
*/
virtual WEAVE_ERROR SetLeafData(PropertyPathHandle aLeafHandle, nl::Weave::TLV::TLVReader &aReader) = 0;
/**
* Given a path handle to a node, a TLV reader, and an indication
* of whether a null type was received, set the data in the callee.
* TDM will only call this function for handles that are nullable,
* optional, ephemeral, or leafs. If aHandle is a non-leaf node
* and is nullified, TDM will not call SetData for its children.
*
* @param[in] aHandle The PropertyPathHandle in question.
*
* @param[inout] aReader The TLV reader to read from.
*
* @param[out] aIsNull Is aHandle nullified?
*
* @retval #WEAVE_NO_ERROR On success.
* @retval other Was unable to read out data from the reader.
*/
virtual WEAVE_ERROR SetData(PropertyPathHandle aHandle, nl::Weave::TLV::TLVReader &aReader, bool aIsNull) = 0;
/**
* Signals to delegates when notable events occur while parsing dictionaries. In all cases, a property path handle is provided that provides more context on what this event applies to.
*
* For dictionary replace begin/ends, these handles are purely schema handles.
* For dictionary item added/modififed events, these handles are property path handles as they contain the dictionary key as well.
*/
virtual void OnDataSinkEvent(DataSinkEventType aType, PropertyPathHandle aHandle) = 0;
};
class IDataSourceDelegate
{
public:
/**
* Given a path handle to a leaf node and a TLV writer, get the data from the callee.
*
* @retval #WEAVE_NO_ERROR On success.
* @retval other Was unable to retrieve data and write it into the writer.
*/
virtual WEAVE_ERROR GetLeafData(PropertyPathHandle aLeafHandle, uint64_t aTagToWrite, nl::Weave::TLV::TLVWriter &aWriter) = 0;
/**
* Given a path handle to a node, a TLV writer, and booleans indicating whether the
* value is null or not present, get the data from the trait source that will build a
* notify. If the path handle is not a leaf node, TDM will handle writing values to
* the writer (like opening containers, nullifying the struct, etc). If a non-leaf
* node is null or not present, TDM will not call GetData for its children.
*
* This function will only be called for handles that are nullable, optional,
* ephemeral, or leafs. The expectation is that any traits with handles that
* have those options enabled will implement appropriate logic to populate
* aIsNull and aIsPresent.
*
* @param[in] aHandle The PropertyPathHandle in question.
*
* @param[in] aTagToWrite The tag to write for the aHandle.
*
* @param[inout] aWriter The writer to write TLV elements to.
*
* @param[out] aIsNull Is aHandle nullified? If yes, TDM will write
* a null element. If aHandle is not a leaf,
* TDM will skip over its children.
*
* @param[out] aIsPresent Is aHandle present? If no and if aHandle
* is not a leaf, TDM will skip over the
* path and its children.
*
*
* @retval #WEAVE_NO_ERROR On success.
* @retval other Was unable to retrieve data and write it into the writer.
*/
virtual WEAVE_ERROR GetData(PropertyPathHandle aHandle,
uint64_t aTagToWrite,
nl::Weave::TLV::TLVWriter &aWriter,
bool &aIsNull,
bool &aIsPresent) = 0;
#if TDM_ENABLE_PUBLISHER_DICTIONARY_SUPPORT
/**
* Given a handle to a particular dictionary and some context (that is usable by the delegate to track state between invocations), return
* the next dictionary item key.
*
* The context is initially set to 0 on the first call. There-after, the application is allowed to store any data
* (up to width of a pointer) within that variable and it will be passed in un-modified on successive invocations.
*
* @retval #WEAVE_NO_ERROR On success.
* @retval #WEAVE_END_OF_INPUT if there are no more keys to iterate over in the dictionary.
*
*/
virtual WEAVE_ERROR GetNextDictionaryItemKey(PropertyPathHandle aDictionaryHandle, uintptr_t &aContext, PropertyDictionaryKey &aKey) = 0;
#endif
};
/**
* Given a reader positioned at the root of a WDM path element, read out the relevant tags and provide
* the equivalent path handle.
*
*
* @retval #WEAVE_NO_ERROR On success.
* @retval #WEAVE_ERROR_TLV_TAG_NOT_FOUND If a matching handle could not be found due to a
* malformed/incorrectly specified path.
*/
WEAVE_ERROR MapPathToHandle(nl::Weave::TLV::TLVReader &aPathReader, PropertyPathHandle &aHandle) const;
/**
* Convert the path handle to a TLV path.
*
* @retval #WEAVE_NO_ERROR On success.
* @retval other Was unable to convert the handle to a TLV path
*/
WEAVE_ERROR MapHandleToPath(PropertyPathHandle aHandle, nl::Weave::TLV::TLVWriter &aPathWriter) const;
/**
* Given a path handle and a reader positioned on the corresponding data element, process the data buffer pointed to by the reader and
* store it into the sink by invoking the SetLeafData call whenever a leaf data item is encountered.
*
* @retval #WEAVE_NO_ERROR On success.
* @retval other Encountered errors parsing/processing the data.
*/
WEAVE_ERROR StoreData(PropertyPathHandle aHandle, nl::Weave::TLV::TLVReader &aReader, IDataSinkDelegate *aDelegate) const;
/**
* Given a path handle and a writer position on the corresponding data element, retrieve leaf data from the source and write it into the buffer
* pointed to by the writer in a schema compliant manner.
*
* @retval #WEAVE_NO_ERROR On success.
* @retval other Encountered errors writing out the data.
*/
WEAVE_ERROR RetrieveData(PropertyPathHandle aHandle, uint64_t aTagToWrite, nl::Weave::TLV::TLVWriter &aWriter, IDataSourceDelegate *aDelegate) const;
/**********
*
* Schema Query Functions
*
*********/
/* Offset from the value of a path that provides the index into the table for that handle
* It is 2 since the 0 and 1 are special handles.
*/
static const uint32_t kHandleTableOffset = 2;
/* Returns the property path handle of the child of a parent given the parent handle and the child's context tag.
* If the parent happens to be in a dictionary, the key is preserved in the child.
*/
PropertyPathHandle GetChildHandle(PropertyPathHandle aParentHandle, uint8_t aContextTag) const;
/* Returns the property path handle of the dictionary item given its parent dictionary handle and an item
* key.
*/
PropertyPathHandle GetDictionaryItemHandle(PropertyPathHandle aParentHandle, uint16_t aDictionaryKey) const;
/**
* Returns true if the handle refers to a leaf node in the schema tree.
*
* @retval bool
*/
bool IsLeaf(PropertyPathHandle aPropertyHandle) const;
/**
* Returns a pointer to the PropertyInfo structure describing a particular path handle.
*
* @retval PropertyInfo*
*/
const PropertyInfo *GetMap(PropertyPathHandle aHandle) const;
/**
* Returns the tag associated with a path handle. If it's a dictionary element, this function returns the ProfileTag. Otherwise, it returns
* context tags.
*
* @retval uint64_t
*/
uint64_t GetTag(PropertyPathHandle aHandle) const;
/**
* Returns the parent handle of a given child path handle. Dictionary keys in the handle are preserved in the case where the parent
* handle is also a dictionary element.
*
* @retval PropertyPathHandle Handle of the parent.
*/
PropertyPathHandle GetParent(PropertyPathHandle aHandle) const;
/**
* Returns the first child handle associated with a particular parent.
*
* @retval PropertyPathHandle Handle of the first child.
*/
PropertyPathHandle GetFirstChild(PropertyPathHandle aParentHandle) const;
/**
* Given a handle to an existing child, returns the next child handle associated with a particular parent.
*
* @retval PropertyPathHandle Handle of the next child.
*/
PropertyPathHandle GetNextChild(PropertyPathHandle aParentId, PropertyPathHandle aChildHandle) const;
/**
* Calculate the depth in the schema tree for a given handle.
*
* @retval int32_t The depth in the tree
*/
int32_t GetDepth(PropertyPathHandle aHandle) const;
/**
* Given two property handles, calculate the lowest handle that serves as a parent to both of these handles. Additionally, return the two child branches that contain each of the two handles (even
* if they are the same).
*
* @retval PropertyPathHandle Handle to the lowest parent.
*/
PropertyPathHandle FindLowestCommonAncestor(PropertyPathHandle aHandle1, PropertyPathHandle aHandle2, PropertyPathHandle *aHandle1BranchChild, PropertyPathHandle *aHandle2BranchChild) const;
/**
* Returns true if the passed in profileId matches that stored in the schema.
*
* @retval bool
*/
bool MatchesProfileId(uint32_t aProfileId) const;
/**
* Returns the profile id of the associated trait.
*
* @retval Trait profile id
*/
uint32_t GetProfileId(void) const;
/**
* Returns true if the handle is a dictionary (and not in a dictionary - see method below).
*
* @retval bool
*/
bool IsDictionary(PropertyPathHandle aHandle) const;
/**
* Returns true if the handle is *inside* a dictionary (a dictionary element). A user passed in handle (aDictionaryItemHandle) is updated to
* point to the top-most dictionary element handle within the dictionary.
*
* @retval bool
*/
bool IsInDictionary(PropertyPathHandle aHandle, PropertyPathHandle &aDictionaryItemHandle) const;
bool IsNullable(PropertyPathHandle aHandle) const;
bool IsEphemeral(PropertyPathHandle aHandle) const;
bool IsOptional(PropertyPathHandle aHandle) const;
/**
* Checks if a given handle is a child of another handle. This can be an in-direct parent.
*
* @retval bool
*/
bool IsParent(PropertyPathHandle aChildHandle, PropertyPathHandle aParentHandle) const;
/**
* Given a version range, this function checks to see if there is a compatibility intersection between that
* and what is supported by schema that is backing this schema engine. If there is an intersection, the function will
* return true and update the aIntersection argument passed in to reflect that results of that intersection test.
*/
bool GetVersionIntersection(SchemaVersionRange &aVersion, SchemaVersionRange &aIntersection) const;
/**
* Given a provided data schema version, this will return the highest forward compatible schema version.
*/
SchemaVersion GetHighestForwardVersion(SchemaVersion aVersion) const;
/**
* Given a provided data schema version, this will return the minimum compatible schema version
*/
SchemaVersion GetLowestCompatibleVersion(SchemaVersion aVersion) const;
private:
PropertyPathHandle _GetChildHandle(PropertyPathHandle aParentHandle, uint8_t aContextTag) const;
bool GetBitFromPathHandleBitfield(uint8_t *aBitfield, PropertyPathHandle aPathHandle) const;
public:
const Schema mSchema;
};
/*
* @class TraitDataSink
*
* @brief Base abstract class that represents a particular instance of a trait on a specific external resource (client). Application
* developers are expected to subclass this to make a concrete sink that ingests data received from publishers.
*
* It takes in a pointer to a schema that it then uses to help decipher incoming TLV data from a publisher and invoke the
* relevant data setter calls to pass the data up to subclasses.
*/
class TraitDataSink : private TraitSchemaEngine::IDataSinkDelegate
{
public:
TraitDataSink(const TraitSchemaEngine *aEngine);
const TraitSchemaEngine *GetSchemaEngine(void) const { return mSchemaEngine; }
typedef WEAVE_ERROR (*OnChangeRejection)(uint16_t aRejectionStatusCode, uint64_t aVersion, void *aContext);
enum ChangeFlags {
kFirstElementInChange = (1 << 0),
kLastElementInChange = (1 << 1)
};
/**
* Given a reader that points to a data element conformant to a schema bound to this object, this method processes that data and
* invokes the relevant SetLeafData call below for all leaf items in the buffer.
*
* A change rejection function can be passed in as well that will be invoked if the sink chooses to reject this data for any reason.
*
* @retval #WEAVE_NO_ERROR On success.
* @retval other Encountered errors writing out the data.
*/
WEAVE_ERROR StoreDataElement(PropertyPathHandle aHandle, TLV::TLVReader &aReader, uint8_t aFlags, OnChangeRejection aFunc, void *aContext);
/**
* Retrieves the current version of the data that resides in this sink.
*/
uint64_t GetVersion(void) const { return mVersion; }
/**
* Returns a boolean value that determines whether the version is valid.
*/
bool IsVersionValid(void) const { return mHasValidVersion; }
/**
* Convenience function for data sinks to handle unknown leaf handles with
* a system level tolerance for mismatched schema as defined by
* TDM_DISABLE_STRICT_SCHEMA_COMPILANCE.
*/
WEAVE_ERROR HandleUnknownLeafHandle(void)
{
#if TDM_DISABLE_STRICT_SCHEMA_COMPLIANCE
return WEAVE_NO_ERROR;
#else
return WEAVE_ERROR_TLV_TAG_NOT_FOUND;
#endif
}
enum EventType {
/* Signals the beginning of a change record which in certain scenarios can span multiple data elements over multiple notifies
* (the latter only a possibility if the data being transmitted is unable to fit within a single packet)
*/
kEventChangeBegin,
/* Start of a data element */
kEventDataElementBegin,
/* End of a data element */
kEventDataElementEnd,
/* End of a change record */
kEventChangeEnd,
/* Start of replacement of an entire dictionary */
kEventDictionaryReplaceBegin,
/* End of replacement of an entire dictionary */
kEventDictionaryReplaceEnd,
/* Start of modification or addition of a dictionary item */
kEventDictionaryItemModifyBegin,
/* End of modification or addition of a dictionary item */
kEventDictionaryItemModifyEnd,
/* Deletion of a dictionary item */
kEventDictionaryItemDelete,
/* Signals the start of the processing of a notify packet
*/
kEventNotifyRequestBegin,
/* Signals the end of the processing of a notify packet
*/
kEventNotifyRequestEnd,
/* Signals the start of the processing of a view response
* TODO: I'm not entirely convinced of the need to have this event.
*/
kEventViewResponseBegin,
/* Signals the end of the processing of a view response
* TODO: I'm not entirely convinced of the need to have this event.
*/
kEventViewResponseEnd,
/* Signals the termination of a subscription either due to an error, or the subscription was cancelled */
kEventSubscriptionTerminated
};
union InEventParam {
struct {
PropertyPathHandle mTargetHandle;
} mDictionaryReplaceBegin;
struct {
PropertyPathHandle mTargetHandle;
} mDictionaryReplaceEnd;
struct {
PropertyPathHandle mTargetHandle;
} mDictionaryItemModifyBegin;
struct {
PropertyPathHandle mTargetHandle;
} mDictionaryItemModifyEnd;
struct {
PropertyPathHandle mTargetHandle;
} mDictionaryItemDelete;
};
/*
* Invoked either by the base class or by an external agent (like the subscription engine) to signal the occurence of an event (of type EventType).
* Sub-classes are expected to over-ride this if they desire to be made known of these events.
*/
virtual WEAVE_ERROR OnEvent(uint16_t aType, void *aInEventParam) { return WEAVE_NO_ERROR; }
protected: // IDataSinkDelegate
virtual WEAVE_ERROR SetLeafData(PropertyPathHandle aLeafHandle, nl::Weave::TLV::TLVReader &aReader) __OVERRIDE = 0;
/*
* Defaults to calling SetLeafData if aHandle is a leaf. DataSinks
* can optionally implement this if they need to support nullable,
* ephemeral, or optional properties.
*
* TODO: make this the defacto API, moving all the logic from
* SetLeafData into this function.
*/
virtual WEAVE_ERROR SetData(PropertyPathHandle aHandle,
nl::Weave::TLV::TLVReader &aReader,
bool aIsNull) __OVERRIDE;
/* Subclass can invoke this if they desire to reject a particular data change */
void RejectChange(uint16_t aRejectionStatusCode);
/* Subclass can invoke this to clear out their version */
void ClearVersion(void) { mHasValidVersion = false; }
const TraitSchemaEngine *mSchemaEngine;
private:
void OnDataSinkEvent(DataSinkEventType aType, PropertyPathHandle aHandle) __OVERRIDE;
uint64_t mVersion;
bool mHasValidVersion;
static OnChangeRejection sChangeRejectionCb;
static void *sChangeRejectionContext;
};
class Command;
class TraitDataSource : private TraitSchemaEngine::IDataSourceDelegate
{
public:
TraitDataSource(const TraitSchemaEngine *aEngine);
const TraitSchemaEngine *GetSchemaEngine(void) const { return mSchemaEngine; }
uint64_t GetVersion(void) const { return mVersion; }
WEAVE_ERROR ReadData(PropertyPathHandle aHandle, uint64_t aTagToWrite, TLV::TLVWriter &aWriter);
/* Interactions with the underlying data has to always be done within a locked context. This applies to both the app logic (e.g a publisher when modifying its source data)
* as well as to the core WDM logic (when trying to access that published data). This is required of both publishers and clients.
*/
WEAVE_ERROR Lock(void);
WEAVE_ERROR Unlock(void);
void SetDirty(PropertyPathHandle aPropertyHandle);
#if TDM_ENABLE_PUBLISHER_DICTIONARY_SUPPORT
void DeleteKey(PropertyPathHandle aPropertyHandle);
#endif
virtual void OnCustomCommand(Command * aCommand,
const nl::Weave::WeaveMessageInfo * aMsgInfo,
nl::Weave::PacketBuffer * aPayload,
const uint64_t & aCommandType,
const bool aIsExpiryTimeValid,
const int64_t & aExpiryTimeMicroSecond,
const bool aIsMustBeVersionValid,
const uint64_t & aMustBeVersion,
nl::Weave::TLV::TLVReader & aArgumentReader);
/*
* Invoked either by the base class or by an external agent (like the subscription engine) to signal the occurrence of an event (of type EventType).
* Sub-classes are expected to over-ride this if they desire to be made known of these events.
*/
virtual WEAVE_ERROR OnEvent(uint16_t aType, void *aInEventParam) { return WEAVE_NO_ERROR; }
#if (WEAVE_CONFIG_WDM_PUBLISHER_GRAPH_SOLVER == IntermediateGraphSolver)
/* Set of functions to be called by the intermediate graph solver on the notification engine for marking/clearing this entire data source as dirty */
void SetRootDirty(void) { mRootIsDirty = true; }
void ClearRootDirty(void) { mRootIsDirty = false; }
bool IsRootDirty(void) const { return mRootIsDirty; }
bool mRootIsDirty;
#endif
protected: // IDataSourceDelegate
/*
* Defaults to calling GetLeafData if aHandle is a leaf. DataSources
* can optionally implement this if they need to support nullable,
* ephemeral, or optional properties.
*
* TODO: make this the defacto API, moving all the logic from
* GetLeafData into this function.
*/
virtual WEAVE_ERROR GetData(PropertyPathHandle aHandle,
uint64_t aTagToWrite,
nl::Weave::TLV::TLVWriter &aWriter,
bool &aIsNull,
bool &aIsPresent) __OVERRIDE;
virtual WEAVE_ERROR GetLeafData(PropertyPathHandle aLeafHandle, uint64_t aTagToWrite, nl::Weave::TLV::TLVWriter &aWriter) __OVERRIDE = 0 ;
#if TDM_ENABLE_PUBLISHER_DICTIONARY_SUPPORT
virtual WEAVE_ERROR GetNextDictionaryItemKey(PropertyPathHandle aDictionaryHandle, uintptr_t &aContext, PropertyDictionaryKey &aKey) __OVERRIDE { return WEAVE_ERROR_INVALID_ARGUMENT; }
#endif
void IncrementVersion(void) { mVersion++; }
uint64_t mVersion;
// Controls whether mVersion is incremented automatically or not.
bool mManagedVersion;
const TraitSchemaEngine *mSchemaEngine;
private:
// Tracks whether SetDirty was called within a Lock/Unlock 'session'
bool mSetDirtyCalled;
};
}; // WeaveMakeManagedNamespaceIdentifier(DataManagement, kWeaveManagedNamespaceDesignation_Current)
}; // Profiles
}; // Weave
}; // nl
#endif // _WEAVE_DATA_MANAGEMENT_TRAIT_DATA_CURRENT_H