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_dbaccess.hxx"
30 
31 #ifndef DBA_COREDATAACESS_COMPONENTDEFINITION_HXX
32 #include "ComponentDefinition.hxx"
33 #endif
34 #ifndef _DBASHARED_APITOOLS_HXX_
35 #include "apitools.hxx"
36 #endif
37 #ifndef DBACCESS_SHARED_DBASTRINGS_HRC
38 #include "dbastrings.hrc"
39 #endif
40 #include "module_dba.hxx"
41 
42 #ifndef _TOOLS_DEBUG_HXX
43 #include <tools/debug.hxx>
44 #endif
45 #ifndef _COMPHELPER_SEQUENCE_HXX_
46 #include <comphelper/sequence.hxx>
47 #endif
48 #ifndef _COM_SUN_STAR_LANG_DISPOSEDEXCEPTION_HPP_
49 #include <com/sun/star/lang/DisposedException.hpp>
50 #endif
51 #ifndef _COM_SUN_STAR_BEANS_PROPERTYATTRIBUTE_HPP_
52 #include <com/sun/star/beans/PropertyAttribute.hpp>
53 #endif
54 #ifndef _COMPHELPER_PROPERTY_HXX_
55 #include <comphelper/property.hxx>
56 #endif
57 #ifndef _DBACORE_DEFINITIONCOLUMN_HXX_
58 #include "definitioncolumn.hxx"
59 #endif
60 #include <cppuhelper/implbase1.hxx>
61 #include <comphelper/componentcontext.hxx>
62 
63 using namespace ::com::sun::star::uno;
64 using namespace ::com::sun::star::sdbc;
65 using namespace ::com::sun::star::lang;
66 
67 using namespace ::com::sun::star::beans;
68 using namespace ::com::sun::star::container;
69 using namespace ::osl;
70 using namespace ::comphelper;
71 using namespace ::cppu;
72 
73 extern "C" void SAL_CALL createRegistryInfo_OComponentDefinition()
74 {
75 	static ::dba::OAutoRegistration< ::dbaccess::OComponentDefinition > aAutoRegistration;
76 }
77 
78 //........................................................................
79 namespace dbaccess
80 {
81 //........................................................................
82 /// helper class for column property change events which holds the OComponentDefinition weak
83 typedef ::cppu::WeakImplHelper1	< XPropertyChangeListener > TColumnPropertyListener_BASE;
84 class OColumnPropertyListener : public TColumnPropertyListener_BASE
85 {
86     OComponentDefinition* m_pComponent;
87 
88     OColumnPropertyListener(const OColumnPropertyListener&);
89     void operator =(const OColumnPropertyListener&);
90 protected:
91     virtual ~OColumnPropertyListener(){}
92 public:
93     OColumnPropertyListener(OComponentDefinition* _pComponent) : m_pComponent(_pComponent){}
94     // XPropertyChangeListener
95 	virtual void SAL_CALL propertyChange( const PropertyChangeEvent& /*_rEvent*/ ) throw (RuntimeException)
96     {
97         if ( m_pComponent )
98             m_pComponent->notifyDataSourceModified();
99     }
100 	// XEventListener
101 	virtual void SAL_CALL disposing( const EventObject& /*_rSource*/ ) throw (RuntimeException)
102     {
103     }
104     void clear() { m_pComponent = NULL; }
105 };
106 DBG_NAME(OComponentDefinition_Impl)
107 OComponentDefinition_Impl::OComponentDefinition_Impl()
108 {
109     DBG_CTOR(OComponentDefinition_Impl,NULL);
110 }
111 // -----------------------------------------------------------------------------
112 OComponentDefinition_Impl::~OComponentDefinition_Impl()
113 {
114     DBG_DTOR(OComponentDefinition_Impl,NULL);
115 }
116 //==========================================================================
117 //= OComponentDefinition
118 //==========================================================================
119 //--------------------------------------------------------------------------
120 DBG_NAME(OComponentDefinition)
121 //--------------------------------------------------------------------------
122 void OComponentDefinition::registerProperties()
123 {
124     m_xColumnPropertyListener = ::comphelper::ImplementationReference<OColumnPropertyListener,XPropertyChangeListener>(new OColumnPropertyListener(this));
125 	OComponentDefinition_Impl& rDefinition( getDefinition() );
126     ODataSettings::registerPropertiesFor( &rDefinition );
127 
128 	registerProperty(PROPERTY_NAME, PROPERTY_ID_NAME, PropertyAttribute::BOUND | PropertyAttribute::READONLY|PropertyAttribute::CONSTRAINED,
129 					&rDefinition.m_aProps.aTitle, ::getCppuType(&rDefinition.m_aProps.aTitle));
130 
131 	if ( m_bTable )
132 	{
133 		registerProperty(PROPERTY_SCHEMANAME, PROPERTY_ID_SCHEMANAME, PropertyAttribute::BOUND,
134 						&rDefinition.m_sSchemaName, ::getCppuType(&rDefinition.m_sSchemaName));
135 
136 		registerProperty(PROPERTY_CATALOGNAME, PROPERTY_ID_CATALOGNAME, PropertyAttribute::BOUND,
137 						&rDefinition.m_sCatalogName, ::getCppuType(&rDefinition.m_sCatalogName));
138 	}
139 }
140 
141 //--------------------------------------------------------------------------
142 OComponentDefinition::OComponentDefinition(const Reference< XMultiServiceFactory >& _xORB
143 										   ,const Reference< XInterface >&	_xParentContainer
144 										   ,const TContentPtr& _pImpl
145 										   ,sal_Bool _bTable)
146 	:OContentHelper(_xORB,_xParentContainer,_pImpl)
147 	,ODataSettings(OContentHelper::rBHelper,!_bTable)
148 	,m_bTable(_bTable)
149 {
150 	DBG_CTOR(OComponentDefinition, NULL);
151 	registerProperties();
152 }
153 //--------------------------------------------------------------------------
154 OComponentDefinition::~OComponentDefinition()
155 {
156 	DBG_DTOR(OComponentDefinition, NULL);
157 }
158 
159 //--------------------------------------------------------------------------
160 OComponentDefinition::OComponentDefinition(	const Reference< XInterface >& _rxContainer
161 									   ,const ::rtl::OUString& _rElementName
162 									   ,const Reference< XMultiServiceFactory >& _xORB
163 									   ,const TContentPtr& _pImpl
164 									   ,sal_Bool _bTable)
165 	:OContentHelper(_xORB,_rxContainer,_pImpl)
166 	,ODataSettings(OContentHelper::rBHelper,!_bTable)
167 	,m_bTable(_bTable)
168 {
169 	DBG_CTOR(OComponentDefinition, NULL);
170 	registerProperties();
171 
172 	m_pImpl->m_aProps.aTitle = _rElementName;
173 	DBG_ASSERT(m_pImpl->m_aProps.aTitle.getLength() != 0, "OComponentDefinition::OComponentDefinition : invalid name !");
174 }
175 
176 //--------------------------------------------------------------------------
177 IMPLEMENT_IMPLEMENTATION_ID(OComponentDefinition);
178 IMPLEMENT_GETTYPES3(OComponentDefinition,ODataSettings,OContentHelper,OComponentDefinition_BASE);
179 IMPLEMENT_FORWARD_XINTERFACE3( OComponentDefinition,OContentHelper,ODataSettings,OComponentDefinition_BASE)
180 //--------------------------------------------------------------------------
181 ::rtl::OUString OComponentDefinition::getImplementationName_static(  ) throw(RuntimeException)
182 {
183 	return ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.dba.OComponentDefinition"));
184 }
185 
186 //--------------------------------------------------------------------------
187 ::rtl::OUString SAL_CALL OComponentDefinition::getImplementationName(  ) throw(RuntimeException)
188 {
189 	return getImplementationName_static();
190 }
191 
192 //--------------------------------------------------------------------------
193 Sequence< ::rtl::OUString > OComponentDefinition::getSupportedServiceNames_static(  ) throw(RuntimeException)
194 {
195 	Sequence< ::rtl::OUString > aServices(2);
196 	aServices.getArray()[0] = SERVICE_SDB_TABLEDEFINITION;
197 	aServices.getArray()[1] = ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.ucb.Content"));
198 
199 	return aServices;
200 }
201 
202 //--------------------------------------------------------------------------
203 Sequence< ::rtl::OUString > SAL_CALL OComponentDefinition::getSupportedServiceNames(  ) throw(RuntimeException)
204 {
205 	return getSupportedServiceNames_static();
206 }
207 //------------------------------------------------------------------------------
208 Reference< XInterface > OComponentDefinition::Create( const Reference< XComponentContext >& _rxContext )
209 {
210     ::comphelper::ComponentContext aContext( _rxContext );
211 	return *(new OComponentDefinition( aContext.getLegacyServiceFactory(), NULL, TContentPtr( new OComponentDefinition_Impl ) ) );
212 }
213 // -----------------------------------------------------------------------------
214 void SAL_CALL OComponentDefinition::disposing()
215 {
216 	OContentHelper::disposing();
217     if ( m_pColumns.get() )
218 	    m_pColumns->disposing();
219     m_xColumnPropertyListener->clear();
220     m_xColumnPropertyListener.dispose();
221 }
222 // -----------------------------------------------------------------------------
223 IPropertyArrayHelper& OComponentDefinition::getInfoHelper()
224 {
225 	return *getArrayHelper();
226 }
227 //--------------------------------------------------------------------------
228 IPropertyArrayHelper* OComponentDefinition::createArrayHelper( ) const
229 {
230 	Sequence< Property > aProps;
231 	describeProperties(aProps);
232 	return new OPropertyArrayHelper(aProps);
233 }
234 //--------------------------------------------------------------------------
235 Reference< XPropertySetInfo > SAL_CALL OComponentDefinition::getPropertySetInfo(  ) throw(RuntimeException)
236 {
237 	Reference<XPropertySetInfo> xInfo( createPropertySetInfo( getInfoHelper() ) );
238 	return xInfo;
239 }
240 
241 // -----------------------------------------------------------------------------
242 ::rtl::OUString OComponentDefinition::determineContentType() const
243 {
244     return m_bTable
245         ?   ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "application/vnd.org.openoffice.DatabaseTable" ) )
246         :   ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "application/vnd.org.openoffice.DatabaseCommandDefinition" ) );
247 }
248 
249 // -----------------------------------------------------------------------------
250 Reference< XNameAccess> OComponentDefinition::getColumns() throw (RuntimeException)
251 {
252 	::osl::MutexGuard aGuard(m_aMutex);
253 	::connectivity::checkDisposed(OContentHelper::rBHelper.bDisposed);
254 
255 	if ( !m_pColumns.get() )
256 	{
257         ::std::vector< ::rtl::OUString> aNames;
258 
259         const OComponentDefinition_Impl& rDefinition( getDefinition() );
260 		aNames.reserve( rDefinition.size() );
261 
262         OComponentDefinition_Impl::const_iterator aIter = rDefinition.begin();
263 		OComponentDefinition_Impl::const_iterator aEnd = rDefinition.end();
264 		for ( ; aIter != aEnd; ++aIter )
265 			aNames.push_back( aIter->first );
266 
267         m_pColumns.reset( new OColumns( *this, m_aMutex, sal_True, aNames, this, NULL, sal_True, sal_False, sal_False ) );
268 		m_pColumns->setParent( *this );
269 	}
270 	return m_pColumns.get();
271 }
272 // -----------------------------------------------------------------------------
273 OColumn* OComponentDefinition::createColumn(const ::rtl::OUString& _rName) const
274 {
275     const OComponentDefinition_Impl& rDefinition( getDefinition() );
276     OComponentDefinition_Impl::const_iterator aFind = rDefinition.find( _rName );
277 	if ( aFind != rDefinition.end() )
278     {
279         aFind->second->addPropertyChangeListener(::rtl::OUString(),m_xColumnPropertyListener.getRef());
280 		return new OTableColumnWrapper( aFind->second, aFind->second, true );
281     }
282     OSL_ENSURE( false, "OComponentDefinition::createColumn: is this a valid case?" );
283         // This here is the last place creating a OTableColumn, and somehow /me thinks it is not needed ...
284 	return new OTableColumn( _rName );
285 }
286 // -----------------------------------------------------------------------------
287 Reference< XPropertySet > OComponentDefinition::createColumnDescriptor()
288 {
289 	return new OTableColumnDescriptor( true );
290 }
291 // -----------------------------------------------------------------------------
292 void OComponentDefinition::setFastPropertyValue_NoBroadcast(sal_Int32 nHandle,const Any& rValue) throw (Exception)
293 {
294 	ODataSettings::setFastPropertyValue_NoBroadcast(nHandle,rValue);
295 	notifyDataSourceModified();
296 }
297 // -----------------------------------------------------------------------------
298 void OComponentDefinition::columnDropped(const ::rtl::OUString& _sName)
299 {
300     getDefinition().erase( _sName );
301 	notifyDataSourceModified();
302 }
303 // -----------------------------------------------------------------------------
304 void OComponentDefinition::columnAppended( const Reference< XPropertySet >& _rxSourceDescriptor )
305 {
306 	::rtl::OUString sName;
307 	_rxSourceDescriptor->getPropertyValue( PROPERTY_NAME ) >>= sName;
308 
309     Reference<XPropertySet> xColDesc = new OTableColumnDescriptor( true );
310 	::comphelper::copyProperties( _rxSourceDescriptor, xColDesc );
311     getDefinition().insert( sName, xColDesc );
312 
313     // formerly, here was a setParent at the xColDesc. The parent used was an adapter (ChildHelper_Impl)
314     // which held another XChild weak, and forwarded all getParent requests to this other XChild.
315     // m_pColumns was used for this. This was nonsense, since m_pColumns dies when our instance dies,
316     // but xColDesc will live longer than this. So effectively, the setParent call was pretty useless.
317     //
318     // The intention for this parenting was that the column descriptor is able to find the data source,
319     // by traveling up the parent hierachy until there's an XDataSource. This didn't work (which
320     // for instance causes #i65023#). We need another way to properly ensure this.
321 
322     notifyDataSourceModified();
323 }
324 
325 //........................................................................
326 }	// namespace dbaccess
327 //........................................................................
328 
329