summaryrefslogtreecommitdiff
path: root/xmloff/source/style/xmlexppr.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'xmloff/source/style/xmlexppr.cxx')
-rw-r--r--xmloff/source/style/xmlexppr.cxx1141
1 files changed, 1141 insertions, 0 deletions
diff --git a/xmloff/source/style/xmlexppr.cxx b/xmloff/source/style/xmlexppr.cxx
new file mode 100644
index 000000000000..48f383a9a376
--- /dev/null
+++ b/xmloff/source/style/xmlexppr.cxx
@@ -0,0 +1,1141 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_xmloff.hxx"
+#include <com/sun/star/container/XNameContainer.hpp>
+#include <com/sun/star/xml/AttributeData.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/beans/XPropertyState.hpp>
+#include <com/sun/star/lang/XTypeProvider.hpp>
+#include <com/sun/star/beans/XMultiPropertySet.hpp>
+#include <com/sun/star/beans/XTolerantMultiPropertySet.hpp>
+#include <com/sun/star/beans/TolerantPropertySetResultType.hpp>
+#include <rtl/ustrbuf.hxx>
+#include <list>
+#include <boost/unordered_map.hpp>
+
+#include <xmloff/xmlexppr.hxx>
+#include <xmloff/xmltoken.hxx>
+#include <xmloff/attrlist.hxx>
+#include <xmloff/nmspmap.hxx>
+#include "xmloff/xmlnmspe.hxx"
+#include <xmloff/xmlexp.hxx>
+#include <xmloff/xmlprmap.hxx>
+#include <xmloff/PropertySetInfoHash.hxx>
+#include <comphelper/stl_types.hxx>
+
+#ifndef _SVSTDARR_USHORTS
+#define _SVSTDARR_USHORTS
+#include <svl/svstdarr.hxx>
+#endif
+
+using ::rtl::OUString;
+using ::rtl::OUStringBuffer;
+
+using namespace ::std;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::beans;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+using namespace ::xmloff::token;
+
+#define GET_PROP_TYPE( f ) static_cast<sal_uInt16>((f & XML_TYPE_PROP_MASK) >> XML_TYPE_PROP_SHIFT)
+
+struct XMLPropTokens_Impl
+{
+ sal_uInt16 nType;
+ XMLTokenEnum eToken;
+};
+
+#define ENTRY(t) { GET_PROP_TYPE(XML_TYPE_PROP_##t), XML_##t##_PROPERTIES }
+const sal_uInt16 MAX_PROP_TYPES =
+ (XML_TYPE_PROP_END >> XML_TYPE_PROP_SHIFT) -
+ (XML_TYPE_PROP_START >> XML_TYPE_PROP_SHIFT);
+
+static XMLPropTokens_Impl aPropTokens[MAX_PROP_TYPES] =
+{
+ ENTRY(CHART),
+ ENTRY(GRAPHIC),
+ ENTRY(TABLE),
+ ENTRY(TABLE_COLUMN),
+ ENTRY(TABLE_ROW),
+ ENTRY(TABLE_CELL),
+ ENTRY(LIST_LEVEL),
+ ENTRY(PARAGRAPH),
+ ENTRY(TEXT),
+ ENTRY(DRAWING_PAGE),
+ ENTRY(PAGE_LAYOUT),
+ ENTRY(HEADER_FOOTER),
+ ENTRY(RUBY),
+ ENTRY(SECTION)
+};
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// public methods
+//
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Take all properties of the XPropertySet which are also found in the
+// XMLPropertyMapEntry-array and which are not set to their default-value,
+// if a state is available.
+//
+// After that I call the method 'ContextFilter'.
+//
+
+typedef std::list<XMLPropertyState> XMLPropertyStateList_Impl;
+
+class XMLPropertyStates_Impl
+{
+ XMLPropertyStateList_Impl aPropStates;
+ XMLPropertyStateList_Impl::iterator aLastItr;
+ sal_uInt32 nCount;
+public:
+ XMLPropertyStates_Impl();
+ void AddPropertyState(const XMLPropertyState& rPropState);
+ void FillPropertyStateVector(std::vector<XMLPropertyState>& rVector);
+};
+
+XMLPropertyStates_Impl::XMLPropertyStates_Impl() :
+ aPropStates(),
+ nCount(0)
+{
+ aLastItr = aPropStates.begin();
+}
+
+void XMLPropertyStates_Impl::AddPropertyState(
+ const XMLPropertyState& rPropState)
+{
+ XMLPropertyStateList_Impl::iterator aItr = aPropStates.begin();
+ sal_Bool bInserted(sal_False);
+ if (nCount)
+ {
+ if (aLastItr->mnIndex < rPropState.mnIndex)
+ aItr = ++aLastItr;
+ }
+ do
+ {
+ // TODO: one path required only
+ if (aItr == aPropStates.end())
+ {
+ aLastItr = aPropStates.insert(aPropStates.end(), rPropState);
+ bInserted = sal_True;
+ nCount++;
+ }
+ else if (aItr->mnIndex > rPropState.mnIndex)
+ {
+ aLastItr = aPropStates.insert(aItr, rPropState);
+ bInserted = sal_True;
+ nCount++;
+ }
+ }
+ while(!bInserted && (aItr++ != aPropStates.end()));
+}
+
+void XMLPropertyStates_Impl::FillPropertyStateVector(
+ std::vector<XMLPropertyState>& rVector)
+{
+ if (nCount)
+ {
+ rVector.resize(nCount, XMLPropertyState(-1));
+ ::std::copy( aPropStates.begin(), aPropStates.end(), rVector.begin() );
+ }
+}
+
+class FilterPropertyInfo_Impl
+{
+ const rtl::OUString sApiName;
+ std::list<sal_uInt32> aIndexes;
+ sal_uInt32 nCount;
+
+public:
+
+ FilterPropertyInfo_Impl( const rtl::OUString& rApiName,
+ const sal_uInt32 nIndex);
+
+ const OUString& GetApiName() const { return sApiName; }
+ std::list<sal_uInt32>& GetIndexes() { return aIndexes; }
+
+ void AddIndex( sal_uInt32 nIndex )
+ {
+ aIndexes.push_back(nIndex);
+ nCount++;
+ }
+
+ // for sort
+ sal_Bool operator< ( const FilterPropertyInfo_Impl& rArg ) const
+ {
+ return (GetApiName() < rArg.GetApiName());
+ }
+};
+
+FilterPropertyInfo_Impl::FilterPropertyInfo_Impl(
+ const rtl::OUString& rApiName,
+ const sal_uInt32 nIndex ) :
+ sApiName( rApiName ),
+ aIndexes(),
+ nCount(1)
+{
+ aIndexes.push_back(nIndex);
+}
+
+typedef std::list<FilterPropertyInfo_Impl> FilterPropertyInfoList_Impl;
+
+// ----------------------------------------------------------------------------
+
+class FilterPropertiesInfo_Impl
+{
+ sal_uInt32 nCount;
+ FilterPropertyInfoList_Impl aPropInfos;
+ FilterPropertyInfoList_Impl::iterator aLastItr;
+
+ Sequence <OUString> *pApiNames;
+
+public:
+ FilterPropertiesInfo_Impl();
+ ~FilterPropertiesInfo_Impl();
+
+ void AddProperty(const rtl::OUString& rApiName, const sal_uInt32 nIndex);
+ const uno::Sequence<OUString>& GetApiNames();
+ void FillPropertyStateArray(
+ vector< XMLPropertyState >& rPropStates,
+ const Reference< XPropertySet >& xPropSet,
+ const UniReference< XMLPropertySetMapper >& maPropMapper,
+ const sal_Bool bDefault = sal_False);
+ sal_uInt32 GetPropertyCount() const { return nCount; }
+};
+
+// ----------------------------------------------------------------------------
+
+typedef boost::unordered_map
+<
+ PropertySetInfoKey,
+ FilterPropertiesInfo_Impl *,
+ PropertySetInfoHash,
+ PropertySetInfoHash
+>
+FilterOropertiesHashMap_Impl;
+
+class FilterPropertiesInfos_Impl : public FilterOropertiesHashMap_Impl
+{
+public:
+ ~FilterPropertiesInfos_Impl ();
+};
+
+FilterPropertiesInfos_Impl::~FilterPropertiesInfos_Impl ()
+{
+ FilterOropertiesHashMap_Impl::iterator aIter = begin();
+ FilterOropertiesHashMap_Impl::iterator aEnd = end();
+ while( aIter != aEnd )
+ {
+ delete (*aIter).second;
+ (*aIter).second = 0;
+ ++aIter;
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+FilterPropertiesInfo_Impl::FilterPropertiesInfo_Impl() :
+ nCount(0),
+ aPropInfos(),
+ pApiNames( 0 )
+{
+ aLastItr = aPropInfos.begin();
+}
+
+FilterPropertiesInfo_Impl::~FilterPropertiesInfo_Impl()
+{
+ delete pApiNames;
+}
+
+void FilterPropertiesInfo_Impl::AddProperty(
+ const rtl::OUString& rApiName, const sal_uInt32 nIndex)
+{
+ aPropInfos.push_back(FilterPropertyInfo_Impl(rApiName, nIndex));
+ nCount++;
+
+ OSL_ENSURE( !pApiNames, "perfomance warning: API names already retrieved" );
+ if( pApiNames )
+ {
+ delete pApiNames;
+ pApiNames = NULL;
+ }
+}
+const uno::Sequence<OUString>& FilterPropertiesInfo_Impl::GetApiNames()
+{
+ OSL_ENSURE(nCount == aPropInfos.size(), "wrong property count");
+ if( !pApiNames )
+ {
+ // we have to do three things:
+ // 1) sort API names,
+ // 2) merge duplicates,
+ // 3) construct sequence
+
+ // sort names
+ aPropInfos.sort();
+
+ // merge duplicates
+ if ( nCount > 1 )
+ {
+ FilterPropertyInfoList_Impl::iterator aOld = aPropInfos.begin();
+ FilterPropertyInfoList_Impl::iterator aEnd = aPropInfos.end();
+ FilterPropertyInfoList_Impl::iterator aCurrent = aOld;
+ ++aCurrent;
+
+ while ( aCurrent != aEnd )
+ {
+ // equal to next element?
+ if ( aOld->GetApiName().equals( aCurrent->GetApiName() ) )
+ {
+ // if equal: merge index lists
+ aOld->GetIndexes().merge( aCurrent->GetIndexes() );
+ // erase element, and continue with next
+ aCurrent = aPropInfos.erase( aCurrent );
+ nCount--;
+ }
+ else
+ {
+ // remember old element and continue with next
+ aOld = aCurrent;
+ ++aCurrent;
+ }
+ }
+ }
+
+ // construct sequence
+ pApiNames = new Sequence < OUString >( nCount );
+ OUString *pNames = pApiNames->getArray();
+ FilterPropertyInfoList_Impl::iterator aItr = aPropInfos.begin();
+ FilterPropertyInfoList_Impl::iterator aEnd = aPropInfos.end();
+ for ( ; aItr != aEnd; ++aItr, ++pNames)
+ *pNames = aItr->GetApiName();
+ }
+
+ return *pApiNames;
+}
+
+void FilterPropertiesInfo_Impl::FillPropertyStateArray(
+ vector< XMLPropertyState >& rPropStates,
+ const Reference< XPropertySet >& rPropSet,
+ const UniReference< XMLPropertySetMapper >& rPropMapper,
+ const sal_Bool bDefault )
+{
+ XMLPropertyStates_Impl aPropStates;
+
+ const uno::Sequence<OUString>& rApiNames = GetApiNames();
+
+ Reference < XTolerantMultiPropertySet > xTolPropSet( rPropSet, UNO_QUERY );
+ if (xTolPropSet.is())
+ {
+ if (!bDefault)
+ {
+ Sequence < beans::GetDirectPropertyTolerantResult > aResults(xTolPropSet->getDirectPropertyValuesTolerant(rApiNames));
+ sal_Int32 nResultCount(aResults.getLength());
+ if (nResultCount > 0)
+ {
+ const beans::GetDirectPropertyTolerantResult *pResults = aResults.getConstArray();
+ FilterPropertyInfoList_Impl::iterator aPropIter(aPropInfos.begin());
+ XMLPropertyState aNewProperty( -1 );
+ sal_uInt32 i = 0;
+ while (nResultCount > 0 && i < nCount)
+ {
+ if (pResults->Name == aPropIter->GetApiName())
+ {
+ aNewProperty.mnIndex = -1;
+ aNewProperty.maValue = pResults->Value;
+
+ for( std::list<sal_uInt32>::iterator aIndexItr(aPropIter->GetIndexes().begin());
+ aIndexItr != aPropIter->GetIndexes().end();
+ ++aIndexItr )
+ {
+ aNewProperty.mnIndex = *aIndexItr;
+ aPropStates.AddPropertyState( aNewProperty );
+ }
+ ++pResults;
+ --nResultCount;
+ }
+ ++aPropIter;
+ ++i;
+ }
+ }
+ }
+ else
+ {
+ Sequence < beans::GetPropertyTolerantResult > aResults(xTolPropSet->getPropertyValuesTolerant(rApiNames));
+ OSL_ENSURE( rApiNames.getLength() == aResults.getLength(), "wrong implemented XTolerantMultiPropertySet" );
+ const beans::GetPropertyTolerantResult *pResults = aResults.getConstArray();
+ FilterPropertyInfoList_Impl::iterator aPropIter(aPropInfos.begin());
+ XMLPropertyState aNewProperty( -1 );
+ sal_uInt32 nResultCount(aResults.getLength());
+ OSL_ENSURE( nCount == nResultCount, "wrong implemented XTolerantMultiPropertySet??" );
+ for( sal_uInt32 i = 0; i < nResultCount; ++i )
+ {
+ if ((pResults->Result == beans::TolerantPropertySetResultType::SUCCESS) &&
+ ((pResults->State == PropertyState_DIRECT_VALUE) || (pResults->State == PropertyState_DEFAULT_VALUE)))
+ {
+ aNewProperty.mnIndex = -1;
+ aNewProperty.maValue = pResults->Value;
+
+ for( std::list<sal_uInt32>::iterator aIndexItr(aPropIter->GetIndexes().begin());
+ aIndexItr != aPropIter->GetIndexes().end();
+ ++aIndexItr )
+ {
+ aNewProperty.mnIndex = *aIndexItr;
+ aPropStates.AddPropertyState( aNewProperty );
+ }
+ }
+ ++pResults;
+ ++aPropIter;
+ }
+ }
+ }
+ else
+ {
+ Sequence < PropertyState > aStates;
+ const PropertyState *pStates = 0;
+ Reference< XPropertyState > xPropState( rPropSet, UNO_QUERY );
+ if( xPropState.is() )
+ {
+ aStates = xPropState->getPropertyStates( rApiNames );
+ pStates = aStates.getConstArray();
+ }
+
+ Reference < XMultiPropertySet > xMultiPropSet( rPropSet, UNO_QUERY );
+ if( xMultiPropSet.is() && !bDefault )
+ {
+ Sequence < Any > aValues;
+ if( pStates )
+ {
+ // step 1: get value count
+ sal_uInt32 nValueCount = 0;
+ sal_uInt32 i;
+
+ for( i = 0; i < nCount; ++i, ++pStates )
+ {
+ if( (*pStates == PropertyState_DIRECT_VALUE)/* || (bDefault && (*pStates == PropertyState_DEFAULT_VALUE))*/ )
+ nValueCount++;
+ }
+
+ if( nValueCount )
+ {
+ // step 2: collect property names
+ Sequence < OUString > aAPINames( nValueCount );
+ OUString *pAPINames = aAPINames.getArray();
+
+ ::std::vector< FilterPropertyInfoList_Impl::iterator > aPropIters;
+ aPropIters.reserve( nValueCount );
+
+ FilterPropertyInfoList_Impl::iterator aItr = aPropInfos.begin();
+ OSL_ENSURE(aItr != aPropInfos.end(),"Invalid iterator!");
+
+ pStates = aStates.getConstArray();
+ i = 0;
+ while( i < nValueCount )
+ {
+ if( (*pStates == PropertyState_DIRECT_VALUE)/* || (bDefault && (*pStates == PropertyState_DEFAULT_VALUE))*/ )
+ {
+ *pAPINames++ = aItr->GetApiName();
+ aPropIters.push_back( aItr );
+ ++i;
+ }
+ ++aItr;
+ ++pStates;
+ }
+
+ aValues = xMultiPropSet->getPropertyValues( aAPINames );
+ const Any *pValues = aValues.getConstArray();
+
+ ::std::vector< FilterPropertyInfoList_Impl::iterator >::const_iterator
+ pPropIter = aPropIters.begin();
+
+ XMLPropertyState aNewProperty( -1 );
+ for( i = 0; i < nValueCount; ++i )
+ {
+ aNewProperty.mnIndex = -1;
+ aNewProperty.maValue = *pValues;
+
+ const ::std::list< sal_uInt32 >& rIndexes( (*pPropIter)->GetIndexes() );
+ for ( std::list<sal_uInt32>::const_iterator aIndexItr = rIndexes.begin();
+ aIndexItr != rIndexes.end();
+ ++aIndexItr
+ )
+ {
+ aNewProperty.mnIndex = *aIndexItr;
+ aPropStates.AddPropertyState( aNewProperty );
+ }
+
+ ++pPropIter;
+ ++pValues;
+ }
+ }
+ }
+ else
+ {
+ aValues = xMultiPropSet->getPropertyValues( rApiNames );
+ const Any *pValues = aValues.getConstArray();
+
+ FilterPropertyInfoList_Impl::iterator aItr = aPropInfos.begin();
+ for(sal_uInt32 i = 0; i < nCount; ++i)
+ {
+ // The value is stored in the PropertySet itself, add to list.
+ XMLPropertyState aNewProperty( -1 );
+ aNewProperty.maValue = *pValues;
+ ++pValues;
+ for( std::list<sal_uInt32>::iterator aIndexItr =
+ aItr->GetIndexes().begin();
+ aIndexItr != aItr->GetIndexes().end();
+ ++aIndexItr )
+ {
+ aNewProperty.mnIndex = *aIndexItr;
+ aPropStates.AddPropertyState( aNewProperty );
+ }
+ ++aItr;
+ }
+ }
+ }
+ else
+ {
+ FilterPropertyInfoList_Impl::iterator aItr = aPropInfos.begin();
+ for(sal_uInt32 i = 0; i < nCount; ++i)
+ {
+ sal_Bool bDirectValue =
+ !pStates || *pStates == PropertyState_DIRECT_VALUE;
+ if( bDirectValue || bDefault )
+ {
+ // The value is stored in the PropertySet itself, add to list.
+ sal_Bool bGotValue = sal_False;
+ XMLPropertyState aNewProperty( -1 );
+ for( std::list<sal_uInt32>::const_iterator aIndexItr =
+ aItr->GetIndexes().begin();
+ aIndexItr != aItr->GetIndexes().end();
+ ++aIndexItr )
+ {
+ if( bDirectValue ||
+ (rPropMapper->GetEntryFlags( *aIndexItr ) &
+ MID_FLAG_DEFAULT_ITEM_EXPORT) != 0 )
+ {
+ try
+ {
+ if( !bGotValue )
+ {
+ aNewProperty.maValue =
+ rPropSet->getPropertyValue( aItr->GetApiName() );
+ bGotValue = sal_True;
+ }
+ aNewProperty.mnIndex = *aIndexItr;
+ aPropStates.AddPropertyState( aNewProperty );
+ }
+ catch( UnknownPropertyException& )
+ {
+ // might be a problem of getImplemenetationId
+ OSL_ENSURE( !this, "unknown property in getPropertyValue" );
+ }
+
+ }
+ }
+ }
+
+ ++aItr;
+ if( pStates )
+ ++pStates;
+ }
+ }
+ }
+ aPropStates.FillPropertyStateVector(rPropStates);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// ctor/dtor , class SvXMLExportPropertyMapper
+//
+
+SvXMLExportPropertyMapper::SvXMLExportPropertyMapper(
+ const UniReference< XMLPropertySetMapper >& rMapper ) :
+ pCache( 0 ),
+ maPropMapper( rMapper )
+{
+}
+
+SvXMLExportPropertyMapper::~SvXMLExportPropertyMapper()
+{
+ delete pCache;
+ mxNextMapper = 0;
+}
+
+void SvXMLExportPropertyMapper::ChainExportMapper(
+ const UniReference< SvXMLExportPropertyMapper>& rMapper )
+{
+ // add map entries from rMapper to current map
+ maPropMapper->AddMapperEntry( rMapper->getPropertySetMapper() );
+ // rMapper uses the same map as 'this'
+ rMapper->maPropMapper = maPropMapper;
+
+ // set rMapper as last mapper in current chain
+ UniReference< SvXMLExportPropertyMapper > xNext = mxNextMapper;
+ if( xNext.is())
+ {
+ while( xNext->mxNextMapper.is())
+ xNext = xNext->mxNextMapper;
+ xNext->mxNextMapper = rMapper;
+ }
+ else
+ mxNextMapper = rMapper;
+
+ // if rMapper was already chained, correct
+ // map pointer of successors
+ xNext = rMapper;
+
+ while( xNext->mxNextMapper.is())
+ {
+ xNext = xNext->mxNextMapper;
+ xNext->maPropMapper = maPropMapper;
+ }
+}
+
+
+vector< XMLPropertyState > SvXMLExportPropertyMapper::_Filter(
+ const Reference< XPropertySet > xPropSet,
+ const sal_Bool bDefault ) const
+{
+ vector< XMLPropertyState > aPropStateArray;
+
+ // Retrieve XPropertySetInfo and XPropertyState
+ Reference< XPropertySetInfo > xInfo( xPropSet->getPropertySetInfo() );
+ if( !xInfo.is() )
+ return aPropStateArray;
+
+ sal_Int32 nProps = maPropMapper->GetEntryCount();
+
+ FilterPropertiesInfo_Impl *pFilterInfo = 0;
+
+ Reference < XTypeProvider > xTypeProv( xPropSet, UNO_QUERY );
+ Sequence< sal_Int8 > aImplId;
+ if( xTypeProv.is() )
+ {
+ aImplId = xTypeProv->getImplementationId();
+ if( aImplId.getLength() == 16 )
+ {
+ if( pCache )
+ {
+ // The key must not be created outside this block, because it
+ // keeps a reference to the property set info.
+ PropertySetInfoKey aKey( xInfo, aImplId );
+ FilterPropertiesInfos_Impl::iterator aIter =
+ pCache->find( aKey );
+ if( aIter != pCache->end() )
+ pFilterInfo = (*aIter).second;
+ }
+ }
+ }
+
+ sal_Bool bDelInfo = sal_False;
+ if( !pFilterInfo )
+ {
+ pFilterInfo = new FilterPropertiesInfo_Impl;
+ for( sal_Int32 i=0; i < nProps; i++ )
+ {
+ // Are we allowed to ask for the property? (MID_FLAG_NO_PROP..)
+ // Does the PropertySet contain name of mpEntries-array ?
+ const OUString& rAPIName = maPropMapper->GetEntryAPIName( i );
+ const sal_Int32 nFlags = maPropMapper->GetEntryFlags( i );
+ if( (0 == (nFlags & MID_FLAG_NO_PROPERTY_EXPORT)) &&
+ ( (0 != (nFlags & MID_FLAG_MUST_EXIST)) ||
+ xInfo->hasPropertyByName( rAPIName ) ) )
+ {
+ const SvtSaveOptions::ODFDefaultVersion nCurrentVersion( SvtSaveOptions().GetODFDefaultVersion() );
+ const SvtSaveOptions::ODFDefaultVersion nEarliestODFVersionForExport(
+ maPropMapper->GetEarliestODFVersionForExport( i ) );
+ if( nCurrentVersion >= nEarliestODFVersionForExport
+ || nCurrentVersion == SvtSaveOptions::ODFVER_UNKNOWN
+ || nEarliestODFVersionForExport == SvtSaveOptions::ODFVER_UNKNOWN )
+ pFilterInfo->AddProperty(rAPIName, i);
+ }
+ }
+
+ if( xTypeProv.is() && aImplId.getLength() == 16 )
+ {
+ // Check whether the property set info is destroyed if it is
+ // assigned to a weak reference only. If it is destroyed, then
+ // every instance of getPropertySetInfo returns a new object.
+ // Such property set infos must not be cached.
+ WeakReference < XPropertySetInfo > xWeakInfo( xInfo );
+ xInfo = 0;
+ xInfo = xWeakInfo;
+ if( xInfo.is() )
+ {
+ if( !pCache )
+ ((SvXMLExportPropertyMapper *)this)->pCache =
+ new FilterPropertiesInfos_Impl;
+ PropertySetInfoKey aKey( xInfo, aImplId );
+ (*pCache)[aKey] = pFilterInfo;
+ }
+ else
+ bDelInfo = sal_True;
+ }
+ else
+ {
+ OSL_FAIL("here is no TypeProvider or the ImplId is wrong");
+ bDelInfo = sal_True;
+ }
+ }
+
+ if( pFilterInfo->GetPropertyCount() )
+ {
+ try
+ {
+ pFilterInfo->FillPropertyStateArray(aPropStateArray,
+ xPropSet, maPropMapper,
+ bDefault);
+ }
+ catch( UnknownPropertyException& )
+ {
+ // might be a problem of getImplemenetationId
+ OSL_ENSURE( !this, "unknown property in getPropertyStates" );
+ }
+ }
+
+ // Call centext-filter
+ if( !aPropStateArray.empty() )
+ ContextFilter( aPropStateArray, xPropSet );
+
+ // Have to do if we change from a vector to a list or something like that
+
+ if( bDelInfo )
+ delete pFilterInfo;
+
+ return aPropStateArray;
+}
+
+void SvXMLExportPropertyMapper::ContextFilter(
+ vector< XMLPropertyState >& rProperties,
+ Reference< XPropertySet > rPropSet ) const
+{
+ // Derived class could implement this.
+ if( mxNextMapper.is() )
+ mxNextMapper->ContextFilter( rProperties, rPropSet );
+}
+
+///////////////////////////////////////////////////////////////////////////
+//
+// Compares two Sequences of XMLPropertyState:
+// 1.Number of elements equal ?
+// 2.Index of each element equal ? (So I know whether the propertynames are the same)
+// 3.Value of each element equal ?
+//
+sal_Bool SvXMLExportPropertyMapper::Equals(
+ const vector< XMLPropertyState >& aProperties1,
+ const vector< XMLPropertyState >& aProperties2 ) const
+{
+ sal_Bool bRet = sal_True;
+ sal_uInt32 nCount = aProperties1.size();
+
+ if( nCount == aProperties2.size() )
+ {
+ sal_uInt32 nIndex = 0;
+ while( bRet && nIndex < nCount )
+ {
+ const XMLPropertyState& rProp1 = aProperties1[ nIndex ];
+ const XMLPropertyState& rProp2 = aProperties2[ nIndex ];
+
+ // Compare index. If equal, compare value
+ if( rProp1.mnIndex == rProp2.mnIndex )
+ {
+ if( rProp1.mnIndex != -1 )
+ {
+ // Now compare values
+ if( ( maPropMapper->GetEntryType( rProp1.mnIndex ) &
+ XML_TYPE_BUILDIN_CMP ) != 0 )
+ // simple type ( binary compare )
+ bRet = ( rProp1.maValue == rProp2.maValue );
+ else
+ // complex type ( ask for compare-function )
+ bRet = maPropMapper->GetPropertyHandler(
+ rProp1.mnIndex )->equals( rProp1.maValue,
+ rProp2.maValue );
+ }
+ }
+ else
+ bRet = sal_False;
+
+ nIndex++;
+ }
+ }
+ else
+ bRet = sal_False;
+
+ return bRet;
+}
+
+
+/** fills the given attribute list with the items in the given set
+void SvXMLExportPropertyMapper::exportXML( SvXMLAttributeList& rAttrList,
+ const ::std::vector< XMLPropertyState >& rProperties,
+ const SvXMLUnitConverter& rUnitConverter,
+ const SvXMLNamespaceMap& rNamespaceMap,
+ sal_uInt16 nFlags ) const
+{
+ _exportXML( rAttrList, rProperties, rUnitConverter, rNamespaceMap,
+ nFlags, 0, -1, -1 );
+}
+
+
+void SvXMLExportPropertyMapper::exportXML( SvXMLAttributeList& rAttrList,
+ const ::std::vector< XMLPropertyState >& rProperties,
+ const SvXMLUnitConverter& rUnitConverter,
+ const SvXMLNamespaceMap& rNamespaceMap,
+ sal_Int32 nPropMapStartIdx, sal_Int32 nPropMapEndIdx,
+ sal_uInt16 nFlags ) const
+{
+ _exportXML( rAttrList, rProperties, rUnitConverter, rNamespaceMap,
+ nFlags, 0, nPropMapStartIdx, nPropMapEndIdx );
+}
+*/
+
+
+void SvXMLExportPropertyMapper::exportXML( SvXMLAttributeList& rAttrList,
+ const XMLPropertyState& rProperty,
+ const SvXMLUnitConverter& rUnitConverter,
+ const SvXMLNamespaceMap& rNamespaceMap,
+ sal_uInt16 nFlags ) const
+{
+ if( ( maPropMapper->GetEntryFlags( rProperty.mnIndex ) &
+ MID_FLAG_ELEMENT_ITEM_EXPORT ) == 0 )
+ _exportXML( rAttrList, rProperty, rUnitConverter, rNamespaceMap,
+ nFlags );
+}
+
+void SvXMLExportPropertyMapper::exportXML(
+ SvXMLExport& rExport,
+ const ::std::vector< XMLPropertyState >& rProperties,
+ sal_uInt16 nFlags ) const
+{
+ exportXML( rExport, rProperties, -1, -1, nFlags );
+}
+
+void SvXMLExportPropertyMapper::exportXML(
+ SvXMLExport& rExport,
+ const ::std::vector< XMLPropertyState >& rProperties,
+ sal_Int32 nPropMapStartIdx, sal_Int32 nPropMapEndIdx,
+ sal_uInt16 nFlags ) const
+{
+ sal_uInt16 nPropTypeFlags = 0;
+ for( sal_uInt16 i=0; i<MAX_PROP_TYPES; ++i )
+ {
+ sal_uInt16 nPropType = aPropTokens[i].nType;
+ if( 0==i || (nPropTypeFlags & (1 << nPropType)) != 0 )
+ {
+ SvUShorts aIndexArray;
+
+ _exportXML( nPropType, nPropTypeFlags,
+ rExport.GetAttrList(), rProperties,
+ rExport.GetMM100UnitConverter(),
+ rExport.GetNamespaceMap(),
+ nFlags, &aIndexArray,
+ nPropMapStartIdx, nPropMapEndIdx );
+
+ if( rExport.GetAttrList().getLength() > 0L ||
+ (nFlags & XML_EXPORT_FLAG_EMPTY) != 0 ||
+ aIndexArray.Count() != 0 )
+ {
+ SvXMLElementExport aElem( rExport, XML_NAMESPACE_STYLE,
+ aPropTokens[i].eToken,
+ (nFlags & XML_EXPORT_FLAG_IGN_WS) != 0,
+ sal_False );
+
+ exportElementItems( rExport, rProperties, nFlags, aIndexArray );
+ }
+ }
+ }
+}
+
+/** this method is called for every item that has the
+ MID_FLAG_SPECIAL_ITEM_EXPORT flag set */
+void SvXMLExportPropertyMapper::handleSpecialItem(
+ SvXMLAttributeList& rAttrList,
+ const XMLPropertyState& rProperty,
+ const SvXMLUnitConverter& rUnitConverter,
+ const SvXMLNamespaceMap& rNamespaceMap,
+ const ::std::vector< XMLPropertyState > *pProperties,
+ sal_uInt32 nIdx ) const
+{
+ OSL_ENSURE( mxNextMapper.is(), "special item not handled in xml export" );
+ if( mxNextMapper.is() )
+ mxNextMapper->handleSpecialItem( rAttrList, rProperty, rUnitConverter,
+ rNamespaceMap, pProperties, nIdx );
+}
+
+/** this method is called for every item that has the
+ MID_FLAG_ELEMENT_EXPORT flag set */
+void SvXMLExportPropertyMapper::handleElementItem(
+ SvXMLExport& rExport,
+ const XMLPropertyState& rProperty,
+ sal_uInt16 nFlags,
+ const ::std::vector< XMLPropertyState > *pProperties,
+ sal_uInt32 nIdx ) const
+{
+ OSL_ENSURE( mxNextMapper.is(), "element item not handled in xml export" );
+ if( mxNextMapper.is() )
+ mxNextMapper->handleElementItem( rExport, rProperty, nFlags,
+ pProperties, nIdx );
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// protected methods
+//
+
+/** fills the given attribute list with the items in the given set */
+void SvXMLExportPropertyMapper::_exportXML(
+ sal_uInt16 nPropType, sal_uInt16& rPropTypeFlags,
+ SvXMLAttributeList& rAttrList,
+ const ::std::vector< XMLPropertyState >& rProperties,
+ const SvXMLUnitConverter& rUnitConverter,
+ const SvXMLNamespaceMap& rNamespaceMap,
+ sal_uInt16 nFlags,
+ SvUShorts* pIndexArray,
+ sal_Int32 nPropMapStartIdx, sal_Int32 nPropMapEndIdx ) const
+{
+ const sal_uInt32 nCount = rProperties.size();
+ sal_uInt32 nIndex = 0;
+
+ if( -1 == nPropMapStartIdx )
+ nPropMapStartIdx = 0;
+ if( -1 == nPropMapEndIdx )
+ nPropMapEndIdx = maPropMapper->GetEntryCount();
+
+ while( nIndex < nCount )
+ {
+ sal_Int32 nPropMapIdx = rProperties[nIndex].mnIndex;
+ if( nPropMapIdx >= nPropMapStartIdx &&
+ nPropMapIdx < nPropMapEndIdx )// valid entry?
+ {
+ sal_uInt32 nEFlags = maPropMapper->GetEntryFlags( nPropMapIdx );
+ sal_uInt16 nEPType = GET_PROP_TYPE(nEFlags);
+ OSL_ENSURE( nEPType >= (XML_TYPE_PROP_START>>XML_TYPE_PROP_SHIFT),
+ "no prop type sepcified" );
+ rPropTypeFlags |= (1 << nEPType);
+ if( nEPType == nPropType )
+ {
+ // we have a valid map entry here, so lets use it...
+ if( ( nEFlags & MID_FLAG_ELEMENT_ITEM_EXPORT ) != 0 )
+ {
+ // element items do not add any properties,
+ // we export it later
+ if( pIndexArray )
+ pIndexArray->Insert( (sal_uInt16)nIndex, pIndexArray->Count() );
+ }
+ else
+ {
+ _exportXML( rAttrList, rProperties[nIndex], rUnitConverter,
+ rNamespaceMap, nFlags, &rProperties, nIndex );
+ }
+ }
+ }
+
+ nIndex++;
+ }
+}
+
+void SvXMLExportPropertyMapper::_exportXML(
+ SvXMLAttributeList& rAttrList,
+ const XMLPropertyState& rProperty,
+ const SvXMLUnitConverter& rUnitConverter,
+ const SvXMLNamespaceMap& rNamespaceMap,
+ sal_uInt16 /*nFlags*/,
+ const ::std::vector< XMLPropertyState > *pProperties,
+ sal_uInt32 nIdx ) const
+{
+ OUString sCDATA( GetXMLToken(XML_CDATA) );
+
+ if ( ( maPropMapper->GetEntryFlags( rProperty.mnIndex ) &
+ MID_FLAG_SPECIAL_ITEM_EXPORT ) != 0 )
+ {
+ uno::Reference< container::XNameContainer > xAttrContainer;
+ if( (rProperty.maValue >>= xAttrContainer) && xAttrContainer.is() )
+ {
+ SvXMLNamespaceMap *pNewNamespaceMap = 0;
+ const SvXMLNamespaceMap *pNamespaceMap = &rNamespaceMap;
+
+ uno::Sequence< OUString > aAttribNames( xAttrContainer->getElementNames() );
+ const OUString* pAttribName = aAttribNames.getConstArray();
+
+ const sal_Int32 nCount = aAttribNames.getLength();
+
+ OUStringBuffer sNameBuffer;
+ xml::AttributeData aData;
+ for( sal_Int32 i=0; i < nCount; i++, pAttribName++ )
+ {
+ xAttrContainer->getByName( *pAttribName ) >>= aData;
+ OUString sAttribName( *pAttribName );
+
+ // extract namespace prefix from attribute name if it exists
+ OUString sPrefix;
+ const sal_Int32 nColonPos =
+ pAttribName->indexOf( sal_Unicode(':') );
+ if( nColonPos != -1 )
+ sPrefix = pAttribName->copy( 0, nColonPos );
+
+ if( sPrefix.getLength() )
+ {
+ OUString sNamespace( aData.Namespace );
+
+ // if the prefix isn't defined yet or has another meaning,
+ // we have to redefine it now.
+ sal_uInt16 nKey = pNamespaceMap->GetKeyByPrefix( sPrefix );
+ if( USHRT_MAX == nKey || pNamespaceMap->GetNameByKey( nKey ) != sNamespace )
+ {
+ sal_Bool bAddNamespace = sal_False;
+ if( USHRT_MAX == nKey )
+ {
+ // The prefix is unused, so it is sufficient
+ // to add it to the namespace map.
+ bAddNamespace = sal_True;
+ }
+ else
+ {
+ // check if there is a prefix registered for the
+ // namepsace URI
+ nKey = pNamespaceMap->GetKeyByName( sNamespace );
+ if( XML_NAMESPACE_UNKNOWN == nKey )
+ {
+ // There is no prefix for the namespace, so
+ // we have to generate one and have to add it.
+ sal_Int32 n=0;
+ OUString sOrigPrefix( sPrefix );
+ do
+ {
+ sNameBuffer.append( sOrigPrefix );
+ sNameBuffer.append( ++n );
+ sPrefix = sNameBuffer.makeStringAndClear();
+ nKey = pNamespaceMap->GetKeyByPrefix( sPrefix );
+ }
+ while( nKey != USHRT_MAX );
+
+ bAddNamespace = sal_True;
+ }
+ else
+ {
+ // If there is a prefix for the namespace,
+ // we reuse that.
+ sPrefix = pNamespaceMap->GetPrefixByKey( nKey );
+ }
+ // In any case, the attribute name has to be adapted.
+ sNameBuffer.append( sPrefix );
+ sNameBuffer.append( sal_Unicode(':') );
+ sNameBuffer.append( pAttribName->copy( nColonPos+1 ) );
+ sAttribName = sNameBuffer.makeStringAndClear();
+ }
+
+ if( bAddNamespace )
+ {
+ if( !pNewNamespaceMap )
+ {
+ pNewNamespaceMap = new SvXMLNamespaceMap( rNamespaceMap );
+ pNamespaceMap = pNewNamespaceMap;
+ }
+ pNewNamespaceMap->Add( sPrefix, sNamespace );
+ sNameBuffer.append( GetXMLToken(XML_XMLNS) );
+ sNameBuffer.append( sal_Unicode(':') );
+ sNameBuffer.append( sPrefix );
+ rAttrList.AddAttribute( sNameBuffer.makeStringAndClear(),
+ sNamespace );
+ }
+ }
+ }
+ OUString sOldValue( rAttrList.getValueByName( sAttribName ) );
+ OSL_ENSURE( sOldValue.getLength() == 0, "alien attribute exists already" );
+ OSL_ENSURE(aData.Type == GetXMLToken(XML_CDATA), "different type to our default type which should be written out");
+ if( !sOldValue.getLength() )
+ rAttrList.AddAttribute( sAttribName, aData.Value );
+ }
+
+ delete pNewNamespaceMap;
+ }
+ else
+ {
+ handleSpecialItem( rAttrList, rProperty, rUnitConverter,
+ rNamespaceMap, pProperties, nIdx );
+ }
+ }
+ else if ( ( maPropMapper->GetEntryFlags( rProperty.mnIndex ) &
+ MID_FLAG_ELEMENT_ITEM_EXPORT ) == 0 )
+ {
+ OUString aValue;
+ const OUString sName( rNamespaceMap.GetQNameByKey(
+ maPropMapper->GetEntryNameSpace( rProperty.mnIndex ),
+ maPropMapper->GetEntryXMLName( rProperty.mnIndex ) ) );
+
+ sal_Bool bRemove = sal_False;
+ if( ( maPropMapper->GetEntryFlags( rProperty.mnIndex ) &
+ MID_FLAG_MERGE_ATTRIBUTE ) != 0 )
+ {
+ aValue = rAttrList.getValueByName( sName );
+ bRemove = sal_True;
+ }
+
+ if( maPropMapper->exportXML( aValue, rProperty, rUnitConverter ) )
+ {
+ if( bRemove )
+ rAttrList.RemoveAttribute( sName );
+ rAttrList.AddAttribute( sName, aValue );
+ }
+ }
+}
+
+void SvXMLExportPropertyMapper::exportElementItems(
+ SvXMLExport& rExport,
+ const ::std::vector< XMLPropertyState >& rProperties,
+ sal_uInt16 nFlags,
+ const SvUShorts& rIndexArray ) const
+{
+ const sal_uInt16 nCount = rIndexArray.Count();
+
+ sal_Bool bItemsExported = sal_False;
+ OUString sWS( GetXMLToken(XML_WS) );
+ for( sal_uInt16 nIndex = 0; nIndex < nCount; nIndex++ )
+ {
+ const sal_uInt16 nElement = rIndexArray.GetObject( nIndex );
+
+ OSL_ENSURE( 0 != ( maPropMapper->GetEntryFlags(
+ rProperties[nElement].mnIndex ) & MID_FLAG_ELEMENT_ITEM_EXPORT),
+ "wrong mid flag!" );
+
+ rExport.IgnorableWhitespace();
+ handleElementItem( rExport, rProperties[nElement],
+ nFlags, &rProperties, nElement );
+ bItemsExported = sal_True;
+ }
+
+ if( bItemsExported )
+ rExport.IgnorableWhitespace();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */