3 /// Standalone templates related to the record classes.
4 /// Split into a separate file to speed compile times.
8 Copyright (C) 2005-2012, Net Direct Inc. (http://www.netdirect.ca/)
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19 See the GNU General Public License in the COPYING file at the
20 root directory of this project for more details.
23 #ifndef __BARRY_RECORD_TEMPLATES_H__
24 #define __BARRY_RECORD_TEMPLATES_H__
33 //////////////////////////////////////////////////////////////////////////////
34 // Generic Field Handles
36 /// \addtogroup GenericFieldHandles
39 //////////////////////////////////////////////////////////////////////////////
40 // *NamedFieldCmp classes
42 /// FieldSorter<> is a helper class for NamedFieldCmp<>, used as the
43 /// callback for FieldHandle<>::Member(). It uses operator< to store
44 /// a comparison result for the given record and field.
45 template <class RecordT
>
48 const RecordT
&m_one
, &m_two
;
49 mutable bool m_comparison
, m_equal
;
52 FieldSorter(const RecordT
&a
, const RecordT
&b
)
60 bool GetComparison() const { return m_comparison
; }
61 bool IsEqual() const { return m_equal
; }
63 void operator()(EnumFieldBase
<RecordT
> *ep
,
64 const FieldIdentity
&id
) const
66 m_comparison
= ep
->GetValue(m_one
) < ep
->GetValue(m_two
);
67 m_equal
= !m_comparison
&&
68 !(ep
->GetValue(m_two
) < ep
->GetValue(m_one
));
71 void operator()(typename FieldHandle
<RecordT
>::PostalPointer pp
,
72 const FieldIdentity
&id
) const
75 &a
= m_one
.*(pp
.m_PostalAddress
).*(pp
.m_PostalField
),
76 &b
= m_two
.*(pp
.m_PostalAddress
).*(pp
.m_PostalField
);
79 m_equal
= !m_comparison
&& !(b
< a
);
82 template <class TypeT
>
83 void operator()(TypeT
RecordT::* mp
, const FieldIdentity
&id
) const
85 m_comparison
= m_one
.*mp
< m_two
.*mp
;
86 m_equal
= !m_comparison
&& !(m_two
.*mp
< m_one
.*mp
);
93 /// A comparison functor, intended to be used in std::sort(), which
94 /// allows sorting by a particular record's member variable, selected
95 /// by string name. eg. It allows you to sort a vector of Contact
96 /// records by Name, HomeAddress, WorkPhone, or Company name, etc.
98 /// This template takes the record type as template argument, and works
99 /// with only that record type.
101 /// If the given name is not found the FieldHandles for RecordT, this
102 /// class will throw a std::logic_error exception.
104 template <class RecordT
>
107 const std::string
&m_name
;
110 NamedFieldCmp(const std::string
&field_name
)
115 bool operator() (const RecordT
&a
, const RecordT
&b
) const
117 bool comparison
= false;
119 std::istringstream
iss(m_name
);
120 while( std::getline(iss
, token
, ',') ) {
121 typename FieldHandle
<RecordT
>::ListT::const_iterator
122 fhi
= RecordT::GetFieldHandles().begin(),
123 fhe
= RecordT::GetFieldHandles().end();
125 for( ; fhi
!= fhe
; ++fhi
) {
126 if( token
== fhi
->GetIdentity().Name
) {
127 FieldSorter
<RecordT
> fs(a
, b
);
129 comparison
= fs
.GetComparison();
131 // if equal, compare next token
142 throw std::logic_error("NamedFieldCmp: No field named '" + token
+ "' in '" + RecordT::GetDBName() + "'");
145 // return last seen comparison
156 /// This class is a wrapper around the NamedFieldCmp<>, allowing you to
157 /// sort a vector (or other container) of DBData objects. This class will
158 /// parse each record before passing the result on to NamedFieldCmp<>
159 /// and returning the result. All the parsing work is then thrown away,
160 /// so this is more of a convenience class than for performance.
162 /// This class expects that all the DBData given to it is one of the
163 /// known records which have a parser. If the record unrecognized, it
164 /// will throw a std::logic_error exception.
166 class DBNamedFieldCmp
168 const std::string
&m_name
;
169 const IConverter
*m_ic
;
172 explicit DBNamedFieldCmp(const std::string
&field_name
,
173 const Barry::IConverter
*ic
= 0);
175 bool operator() (const Barry::DBData
&a
, const Barry::DBData
&b
) const;