1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_svx.hxx"
30 #include <svx/dataaccessdescriptor.hxx>
31 #include <comphelper/stl_types.hxx>
32 #include <comphelper/propertysetinfo.hxx>
33 #include <comphelper/genericpropertyset.hxx>
34 #include <osl/diagnose.h>
35 #include <com/sun/star/sdbc/XConnection.hpp>
36 #include <com/sun/star/ucb/XContent.hpp>
37 #include <com/sun/star/beans/PropertyAttribute.hpp>
38 #include <tools/urlobj.hxx>
39 
40 //........................................................................
41 namespace svx
42 {
43 //........................................................................
44 
45 	using namespace ::com::sun::star::uno;
46 	using namespace ::com::sun::star::sdbc;
47 	using namespace ::com::sun::star::beans;
48 	using namespace ::com::sun::star::ucb;
49 	using namespace ::comphelper;
50 
51 #define CONST_CHAR( propname ) propname, sizeof(propname) - 1
52 
53 #ifndef SVX_LIGHT
54 	//====================================================================
55 	//= ODADescriptorImpl
56 	//====================================================================
57 	class ODADescriptorImpl
58 	{
59 	protected:
60 		sal_Bool					m_bSetOutOfDate			: 1;
61 		sal_Bool					m_bSequenceOutOfDate	: 1;
62 
63 	public:
64         typedef ::std::map< DataAccessDescriptorProperty, Any >     DescriptorValues;
65 		DescriptorValues			m_aValues;
66 		Sequence< PropertyValue >	m_aAsSequence;
67 		Reference< XPropertySet >	m_xAsSet;
68 
69         typedef ::std::map< ::rtl::OUString, PropertyMapEntry* >    MapString2PropertyEntry;
70 
71 	public:
72 		ODADescriptorImpl();
73 		ODADescriptorImpl(const ODADescriptorImpl& _rSource);
74 
75 		void invalidateExternRepresentations();
76 
77 		void updateSequence();
78 		void updateSet();
79 
80 		/** builds the descriptor from a property value sequence
81 			@return <TRUE/>
82 				if and only if the sequence contained valid properties only
83 		*/
84 		sal_Bool buildFrom( const Sequence< PropertyValue >& _rValues );
85 
86 		/** builds the descriptor from a property set
87 			@return <TRUE/>
88 				if and only if the set contained valid properties only
89 		*/
90 		sal_Bool buildFrom( const Reference< XPropertySet >& _rValues );
91 
92 	protected:
93         static PropertyValue		            buildPropertyValue( const DescriptorValues::const_iterator& _rPos );
94 		static const MapString2PropertyEntry&   getPropertyMap( );
95         static PropertyMapEntry*                getPropertyMapEntry( const DescriptorValues::const_iterator& _rPos );
96 	};
97 
98 	//--------------------------------------------------------------------
99 	ODADescriptorImpl::ODADescriptorImpl()
100 		:m_bSetOutOfDate(sal_True)
101 		,m_bSequenceOutOfDate(sal_True)
102 	{
103 	}
104 
105 	//--------------------------------------------------------------------
106 	ODADescriptorImpl::ODADescriptorImpl(const ODADescriptorImpl& _rSource)
107         :m_bSetOutOfDate( _rSource.m_bSetOutOfDate )
108         ,m_bSequenceOutOfDate( _rSource.m_bSequenceOutOfDate )
109 		,m_aValues( _rSource.m_aValues )
110 	{
111 		if (!m_bSetOutOfDate)
112 			m_xAsSet = _rSource.m_xAsSet;
113 		if (!m_bSequenceOutOfDate)
114 			m_aAsSequence = _rSource.m_aAsSequence;
115 	}
116 
117 	//--------------------------------------------------------------------
118 	sal_Bool ODADescriptorImpl::buildFrom( const Sequence< PropertyValue >& _rValues )
119 	{
120         const MapString2PropertyEntry& rProperties = getPropertyMap();
121 
122 		sal_Bool bValidPropsOnly = sal_True;
123 
124 		// loop through the sequence, and fill our m_aValues
125 		const PropertyValue* pValues = _rValues.getConstArray();
126 		const PropertyValue* pValuesEnd = pValues + _rValues.getLength();
127 		for (;pValues != pValuesEnd; ++pValues)
128 		{
129             MapString2PropertyEntry::const_iterator aPropPos = rProperties.find( pValues->Name );
130             if ( aPropPos != rProperties.end() )
131 			{
132 				DataAccessDescriptorProperty eProperty = (DataAccessDescriptorProperty)aPropPos->second->mnHandle;
133 				m_aValues[eProperty] = pValues->Value;
134 			}
135 			else
136 				// unknown property
137 				bValidPropsOnly = sal_False;
138 		}
139 
140 		if (bValidPropsOnly)
141 		{
142 			m_aAsSequence = _rValues;
143 			m_bSequenceOutOfDate = sal_False;
144 		}
145 		else
146 			m_bSequenceOutOfDate = sal_True;
147 
148 		return bValidPropsOnly;
149 	}
150 
151 	//--------------------------------------------------------------------
152 	sal_Bool ODADescriptorImpl::buildFrom( const Reference< XPropertySet >& _rxValues )
153 	{
154 		Reference< XPropertySetInfo > xPropInfo;
155 		if (_rxValues.is())
156 			xPropInfo = _rxValues->getPropertySetInfo();
157 		if (!xPropInfo.is())
158 		{
159 			OSL_ENSURE(sal_False, "ODADescriptorImpl::buildFrom: invalid property set!");
160 			return sal_False;
161 		}
162 
163 		// build a PropertyValue sequence with the current values
164 		Sequence< Property > aProperties = xPropInfo->getProperties();
165 		const Property* pProperty = aProperties.getConstArray();
166 		const Property* pPropertyEnd = pProperty + aProperties.getLength();
167 
168 		Sequence< PropertyValue > aValues(aProperties.getLength());
169 		PropertyValue* pValues = aValues.getArray();
170 
171 		for (;pProperty != pPropertyEnd; ++pProperty, ++pValues)
172 		{
173 			pValues->Name = pProperty->Name;
174 			pValues->Value = _rxValues->getPropertyValue(pProperty->Name);
175 		}
176 
177 		sal_Bool bValidPropsOnly = buildFrom(aValues);
178 		if (bValidPropsOnly)
179 		{
180 			m_xAsSet = _rxValues;
181 			m_bSetOutOfDate = sal_False;
182 		}
183 		else
184 			m_bSetOutOfDate = sal_True;
185 
186 		return bValidPropsOnly;
187 	}
188 
189 	//--------------------------------------------------------------------
190 	void ODADescriptorImpl::invalidateExternRepresentations()
191 	{
192 		m_bSetOutOfDate = sal_True;
193 		m_bSequenceOutOfDate = sal_True;
194 	}
195 
196 	//--------------------------------------------------------------------
197 	const ODADescriptorImpl::MapString2PropertyEntry& ODADescriptorImpl::getPropertyMap( )
198 	{
199 		// the properties we know
200         static MapString2PropertyEntry s_aProperties;
201         if ( s_aProperties.empty() )
202         {
203 		    static PropertyMapEntry s_aDesriptorProperties[] =
204 		    {
205 			    { CONST_CHAR("ActiveConnection"),	daConnection,			&::getCppuType( static_cast< Reference< XConnection >* >(NULL) ),	PropertyAttribute::TRANSIENT, 0 },
206 			    { CONST_CHAR("BookmarkSelection"),	daBookmarkSelection,	&::getBooleanCppuType( ),											PropertyAttribute::TRANSIENT, 0 },
207 			    { CONST_CHAR("Column"),				daColumnObject,			&::getCppuType( static_cast< Reference< XPropertySet >* >(NULL) ),	PropertyAttribute::TRANSIENT, 0 },
208 			    { CONST_CHAR("ColumnName"),			daColumnName,			&::getCppuType( static_cast< ::rtl::OUString* >(NULL) ),			PropertyAttribute::TRANSIENT, 0 },
209 			    { CONST_CHAR("Command"),			daCommand,				&::getCppuType( static_cast< ::rtl::OUString* >(NULL) ),			PropertyAttribute::TRANSIENT, 0 },
210 			    { CONST_CHAR("CommandType"),		daCommandType,			&::getCppuType( static_cast< sal_Int32* >(NULL) ),					PropertyAttribute::TRANSIENT, 0 },
211 			    { CONST_CHAR("Component"),			daComponent,			&::getCppuType( static_cast< Reference< XContent >* >(NULL) ),		PropertyAttribute::TRANSIENT, 0 },
212 			    { CONST_CHAR("ConnectionResource"),	daConnectionResource,	&::getCppuType( static_cast< ::rtl::OUString* >(NULL) ),			PropertyAttribute::TRANSIENT, 0 },
213 			    { CONST_CHAR("Cursor"),				daCursor,				&::getCppuType( static_cast< Reference< XResultSet>* >(NULL) ),		PropertyAttribute::TRANSIENT, 0 },
214 			    { CONST_CHAR("DataSourceName"),		daDataSource,			&::getCppuType( static_cast< ::rtl::OUString* >(NULL) ),			PropertyAttribute::TRANSIENT, 0 },
215 			    { CONST_CHAR("DatabaseLocation"),	daDatabaseLocation,		&::getCppuType( static_cast< ::rtl::OUString* >(NULL) ),			PropertyAttribute::TRANSIENT, 0 },
216 			    { CONST_CHAR("EscapeProcessing"),	daEscapeProcessing,		&::getBooleanCppuType( ),											PropertyAttribute::TRANSIENT, 0 },
217 			    { CONST_CHAR("Filter"),				daFilter,				&::getCppuType( static_cast< ::rtl::OUString* >(NULL) ),			PropertyAttribute::TRANSIENT, 0 },
218 			    { CONST_CHAR("Selection"),			daSelection,			&::getCppuType( static_cast< Sequence< Any >* >(NULL) ),			PropertyAttribute::TRANSIENT, 0 },
219 			    { NULL, 0, 0, NULL, 0, 0 }
220 		    };
221 
222             PropertyMapEntry* pEntry = s_aDesriptorProperties;
223             while ( pEntry->mpName )
224             {
225                 s_aProperties[ ::rtl::OUString::createFromAscii( pEntry->mpName ) ] = pEntry;
226                 ++pEntry;
227             }
228         }
229 
230 		return s_aProperties;
231 	}
232 
233 	//--------------------------------------------------------------------
234 	PropertyMapEntry* ODADescriptorImpl::getPropertyMapEntry( const DescriptorValues::const_iterator& _rPos )
235 	{
236         const MapString2PropertyEntry& rProperties = getPropertyMap();
237 
238 		sal_Int32 nNeededHandle = (sal_Int32)(_rPos->first);
239 
240         for ( MapString2PropertyEntry::const_iterator loop = rProperties.begin();
241               loop != rProperties.end();
242               ++loop
243             )
244         {
245 			if ( nNeededHandle == loop->second->mnHandle )
246 				return loop->second;
247 		}
248         throw RuntimeException();
249 	}
250 
251 	//--------------------------------------------------------------------
252 	PropertyValue ODADescriptorImpl::buildPropertyValue( const DescriptorValues::const_iterator& _rPos )
253 	{
254 		// the map entry
255         PropertyMapEntry* pProperty = getPropertyMapEntry( _rPos );
256 
257 		// build the property value
258 		PropertyValue aReturn;
259         aReturn.Name	= ::rtl::OUString( pProperty->mpName, pProperty->mnNameLen, RTL_TEXTENCODING_ASCII_US );
260 		aReturn.Handle	= pProperty->mnHandle;
261 		aReturn.Value	= _rPos->second;
262 		aReturn.State	= PropertyState_DIRECT_VALUE;
263 
264 		// outta here
265 		return aReturn;
266 	}
267 
268 	//--------------------------------------------------------------------
269 	void ODADescriptorImpl::updateSequence()
270 	{
271 		if (!m_bSequenceOutOfDate)
272 			return;
273 
274 		m_aAsSequence.realloc(m_aValues.size());
275 		PropertyValue* pValue = m_aAsSequence.getArray();
276 
277 		// loop through all our values
278 		for	(	DescriptorValues::const_iterator aLoop = m_aValues.begin();
279 				aLoop != m_aValues.end();
280 				++aLoop, ++pValue
281 			)
282 		{
283 			*pValue = buildPropertyValue(aLoop);
284 		}
285 
286 		// don't need to rebuild next time
287 		m_bSequenceOutOfDate = sal_False;
288 	}
289 
290 	//--------------------------------------------------------------------
291 	void ODADescriptorImpl::updateSet()
292 	{
293 		if (!m_bSetOutOfDate)
294 			return;
295 
296 		// will be the current values
297 		Sequence< PropertyValue > aValuesToSet(m_aValues.size());
298 		PropertyValue* pValuesToSet = aValuesToSet.getArray();
299 
300 		// build a new property set info
301 		PropertySetInfo* pPropSetInfo = new PropertySetInfo;
302 
303 		// loop through all our values
304 		for	(	DescriptorValues::const_iterator aLoop = m_aValues.begin();
305 				aLoop != m_aValues.end();
306 				++aLoop, ++pValuesToSet
307 			)
308 		{
309 			PropertyMapEntry* pMapEntry = getPropertyMapEntry( aLoop );
310 			pPropSetInfo->add( pMapEntry, 1 );
311 
312 			*pValuesToSet = buildPropertyValue(aLoop);
313 		}
314 
315 		// create the generic set
316 		m_xAsSet = GenericPropertySet_CreateInstance( pPropSetInfo );
317 
318 		// no we have the set, still need to set the current values
319 		const PropertyValue* pSetValues = aValuesToSet.getConstArray();
320 		const PropertyValue* pSetValuesEnd = pSetValues + aValuesToSet.getLength();
321 		for	(; pSetValues != pSetValuesEnd; ++pSetValues)
322 			m_xAsSet->setPropertyValue(pSetValues->Name, pSetValues->Value);
323 
324 		// don't need to rebuild next time
325 		m_bSetOutOfDate = sal_True;
326 	}
327 #endif
328 
329 	//====================================================================
330 	//= ODataAccessDescriptor
331 	//====================================================================
332 	//--------------------------------------------------------------------
333 	ODataAccessDescriptor::ODataAccessDescriptor()
334 #ifndef SVX_LIGHT
335 		:m_pImpl(new ODADescriptorImpl)
336 #else
337 		:m_pImpl(NULL)
338 #endif
339 	{
340 	}
341 
342 	//--------------------------------------------------------------------
343 	ODataAccessDescriptor::ODataAccessDescriptor( const ODataAccessDescriptor& _rSource )
344 #ifndef SVX_LIGHT
345 		:m_pImpl(new ODADescriptorImpl(*_rSource.m_pImpl))
346 #else
347 		:m_pImpl(NULL)
348 #endif
349 	{
350 	}
351 
352 	//--------------------------------------------------------------------
353 	const ODataAccessDescriptor& ODataAccessDescriptor::operator=(const ODataAccessDescriptor& _rSource)
354 	{
355 #ifndef SVX_LIGHT
356 		delete m_pImpl;
357 		m_pImpl = new ODADescriptorImpl(*_rSource.m_pImpl);
358 #else
359 		OSL_ENSURE(sal_False, "ODataAccessDescriptor::operator=: not available in the SVX_LIGHT version!");
360 #endif
361 		return *this;
362 	}
363 
364 	//--------------------------------------------------------------------
365 	ODataAccessDescriptor::ODataAccessDescriptor( const Reference< XPropertySet >& _rValues )
366 #ifndef SVX_LIGHT
367 		:m_pImpl(new ODADescriptorImpl)
368 #else
369 		:m_pImpl(NULL)
370 #endif
371 	{
372 #ifndef SVX_LIGHT
373 		m_pImpl->buildFrom(_rValues);
374 #else
375 		OSL_ENSURE(sal_False, "ODataAccessDescriptor::ODataAccessDescriptor: not available in the SVX_LIGHT version!");
376 #endif
377 	}
378 
379 	//--------------------------------------------------------------------
380 	ODataAccessDescriptor::ODataAccessDescriptor( const Any& _rValues )
381 #ifndef SVX_LIGHT
382 		:m_pImpl(new ODADescriptorImpl)
383 #else
384 		:m_pImpl(NULL)
385 #endif
386 	{
387 #ifndef SVX_LIGHT
388 		// check if we know the format in the Any
389 		Sequence< PropertyValue > aValues;
390 		Reference< XPropertySet > xValues;
391 		if ( _rValues >>= aValues )
392 			m_pImpl->buildFrom( aValues );
393 		else if ( _rValues >>= xValues )
394 			m_pImpl->buildFrom( xValues );
395 #else
396 		OSL_ENSURE(sal_False, "ODataAccessDescriptor::ODataAccessDescriptor: not available in the SVX_LIGHT version!");
397 #endif
398 	}
399 
400 	//--------------------------------------------------------------------
401 	ODataAccessDescriptor::ODataAccessDescriptor( const Sequence< PropertyValue >& _rValues )
402 #ifndef SVX_LIGHT
403 		:m_pImpl(new ODADescriptorImpl)
404 #else
405 		:m_pImpl(NULL)
406 #endif
407 	{
408 #ifndef SVX_LIGHT
409 		m_pImpl->buildFrom(_rValues);
410 #else
411 		OSL_ENSURE(sal_False, "ODataAccessDescriptor::ODataAccessDescriptor: not available in the SVX_LIGHT version!");
412 #endif
413 	}
414 
415 	//--------------------------------------------------------------------
416 	ODataAccessDescriptor::~ODataAccessDescriptor()
417 	{
418 		delete m_pImpl;
419 	}
420 
421 	//--------------------------------------------------------------------
422 	void ODataAccessDescriptor::clear()
423 	{
424 #ifndef SVX_LIGHT
425 		m_pImpl->m_aValues.clear();
426 #endif
427 	}
428 
429 	//--------------------------------------------------------------------
430 	void ODataAccessDescriptor::erase(DataAccessDescriptorProperty _eWhich)
431 	{
432 #ifndef SVX_LIGHT
433 		OSL_ENSURE(has(_eWhich), "ODataAccessDescriptor::erase: invalid call!");
434 		if (has(_eWhich))
435 			m_pImpl->m_aValues.erase(_eWhich);
436 #endif
437 	}
438 
439 	//--------------------------------------------------------------------
440 	sal_Bool ODataAccessDescriptor::has(DataAccessDescriptorProperty _eWhich) const
441 	{
442 #ifndef SVX_LIGHT
443 		return m_pImpl->m_aValues.find(_eWhich) != m_pImpl->m_aValues.end();
444 #else
445 		return sal_False;
446 #endif
447 	}
448 
449 	//--------------------------------------------------------------------
450 	const Any& ODataAccessDescriptor::operator [] ( DataAccessDescriptorProperty _eWhich ) const
451 	{
452 #ifndef SVX_LIGHT
453 		if (!has(_eWhich))
454 		{
455 			OSL_ENSURE(sal_False, "ODataAccessDescriptor::operator[]: invalid acessor!");
456 			static const Any aDummy;
457 			return aDummy;
458 		}
459 
460 		return m_pImpl->m_aValues[_eWhich];
461 #else
462 		static const Any aDummy;
463 		return aDummy;
464 #endif
465 	}
466 
467 	//--------------------------------------------------------------------
468 	Any& ODataAccessDescriptor::operator[] ( DataAccessDescriptorProperty _eWhich )
469 	{
470 #ifndef SVX_LIGHT
471 		m_pImpl->invalidateExternRepresentations();
472 		return m_pImpl->m_aValues[_eWhich];
473 #else
474 		static const Any aDummy;
475 		return aDummy;
476 #endif
477 	}
478 
479 	//--------------------------------------------------------------------
480 	void ODataAccessDescriptor::initializeFrom(const Reference< XPropertySet >& _rxValues, sal_Bool _bClear)
481 	{
482 #ifndef SVX_LIGHT
483 		if (_bClear)
484 			clear();
485 		m_pImpl->buildFrom(_rxValues);
486 #endif
487 	}
488 
489 	//--------------------------------------------------------------------
490 	void ODataAccessDescriptor::initializeFrom(const Sequence< PropertyValue >& _rValues, sal_Bool _bClear)
491 	{
492 #ifndef SVX_LIGHT
493 		if (_bClear)
494 			clear();
495 		m_pImpl->buildFrom(_rValues);
496 #endif
497 	}
498 
499 	//--------------------------------------------------------------------
500 	Sequence< PropertyValue > ODataAccessDescriptor::createPropertyValueSequence()
501 	{
502 #ifndef SVX_LIGHT
503 		m_pImpl->updateSequence();
504 		return m_pImpl->m_aAsSequence;
505 #else
506 		return Sequence< PropertyValue >();
507 #endif
508 	}
509 	//--------------------------------------------------------------------
510 	Sequence< Any > ODataAccessDescriptor::createAnySequence()
511 	{
512 #ifndef SVX_LIGHT
513 		m_pImpl->updateSequence();
514 		Sequence< Any > aRet(m_pImpl->m_aAsSequence.getLength());
515 		const PropertyValue* pBegin = m_pImpl->m_aAsSequence.getConstArray();
516 		const PropertyValue* pEnd	  = pBegin + m_pImpl->m_aAsSequence.getLength();
517 		for(sal_Int32 i=0;pBegin != pEnd;++pBegin,++i)
518 			aRet[i] <<= *pBegin;
519 		return aRet;
520 #else
521 		return Sequence< createAnySequence >();
522 #endif
523 	}
524 
525 	//--------------------------------------------------------------------
526 	Reference< XPropertySet > ODataAccessDescriptor::createPropertySet()
527 	{
528 #ifndef SVX_LIGHT
529 		m_pImpl->updateSet();
530 		return m_pImpl->m_xAsSet;
531 #else
532 		return Reference< XPropertySet >();
533 #endif
534 	}
535 	//--------------------------------------------------------------------
536 	::rtl::OUString ODataAccessDescriptor::getDataSource() const
537 	{
538 #ifndef SVX_LIGHT
539 		::rtl::OUString	sDataSourceName;
540 		if ( has(daDataSource) )
541 			(*this)[daDataSource] >>= sDataSourceName;
542 		else if ( has(daDatabaseLocation) )
543 			(*this)[daDatabaseLocation] >>= sDataSourceName;
544 		return sDataSourceName;
545 #else
546 		return ::rtl::OUString();
547 #endif
548 	}
549 	//--------------------------------------------------------------------
550 	void ODataAccessDescriptor::setDataSource(const ::rtl::OUString& _sDataSourceNameOrLocation)
551 	{
552 #ifndef SVX_LIGHT
553 		if ( _sDataSourceNameOrLocation.getLength() )
554 		{
555 			INetURLObject aURL(_sDataSourceNameOrLocation);
556 			(*this)[ (( aURL.GetProtocol() == INET_PROT_FILE ) ? daDatabaseLocation : daDataSource)] <<= _sDataSourceNameOrLocation;
557 		}
558 		else
559 			(*this)[ daDataSource ] <<= ::rtl::OUString();
560 #endif
561 	}
562 
563 //........................................................................
564 }	// namespace svx
565 //........................................................................
566 
567 
568