| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the 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 <hash_map> |
| |
| #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 std::hash_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_ENSURE(sal_False, "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 |
| /*vector< XMLPropertyState >::iterator aItr = aPropStateArray.begin(); |
| while (aItr != aPropStateArray.end()) |
| { |
| if (aItr->mnIndex == -1) |
| aItr = aPropStateArray.erase(aItr); |
| else |
| aItr++; |
| }*/ |
| |
| 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; //aValue.getLength() != 0; |
| } |
| |
| 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(); |
| } |