LCOV - code coverage report
Current view: top level - sc/source/filter/xml - xmlexternaltabi.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 118 180 65.6 %
Date: 2014-04-11 Functions: 21 28 75.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10