BDE 4.14.0 Production release
Loading...
Searching...
No Matches
ball_attributecontainer.h
Go to the documentation of this file.
1/// @file ball_attributecontainer.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// ball_attributecontainer.h -*-C++-*-
8#ifndef INCLUDED_BALL_ATTRIBUTECONTAINER
9#define INCLUDED_BALL_ATTRIBUTECONTAINER
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup ball_attributecontainer ball_attributecontainer
15/// @brief Provide a protocol for containers holding logging attributes.
16/// @addtogroup bal
17/// @{
18/// @addtogroup ball
19/// @{
20/// @addtogroup ball_attributecontainer
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#ball_attributecontainer-purpose"> Purpose</a>
25/// * <a href="#ball_attributecontainer-classes"> Classes </a>
26/// * <a href="#ball_attributecontainer-description"> Description </a>
27/// * <a href="#ball_attributecontainer-usage"> Usage </a>
28/// * <a href="#ball_attributecontainer-example-1-an-implementation-of-ball-attributecontainer"> Example 1: An Implementation of ball::AttributeContainer </a>
29/// * <a href="#ball_attributecontainer-example-2-a-generic-implementation-of-ball-attributecontainer"> Example 2: A Generic Implementation of ball::AttributeContainer </a>
30/// * <a href="#ball_attributecontainer-example-3-using-a-ball-attributecontainer"> Example 3. Using a ball::AttributeContainer </a>
31///
32/// # Purpose {#ball_attributecontainer-purpose}
33/// Provide a protocol for containers holding logging attributes.
34///
35/// # Classes {#ball_attributecontainer-classes}
36///
37/// - ball::AttributeContainer: a protocol for a collection of attributes
38///
39/// @see ball_attribute, ball_defaultattributecontainer
40///
41/// # Description {#ball_attributecontainer-description}
42/// This component defines a protocol class,
43/// `ball::AttributeContainer`, for containers of `ball::Attribute` values. The
44/// `ball::AttributeContainer` protocol primarily provides a `hasValue()`
45/// method, allowing clients to determine if a given attribute value is held by
46/// the container.
47///
48/// This component participates in the implementation of "Rule-Based Logging".
49/// For more information on how to use that feature, please see the package
50/// level documentation and usage examples for "Rule-Based Logging".
51///
52/// ## Usage {#ball_attributecontainer-usage}
53///
54///
55/// In the following examples we examine two derived implementations of the
56/// `ball::AttributeContainer` protocol. The first implementation is
57/// potentially more efficient, holding a specific group of attributes relevant
58/// to a particular application. The second implementation is more general,
59/// and can hold any valid `ball::Attribute` value. In the final example we
60/// demonstrate how to call the methods of the `ball::AttributeContainer`
61/// protocol.
62///
63/// ### Example 1: An Implementation of ball::AttributeContainer {#ball_attributecontainer-example-1-an-implementation-of-ball-attributecontainer}
64///
65///
66/// In the following example we develop a `ball::AttributeContainer`
67/// implementation specifically intended for a service offline that will perform
68/// rule-based logging, governed by the service client's Bloomberg "uuid",
69/// "luw", and "firm number". We define a class `ServiceAttributes` that
70/// contains three integer `ball::Attribute` values having the names "uuid",
71/// "luw", and "firmNumber".
72///
73/// Note that this implementation requires no memory allocation, so it will be
74/// more efficient than a more general set-based implementation if the container
75/// is frequently created, destroyed, or modified. We will develop a
76/// `ball::AttributeContainer` implementation that can hold any
77/// `ball::Attribute` value in example 2 (and one is provided by the `ball`
78/// package in the @ref ball_defaultattributecontainer component).
79/// @code
80/// // serviceattributes.h
81///
82/// /// Provide a concrete implementation of the `ball::AttributeContainer`
83/// /// that holds the `uuid`, `luw`, and `firmNumber` associated with a
84/// /// request to the example service. This concrete container
85/// /// exposes those properties in attributes named "uuid", "luw", and
86/// /// "firmNumber" respectively.
87/// class ServiceAttributes : public ball::AttributeContainer {
88///
89/// @endcode
90/// Note that we use the type `ball::Attribute` for our data members for
91/// simplicity. It would be a little more efficient to use `int` data members,
92/// but the implementation of `hasValue()` would be less readable.
93/// @code
94/// // DATA
95/// ball::Attribute d_uuid; // Bloomberg user id
96/// ball::Attribute d_luw; // Bloomberg luw
97/// ball::Attribute d_firmNumber; // Bloomberg firm number
98///
99/// // ...
100///
101/// public:
102/// // PUBLIC CONSTANTS
103///
104/// // The names of the attributes exposed by this attribute container.
105/// static const char * const UUID_ATTRIBUTE_NAME;
106/// static const char * const LUW_ATTRIBUTE_NAME;
107/// static const char * const FIRMNUMBER_ATTRIBUTE_NAME;
108///
109/// // CREATORS
110///
111/// /// Create a service-attributes object with the specified `uuid`,
112/// /// `luw`, and `firmNumber`.
113/// ServiceAttributes(int uuid, int luw, int firmNumber);
114///
115/// virtual ~ServiceAttributes();
116/// // Destroy this service-attributes object.
117///
118/// // ACCESSORS
119///
120/// /// Return `true` if the attribute having specified `value` exists
121/// /// in this object, and `false` otherwise. This implementation will
122/// /// return `true` if `value.name()` equals "uuid", "luw", or "firm"
123/// /// and `value.value()` is an `int` equal to the corresponding
124/// /// property value supplied at construction.
125/// virtual bool hasValue(const ball::Attribute& value) const;
126///
127/// /// Format this object to the specified output `stream`.
128/// virtual bsl::ostream& print(bsl::ostream& stream,
129/// int level = 0,
130/// int spacesPerLevel = 4) const;
131///
132/// /// Invoke the specified `visitor` function for all attributes in
133/// /// this container.
134/// virtual void visitAttributes(
135/// const bsl::function<void(const ball::Attribute&)>& visitor) const;
136/// };
137///
138/// // CREATORS
139/// inline
140/// ServiceAttributes::ServiceAttributes(int uuid, int luw, int firmNumber)
141/// : d_uuid(UUID_ATTRIBUTE_NAME, uuid)
142/// , d_luw(LUW_ATTRIBUTE_NAME, luw)
143/// , d_firmNumber(FIRMNUMBER_ATTRIBUTE_NAME, firmNumber)
144/// {
145/// }
146///
147/// // serviceattributes.cpp
148///
149/// // PUBLIC CONSTANTS
150/// const char * const ServiceAttributes::UUID_ATTRIBUTE_NAME = "uuid";
151/// const char * const ServiceAttributes::LUW_ATTRIBUTE_NAME = "luw";
152/// const char * const ServiceAttributes::FIRMNUMBER_ATTRIBUTE_NAME =
153/// "firmNumber";
154///
155/// // CREATORS
156/// ServiceAttributes::~ServiceAttributes()
157/// {
158/// }
159///
160/// // ACCESSORS
161/// bool ServiceAttributes::hasValue(const ball::Attribute& value) const
162/// {
163/// return d_uuid == value || d_luw == value || d_firmNumber == value;
164/// }
165///
166/// bsl::ostream& ServiceAttributes::print(bsl::ostream& stream,
167/// int level,
168/// int spacesPerLevel) const
169/// {
170/// bslim::Printer printer(&stream, level, spacesPerLevel);
171/// printer.start();
172/// printer.printAttribute("uuid", d_uuid);
173/// printer.printAttribute("luw", d_luw);
174/// printer.printAttribute("firmNumber", d_firmNumber);
175/// printer.end();
176/// return stream;
177/// }
178///
179/// void ServiceAttributes::visitAttributes(
180/// const bsl::function<void(const ball::Attribute&)> &visitor) const
181/// {
182/// visitor(d_uuid);
183/// visitor(d_luw);
184/// visitor(d_firmNumber);
185/// }
186/// @endcode
187///
188/// ### Example 2: A Generic Implementation of ball::AttributeContainer {#ball_attributecontainer-example-2-a-generic-implementation-of-ball-attributecontainer}
189///
190///
191/// In this second example we define a `ball::AttributeContainer` that can
192/// contain any valid `ball::Attribute` value (a "generic"
193/// `ball::AttributeContainer`). In practice, an implementation that can
194/// contain any attribute values may be less efficient than one specifically
195/// created for a particular group of attributes needed by an application (as
196/// shown in {Example 1}).
197///
198/// Note that the `ball` package provides a similar `ball::AttributeContainer`
199/// implementation in the @ref ball_defaultattributecontainer component.
200/// @code
201/// // attributeset.h
202///
203/// /// A simple set-based implementation of the `ball::AttributeContainer`
204/// /// protocol, used for testing.
205/// class AttributeSet : public ball::AttributeContainer {
206/// @endcode
207/// To define an STL set (or hash set) for `ball::Attribute` values, we must
208/// define a comparison (or hash) operation for attribute values. Here we
209/// define a comparison functor that compares attributes by name, then by
210/// value-type, and finally by value.
211/// @code
212/// struct AttributeComparator {
213/// /// Return `true` if the specified `lhs` attribute is ordered
214/// /// before the specified `rhs` attribute, and `false` otherwise.
215/// bool operator()(const ball::Attribute& lhs,
216/// const ball::Attribute& rhs) const
217/// {
218/// int cmp = bsl::strcmp(lhs.name(), rhs.name());
219/// if (0 != cmp) {
220/// return cmp < 0;
221/// }
222/// if (lhs.value().typeIndex() != rhs.value().typeIndex()) {
223/// return lhs.value().typeIndex() < rhs.value().typeIndex();
224/// }
225/// switch (lhs.value().typeIndex()) {
226/// case 0: // unset
227/// return true;
228/// case 1: // int
229/// return lhs.value().the<int>() < rhs.value().the<int>();
230/// case 2: // long
231/// return lhs.value().the<long>() < rhs.value().the<long>();
232/// case 3: // long long
233/// return lhs.value().the<long long>()
234/// < rhs.value().the<long long>();
235/// case 4: // unsigned int
236/// return lhs.value().the<unsigned int>()
237/// < rhs.value().the<unsigned int>();
238/// case 5: // unsigned long
239/// return lhs.value().the<unsigned long>()
240/// < rhs.value().the<unsigned long>();
241/// case 6: // unsigned long long
242/// return lhs.value().the<unsigned long long>()
243/// < rhs.value().the<unsigned long long>();
244/// case 7: // string
245/// return lhs.value().the<bsl::string>() <
246/// rhs.value().the<bsl::string>();
247/// case 8: // const void *
248/// return lhs.value().the<const void *>() <
249/// rhs.value().the<const void *>();
250/// case 9: // Guid
251/// return lhs.value().the<bdlb::Guid>() <
252/// rhs.value().the<bdlb::Guid>();
253/// }
254/// BSLS_ASSERT(false);
255/// return false;
256/// }
257/// };
258///
259/// // DATA
260/// bsl::set<ball::Attribute, AttributeComparator> d_set;
261///
262/// public:
263/// // CREATORS
264///
265/// /// Create an attribute set.
266/// AttributeSet(bslma::Allocator *basicAllocator = 0);
267///
268/// /// Destroy this attribute set.
269/// virtual ~AttributeSet();
270///
271/// // MANIPULATORS
272///
273/// /// Add the specified value to this attribute set.
274/// void insert(const ball::Attribute& value);
275///
276/// /// Remove the specified value from this attribute set. Return
277/// /// `true` if the attribute was found, and `false` if `value` was
278/// /// not a member of this set.
279/// bool remove(const ball::Attribute& value);
280///
281/// // ACCESSORS
282///
283/// /// Return `true` if the attribute having specified `value` exists
284/// /// in this object, and `false` otherwise.
285/// virtual bool hasValue(const ball::Attribute& value) const;
286///
287/// /// Format this object to the specified output `stream` at the
288/// /// (absolute value of) the optionally specified indentation `level`
289/// /// and return a reference to `stream`.
290/// virtual bsl::ostream& print(bsl::ostream& stream,
291/// int level = 0,
292/// int spacesPerLevel = 4) const;
293///
294/// /// Invoke the specified `visitor` function for all attributes in
295/// /// this container.
296/// virtual void visitAttributes(
297/// const bsl::function<void(const ball::Attribute&)>& visitor) const;
298/// };
299/// @endcode
300/// The `AttributeSet` methods are simple wrappers around `bsl::set` methods:
301/// @code
302/// inline
303/// AttributeSet::AttributeSet(bslma::Allocator *basicAllocator)
304/// : d_set(AttributeComparator(), basicAllocator)
305/// {
306/// }
307///
308/// // MANIPULATORS
309/// inline
310/// void AttributeSet::insert(const ball::Attribute& value)
311/// {
312/// d_set.insert(value);
313/// }
314///
315/// inline
316/// bool AttributeSet::remove(const ball::Attribute& value)
317/// {
318/// return d_set.erase(value) > 0;
319/// }
320///
321/// // attributeset.cpp
322///
323/// // CREATORS
324/// AttributeSet::~AttributeSet()
325/// {
326/// }
327///
328/// // ACCESSORS
329/// bool AttributeSet::hasValue(const ball::Attribute& value) const
330/// {
331/// return d_set.find(value) != d_set.end();
332/// }
333///
334/// bsl::ostream& AttributeSet::print(bsl::ostream& stream,
335/// int level,
336/// int spacesPerLevel) const
337/// {
338/// bslim::Printer printer(&stream, level, spacesPerLevel);
339/// printer.start();
340///
341/// bsl::set<ball::Attribute, AttributeComparator>::const_iterator it
342/// = d_set.begin();
343/// for (; it != d_set.end(); ++it) {
344/// printer.printValue(*it);
345/// }
346/// printer.end();
347///
348/// return stream;
349/// }
350///
351/// void AttributeSet::visitAttributes(
352/// const bsl::function<void(const ball::Attribute&)> &visitor) const
353/// {
354/// bsl::set<ball::Attribute, AttributeComparator>::const_iterator it
355/// = d_set.begin();
356/// for (; it != d_set.end(); ++it) {
357/// visitor(*it);
358/// }
359/// }
360/// @endcode
361///
362/// ### Example 3. Using a ball::AttributeContainer {#ball_attributecontainer-example-3-using-a-ball-attributecontainer}
363///
364///
365/// In this final example, we demonstrate how to call the methods of the
366/// `ball::AttributeContainer` protocol.
367///
368/// First we create an object of a concrete type that implements the
369/// `ball::AttributeContainer` protocol (e.g., `ServiceAttributes` defined in
370/// {Example 1}). Then we obtain a reference to this object.
371/// @code
372/// ServiceAttributes serviceAttributes(3938908, 1, 9001);
373/// const ball::AttributeContainer& attributes = serviceAttributes;
374/// @endcode
375/// We use `hasValue()` to examine the values in the container:
376/// @code
377/// assert(true == attributes.hasValue(ball::Attribute("uuid", 3938908)));
378/// assert(true == attributes.hasValue(ball::Attribute("luw", 1)));
379/// assert(true == attributes.hasValue(ball::Attribute("firmNumber", 9001)));
380///
381/// assert(false == attributes.hasValue(ball::Attribute("uuid", 1391015)));
382/// assert(false == attributes.hasValue(ball::Attribute("luw", 2)));
383/// assert(false == attributes.hasValue(ball::Attribute("bad name", 3938908)));
384/// @endcode
385/// Finally we can print the attribute values in the container:
386/// @code
387/// bsl::cout << attributes << bsl::endl;
388/// @endcode
389/// The resulting output should look like:
390/// @code
391/// [ [ uuid = 3938908 ] [ luw = 1 ] [ firmNumber = 9001 ] ]
392/// @endcode
393/// @}
394/** @} */
395/** @} */
396
397/** @addtogroup bal
398 * @{
399 */
400/** @addtogroup ball
401 * @{
402 */
403/** @addtogroup ball_attributecontainer
404 * @{
405 */
406
407#include <balscm_version.h>
408
409#include <bsl_functional.h>
410#include <bsl_iosfwd.h>
411
412
413namespace ball {
414
415class Attribute;
416
417 // ========================
418 // class AttributeContainer
419 // ========================
420
421/// This class defines a protocol for a container of attribute values. The
422/// attribute container provides a `hasValue()` method to determine whether
423/// an attribute value is in the container.
424///
425/// See @ref ball_attributecontainer
427
428 public:
429 // CREATORS
430
431 /// Destroy this object.
433
434 // ACCESSORS
435
436 /// Return `true` if a attribute having the specified `value` exists in
437 /// this object, and `false` otherwise.
438 virtual bool hasValue(const Attribute& value) const = 0;
439
440 /// Format this object to the specified output `stream` at the (absolute
441 /// value of) the optionally specified indentation `level` and return a
442 /// reference to `stream`. If `level` is specified, optionally specify
443 /// `spacesPerLevel`, the number of spaces per indentation level for
444 /// this and all of its nested objects. If `level` is negative,
445 /// suppress indentation of the first line. If `spacesPerLevel` is
446 /// negative, format the entire output on one line, suppressing all but
447 /// the initial indentation (as governed by `level`). If `stream` is
448 /// not valid on entry, this operation has no effect.
449 virtual bsl::ostream& print(bsl::ostream& stream,
450 int level = 0,
451 int spacesPerLevel = 4) const = 0;
452
453 /// Invoke the specified `visitor` function for all attributes in this
454 /// container.
455 virtual void visitAttributes(
456 const bsl::function<void(const ball::Attribute&)>& visitor) const = 0;
457};
458
459// FREE OPERATORS
460
461/// Write the value of the specified `container` to the specified output
462/// `stream` in a single-line format, and return a reference to the
463/// modifiable stream.
464bsl::ostream& operator<<(bsl::ostream& stream,
465 const AttributeContainer& container);
466
467// ============================================================================
468// INLINE DEFINITIONS
469// ============================================================================
470
471 // ------------------------
472 // class AttributeContainer
473 // ------------------------
474
475} // close package namespace
476
477// FREE OPERATORS
478inline
479bsl::ostream& ball::operator<<(bsl::ostream& stream,
480 const AttributeContainer& container)
481{
482 return container.print(stream, 0, -1);
483}
484
485
486
487#endif
488
489// ----------------------------------------------------------------------------
490// Copyright 2015 Bloomberg Finance L.P.
491//
492// Licensed under the Apache License, Version 2.0 (the "License");
493// you may not use this file except in compliance with the License.
494// You may obtain a copy of the License at
495//
496// http://www.apache.org/licenses/LICENSE-2.0
497//
498// Unless required by applicable law or agreed to in writing, software
499// distributed under the License is distributed on an "AS IS" BASIS,
500// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
501// See the License for the specific language governing permissions and
502// limitations under the License.
503// ----------------------------- END-OF-FILE ----------------------------------
504
505/** @} */
506/** @} */
507/** @} */
Definition ball_attributecontainer.h:426
virtual void visitAttributes(const bsl::function< void(const ball::Attribute &)> &visitor) const =0
virtual ~AttributeContainer()
Destroy this object.
virtual bool hasValue(const Attribute &value) const =0
virtual bsl::ostream & print(bsl::ostream &stream, int level=0, int spacesPerLevel=4) const =0
Definition ball_attribute.h:198
Forward declaration.
Definition bslstl_function.h:934
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition ball_administration.h:214
bsl::ostream & operator<<(bsl::ostream &output, const Attribute &attribute)