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 <vector>
21
22 #include <tools/solar.h>
23 #include <o3tl/sorted_vector.hxx>
24 #include <com/sun/star/ucb/XAnyCompareFactory.hpp>
25 #include <com/sun/star/container/XNamed.hpp>
26 #include <com/sun/star/container/XIndexReplace.hpp>
27 #include <rtl/ustrbuf.hxx>
28 #include <sal/log.hxx>
29 #include <xmloff/xmlnume.hxx>
30 #include <xmloff/XMLTextListAutoStylePool.hxx>
31 #include <xmloff/xmlexp.hxx>
32
33
34 using namespace ::com::sun::star;
35 using namespace ::com::sun::star::uno;
36 using namespace ::com::sun::star::beans;
37 using namespace ::com::sun::star::container;
38 using namespace ::com::sun::star::style;
39
40
41 class XMLTextListAutoStylePoolEntry_Impl
42 {
43 OUString sName;
44 OUString sInternalName;
45 Reference < XIndexReplace > xNumRules;
46 sal_uInt32 const nPos;
47 bool bIsNamed;
48
49
50 public:
51
52 XMLTextListAutoStylePoolEntry_Impl(
53 sal_uInt32 nPos,
54 const Reference < XIndexReplace > & rNumRules,
55 XMLTextListAutoStylePoolNames_Impl& rNames,
56 const OUString& rPrefix,
57 sal_uInt32& rName );
58
XMLTextListAutoStylePoolEntry_Impl(const Reference<XIndexReplace> & rNumRules)59 explicit XMLTextListAutoStylePoolEntry_Impl(
60 const Reference < XIndexReplace > & rNumRules ) :
61 xNumRules( rNumRules ),
62 nPos( 0 ),
63 bIsNamed( false )
64 {
65 Reference < XNamed > xNamed( xNumRules, UNO_QUERY );
66 if( xNamed.is() )
67 {
68 sInternalName = xNamed->getName();
69 bIsNamed = true;
70 }
71 }
72
XMLTextListAutoStylePoolEntry_Impl(const OUString & rInternalName)73 explicit XMLTextListAutoStylePoolEntry_Impl(
74 const OUString& rInternalName ) :
75 sInternalName( rInternalName ),
76 nPos( 0 ),
77 bIsNamed( true )
78 {
79 }
80
GetName() const81 const OUString& GetName() const { return sName; }
GetInternalName() const82 const OUString& GetInternalName() const { return sInternalName; }
GetNumRules() const83 const Reference < XIndexReplace > & GetNumRules() const { return xNumRules; }
GetPos() const84 sal_uInt32 GetPos() const { return nPos; }
IsNamed() const85 bool IsNamed() const { return bIsNamed; }
86 };
87
XMLTextListAutoStylePoolEntry_Impl(sal_uInt32 nP,const Reference<XIndexReplace> & rNumRules,XMLTextListAutoStylePoolNames_Impl & rNames,const OUString & rPrefix,sal_uInt32 & rName)88 XMLTextListAutoStylePoolEntry_Impl::XMLTextListAutoStylePoolEntry_Impl(
89 sal_uInt32 nP,
90 const Reference < XIndexReplace > & rNumRules,
91 XMLTextListAutoStylePoolNames_Impl& rNames,
92 const OUString& rPrefix,
93 sal_uInt32& rName ) :
94 xNumRules( rNumRules ),
95 nPos( nP ),
96 bIsNamed( false )
97 {
98 Reference < XNamed > xNamed( xNumRules, UNO_QUERY );
99 if( xNamed.is() )
100 {
101 sInternalName = xNamed->getName();
102 bIsNamed = true;
103 }
104
105 // create a name that hasn't been used before. The created name has not
106 // to be added to the array, because it will never tried again
107 OUStringBuffer sBuffer( 7 );
108 do
109 {
110 rName++;
111 sBuffer.append( rPrefix );
112 sBuffer.append( static_cast<sal_Int32>(rName) );
113 sName = sBuffer.makeStringAndClear();
114 }
115 while (rNames.find(sName) != rNames.end());
116 }
117
118 struct XMLTextListAutoStylePoolEntryCmp_Impl
119 {
operator ()XMLTextListAutoStylePoolEntryCmp_Impl120 bool operator()(
121 std::unique_ptr<XMLTextListAutoStylePoolEntry_Impl> const& r1,
122 std::unique_ptr<XMLTextListAutoStylePoolEntry_Impl> const& r2 ) const
123 {
124 if( r1->IsNamed() )
125 {
126 if( r2->IsNamed() )
127 return r1->GetInternalName().compareTo( r2->GetInternalName() ) < 0;
128 else
129 return true;
130 }
131 else
132 {
133 if( r2->IsNamed() )
134 return false;
135 else
136 return r1->GetNumRules().get() < r2->GetNumRules().get();
137 }
138 }
139 };
140 class XMLTextListAutoStylePool_Impl : public o3tl::sorted_vector<std::unique_ptr<XMLTextListAutoStylePoolEntry_Impl>, XMLTextListAutoStylePoolEntryCmp_Impl> {};
141
XMLTextListAutoStylePool(SvXMLExport & rExp)142 XMLTextListAutoStylePool::XMLTextListAutoStylePool( SvXMLExport& rExp ) :
143 rExport( rExp ),
144 sPrefix( "L" ),
145 pPool( new XMLTextListAutoStylePool_Impl ),
146 nName( 0 )
147 {
148 Reference<ucb::XAnyCompareFactory> xCompareFac( rExp.GetModel(), uno::UNO_QUERY );
149 if( xCompareFac.is() )
150 mxNumRuleCompare = xCompareFac->createAnyCompareByName( "NumberingRules" );
151 SvXMLExportFlags nExportFlags = rExport.getExportFlags();
152 bool bStylesOnly = (nExportFlags & SvXMLExportFlags::STYLES) && !(nExportFlags & SvXMLExportFlags::CONTENT);
153 if( bStylesOnly )
154 sPrefix = "ML";
155
156 }
157
~XMLTextListAutoStylePool()158 XMLTextListAutoStylePool::~XMLTextListAutoStylePool()
159 {
160 }
161
RegisterName(const OUString & rName)162 void XMLTextListAutoStylePool::RegisterName( const OUString& rName )
163 {
164 m_aNames.insert(rName);
165 }
166
Find(const XMLTextListAutoStylePoolEntry_Impl * pEntry) const167 sal_uInt32 XMLTextListAutoStylePool::Find( const XMLTextListAutoStylePoolEntry_Impl* pEntry ) const
168 {
169 if( !pEntry->IsNamed() && mxNumRuleCompare.is() )
170 {
171 const sal_uInt32 nCount = pPool->size();
172
173 uno::Any aAny1, aAny2;
174 aAny1 <<= pEntry->GetNumRules();
175
176 for( sal_uInt32 nPos = 0; nPos < nCount; nPos++ )
177 {
178 aAny2 <<= (*pPool)[nPos]->GetNumRules();
179
180 if( mxNumRuleCompare->compare( aAny1, aAny2 ) == 0 )
181 return nPos;
182 }
183 }
184 else
185 {
186 XMLTextListAutoStylePool_Impl::const_iterator it = pPool->find( pEntry );
187 if( it != pPool->end() )
188 return it - pPool->begin();
189 }
190
191 return sal_uInt32(-1);
192 }
193
Add(const Reference<XIndexReplace> & rNumRules)194 OUString XMLTextListAutoStylePool::Add(
195 const Reference < XIndexReplace > & rNumRules )
196 {
197 OUString sName;
198 XMLTextListAutoStylePoolEntry_Impl aTmp( rNumRules );
199
200 sal_uInt32 nPos = Find( &aTmp );
201 if( nPos != sal_uInt32(-1) )
202 {
203 sName = (*pPool)[ nPos ]->GetName();
204 }
205 else
206 {
207 std::unique_ptr<XMLTextListAutoStylePoolEntry_Impl> pEntry(
208 new XMLTextListAutoStylePoolEntry_Impl( pPool->size(),
209 rNumRules, m_aNames, sPrefix,
210 nName ));
211 sName = pEntry->GetName();
212 pPool->insert( std::move(pEntry) );
213 }
214
215 return sName;
216 }
217
Find(const Reference<XIndexReplace> & rNumRules) const218 OUString XMLTextListAutoStylePool::Find(
219 const Reference < XIndexReplace > & rNumRules ) const
220 {
221 OUString sName;
222 XMLTextListAutoStylePoolEntry_Impl aTmp( rNumRules );
223
224 sal_uInt32 nPos = Find( &aTmp );
225 if( nPos != sal_uInt32(-1) )
226 sName = (*pPool)[ nPos ]->GetName();
227
228 return sName;
229 }
230
Find(const OUString & rInternalName) const231 OUString XMLTextListAutoStylePool::Find(
232 const OUString& rInternalName ) const
233 {
234 OUString sName;
235 XMLTextListAutoStylePoolEntry_Impl aTmp( rInternalName );
236 sal_uInt32 nPos = Find( &aTmp );
237 if( nPos != sal_uInt32(-1) )
238 sName = (*pPool)[ nPos ]->GetName();
239
240 return sName;
241 }
242
exportXML() const243 void XMLTextListAutoStylePool::exportXML() const
244 {
245 sal_uInt32 nCount = pPool->size();
246 if( !nCount )
247 return;
248
249 std::vector<XMLTextListAutoStylePoolEntry_Impl*> aExpEntries(nCount);
250
251 sal_uInt32 i;
252 for( i=0; i < nCount; i++ )
253 {
254 XMLTextListAutoStylePoolEntry_Impl *pEntry = (*pPool)[i].get();
255 SAL_WARN_IF( pEntry->GetPos() >= nCount, "xmloff", "Illegal pos" );
256 aExpEntries[pEntry->GetPos()] = pEntry;
257 }
258
259 SvxXMLNumRuleExport aNumRuleExp( rExport );
260
261 for( i=0; i < nCount; i++ )
262 {
263 XMLTextListAutoStylePoolEntry_Impl *pEntry = aExpEntries[i];
264 aNumRuleExp.exportNumberingRule( pEntry->GetName(), false,
265 pEntry->GetNumRules() );
266 }
267 }
268
269
270 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
271