Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : */
9 :
10 : #include "dpresfilter.hxx"
11 : #include "global.hxx"
12 :
13 : #include <unotools/charclass.hxx>
14 : #include <rtl/math.hxx>
15 :
16 : #include <com/sun/star/sheet/DataPilotFieldFilter.hpp>
17 :
18 : using namespace com::sun::star;
19 : using namespace std;
20 :
21 420 : ScDPResultFilter::ScDPResultFilter(const OUString& rDimName, bool bDataLayout) :
22 420 : maDimName(rDimName), mbHasValue(false), mbDataLayout(bDataLayout) {}
23 :
24 91 : ScDPResultFilterContext::ScDPResultFilterContext() :
25 91 : mnCol(0), mnRow(0) {}
26 :
27 1857 : size_t ScDPResultTree::NamePairHash::operator() (const NamePairType& rPair) const
28 : {
29 : OUStringHash aHash;
30 1857 : return aHash(rPair.first) + aHash(rPair.second);
31 : }
32 :
33 393 : ScDPResultTree::DimensionNode::DimensionNode(const MemberNode* pParent) :
34 393 : mpParent(pParent) {}
35 :
36 766 : ScDPResultTree::DimensionNode::~DimensionNode()
37 : {
38 383 : MembersType::iterator it = maChildMembers.begin(), itEnd = maChildMembers.end();
39 1743 : for (; it != itEnd; ++it)
40 1360 : delete it->second;
41 383 : }
42 :
43 : #if DEBUG_PIVOT_TABLE
44 : void ScDPResultTree::DimensionNode::dump(int nLevel) const
45 : {
46 : string aIndent(nLevel*2, ' ');
47 : MembersType::const_iterator it = maChildMembers.begin(), itEnd = maChildMembers.end();
48 : for (; it != itEnd; ++it)
49 : {
50 : cout << aIndent << "member: ";
51 : const ScDPItemData& rVal = it->first;
52 : if (rVal.IsValue())
53 : cout << rVal.GetValue();
54 : else
55 : cout << rVal.GetString();
56 : cout << endl;
57 :
58 : it->second->dump(nLevel+1);
59 : }
60 : }
61 : #endif
62 :
63 1609 : ScDPResultTree::MemberNode::MemberNode(const DimensionNode* pParent) :
64 1609 : mpParent(pParent) {}
65 :
66 3160 : ScDPResultTree::MemberNode::~MemberNode()
67 : {
68 1580 : DimensionsType::iterator it = maChildDimensions.begin(), itEnd = maChildDimensions.end();
69 1963 : for (; it != itEnd; ++it)
70 383 : delete it->second;
71 1580 : }
72 :
73 : #if DEBUG_PIVOT_TABLE
74 : void ScDPResultTree::MemberNode::dump(int nLevel) const
75 : {
76 : string aIndent(nLevel*2, ' ');
77 : ValuesType::const_iterator itVal = maValues.begin(), itValEnd = maValues.end();
78 : for (; itVal != itValEnd; ++itVal)
79 : cout << aIndent << "value: " << *itVal << endl;
80 :
81 : DimensionsType::const_iterator it = maChildDimensions.begin(), itEnd = maChildDimensions.end();
82 : for (; it != itEnd; ++it)
83 : {
84 : cout << aIndent << "dimension: " << it->first << endl;
85 : it->second->dump(nLevel+1);
86 : }
87 : }
88 : #endif
89 :
90 213 : ScDPResultTree::ScDPResultTree() : mpRoot(new MemberNode(NULL)) {}
91 422 : ScDPResultTree::~ScDPResultTree()
92 : {
93 211 : delete mpRoot;
94 211 : }
95 :
96 1416 : void ScDPResultTree::add(
97 : const std::vector<ScDPResultFilter>& rFilters, long /*nCol*/, long /*nRow*/, double fVal)
98 : {
99 : // TODO: I'll work on the col / row to value node mapping later.
100 :
101 1416 : const OUString* pDimName = NULL;
102 1416 : const OUString* pMemName = NULL;
103 1416 : MemberNode* pMemNode = mpRoot;
104 :
105 1416 : std::vector<ScDPResultFilter>::const_iterator itFilter = rFilters.begin(), itFilterEnd = rFilters.end();
106 3790 : for (; itFilter != itFilterEnd; ++itFilter)
107 : {
108 2374 : const ScDPResultFilter& filter = *itFilter;
109 2374 : if (filter.mbDataLayout)
110 54 : continue;
111 :
112 2320 : if (maPrimaryDimName.isEmpty())
113 74 : maPrimaryDimName = filter.maDimName;
114 :
115 : // See if this dimension exists.
116 2320 : DimensionsType& rDims = pMemNode->maChildDimensions;
117 2320 : OUString aUpperName = ScGlobal::pCharClass->uppercase(filter.maDimName);
118 2320 : DimensionsType::iterator itDim = rDims.find(aUpperName);
119 2320 : if (itDim == rDims.end())
120 : {
121 : // New dimenison. Insert it.
122 : std::pair<DimensionsType::iterator, bool> r =
123 393 : rDims.insert(DimensionsType::value_type(aUpperName, new DimensionNode(pMemNode)));
124 :
125 393 : if (!r.second)
126 : // Insertion failed!
127 0 : return;
128 :
129 393 : itDim = r.first;
130 : }
131 :
132 2320 : pDimName = &itDim->first;
133 :
134 : // Now, see if this dimension member exists.
135 2320 : DimensionNode* pDim = itDim->second;
136 2320 : MembersType& rMembers = pDim->maChildMembers;
137 2320 : aUpperName = ScGlobal::pCharClass->uppercase(filter.maValue);
138 2320 : MembersType::iterator itMem = rMembers.find(aUpperName);
139 2320 : if (itMem == rMembers.end())
140 : {
141 : // New member. Insert it.
142 : std::pair<MembersType::iterator, bool> r =
143 : rMembers.insert(
144 1387 : MembersType::value_type(aUpperName, new MemberNode(pDim)));
145 :
146 1387 : if (!r.second)
147 : // Insertion failed!
148 0 : return;
149 :
150 1387 : itMem = r.first;
151 : }
152 :
153 2320 : pMemName = &itMem->first;
154 2320 : pMemNode = itMem->second;
155 2320 : }
156 :
157 1416 : if (pDimName && pMemName)
158 : {
159 : NamePairType aNames(
160 : ScGlobal::pCharClass->uppercase(*pDimName),
161 1317 : ScGlobal::pCharClass->uppercase(*pMemName));
162 :
163 1317 : LeafValuesType::iterator it = maLeafValues.find(aNames);
164 1317 : if (it == maLeafValues.end())
165 : {
166 : // This name pair doesn't exist. Associate a new value for it.
167 516 : maLeafValues.insert(LeafValuesType::value_type(aNames, fVal));
168 : }
169 : else
170 : {
171 : // This name pair already exists. Set the value to NaN.
172 801 : rtl::math::setNan(&it->second);
173 1317 : }
174 : }
175 :
176 1416 : pMemNode->maValues.push_back(fVal);
177 : }
178 :
179 91 : void ScDPResultTree::swap(ScDPResultTree& rOther)
180 : {
181 91 : std::swap(maPrimaryDimName, rOther.maPrimaryDimName);
182 91 : std::swap(mpRoot, rOther.mpRoot);
183 91 : maLeafValues.swap(rOther.maLeafValues);
184 91 : }
185 :
186 43 : bool ScDPResultTree::empty() const
187 : {
188 43 : return mpRoot->maChildDimensions.empty();
189 : }
190 :
191 9 : void ScDPResultTree::clear()
192 : {
193 9 : maPrimaryDimName = EMPTY_OUSTRING;
194 9 : delete mpRoot;
195 9 : mpRoot = new MemberNode(NULL);
196 9 : }
197 :
198 43 : const ScDPResultTree::ValuesType* ScDPResultTree::getResults(
199 : const uno::Sequence<sheet::DataPilotFieldFilter>& rFilters) const
200 : {
201 43 : const sheet::DataPilotFieldFilter* p = rFilters.getConstArray();
202 43 : const sheet::DataPilotFieldFilter* pEnd = p + static_cast<size_t>(rFilters.getLength());
203 43 : const MemberNode* pMember = mpRoot;
204 128 : for (; p != pEnd; ++p)
205 : {
206 : DimensionsType::const_iterator itDim = pMember->maChildDimensions.find(
207 45 : ScGlobal::pCharClass->uppercase(p->FieldName));
208 :
209 45 : if (itDim == pMember->maChildDimensions.end())
210 : // Specified dimension not found.
211 48 : return NULL;
212 :
213 21 : const DimensionNode* pDim = itDim->second;
214 : MembersType::const_iterator itMem = pDim->maChildMembers.find(
215 21 : ScGlobal::pCharClass->uppercase(p->MatchValue));
216 :
217 21 : if (itMem == pDim->maChildMembers.end())
218 : // Specified member not found.
219 0 : return NULL;
220 :
221 21 : pMember = itMem->second;
222 : }
223 :
224 19 : return &pMember->maValues;
225 : }
226 :
227 24 : double ScDPResultTree::getLeafResult(const com::sun::star::sheet::DataPilotFieldFilter& rFilter) const
228 : {
229 : NamePairType aPair(
230 : ScGlobal::pCharClass->uppercase(rFilter.FieldName),
231 24 : ScGlobal::pCharClass->uppercase(rFilter.MatchValue));
232 :
233 24 : LeafValuesType::const_iterator it = maLeafValues.find(aPair);
234 24 : if (it != maLeafValues.end())
235 : // Found!
236 24 : return it->second;
237 :
238 : // Not found. Return an NaN.
239 : double fNan;
240 0 : rtl::math::setNan(&fNan);
241 0 : return fNan;
242 156 : }
243 :
244 : #if DEBUG_PIVOT_TABLE
245 : void ScDPResultTree::dump() const
246 : {
247 : cout << "primary dimension name: " << maPrimaryDimName << endl;
248 : mpRoot->dump(0);
249 : }
250 : #endif
251 :
252 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|