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