Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : : #include "xmlexternaltabi.hxx"
30 : : #include "xmlimprt.hxx"
31 : : #include "xmltabi.hxx"
32 : : #include "xmlstyli.hxx"
33 : :
34 : : #include "token.hxx"
35 : : #include "document.hxx"
36 : :
37 : : #include <xmloff/nmspmap.hxx>
38 : : #include <xmloff/xmlnmspe.hxx>
39 : : #include <xmloff/xmltoken.hxx>
40 : : #include <xmloff/xmluconv.hxx>
41 : :
42 : : #include <sax/tools/converter.hxx>
43 : :
44 : : #include <com/sun/star/util/NumberFormat.hpp>
45 : :
46 : : using namespace ::com::sun::star;
47 : :
48 : : using ::rtl::OUString;
49 : : using ::com::sun::star::uno::Reference;
50 : : using ::com::sun::star::xml::sax::XAttributeList;
51 : :
52 : : // ============================================================================
53 : :
54 : 0 : ScXMLExternalRefTabSourceContext::ScXMLExternalRefTabSourceContext(
55 : : ScXMLImport& rImport, sal_uInt16 nPrefix, const OUString& rLName,
56 : : const Reference<XAttributeList>& xAttrList, ScXMLExternalTabData& rRefInfo ) :
57 : : SvXMLImportContext( rImport, nPrefix, rLName ),
58 : : mrScImport(rImport),
59 : 0 : mrExternalRefInfo(rRefInfo)
60 : : {
61 : : using namespace ::xmloff::token;
62 : :
63 [ # # ][ # # ]: 0 : sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
[ # # ]
64 [ # # ]: 0 : for (sal_Int16 i = 0; i < nAttrCount; ++i)
65 : : {
66 [ # # ][ # # ]: 0 : const rtl::OUString& sAttrName = xAttrList->getNameByIndex(i);
67 : 0 : rtl::OUString aLocalName;
68 [ # # ]: 0 : sal_uInt16 nAttrPrefix = mrScImport.GetNamespaceMap().GetKeyByAttrName(sAttrName, &aLocalName);
69 [ # # ][ # # ]: 0 : const rtl::OUString& sValue = xAttrList->getValueByIndex(i);
70 [ # # ]: 0 : if (nAttrPrefix == XML_NAMESPACE_XLINK)
71 : : {
72 [ # # ][ # # ]: 0 : if (IsXMLToken(aLocalName, XML_HREF))
73 : 0 : maRelativeUrl = sValue;
74 : : }
75 [ # # ]: 0 : else if (nAttrPrefix == XML_NAMESPACE_TABLE)
76 : : {
77 [ # # ][ # # ]: 0 : if (IsXMLToken(aLocalName, XML_TABLE_NAME))
78 : 0 : maTableName = sValue;
79 [ # # ][ # # ]: 0 : else if (IsXMLToken(aLocalName, XML_FILTER_NAME))
80 : 0 : maFilterName = sValue;
81 [ # # ][ # # ]: 0 : else if (IsXMLToken(aLocalName, XML_FILTER_OPTIONS))
82 : 0 : maFilterOptions = sValue;
83 : : }
84 : 0 : }
85 : 0 : }
86 : :
87 : 0 : ScXMLExternalRefTabSourceContext::~ScXMLExternalRefTabSourceContext()
88 : : {
89 [ # # ]: 0 : }
90 : :
91 : 0 : SvXMLImportContext* ScXMLExternalRefTabSourceContext::CreateChildContext(
92 : : sal_uInt16 nPrefix, const OUString& rLocalName, const Reference<XAttributeList>& /*xAttrList*/ )
93 : : {
94 [ # # ]: 0 : return new SvXMLImportContext(GetImport(), nPrefix, rLocalName);
95 : : }
96 : :
97 : : /**
98 : : * Make sure the URL is a valid relative URL, mainly to avoid storing
99 : : * absolute URL as relative URL by accident. For now, we only check the first
100 : : * three characters which are assumed to be always '../', because the relative
101 : : * URL for an external document is always in reference to the content.xml
102 : : * fragment of the original document.
103 : : */
104 : 0 : static bool lcl_isValidRelativeURL(const OUString& rUrl)
105 : : {
106 [ # # ]: 0 : sal_Int32 n = ::std::min( rUrl.getLength(), static_cast<sal_Int32>(3));
107 [ # # ]: 0 : if (n < 3)
108 : 0 : return false;
109 : 0 : const sal_Unicode* p = rUrl.getStr();
110 [ # # ]: 0 : for (sal_Int32 i = 0; i < n; ++i)
111 : : {
112 : 0 : sal_Unicode c = p[i];
113 [ # # ][ # # ]: 0 : if (i < 2 && c != '.')
114 : : // the path must begin with '..'
115 : 0 : return false;
116 [ # # ][ # # ]: 0 : else if (i == 2 && c != '/')
117 : : // a '/' path separator must follow
118 : 0 : return false;
119 : : }
120 : 0 : return true;
121 : : }
122 : :
123 : 0 : void ScXMLExternalRefTabSourceContext::EndElement()
124 : : {
125 : 0 : ScDocument* pDoc = mrScImport.GetDocument();
126 [ # # ]: 0 : if (!pDoc)
127 : 0 : return;
128 : :
129 : 0 : ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager();
130 [ # # ]: 0 : if (lcl_isValidRelativeURL(maRelativeUrl))
131 : 0 : pRefMgr->setRelativeFileName(mrExternalRefInfo.mnFileId, maRelativeUrl);
132 : 0 : pRefMgr->setFilterData(mrExternalRefInfo.mnFileId, maFilterName, maFilterOptions);
133 : : }
134 : :
135 : : // ============================================================================
136 : :
137 : 0 : ScXMLExternalRefRowsContext::ScXMLExternalRefRowsContext(
138 : : ScXMLImport& rImport, sal_uInt16 nPrefix, const OUString& rLName,
139 : : const Reference<XAttributeList>& /* xAttrList */, ScXMLExternalTabData& rRefInfo ) :
140 : : SvXMLImportContext( rImport, nPrefix, rLName ),
141 : : mrScImport(rImport),
142 : 0 : mrExternalRefInfo(rRefInfo)
143 : : {
144 : 0 : }
145 : :
146 : 0 : ScXMLExternalRefRowsContext::~ScXMLExternalRefRowsContext()
147 : : {
148 [ # # ]: 0 : }
149 : :
150 : 0 : SvXMLImportContext* ScXMLExternalRefRowsContext::CreateChildContext(
151 : : sal_uInt16 nPrefix, const OUString& rLocalName, const Reference<XAttributeList>& xAttrList )
152 : : {
153 : : // #i101319# row elements inside group, rows or header-rows
154 : : // are treated like row elements directly in the table element
155 : :
156 : 0 : const SvXMLTokenMap& rTokenMap = mrScImport.GetTableRowsElemTokenMap();
157 : 0 : sal_uInt16 nToken = rTokenMap.Get(nPrefix, rLocalName);
158 [ # # # ]: 0 : switch (nToken)
159 : : {
160 : : case XML_TOK_TABLE_ROWS_ROW_GROUP:
161 : : case XML_TOK_TABLE_ROWS_HEADER_ROWS:
162 : : case XML_TOK_TABLE_ROWS_ROWS:
163 : : return new ScXMLExternalRefRowsContext(
164 [ # # ]: 0 : mrScImport, nPrefix, rLocalName, xAttrList, mrExternalRefInfo);
165 : : case XML_TOK_TABLE_ROWS_ROW:
166 : : return new ScXMLExternalRefRowContext(
167 [ # # ]: 0 : mrScImport, nPrefix, rLocalName, xAttrList, mrExternalRefInfo);
168 : : default:
169 : : ;
170 : : }
171 [ # # ]: 0 : return new SvXMLImportContext(GetImport(), nPrefix, rLocalName);
172 : : }
173 : :
174 : 0 : void ScXMLExternalRefRowsContext::EndElement()
175 : : {
176 : 0 : }
177 : :
178 : : // ============================================================================
179 : :
180 : 0 : ScXMLExternalRefRowContext::ScXMLExternalRefRowContext(
181 : : ScXMLImport& rImport, sal_uInt16 nPrefix, const OUString& rLName,
182 : : const Reference<XAttributeList>& xAttrList, ScXMLExternalTabData& rRefInfo ) :
183 : : SvXMLImportContext( rImport, nPrefix, rLName ),
184 : : mrScImport(rImport),
185 : : mrExternalRefInfo(rRefInfo),
186 : 0 : mnRepeatRowCount(1)
187 : : {
188 : 0 : mrExternalRefInfo.mnCol = 0;
189 : :
190 [ # # ][ # # ]: 0 : sal_Int16 nAttrCount(xAttrList.is() ? xAttrList->getLength() : 0);
[ # # ]
191 [ # # ]: 0 : const SvXMLTokenMap& rAttrTokenMap = mrScImport.GetTableRowAttrTokenMap();
192 [ # # ]: 0 : for( sal_Int16 i=0; i < nAttrCount; ++i )
193 : : {
194 [ # # ][ # # ]: 0 : const rtl::OUString& sAttrName = xAttrList->getNameByIndex(i);
195 : 0 : rtl::OUString aLocalName;
196 [ # # ]: 0 : sal_uInt16 nAttrPrefix = mrScImport.GetNamespaceMap().GetKeyByAttrName(sAttrName, &aLocalName);
197 [ # # ][ # # ]: 0 : const rtl::OUString& sValue = xAttrList->getValueByIndex(i);
198 : :
199 [ # # ][ # # ]: 0 : switch (rAttrTokenMap.Get(nAttrPrefix, aLocalName))
200 : : {
201 : : case XML_TOK_TABLE_ROW_ATTR_REPEATED:
202 : : {
203 [ # # ]: 0 : mnRepeatRowCount = std::max(sValue.toInt32(), static_cast<sal_Int32>(1));
204 : : }
205 : 0 : break;
206 : : }
207 : 0 : }
208 : 0 : }
209 : :
210 : 0 : ScXMLExternalRefRowContext::~ScXMLExternalRefRowContext()
211 : : {
212 [ # # ]: 0 : }
213 : :
214 : 0 : SvXMLImportContext* ScXMLExternalRefRowContext::CreateChildContext(
215 : : sal_uInt16 nPrefix, const OUString& rLocalName, const Reference<XAttributeList>& xAttrList )
216 : : {
217 : 0 : const SvXMLTokenMap& rTokenMap = mrScImport.GetTableRowElemTokenMap();
218 : 0 : sal_uInt16 nToken = rTokenMap.Get(nPrefix, rLocalName);
219 [ # # ][ # # ]: 0 : if (nToken == XML_TOK_TABLE_ROW_CELL || nToken == XML_TOK_TABLE_ROW_COVERED_CELL)
220 [ # # ]: 0 : return new ScXMLExternalRefCellContext(mrScImport, nPrefix, rLocalName, xAttrList, mrExternalRefInfo);
221 : :
222 [ # # ]: 0 : return new SvXMLImportContext(GetImport(), nPrefix, rLocalName);
223 : : }
224 : :
225 : 0 : void ScXMLExternalRefRowContext::EndElement()
226 : : {
227 [ # # ]: 0 : ScExternalRefCache::TableTypeRef pTab = mrExternalRefInfo.mpCacheTable;
228 : :
229 [ # # ]: 0 : for (sal_Int32 i = 1; i < mnRepeatRowCount; ++i)
230 : : {
231 : : // Performance: duplicates of a non-existent row will still not exist.
232 : : // Don't find that out for every cell.
233 : : // External references often are a sparse matrix.
234 [ # # ][ # # ]: 0 : if (i == 1 && !pTab->hasRow( mrExternalRefInfo.mnRow))
[ # # ][ # # ]
235 : : {
236 : 0 : mrExternalRefInfo.mnRow += mnRepeatRowCount;
237 : 0 : return;
238 : : }
239 : :
240 [ # # ]: 0 : for (sal_Int32 j = 0; j < mrExternalRefInfo.mnCol; ++j)
241 : : {
242 : : ScExternalRefCache::TokenRef pToken = pTab->getCell(
243 [ # # ]: 0 : static_cast<SCCOL>(j), static_cast<SCROW>(mrExternalRefInfo.mnRow));
244 : :
245 [ # # ]: 0 : if (pToken.get())
246 : : {
247 : : pTab->setCell(static_cast<SCCOL>(j),
248 [ # # ][ # # ]: 0 : static_cast<SCROW>(mrExternalRefInfo.mnRow+i), pToken);
249 : : }
250 [ # # ]: 0 : }
251 : : }
252 [ # # ][ # # ]: 0 : mrExternalRefInfo.mnRow += mnRepeatRowCount;
253 : : }
254 : :
255 : : // ============================================================================
256 : :
257 : 0 : ScXMLExternalRefCellContext::ScXMLExternalRefCellContext(
258 : : ScXMLImport& rImport, sal_uInt16 nPrefix, const OUString& rLName,
259 : : const Reference<XAttributeList>& xAttrList, ScXMLExternalTabData& rRefInfo ) :
260 : : SvXMLImportContext( rImport, nPrefix, rLName ),
261 : : mrScImport(rImport),
262 : : mrExternalRefInfo(rRefInfo),
263 : : mfCellValue(0.0),
264 : : mnRepeatCount(1),
265 : : mnNumberFormat(-1),
266 : : mnCellType(::com::sun::star::util::NumberFormat::UNDEFINED),
267 : : mbIsNumeric(false),
268 : 0 : mbIsEmpty(true)
269 : : {
270 : : using namespace ::xmloff::token;
271 : :
272 [ # # ][ # # ]: 0 : sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
[ # # ]
273 [ # # ]: 0 : const SvXMLTokenMap& rTokenMap = rImport.GetTableRowCellAttrTokenMap();
274 [ # # ]: 0 : for (sal_Int16 i = 0; i < nAttrCount; ++i)
275 : : {
276 : 0 : OUString aLocalName;
277 : 0 : sal_uInt16 nAttrPrefix = rImport.GetNamespaceMap().GetKeyByAttrName(
278 [ # # # # ]: 0 : xAttrList->getNameByIndex(i), &aLocalName);
[ # # ]
279 : :
280 [ # # ][ # # ]: 0 : const rtl::OUString& sValue = xAttrList->getValueByIndex(i);
281 [ # # ]: 0 : sal_uInt16 nToken = rTokenMap.Get(nAttrPrefix, aLocalName);
282 : :
283 [ # # # # : 0 : switch (nToken)
# # # #
# ]
284 : : {
285 : : case XML_TOK_TABLE_ROW_CELL_ATTR_STYLE_NAME:
286 : : {
287 [ # # ]: 0 : XMLTableStylesContext* pStyles = static_cast<XMLTableStylesContext*>(mrScImport.GetAutoStyles());
288 : : const XMLTableStyleContext* pStyle = static_cast<const XMLTableStyleContext*>(
289 [ # # ]: 0 : pStyles->FindStyleChildContext(XML_STYLE_FAMILY_TABLE_CELL, sValue, true));
290 [ # # ]: 0 : if (pStyle)
291 [ # # ]: 0 : mnNumberFormat = const_cast<XMLTableStyleContext*>(pStyle)->GetNumberFormat();
292 : : }
293 : 0 : break;
294 : : case XML_TOK_TABLE_ROW_CELL_ATTR_REPEATED:
295 : : {
296 [ # # ]: 0 : mnRepeatCount = ::std::max(sValue.toInt32(), static_cast<sal_Int32>(1));
297 : : }
298 : 0 : break;
299 : : case XML_TOK_TABLE_ROW_CELL_ATTR_VALUE_TYPE:
300 : : {
301 [ # # ]: 0 : mnCellType = mrScImport.GetCellType(sValue);
302 : : }
303 : 0 : break;
304 : : case XML_TOK_TABLE_ROW_CELL_ATTR_VALUE:
305 : : {
306 [ # # ]: 0 : if (!sValue.isEmpty())
307 : : {
308 [ # # ]: 0 : ::sax::Converter::convertDouble(mfCellValue, sValue);
309 : 0 : mbIsNumeric = true;
310 : 0 : mbIsEmpty = false;
311 : : }
312 : : }
313 : 0 : break;
314 : : case XML_TOK_TABLE_ROW_CELL_ATTR_DATE_VALUE:
315 : : {
316 [ # # ][ # # ]: 0 : if (!sValue.isEmpty() && mrScImport.SetNullDateOnUnitConverter())
[ # # ][ # # ]
317 : : {
318 [ # # ]: 0 : mrScImport.GetMM100UnitConverter().convertDateTime(mfCellValue, sValue);
319 : 0 : mbIsNumeric = true;
320 : 0 : mbIsEmpty = false;
321 : : }
322 : : }
323 : 0 : break;
324 : : case XML_TOK_TABLE_ROW_CELL_ATTR_TIME_VALUE:
325 : : {
326 [ # # ]: 0 : if (!sValue.isEmpty())
327 : : {
328 [ # # ]: 0 : ::sax::Converter::convertDuration(mfCellValue, sValue);
329 : 0 : mbIsNumeric = true;
330 : 0 : mbIsEmpty = false;
331 : : }
332 : : }
333 : 0 : break;
334 : : case XML_TOK_TABLE_ROW_CELL_ATTR_STRING_VALUE:
335 : : {
336 [ # # ]: 0 : if (!sValue.isEmpty())
337 : : {
338 : 0 : maCellString = sValue;
339 : 0 : mbIsNumeric = false;
340 : 0 : mbIsEmpty = false;
341 : : }
342 : : }
343 : 0 : break;
344 : : case XML_TOK_TABLE_ROW_CELL_ATTR_BOOLEAN_VALUE:
345 : : {
346 [ # # ]: 0 : if (!sValue.isEmpty())
347 : : {
348 [ # # ][ # # ]: 0 : mfCellValue = IsXMLToken(sValue, XML_TRUE) ? 1.0 : 0.0;
349 : 0 : mbIsNumeric = true;
350 : 0 : mbIsEmpty = false;
351 : : }
352 : : }
353 : 0 : break;
354 : : default:
355 : : ;
356 : : }
357 : 0 : }
358 : 0 : }
359 : :
360 : 0 : ScXMLExternalRefCellContext::~ScXMLExternalRefCellContext()
361 : : {
362 [ # # ]: 0 : }
363 : :
364 : 0 : SvXMLImportContext* ScXMLExternalRefCellContext::CreateChildContext(
365 : : sal_uInt16 nPrefix, const OUString& rLocalName, const Reference<XAttributeList>& xAttrList )
366 : : {
367 : 0 : const SvXMLTokenMap& rTokenMap = mrScImport.GetTableRowCellElemTokenMap();
368 : 0 : sal_uInt16 nToken = rTokenMap.Get(nPrefix, rLocalName);
369 [ # # ]: 0 : if (nToken == XML_TOK_TABLE_ROW_CELL_P)
370 [ # # ]: 0 : return new ScXMLExternalRefCellTextContext(mrScImport, nPrefix, rLocalName, xAttrList, *this);
371 : :
372 [ # # ]: 0 : return new SvXMLImportContext(GetImport(), nPrefix, rLocalName);
373 : : }
374 : :
375 : 0 : void ScXMLExternalRefCellContext::EndElement()
376 : : {
377 [ # # ]: 0 : if (!maCellString.isEmpty())
378 : 0 : mbIsEmpty = false;
379 : :
380 [ # # ]: 0 : for (sal_Int32 i = 0; i < mnRepeatCount; ++i, ++mrExternalRefInfo.mnCol)
381 : : {
382 [ # # ]: 0 : if (mbIsEmpty)
383 : 0 : continue;
384 : :
385 : 0 : ScExternalRefCache::TokenRef aToken;
386 [ # # ]: 0 : if (mbIsNumeric)
387 [ # # ][ # # ]: 0 : aToken.reset(new formula::FormulaDoubleToken(mfCellValue));
[ # # ]
388 : : else
389 [ # # ][ # # ]: 0 : aToken.reset(new formula::FormulaStringToken(maCellString));
[ # # ][ # # ]
[ # # ]
390 : :
391 : 0 : sal_uInt32 nNumFmt = mnNumberFormat >= 0 ? static_cast<sal_uInt32>(mnNumberFormat) : 0;
392 : : mrExternalRefInfo.mpCacheTable->setCell(
393 : : static_cast<SCCOL>(mrExternalRefInfo.mnCol),
394 : : static_cast<SCROW>(mrExternalRefInfo.mnRow),
395 [ # # ][ # # ]: 0 : aToken, nNumFmt);
396 [ # # ]: 0 : }
397 : 0 : }
398 : :
399 : 0 : void ScXMLExternalRefCellContext::SetCellString(const OUString& rStr)
400 : : {
401 : 0 : maCellString = rStr;
402 : 0 : }
403 : :
404 : : // ============================================================================
405 : :
406 : 0 : ScXMLExternalRefCellTextContext::ScXMLExternalRefCellTextContext(
407 : : ScXMLImport& rImport, sal_uInt16 nPrefix, const OUString& rLName,
408 : : const Reference<XAttributeList>& /*xAttrList*/,
409 : : ScXMLExternalRefCellContext& rParent ) :
410 : : SvXMLImportContext( rImport, nPrefix, rLName ),
411 : : mrScImport(rImport),
412 : 0 : mrParent(rParent)
413 : : {
414 : 0 : }
415 : :
416 : 0 : ScXMLExternalRefCellTextContext::~ScXMLExternalRefCellTextContext()
417 : : {
418 [ # # ]: 0 : }
419 : :
420 : 0 : SvXMLImportContext* ScXMLExternalRefCellTextContext::CreateChildContext(
421 : : sal_uInt16 nPrefix, const OUString& rLocalName, const Reference<XAttributeList>& /*xAttrList*/ )
422 : : {
423 [ # # ]: 0 : return new SvXMLImportContext(GetImport(), nPrefix, rLocalName);
424 : : }
425 : :
426 : 0 : void ScXMLExternalRefCellTextContext::Characters(const OUString& rChar)
427 : : {
428 : 0 : maCellStrBuf.append(rChar);
429 : 0 : }
430 : :
431 : 0 : void ScXMLExternalRefCellTextContext::EndElement()
432 : : {
433 : 0 : mrParent.SetCellString(maCellStrBuf.makeStringAndClear());
434 : 0 : }
435 : :
436 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|