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_connectivity.hxx"
30 #include "connectivity/sdbcx/VTable.hxx"
31 #include <com/sun/star/lang/DisposedException.hpp>
32 #include "connectivity/sdbcx/VIndex.hxx"
33 #include <comphelper/sequence.hxx>
34 #include "connectivity/sdbcx/VCollection.hxx"
35 #include "TConnection.hxx"
36 #include "connectivity/sdbcx/VColumn.hxx"
37 #include "connectivity/sdbcx/VKey.hxx"
38 #include "connectivity/dbtools.hxx"
39 #include <connectivity/dbexception.hxx>
40 
41 // -------------------------------------------------------------------------
42 using namespace ::connectivity;
43 using namespace ::connectivity::sdbcx;
44 using namespace ::dbtools;
45 using namespace ::com::sun::star::beans;
46 using namespace ::com::sun::star::uno;
47 using namespace ::com::sun::star::sdbc;
48 using namespace ::com::sun::star::sdbcx;
49 using namespace ::com::sun::star::container;
50 using namespace ::com::sun::star::lang;
51 
52 // -----------------------------------------------------------------------------
53 ::rtl::OUString SAL_CALL OTable::getImplementationName(  ) throw (::com::sun::star::uno::RuntimeException)
54 {
55 	if(isNew())
56 		return ::rtl::OUString::createFromAscii("com.sun.star.sdbcx.VTableDescriptor");
57 	return ::rtl::OUString::createFromAscii("com.sun.star.sdbcx.Table");
58 }
59 
60 // -----------------------------------------------------------------------------
61 ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL OTable::getSupportedServiceNames(  ) throw(::com::sun::star::uno::RuntimeException)
62 {
63 	::com::sun::star::uno::Sequence< ::rtl::OUString > aSupported(1);
64 	if(isNew())
65 		aSupported[0] = ::rtl::OUString::createFromAscii("com.sun.star.sdbcx.TableDescriptor");
66 	else
67 		aSupported[0] = ::rtl::OUString::createFromAscii("com.sun.star.sdbcx.Table");
68 
69 	return aSupported;
70 }
71 // -----------------------------------------------------------------------------
72 sal_Bool SAL_CALL OTable::supportsService( const ::rtl::OUString& _rServiceName ) throw(::com::sun::star::uno::RuntimeException)
73 {
74 	Sequence< ::rtl::OUString > aSupported(getSupportedServiceNames());
75 	const ::rtl::OUString* pSupported = aSupported.getConstArray();
76 	const ::rtl::OUString* pEnd = pSupported + aSupported.getLength();
77 	for (;pSupported != pEnd && !pSupported->equals(_rServiceName); ++pSupported)
78 		;
79 
80 	return pSupported != pEnd;
81 }
82 // -------------------------------------------------------------------------
83 OTable::OTable(OCollection*	_pTables,
84 			   sal_Bool _bCase)
85 			   : OTableDescriptor_BASE(m_aMutex)
86 				,ODescriptor(OTableDescriptor_BASE::rBHelper,_bCase,sal_True)
87 				,m_pKeys(NULL)
88 				,m_pColumns(NULL)
89 				,m_pIndexes(NULL)
90 				,m_pTables(_pTables)
91 {
92 }
93 // -----------------------------------------------------------------------------
94 OTable::OTable( OCollection*	_pTables,
95 				sal_Bool _bCase,
96 				const ::rtl::OUString& _Name,		const ::rtl::OUString& _Type,
97 				const ::rtl::OUString& _Description,const ::rtl::OUString& _SchemaName,
98 				const ::rtl::OUString& _CatalogName) :	OTableDescriptor_BASE(m_aMutex)
99 				,ODescriptor(OTableDescriptor_BASE::rBHelper,_bCase)
100                 ,m_CatalogName(_CatalogName)
101                 ,m_SchemaName(_SchemaName)
102                 ,m_Description(_Description)
103                 ,m_Type(_Type)
104 				,m_pKeys(NULL)
105 				,m_pColumns(NULL)
106 				,m_pIndexes(NULL)
107                 ,m_pTables(_pTables)
108 {
109 	m_Name = _Name;
110 }
111 // -------------------------------------------------------------------------
112 OTable::~OTable()
113 {
114 	delete m_pKeys;
115 	delete m_pColumns;
116 	delete m_pIndexes;
117 }
118 // -------------------------------------------------------------------------
119 void OTable::construct()
120 {
121 	ODescriptor::construct();
122 
123 	sal_Int32 nAttrib = isNew() ? 0 : PropertyAttribute::READONLY;
124 
125 	registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_CATALOGNAME),		PROPERTY_ID_CATALOGNAME,nAttrib,&m_CatalogName,	::getCppuType(reinterpret_cast< ::rtl::OUString*>(NULL)));
126 	registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_SCHEMANAME),		PROPERTY_ID_SCHEMANAME,	nAttrib,&m_SchemaName,	::getCppuType(reinterpret_cast< ::rtl::OUString*>(NULL)));
127 	registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_DESCRIPTION),		PROPERTY_ID_DESCRIPTION,nAttrib,&m_Description,	::getCppuType(reinterpret_cast< ::rtl::OUString*>(NULL)));
128 	registerProperty(OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_TYPE),			PROPERTY_ID_TYPE,		nAttrib,&m_Type,		::getCppuType(reinterpret_cast< ::rtl::OUString*>(NULL)));
129 }
130 // -----------------------------------------------------------------------------
131 void SAL_CALL OTable::acquire() throw()
132 {
133 	OTableDescriptor_BASE::acquire();
134 }
135 // -----------------------------------------------------------------------------
136 void SAL_CALL OTable::release() throw()
137 {
138 	OTableDescriptor_BASE::release();
139 }
140 
141 // -------------------------------------------------------------------------
142 Any SAL_CALL OTable::queryInterface( const Type & rType ) throw(RuntimeException)
143 {
144 	Any aRet = ODescriptor::queryInterface( rType);
145 	if(!aRet.hasValue())
146 	{
147 		if(!isNew())
148 			aRet = OTable_BASE::queryInterface( rType);
149 		if(isNew() && (rType == getCppuType( (Reference<XIndexesSupplier>*)0)))
150 			return Any();
151 		if(!aRet.hasValue())
152 			aRet = OTableDescriptor_BASE::queryInterface( rType);
153 	}
154 	return aRet;
155 }
156 // -------------------------------------------------------------------------
157 Sequence< Type > SAL_CALL OTable::getTypes(  ) throw(RuntimeException)
158 {
159 	if(isNew())
160 		return ::comphelper::concatSequences(ODescriptor::getTypes(),OTableDescriptor_BASE::getTypes());
161 	return ::comphelper::concatSequences(ODescriptor::getTypes(),OTableDescriptor_BASE::getTypes(),OTable_BASE::getTypes());
162 }
163 // -------------------------------------------------------------------------
164 void SAL_CALL OTable::disposing(void)
165 {
166 	ODescriptor::disposing();
167 
168 	::osl::MutexGuard aGuard(m_aMutex);
169 
170 	if(m_pKeys)
171 		m_pKeys->disposing();
172 	if(m_pColumns)
173 		m_pColumns->disposing();
174 	if(m_pIndexes)
175 		m_pIndexes->disposing();
176 
177 	m_pTables = NULL;
178 }
179 // -----------------------------------------------------------------------------
180 // XColumnsSupplier
181 Reference< XNameAccess > SAL_CALL OTable::getColumns(  ) throw(RuntimeException)
182 {
183 	::osl::MutexGuard aGuard(m_aMutex);
184 	checkDisposed(OTableDescriptor_BASE::rBHelper.bDisposed);
185 
186 	try
187 	{
188 		if ( !m_pColumns )
189 			refreshColumns();
190 	}
191 	catch( const RuntimeException& )
192 	{
193 		// allowed to leave this method
194 		throw;
195 	}
196 	catch( const Exception& )
197 	{
198 		// allowed
199 	}
200 
201 	return m_pColumns;
202 }
203 
204 // -------------------------------------------------------------------------
205 // XKeysSupplier
206 Reference< XIndexAccess > SAL_CALL OTable::getKeys(  ) throw(RuntimeException)
207 {
208 	::osl::MutexGuard aGuard(m_aMutex);
209 	checkDisposed(OTableDescriptor_BASE::rBHelper.bDisposed);
210 
211     Reference< XIndexAccess > xKeys;
212 
213 	try
214 	{
215         if ( !m_pKeys )
216 		    refreshKeys();
217         xKeys = m_pKeys;
218 	}
219 	catch( const RuntimeException& )
220 	{
221 		// allowed to leave this method
222 		throw;
223 	}
224 	catch( const Exception& )
225 	{
226 		// allowed
227 	}
228 
229 	return xKeys;
230 }
231 // -----------------------------------------------------------------------------
232 cppu::IPropertyArrayHelper* OTable::createArrayHelper( sal_Int32 /*_nId*/ ) const
233 {
234     return doCreateArrayHelper();
235 }
236 // -------------------------------------------------------------------------
237 cppu::IPropertyArrayHelper & OTable::getInfoHelper()
238 {
239 	return *const_cast<OTable*>(this)->getArrayHelper(isNew() ? 1 : 0);
240 }
241 // -------------------------------------------------------------------------
242 Reference< XPropertySet > SAL_CALL OTable::createDataDescriptor(  ) throw(RuntimeException)
243 {
244 	::osl::MutexGuard aGuard(m_aMutex);
245 	checkDisposed(OTableDescriptor_BASE::rBHelper.bDisposed);
246 
247 	OTable* pTable = new OTable(m_pTables,isCaseSensitive(),m_Name,m_Type,m_Description,m_SchemaName,m_CatalogName);
248 	pTable->setNew(sal_True);
249 	return pTable;
250 }
251 // -------------------------------------------------------------------------
252 // XIndexesSupplier
253 Reference< XNameAccess > SAL_CALL OTable::getIndexes(  ) throw(RuntimeException)
254 {
255 	::osl::MutexGuard aGuard(m_aMutex);
256 	checkDisposed(OTableDescriptor_BASE::rBHelper.bDisposed);
257 
258 	try
259 	{
260 		if ( !m_pIndexes )
261 			refreshIndexes();
262 	}
263 	catch( const RuntimeException& )
264 	{
265 		// allowed to leave this method
266 		throw;
267 	}
268 	catch( const Exception& )
269 	{
270 		// allowed
271 	}
272 
273 	return m_pIndexes;
274 }
275 // -------------------------------------------------------------------------
276 // XRename
277 void SAL_CALL OTable::rename( const ::rtl::OUString& newName ) throw(SQLException, ElementExistException, RuntimeException)
278 {
279 	::osl::MutexGuard aGuard(m_aMutex);
280 	checkDisposed(OTableDescriptor_BASE::rBHelper.bDisposed);
281 
282 	const ::rtl::OUString sOldComposedName = getName();
283 	const Reference< XDatabaseMetaData> xMetaData = getMetaData();
284 	if ( xMetaData.is() )
285 		::dbtools::qualifiedNameComponents(xMetaData,newName,m_CatalogName,m_SchemaName,m_Name,::dbtools::eInDataManipulation);
286 	else
287 		m_Name = newName;
288 
289 	m_pTables->renameObject(sOldComposedName,newName);
290 }
291 // -----------------------------------------------------------------------------
292 Reference< XDatabaseMetaData> OTable::getMetaData() const
293 {
294 	return NULL;
295 }
296 // -------------------------------------------------------------------------
297 // XAlterTable
298 void SAL_CALL OTable::alterColumnByName( const ::rtl::OUString& /*colName*/, const Reference< XPropertySet >& /*descriptor*/ ) throw(SQLException, NoSuchElementException, RuntimeException)
299 {
300     throwFeatureNotImplementedException( "XAlterTable::alterColumnByName", *this );
301 }
302 // -------------------------------------------------------------------------
303 void SAL_CALL OTable::alterColumnByIndex( sal_Int32 /*index*/, const Reference< XPropertySet >& /*descriptor*/ ) throw(SQLException, ::com::sun::star::lang::IndexOutOfBoundsException, RuntimeException)
304 {
305     throwFeatureNotImplementedException( "XAlterTable::alterColumnByIndex", *this );
306 }
307 // -------------------------------------------------------------------------
308 ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL OTable::getPropertySetInfo(  ) throw(::com::sun::star::uno::RuntimeException)
309 {
310 	return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper());
311 }
312 // -----------------------------------------------------------------------------
313 ::rtl::OUString SAL_CALL OTable::getName() throw(::com::sun::star::uno::RuntimeException)
314 {
315 	// this is only correct for tables who haven't a schema or catalog name
316 	OSL_ENSURE(!m_CatalogName.getLength(),"getName(): forgot to overload getName()!");
317 	OSL_ENSURE(!m_SchemaName.getLength(),"getName(): forgot to overload getName()!");
318 	return m_Name;
319 }
320 // -----------------------------------------------------------------------------
321 void SAL_CALL OTable::setName( const ::rtl::OUString& /*aName*/ ) throw(::com::sun::star::uno::RuntimeException)
322 {
323 }
324 // -----------------------------------------------------------------------------
325 void OTable::refreshColumns()
326 {
327 }
328 // -----------------------------------------------------------------------------
329 void OTable::refreshKeys()
330 {
331 }
332 // -----------------------------------------------------------------------------
333 void OTable::refreshIndexes()
334 {
335 }
336 // -----------------------------------------------------------------------------
337