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 375 : ScDPResultFilter::ScDPResultFilter(const OUString& rDimName, bool bDataLayout) :
22 375 : maDimName(rDimName), mbHasValue(false), mbDataLayout(bDataLayout) {}
23 :
24 84 : ScDPResultFilterContext::ScDPResultFilterContext() :
25 84 : mnCol(0), mnRow(0) {}
26 :
27 1736 : size_t ScDPResultTree::NamePairHash::operator() (const NamePairType& rPair) const
28 : {
29 : OUStringHash aHash;
30 1736 : return aHash(rPair.first) + aHash(rPair.second);
31 : }
32 :
33 364 : ScDPResultTree::DimensionNode::DimensionNode(const MemberNode* pParent) :
34 364 : mpParent(pParent) {}
35 :
36 728 : ScDPResultTree::DimensionNode::~DimensionNode()
37 : {
38 364 : MembersType::iterator it = maChildMembers.begin(), itEnd = maChildMembers.end();
39 1678 : for (; it != itEnd; ++it)
40 1314 : delete it->second;
41 364 : }
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 1514 : ScDPResultTree::MemberNode::MemberNode(const DimensionNode* pParent) :
64 1514 : mpParent(pParent) {}
65 :
66 3028 : ScDPResultTree::MemberNode::~MemberNode()
67 : {
68 1514 : DimensionsType::iterator it = maChildDimensions.begin(), itEnd = maChildDimensions.end();
69 1878 : for (; it != itEnd; ++it)
70 364 : delete it->second;
71 1514 : }
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 191 : ScDPResultTree::ScDPResultTree() : mpRoot(new MemberNode(NULL)) {}
91 382 : ScDPResultTree::~ScDPResultTree()
92 : {
93 191 : delete mpRoot;
94 191 : }
95 :
96 1331 : 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 1331 : const OUString* pDimName = NULL;
102 1331 : const OUString* pMemName = NULL;
103 1331 : MemberNode* pMemNode = mpRoot;
104 :
105 1331 : std::vector<ScDPResultFilter>::const_iterator itFilter = rFilters.begin(), itFilterEnd = rFilters.end();
106 3556 : for (; itFilter != itFilterEnd; ++itFilter)
107 : {
108 2225 : const ScDPResultFilter& filter = *itFilter;
109 2225 : if (filter.mbDataLayout)
110 22 : continue;
111 :
112 2203 : if (maPrimaryDimName.isEmpty())
113 67 : maPrimaryDimName = filter.maDimName;
114 :
115 : // See if this dimension exists.
116 2203 : DimensionsType& rDims = pMemNode->maChildDimensions;
117 2203 : OUString aUpperName = ScGlobal::pCharClass->uppercase(filter.maDimName);
118 2203 : DimensionsType::iterator itDim = rDims.find(aUpperName);
119 2203 : if (itDim == rDims.end())
120 : {
121 : // New dimenison. Insert it.
122 : std::pair<DimensionsType::iterator, bool> r =
123 364 : rDims.insert(DimensionsType::value_type(aUpperName, new DimensionNode(pMemNode)));
124 :
125 364 : if (!r.second)
126 : // Insertion failed!
127 0 : return;
128 :
129 364 : itDim = r.first;
130 : }
131 :
132 2203 : pDimName = &itDim->first;
133 :
134 : // Now, see if this dimension member exists.
135 2203 : DimensionNode* pDim = itDim->second;
136 2203 : MembersType& rMembers = pDim->maChildMembers;
137 2203 : aUpperName = ScGlobal::pCharClass->uppercase(filter.maValue);
138 2203 : MembersType::iterator itMem = rMembers.find(aUpperName);
139 2203 : if (itMem == rMembers.end())
140 : {
141 : // New member. Insert it.
142 : std::pair<MembersType::iterator, bool> r =
143 : rMembers.insert(
144 1314 : MembersType::value_type(aUpperName, new MemberNode(pDim)));
145 :
146 1314 : if (!r.second)
147 : // Insertion failed!
148 0 : return;
149 :
150 1314 : itMem = r.first;
151 : }
152 :
153 2203 : pMemName = &itMem->first;
154 2203 : pMemNode = itMem->second;
155 2203 : }
156 :
157 1331 : if (pDimName && pMemName)
158 : {
159 : NamePairType aNames(
160 : ScGlobal::pCharClass->uppercase(*pDimName),
161 1241 : ScGlobal::pCharClass->uppercase(*pMemName));
162 :
163 1241 : LeafValuesType::iterator it = maLeafValues.find(aNames);
164 1241 : if (it == maLeafValues.end())
165 : {
166 : // This name pair doesn't exist. Associate a new value for it.
167 475 : maLeafValues.insert(LeafValuesType::value_type(aNames, fVal));
168 : }
169 : else
170 : {
171 : // This name pair already exists. Set the value to NaN.
172 766 : rtl::math::setNan(&it->second);
173 1241 : }
174 : }
175 :
176 1331 : pMemNode->maValues.push_back(fVal);
177 : }
178 :
179 84 : void ScDPResultTree::swap(ScDPResultTree& rOther)
180 : {
181 84 : std::swap(maPrimaryDimName, rOther.maPrimaryDimName);
182 84 : std::swap(mpRoot, rOther.mpRoot);
183 84 : maLeafValues.swap(rOther.maLeafValues);
184 84 : }
185 :
186 31 : bool ScDPResultTree::empty() const
187 : {
188 31 : 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 31 : const ScDPResultTree::ValuesType* ScDPResultTree::getResults(
199 : const uno::Sequence<sheet::DataPilotFieldFilter>& rFilters) const
200 : {
201 31 : const sheet::DataPilotFieldFilter* p = rFilters.getConstArray();
202 31 : const sheet::DataPilotFieldFilter* pEnd = p + static_cast<size_t>(rFilters.getLength());
203 31 : const MemberNode* pMember = mpRoot;
204 78 : for (; p != pEnd; ++p)
205 : {
206 : DimensionsType::const_iterator itDim = pMember->maChildDimensions.find(
207 28 : ScGlobal::pCharClass->uppercase(p->FieldName));
208 :
209 28 : if (itDim == pMember->maChildDimensions.end())
210 : // Specified dimension not found.
211 40 : return NULL;
212 :
213 8 : const DimensionNode* pDim = itDim->second;
214 : MembersType::const_iterator itMem = pDim->maChildMembers.find(
215 8 : ScGlobal::pCharClass->uppercase(p->MatchValue));
216 :
217 8 : if (itMem == pDim->maChildMembers.end())
218 : // Specified member not found.
219 0 : return NULL;
220 :
221 8 : pMember = itMem->second;
222 : }
223 :
224 11 : return &pMember->maValues;
225 : }
226 :
227 20 : double ScDPResultTree::getLeafResult(const com::sun::star::sheet::DataPilotFieldFilter& rFilter) const
228 : {
229 : NamePairType aPair(
230 : ScGlobal::pCharClass->uppercase(rFilter.FieldName),
231 20 : ScGlobal::pCharClass->uppercase(rFilter.MatchValue));
232 :
233 20 : LeafValuesType::const_iterator it = maLeafValues.find(aPair);
234 20 : if (it != maLeafValues.end())
235 : // Found!
236 20 : return it->second;
237 :
238 : // Not found. Return an NaN.
239 : double fNan;
240 0 : rtl::math::setNan(&fNan);
241 0 : return fNan;
242 : }
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: */
|