1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_xmloff.hxx"
26
27 #include <vector>
28 #include <osl/mutex.hxx>
29 #include <xmloff/xmltoken.hxx>
30 #include <rtl/uuid.h>
31 #include <rtl/memory.h>
32
33 #include <xmloff/attrlist.hxx>
34
35 using ::rtl::OUString;
36
37 using namespace ::osl;
38 using namespace ::com::sun::star;
39 using namespace ::xmloff::token;
40
41 struct SvXMLTagAttribute_Impl
42 {
SvXMLTagAttribute_ImplSvXMLTagAttribute_Impl43 SvXMLTagAttribute_Impl(){}
SvXMLTagAttribute_ImplSvXMLTagAttribute_Impl44 SvXMLTagAttribute_Impl( const OUString &rName,
45 const OUString &rValue )
46 : sName(rName),
47 sValue(rValue)
48 {
49 }
50
SvXMLTagAttribute_ImplSvXMLTagAttribute_Impl51 SvXMLTagAttribute_Impl( const SvXMLTagAttribute_Impl& r ) :
52 sName(r.sName),
53 sValue(r.sValue)
54 {
55 }
56
57 OUString sName;
58 OUString sValue;
59 };
60
61 struct SvXMLAttributeList_Impl
62 {
SvXMLAttributeList_ImplSvXMLAttributeList_Impl63 SvXMLAttributeList_Impl()
64 {
65 // performance improvement during adding
66 vecAttribute.reserve(20);
67 }
68
SvXMLAttributeList_ImplSvXMLAttributeList_Impl69 SvXMLAttributeList_Impl( const SvXMLAttributeList_Impl& r ) :
70 vecAttribute( r.vecAttribute )
71 {
72 }
73
74 ::std::vector<struct SvXMLTagAttribute_Impl> vecAttribute;
75 typedef ::std::vector<struct SvXMLTagAttribute_Impl>::size_type size_type;
76 };
77
78
79
getLength(void)80 sal_Int16 SAL_CALL SvXMLAttributeList::getLength(void) throw( ::com::sun::star::uno::RuntimeException )
81 {
82 return sal::static_int_cast< sal_Int16 >(m_pImpl->vecAttribute.size());
83 }
84
85
SvXMLAttributeList(const SvXMLAttributeList & r)86 SvXMLAttributeList::SvXMLAttributeList( const SvXMLAttributeList &r ) :
87 cppu::WeakImplHelper3<com::sun::star::xml::sax::XAttributeList, com::sun::star::util::XCloneable, com::sun::star::lang::XUnoTunnel>(r),
88 m_pImpl( new SvXMLAttributeList_Impl( *r.m_pImpl ) )
89 {
90 }
91
SvXMLAttributeList(const uno::Reference<xml::sax::XAttributeList> & rAttrList)92 SvXMLAttributeList::SvXMLAttributeList( const uno::Reference<
93 xml::sax::XAttributeList> & rAttrList )
94 : sType( GetXMLToken(XML_CDATA) )
95 {
96 m_pImpl = new SvXMLAttributeList_Impl;
97
98 SvXMLAttributeList* pImpl =
99 SvXMLAttributeList::getImplementation( rAttrList );
100
101 if( pImpl )
102 *m_pImpl = *(pImpl->m_pImpl);
103 else
104 AppendAttributeList( rAttrList );
105 }
106
getNameByIndex(sal_Int16 i)107 OUString SAL_CALL SvXMLAttributeList::getNameByIndex(sal_Int16 i) throw( ::com::sun::star::uno::RuntimeException )
108 {
109 return ( static_cast< SvXMLAttributeList_Impl::size_type >( i ) < m_pImpl->vecAttribute.size() ) ? m_pImpl->vecAttribute[i].sName : OUString();
110 }
111
112
getTypeByIndex(sal_Int16)113 OUString SAL_CALL SvXMLAttributeList::getTypeByIndex(sal_Int16) throw( ::com::sun::star::uno::RuntimeException )
114 {
115 return sType;
116 }
117
getValueByIndex(sal_Int16 i)118 OUString SAL_CALL SvXMLAttributeList::getValueByIndex(sal_Int16 i) throw( ::com::sun::star::uno::RuntimeException )
119 {
120 return ( static_cast< SvXMLAttributeList_Impl::size_type >( i ) < m_pImpl->vecAttribute.size() ) ? m_pImpl->vecAttribute[i].sValue : OUString();
121 }
122
getTypeByName(const OUString &)123 OUString SAL_CALL SvXMLAttributeList::getTypeByName( const OUString& ) throw( ::com::sun::star::uno::RuntimeException )
124 {
125 return sType;
126 }
127
getValueByName(const OUString & sName)128 OUString SAL_CALL SvXMLAttributeList::getValueByName(const OUString& sName) throw( ::com::sun::star::uno::RuntimeException )
129 {
130 ::std::vector<struct SvXMLTagAttribute_Impl>::iterator ii = m_pImpl->vecAttribute.begin();
131
132 for( ; ii != m_pImpl->vecAttribute.end() ; ++ii ) {
133 if( (*ii).sName == sName ) {
134 return (*ii).sValue;
135 }
136 }
137 return OUString();
138 }
139
140
createClone()141 uno::Reference< ::com::sun::star::util::XCloneable > SvXMLAttributeList::createClone() throw( ::com::sun::star::uno::RuntimeException )
142 {
143 uno::Reference< ::com::sun::star::util::XCloneable > r = new SvXMLAttributeList( *this );
144 return r;
145 }
146
147
SvXMLAttributeList()148 SvXMLAttributeList::SvXMLAttributeList()
149 : sType( GetXMLToken(XML_CDATA) )
150 {
151 m_pImpl = new SvXMLAttributeList_Impl;
152 }
153
154
155
~SvXMLAttributeList()156 SvXMLAttributeList::~SvXMLAttributeList()
157 {
158 delete m_pImpl;
159 }
160
161
AddAttribute(const OUString & sName,const OUString & sValue)162 void SvXMLAttributeList::AddAttribute( const OUString &sName ,
163 const OUString &sValue )
164 {
165 if (GetIndexByName(sName) == -1) {
166 m_pImpl->vecAttribute.push_back( SvXMLTagAttribute_Impl( sName , sValue ) );
167 } else {
168 throw com::sun::star::uno::RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM("attempt to insert duplicate XML tag attribute: ")) + sName, NULL);
169 }
170 }
171
Clear()172 void SvXMLAttributeList::Clear()
173 {
174 m_pImpl->vecAttribute.clear();
175
176 OSL_ASSERT( ! getLength() );
177 }
178
RemoveAttribute(const OUString sName)179 void SvXMLAttributeList::RemoveAttribute( const OUString sName )
180 {
181 ::std::vector<struct SvXMLTagAttribute_Impl>::iterator ii = m_pImpl->vecAttribute.begin();
182
183 for( ; ii != m_pImpl->vecAttribute.end() ; ++ii ) {
184 if( (*ii).sName == sName ) {
185 m_pImpl->vecAttribute.erase( ii );
186 break;
187 }
188 }
189 }
190
191
SetAttributeList(const uno::Reference<::com::sun::star::xml::sax::XAttributeList> & r)192 void SvXMLAttributeList::SetAttributeList( const uno::Reference< ::com::sun::star::xml::sax::XAttributeList > &r )
193 {
194 Clear();
195 AppendAttributeList( r );
196 }
197
AppendAttributeList(const uno::Reference<::com::sun::star::xml::sax::XAttributeList> & r)198 void SvXMLAttributeList::AppendAttributeList( const uno::Reference< ::com::sun::star::xml::sax::XAttributeList > &r )
199 {
200 OSL_ASSERT( r.is() );
201
202 sal_Int16 nMax = r->getLength();
203 SvXMLAttributeList_Impl::size_type nTotalSize =
204 m_pImpl->vecAttribute.size() + nMax;
205 m_pImpl->vecAttribute.reserve( nTotalSize );
206
207 OUString sName;
208 for( sal_Int16 i = 0 ; i < nMax ; ++i ) {
209 sName = r->getNameByIndex(i);
210 if (GetIndexByName(sName) == -1) {
211 m_pImpl->vecAttribute.push_back( SvXMLTagAttribute_Impl(
212 sName ,
213 r->getValueByIndex( i )));
214 } else {
215 throw com::sun::star::uno::RuntimeException(OUString(RTL_CONSTASCII_USTRINGPARAM("attempt to insert duplicate XML tag attribute: ")) + sName, NULL);
216 }
217 }
218
219 OSL_ASSERT( nTotalSize == (SvXMLAttributeList_Impl::size_type)getLength());
220 }
221
SetValueByIndex(sal_Int16 i,const::rtl::OUString & rValue)222 void SvXMLAttributeList::SetValueByIndex( sal_Int16 i,
223 const ::rtl::OUString& rValue )
224 {
225 if( static_cast< SvXMLAttributeList_Impl::size_type >( i )
226 < m_pImpl->vecAttribute.size() )
227 {
228 m_pImpl->vecAttribute[i].sValue = rValue;
229 }
230 }
231
RemoveAttributeByIndex(sal_Int16 i)232 void SvXMLAttributeList::RemoveAttributeByIndex( sal_Int16 i )
233 {
234 if( static_cast< SvXMLAttributeList_Impl::size_type >( i )
235 < m_pImpl->vecAttribute.size() )
236 m_pImpl->vecAttribute.erase( m_pImpl->vecAttribute.begin() + i );
237 }
238
RenameAttributeByIndex(sal_Int16 i,const OUString & rNewName)239 void SvXMLAttributeList::RenameAttributeByIndex( sal_Int16 i,
240 const OUString& rNewName )
241 {
242 if( static_cast< SvXMLAttributeList_Impl::size_type >( i )
243 < m_pImpl->vecAttribute.size() )
244 {
245 m_pImpl->vecAttribute[i].sName = rNewName;
246 }
247 }
248
GetIndexByName(const OUString & rName) const249 sal_Int16 SvXMLAttributeList::GetIndexByName( const OUString& rName ) const
250 {
251 ::std::vector<struct SvXMLTagAttribute_Impl>::iterator ii =
252 m_pImpl->vecAttribute.begin();
253
254 for( sal_Int16 nIndex=0; ii!=m_pImpl->vecAttribute.end(); ++ii, ++nIndex )
255 {
256 if( (*ii).sName == rName )
257 {
258 return nIndex;
259 }
260 }
261 return -1;
262 }
263
264 // XUnoTunnel & co
getUnoTunnelId()265 const uno::Sequence< sal_Int8 > & SvXMLAttributeList::getUnoTunnelId() throw()
266 {
267 static uno::Sequence< sal_Int8 > * pSeq = 0;
268 if( !pSeq )
269 {
270 Guard< Mutex > aGuard( Mutex::getGlobalMutex() );
271 if( !pSeq )
272 {
273 static uno::Sequence< sal_Int8 > aSeq( 16 );
274 rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True );
275 pSeq = &aSeq;
276 }
277 }
278 return *pSeq;
279 }
280
getImplementation(uno::Reference<uno::XInterface> xInt)281 SvXMLAttributeList* SvXMLAttributeList::getImplementation( uno::Reference< uno::XInterface > xInt ) throw()
282 {
283 uno::Reference< lang::XUnoTunnel > xUT( xInt, uno::UNO_QUERY );
284 if( xUT.is() )
285 {
286 return
287 reinterpret_cast<SvXMLAttributeList*>(
288 sal::static_int_cast<sal_IntPtr>(
289 xUT->getSomething( SvXMLAttributeList::getUnoTunnelId())));
290 }
291 else
292 return NULL;
293 }
294
295 // XUnoTunnel
getSomething(const uno::Sequence<sal_Int8> & rId)296 sal_Int64 SAL_CALL SvXMLAttributeList::getSomething( const uno::Sequence< sal_Int8 >& rId )
297 throw( uno::RuntimeException )
298 {
299 if( rId.getLength() == 16 && 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(),
300 rId.getConstArray(), 16 ) )
301 {
302 return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_uIntPtr>(this));
303 }
304 return 0;
305 }
306
307
308