Provide a protocol for containers holding logging attributes.
Outline
Purpose
Provide a protocol for containers holding logging attributes.
Classes
- See also
- ball_attribute, ball_defaultattributecontainer
Description
This component defines a protocol class, ball::AttributeContainer, for containers of ball::Attribute values. The ball::AttributeContainer protocol primarily provides a hasValue() method, allowing clients to determine if a given attribute value is held by the container.
This component participates in the implementation of "Rule-Based Logging". For more information on how to use that feature, please see the package level documentation and usage examples for "Rule-Based Logging".
Usage
In the following examples we examine two derived implementations of the ball::AttributeContainer protocol. The first implementation is potentially more efficient, holding a specific group of attributes relevant to a particular application. The second implementation is more general, and can hold any valid ball::Attribute value. In the final example we demonstrate how to call the methods of the ball::AttributeContainer protocol.
Example 1: An Implementation of ball::AttributeContainer
In the following example we develop a ball::AttributeContainer implementation specifically intended for a service offline that will perform rule-based logging, governed by the service client's Bloomberg "uuid", "luw", and "firm number". We define a class ServiceAttributes that contains three integer ball::Attribute values having the names "uuid", "luw", and "firmNumber".
Note that this implementation requires no memory allocation, so it will be more efficient than a more general set-based implementation if the container is frequently created, destroyed, or modified. We will develop a ball::AttributeContainer implementation that can hold any ball::Attribute value in example 2 (and one is provided by the ball package in the ball_defaultattributecontainer component).
Definition ball_attributecontainer.h:426
Note that we use the type ball::Attribute for our data members for simplicity. It would be a little more efficient to use int data members, but the implementation of hasValue() would be less readable.
public:
static const char * const UUID_ATTRIBUTE_NAME;
static const char * const LUW_ATTRIBUTE_NAME;
static const char * const FIRMNUMBER_ATTRIBUTE_NAME;
ServiceAttributes(int uuid, int luw, int firmNumber);
virtual ~ServiceAttributes();
virtual bsl::ostream& print(bsl::ostream& stream,
int level = 0,
int spacesPerLevel = 4) const;
virtual void visitAttributes(
};
inline
ServiceAttributes::ServiceAttributes(int uuid, int luw, int firmNumber)
: d_uuid(UUID_ATTRIBUTE_NAME, uuid)
, d_luw(LUW_ATTRIBUTE_NAME, luw)
, d_firmNumber(FIRMNUMBER_ATTRIBUTE_NAME, firmNumber)
{
}
const char * const ServiceAttributes::UUID_ATTRIBUTE_NAME = "uuid";
const char * const ServiceAttributes::LUW_ATTRIBUTE_NAME = "luw";
const char * const ServiceAttributes::FIRMNUMBER_ATTRIBUTE_NAME =
"firmNumber";
ServiceAttributes::~ServiceAttributes()
{
}
{
return d_uuid == value || d_luw == value || d_firmNumber == value;
}
bsl::ostream& ServiceAttributes::print(bsl::ostream& stream,
int level,
int spacesPerLevel) const
{
printer.start();
printer.printAttribute("uuid", d_uuid);
printer.printAttribute("luw", d_luw);
printer.printAttribute("firmNumber", d_firmNumber);
printer.end();
return stream;
}
void ServiceAttributes::visitAttributes(
{
visitor(d_uuid);
visitor(d_luw);
visitor(d_firmNumber);
}
Definition ball_attribute.h:199
Forward declaration.
Definition bslstl_function.h:946
Definition bslim_printer.h:604
Example 2: A Generic Implementation of ball::AttributeContainer
In this second example we define a ball::AttributeContainer that can contain any valid ball::Attribute value (a "generic" ball::AttributeContainer). In practice, an implementation that can contain any attribute values may be less efficient than one specifically created for a particular group of attributes needed by an application (as shown in {Example 1}).
Note that the ball package provides a similar ball::AttributeContainer implementation in the ball_defaultattributecontainer component.
To define an STL set (or hash set) for ball::Attribute values, we must define a comparison (or hash) operation for attribute values. Here we define a comparison functor that compares attributes by name, then by value-type, and finally by value.
struct AttributeComparator {
{
int cmp = bsl::strcmp(lhs.name(), rhs.name());
if (0 != cmp) {
return cmp < 0;
}
if (lhs.value().typeIndex() != rhs.value().typeIndex()) {
return lhs.value().typeIndex() < rhs.value().typeIndex();
}
switch (
lhs.value().typeIndex()) {
case 0:
return true;
case 1:
return lhs.value().the<
int>() <
rhs.value().the<
int>();
case 2:
return lhs.value().the<
long>() <
rhs.value().the<
long>();
case 3:
return lhs.value().the<
long long>()
<
rhs.value().the<
long long>();
case 4:
return lhs.value().the<
unsigned int>()
<
rhs.value().the<
unsigned int>();
case 5:
return lhs.value().the<
unsigned long>()
<
rhs.value().the<
unsigned long>();
case 6:
return lhs.value().the<
unsigned long long>()
<
rhs.value().the<
unsigned long long>();
case 7:
case 8:
return lhs.value().the<
const void *>() <
rhs.value().the<
const void *>();
case 9:
}
return false;
}
};
public:
virtual ~AttributeSet();
virtual bsl::ostream&
print(bsl::ostream& stream,
int level = 0,
int spacesPerLevel = 4) const;
virtual void visitAttributes(
};
Definition bdlb_guid.h:201
Definition bslstl_string.h:1252
Definition bslstl_set.h:691
Definition bslma_allocator.h:545
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1976
bsl::ostream & print(bsl::ostream &stream, const TYPE &object, int level=0, int spacesPerLevel=4)
Definition bdlb_printmethods.h:725
ALLOCATOR const STRING_VIEW_LIKE_TYPE & rhs
Definition bslstl_string.h:3918
ALLOCATOR & lhs
Definition bslstl_string.h:3917
The AttributeSet methods are simple wrappers around bsl::set methods:
inline
: d_set(AttributeComparator(), basicAllocator)
{
}
inline
{
}
inline
{
return d_set.
erase(value) > 0;
}
AttributeSet::~AttributeSet()
{
}
{
return d_set.
find(value) != d_set.
end();
}
bsl::ostream& AttributeSet::print(bsl::ostream& stream,
int level,
int spacesPerLevel) const
{
printer.start();
for (; it != d_set.
end(); ++it) {
printer.printValue(*it);
}
return stream;
}
void AttributeSet::visitAttributes(
{
for (; it != d_set.
end(); ++it) {
visitor(*it);
}
}
pair< iterator, bool > insert(const value_type &value)
Definition bslstl_set.h:2834
set &operator=(BloombergLP::bslmf::MovableRef< set > rhs) BSLS_KEYWORD_NOEXCEPT_SPECIFICATION(AllocatorTraits iterator begin() BSLS_KEYWORD_NOEXCEPT
Definition bslstl_set.h:2802
iterator find(const key_type &key)
Definition bslstl_set.h:1488
BloombergLP::bslstl::TreeIterator< const value_type, Node, difference_type > const_iterator
Definition bslstl_set.h:796
iterator end() BSLS_KEYWORD_NOEXCEPT
Definition bslstl_set.h:2810
iterator erase(const_iterator position)
Definition bslstl_set.h:3047
Example 3. Using a ball::AttributeContainer
In this final example, we demonstrate how to call the methods of the ball::AttributeContainer protocol.
First we create an object of a concrete type that implements the ball::AttributeContainer protocol (e.g., ServiceAttributes defined in {Example 1}). Then we obtain a reference to this object.
ServiceAttributes serviceAttributes(3938908, 1, 9001);
We use hasValue() to examine the values in the container:
virtual bool hasValue(const Attribute &value) const =0
Finally we can print the attribute values in the container:
bsl::cout << attributes << bsl::endl;
The resulting output should look like:
[ [ uuid = 3938908 ] [ luw = 1 ] [ firmNumber = 9001 ] ]