xref: /trunk/main/xmloff/source/core/attrlist.cxx (revision ffd38472365e95f6a578737bc9a5eb0fac624a86)
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 {
43     SvXMLTagAttribute_Impl(){}
44     SvXMLTagAttribute_Impl( const OUString &rName,
45                          const OUString &rValue )
46         : sName(rName),
47         sValue(rValue)
48     {
49     }
50 
51     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 {
63     SvXMLAttributeList_Impl()
64     {
65         // performance improvement during adding
66         vecAttribute.reserve(20);
67     }
68 
69     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 
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 
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 
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 
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 
113 OUString SAL_CALL SvXMLAttributeList::getTypeByIndex(sal_Int16) throw( ::com::sun::star::uno::RuntimeException )
114 {
115     return sType;
116 }
117 
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 
123 OUString SAL_CALL SvXMLAttributeList::getTypeByName( const OUString& ) throw( ::com::sun::star::uno::RuntimeException )
124 {
125     return sType;
126 }
127 
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 
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 
148 SvXMLAttributeList::SvXMLAttributeList()
149     : sType( GetXMLToken(XML_CDATA) )
150 {
151     m_pImpl = new SvXMLAttributeList_Impl;
152 }
153 
154 
155 
156 SvXMLAttributeList::~SvXMLAttributeList()
157 {
158     delete m_pImpl;
159 }
160 
161 
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 
172 void SvXMLAttributeList::Clear()
173 {
174     m_pImpl->vecAttribute.clear();
175 
176     OSL_ASSERT( ! getLength() );
177 }
178 
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 
192 void SvXMLAttributeList::SetAttributeList( const uno::Reference< ::com::sun::star::xml::sax::XAttributeList >  &r )
193 {
194     Clear();
195     AppendAttributeList( r );
196 }
197 
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 
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 
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 
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 
249 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
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 
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
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