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 #include "databaseobjectview.hxx"
32 #include "dbustrings.hrc"
33 #include "asyncmodaldialog.hxx"
34 
35 /** === begin UNO includes === **/
36 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
37 #include <com/sun/star/frame/XDispatchProvider.hpp>
38 #include <com/sun/star/frame/XFrame.hpp>
39 #include <com/sun/star/frame/XFrames.hpp>
40 #include <com/sun/star/frame/FrameSearchFlag.hpp>
41 #include <com/sun/star/sdb/CommandType.hpp>
42 #include <com/sun/star/sdb/application/XTableUIProvider.hpp>
43 #include <com/sun/star/beans/NamedValue.hpp>
44 #include <com/sun/star/awt/Rectangle.hpp>
45 /** === end UNO includes === **/
46 
47 #include <comphelper/extract.hxx>
48 #include <comphelper/sequence.hxx>
49 #include <connectivity/dbtools.hxx>
50 #include <osl/diagnose.h>
51 #include <toolkit/helper/vclunohelper.hxx>
52 #include <tools/diagnose_ex.h>
53 #include <vcl/window.hxx>
54 
55 // .........................................................................
56 namespace dbaui
57 {
58 // .........................................................................
59 
60 	using namespace ::com::sun::star::uno;
61 	using namespace ::com::sun::star::sdbc;
62 	using namespace ::com::sun::star::sdb;
63     using namespace ::com::sun::star::sdb::application;
64     using namespace ::com::sun::star::ui::dialogs;
65 	using namespace ::com::sun::star::frame;
66 	using namespace ::com::sun::star::lang;
67 	using namespace ::com::sun::star::beans;
68 	using namespace ::com::sun::star::awt;
69 
70 	//======================================================================
71 	//= DatabaseObjectView
72 	//======================================================================
73 	DatabaseObjectView::DatabaseObjectView( const Reference< XMultiServiceFactory >& _rxORB,
74             const Reference< XDatabaseDocumentUI >& _rxApplication,
75 			const Reference< XFrame >& _rxParentFrame,
76 			const ::rtl::OUString& _rComponentURL )
77 		:m_xORB             ( _rxORB            )
78 		,m_xParentFrame     ( _rxParentFrame    )
79         ,m_xFrameLoader     (                   )
80         ,m_xApplication     ( _rxApplication    )
81         ,m_sComponentURL    ( _rComponentURL    )
82 	{
83 		OSL_ENSURE( m_xORB.is(), "DatabaseObjectView::DatabaseObjectView: invalid service factory!" );
84         OSL_ENSURE( m_xApplication.is(), "DatabaseObjectView::DatabaseObjectView: invalid connection!" );
85 	}
86 
87 	//----------------------------------------------------------------------
88     Reference< XConnection > DatabaseObjectView::getConnection() const
89     {
90         Reference< XConnection > xConnection;
91         if ( m_xApplication.is() )
92             xConnection = m_xApplication->getActiveConnection();
93         return xConnection;
94     }
95 
96 	//----------------------------------------------------------------------
97 	Reference< XComponent > DatabaseObjectView::createNew( const Reference< XDataSource >& _xDataSource, const ::comphelper::NamedValueCollection& i_rDispatchArgs )
98 	{
99         return doCreateView( makeAny( _xDataSource ), ::rtl::OUString(), i_rDispatchArgs );
100 	}
101 
102 	//----------------------------------------------------------------------
103 	Reference< XComponent > DatabaseObjectView::openExisting( const Any& _rDataSource, const ::rtl::OUString& _rName,
104             const ::comphelper::NamedValueCollection& i_rDispatchArgs )
105 	{
106         return doCreateView( _rDataSource, _rName, i_rDispatchArgs );
107 	}
108 
109 	//----------------------------------------------------------------------
110 	Reference< XComponent > DatabaseObjectView::doCreateView( const Any& _rDataSource, const ::rtl::OUString& _rObjectName,
111         const ::comphelper::NamedValueCollection& i_rCreationArgs )
112     {
113         ::comphelper::NamedValueCollection aDispatchArgs;
114 
115         aDispatchArgs.merge( i_rCreationArgs, false );    // false => do not overwrite
116         fillDispatchArgs( aDispatchArgs, _rDataSource, _rObjectName );
117         aDispatchArgs.merge( i_rCreationArgs, true );    // true => do overwrite
118 
119         return doDispatch( aDispatchArgs );
120     }
121 
122 	//----------------------------------------------------------------------
123 	Reference< XComponent > DatabaseObjectView::doDispatch( const ::comphelper::NamedValueCollection& i_rDispatchArgs )
124 	{
125 		Reference< XComponent > xReturn;
126 		if ( m_xORB.is() )
127 		{
128 			try
129 			{
130 				// if we have no externally provided frame, create one
131 				if ( !m_xFrameLoader.is() )
132 				{
133 					Reference< XSingleServiceFactory > xFact(m_xORB->createInstance(::rtl::OUString::createFromAscii("com.sun.star.frame.TaskCreator")), UNO_QUERY_THROW);
134 					Sequence< Any > lArgs(2);
135 					NamedValue      aProp;
136                     sal_Int32       nArg = 0;
137 
138 					aProp.Name    = ::rtl::OUString::createFromAscii("ParentFrame");
139 					aProp.Value <<= m_xParentFrame;
140 					lArgs[nArg++] <<= aProp;
141 
142 					aProp.Name    = ::rtl::OUString::createFromAscii("TopWindow");
143 					aProp.Value <<= sal_True;
144 					lArgs[nArg++] <<= aProp;
145 
146 					m_xFrameLoader.set(xFact->createInstanceWithArguments(lArgs), UNO_QUERY_THROW);
147 
148                     // everything we load can be considered a "top level document", so set the respective bit at the window.
149                     // This, amongst other things, triggers that the component in this task participates in the
150                     // "ThisComponent"-game for the global application Basic.
151                     const Reference< XFrame > xFrame( m_xFrameLoader, UNO_QUERY_THROW );
152                     const Reference< XWindow > xFrameWindow( xFrame->getContainerWindow(), UNO_SET_THROW );
153                     Window* pContainerWindow = VCLUnoHelper::GetWindow( xFrameWindow );
154                     ENSURE_OR_THROW( pContainerWindow, "no implementation access to the frame's container window!" );
155                     pContainerWindow->SetExtendedStyle( pContainerWindow->GetExtendedStyle() | WB_EXT_DOCUMENT );
156 				}
157 
158 				Reference< XComponentLoader > xFrameLoader( m_xFrameLoader, UNO_QUERY_THROW );
159 				xReturn = xFrameLoader->loadComponentFromURL(
160 					m_sComponentURL,
161 					::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("_self")),
162 					0,
163 					i_rDispatchArgs.getPropertyValues()
164 				);
165 			}
166             catch( const Exception& )
167             {
168                 DBG_UNHANDLED_EXCEPTION();
169             }
170 		}
171 		return xReturn;
172 	}
173 
174 	//----------------------------------------------------------------------
175 	void DatabaseObjectView::fillDispatchArgs(
176 			::comphelper::NamedValueCollection& i_rDispatchArgs,
177 			const Any& _aDataSource,
178             const ::rtl::OUString& /* _rName */
179 		)
180 	{
181 		::rtl::OUString sDataSource;
182 		Reference<XDataSource> xDataSource;
183 		if ( _aDataSource >>= sDataSource )
184 		{
185             i_rDispatchArgs.put( (::rtl::OUString)PROPERTY_DATASOURCENAME, sDataSource );
186 		}
187 		else if ( _aDataSource >>= xDataSource )
188 		{
189             i_rDispatchArgs.put( (::rtl::OUString)PROPERTY_DATASOURCE, xDataSource );
190 		}
191 
192         i_rDispatchArgs.put( (::rtl::OUString)PROPERTY_ACTIVE_CONNECTION, getConnection() );
193 	}
194 
195 	//======================================================================
196 	//= QueryDesigner
197 	//======================================================================
198 	//----------------------------------------------------------------------
199 	QueryDesigner::QueryDesigner( const Reference< XMultiServiceFactory >& _rxORB, const Reference< XDatabaseDocumentUI >& _rxApplication,
200 		const Reference< XFrame >& _rxParentFrame, bool _bCreateView )
201         :DatabaseObjectView( _rxORB, _rxApplication, _rxParentFrame, _bCreateView ? URL_COMPONENT_VIEWDESIGN : URL_COMPONENT_QUERYDESIGN )
202         ,m_nCommandType( _bCreateView ? CommandType::TABLE : CommandType::QUERY )
203 	{
204 	}
205 
206 	//----------------------------------------------------------------------
207 	void QueryDesigner::fillDispatchArgs( ::comphelper::NamedValueCollection& i_rDispatchArgs, const Any& _aDataSource,
208 		const ::rtl::OUString& _rObjectName )
209 	{
210 		DatabaseObjectView::fillDispatchArgs( i_rDispatchArgs, _aDataSource, _rObjectName );
211 
212 		const bool bIncludeQueryName = 0 != _rObjectName.getLength();
213         const bool bGraphicalDesign = i_rDispatchArgs.getOrDefault( (::rtl::OUString)PROPERTY_GRAPHICAL_DESIGN, sal_True );
214         const bool bEditViewAsSQLCommand = ( m_nCommandType == CommandType::TABLE ) && !bGraphicalDesign;
215 
216         i_rDispatchArgs.put( (::rtl::OUString)PROPERTY_COMMAND_TYPE, m_nCommandType );
217 
218         if ( bIncludeQueryName )
219 		{
220             i_rDispatchArgs.put( (::rtl::OUString)PROPERTY_COMMAND, _rObjectName );
221         }
222 
223         if ( bEditViewAsSQLCommand )
224         {
225             i_rDispatchArgs.put( (::rtl::OUString)PROPERTY_ESCAPE_PROCESSING, sal_False );
226         }
227 	}
228 
229 	//======================================================================
230 	//= TableDesigner
231 	//======================================================================
232 	//----------------------------------------------------------------------
233 	TableDesigner::TableDesigner( const Reference< XMultiServiceFactory >& _rxORB, const Reference< XDatabaseDocumentUI >& _rxApplication, const Reference< XFrame >& _rxParentFrame )
234 		:DatabaseObjectView( _rxORB, _rxApplication, _rxParentFrame, static_cast< ::rtl::OUString >( URL_COMPONENT_TABLEDESIGN ) )
235 	{
236 	}
237 
238 	//----------------------------------------------------------------------
239 	void TableDesigner::fillDispatchArgs( ::comphelper::NamedValueCollection& i_rDispatchArgs, const Any& _aDataSource,
240 		const ::rtl::OUString& _rObjectName )
241 	{
242 		DatabaseObjectView::fillDispatchArgs( i_rDispatchArgs, _aDataSource, _rObjectName );
243 
244         if ( 0 != _rObjectName.getLength() )
245 		{
246             i_rDispatchArgs.put( (::rtl::OUString)PROPERTY_CURRENTTABLE, _rObjectName );
247 		}
248 	}
249 
250 	//----------------------------------------------------------------------
251     Reference< XComponent > TableDesigner::doCreateView( const Any& _rDataSource, const ::rtl::OUString& _rObjectName,
252         const ::comphelper::NamedValueCollection& i_rCreationArgs )
253     {
254         bool bIsNewDesign = ( _rObjectName.getLength() == 0 );
255 
256         // let's see whether the connection can provide a dedicated table desginer
257         Reference< XInterface > xDesigner;
258         if ( !bIsNewDesign )
259             xDesigner = impl_getConnectionProvidedDesigner_nothrow( _rObjectName );
260 
261         if ( !xDesigner.is() )
262             return DatabaseObjectView::doCreateView( _rDataSource, _rObjectName, i_rCreationArgs );
263 
264         // try whether the designer is a dialog
265         Reference< XExecutableDialog > xDialog( xDesigner, UNO_QUERY_THROW );
266         if ( xDialog.is() )
267         {
268             try { AsyncDialogExecutor::executeModalDialogAsync( xDialog ); }
269             catch( const Exception& ) { DBG_UNHANDLED_EXCEPTION(); }
270             return NULL;
271         }
272 
273         Reference< XComponent > xDesignerComponent( xDesigner, UNO_QUERY );
274         OSL_ENSURE( xDesignerComponent.is(), "TableDesigner::doCreateView: a designer which is no dialog and no component?" );
275         return xDesignerComponent;
276     }
277 
278 	//----------------------------------------------------------------------
279     Reference< XInterface > TableDesigner::impl_getConnectionProvidedDesigner_nothrow( const ::rtl::OUString& _rTableName )
280     {
281         Reference< XInterface > xDesigner;
282         try
283         {
284             Reference< XTableUIProvider > xTableUIProv( getConnection(), UNO_QUERY );
285             if ( xTableUIProv.is() )
286                 xDesigner = xTableUIProv->getTableEditor( getApplicationUI(), _rTableName );
287         }
288         catch( const Exception& )
289         {
290         	DBG_UNHANDLED_EXCEPTION();
291         }
292         return xDesigner;
293     }
294 
295     //======================================================================
296 	//= ResultSetBrowser
297 	//======================================================================
298 	//----------------------------------------------------------------------
299 	ResultSetBrowser::ResultSetBrowser( const Reference< XMultiServiceFactory >& _rxORB, const Reference< XDatabaseDocumentUI >& _rxApplication, const Reference< XFrame >& _rxParentFrame,
300             sal_Bool _bTable )
301 		:DatabaseObjectView( _rxORB, _rxApplication, _rxParentFrame, static_cast < ::rtl::OUString >( URL_COMPONENT_DATASOURCEBROWSER ) )
302 		,m_bTable(_bTable)
303 	{
304 	}
305 
306 	//----------------------------------------------------------------------
307 	void ResultSetBrowser::fillDispatchArgs( ::comphelper::NamedValueCollection& i_rDispatchArgs, const Any& _aDataSource,
308 		const ::rtl::OUString& _rQualifiedName)
309 	{
310 		DatabaseObjectView::fillDispatchArgs( i_rDispatchArgs, _aDataSource, _rQualifiedName );
311 		OSL_ENSURE( 0 != _rQualifiedName.getLength(),"A Table name must be set");
312 		::rtl::OUString sCatalog;
313 		::rtl::OUString sSchema;
314 		::rtl::OUString sTable;
315 		if ( m_bTable )
316 			::dbtools::qualifiedNameComponents( getConnection()->getMetaData(), _rQualifiedName, sCatalog, sSchema, sTable, ::dbtools::eInDataManipulation );
317 
318         i_rDispatchArgs.put( (::rtl::OUString)PROPERTY_COMMAND_TYPE, (m_bTable ? CommandType::TABLE : CommandType::QUERY) );
319         i_rDispatchArgs.put( (::rtl::OUString)PROPERTY_COMMAND, _rQualifiedName );
320         i_rDispatchArgs.put( (::rtl::OUString)PROPERTY_ENABLE_BROWSER, sal_False );
321 
322 		if ( m_bTable )
323 		{
324             i_rDispatchArgs.put( (::rtl::OUString)PROPERTY_UPDATE_CATALOGNAME, sCatalog );
325             i_rDispatchArgs.put( (::rtl::OUString)PROPERTY_UPDATE_SCHEMANAME, sSchema );
326             i_rDispatchArgs.put( (::rtl::OUString)PROPERTY_UPDATE_TABLENAME, sTable );
327 		}
328 	}
329 
330 	//======================================================================
331 	//= RelationDesigner
332 	//======================================================================
333 	//----------------------------------------------------------------------
334 	RelationDesigner::RelationDesigner( const Reference< XMultiServiceFactory >& _rxORB, const Reference< XDatabaseDocumentUI >& _rxApplication, const Reference< XFrame >& _rxParentFrame )
335         :DatabaseObjectView( _rxORB, _rxApplication, _rxParentFrame, static_cast< ::rtl::OUString >( URL_COMPONENT_RELATIONDESIGN ) )
336 	{
337 	}
338 // .........................................................................
339 }	// namespace dbaui
340 // .........................................................................
341 
342