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