summaryrefslogtreecommitdiff
path: root/dbaccess/qa
diff options
context:
space:
mode:
Diffstat (limited to 'dbaccess/qa')
-rw-r--r--dbaccess/qa/complex/dbaccess/ApplicationController.java187
-rw-r--r--dbaccess/qa/complex/dbaccess/Beamer.java185
-rw-r--r--dbaccess/qa/complex/dbaccess/CRMBasedTestCase.java91
-rwxr-xr-xdbaccess/qa/complex/dbaccess/CopyTableInterActionHandler.java50
-rwxr-xr-xdbaccess/qa/complex/dbaccess/CopyTableWizard.java244
-rw-r--r--dbaccess/qa/complex/dbaccess/DataSource.java126
-rwxr-xr-xdbaccess/qa/complex/dbaccess/DatabaseApplication.java98
-rw-r--r--dbaccess/qa/complex/dbaccess/DatabaseDocument.java1009
-rw-r--r--dbaccess/qa/complex/dbaccess/FileHelper.java44
-rw-r--r--dbaccess/qa/complex/dbaccess/Parser.java217
-rw-r--r--dbaccess/qa/complex/dbaccess/PropertyBag.java324
-rw-r--r--dbaccess/qa/complex/dbaccess/Query.java136
-rw-r--r--dbaccess/qa/complex/dbaccess/QueryInQuery.java202
-rw-r--r--dbaccess/qa/complex/dbaccess/RowSet.java1036
-rw-r--r--dbaccess/qa/complex/dbaccess/RowSetEventListener.java111
-rwxr-xr-xdbaccess/qa/complex/dbaccess/SingleSelectQueryComposer.java401
-rw-r--r--dbaccess/qa/complex/dbaccess/TestCase.java163
-rw-r--r--dbaccess/qa/complex/dbaccess/UISettings.java160
-rw-r--r--dbaccess/qa/complex/dbaccess/dbaccess.sce12
-rwxr-xr-xdbaccess/qa/complex/dbaccess/makefile.mk133
-rw-r--r--dbaccess/qa/unoapi/Test.java52
-rw-r--r--dbaccess/qa/unoapi/dbaccess.props6
-rw-r--r--dbaccess/qa/unoapi/dbaccess.sce15
-rw-r--r--dbaccess/qa/unoapi/knownissues.xcl62
-rw-r--r--dbaccess/qa/unoapi/makefile.mk48
-rwxr-xr-xdbaccess/qa/unoapi/testdocuments/TestDB/testDB.dbfbin0 -> 949 bytes
-rwxr-xr-xdbaccess/qa/unoapi/testdocuments/TestDB/testDB.dbtbin0 -> 512 bytes
27 files changed, 5112 insertions, 0 deletions
diff --git a/dbaccess/qa/complex/dbaccess/ApplicationController.java b/dbaccess/qa/complex/dbaccess/ApplicationController.java
new file mode 100644
index 000000000000..bffc1ce97c4c
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/ApplicationController.java
@@ -0,0 +1,187 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package complex.dbaccess;
+
+import com.sun.star.beans.PropertyValue;
+import com.sun.star.beans.XPropertySet;
+import com.sun.star.container.XNameAccess;
+import com.sun.star.frame.FrameSearchFlag;
+import com.sun.star.frame.XComponentLoader;
+import com.sun.star.frame.XModel;
+import com.sun.star.frame.XStorable;
+import com.sun.star.lang.XComponent;
+import com.sun.star.lang.XMultiServiceFactory;
+import com.sun.star.sdb.XOfficeDatabaseDocument;
+import com.sun.star.sdb.application.XDatabaseDocumentUI;
+import com.sun.star.sdbcx.XTablesSupplier;
+import com.sun.star.uno.Exception;
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.uno.XComponentContext;
+import connectivity.tools.HsqlColumnDescriptor;
+import connectivity.tools.HsqlDatabase;
+import connectivity.tools.HsqlTableDescriptor;
+import helper.URLHelper;
+import java.io.File;
+import java.io.IOException;
+
+
+// ---------- junit imports -----------------
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.openoffice.test.OfficeConnection;
+import static org.junit.Assert.*;
+// ------------------------------------------
+
+/** complex test case for Base's application UI
+ */
+public class ApplicationController extends TestCase
+{
+
+ private HsqlDatabase m_database;
+ private XOfficeDatabaseDocument m_databaseDocument;
+ private XDatabaseDocumentUI m_documentUI;
+
+ public ApplicationController()
+ {
+ super();
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+
+// public String[] getTestMethodNames()
+// {
+// return new String[]
+// {
+// "checkSaveAs"
+// };
+// }
+
+ // --------------------------------------------------------------------------------------------------------
+ public String getTestObjectName()
+ {
+ return getClass().getName();
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private void impl_closeDocument()
+ {
+ if (m_database != null)
+ {
+ m_database.close();
+ m_database = null;
+ m_databaseDocument = null;
+ m_documentUI = null;
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private void impl_switchToDocument(String _documentURL) throws java.lang.Exception
+ {
+ // close previous database document
+ impl_closeDocument();
+
+ // create/load the new database document
+ m_database = (_documentURL == null)
+ ? new HsqlDatabase(getMSF())
+ : new HsqlDatabase(getMSF(), _documentURL);
+ m_databaseDocument = m_database.getDatabaseDocument();
+
+ // load it into a frame
+ final Object object = getMSF().createInstance("com.sun.star.frame.Desktop");
+ final XComponentLoader xComponentLoader = UnoRuntime.queryInterface(XComponentLoader.class, object);
+ final XComponent loadedComponent = xComponentLoader.loadComponentFromURL(m_database.getDocumentURL(), "_blank", FrameSearchFlag.ALL, new PropertyValue[0]);
+
+ assertTrue("too many document instances!",
+ UnoRuntime.areSame(loadedComponent, m_databaseDocument));
+
+ // get the controller, which provides access to various UI operations
+ final XModel docModel = UnoRuntime.queryInterface(XModel.class,
+ loadedComponent);
+ m_documentUI = UnoRuntime.queryInterface(XDatabaseDocumentUI.class,
+ docModel.getCurrentController());
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ @Before public void before() throws java.lang.Exception
+ {
+ super.before();
+ impl_switchToDocument(null);
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ @After public void after() throws java.lang.Exception
+ {
+ impl_closeDocument();
+ super.after();
+ }
+ // --------------------------------------------------------------------------------------------------------
+
+ @Test public void checkSaveAs() throws Exception, IOException, java.lang.Exception
+ {
+ // issue 93737 describes the problem that when you save-as a database document, and do changes to it,
+ // then those changes are saved in the old document, actually
+ final String oldDocumentURL = m_database.getDocumentURL();
+
+ final String newDocumentURL = createTempFileURL();
+
+ // store the doc in a new location
+ final XStorable storeDoc = UnoRuntime.queryInterface( XStorable.class, m_databaseDocument );
+ storeDoc.storeAsURL( newDocumentURL, new PropertyValue[] { } );
+
+ // connect
+ m_documentUI.connect();
+ assertTrue("could not connect to " + m_database.getDocumentURL(), m_documentUI.isConnected());
+
+ // create a table in the database
+ m_database.createTable(new HsqlTableDescriptor("abc", new HsqlColumnDescriptor[]
+ {
+ new HsqlColumnDescriptor("a", "VARCHAR(50)"),
+ new HsqlColumnDescriptor("b", "VARCHAR(50)"),
+ new HsqlColumnDescriptor("c", "VARCHAR(50)")
+ }));
+
+ // load the old document, and verify there is *no* table therein
+ impl_switchToDocument(oldDocumentURL);
+ m_documentUI.connect();
+ assertTrue("could not connect to " + m_database.getDocumentURL(), m_documentUI.isConnected());
+ XTablesSupplier suppTables = UnoRuntime.queryInterface( XTablesSupplier.class, m_documentUI.getActiveConnection() );
+ XNameAccess tables = suppTables.getTables();
+ assertTrue("the table was created in the wrong database", !tables.hasByName("abc"));
+
+ // load the new document, and verify there *is* a table therein
+ impl_switchToDocument(newDocumentURL);
+ m_documentUI.connect();
+ assertTrue("could not connect to " + m_database.getDocumentURL(), m_documentUI.isConnected());
+
+ suppTables = UnoRuntime.queryInterface( XTablesSupplier.class, m_documentUI.getActiveConnection() );
+ tables = suppTables.getTables();
+ assertTrue("the newly created table has not been written", tables.hasByName("abc"));
+ }
+}
diff --git a/dbaccess/qa/complex/dbaccess/Beamer.java b/dbaccess/qa/complex/dbaccess/Beamer.java
new file mode 100644
index 000000000000..2b77e21b9d60
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/Beamer.java
@@ -0,0 +1,185 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package complex.dbaccess;
+
+import com.sun.star.beans.PropertyState;
+import com.sun.star.beans.PropertyValue;
+import com.sun.star.container.XEnumeration;
+import com.sun.star.container.XEnumerationAccess;
+import com.sun.star.frame.FrameSearchFlag;
+import com.sun.star.frame.XComponentLoader;
+import com.sun.star.frame.XController;
+import com.sun.star.frame.XDispatch;
+import com.sun.star.frame.XDispatchProvider;
+import com.sun.star.frame.XFrame;
+import com.sun.star.frame.XModel;
+import com.sun.star.lang.XComponent;
+import com.sun.star.sdb.CommandType;
+import com.sun.star.uno.Exception;
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.util.URL;
+import com.sun.star.util.XURLTransformer;
+import com.sun.star.view.XSelectionSupplier;
+import java.io.IOException;
+
+
+// ---------- junit imports -----------------
+import org.junit.After;
+// import org.junit.AfterClass;
+import org.junit.Before;
+// import org.junit.BeforeClass;
+import org.junit.Test;
+// import org.openoffice.test.OfficeConnection;
+import static org.junit.Assert.*;
+// ------------------------------------------
+
+
+/** complex test case for Base's application UI
+ */
+public class Beamer extends TestCase
+{
+
+ private XModel docModel;
+
+ public Beamer()
+ {
+ super();
+ }
+
+// // --------------------------------------------------------------------------------------------------------
+// protected final XComponentContext getComponentContext()
+// {
+// XComponentContext context = null;
+// try
+// {
+// final XPropertySet orbProps = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class, getORB());
+// context = (XComponentContext) UnoRuntime.queryInterface(XComponentContext.class,
+// orbProps.getPropertyValue("DefaultContext"));
+// }
+// catch (Exception ex)
+// {
+// failed("could not retrieve the ComponentContext");
+// }
+// return context;
+// }
+ // --------------------------------------------------------------------------------------------------------
+
+// public String[] getTestMethodNames()
+// {
+// return new String[]
+// {
+// "testBeamer"
+// };
+// }
+
+// // --------------------------------------------------------------------------------------------------------
+// public String getTestObjectName()
+// {
+// return getClass().getName();
+// }
+
+ // --------------------------------------------------------------------------------------------------------
+// protected final XMultiServiceFactory getORB()
+// {
+// return (XMultiServiceFactory) param.getMSF();
+// }
+
+ // --------------------------------------------------------------------------------------------------------
+ private void impl_closeDocument()
+ {
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ @Before public void before() throws Exception, java.lang.Exception
+ {
+ // load it into a frame
+ final Object object = getMSF().createInstance("com.sun.star.frame.Desktop");
+ final XComponentLoader xComponentLoader = UnoRuntime.queryInterface(XComponentLoader.class, object);
+ final XComponent loadedComponent = xComponentLoader.loadComponentFromURL("private:factory/swriter", "_blank", 0, new PropertyValue[0]);
+ // get the controller, which provides access to various UI operations
+ docModel = UnoRuntime.queryInterface(XModel.class, loadedComponent);
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ @After public void after()
+ {
+ }
+ // --------------------------------------------------------------------------------------------------------
+
+ @Test public void testBeamer() throws Exception, IOException, java.lang.Exception
+ {
+ final XController controller = docModel.getCurrentController();
+ final XFrame frame = controller.getFrame();
+ final XDispatchProvider dispatchP = UnoRuntime.queryInterface(XDispatchProvider.class, frame);
+ URL command = new URL();
+ // command.Complete = ".component:DB/DataSourceBrowser";
+ command.Complete = ".uno:ViewDataSourceBrowser";
+
+ Object instance = getMSF().createInstance("com.sun.star.util.URLTransformer");
+ XURLTransformer atrans = UnoRuntime.queryInterface(XURLTransformer.class, instance);
+ com.sun.star.util.URL[] aURLA = new com.sun.star.util.URL[1];
+ aURLA[0] = command;
+ atrans.parseStrict(aURLA);
+ command = aURLA[0];
+
+ final XDispatch dispatch = dispatchP.queryDispatch(command, "_self", FrameSearchFlag.AUTO);
+ assertNotNull(dispatch);
+ dispatch.dispatch(command, new PropertyValue[0]);
+
+ final PropertyValue[] props = new PropertyValue[]
+ {
+ new PropertyValue("DataSourceName", 0, "Bibliography", PropertyState.DIRECT_VALUE),
+ new PropertyValue("CommandType", 0, Integer.valueOf(CommandType.TABLE), PropertyState.DIRECT_VALUE),
+ new PropertyValue("Command", 0, "biblio", PropertyState.DIRECT_VALUE)
+ };
+
+ final XFrame beamer = frame.findFrame("_beamer", 0);
+ assertNotNull(beamer);
+ final XEnumerationAccess evtBc = UnoRuntime.queryInterface(XEnumerationAccess.class, getMSF().createInstance("com.sun.star.frame.GlobalEventBroadcaster"));
+ XEnumeration enumeration = evtBc.createEnumeration();
+ int count = -1;
+ while (enumeration.hasMoreElements())
+ {
+ enumeration.nextElement();
+ ++count;
+ }
+ final XSelectionSupplier selSup = UnoRuntime.queryInterface(XSelectionSupplier.class, beamer.getController());
+ selSup.select(props);
+ final com.sun.star.util.XCloseable close = UnoRuntime.queryInterface(com.sun.star.util.XCloseable.class, frame);
+ close.close(false);
+
+ enumeration = evtBc.createEnumeration();
+ int count2 = 0;
+ while (enumeration.hasMoreElements())
+ {
+ enumeration.nextElement();
+ ++count2;
+ }
+
+ assertTrue("count1 = " + count + " count2 = " + count2, count == count2);
+ }
+}
diff --git a/dbaccess/qa/complex/dbaccess/CRMBasedTestCase.java b/dbaccess/qa/complex/dbaccess/CRMBasedTestCase.java
new file mode 100644
index 000000000000..ff89c755a90f
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/CRMBasedTestCase.java
@@ -0,0 +1,91 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package complex.dbaccess;
+
+import com.sun.star.sdb.XSingleSelectQueryComposer;
+import connectivity.tools.CRMDatabase;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+// ---------- junit imports -----------------
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.openoffice.test.OfficeConnection;
+import static org.junit.Assert.*;
+// ------------------------------------------
+
+public abstract class CRMBasedTestCase extends TestCase
+{
+ protected CRMDatabase m_database;
+
+ // --------------------------------------------------------------------------------------------------------
+ protected void createTestCase()
+ {
+ try
+ {
+ m_database = new CRMDatabase( getMSF(), false );
+ }
+ catch ( Exception e )
+ {
+ e.printStackTrace( System.err );
+ fail( "caught an exception (" + e.getMessage() + ") while creating the test case");
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ @Before public void before()
+ {
+ createTestCase();
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ @After public void after()
+ {
+ try
+ {
+ if ( m_database != null )
+ {
+ m_database.saveAndClose();
+ }
+ }
+ catch ( Exception ex )
+ {
+ Logger.getLogger( this.getClass().getName() ).log( Level.SEVERE, null, ex );
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ /** creates a SingleSelectQueryComposer for our connection
+ */
+ protected final XSingleSelectQueryComposer createQueryComposer() throws com.sun.star.uno.Exception
+ {
+ return m_database.getConnection().createSingleSelectQueryComposer();
+ }
+}
diff --git a/dbaccess/qa/complex/dbaccess/CopyTableInterActionHandler.java b/dbaccess/qa/complex/dbaccess/CopyTableInterActionHandler.java
new file mode 100755
index 000000000000..53527e356f78
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/CopyTableInterActionHandler.java
@@ -0,0 +1,50 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package complex.dbaccess;
+
+import com.sun.star.lib.uno.helper.WeakBase;
+import com.sun.star.task.XInteractionHandler;
+import com.sun.star.task.XInteractionRequest;
+
+/**
+ *
+ * @author oj93728
+ */
+class CopyTableInterActionHandler extends WeakBase
+ implements XInteractionHandler
+{
+ private final CopyTableWizard test;
+ public CopyTableInterActionHandler(CopyTableWizard testCase)
+ {
+ test = testCase;
+ }
+
+ public void handle(XInteractionRequest xRequest)
+ {
+ test.assure(xRequest.toString());
+ }
+}
diff --git a/dbaccess/qa/complex/dbaccess/CopyTableWizard.java b/dbaccess/qa/complex/dbaccess/CopyTableWizard.java
new file mode 100755
index 000000000000..89fc56253ed0
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/CopyTableWizard.java
@@ -0,0 +1,244 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package complex.dbaccess;
+
+import com.sun.star.accessibility.XAccessible;
+import com.sun.star.accessibility.XAccessibleContext;
+import com.sun.star.awt.XExtendedToolkit;
+import com.sun.star.awt.XWindow;
+import com.sun.star.beans.Optional;
+import com.sun.star.beans.XPropertySet;
+import com.sun.star.container.XNameAccess;
+import com.sun.star.sdb.CommandType;
+import com.sun.star.sdb.application.XCopyTableWizard;
+import com.sun.star.sdb.DataAccessDescriptorFactory;
+import com.sun.star.sdbc.XConnection;
+import com.sun.star.sdbcx.XTablesSupplier;
+import com.sun.star.task.XInteractionHandler;
+import com.sun.star.uno.Exception;
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.uno.XComponentContext;
+import connectivity.tools.DbaseDatabase;
+import java.io.IOException;
+import util.UITools;
+
+// ---------- junit imports -----------------
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.openoffice.test.OfficeConnection;
+import static org.junit.Assert.*;
+// ------------------------------------------
+
+/** complex test case for Base's application UI
+ */
+public class CopyTableWizard extends CRMBasedTestCase
+{
+
+ private DatabaseApplication source;
+ private DatabaseApplication dest;
+
+ public CopyTableWizard()
+ {
+ super();
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+// public String[] getTestMethodNames()
+// {
+// return new String[]
+// {
+// "copyTable", "copyTableDbase"
+// };
+// }
+
+ // --------------------------------------------------------------------------------------------------------
+// @Override
+// public String getTestObjectName()
+// {
+// return getClass().getName();
+// }
+// --------------------------------------------------------------------------------------------------------
+ // --------------------------------------------------------------------------------------------------------
+
+ @After public void after()
+ {
+ dest.store();
+ super.after();
+ }
+
+ @Before public void before()
+ {
+ try
+ {
+ createTestCase();
+ source = new DatabaseApplication(this.m_database.getDatabase());
+ dest = new DatabaseApplication(new DbaseDatabase(getMSF()));
+ }
+ catch (java.lang.Exception ex)
+ {
+ fail("");
+ }
+ }
+ // --------------------------------------------------------------------------------------------------------
+
+
+
+ class CopyThread implements Runnable
+ {
+
+ final XCopyTableWizard copyWizard;
+
+ public CopyThread(final XCopyTableWizard copyWizard)
+ {
+ this.copyWizard = copyWizard;
+ }
+
+ public void run()
+ {
+ copyWizard.execute();
+ }
+ }
+
+ private XWindow getActiveWindow()
+ {
+ Object toolKit = null;
+ try
+ {
+ toolKit = getMSF().createInstance("com.sun.star.awt.Toolkit");
+ }
+ catch (com.sun.star.uno.Exception e)
+ {
+ return null;
+ }
+
+ XExtendedToolkit tk = (XExtendedToolkit) UnoRuntime.queryInterface(XExtendedToolkit.class, toolKit);
+ Object atw = tk.getActiveTopWindow();
+ return (XWindow) UnoRuntime.queryInterface(XWindow.class, atw);
+ }
+
+ @Test public void copyTable() throws Exception, IOException, java.lang.Exception
+ {
+ copyTable(source,source);
+ }
+
+ @Test public void copyTableDbase() throws Exception, IOException, java.lang.Exception
+ {
+ copyTable(source,dest);
+ }
+ private void copyTable(final DatabaseApplication sourceDb,final DatabaseApplication destDb) throws Exception, IOException, java.lang.Exception
+ {
+ final XConnection destConnection = destDb.getDocumentUI().getActiveConnection();
+
+ final XConnection sourceConnection = sourceDb.getDocumentUI().getActiveConnection();
+ final XTablesSupplier suppTables = UnoRuntime.queryInterface(XTablesSupplier.class, sourceConnection);
+ final XNameAccess tables = suppTables.getTables();
+
+ final String[] names = tables.getElementNames();
+ for (int i = 0; i < names.length; i++)
+ {
+ copyTable(names[i], sourceConnection, destConnection);
+ }
+ }
+
+ public void assure(final String message)
+ {
+ fail(message);
+ }
+
+ private void copyTable(final String tableName, final XConnection sourceConnection, final XConnection destConnection) throws Exception, IOException, java.lang.Exception
+ {
+
+ final XInteractionHandler interAction = new CopyTableInterActionHandler(this);
+ final XComponentContext context = getComponentContext();
+ final XPropertySet sourceDescriptor = DataAccessDescriptorFactory.get(context).createDataAccessDescriptor();
+ sourceDescriptor.setPropertyValue("CommandType", CommandType.TABLE);
+ sourceDescriptor.setPropertyValue("Command", tableName);
+ sourceDescriptor.setPropertyValue("ActiveConnection", sourceConnection);
+
+ final XPropertySet destDescriptor = DataAccessDescriptorFactory.get(context).createDataAccessDescriptor();
+ destDescriptor.setPropertyValue("ActiveConnection", destConnection);
+
+ final XCopyTableWizard copyWizard = com.sun.star.sdb.application.CopyTableWizard.createWithInteractionHandler(context, sourceDescriptor, destDescriptor, interAction);
+ copyWizard.setOperation((short) 0); // com.sun.star.sdb.application.CopyDefinitionAndData
+ Optional<String> auto = new Optional<String>();
+
+ auto.IsPresent = destConnection.getMetaData().supportsCoreSQLGrammar();
+ if (auto.IsPresent)
+ {
+ auto.Value = "ID_test";
+ }
+ copyWizard.setCreatePrimaryKey(auto);
+ Thread thread = new Thread(new CopyThread(copyWizard));
+ thread.start();
+ sleep();
+
+ try
+ {
+ final XWindow dialog = getActiveWindow();
+ final UITools uiTools = new UITools(getMSF(), dialog);
+ final XAccessible root = uiTools.getRoot();
+ final XAccessibleContext accContext = root.getAccessibleContext();
+ final int count = accContext.getAccessibleChildCount();
+ String buttonName = "Create";
+ final XAccessibleContext childContext = accContext.getAccessibleChild(count - 3).getAccessibleContext();
+ final String name = childContext.getAccessibleName();
+ if (name != null && !"".equals(name))
+ {
+ buttonName = name;
+ }
+ try
+ {
+ uiTools.clickButton(buttonName);
+ }
+ catch (java.lang.Exception exception)
+ {
+ exception.printStackTrace();
+ }
+ }
+ catch (com.sun.star.lang.IndexOutOfBoundsException indexOutOfBoundsException)
+ {
+ }
+ sleep();
+
+ thread.join();
+ }
+
+ private void sleep()
+ {
+ try
+ {
+ Thread.sleep(500);
+ }
+ catch (java.lang.InterruptedException e)
+ {
+ }
+ }
+ // --------------------------------------------------------------------------------------------------------
+}
diff --git a/dbaccess/qa/complex/dbaccess/DataSource.java b/dbaccess/qa/complex/dbaccess/DataSource.java
new file mode 100644
index 000000000000..e8f8f7a41d77
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/DataSource.java
@@ -0,0 +1,126 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package complex.dbaccess;
+
+import com.sun.star.container.XNameAccess;
+import com.sun.star.lang.XMultiServiceFactory;
+import com.sun.star.uno.Exception;
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.uno.XNamingService;
+// import complexlib.ComplexTestCase;
+import connectivity.tools.CRMDatabase;
+import connectivity.tools.HsqlDatabase;
+//import java.util.logging.Level;
+//import java.util.logging.Logger;
+
+// ---------- junit imports -----------------
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.openoffice.test.OfficeConnection;
+import static org.junit.Assert.*;
+// ------------------------------------------
+
+
+public class DataSource extends TestCase
+{
+
+ HsqlDatabase m_database;
+ connectivity.tools.DataSource m_dataSource;
+
+ // --------------------------------------------------------------------------------------------------------
+// public String[] getTestMethodNames()
+// {
+// return new String[]
+// {
+// "testRegistrationName"
+// };
+// }
+//
+// // --------------------------------------------------------------------------------------------------------
+// public String getTestObjectName()
+// {
+// return "DataSource";
+// }
+
+ // --------------------------------------------------------------------------------------------------------
+ private void createTestCase()
+ {
+ try
+ {
+ if (m_database == null)
+ {
+ final CRMDatabase database = new CRMDatabase( getMSF(), false );
+ m_database = database.getDatabase();
+ m_dataSource = m_database.getDataSource();
+ }
+ }
+ catch (Exception e)
+ {
+ fail("could not create the test case, error message:\n" + e.getMessage());
+ }
+ catch (java.lang.Exception e)
+ {
+ fail("could not create the test case, error message:\n" + e.getMessage());
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+// private XMultiServiceFactory getFactory()
+// {
+// return (XMultiServiceFactory) param.getMSF();
+// }
+
+ // --------------------------------------------------------------------------------------------------------
+ @Test public void testRegistrationName()
+ {
+ try
+ {
+ createTestCase();
+ // 1. check the existing "Bibliography" data source whether it has the proper name
+ String dataSourceName = "Bibliography";
+ final connectivity.tools.DataSource bibliography = new connectivity.tools.DataSource(getMSF(), dataSourceName);
+ assertEquals("pre-registered database has a wrong name!", dataSourceName, bibliography.getName());
+ // 2. register a newly created data source, and verify it has the proper name
+ dataSourceName = "someDataSource";
+ final XNamingService dataSourceRegistrations = (XNamingService) UnoRuntime.queryInterface(
+ XNamingService.class, getMSF().createInstance("com.sun.star.sdb.DatabaseContext"));
+ final XNameAccess existenceCheck = UnoRuntime.queryInterface( XNameAccess.class, dataSourceRegistrations );
+ if ( existenceCheck.hasByName( "someDataSource" ) )
+ dataSourceRegistrations.revokeObject( "someDataSource" );
+ dataSourceRegistrations.registerObject("someDataSource", m_dataSource.getXDataSource());
+ assertEquals("registration name of a newly registered data source is wrong", dataSourceName, m_dataSource.getName());
+ }
+ catch (Exception ex)
+ {
+ // Logger.getLogger(DataSource.class.getName()).log(Level.SEVERE, null, ex);
+ fail();
+ }
+ }
+}
diff --git a/dbaccess/qa/complex/dbaccess/DatabaseApplication.java b/dbaccess/qa/complex/dbaccess/DatabaseApplication.java
new file mode 100755
index 000000000000..0941bd318d47
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/DatabaseApplication.java
@@ -0,0 +1,98 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package complex.dbaccess;
+
+import com.sun.star.beans.PropertyValue;
+import com.sun.star.frame.FrameSearchFlag;
+import com.sun.star.frame.XComponentLoader;
+import com.sun.star.frame.XModel;
+import com.sun.star.frame.XStorable;
+import com.sun.star.lang.XComponent;
+import com.sun.star.sdb.XOfficeDatabaseDocument;
+import com.sun.star.sdb.application.XDatabaseDocumentUI;
+import com.sun.star.uno.Exception;
+import com.sun.star.uno.UnoRuntime;
+import connectivity.tools.DatabaseAccess;
+
+/**
+ *
+ * @author oj93728
+ */
+public class DatabaseApplication
+{
+
+ private final XOfficeDatabaseDocument databaseDocument;
+ private final XDatabaseDocumentUI documentUI;
+ private final DatabaseAccess db;
+
+ public DatabaseApplication(final DatabaseAccess _db) throws Exception
+ {
+ db = _db;
+ databaseDocument = db.getDatabaseDocument();
+
+ // load it into a frame
+ final Object object = db.getORB().createInstance("com.sun.star.frame.Desktop");
+ final XComponentLoader xComponentLoader = UnoRuntime.queryInterface(XComponentLoader.class, object);
+ final XComponent loadedComponent = xComponentLoader.loadComponentFromURL(db.getDocumentURL(), "_blank", FrameSearchFlag.ALL, new PropertyValue[0]);
+
+ // get the controller, which provides access to various UI operations
+ final XModel docModel = UnoRuntime.queryInterface(XModel.class, loadedComponent);
+ documentUI = UnoRuntime.queryInterface(XDatabaseDocumentUI.class, docModel.getCurrentController());
+ documentUI.connect();
+ }
+
+ public XOfficeDatabaseDocument getDatabaseDocument()
+ {
+ return databaseDocument;
+ }
+
+ public XDatabaseDocumentUI getDocumentUI()
+ {
+ return documentUI;
+ }
+
+ public DatabaseAccess getDb()
+ {
+ return db;
+ }
+
+ public void store()
+ {
+ // store the doc in a new location
+ try
+ {
+ final XStorable storeDoc = UnoRuntime.queryInterface(XStorable.class, databaseDocument);
+ if (storeDoc != null)
+ {
+ storeDoc.store();
+ }
+ }
+ catch (com.sun.star.io.IOException iOException)
+ {
+ }
+ }
+}
diff --git a/dbaccess/qa/complex/dbaccess/DatabaseDocument.java b/dbaccess/qa/complex/dbaccess/DatabaseDocument.java
new file mode 100644
index 000000000000..757ae2de22d5
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/DatabaseDocument.java
@@ -0,0 +1,1009 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package complex.dbaccess;
+
+import com.sun.star.awt.XTopWindow;
+import com.sun.star.beans.PropertyState;
+import com.sun.star.document.DocumentEvent;
+import com.sun.star.lang.XEventListener;
+import com.sun.star.lang.XMultiServiceFactory;
+import com.sun.star.script.XStorageBasedLibraryContainer;
+import com.sun.star.task.XInteractionRequest;
+
+import com.sun.star.uno.Type;
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.frame.XStorable;
+import com.sun.star.beans.PropertyValue;
+import com.sun.star.beans.XPropertySet;
+import com.sun.star.container.XNameContainer;
+import com.sun.star.container.XSet;
+import com.sun.star.document.XDocumentEventBroadcaster;
+import com.sun.star.document.XDocumentEventListener;
+import com.sun.star.document.XEmbeddedScripts;
+import com.sun.star.document.XEventsSupplier;
+import com.sun.star.lang.XComponent;
+import com.sun.star.frame.XComponentLoader;
+import com.sun.star.frame.XDispatch;
+import com.sun.star.frame.XDispatchProvider;
+import com.sun.star.frame.XFrame;
+import com.sun.star.frame.XLoadable;
+import com.sun.star.frame.XModel;
+import com.sun.star.frame.XModel2;
+import com.sun.star.frame.XTitle;
+import com.sun.star.lang.EventObject;
+import com.sun.star.lang.XServiceInfo;
+import com.sun.star.lang.XSingleComponentFactory;
+import com.sun.star.lang.XTypeProvider;
+import com.sun.star.script.provider.XScriptProviderSupplier;
+import com.sun.star.sdb.XDocumentDataSource;
+
+import com.sun.star.sdb.XFormDocumentsSupplier;
+import com.sun.star.sdb.XOfficeDatabaseDocument;
+import com.sun.star.sdb.XReportDocumentsSupplier;
+import com.sun.star.task.DocumentMacroConfirmationRequest;
+import com.sun.star.task.XInteractionApprove;
+import com.sun.star.task.XInteractionContinuation;
+import com.sun.star.task.XInteractionHandler;
+import com.sun.star.uno.XComponentContext;
+import com.sun.star.util.CloseVetoException;
+import com.sun.star.util.URL;
+import com.sun.star.util.XChangesBatch;
+import com.sun.star.util.XCloseable;
+import com.sun.star.util.XModifiable;
+import com.sun.star.util.XURLTransformer;
+import java.io.IOException;
+import java.util.Iterator;
+import java.util.ArrayList;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+// ---------- junit imports -----------------
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.openoffice.test.OfficeConnection;
+import static org.junit.Assert.*;
+// ------------------------------------------
+
+public class DatabaseDocument extends TestCase implements com.sun.star.document.XDocumentEventListener
+{
+
+ private static final String _BLANK = "_blank";
+ private XComponent m_callbackFactory = null;
+ private final ArrayList m_documentEvents = new ArrayList();
+ private final ArrayList m_globalEvents = new ArrayList();
+ // for those states, see testDocumentEvents
+ private static short STATE_NOT_STARTED = 0;
+ private static short STATE_LOADING_DOC = 1;
+ private static short STATE_MACRO_EXEC_APPROVED = 2;
+ private static short STATE_ON_LOAD_RECEIVED = 3;
+ private short m_loadDocState = STATE_NOT_STARTED;
+
+ // ========================================================================================================
+ /** a helper class which can be used by the Basic scripts in our test documents
+ * to notify us of events in this document
+ */
+ private class CallbackComponent implements XDocumentEventListener, XTypeProvider
+ {
+
+ public void documentEventOccured(DocumentEvent _event)
+ {
+ onDocumentEvent(_event);
+ }
+
+ public void disposing(com.sun.star.lang.EventObject _Event)
+ {
+ // not interested in
+ }
+
+ public Type[] getTypes()
+ {
+ final Class interfaces[] = getClass().getInterfaces();
+ Type types[] = new Type[interfaces.length];
+ for (int i = 0; i < interfaces.length; ++i)
+ {
+ types[i] = new Type(interfaces[i]);
+ }
+ return types;
+ }
+
+ public byte[] getImplementationId()
+ {
+ return getClass().toString().getBytes();
+ }
+ };
+
+ // ========================================================================================================
+ private static String getCallbackComponentServiceName()
+ {
+ return "org.openoffice.complex.dbaccess.EventCallback";
+ }
+
+ // ========================================================================================================
+ /** a factory for a CallbackComponent
+ */
+ private class CallbackComponentFactory implements XSingleComponentFactory, XServiceInfo, XComponent
+ {
+
+ private final ArrayList m_eventListeners = new ArrayList();
+
+ public Object createInstanceWithContext(XComponentContext _context) throws com.sun.star.uno.Exception
+ {
+ return new CallbackComponent();
+ }
+
+ public Object createInstanceWithArgumentsAndContext(Object[] arg0, XComponentContext _context) throws com.sun.star.uno.Exception
+ {
+ return createInstanceWithContext(_context);
+ }
+
+ public String getImplementationName()
+ {
+ return "org.openoffice.complex.dbaccess.CallbackComponent";
+ }
+
+ public boolean supportsService(String _service)
+ {
+ return _service.equals(getCallbackComponentServiceName());
+ }
+
+ public String[] getSupportedServiceNames()
+ {
+ return new String[]
+ {
+ getCallbackComponentServiceName()
+ };
+ }
+
+ public void dispose()
+ {
+ final EventObject event = new EventObject(this);
+
+ final ArrayList eventListenersCopy = (ArrayList) m_eventListeners.clone();
+ final Iterator iter = eventListenersCopy.iterator();
+ while (iter.hasNext())
+ {
+ ((XEventListener) iter.next()).disposing(event);
+ }
+ }
+
+ public void addEventListener(XEventListener _listener)
+ {
+ if (_listener != null)
+ {
+ m_eventListeners.add(_listener);
+ }
+ }
+
+ public void removeEventListener(XEventListener _listener)
+ {
+ m_eventListeners.remove(_listener);
+ }
+ };
+
+ // ========================================================================================================
+ private class MacroExecutionApprove implements XInteractionHandler
+ {
+
+ private XInteractionHandler m_defaultHandler = null;
+
+ MacroExecutionApprove(XMultiServiceFactory _factory)
+ {
+ try
+ {
+ m_defaultHandler = UnoRuntime.queryInterface(XInteractionHandler.class, _factory.createInstance("com.sun.star.task.InteractionHandler"));
+ }
+ catch (Exception ex)
+ {
+ Logger.getLogger(DatabaseDocument.class.getName()).log(Level.SEVERE, null, ex);
+ }
+ }
+
+ public void handle(XInteractionRequest _request)
+ {
+ final Object request = _request.getRequest();
+ if (!(request instanceof DocumentMacroConfirmationRequest) && (m_defaultHandler != null))
+ {
+ m_defaultHandler.handle(_request);
+ return;
+ }
+
+ assertEquals("interaction handleer called in wrong state", STATE_LOADING_DOC, m_loadDocState);
+
+ // auto-approve
+ final XInteractionContinuation continuations[] = _request.getContinuations();
+ for (int i = 0; i < continuations.length; ++i)
+ {
+ final XInteractionApprove approve = UnoRuntime.queryInterface(XInteractionApprove.class, continuations[i]);
+ if (approve != null)
+ {
+ approve.select();
+ m_loadDocState = STATE_MACRO_EXEC_APPROVED;
+ break;
+ }
+ }
+ }
+ };
+
+ // ========================================================================================================
+ // --------------------------------------------------------------------------------------------------------
+// public String[] getTestMethodNames()
+// {
+// return new String[]
+// {
+// "testLoadable",
+// "testDocumentRevenants",
+// "testDocumentEvents",
+// "testGlobalEvents"
+// };
+// }
+//
+// // --------------------------------------------------------------------------------------------------------
+// public String getTestObjectName()
+// {
+// return "DatabaseDocument";
+// }
+
+ // --------------------------------------------------------------------------------------------------------
+ @Before public void before() throws java.lang.Exception
+ {
+ super.before();
+
+ try
+ {
+ // at our service factory, insert a new factory for our CallbackComponent
+ // this will allow the Basic code in our test documents to call back into this test case
+ // here, by just instantiating this service
+ final XSet globalFactory = UnoRuntime.queryInterface(XSet.class, getMSF());
+ m_callbackFactory = new CallbackComponentFactory();
+ globalFactory.insert(m_callbackFactory);
+
+ // register ourself as listener at the global event broadcaster
+ final XDocumentEventBroadcaster broadcaster = UnoRuntime.queryInterface(XDocumentEventBroadcaster.class, getMSF().createInstance("com.sun.star.frame.GlobalEventBroadcaster"));
+ broadcaster.addDocumentEventListener(this);
+ }
+ catch (Exception e)
+ {
+ System.out.println("could not create the test case, error message:\n" + e.getMessage());
+ e.printStackTrace(System.err);
+ fail("failed to create the test case");
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ @After public void after() throws java.lang.Exception
+ {
+ try
+ {
+ // dispose our callback factory. This will automatically remove it from our service
+ // factory
+ m_callbackFactory.dispose();
+
+ // revoke ourself as listener at the global event broadcaster
+ final XDocumentEventBroadcaster broadcaster = UnoRuntime.queryInterface(XDocumentEventBroadcaster.class, getMSF().createInstance("com.sun.star.frame.GlobalEventBroadcaster"));
+ broadcaster.removeDocumentEventListener(this);
+ }
+ catch (Exception e)
+ {
+ System.out.println("could not create the test case, error message:\n" + e.getMessage());
+ e.printStackTrace(System.err);
+ fail("failed to close the test case");
+ }
+
+ super.after();
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private static class UnoMethodDescriptor
+ {
+
+ public Class unoInterfaceClass = null;
+ public String methodName = null;
+
+ public UnoMethodDescriptor(Class _class, String _method)
+ {
+ unoInterfaceClass = _class;
+ methodName = _method;
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private void impl_checkDocumentInitState(Object _document, boolean _isInitialized)
+ {
+ // things you cannot do with an uninitialized document:
+ final UnoMethodDescriptor[] unsupportedMethods = new UnoMethodDescriptor[]
+ {
+ new UnoMethodDescriptor(XStorable.class, "store"),
+ new UnoMethodDescriptor(XFormDocumentsSupplier.class, "getFormDocuments"),
+ new UnoMethodDescriptor(XReportDocumentsSupplier.class, "getReportDocuments"),
+ new UnoMethodDescriptor(XScriptProviderSupplier.class, "getScriptProvider"),
+ new UnoMethodDescriptor(XEventsSupplier.class, "getEvents"),
+ new UnoMethodDescriptor(XTitle.class, "getTitle"),
+ new UnoMethodDescriptor(XModel2.class, "getControllers")
+ // (there's much more than this, but we cannot list all methods here, can we ...)
+ };
+
+ for (int i = 0; i < unsupportedMethods.length; ++i)
+ {
+// assureException( _document, unsupportedMethods[i].unoInterfaceClass,
+// unsupportedMethods[i].methodName, new Object[]{}, _isInitialized ? null : NotInitializedException.class );
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private XModel impl_createDocument() throws Exception
+ {
+ final XModel databaseDoc = UnoRuntime.queryInterface(XModel.class, getMSF().createInstance("com.sun.star.sdb.OfficeDatabaseDocument"));
+
+ // should not be initialized here - we did neither initNew nor load nor storeAsURL it
+ impl_checkDocumentInitState(databaseDoc, false);
+
+ return databaseDoc;
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private void impl_closeDocument(XModel _databaseDoc) throws CloseVetoException, IOException, Exception
+ {
+ final XCloseable closeDoc = UnoRuntime.queryInterface(XCloseable.class, _databaseDoc);
+ closeDoc.close(true);
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private XModel impl_createEmptyEmbeddedHSQLDocument() throws Exception, IOException
+ {
+ final XModel databaseDoc = UnoRuntime.queryInterface(XModel.class, getMSF().createInstance("com.sun.star.sdb.OfficeDatabaseDocument"));
+ final XStorable storeDoc = UnoRuntime.queryInterface(XStorable.class, databaseDoc);
+
+ // verify the document rejects API calls which require it to be initialized
+ impl_checkDocumentInitState(databaseDoc, false);
+
+ // though the document is not initialized, you can ask for the location, the URL, and the args
+ final String location = storeDoc.getLocation();
+ final String url = databaseDoc.getURL();
+ final PropertyValue[] args = databaseDoc.getArgs();
+ // they should be all empty at this time
+ assertEquals("location is expected to be empty here", "", location);
+ assertEquals("URL is expected to be empty here", "", url);
+ assertEquals("Args are expected to be empty here", 0, args.length);
+
+ // and, you should be able to set properties at the data source
+ final XOfficeDatabaseDocument dataSourceAccess = UnoRuntime.queryInterface(XOfficeDatabaseDocument.class, databaseDoc);
+ final XPropertySet dsProperties = UnoRuntime.queryInterface(XPropertySet.class, dataSourceAccess.getDataSource());
+ dsProperties.setPropertyValue("URL", "sdbc:embedded:hsqldb");
+
+ final String documentURL = createTempFileURL();
+ storeDoc.storeAsURL(documentURL, new PropertyValue[0]);
+
+ // now that the document is stored, ...
+ // ... its URL should be correct
+ assertEquals("wrong URL after storing the document", documentURL, databaseDoc.getURL());
+ // ... it should be initialized
+ impl_checkDocumentInitState(databaseDoc, true);
+
+ return databaseDoc;
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ @Test public void testLoadable() throws Exception, IOException
+ {
+ XModel databaseDoc = impl_createEmptyEmbeddedHSQLDocument();
+ String documentURL = databaseDoc.getURL();
+
+ // there's three methods how you can initialize a database document:
+
+ // ....................................................................
+ // 1. XStorable::storeAsURL
+ // (this is for compatibility reasons, to not break existing code)
+ // this test is already made in impl_createEmptyEmbeddedHSQLDocument
+
+ // ....................................................................
+ // 2. XLoadable::load
+ databaseDoc = UnoRuntime.queryInterface(XModel.class, getMSF().createInstance("com.sun.star.sdb.OfficeDatabaseDocument"));
+ documentURL = copyToTempFile(documentURL);
+ // load the doc, and verify it's initialized then, and has the proper URL
+ XLoadable loadDoc = UnoRuntime.queryInterface(XLoadable.class, databaseDoc);
+ loadDoc.load(new PropertyValue[]
+ {
+ new PropertyValue("URL", 0, documentURL, PropertyState.DIRECT_VALUE)
+ });
+ databaseDoc.attachResource(documentURL, new PropertyValue[0]);
+
+ assertEquals("wrong URL after loading the document", documentURL, databaseDoc.getURL());
+ impl_checkDocumentInitState(databaseDoc, true);
+
+ // and while we are here ... initilizing the same document again should not be possible
+// assureException( databaseDoc, XLoadable.class, "initNew", new Object[0],
+// DoubleInitializationException.class );
+// assureException( databaseDoc, XLoadable.class, "load", new Object[] { new PropertyValue[0] },
+// DoubleInitializationException.class );
+
+ // ....................................................................
+ // 3. XLoadable::initNew
+ impl_closeDocument(databaseDoc);
+ databaseDoc = impl_createDocument();
+ loadDoc = UnoRuntime.queryInterface(XLoadable.class, databaseDoc);
+ loadDoc.initNew();
+ assertEquals("wrong URL after initializing the document", "", databaseDoc.getURL());
+ impl_checkDocumentInitState(databaseDoc, true);
+
+ // same as above - initializing the document a second time must fail
+// assureException( databaseDoc, XLoadable.class, "initNew", new Object[0],
+// DoubleInitializationException.class );
+// assureException( databaseDoc, XLoadable.class, "load", new Object[] { new PropertyValue[0] },
+// DoubleInitializationException.class );
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private PropertyValue[] impl_getMarkerLoadArgs()
+ {
+ return new PropertyValue[]
+ {
+ new PropertyValue( "PickListEntry", 0, false, PropertyState.DIRECT_VALUE ),
+ new PropertyValue( "TestCase_Marker", 0, "Yes", PropertyState.DIRECT_VALUE )
+ };
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private boolean impl_hasMarker( final PropertyValue[] _args )
+ {
+ for ( int i=0; i<_args.length; ++i )
+ {
+ if ( _args[i].Name.equals( "TestCase_Marker" ) && _args[i].Value.equals( "Yes" ) )
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private PropertyValue[] impl_getDefaultLoadArgs()
+ {
+ return new PropertyValue[]
+ {
+ new PropertyValue("PickListEntry", 0, false, PropertyState.DIRECT_VALUE)
+ };
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private PropertyValue[] impl_getMacroExecLoadArgs()
+ {
+ return new PropertyValue[]
+ {
+ new PropertyValue("PickListEntry", 0, false, PropertyState.DIRECT_VALUE),
+ new PropertyValue("MacroExecutionMode", 0, com.sun.star.document.MacroExecMode.USE_CONFIG, PropertyState.DIRECT_VALUE),
+ new PropertyValue("InteractionHandler", 0, new MacroExecutionApprove(getMSF()), PropertyState.DIRECT_VALUE)
+ };
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private int impl_setMacroSecurityLevel(int _level) throws Exception
+ {
+ final XMultiServiceFactory configProvider = UnoRuntime.queryInterface(XMultiServiceFactory.class, getMSF().createInstance("com.sun.star.configuration.ConfigurationProvider"));
+
+ final PropertyValue[] args = new PropertyValue[]
+ {
+ new PropertyValue("nodepath", 0, "/org.openoffice.Office.Common/Security/Scripting", PropertyState.DIRECT_VALUE)
+ };
+
+ final XPropertySet securitySettings = UnoRuntime.queryInterface(XPropertySet.class, configProvider.createInstanceWithArguments("com.sun.star.configuration.ConfigurationUpdateAccess", args));
+ final int oldValue = ((Integer) securitySettings.getPropertyValue("MacroSecurityLevel")).intValue();
+ securitySettings.setPropertyValue("MacroSecurityLevel", Integer.valueOf(_level));
+
+ final XChangesBatch committer = UnoRuntime.queryInterface(XChangesBatch.class, securitySettings);
+ committer.commitChanges();
+
+ return oldValue;
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private XModel impl_loadDocument( final String _documentURL, final PropertyValue[] _loadArgs ) throws Exception
+ {
+ final XComponentLoader loader = UnoRuntime.queryInterface(XComponentLoader.class, getMSF().createInstance("com.sun.star.frame.Desktop"));
+ return UnoRuntime.queryInterface(XModel.class, loader.loadComponentFromURL(_documentURL, _BLANK, 0, _loadArgs));
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private void impl_storeDocument( final XModel _document ) throws Exception, IOException
+ {
+ // store the document
+ final String documentURL = FileHelper.getOOoCompatibleFileURL( _document.getURL() );
+ final XStorable storeDoc = UnoRuntime.queryInterface(XStorable.class, _document);
+ storeDoc.store();
+
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private XModel impl_createDocWithMacro( final String _libName, final String _moduleName, final String _code ) throws Exception, IOException
+ {
+ // create an empty document
+ XModel databaseDoc = impl_createEmptyEmbeddedHSQLDocument();
+
+ // create Basic library/module therein
+ final XEmbeddedScripts embeddedScripts = UnoRuntime.queryInterface(XEmbeddedScripts.class, databaseDoc);
+ final XStorageBasedLibraryContainer basicLibs = embeddedScripts.getBasicLibraries();
+ final XNameContainer newLib = basicLibs.createLibrary( _libName );
+ newLib.insertByName( _moduleName, _code );
+
+ return databaseDoc;
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ /** tests various aspects of database document "revenants"
+ *
+ * Well, I do not really have a good term for this ... The point is, database documents are in real
+ * only *one* aspect of a more complex thing. The second aspect is a data source. Both, in some sense,
+ * just represent different views on the same thing. For a given database, there's at each time at most
+ * one data source, and at most one database document. Both have a independent life time, and are
+ * created when needed.
+ * In particular, a document can be closed (this is what happens when the last UI window displaying
+ * this document is closed), and then dies. Now when the other "view", the data source, still exists,
+ * the the underlying document data is not discarded, but kept alive (else the data source would die
+ * just because the document dies, which is not desired). If the document is loaded, again, then
+ * it is re-created, using the data of its previous "incarnation".
+ *
+ * This method here tests some of those aspects of a document which should survive the death of one
+ * instance and re-creation as a revenant.
+ */
+ @Test public void testDocumentRevenants() throws Exception, IOException
+ {
+ // create an empty document
+ XModel databaseDoc = impl_createDocWithMacro( "Lib", "Module",
+ "Sub Hello\n" +
+ " MsgBox \"Hello\"\n" +
+ "End Sub\n"
+ );
+ impl_storeDocument( databaseDoc );
+ final String documentURL = databaseDoc.getURL();
+
+ // at this stage, the marker should not yet be present in the doc's args, else some of the below
+ // tests become meaningless
+ assertTrue( "A newly created doc should not have the test case marker", !impl_hasMarker( databaseDoc.getArgs() ) );
+
+ // obtain the DataSource associated with the document. Keeping this alive
+ // ensures that the "impl data" of the document is kept alive, too, so when closing
+ // and re-opening it, this "impl data" must be re-used.
+ XDocumentDataSource dataSource = UnoRuntime.queryInterface(XDocumentDataSource.class, (UnoRuntime.queryInterface(XOfficeDatabaseDocument.class, databaseDoc)).getDataSource());
+
+ // close and reload the doc
+ impl_closeDocument(databaseDoc);
+ databaseDoc = impl_loadDocument( documentURL, impl_getMarkerLoadArgs() );
+ // since we just put the marker into the load-call, it should be present at the doc
+ assertTrue( "The test case marker got lost.", impl_hasMarker( databaseDoc.getArgs() ) );
+
+ // The basic library should have survived
+ final XEmbeddedScripts embeddedScripts = UnoRuntime.queryInterface(XEmbeddedScripts.class, databaseDoc);
+ final XStorageBasedLibraryContainer basicLibs = embeddedScripts.getBasicLibraries();
+ assertTrue( "Baisc lib did not survive reloading a closed document", basicLibs.hasByName( "Lib" ) );
+ final XNameContainer lib = UnoRuntime.queryInterface(XNameContainer.class, basicLibs.getByName("Lib"));
+ assertTrue( "Basic module did not survive reloading a closed document", lib.hasByName( "Module" ) );
+
+ // now closing the doc, and obtaining it from the data source, should preserve the marker we put into the load
+ // args
+ impl_closeDocument( databaseDoc );
+ databaseDoc = UnoRuntime.queryInterface(XModel.class, dataSource.getDatabaseDocument());
+ assertTrue( "The test case marker did not survive re-retrieval of the doc from the data source.",
+ impl_hasMarker( databaseDoc.getArgs() ) );
+
+ // on the other hand, closing and regurlarly re-loading the doc *without* the marker should indeed
+ // lose it
+ impl_closeDocument( databaseDoc );
+ databaseDoc = impl_loadDocument( documentURL, impl_getDefaultLoadArgs() );
+ assertTrue( "Reloading the document kept the old args, instead of the newly supplied ones.",
+ !impl_hasMarker( databaseDoc.getArgs() ) );
+
+ // clean up
+ impl_closeDocument( databaseDoc );
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ @Test public void testDocumentEvents() throws Exception, IOException
+ {
+ // create an empty document
+ final String libName = "EventHandlers";
+ final String moduleName = "all";
+ final String eventHandlerCode =
+ "Option Explicit\n" +
+ "\n" +
+ "Sub OnLoad\n" +
+ " Dim oCallback as Object\n" +
+ " oCallback = createUnoService( \"" + getCallbackComponentServiceName() + "\" )\n" +
+ "\n" +
+ " ' as long as the Document is not passed to the Basic callbacks, we need to create\n" +
+ " ' one ourself\n" +
+ " Dim oEvent as new com.sun.star.document.DocumentEvent\n" +
+ " oEvent.EventName = \"OnLoad\"\n" +
+ " oEvent.Source = ThisComponent\n" +
+ "\n" +
+ " oCallback.documentEventOccured( oEvent )\n" +
+ "End Sub\n";
+ XModel databaseDoc = impl_createDocWithMacro( libName, moduleName, eventHandlerCode );
+ final String documentURL = databaseDoc.getURL();
+
+ // bind the macro to the OnLoad event
+ final String macroURI = "vnd.sun.star.script:" + libName + "." + moduleName + ".OnLoad?language=Basic&location=document";
+ final XEventsSupplier eventsSupplier = UnoRuntime.queryInterface(XEventsSupplier.class, databaseDoc);
+ eventsSupplier.getEvents().replaceByName("OnLoad", new PropertyValue[]
+ {
+ new PropertyValue("EventType", 0, "Script", PropertyState.DIRECT_VALUE),
+ new PropertyValue("Script", 0, macroURI, PropertyState.DIRECT_VALUE)
+ });
+
+ // store the document, and close it
+ impl_storeDocument( databaseDoc );
+ impl_closeDocument( databaseDoc );
+
+ // ensure the macro security configuration is "ask the user for document macro execution"
+ final int oldSecurityLevel = impl_setMacroSecurityLevel(1);
+
+ // load it, again
+ m_loadDocState = STATE_LOADING_DOC;
+ // expected order of states is:
+ // STATE_LOADING_DOC - initialized here
+ // STATE_MACRO_EXEC_APPROVED - done in our interaction handler, which auto-approves the execution of macros
+ // STATE_ON_LOAD_RECEIVED - done in our callback for the document events
+ //
+ // In particular, it is important that the interaction handler (which plays the role of the user confirmation
+ // here) is called before the OnLoad notification is received - since the latter happens from within
+ // a Basic macro which is bound to the OnLoad event of the document.
+
+ final String context = "OnLoad";
+ impl_startObservingEvents(context);
+ databaseDoc = impl_loadDocument( documentURL, impl_getMacroExecLoadArgs() );
+ impl_stopObservingEvents(m_documentEvents, new String[]
+ {
+ "OnLoad"
+ }, context);
+
+ assertEquals("our provided interaction handler was not called", STATE_ON_LOAD_RECEIVED, m_loadDocState);
+
+ // restore macro security level
+ impl_setMacroSecurityLevel(oldSecurityLevel);
+
+ // close the document
+ impl_closeDocument(databaseDoc);
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ @Test public void testGlobalEvents() throws Exception, IOException
+ {
+ XModel databaseDoc = impl_createEmptyEmbeddedHSQLDocument();
+ final XStorable storeDoc = UnoRuntime.queryInterface(XStorable.class, databaseDoc);
+
+ String context, newURL;
+
+ // XStorable.store
+ final String oldURL = databaseDoc.getURL();
+ context = "store";
+ impl_startObservingEvents(context);
+ storeDoc.store();
+ assertEquals("store is not expected to change the document URL", databaseDoc.getURL(), oldURL);
+ impl_stopObservingEvents(m_globalEvents, new String[]
+ {
+ "OnSave", "OnSaveDone"
+ }, context);
+
+ // XStorable.storeToURL
+ context = "storeToURL";
+ impl_startObservingEvents(context);
+ storeDoc.storeToURL(createTempFileURL(), new PropertyValue[0]);
+ assertEquals("storetoURL is not expected to change the document URL", databaseDoc.getURL(), oldURL);
+ impl_stopObservingEvents(m_globalEvents, new String[]
+ {
+ "OnSaveTo", "OnSaveToDone"
+ }, context);
+
+ // XStorable.storeAsURL
+ newURL = createTempFileURL();
+ context = "storeAsURL";
+ impl_startObservingEvents(context);
+ storeDoc.storeAsURL(newURL, new PropertyValue[0]);
+ assertEquals("storeAsURL is expected to change the document URL", databaseDoc.getURL(), newURL);
+ impl_stopObservingEvents(m_globalEvents, new String[]
+ {
+ "OnSaveAs", "OnSaveAsDone"
+ }, context);
+
+ // XModifiable.setModified
+ final XModifiable modifyDoc = UnoRuntime.queryInterface(XModifiable.class, databaseDoc);
+ context = "setModified";
+ impl_startObservingEvents(context);
+ modifyDoc.setModified(true);
+ assertEquals("setModified didn't work", modifyDoc.isModified(), true);
+ impl_stopObservingEvents(m_globalEvents, new String[]
+ {
+ "OnModifyChanged"
+ }, context);
+
+ // XStorable.store, with implicit reset of the "Modified" flag
+ context = "store (2)";
+ impl_startObservingEvents(context);
+ storeDoc.store();
+ assertEquals("'store' should implicitly reset the modified flag", modifyDoc.isModified(), false);
+ impl_stopObservingEvents(m_globalEvents, new String[]
+ {
+ "OnSave", "OnSaveDone", "OnModifyChanged"
+ }, context);
+
+ // XComponentLoader.loadComponentFromURL
+ newURL = copyToTempFile(databaseDoc.getURL());
+ final XComponentLoader loader = UnoRuntime.queryInterface(XComponentLoader.class, getMSF().createInstance("com.sun.star.frame.Desktop"));
+ context = "loadComponentFromURL";
+ impl_startObservingEvents(context);
+ databaseDoc = UnoRuntime.queryInterface(XModel.class, loader.loadComponentFromURL(newURL, _BLANK, 0, impl_getDefaultLoadArgs()));
+ impl_stopObservingEvents(m_globalEvents,
+ new String[]
+ {
+ "OnLoadFinished", "OnViewCreated", "OnFocus", "OnLoad"
+ }, context);
+
+ // closing a document by API
+ final XCloseable closeDoc = UnoRuntime.queryInterface(XCloseable.class, databaseDoc);
+ context = "close (API)";
+ impl_startObservingEvents(context);
+ closeDoc.close(true);
+ impl_stopObservingEvents(m_globalEvents,
+ new String[]
+ {
+ "OnPrepareUnload", "OnViewClosed", "OnUnload"
+ }, context);
+
+ // closing a document via UI
+ context = "close (UI)";
+ impl_startObservingEvents("prepare for '" + context + "'");
+ databaseDoc = UnoRuntime.queryInterface(XModel.class, loader.loadComponentFromURL(newURL, _BLANK, 0, impl_getDefaultLoadArgs()));
+ impl_waitForEvent(m_globalEvents, "OnLoad", 5000);
+ // wait for all events to arrive - OnLoad should be the last one
+
+ final XDispatchProvider dispatchProvider = UnoRuntime.queryInterface(XDispatchProvider.class, databaseDoc.getCurrentController().getFrame());
+ final URL url = impl_getURL(".uno:CloseDoc");
+ final XDispatch dispatcher = dispatchProvider.queryDispatch(url, "", 0);
+ impl_startObservingEvents(context);
+ dispatcher.dispatch(url, new PropertyValue[0]);
+ impl_stopObservingEvents(m_globalEvents,
+ new String[]
+ {
+ "OnPrepareViewClosing", "OnViewClosed", "OnPrepareUnload", "OnUnload"
+ }, context);
+
+ // creating a new document
+ databaseDoc = impl_createDocument();
+ final XLoadable loadDoc = UnoRuntime.queryInterface(XLoadable.class, databaseDoc);
+ context = "initNew";
+ impl_startObservingEvents(context);
+ loadDoc.initNew();
+ impl_stopObservingEvents(m_globalEvents, new String[]
+ {
+ "OnCreate"
+ }, context);
+
+ impl_startObservingEvents(context + " (cleanup)");
+ impl_closeDocument(databaseDoc);
+ impl_waitForEvent(m_globalEvents, "OnUnload", 5000);
+
+ // focus changes
+ context = "activation";
+ // for this, load a database document ...
+ impl_startObservingEvents("prepare for '" + context + "'");
+ databaseDoc = UnoRuntime.queryInterface(XModel.class, loader.loadComponentFromURL(newURL, _BLANK, 0, impl_getDefaultLoadArgs()));
+ final int previousOnLoadEventPos = impl_waitForEvent(m_globalEvents, "OnLoad", 5000);
+ // ... and another document ...
+ final String otherURL = copyToTempFile(databaseDoc.getURL());
+ final XModel otherDoc = UnoRuntime.queryInterface(XModel.class, loader.loadComponentFromURL(otherURL, _BLANK, 0, impl_getDefaultLoadArgs()));
+ impl_raise(otherDoc);
+ impl_waitForEvent(m_globalEvents, "OnLoad", 5000, previousOnLoadEventPos + 1);
+
+ // ... and switch between the two
+ impl_startObservingEvents(context);
+ impl_raise(databaseDoc);
+ impl_stopObservingEvents(m_globalEvents, new String[]
+ {
+ "OnUnfocus", "OnFocus"
+ }, context);
+
+ // cleanup
+ impl_startObservingEvents("cleanup after '" + context + "'");
+ impl_closeDocument(databaseDoc);
+ impl_closeDocument(otherDoc);
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private URL impl_getURL(String _completeURL) throws Exception
+ {
+ final URL[] url =
+ {
+ new URL()
+ };
+ url[0].Complete = _completeURL;
+ final XURLTransformer urlTransformer = UnoRuntime.queryInterface(XURLTransformer.class, getMSF().createInstance("com.sun.star.util.URLTransformer"));
+ urlTransformer.parseStrict(url);
+ return url[0];
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private void impl_raise(XModel _document)
+ {
+ final XFrame frame = _document.getCurrentController().getFrame();
+ final XTopWindow topWindow = UnoRuntime.queryInterface(XTopWindow.class, frame.getContainerWindow());
+ topWindow.toFront();
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private void impl_startObservingEvents(String _context)
+ {
+ System.out.println(" " + _context + " {");
+ synchronized (m_documentEvents)
+ {
+ m_documentEvents.clear();
+ }
+ synchronized (m_globalEvents)
+ {
+ m_globalEvents.clear();
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private void impl_stopObservingEvents(ArrayList _actualEvents, String[] _expectedEvents, String _context)
+ {
+ try
+ {
+ synchronized (_actualEvents)
+ {
+ int actualEventCount = _actualEvents.size();
+ while (actualEventCount < _expectedEvents.length)
+ {
+ // well, it's possible not all events already arrived, yet - finally, some of them
+ // are notified asynchronously
+ // So, wait a few seconds.
+ try
+ {
+ _actualEvents.wait(20000);
+ }
+ catch (InterruptedException ex)
+ {
+ }
+
+ if (actualEventCount == _actualEvents.size())
+ // the above wait was left because of the timeout, *not* because an event
+ // arrived. Okay, we won't wait any longer, this is a failure.
+ {
+ break;
+ }
+ actualEventCount = _actualEvents.size();
+ }
+
+ assertEquals("wrong event count for '" + _context + "'",
+ _expectedEvents.length, _actualEvents.size());
+
+ for (int i = 0; i < _expectedEvents.length; ++i)
+ {
+ assertEquals("wrong event at positon " + (i + 1) + " for '" + _context + "'",
+ _expectedEvents[i], _actualEvents.get(i));
+ }
+ }
+ }
+ finally
+ {
+ System.out.println(" }");
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ int impl_waitForEvent(ArrayList _eventQueue, String _expectedEvent, int _maxMilliseconds)
+ {
+ return impl_waitForEvent(_eventQueue, _expectedEvent, _maxMilliseconds, 0);
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ int impl_waitForEvent(ArrayList _eventQueue, String _expectedEvent, int _maxMilliseconds, int _firstQueueElementToCheck)
+ {
+ synchronized (_eventQueue)
+ {
+ int waitedMilliseconds = 0;
+
+ while (waitedMilliseconds < _maxMilliseconds)
+ {
+ for (int i = _firstQueueElementToCheck; i < _eventQueue.size(); ++i)
+ {
+ if (_expectedEvent.equals(_eventQueue.get(i)))
+ // found the event in the queue
+ {
+ return i;
+ }
+ }
+
+ // wait a little, perhaps the event will still arrive
+ try
+ {
+ _eventQueue.wait(500);
+ waitedMilliseconds += 500;
+ }
+ catch (InterruptedException e)
+ {
+ }
+ }
+ }
+
+ fail("expected event '" + _expectedEvent + "' did not arrive after " + _maxMilliseconds + " milliseconds");
+ return -1;
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ void onDocumentEvent(DocumentEvent _Event)
+ {
+ if ("OnTitleChanged".equals(_Event.EventName))
+ // OnTitleChanged events are notified too often. This is known, and accepted.
+ // (the deeper reason is that it's diffult to determine, in the DatabaseDocument implementatin,
+ // when the title actually changed. In particular, when we do a saveAsURL, and then ask for a
+ // title *before* the TitleHelper got the document's OnSaveAsDone event, then the wrong (old)
+ // title is obtained.
+ {
+ return;
+ }
+
+ if ((_Event.EventName.equals("OnLoad")) && (m_loadDocState != STATE_NOT_STARTED))
+ {
+ assertEquals("OnLoad event must come *after* invocation of the interaction handler / user!",
+ m_loadDocState, STATE_MACRO_EXEC_APPROVED);
+ m_loadDocState = STATE_ON_LOAD_RECEIVED;
+ }
+
+ synchronized (m_documentEvents)
+ {
+ m_documentEvents.add(_Event.EventName);
+ m_documentEvents.notifyAll();
+ }
+
+ System.out.println(" document event: " + _Event.EventName);
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ public void documentEventOccured(DocumentEvent _Event)
+ {
+ if ("OnTitleChanged".equals(_Event.EventName))
+ // ignore. See onDocumentEvent for a justification
+ {
+ return;
+ }
+
+ synchronized (m_globalEvents)
+ {
+ m_globalEvents.add(_Event.EventName);
+ m_globalEvents.notifyAll();
+ }
+
+ System.out.println(" global event: " + _Event.EventName);
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ public void disposing(EventObject _Event)
+ {
+ // not interested in
+ }
+}
diff --git a/dbaccess/qa/complex/dbaccess/FileHelper.java b/dbaccess/qa/complex/dbaccess/FileHelper.java
new file mode 100644
index 000000000000..f72dc0ff7ca3
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/FileHelper.java
@@ -0,0 +1,44 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package complex.dbaccess;
+
+public class FileHelper
+{
+ private FileHelper(){}
+ static public String getOOoCompatibleFileURL( String _javaFileURL )
+ {
+ String returnURL = _javaFileURL;
+ if ( ( returnURL.indexOf( "file:/" ) == 0 ) && ( returnURL.indexOf( "file:///" ) == -1 ) )
+ {
+ // for some reason, the URLs here in Java start with "file:/" only, instead of "file:///"
+ // Some of the office code doesn't like this ...
+ returnURL = "file:///" + returnURL.substring( 6 );
+ }
+ return returnURL;
+ }
+}
diff --git a/dbaccess/qa/complex/dbaccess/Parser.java b/dbaccess/qa/complex/dbaccess/Parser.java
new file mode 100644
index 000000000000..3b6b0b92e3ed
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/Parser.java
@@ -0,0 +1,217 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package complex.dbaccess;
+
+import com.sun.star.beans.XPropertySet;
+import com.sun.star.container.XIndexAccess;
+import com.sun.star.sdb.XParametersSupplier;
+import com.sun.star.sdb.XSingleSelectQueryComposer;
+import com.sun.star.sdbc.DataType;
+import com.sun.star.sdbc.SQLException;
+import com.sun.star.uno.Exception;
+import com.sun.star.uno.UnoRuntime;
+
+
+// ---------- junit imports -----------------
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.openoffice.test.OfficeConnection;
+import static org.junit.Assert.*;
+// ------------------------------------------
+
+public class Parser extends CRMBasedTestCase
+{
+ // --------------------------------------------------------------------------------------------------------
+// public String[] getTestMethodNames()
+// {
+// return new String[] {
+// "checkJoinSyntax",
+// "checkParameterTypes",
+// "checkWhere",
+// };
+// }
+
+ // --------------------------------------------------------------------------------------------------------
+// public String getTestObjectName()
+// {
+// return "Parser";
+// }
+
+ // --------------------------------------------------------------------------------------------------------
+ protected void createTestCase()
+ {
+ try
+ {
+ super.createTestCase();
+ m_database.getDatabase().getDataSource().createQuery( "query products", "SELECT * FROM \"products\"" );
+ }
+ catch ( Exception e )
+ {
+ e.printStackTrace( System.err );
+ fail( "caught an exception (" + e.getMessage() + ") while creating the test case");
+ }
+ }
+
+ @Test public void checkWhere() throws Exception
+ {
+ final XSingleSelectQueryComposer composer = createQueryComposer();
+ final String SELECT = "SELECT \"products\".\"Name\" FROM \"products\" WHERE ";
+ final String[] queries = new String[]
+ {
+ "\"ID\" in ( 1,2,3,4)"
+ ,"not ( \"ID\" in ( 1,2,3,4))"
+ ,"(1 = 1) is true"
+ ,"(1 = 1) is not false"
+ ,"(1 = 1) is not null"
+ ,"not ( (1 = 1) is not null)"
+ ,"'a' like 'a%'"
+ ,"not ( 'a' like 'a%')"
+ ,"'a' not like 'a%'"
+ ,"1 between 0 and 2"
+ ,"not ( 1 between 0 and 2 )"
+ ,"1 not between 3 and 4"
+ ,"1 not between ( select \"ID\" from \"categories\") and ( select \"ID\" from \"categories\")"
+ ,"1 = 1"
+ ,"0 < 1"
+ ,"not(0 < 1)"
+ ,"1 > 0"
+ ,"not(1 > 0)"
+ ,"1 <> 0"
+ ,"(1 <> 0 and 'a' = 'a' and 'c' = 'd') or (1 = 1 and 2 = 2 and 3 = 4)"
+ ,"not ( 1 <> 0 )"
+ ,"\"CategoryID\" in ( select \"ID\" from \"categories\")"
+ ,"not (\"CategoryID\" in ( select \"ID\" from \"categories\"))"
+ ,"\"CategoryID\" not in ( select \"ID\" from \"categories\")"
+ };
+ for (int i = 0; i < queries.length; i++)
+ {
+ composer.setQuery( SELECT + queries[i]);
+ }
+ }
+ // --------------------------------------------------------------------------------------------------------
+ /** verifies that aliases for inner queries work as expected
+ */
+ @Test public void checkJoinSyntax() throws Exception
+ {
+ final XSingleSelectQueryComposer composer = createQueryComposer();
+
+ // feed the composer with some statements. If any of those cannot be parsed, the composer
+ // will throw an exception - which is a regression then
+ composer.setQuery(
+ "SELECT \"categories\".\"Name\", " +
+ "\"products\".\"Name\" " +
+ "FROM \"products\" RIGHT OUTER JOIN \"categories\" AS \"categories\" ON \"products\".\"CategoryID\" = \"categories\".\"ID\"" );
+
+ composer.setQuery(
+ "SELECT \"categories\".\"Name\", " +
+ "\"products\".\"Name\" " +
+ "FROM \"products\" LEFT OUTER JOIN \"categories\" AS \"categories\" ON \"products\".\"CategoryID\" = \"categories\".\"ID\"" );
+
+ composer.setQuery(
+ "SELECT \"categories\".\"Name\", " +
+ "\"products\".\"Name\" " +
+ "FROM \"products\" CROSS JOIN \"categories\" AS \"categories\"" );
+
+ composer.setQuery(
+ "SELECT \"categories\".\"Name\", " +
+ "\"products\".\"Name\" " +
+ "FROM \"products\" INNER JOIN \"categories\" AS \"categories\" ON \"products\".\"CategoryID\" = \"categories\".\"ID\"" );
+
+ // just to be sure the composer *really* parses upon setting the query: feed it with
+ // an unparseable statement
+ boolean caughtExpected = false;
+ try
+ {
+ composer.setQuery( "NONSENSE" );
+ }
+ catch( SQLException e )
+ {
+ caughtExpected = true;
+ }
+ assertTrue( "pre-condition not met: parser should except on unparseable statements, else the complete" +
+ "test is bogus!", caughtExpected );
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private void impl_checkParameters( final String _statement, final String[] _expectedParameterNames, final int[] _expectedParameterTypes,final String _context ) throws Exception
+ {
+ final XSingleSelectQueryComposer composer = createQueryComposer();
+ composer.setQuery( _statement );
+
+ assertEquals( "checkParameterTypes: internal error", _expectedParameterNames.length, _expectedParameterTypes.length );
+
+ final XParametersSupplier paramSupp = UnoRuntime.queryInterface(XParametersSupplier.class, composer);
+ final XIndexAccess parameters = paramSupp.getParameters();
+
+ assertEquals( "(ctx: " + _context + ") unexpected parameter count", _expectedParameterNames.length, parameters.getCount() );
+ for ( int i=0; i<parameters.getCount(); ++i )
+ {
+ final XPropertySet parameter = UnoRuntime.queryInterface(XPropertySet.class, parameters.getByIndex(i));
+
+ final String name = (String)parameter.getPropertyValue( "Name" );
+ assertEquals( "(ctx: " + _context + ") unexpected parameter name for parameter number " + ( i + 1 ), _expectedParameterNames[i], name );
+
+ final int type = ((Integer)parameter.getPropertyValue( "Type" )).intValue();
+ assertEquals( "(ctx: " + _context + ") unexpected data type for parameter number " + ( i + 1 ), _expectedParameterTypes[i], type );
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ /** verifies that the parser properly recognizes the types of parameters
+ */
+ @Test public void checkParameterTypes() throws Exception
+ {
+ impl_checkParameters(
+ "SELECT * FROM \"all orders\" " +
+ "WHERE ( \"Order Date\" >= :order_date ) " +
+ " AND ( ( \"Customer Name\" LIKE :customer ) " +
+ " OR ( \"Product Name\" LIKE ? ) " +
+ " )",
+ new String[] { "order_date", "customer", "Product Name" },
+ new int[] { DataType.DATE, DataType.VARCHAR, DataType.VARCHAR },
+ ">= && LIKE"
+ );
+
+ impl_checkParameters(
+ "SELECT * FROM \"categories\" " +
+ "WHERE \"ID\" BETWEEN :id_lo AND :id_hi",
+ new String[] { "id_lo", "id_hi" },
+ new int[] { DataType.INTEGER, DataType.INTEGER },
+ "BETWEEN"
+ );
+
+ impl_checkParameters(
+ "SELECT CONCAT( :prefix, CONCAT( \"Name\", :suffix ) ) FROM \"customers\"",
+ new String[] { "prefix", "suffix" },
+ new int[] { DataType.VARCHAR, DataType.VARCHAR },
+ "CONCAT"
+ );
+ }
+}
diff --git a/dbaccess/qa/complex/dbaccess/PropertyBag.java b/dbaccess/qa/complex/dbaccess/PropertyBag.java
new file mode 100644
index 000000000000..4920f8fa0006
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/PropertyBag.java
@@ -0,0 +1,324 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package complex.dbaccess;
+
+// import complexlib.ComplexTestCase;
+
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.uno.XInterface;
+import com.sun.star.lang.XMultiServiceFactory;
+import com.sun.star.beans.*;
+
+// ---------- junit imports -----------------
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.openoffice.test.OfficeConnection;
+import static org.junit.Assert.*;
+// ------------------------------------------
+
+public class PropertyBag extends TestCase
+{
+ private static final String VALUE = "Value";
+ private XPropertyContainer m_bag;
+ private XPropertySet m_set;
+ private XPropertyAccess m_access;
+ private XMultiServiceFactory m_orb = null;
+
+// public String[] getTestMethodNames()
+// {
+// return new String[]
+// {
+// "checkBasics",
+// "checkSequenceAccess",
+// "checkDynamicSet"
+// };
+// }
+
+ public String getTestObjectName()
+ {
+ return "PropertyBag";
+ }
+
+ @Before public void before()
+ {
+ m_orb = getMSF();
+ }
+
+ @Test public void checkBasics()
+ {
+ createEmptyBag();
+ System.out.println("testing the basics");
+
+ // check whether empty property names are rejected
+ boolean caughtExpected = false;
+ try
+ {
+ m_bag.addProperty( "", PropertyAttribute.BOUND, Integer.valueOf( 3 ) );
+ }
+ catch(com.sun.star.lang.IllegalArgumentException e) { caughtExpected = true; }
+ catch(com.sun.star.uno.Exception e) { }
+ if ( !caughtExpected )
+ {
+ fail("empty property names are not rejected by XPropertyContainer::addProperty");
+ }
+
+ // check whether duplicate insertions are rejected
+ caughtExpected = false;
+ try
+ {
+ m_bag.addProperty( VALUE, PropertyAttribute.BOUND, "" );
+ m_bag.addProperty( VALUE, PropertyAttribute.BOUND, "" );
+ }
+ catch(com.sun.star.beans.PropertyExistException e) { caughtExpected = true; }
+ catch(com.sun.star.uno.Exception e) { }
+ if ( !caughtExpected )
+ {
+ fail("insertion of duplicate property names is not rejected");
+ }
+
+ // try removing the property we just added - this should fail, as it does not have
+ // the REMOVEABLE attribute
+ caughtExpected = false;
+ try
+ {
+ m_bag.removeProperty( VALUE);
+ }
+ catch(com.sun.star.beans.NotRemoveableException e) { caughtExpected = true; }
+ catch(com.sun.star.uno.Exception e) { }
+ if ( !caughtExpected )
+ {
+ fail("removing non-removeable properties is expected to fail - but it didn't");
+ }
+
+ // try removing a non-existent property
+ caughtExpected = false;
+ try
+ {
+ m_bag.removeProperty( "NonExistent" );
+ }
+ catch(com.sun.star.beans.UnknownPropertyException e) { caughtExpected = true; }
+ catch(com.sun.star.uno.Exception e) { }
+ if ( !caughtExpected )
+ {
+ fail("removing non-existent properties is expected to fail - but it didn't");
+ }
+
+ // try writing and reading a value for the one property we have so far
+ try
+ {
+ final String testValue = "someArbitraryValue";
+ m_set.setPropertyValue( VALUE , testValue);
+ final String currentValue = (String)m_set.getPropertyValue( VALUE);
+ if ( !currentValue.equals( testValue ) )
+ {
+ fail("set property is not remembered");
+ }
+ }
+ catch(com.sun.star.uno.Exception e)
+ {
+ fail( "setting or getting a property value failed" );
+ }
+
+ // try setting an illegal value for the property
+ caughtExpected = false;
+ try
+ {
+ m_set.setPropertyValue( VALUE, Integer.valueOf( 3 ) );
+ }
+ catch(com.sun.star.lang.IllegalArgumentException e) { caughtExpected = true; }
+ catch(com.sun.star.uno.Exception e) { }
+ if ( !caughtExpected )
+ {
+ fail("the bag does not respect the property type we declared for the property");
+ }
+ }
+
+ @Test public void checkSequenceAccess() throws com.sun.star.uno.Exception
+ {
+ System.out.println( "checking PropertySetAccess via sequences" );
+ createStandardBag( false );
+
+ // ---------------------------------
+ // XPropertyAccess.setPropertyValues
+ final PropertyValue expectedValues[] =
+ {
+ new PropertyValue( "BoolValue", -1, Boolean.FALSE, PropertyState.DIRECT_VALUE ),
+ new PropertyValue( "StringValue", -1, "some text", PropertyState.DIRECT_VALUE ),
+ new PropertyValue( "IntegerValue", -1, Integer.valueOf( 3 ), PropertyState.DIRECT_VALUE ),
+ new PropertyValue( "InterfaceValue", -1, m_bag, PropertyState.DIRECT_VALUE )
+ };
+ m_access.setPropertyValues( expectedValues );
+
+ for ( int i=0; i<expectedValues.length; ++i )
+ {
+ final Object value = m_set.getPropertyValue( expectedValues[i].Name );
+ if ( !value.equals( expectedValues[i].Value ) )
+ {
+ System.out.println( "property name : " + expectedValues[i].Name );
+ System.out.println( "expected value: " + expectedValues[i].Value.toString() );
+ System.out.println( "current value : " + value.toString() );
+ fail( "retrieving a previously set property (" + expectedValues[i].Value.getClass().toString() + ") failed" );
+ }
+ }
+
+ // ---------------------------------
+ // XPropertyAccess.getPropertyValues
+ final PropertyValue currentValues[] = m_access.getPropertyValues();
+ for ( int i=0; i<currentValues.length; ++i )
+ {
+ final String name = currentValues[i].Name;
+ final Object value = currentValues[i].Value;
+ for ( int j=0; j<expectedValues.length; ++j )
+ {
+ if ( expectedValues[j].Name.equals( name ) )
+ {
+ if ( !expectedValues[j].Value.equals( value ) )
+ {
+ System.out.println( "property name : " + expectedValues[j].Name );
+ System.out.println( "expected value: " + expectedValues[j].Value.toString() );
+ System.out.println( "current value : " + value.toString() );
+ fail( "getPropertyValues failed for property '" + name + "' failed" );
+ }
+ break;
+ }
+ }
+
+ if ( !m_set.getPropertyValue( name ).equals( value ) )
+ {
+ fail("XPropertyAccess::getPropertyValues() and XPropertyset::getPropertyValue results are inconsistent");
+ }
+ }
+ }
+
+ @Test public void checkDynamicSet() throws com.sun.star.uno.Exception
+ {
+ System.out.println( "checking proper dynamic of the set" );
+ createStandardBag( false );
+
+ final PropertyValue props[] =
+ {
+ new PropertyValue( "BoolValue", -1, Boolean.FALSE, PropertyState.DIRECT_VALUE),
+ new PropertyValue( "StringValue", -1, "test", PropertyState.DIRECT_VALUE ),
+ new PropertyValue( "SomeOtherStringValue", -1, "string value", PropertyState.DIRECT_VALUE )
+ };
+
+ // try setting some property values which are not existent
+ boolean caughtExpected = false;
+ try
+ {
+ m_access.setPropertyValues( props );
+ }
+ catch( com.sun.star.beans.UnknownPropertyException e ) { caughtExpected = true; }
+ catch( com.sun.star.uno.Exception e ) { }
+ if ( !caughtExpected )
+ {
+ fail("the set shouldn't accept unknown property values, if not explicitly told to do so");
+ }
+
+ // re-create the bag, this time allow it to implicitly add properties
+ createStandardBag( true );
+ boolean success = false;
+ try { m_access.setPropertyValues( props ); success = true; }
+ catch( com.sun.star.uno.Exception e ) { }
+ if ( !success )
+ {
+ fail("property bag failed to implicitly add unknown properties");
+ }
+
+ // see whether this property was really added, and not just ignored
+ final PropertyValue newlyAdded = props[ props.length - 1 ];
+ try
+ {
+ if ( !m_set.getPropertyValue( newlyAdded.Name ).equals( newlyAdded.Value ) )
+ {
+ fail("the new property was not really added, or not added with the proper value");
+ }
+ }
+ catch( com.sun.star.uno.Exception e ) { }
+ }
+
+ private void createEmptyBag()
+ {
+ try
+ {
+ m_bag = null;
+ final String serviceName = "com.sun.star.beans.PropertyBag";
+ m_bag = UnoRuntime.queryInterface(XPropertyContainer.class, m_orb.createInstance(serviceName));
+ if ( m_bag == null )
+ {
+ fail("could not create a " + serviceName + " instance");
+ }
+ m_set = UnoRuntime.queryInterface(XPropertySet.class, m_bag);
+ m_access = UnoRuntime.queryInterface(XPropertyAccess.class, m_bag);
+ }
+ catch( com.sun.star.uno.Exception e )
+ {
+ }
+ }
+
+ private void createStandardBag( boolean allowLazyAdding )
+ {
+ try
+ {
+ m_bag = null;
+
+ final Object initArgs[] = { new NamedValue( "AutomaticAddition", Boolean.valueOf( allowLazyAdding ) ) };
+
+ final String serviceName = "com.sun.star.beans.PropertyBag";
+ m_bag = UnoRuntime.queryInterface(XPropertyContainer.class, m_orb.createInstanceWithArguments(serviceName, initArgs));
+ if ( m_bag == null )
+ {
+ fail("could not create a " + serviceName + " instance");
+ }
+ m_set = UnoRuntime.queryInterface(XPropertySet.class, m_bag);
+ m_access = UnoRuntime.queryInterface(XPropertyAccess.class, m_bag);
+
+ final Object properties[][] =
+ {
+ { "BoolValue", Boolean.TRUE },
+ { "StringValue", "" },
+ { "IntegerValue", Integer.valueOf( 3 ) },
+ { "InterfaceValue", (XInterface)m_bag }
+ };
+ for ( int i=0; i<properties.length; ++i )
+ {
+ m_bag.addProperty(
+ (String)properties[i][0],
+ PropertyAttribute.MAYBEVOID,
+ properties[i][1]
+ );
+ }
+ }
+ catch( com.sun.star.uno.Exception e )
+ {
+ }
+ }
+}
diff --git a/dbaccess/qa/complex/dbaccess/Query.java b/dbaccess/qa/complex/dbaccess/Query.java
new file mode 100644
index 000000000000..222a6668f705
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/Query.java
@@ -0,0 +1,136 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package complex.dbaccess;
+
+import com.sun.star.beans.XPropertySet;
+import com.sun.star.container.XIndexAccess;
+import com.sun.star.container.XNameAccess;
+import com.sun.star.container.XNamed;
+import com.sun.star.lang.XMultiServiceFactory;
+import com.sun.star.sdb.XQueriesSupplier;
+import com.sun.star.sdbcx.XColumnsSupplier;
+import com.sun.star.uno.UnoRuntime;
+import connectivity.tools.CRMDatabase;
+
+// ---------- junit imports -----------------
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.openoffice.test.OfficeConnection;
+import static org.junit.Assert.*;
+// ------------------------------------------
+
+public class Query extends TestCase {
+
+ connectivity.tools.HsqlDatabase m_database;
+
+ // --------------------------------------------------------------------------------------------------------
+// public String[] getTestMethodNames() {
+// return new String[]
+// {
+// "testQueryColumns"
+// };
+// }
+
+ // --------------------------------------------------------------------------------------------------------
+// public String getTestObjectName() {
+// return "Query";
+// }
+
+ // --------------------------------------------------------------------------------------------------------
+ private void createTestCase()
+ {
+ try
+ {
+ if ( m_database == null )
+ {
+ final CRMDatabase database = new CRMDatabase( getMSF(), false );
+ m_database = database.getDatabase();
+ }
+ }
+ catch( Exception e )
+ {
+ System.out.println( "could not create the test case, error message:\n" + e.getMessage() );
+ e.printStackTrace( System.err );
+ fail( "failed to created the test case");
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+// private XMultiServiceFactory getFactory()
+// {
+// return (XMultiServiceFactory)param.getMSF();
+// }
+
+ // --------------------------------------------------------------------------------------------------------
+ @Test public void testQueryColumns()
+ {
+ createTestCase();
+
+ try
+ {
+ final XQueriesSupplier suppQueries = UnoRuntime.queryInterface(
+ XQueriesSupplier.class, m_database.defaultConnection().getXConnection() );
+ final XNameAccess queries = suppQueries.getQueries();
+
+ final String[] queryNames = new String[] { "parseable", "parseable native", "unparseable" };
+ final String[][] expectedColumnNames = new String[][] {
+ new String[] { "ID", "Name", "Address", "City", "Postal","Comment" },
+ new String[] { "TABLE_CATALOG", "TABLE_SCHEMA", "TABLE_NAME", "VIEW_DEFINITION", "CHECK_OPTION", "IS_UPDATABLE", "VALID" },
+ new String[] { "ID_VARCHAR" }
+ };
+
+ for ( int i = 0; i < queryNames.length; ++i )
+ {
+ final XPropertySet query = UnoRuntime.queryInterface(
+ XPropertySet.class, queries.getByName( queryNames[i] ) );
+
+ final XColumnsSupplier suppCols = UnoRuntime.queryInterface(
+ XColumnsSupplier.class, query);
+ final XIndexAccess columns = UnoRuntime.queryInterface(
+ XIndexAccess.class, suppCols.getColumns());
+
+ // check whether the columns supplied by the query match what we expected
+ assertTrue( "invalid column count (found " + columns.getCount() + ", expected: " + expectedColumnNames[i].length + ") for query \"" + queryNames[i] + "\"",
+ columns.getCount() == expectedColumnNames[i].length );
+ for ( int col = 0; col < columns.getCount(); ++col )
+ {
+ final XNamed columnName = UnoRuntime.queryInterface(
+ XNamed.class, columns.getByIndex(col) );
+ assertTrue( "column no. " + col + " of query \"" + queryNames[i] + "\" not matching",
+ columnName.getName().equals( expectedColumnNames[i][col] ) );
+ }
+ }
+ }
+ catch ( Exception e )
+ {
+ fail( "caught an unexpected exception: " + e.getMessage() );
+ }
+ }
+}
diff --git a/dbaccess/qa/complex/dbaccess/QueryInQuery.java b/dbaccess/qa/complex/dbaccess/QueryInQuery.java
new file mode 100644
index 000000000000..0cb0789b782c
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/QueryInQuery.java
@@ -0,0 +1,202 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package complex.dbaccess;
+
+import com.sun.star.container.ElementExistException;
+import com.sun.star.lang.IllegalArgumentException;
+import com.sun.star.lang.WrappedTargetException;
+import com.sun.star.sdb.CommandType;
+import com.sun.star.sdbc.SQLException;
+import connectivity.tools.HsqlColumnDescriptor;
+import connectivity.tools.HsqlTableDescriptor;
+import connectivity.tools.RowSet;
+import com.sun.star.sdbc.XStatement;
+import com.sun.star.sdbc.XResultSet;
+
+// ---------- junit imports -----------------
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.openoffice.test.OfficeConnection;
+import static org.junit.Assert.*;
+// ------------------------------------------
+
+public class QueryInQuery extends CRMBasedTestCase
+{
+ private static final String QUERY_PRODUCTS = "query products";
+// // --------------------------------------------------------------------------------------------------------
+// public String[] getTestMethodNames()
+// {
+// return new String[] {
+// "executeSimpleSelect",
+// "executeAliasedSelect",
+// "checkNameCollisions",
+// "checkCyclicReferences",
+// "checkStatementQiQSupport"
+// };
+// }
+//
+// // --------------------------------------------------------------------------------------------------------
+// public String getTestObjectName()
+// {
+// return "QueryInQuery";
+// }
+
+ // --------------------------------------------------------------------------------------------------------
+ protected void createTestCase()
+ {
+ try
+ {
+ super.createTestCase();
+ m_database.getDatabase().getDataSource().createQuery( QUERY_PRODUCTS,"SELECT * FROM \"products\"");
+ }
+ catch ( Exception e )
+ {
+ e.printStackTrace( System.err );
+ fail( "caught an exception (" + e.getMessage() + ") while creating the test case" );
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private void verifyEqualRowSetContent( int _outerCommandType, String _outerCommand, int _innerCommandType, String _innerCommand ) throws SQLException
+ {
+ final RowSet outerRowSet = m_database.getDatabase().createRowSet( _outerCommandType, _outerCommand );
+ outerRowSet.execute();
+
+ final RowSet innerRowSet = m_database.getDatabase().createRowSet( _innerCommandType, _innerCommand );
+ innerRowSet.execute();
+
+ outerRowSet.last();
+ innerRowSet.last();
+ assertTrue( "wrong record counts", outerRowSet.getRow() == innerRowSet.getRow() );
+
+ outerRowSet.beforeFirst();
+ innerRowSet.beforeFirst();
+ assertTrue( "wrong column counts", outerRowSet.getColumnCount() == innerRowSet.getColumnCount() );
+
+ while ( outerRowSet.next() && innerRowSet.next() )
+ {
+ for ( int i=1; i <= outerRowSet.getColumnCount(); ++i )
+ {
+ assertTrue( "content of column " + i + " of row " + outerRowSet.getRow() + " not identical",
+ innerRowSet.getString(i).equals( outerRowSet.getString(i) ) );
+ }
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ /** executes a SQL statement simply selecting all columns from a query
+ */
+ @Test public void executeSimpleSelect() throws SQLException
+ {
+ verifyEqualRowSetContent(
+ CommandType.COMMAND, "SELECT * FROM \"query products\"",
+ CommandType.QUERY,QUERY_PRODUCTS);
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ /** verifies that aliases for inner queries work as expected
+ */
+ @Test public void executeAliasedSelect() throws SQLException
+ {
+ verifyEqualRowSetContent(
+ CommandType.COMMAND, "SELECT \"PROD\".\"ID\" FROM \"query products\" AS \"PROD\"",
+ CommandType.COMMAND, "SELECT \"ID\" FROM \"products\"" );
+ verifyEqualRowSetContent(
+ CommandType.COMMAND, "SELECT \"PROD\".* FROM \"query products\" AS \"PROD\"",
+ CommandType.QUERY,QUERY_PRODUCTS);
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ /** verifies that aliases for inner queries work as expected
+ */
+ @Test public void checkNameCollisions()
+ {
+ // create a query with a name which is used by a table
+ boolean caughtExpected = false;
+ try
+ {
+ m_database.getDatabase().getDataSource().createQuery( "products", "SELECT * FROM \"products\"" );
+ }
+ catch ( WrappedTargetException e ) { caughtExpected = true; }
+ catch ( IllegalArgumentException e ) {}
+ catch ( ElementExistException e ) { caughtExpected = true; }
+ assertTrue( "creating queries with the name of an existing table should not be possible",
+ caughtExpected );
+
+ // create a table with a name which is used by a query
+ final HsqlTableDescriptor table = new HsqlTableDescriptor( QUERY_PRODUCTS,
+ new HsqlColumnDescriptor[] {
+ new HsqlColumnDescriptor( "ID", "INTEGER" ),
+ new HsqlColumnDescriptor( "Name", "VARCHAR(50)" ) } );
+
+ caughtExpected = false;
+ try
+ {
+ m_database.getDatabase().createTableInSDBCX( table );
+ }
+ catch ( SQLException e ) { caughtExpected = true; }
+ catch ( ElementExistException ex ) { }
+ assertTrue( "creating tables with the name of an existing query should not be possible",
+ caughtExpected );
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ @Test public void checkCyclicReferences() throws ElementExistException, WrappedTargetException, IllegalArgumentException
+ {
+ // some queries which create a cycle in the sub query tree
+ m_database.getDatabase().getDataSource().createQuery( "orders level 1", "SELECT * FROM \"orders level 0\"" );
+ m_database.getDatabase().getDataSource().createQuery( "orders level 2", "SELECT * FROM \"orders level 1\"" );
+ m_database.getDatabase().getDataSource().createQuery( "orders level 3", "SELECT * FROM \"orders level 2\"" );
+ m_database.getDatabase().getDataSource().createQuery( "orders level 0", "SELECT * FROM \"orders level 3\"" );
+
+ final RowSet rowSet = m_database.getDatabase().createRowSet( CommandType.QUERY, "orders level 0" );
+
+ boolean caughtExpected = false;
+ try { rowSet.execute(); }
+ catch ( SQLException e ) { caughtExpected = ( e.ErrorCode == -com.sun.star.sdb.ErrorCondition.PARSER_CYCLIC_SUB_QUERIES ); }
+
+ assertTrue( "executing a query with cyclic nested sub queries should fail!", caughtExpected );
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ @Test public void checkStatementQiQSupport()
+ {
+ try
+ {
+ final XStatement statement = m_database.getConnection().createStatement();
+ final XResultSet resultSet = statement.executeQuery( "SELECT * FROM \"query products\"" );
+ assertTrue( "Result Set is null", resultSet != null );
+ }
+ catch( SQLException e )
+ {
+ fail( "SDB level statements do not allow for queries in queries" );
+ }
+ }
+}
diff --git a/dbaccess/qa/complex/dbaccess/RowSet.java b/dbaccess/qa/complex/dbaccess/RowSet.java
new file mode 100644
index 000000000000..7a11a96d9b00
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/RowSet.java
@@ -0,0 +1,1036 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package complex.dbaccess;
+
+import com.sun.star.beans.PropertyVetoException;
+import com.sun.star.beans.UnknownPropertyException;
+import com.sun.star.beans.XPropertySet;
+import com.sun.star.container.XIndexAccess;
+import com.sun.star.lang.WrappedTargetException;
+import com.sun.star.lang.XComponent;
+import com.sun.star.lang.XMultiServiceFactory;
+import com.sun.star.sdb.CommandType;
+import com.sun.star.sdb.XParametersSupplier;
+import com.sun.star.sdb.XResultSetAccess;
+import com.sun.star.sdb.XRowSetApproveBroadcaster;
+import com.sun.star.sdbc.SQLException;
+import com.sun.star.sdbc.XParameters;
+import com.sun.star.sdbc.XPreparedStatement;
+import com.sun.star.sdbc.XResultSet;
+import com.sun.star.sdbc.XResultSetUpdate;
+import com.sun.star.sdbc.XRow;
+import com.sun.star.sdbc.XRowSet;
+import com.sun.star.sdbc.XRowUpdate;
+import com.sun.star.sdbcx.XColumnsSupplier;
+import com.sun.star.sdbcx.XDeleteRows;
+import com.sun.star.sdbcx.XRowLocate;
+import com.sun.star.uno.UnoRuntime;
+
+import connectivity.tools.CRMDatabase;
+import connectivity.tools.DataSource;
+import connectivity.tools.HsqlDatabase;
+import connectivity.tools.sdb.Connection;
+import java.lang.reflect.Method;
+import java.util.Random;
+
+// ---------- junit imports -----------------
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.openoffice.test.OfficeConnection;
+import static org.junit.Assert.*;
+// ------------------------------------------
+
+public class RowSet extends TestCase
+{
+
+ static final int MAX_TABLE_ROWS = 100;
+ static final int MAX_FETCH_ROWS = 10;
+ private static final String NEXT = "next";
+ private static final String TEST21 = "Test21";
+ HsqlDatabase m_database;
+ DataSource m_dataSource;
+ XRowSet m_rowSet;
+ XResultSet m_resultSet;
+ XResultSetUpdate m_resultSetUpdate;
+ XRow m_row;
+ XRowLocate m_rowLocate;
+ XPropertySet m_rowSetProperties;
+ XParametersSupplier m_paramsSupplier;
+
+ // --------------------------------------------------------------------------------------------------------
+ class ResultSetMovementStress implements Runnable
+ {
+
+ XResultSet m_resultSet;
+ XRow m_row;
+ int m_id;
+
+ public ResultSetMovementStress(XResultSet _resultSet, int _id) throws java.lang.Exception
+ {
+ m_resultSet = _resultSet;
+ m_row = UnoRuntime.queryInterface( XRow.class, m_resultSet );
+ m_id = _id;
+ }
+
+ public void run()
+ {
+ try
+ {
+ m_resultSet.beforeFirst();
+ for (int i = 0; m_resultSet.next(); ++i)
+ {
+ int pos = m_resultSet.getRow();
+ // final int val = m_row.getInt(1);
+// System.out.println("Clone Move(" + m_id +") before i: " + (i+1) + " Pos: " + pos + " Val: " + val);
+ testPosition(m_resultSet, m_row, i + 1, "clone move(" + m_id + ")");
+// val = m_row.getInt(1);
+// System.out.println("Clone Move(" + m_id +") after i: " + (i+1) + " Pos: " + pos + " Val: " + val);
+ int pos2 = m_resultSet.getRow();
+ assertTrue("ResultSetMovementStress wrong position: " + i + " Pos1: " + pos + " Pos2: " + pos2, pos == pos2);
+ }
+ }
+ catch (Exception e)
+ {
+ fail("ResultSetMovementStress(" + m_id + ") failed: " + e);
+ }
+ }
+ }
+ // --------------------------------------------------------------------------------------------------------
+
+// public String[] getTestMethodNames()
+// {
+// return new String[]
+// {
+// "testRowSet",
+// "testRowSetEvents",
+// "testDeleteBehavior",
+// "testCloneMovesPlusDeletions",
+// "testCloneMovesPlusInsertions",
+// "testParameters"
+// };
+// }
+//
+// // --------------------------------------------------------------------------------------------------------
+// public String getTestObjectName()
+// {
+// return "RowSet";
+// }
+//
+ // --------------------------------------------------------------------------------------------------------
+ private void createTestCase(boolean _defaultRowSet)
+ {
+ if (m_database == null)
+ {
+ try
+ {
+ final CRMDatabase database = new CRMDatabase( getMSF(), false );
+ m_database = database.getDatabase();
+ m_dataSource = m_database.getDataSource();
+ }
+ catch (Exception e)
+ {
+ fail("could not create the embedded HSQL database: " + e.getMessage());
+ }
+ }
+
+ try
+ {
+ createStruture();
+ }
+ catch (SQLException e)
+ {
+ fail("could not connect to the database/table structure, error message:\n" + e.getMessage());
+ }
+
+ if (_defaultRowSet)
+ {
+ createRowSet("TEST1", CommandType.TABLE, true, true);
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+// private XMultiServiceFactory getFactory()
+// {
+// return (XMultiServiceFactory) param.getMSF();
+// }
+
+ // --------------------------------------------------------------------------------------------------------
+ /** creates a com.sun.star.sdb.RowSet to use during the test
+ * @param command
+ * the command to use for the RowSet
+ * @param commandType
+ * the command type to use for the RowSet
+ * @param execute
+ * determines whether the RowSet should be executed
+ */
+ private void createRowSet(String command, int commandType, boolean execute)
+ {
+ createRowSet(command, commandType, execute, false);
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ /** creates a com.sun.star.sdb.RowSet to use during the test
+ * @param command
+ * the command to use for the RowSet
+ * @param commandType
+ * the command type to use for the RowSet
+ * @param limitFetchSize
+ * determines whether the fetch size of the RowSet should be limited to MAX_FETCH_ROWS
+ * @param execute
+ * determines whether the RowSet should be executed
+ */
+ private void createRowSet(String command, int commandType, boolean execute, boolean limitFetchSize)
+ {
+ try
+ {
+ m_rowSet = UnoRuntime.queryInterface( XRowSet.class, getMSF().createInstance( "com.sun.star.sdb.RowSet" ) );
+ final XPropertySet rowSetProperties = UnoRuntime.queryInterface( XPropertySet.class, m_rowSet );
+ rowSetProperties.setPropertyValue("Command", command);
+ rowSetProperties.setPropertyValue("CommandType", Integer.valueOf(commandType));
+ rowSetProperties.setPropertyValue("ActiveConnection", m_database.defaultConnection().getXConnection());
+ if (limitFetchSize)
+ {
+ rowSetProperties.setPropertyValue("FetchSize", Integer.valueOf(MAX_FETCH_ROWS));
+ }
+
+ m_resultSet = UnoRuntime.queryInterface( XResultSet.class, m_rowSet );
+ m_resultSetUpdate = UnoRuntime.queryInterface( XResultSetUpdate.class, m_rowSet );
+ m_row = UnoRuntime.queryInterface( XRow.class, m_rowSet );
+ m_rowLocate = UnoRuntime.queryInterface( XRowLocate.class, m_resultSet );
+ m_rowSetProperties = UnoRuntime.queryInterface( XPropertySet.class, m_rowSet );
+ m_paramsSupplier = UnoRuntime.queryInterface( XParametersSupplier.class, m_rowSet );
+
+ if (execute)
+ {
+ m_rowSet.execute();
+ }
+ }
+ catch (Exception e)
+ {
+ fail("caught an exception while creating the RowSet. Type:\n" + e.getClass().toString() + "\nMessage:\n" + e.getMessage());
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ @Test public void testRowSet() throws java.lang.Exception
+ {
+
+ System.out.println("testing testRowSet");
+ createTestCase(true);
+
+ // sequential postioning
+ m_resultSet.beforeFirst();
+ testSequentialPositining(m_resultSet, m_row);
+
+ // absolute positioning
+ testAbsolutePositioning(m_resultSet, m_row);
+
+ // 3rd test
+ test3(createClone(), m_resultSet);
+ // 4th test
+ test4(m_resultSet);
+
+ // concurrent (multi threaded) access to the row set and its clones
+ testConcurrentAccess(m_resultSet);
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ XResultSet createClone() throws SQLException
+ {
+ final XResultSetAccess rowAcc = UnoRuntime.queryInterface( XResultSetAccess.class, m_rowSet );
+ return rowAcc.createResultSet();
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ void createStruture() throws SQLException
+ {
+ m_database.executeSQL("DROP TABLE \"TEST1\" IF EXISTS");
+ m_database.executeSQL("CREATE TABLE \"TEST1\" (\"ID\" integer not null primary key, \"col2\" varchar(50) )");
+
+ final Connection connection = m_database.defaultConnection();
+ final XPreparedStatement prep = connection.prepareStatement("INSERT INTO \"TEST1\" values (?,?)");
+ final XParameters para = UnoRuntime.queryInterface( XParameters.class, prep );
+ for (int i = 1; i <= MAX_TABLE_ROWS; ++i)
+ {
+ para.setInt(1, i);
+ para.setString(2, "Test" + i);
+ prep.executeUpdate();
+ }
+
+ connection.refreshTables();
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ void testPosition(XResultSet m_resultSet, XRow m_row, int expectedValue, String location) throws SQLException
+ {
+ final int val = m_row.getInt(1);
+ final int pos = m_resultSet.getRow();
+ assertTrue(location + ": value/position do not match: " + pos + " (pos) != " + val + " (val)", val == pos);
+ assertTrue(location + ": value/position are not as expected: " + val + " (val) != " + expectedValue + " (expected)", val == expectedValue);
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ void testSequentialPositining(XResultSet _resultSet, XRow _row)
+ {
+ try
+ {
+ // 1st test
+ int i = 1;
+ while (_resultSet.next())
+ {
+ testPosition(_resultSet, _row, i, "testSequentialPositining");
+ ++i;
+ }
+ }
+ catch (Exception e)
+ {
+ fail("testSequentialPositining failed: " + e);
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ void testAbsolutePositioning(XResultSet _resultSet, XRow _row)
+ {
+ try
+ {
+ for (int i = 1; i <= MAX_FETCH_ROWS; ++i)
+ {
+ final int calcPos = (MAX_TABLE_ROWS % i) + 1;
+ assertTrue("testAbsolutePositioning failed", _resultSet.absolute(calcPos));
+ testPosition(_resultSet, _row, calcPos, "testAbsolutePositioning");
+ }
+ }
+ catch (Exception e)
+ {
+ fail("testAbsolutePositioning failed: " + e);
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ void test3(XResultSet clone, XResultSet _resultSet)
+ {
+ try
+ {
+ final XRow _row = UnoRuntime.queryInterface( XRow.class, _resultSet );
+ final XRow cloneRow = UnoRuntime.queryInterface( XRow.class, clone );
+ for (int i = 1; i <= MAX_FETCH_ROWS; ++i)
+ {
+ final int calcPos = (MAX_TABLE_ROWS % i) + 1;
+ if (clone.absolute(calcPos))
+ {
+ testPosition(clone, cloneRow, calcPos, "test3");
+ testAbsolutePositioning(_resultSet, _row);
+ testAbsolutePositioning(clone, cloneRow);
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ fail("test3 failed: " + e);
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ void test4(XResultSet _resultSet)
+ {
+ try
+ {
+ final XRow _row = UnoRuntime.queryInterface( XRow.class, _resultSet );
+ _resultSet.beforeFirst();
+
+ for (int i = 1; i <= MAX_TABLE_ROWS; ++i)
+ {
+ _resultSet.next();
+ final XResultSet clone = createClone();
+ final XRow cloneRow = UnoRuntime.queryInterface( XRow.class, clone );
+ final int calcPos = MAX_TABLE_ROWS - 1;
+ if (calcPos != 0 && clone.absolute(calcPos))
+ {
+ testPosition(clone, cloneRow, calcPos, "test4: clone");
+ testPosition(_resultSet, _row, i, "test4: rowset");
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ fail("test4 failed: " + e);
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ void testConcurrentAccess(XResultSet _resultSet)
+ {
+ System.out.println("testing Thread");
+ try
+ {
+ // final XRow _row = (XRow)UnoRuntime.queryInterface(XRow.class,_resultSet);
+ _resultSet.beforeFirst();
+
+ final int numberOfThreads = 10;
+
+ final Thread threads[] = new Thread[numberOfThreads];
+ for (int i = 0; i < numberOfThreads; ++i)
+ {
+ threads[i] = new Thread(new ResultSetMovementStress(createClone(), i));
+ System.out.println("starting thread " + (i + 1) + " of " + (numberOfThreads));
+ threads[i].start();
+ }
+
+ for (int i = 0; i < numberOfThreads; ++i)
+ {
+ threads[i].join();
+ }
+ }
+ catch (Exception e)
+ {
+ fail("testConcurrentAccess failed: " + e);
+ }
+ }
+ // --------------------------------------------------------------------------------------------------------
+
+ @Test public void testRowSetEvents() throws java.lang.Exception
+ {
+ System.out.println("testing RowSet Events");
+ createTestCase(true);
+
+ // first we create our RowSet object
+ final RowSetEventListener pRow = new RowSetEventListener();
+
+ final XColumnsSupplier colSup = UnoRuntime.queryInterface( XColumnsSupplier.class, m_rowSet );
+ final XPropertySet col = UnoRuntime.queryInterface( XPropertySet.class, colSup.getColumns().getByName( "ID" ) );
+ col.addPropertyChangeListener("Value", pRow);
+ m_rowSetProperties.addPropertyChangeListener("IsModified", pRow);
+ m_rowSetProperties.addPropertyChangeListener("IsNew", pRow);
+ m_rowSetProperties.addPropertyChangeListener("IsRowCountFinal", pRow);
+ m_rowSetProperties.addPropertyChangeListener("RowCount", pRow);
+
+ final XRowSetApproveBroadcaster xApBroad = UnoRuntime.queryInterface( XRowSetApproveBroadcaster.class, m_resultSet );
+ xApBroad.addRowSetApproveListener(pRow);
+ m_rowSet.addRowSetListener(pRow);
+
+ // do some movements to check if we got all notifications
+ final Class cResSet = Class.forName("com.sun.star.sdbc.XResultSet");
+ final boolean moves[] = new boolean[9];
+ for (int i = 0; i < moves.length; ++i)
+ {
+ moves[i] = false;
+ }
+ moves[RowSetEventListener.APPROVE_CURSOR_MOVE] = true;
+ moves[RowSetEventListener.COLUMN_VALUE] = true;
+ moves[RowSetEventListener.CURSOR_MOVED] = true;
+ moves[RowSetEventListener.IS_ROW_COUNT_FINAL] = true;
+ moves[RowSetEventListener.ROW_COUNT] = true;
+
+ testCursorMove(m_resultSet, cResSet.getMethod("afterLast", (Class[]) null), pRow, moves, null);
+
+ moves[RowSetEventListener.IS_ROW_COUNT_FINAL] = false;
+ moves[RowSetEventListener.ROW_COUNT] = false;
+ testCursorMove(m_resultSet, cResSet.getMethod(NEXT, (Class[]) null), pRow, moves, null);
+ testCursorMove(m_resultSet, cResSet.getMethod(NEXT, (Class[]) null), pRow, moves, null);
+ testCursorMove(m_resultSet, cResSet.getMethod(NEXT, (Class[]) null), pRow, moves, null);
+ testCursorMove(m_resultSet, cResSet.getMethod("last", (Class[]) null), pRow, moves, null);
+ testCursorMove(m_resultSet, cResSet.getMethod(NEXT, (Class[]) null), pRow, moves, null);
+ testCursorMove(m_resultSet, cResSet.getMethod("first", (Class[]) null), pRow, moves, null);
+ testCursorMove(m_resultSet, cResSet.getMethod("previous", (Class[]) null), pRow, moves, null);
+ testCursorMove(m_resultSet, cResSet.getMethod(NEXT, (Class[]) null), pRow, moves, null);
+ moves[RowSetEventListener.IS_MODIFIED] = true;
+ final XRowUpdate updRow = UnoRuntime.queryInterface( XRowUpdate.class, m_resultSet );
+ updRow.updateString(2, TEST21);
+ testCursorMove(m_resultSet, cResSet.getMethod(NEXT, (Class[]) null), pRow, moves, null);
+
+ moves[RowSetEventListener.IS_MODIFIED] = false;
+ final Class cupd = Class.forName("com.sun.star.sdbc.XResultSetUpdate");
+ final XResultSetUpdate upd = UnoRuntime.queryInterface( XResultSetUpdate.class, m_resultSet );
+ testCursorMove(upd, cupd.getMethod("moveToInsertRow", (Class[]) null), pRow, moves, null);
+
+ updRow.updateInt(1, MAX_TABLE_ROWS + 2);
+ updRow.updateString(2, "HHHH");
+ moves[RowSetEventListener.APPROVE_CURSOR_MOVE] = false;
+ moves[RowSetEventListener.CURSOR_MOVED] = false;
+ moves[RowSetEventListener.IS_MODIFIED] = true;
+ moves[RowSetEventListener.IS_NEW] = true;
+ moves[RowSetEventListener.ROW_COUNT] = true;
+ moves[RowSetEventListener.APPROVE_ROW_CHANGE] = true;
+ moves[RowSetEventListener.ROW_CHANGED] = true;
+ testCursorMove(upd, cupd.getMethod("insertRow", (Class[]) null), pRow, moves, null);
+
+ moves[RowSetEventListener.IS_NEW] = false;
+ moves[RowSetEventListener.ROW_COUNT] = false;
+ m_resultSet.first();
+ updRow.updateInt(1, MAX_TABLE_ROWS + 3);
+ updRow.updateString(2, "__");
+ testCursorMove(upd, cupd.getMethod("updateRow", (Class[]) null), pRow, moves, null);
+
+ moves[RowSetEventListener.IS_NEW] = true;
+ moves[RowSetEventListener.ROW_COUNT] = true;
+ m_resultSet.first();
+ testCursorMove(upd, cupd.getMethod("deleteRow", (Class[]) null), pRow, moves, null);
+
+ moves[RowSetEventListener.IS_NEW] = false;
+ moves[RowSetEventListener.COLUMN_VALUE] = true;
+ moves[RowSetEventListener.ROW_COUNT] = false;
+ m_resultSet.first();
+ updRow.updateString(2, TEST21);
+ testCursorMove(m_resultSet, cResSet.getMethod("refreshRow", (Class[]) null), pRow, moves, null);
+
+ m_resultSet.first();
+ updRow.updateString(2, TEST21);
+ testCursorMove(upd, cupd.getMethod("cancelRowUpdates", (Class[]) null), pRow, moves, null);
+
+ for (int i = 0; i < moves.length; ++i)
+ {
+ moves[i] = false;
+ }
+ moves[RowSetEventListener.APPROVE_CURSOR_MOVE] = true;
+ moves[RowSetEventListener.COLUMN_VALUE] = true;
+ moves[RowSetEventListener.CURSOR_MOVED] = true;
+
+ final Class cloc = Class.forName("com.sun.star.sdbcx.XRowLocate");
+ m_resultSet.first();
+ final Object bookmark = m_rowLocate.getBookmark();
+ m_resultSet.next();
+ final Object temp[] = new Object[1];
+ temp[0] = bookmark;
+ Class ctemp[] = new Class[1];
+ ctemp[0] = Object.class;
+ testCursorMove(m_rowLocate, cloc.getMethod("moveToBookmark", ctemp), pRow, moves, temp);
+
+ final Object temp2[] = new Object[2];
+ temp2[0] = bookmark;
+ temp2[1] = Integer.valueOf(1);
+ final Class ctemp2[] = new Class[2];
+ ctemp2[0] = Object.class;
+ ctemp2[1] = int.class;
+ testCursorMove(m_rowLocate, cloc.getMethod("moveRelativeToBookmark", ctemp2), pRow, moves, temp2);
+
+ for (int i = 0; i < moves.length; ++i)
+ {
+ moves[i] = false;
+ }
+ moves[RowSetEventListener.APPROVE_ROW_CHANGE] = true;
+ moves[RowSetEventListener.ROW_CHANGED] = true;
+ moves[RowSetEventListener.ROW_COUNT] = true;
+ final Class cdelRows = Class.forName("com.sun.star.sdbcx.XDeleteRows");
+ ctemp[0] = Object[].class;
+ final XDeleteRows delRows = UnoRuntime.queryInterface( XDeleteRows.class, m_resultSet );
+ final Object bookmarks[] = new Object[5];
+ m_resultSet.first();
+ for (int i = 0; i < bookmarks.length; ++i)
+ {
+ m_resultSet.next();
+ bookmarks[i] = m_rowLocate.getBookmark();
+ }
+
+ temp[0] = bookmarks;
+ testCursorMove(delRows, cdelRows.getMethod("deleteRows", ctemp), pRow, moves, temp);
+
+ // now destroy the RowSet
+ final XComponent xComp = UnoRuntime.queryInterface( XComponent.class, m_resultSet );
+ xComp.dispose();
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private void testCursorMove(Object res, Method _method, RowSetEventListener _evt, boolean _must[], Object args[]) throws java.lang.Exception
+ {
+ _evt.clearCalling();
+ _method.invoke(res, args);
+
+ System.out.println("testing events for " + _method.getName());
+ final int calling[] = _evt.getCalling();
+ int pos = 1;
+ assertTrue("Callings are not in the correct order for APPROVE_CURSOR_MOVE ",
+ (!_must[RowSetEventListener.APPROVE_CURSOR_MOVE] || calling[RowSetEventListener.APPROVE_CURSOR_MOVE] == -1) || calling[RowSetEventListener.APPROVE_CURSOR_MOVE] == pos++);
+ assertTrue("Callings are not in the correct order for APPROVE_ROW_CHANGE",
+ (!_must[RowSetEventListener.APPROVE_ROW_CHANGE] || calling[RowSetEventListener.APPROVE_ROW_CHANGE] == -1) || calling[RowSetEventListener.APPROVE_ROW_CHANGE] == pos++);
+ assertTrue("Callings are not in the correct order for COLUMN_VALUE",
+ (!_must[RowSetEventListener.COLUMN_VALUE] || calling[RowSetEventListener.COLUMN_VALUE] == -1) || calling[RowSetEventListener.COLUMN_VALUE] == pos++);
+ assertTrue("Callings are not in the correct order for CURSOR_MOVED",
+ (!_must[RowSetEventListener.CURSOR_MOVED] || calling[RowSetEventListener.CURSOR_MOVED] == -1) || calling[RowSetEventListener.CURSOR_MOVED] == pos++);
+ assertTrue("Callings are not in the correct order for ROW_CHANGED",
+ (!_must[RowSetEventListener.ROW_CHANGED] || calling[RowSetEventListener.ROW_CHANGED] == -1) || calling[RowSetEventListener.ROW_CHANGED] == pos++);
+ assertTrue("Callings are not in the correct order for IS_MODIFIED",
+ (!_must[RowSetEventListener.IS_MODIFIED] || calling[RowSetEventListener.IS_MODIFIED] == -1) || calling[RowSetEventListener.IS_MODIFIED] == pos++);
+ assertTrue("Callings are not in the correct order for IS_NEW",
+ (!_must[RowSetEventListener.IS_NEW] || calling[RowSetEventListener.IS_NEW] == -1) || calling[RowSetEventListener.IS_NEW] == pos++);
+ assertTrue("Callings are not in the correct order for ROW_COUNT",
+ (!_must[RowSetEventListener.ROW_COUNT] || calling[RowSetEventListener.ROW_COUNT] == -1) || calling[RowSetEventListener.ROW_COUNT] == pos++);
+ assertTrue("Callings are not in the correct order for IS_ROW_COUNT_FINAL",
+ (!_must[RowSetEventListener.IS_ROW_COUNT_FINAL] || calling[RowSetEventListener.IS_ROW_COUNT_FINAL] == -1) || calling[RowSetEventListener.IS_ROW_COUNT_FINAL] == pos);
+
+ _evt.clearCalling();
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ /** returns the current row count of the RowSet
+ */
+ private int currentRowCount() throws UnknownPropertyException, WrappedTargetException
+ {
+ final Integer rowCount = (Integer) m_rowSetProperties.getPropertyValue("RowCount");
+ return rowCount.intValue();
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ /** positions the row set at an arbitrary position between 2 and (current row count - 1)
+ */
+ private int positionRandom() throws SQLException, UnknownPropertyException, WrappedTargetException
+ {
+ final int position = (new Random()).nextInt(currentRowCount() - 2) + 2;
+ assertTrue("sub task failed: could not position to row no. " + (Integer.valueOf(position)).toString(),
+ m_resultSet.absolute(position));
+ return m_resultSet.getRow();
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ /** moves the result set to a random record between 2 and (current row count - 1), and deletes this record
+ *
+ * After returning from this method, the row set is still positioned at the deleted record
+ * @return
+ * the number/position of the record which has been deleted
+ */
+ private int deleteRandom() throws SQLException, UnknownPropertyException, WrappedTargetException
+ {
+ // check if the current position and the row count in the result set is changed by a deletion (it should not)
+ final int positionBefore = positionRandom();
+ final int rowCountBefore = currentRowCount();
+
+ m_resultSetUpdate.deleteRow();
+
+ final int positionAfter = m_resultSet.getRow();
+ final int rowCountAfter = currentRowCount();
+ assertTrue("position changed during |deleteRow| (it should not)", positionAfter == positionBefore);
+ assertTrue("row count changed with a |deleteRow| (it should not)", rowCountBefore == rowCountAfter);
+ assertTrue("RowSet does not report the current row as deleted after |deleteRow|", m_resultSet.rowDeleted());
+
+ return positionBefore;
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ @Test public void testDeleteBehavior() throws Exception
+ {
+ createTestCase(true);
+
+ // ensure that all records are known
+ m_resultSet.last();
+ final int initialRowCount = currentRowCount();
+
+ // delete a random row
+ int deletedRow = deleteRandom();
+
+ // .....................................................................................................
+ // asking for the bookmark of a deleted row should fail
+ boolean caughtException = false;
+ try
+ {
+ m_rowLocate.getBookmark();
+ }
+ catch (SQLException e)
+ {
+ caughtException = true;
+ }
+ assertTrue("asking for the bookmark of a deleted row should throw an exception", caughtException);
+
+ // .....................................................................................................
+ // isXXX methods should return |false| on a deleted row
+ assertTrue("one of the isFoo failed after |deleteRow|", !m_resultSet.isBeforeFirst() && !m_resultSet.isAfterLast() && !m_resultSet.isFirst() && !m_resultSet.isLast());
+ // note that we can assume that isFirst / isLast also return |false|, since deleteRandom did
+ // not position on the first or last record, but inbetween
+
+ // .....................................................................................................
+ // check if moving away from this row in either direction yields the expected results
+ assertTrue("|previous| after |deleteRow| failed", m_resultSet.previous());
+ final int positionPrevious = m_resultSet.getRow();
+ assertTrue("position after |previous| after |deleteRow| is not as expected", positionPrevious == deletedRow - 1);
+
+ deletedRow = deleteRandom();
+ assertTrue("|next| after |deleteRow| failed", m_resultSet.next());
+ final int positionAfter = m_resultSet.getRow();
+ assertTrue("position after |next| after |deleteRow| is not as expected", positionAfter == deletedRow);
+ // since the deleted record "vanishs" as soon as the cursor is moved away from it, the absolute position does
+ // not change with a |next| call here
+
+ // .....................................................................................................
+ // check if the deleted rows really vanished after moving away from them
+ assertTrue("row count did not change as expected after two deletions", initialRowCount - 2 == currentRowCount());
+
+ // .....................................................................................................
+ // check if the deleted row vanishes after moving to the insertion row
+ final int rowCountBefore = currentRowCount();
+ final int deletedPos = deleteRandom();
+ m_resultSetUpdate.moveToInsertRow();
+ assertTrue("moving to the insertion row immediately after |deleteRow| does not adjust the row count", rowCountBefore == currentRowCount() + 1);
+
+ m_resultSetUpdate.moveToCurrentRow();
+ assertTrue("|moveToCurrentRow| after |deleteRow| + |moveToInsertRow| results in unexpected position",
+ (m_resultSet.getRow() == deletedPos) && !m_resultSet.rowDeleted());
+
+ // the same, but this time with deleting the first row (which is not covered by deleteRandom)
+ m_resultSet.last();
+ m_resultSetUpdate.deleteRow();
+ m_resultSetUpdate.moveToInsertRow();
+ m_resultSetUpdate.moveToCurrentRow();
+ assertTrue("|last| + |deleteRow| + |moveToInsertRow| + |moveToCurrentRow| results in wrong state", m_resultSet.isAfterLast());
+
+ // .....................................................................................................
+ // check if deleting a deleted row fails as expected
+ deleteRandom();
+ caughtException = false;
+ try
+ {
+ m_resultSetUpdate.deleteRow();
+ }
+ catch (SQLException e)
+ {
+ caughtException = true;
+ }
+ assertTrue("deleting a deleted row succeeded - it shouldn't", caughtException);
+
+ // .....................................................................................................
+ // check if deleteRows fails if it contains the bookmark of a previously-deleted row
+ m_resultSet.first();
+ final Object firstBookmark = m_rowLocate.getBookmark();
+ positionRandom();
+ final Object deleteBookmark = m_rowLocate.getBookmark();
+ m_resultSetUpdate.deleteRow();
+ final XDeleteRows multiDelete = UnoRuntime.queryInterface( XDeleteRows.class, m_resultSet );
+ final int[] deleteSuccess = multiDelete.deleteRows(new Object[]
+ {
+ firstBookmark, deleteBookmark
+ });
+ assertTrue("XDeleteRows::deleteRows with the bookmark of an already-deleted row failed",
+ (deleteSuccess.length == 2) && (deleteSuccess[0] != 0) && (deleteSuccess[1] == 0));
+
+ // .....................................................................................................
+ // check if refreshing a deleted row fails as expected
+ deleteRandom();
+ caughtException = false;
+ try
+ {
+ m_resultSet.refreshRow();
+ }
+ catch (SQLException e)
+ {
+ caughtException = true;
+ }
+ assertTrue("refreshing a deleted row succeeded - it shouldn't", caughtException);
+
+ // .....................................................................................................
+ // rowUpdated/rowDeleted
+ deleteRandom();
+ assertTrue("rowDeleted and/or rowUpdated are wrong on a deleted row", !m_resultSet.rowUpdated() && !m_resultSet.rowInserted());
+
+ // .....................................................................................................
+ // updating values in a deleted row should fail
+ deleteRandom();
+ final XRowUpdate rowUpdated = UnoRuntime.queryInterface( XRowUpdate.class, m_resultSet );
+ caughtException = false;
+ try
+ {
+ rowUpdated.updateString(2, TEST21);
+ }
+ catch (SQLException e)
+ {
+ caughtException = true;
+ }
+ assertTrue("updating values in a deleted row should not succeed", caughtException);
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ /** checks whether deletions on the main RowSet properly interfere (or don't interfere) with the movement
+ * on a clone of the RowSet
+ */
+ @SuppressWarnings("empty-statement")
+ @Test public void testCloneMovesPlusDeletions() throws SQLException, UnknownPropertyException, WrappedTargetException
+ {
+ createTestCase(true);
+ // ensure that all records are known
+ m_resultSet.last();
+
+ final XResultSet clone = createClone();
+ final XRowLocate cloneRowLocate = UnoRuntime.queryInterface( XRowLocate.class, clone );
+
+ positionRandom();
+
+ // .....................................................................................................
+ // move the clone to the same record as the RowSet, and delete this record
+ cloneRowLocate.moveToBookmark(m_rowLocate.getBookmark());
+ final int clonePosition = clone.getRow();
+ m_resultSetUpdate.deleteRow();
+
+ assertTrue("clone doesn't know that its current row has been deleted via the RowSet", clone.rowDeleted());
+ assertTrue("clone's position changed somehow during deletion", clonePosition == clone.getRow());
+
+ // .....................................................................................................
+ // move the row set away from the deleted record. This should still not touch the state of the clone
+ m_resultSet.previous();
+
+ assertTrue("clone doesn't know (anymore) that its current row has been deleted via the RowSet", clone.rowDeleted());
+ assertTrue("clone's position changed somehow during deletion and RowSet-movement", clonePosition == clone.getRow());
+
+ // .....................................................................................................
+ // move the clone away from the deleted record
+ clone.next();
+ assertTrue("clone still assumes that its row is deleted - but we already moved it", !clone.rowDeleted());
+
+ // .....................................................................................................
+ // check whether deleting the extremes (first / last) work
+ m_resultSet.first();
+ cloneRowLocate.moveToBookmark(m_rowLocate.getBookmark());
+ m_resultSetUpdate.deleteRow();
+ clone.previous();
+ assertTrue("deleting the first record left the clone in a strange state (after |previous|)", clone.isBeforeFirst());
+ clone.next();
+ assertTrue("deleting the first record left the clone in a strange state (after |previous| + |next|)", clone.isFirst());
+
+ m_resultSet.last();
+ cloneRowLocate.moveToBookmark(m_rowLocate.getBookmark());
+ m_resultSetUpdate.deleteRow();
+ clone.next();
+ assertTrue("deleting the last record left the clone in a strange state (after |next|)", clone.isAfterLast());
+ clone.previous();
+ assertTrue("deleting the first record left the clone in a strange state (after |next| + |previous|)", clone.isLast());
+
+ // .....................................................................................................
+ // check whether movements of the clone interfere with movements of the RowSet, if the latter is on a deleted row
+ final int positionBefore = positionRandom();
+ m_resultSetUpdate.deleteRow();
+ assertTrue("|deleteRow|, but no |rowDeleted| (this should have been found much earlier!)", m_resultSet.rowDeleted());
+ clone.beforeFirst();
+ while (clone.next());
+ assertTrue("row set forgot that the current row is deleted", m_resultSet.rowDeleted());
+
+ assertTrue("moving to the next record after |deleteRow| and clone moves failed", m_resultSet.next());
+ assertTrue("wrong position after |deleteRow| and clone movement", !m_resultSet.isAfterLast() && !m_resultSet.isBeforeFirst());
+ assertTrue("wrong absolute position after |deleteRow| and clone movement", m_resultSet.getRow() == positionBefore);
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ /** checks whether insertions on the main RowSet properly interfere (or don't interfere) with the movement
+ * on a clone of the RowSet
+ */
+ @Test public void testCloneMovesPlusInsertions() throws SQLException, UnknownPropertyException, WrappedTargetException, PropertyVetoException, com.sun.star.lang.IllegalArgumentException
+ {
+ createTestCase(true);
+ // ensure that all records are known
+ m_rowSetProperties.setPropertyValue("FetchSize", Integer.valueOf(10));
+
+ final XResultSet clone = createClone();
+ final XRow cloneRow = UnoRuntime.queryInterface( XRow.class, clone );
+
+ // .....................................................................................................
+ // first check the basic scenario without the |moveToInsertRow| |moveToCurrentRow|, to ensure that
+ // really those are broken, if at all
+ m_resultSet.last();
+ clone.first();
+ clone.absolute(11);
+ clone.first();
+
+ final int rowValue1 = m_row.getInt(1);
+ final int rowPos = m_resultSet.getRow();
+ final int rowValue2 = m_row.getInt(1);
+ assertTrue("repeated query for the same column value delivers different values (" + rowValue1 + " and " + rowValue2 + ") on row: " + rowPos,
+ rowValue1 == rowValue2);
+
+ testPosition(clone, cloneRow, 1, "mixed clone/rowset move: clone check");
+ testPosition(m_resultSet, m_row, MAX_TABLE_ROWS, "mixed clone/rowset move: rowset check");
+
+ // .....................................................................................................
+ // now the complete scenario
+ m_resultSet.last();
+ m_resultSetUpdate.moveToInsertRow();
+ clone.first();
+ clone.absolute(11);
+ clone.first();
+ m_resultSetUpdate.moveToCurrentRow();
+
+ testPosition(clone, cloneRow, 1, "mixed clone/rowset move/insertion: clone check");
+ testPosition(m_resultSet, m_row, 100, "mixed clone/rowset move/insertion: rowset check");
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private void testTableParameters()
+ {
+ // for a row set simply based on a table, there should be not parameters at all
+ createRowSet("products", CommandType.TABLE, false);
+ try
+ {
+ verifyParameters(new String[]
+ {
+ }, "testTableParameters");
+ }
+ catch (Exception e)
+ {
+ fail("testing the parameters of a table failed" + e.getMessage());
+ }
+ }
+ // --------------------------------------------------------------------------------------------------------
+
+ private void testParametersAfterNormalExecute()
+ {
+ try
+ {
+ createRowSet("SELECT * FROM \"customers\"", CommandType.COMMAND, true);
+ m_rowSetProperties.setPropertyValue("Command", "SELECT * FROM \"customers\" WHERE \"City\" = :city");
+ final XParameters rowsetParams = UnoRuntime.queryInterface( XParameters.class, m_rowSet );
+ rowsetParams.setString(1, "London");
+ m_rowSet.execute();
+ }
+ catch (Exception e)
+ {
+ fail("testing the parameters of a table failed" + e.getMessage());
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private void verifyParameters(String[] _paramNames, String _context) throws com.sun.star.uno.Exception
+ {
+ final XIndexAccess params = m_paramsSupplier.getParameters();
+ final int expected = _paramNames.length;
+ final int found = params != null ? params.getCount() : 0;
+
+ assertTrue("wrong number of parameters (expected: " + expected + ", found: " + found + ") in " + _context,
+ found == expected);
+
+ if (found == 0)
+ {
+ return;
+ }
+
+ for (int i = 0; i < expected; ++i)
+ {
+ final XPropertySet parameter = UnoRuntime.queryInterface( XPropertySet.class, params.getByIndex( i ) );
+
+ final String expectedName = _paramNames[i];
+ final String foundName = (String) parameter.getPropertyValue("Name");
+ assertTrue("wrong parameter name (expected: " + expectedName + ", found: " + foundName + ") in" + _context,
+ expectedName.equals(foundName));
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private void testParametrizedQuery()
+ {
+ try
+ {
+ // for a row set based on a parametrized query, those parameters should be properly
+ // recognized
+ m_dataSource.createQuery("products like", "SELECT * FROM \"products\" WHERE \"Name\" LIKE :product_name");
+ createRowSet("products like", CommandType.QUERY, false);
+ verifyParameters(new String[]
+ {
+ "product_name"
+ }, "testParametrizedQuery");
+ }
+ catch (Exception e)
+ {
+ fail("testing the parameters of a parametrized query failed" + e.getMessage());
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private void testParametersInteraction()
+ {
+ try
+ {
+ createRowSet("products like", CommandType.QUERY, false);
+
+ // let's fill in a parameter value via XParameters, and see whether it is respected by the parameters container
+ final XParameters rowsetParams = UnoRuntime.queryInterface(XParameters.class, m_rowSet);
+ rowsetParams.setString(1, "Apples");
+
+ XIndexAccess params = m_paramsSupplier.getParameters();
+ XPropertySet firstParam = UnoRuntime.queryInterface( XPropertySet.class, params.getByIndex( 0 ) );
+ Object firstParamValue = firstParam.getPropertyValue("Value");
+
+ assertTrue("XParameters and the parameters container do not properly interact",
+ "Apples".equals(firstParamValue));
+
+ // let's see whether this also survices an execute of the row set
+ rowsetParams.setString(1, "Oranges");
+ m_rowSet.execute();
+ {
+ // TODO: the following would not be necessary if the parameters container would *survive*
+ // the execution of the row set. It currently doesn't (though the values it represents do).
+ // It would be nice, but not strictly necessary, if it would.
+ params = m_paramsSupplier.getParameters();
+ firstParam = UnoRuntime.queryInterface( XPropertySet.class, params.getByIndex( 0 ) );
+ }
+ firstParamValue = firstParam.getPropertyValue("Value");
+ assertTrue("XParameters and the parameters container do not properly interact, after the row set has been executed",
+ "Oranges".equals(firstParamValue));
+ }
+ catch (Exception e)
+ {
+ fail("could not test the relationship between XParameters and XParametersSupplier" + e.getMessage());
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private void testParametersInFilter()
+ {
+ try
+ {
+ createRowSet("SELECT * FROM \"customers\"", CommandType.COMMAND, false);
+ m_rowSetProperties.setPropertyValue("Filter", "\"City\" = :city");
+
+ m_rowSetProperties.setPropertyValue("ApplyFilter", Boolean.TRUE);
+ verifyParameters(new String[]
+ {
+ "city"
+ }, "testParametersInFilter");
+
+ m_rowSetProperties.setPropertyValue("ApplyFilter", Boolean.FALSE);
+ verifyParameters(new String[]
+ {
+ }, "testParametersInFilter");
+ }
+ catch (Exception e)
+ {
+ fail("testing the parameters within a WHERE clause failed" + e.getMessage());
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ /** checks the XParametersSupplier functionality of a RowSet
+ */
+ @Test public void testParameters()
+ {
+ createTestCase(false);
+ // use an own RowSet instance, not the one which is also used for the other cases
+
+ testTableParameters();
+ testParametrizedQuery();
+ testParametersInFilter();
+
+ testParametersAfterNormalExecute();
+
+ testParametersInteraction();
+ }
+}
+
diff --git a/dbaccess/qa/complex/dbaccess/RowSetEventListener.java b/dbaccess/qa/complex/dbaccess/RowSetEventListener.java
new file mode 100644
index 000000000000..c4569986a5d7
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/RowSetEventListener.java
@@ -0,0 +1,111 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+package complex.dbaccess;
+
+import com.sun.star.sdb.XRowSetApproveListener;
+import com.sun.star.sdbc.XRowSetListener;
+import com.sun.star.sdb.RowChangeEvent;
+import com.sun.star.lang.EventObject;
+import com.sun.star.beans.XPropertyChangeListener;
+
+public class RowSetEventListener implements XRowSetApproveListener,XRowSetListener,XPropertyChangeListener
+{
+ public static final int APPROVE_CURSOR_MOVE = 0;
+ public static final int APPROVE_ROW_CHANGE = 1;
+ public static final int COLUMN_VALUE = 2;
+ public static final int CURSOR_MOVED = 3;
+ public static final int ROW_CHANGED = 4;
+ public static final int IS_MODIFIED = 5;
+ public static final int IS_NEW = 6;
+ public static final int ROW_COUNT = 7;
+ public static final int IS_ROW_COUNT_FINAL = 8;
+
+ int callPos = 1;
+ int calling [];
+
+ RowSetEventListener(){
+ calling = new int [9];
+ clearCalling();
+ }
+ public int[] getCalling(){
+ return calling;
+ }
+ public void clearCalling(){
+ for(int i = 0 ; i < calling.length; ++i){
+ calling[i] = -1;
+ }
+ callPos = 1;
+ }
+ // XEventListener
+ public void disposing(com.sun.star.lang.EventObject event)
+ {
+ }
+ // XRowSetApproveBroadcaster
+ public boolean approveCursorMove(EventObject event)
+ {
+ calling[APPROVE_CURSOR_MOVE] = callPos++;
+ return true;
+ }
+ public boolean approveRowChange(RowChangeEvent event)
+ {
+ calling[APPROVE_ROW_CHANGE] = callPos++;
+ return true;
+ }
+ public boolean approveRowSetChange(EventObject event)
+ {
+ return true;
+ }
+
+ // XRowSetListener
+ public void cursorMoved(com.sun.star.lang.EventObject event)
+ {
+ calling[CURSOR_MOVED] = callPos++;
+ }
+ public void rowChanged(com.sun.star.lang.EventObject event)
+ {
+ calling[ROW_CHANGED] = callPos++;
+ }
+ public void rowSetChanged(com.sun.star.lang.EventObject event)
+ {
+ }
+
+ public void propertyChange(com.sun.star.beans.PropertyChangeEvent propertyChangeEvent) {
+ if ( "Value".equals(propertyChangeEvent.PropertyName) ){
+ calling[COLUMN_VALUE] = callPos++;
+ } else if ( "IsModified".equals(propertyChangeEvent.PropertyName) ){
+ calling[IS_MODIFIED] = callPos++;
+ } else if ( "IsNew".equals(propertyChangeEvent.PropertyName) ){
+ calling[IS_NEW] = callPos++;
+ } else if ( "RowCount".equals(propertyChangeEvent.PropertyName) ){
+ calling[ROW_COUNT] = callPos++;
+ } else if ( "IsRowCountFinal".equals(propertyChangeEvent.PropertyName) ){
+ calling[IS_ROW_COUNT_FINAL] = callPos++;
+ }
+ }
+
+}
diff --git a/dbaccess/qa/complex/dbaccess/SingleSelectQueryComposer.java b/dbaccess/qa/complex/dbaccess/SingleSelectQueryComposer.java
new file mode 100755
index 000000000000..ec77f084063e
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/SingleSelectQueryComposer.java
@@ -0,0 +1,401 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package complex.dbaccess;
+
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.beans.*;
+import com.sun.star.sdbcx.*;
+import com.sun.star.sdb.*;
+import com.sun.star.container.*;
+
+import com.sun.star.sdbc.DataType;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+// ---------- junit imports -----------------
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.openoffice.test.OfficeConnection;
+import static org.junit.Assert.*;
+// ------------------------------------------
+
+public class SingleSelectQueryComposer extends CRMBasedTestCase
+{
+
+ private XSingleSelectQueryComposer m_composer = null;
+ private final static String COMPLEXFILTER = "( \"ID\" = 1 AND \"Postal\" = '4' )" +
+ " OR ( \"ID\" = 2 AND \"Postal\" = '5' )" +
+ " OR ( \"ID\" = '3' AND \"Postal\" = '6' AND \"Address\" = '7' )" +
+ " OR ( \"Address\" = '8' )" +
+ " OR ( \"Postal\" = '9' )";
+ private final static String INNERPRODUCTSQUERY = "products (inner)";
+
+ // --------------------------------------------------------------------------------------------------------
+// public String[] getTestMethodNames()
+// {
+// return new String[]
+// {
+// "testSetCommand",
+// "testAttributes",
+// "testSubQueries",
+// "testParameters",
+// "testDisjunctiveNormalForm",
+// "testConditionByColumn"
+// };
+// }
+
+// // --------------------------------------------------------------------------------------------------------
+// public String getTestObjectName()
+// {
+// return "SingleSelectQueryComposer";
+// }
+
+ // --------------------------------------------------------------------------------------------------------
+ private void createQueries() throws Exception
+ {
+ m_database.getDatabase().getDataSource().createQuery(INNERPRODUCTSQUERY, "SELECT * FROM \"products\"");
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ protected void createTestCase()
+ {
+ try
+ {
+ super.createTestCase();
+
+ createQueries();
+
+ m_composer = createQueryComposer();
+
+ }
+ catch (Exception e)
+ {
+ fail("caught an exception (" + e.getMessage() + ") while creating the test case");
+ }
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ private void checkAttributeAccess(String _attributeName, String _attributeValue)
+ {
+ System.out.println("setting " + _attributeName + " to " + _attributeValue);
+ String realValue = null;
+ try
+ {
+ final Class composerClass = m_composer.getClass();
+ final Method attributeGetter = composerClass.getMethod("get" + _attributeName, new Class[]
+ {
+ });
+ final Method attributeSetter = composerClass.getMethod("set" + _attributeName, new Class[]
+ {
+ String.class
+ });
+
+ attributeSetter.invoke(m_composer, new Object[]
+ {
+ _attributeValue
+ });
+ realValue = (String) attributeGetter.invoke(m_composer, new Object[]
+ {
+ });
+ }
+ catch (NoSuchMethodException e)
+ {
+ }
+ catch (IllegalAccessException e)
+ {
+ }
+ catch (InvocationTargetException e)
+ {
+ }
+ assertTrue("set/get" + _attributeName + " not working as expected (set: " + _attributeValue + ", get: " + (realValue != null ? realValue : "null") + ")",
+ realValue.equals(_attributeValue));
+ System.out.println(" (results in " + m_composer.getQuery() + ")");
+ }
+
+ /** tests setCommand of the composer
+ */
+ @Test public void testSetCommand()
+ {
+ System.out.println("testing SingleSelectQueryComposer's setCommand");
+
+ try
+ {
+ final String table = "SELECT * FROM \"customers\"";
+ m_composer.setCommand("customers",CommandType.TABLE);
+ assertTrue("setCommand/getQuery TABLE inconsistent", m_composer.getQuery().equals(table));
+
+ m_database.getDatabase().getDataSource().createQuery("set command test", "SELECT * FROM \"orders for customer\" \"a\", \"customers\" \"b\" WHERE \"a\".\"Product Name\" = \"b\".\"Name\"");
+ m_composer.setCommand("set command test",CommandType.QUERY);
+ assertTrue("setCommand/getQuery QUERY inconsistent", m_composer.getQuery().equals(m_database.getDatabase().getDataSource().getQueryDefinition("set command test").getCommand()));
+
+ final String sql = "SELECT * FROM \"orders for customer\" WHERE \"Product Name\" = 'test'";
+ m_composer.setCommand(sql,CommandType.COMMAND);
+ assertTrue("setCommand/getQuery COMMAND inconsistent", m_composer.getQuery().equals(sql));
+ }
+ catch (Exception e)
+ {
+ fail("Exception caught: " + e);
+ }
+ }
+ /** tests accessing attributes of the composer (order, filter, group by, having)
+ */
+ @Test public void testAttributes()
+ {
+ System.out.println("testing SingleSelectQueryComposer's attributes (order, filter, group by, having)");
+
+ try
+ {
+ System.out.println("check setElementaryQuery");
+ final String simpleQuery2 = "SELECT * FROM \"customers\" WHERE \"Name\" = 'oranges'";
+ m_composer.setElementaryQuery(simpleQuery2);
+ assertTrue("setElementaryQuery/getQuery inconsistent", m_composer.getQuery().equals(simpleQuery2));
+
+ System.out.println("check setQuery");
+ final String simpleQuery = "SELECT * FROM \"customers\"";
+ m_composer.setQuery(simpleQuery);
+ assertTrue("set/getQuery inconsistent", m_composer.getQuery().equals(simpleQuery));
+
+ checkAttributeAccess("Filter", "\"Name\" = 'oranges'");
+ checkAttributeAccess("Group", "\"City\"");
+ checkAttributeAccess("Order", "\"Address\"");
+ checkAttributeAccess("HavingClause", "\"ID\" <> 4");
+
+ final XIndexAccess orderColumns = m_composer.getOrderColumns();
+ assertTrue("Order columns doesn't exist: \"Address\"",
+ orderColumns != null && orderColumns.getCount() == 1 && orderColumns.getByIndex(0) != null);
+
+ final XIndexAccess groupColumns = m_composer.getGroupColumns();
+ assertTrue("Group columns doesn't exist: \"City\"",
+ groupColumns != null && groupColumns.getCount() == 1 && groupColumns.getByIndex(0) != null);
+
+ // XColumnsSupplier
+ final XColumnsSupplier xSelectColumns = UnoRuntime.queryInterface(XColumnsSupplier.class, m_composer);
+ assertTrue("no select columns, or wrong number of select columns",
+ xSelectColumns != null && xSelectColumns.getColumns() != null && xSelectColumns.getColumns().getElementNames().length == 6);
+
+ // structured filter
+ m_composer.setQuery("SELECT \"ID\", \"Postal\", \"Address\" FROM \"customers\"");
+ m_composer.setFilter(COMPLEXFILTER);
+ final PropertyValue[][] aStructuredFilter = m_composer.getStructuredFilter();
+ m_composer.setFilter("");
+ m_composer.setStructuredFilter(aStructuredFilter);
+ assertTrue("Structured Filter not identical", m_composer.getFilter().equals(COMPLEXFILTER));
+
+ // structured having clause
+ m_composer.setHavingClause(COMPLEXFILTER);
+ final PropertyValue[][] aStructuredHaving = m_composer.getStructuredHavingClause();
+ m_composer.setHavingClause("");
+ m_composer.setStructuredHavingClause(aStructuredHaving);
+ assertTrue("Structured Having Clause not identical", m_composer.getHavingClause().equals(COMPLEXFILTER));
+ }
+ catch (Exception e)
+ {
+ fail("Exception caught: " + e);
+ }
+ }
+
+ /** test various sub query related features ("queries in queries")
+ */
+ @Test public void testSubQueries() throws Exception
+ {
+ m_composer.setQuery("SELECT * from \"" + INNERPRODUCTSQUERY + "\"");
+ final XTablesSupplier suppTables = UnoRuntime.queryInterface(XTablesSupplier.class, m_composer);
+ final XNameAccess tables = suppTables.getTables();
+ assertTrue("a simple SELECT * FROM <query> could not be parsed",
+ tables != null && tables.hasByName(INNERPRODUCTSQUERY));
+
+ final String sInnerCommand = m_database.getDatabase().getDataSource().getQueryDefinition(INNERPRODUCTSQUERY).getCommand();
+ final String sExecutableQuery = m_composer.getQueryWithSubstitution();
+ assertTrue("simple query containing a sub query improperly parsed to SDBC level statement: \n1. " + sExecutableQuery + "\n2. " + "SELECT * FROM ( " + sInnerCommand + " ) AS \"" + INNERPRODUCTSQUERY + "\"",
+ sExecutableQuery.equals("SELECT * FROM ( " + sInnerCommand + " ) AS \"" + INNERPRODUCTSQUERY + "\""));
+ }
+
+ /** tests the XParametersSupplier functionality
+ */
+ @Test public void testParameters()
+ {
+ try
+ {
+ // "orders for customers" is a query with a named parameter (based on another query)
+ m_database.getDatabase().getDataSource().createQuery("orders for customer", "SELECT * FROM \"all orders\" WHERE \"Customer Name\" LIKE :cname");
+ // "orders for customer and product" is query based on "orders for customers", adding an additional,
+ // anonymous parameter
+ m_database.getDatabase().getDataSource().createQuery("orders for customer and product", "SELECT * FROM \"orders for customer\" WHERE \"Product Name\" LIKE ?");
+
+ m_composer.setQuery(m_database.getDatabase().getDataSource().getQueryDefinition("orders for customer and product").getCommand());
+ final XParametersSupplier suppParams = UnoRuntime.queryInterface(XParametersSupplier.class, m_composer);
+ final XIndexAccess parameters = suppParams.getParameters();
+
+ final String expectedParamNames[] =
+ {
+ "cname",
+ "Product Name"
+ };
+
+ final int paramCount = parameters.getCount();
+ assertTrue("composer did find wrong number of parameters in the nested queries.",
+ paramCount == expectedParamNames.length);
+
+ for (int i = 0; i < paramCount; ++i)
+ {
+ final XPropertySet parameter = UnoRuntime.queryInterface(XPropertySet.class, parameters.getByIndex(i));
+ final String paramName = (String) parameter.getPropertyValue("Name");
+ assertTrue("wrong parameter name at position " + (i + 1) + " (expected: " + expectedParamNames[i] + ", found: " + paramName + ")",
+ paramName.equals(expectedParamNames[i]));
+
+ }
+ }
+ catch (Exception e)
+ {
+ fail("caught an exception: " + e);
+ }
+ }
+
+ @Test public void testConditionByColumn()
+ {
+ try
+ {
+ m_composer.setQuery("SELECT * FROM \"customers\"");
+
+ final Object initArgs[] =
+ {
+ new NamedValue("AutomaticAddition", Boolean.valueOf(true))
+ };
+ final String serviceName = "com.sun.star.beans.PropertyBag";
+ final XPropertyContainer filter = UnoRuntime.queryInterface(XPropertyContainer.class, getMSF().createInstanceWithArguments(serviceName, initArgs));
+ filter.addProperty("Name", PropertyAttribute.MAYBEVOID, "Comment");
+ filter.addProperty("RealName", PropertyAttribute.MAYBEVOID, "Comment");
+ filter.addProperty("TableName", PropertyAttribute.MAYBEVOID, "customers");
+ filter.addProperty("Value", PropertyAttribute.MAYBEVOID, "Good one.");
+ filter.addProperty("Type", PropertyAttribute.MAYBEVOID, Integer.valueOf(DataType.LONGVARCHAR));
+ final XPropertySet column = UnoRuntime.queryInterface(XPropertySet.class, filter);
+
+ m_composer.appendFilterByColumn(column, true,SQLFilterOperator.LIKE);
+ assertTrue("At least one row should exist",m_database.getConnection().createStatement().executeQuery(m_composer.getQuery()).next());
+
+ }
+ catch (Exception e)
+ {
+ // this is an error: the query is expected to be parseable
+ fail("caught an exception: " + e);
+ }
+ }
+
+ private void impl_testDisjunctiveNormalForm(String _query, PropertyValue[][] _expectedDNF)
+ {
+ try
+ {
+ m_composer.setQuery(_query);
+ }
+ catch (Exception e)
+ {
+ // this is an error: the query is expected to be parseable
+ fail("caught an exception: " + e);
+ }
+
+ final PropertyValue[][] disjunctiveNormalForm = m_composer.getStructuredFilter();
+
+ assertEquals("DNF: wrong number of rows", _expectedDNF.length, disjunctiveNormalForm.length);
+ for (int i = 0; i < _expectedDNF.length; ++i)
+ {
+ assertEquals("DNF: wrong number of columns in row " + i, _expectedDNF[i].length, disjunctiveNormalForm[i].length);
+ for (int j = 0; j < _expectedDNF[i].length; ++j)
+ {
+ assertEquals("DNF: wrong content in column " + j + ", row " + i,
+ _expectedDNF[i][j].Name, disjunctiveNormalForm[i][j].Name);
+ }
+ }
+ }
+
+ /** tests the disjunctive normal form functionality, aka the structured filter,
+ * of the composer
+ */
+ @Test public void testDisjunctiveNormalForm()
+ {
+ // a simple case: WHERE clause simply is a combination of predicates knitted with AND
+ String query =
+ "SELECT \"customers\".\"Name\", " +
+ "\"customers\".\"Address\", " +
+ "\"customers\".\"City\", " +
+ "\"customers\".\"Postal\", " +
+ "\"products\".\"Name\" " +
+ "FROM \"orders\", \"customers\", \"orders_details\", \"products\" " +
+ "WHERE ( \"orders\".\"CustomerID\" = \"customers\".\"ID\" " +
+ "AND \"orders_details\".\"OrderID\" = \"orders\".\"ID\" " +
+ "AND \"orders_details\".\"ProductID\" = \"products\".\"ID\" " +
+ ") ";
+
+ impl_testDisjunctiveNormalForm(query, new PropertyValue[][]
+ {
+ new PropertyValue[]
+ {
+ new PropertyValue("CustomerID", SQLFilterOperator.EQUAL, "\"customers\".\"ID\"", PropertyState.DIRECT_VALUE),
+ new PropertyValue("OrderID", SQLFilterOperator.EQUAL, "\"orders\".\"ID\"", PropertyState.DIRECT_VALUE),
+ new PropertyValue("ProductID", SQLFilterOperator.EQUAL, "\"products\".\"ID\"", PropertyState.DIRECT_VALUE)
+ }
+ });
+
+ // somewhat more challenging: One of the conjunction terms is a disjunction itself
+ query =
+ "SELECT \"customers\".\"Name\", " +
+ "\"customers\".\"Address\", " +
+ "\"customers\".\"City\", " +
+ "\"customers\".\"Postal\", " +
+ "\"products\".\"Name\" " +
+ "FROM \"orders\", \"customers\", \"orders_details\", \"products\" " +
+ "WHERE ( \"orders\".\"CustomerID\" = \"customers\".\"ID\" " +
+ "AND \"orders_details\".\"OrderID\" = \"orders\".\"ID\" " +
+ "AND \"orders_details\".\"ProductID\" = \"products\".\"ID\" " +
+ ") " +
+ "AND " +
+ "( \"products\".\"Name\" = 'Apples' " +
+ "OR \"products\".\"ID\" = 2 " +
+ ")";
+
+ impl_testDisjunctiveNormalForm(query, new PropertyValue[][]
+ {
+ new PropertyValue[]
+ {
+ new PropertyValue("CustomerID", SQLFilterOperator.EQUAL, "\"customers\".\"ID\"", PropertyState.DIRECT_VALUE),
+ new PropertyValue("OrderID", SQLFilterOperator.EQUAL, "\"orders\".\"ID\"", PropertyState.DIRECT_VALUE),
+ new PropertyValue("ProductID", SQLFilterOperator.EQUAL, "\"products\".\"ID\"", PropertyState.DIRECT_VALUE),
+ new PropertyValue("Name", SQLFilterOperator.EQUAL, "Apples", PropertyState.DIRECT_VALUE)
+ },
+ new PropertyValue[]
+ {
+ new PropertyValue("CustomerID", SQLFilterOperator.EQUAL, "\"customers\".\"ID\"", PropertyState.DIRECT_VALUE),
+ new PropertyValue("OrderID", SQLFilterOperator.EQUAL, "\"orders\".\"ID\"", PropertyState.DIRECT_VALUE),
+ new PropertyValue("ProductID", SQLFilterOperator.EQUAL, "\"products\".\"ID\"", PropertyState.DIRECT_VALUE),
+ new PropertyValue("ID", SQLFilterOperator.EQUAL, Integer.valueOf(2), PropertyState.DIRECT_VALUE)
+ }
+ });
+
+ }
+}
diff --git a/dbaccess/qa/complex/dbaccess/TestCase.java b/dbaccess/qa/complex/dbaccess/TestCase.java
new file mode 100644
index 000000000000..ba899a114205
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/TestCase.java
@@ -0,0 +1,163 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package complex.dbaccess;
+
+import com.sun.star.beans.PropertyValue;
+import com.sun.star.beans.XPropertySet;
+import com.sun.star.frame.XComponentLoader;
+import com.sun.star.frame.XModel;
+import com.sun.star.lang.XMultiServiceFactory;
+// import com.sun.star.uno.Exception;
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.uno.XComponentContext;
+import helper.FileTools;
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+// ---------- junit imports -----------------
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.openoffice.test.OfficeConnection;
+import static org.junit.Assert.*;
+// ------------------------------------------
+
+
+public abstract class TestCase
+{
+ // --------------------------------------------------------------------------------------------------------
+// protected final XMultiServiceFactory getORB()
+// {
+// return (XMultiServiceFactory)param.getMSF();
+// }
+
+ // --------------------------------------------------------------------------------------------------------
+ protected final XComponentContext getComponentContext()
+ {
+ XComponentContext context = null;
+ try
+ {
+ final XPropertySet orbProps = UnoRuntime.queryInterface( XPropertySet.class, getMSF() );
+ context = UnoRuntime.queryInterface( XComponentContext.class,
+ orbProps.getPropertyValue( "DefaultContext" ) );
+ }
+ catch ( Exception ex )
+ {
+ fail( "could not retrieve the ComponentContext" );
+ }
+ return context;
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ public void before() throws java.lang.Exception
+ {
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ public void after() throws java.lang.Exception
+ {
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ /** returns the URL of a temporary file which can be used during the test.
+ *
+ * The file will be deleted when the process exits
+ * @return the URL of a temporary file
+ */
+ protected final String createTempFileURL() throws IOException
+ {
+ final File documentFile = java.io.File.createTempFile( "dbaccess_test", ".odb" ).getAbsoluteFile();
+ if ( documentFile.exists() )
+ {
+ documentFile.delete();
+ }
+ return FileHelper.getOOoCompatibleFileURL( documentFile.toURI().toURL().toString() );
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ /**
+ * copies the file given by URL to a temporary file
+ * @return
+ * the URL of the new file
+ */
+ protected final String copyToTempFile( String _sourceURL ) throws IOException
+ {
+ final String targetURL = createTempFileURL();
+ try
+ {
+ FileTools.copyFile( new File( new URI( _sourceURL ) ), new File( new URI( targetURL ) ) );
+ }
+ catch ( URISyntaxException e ) { }
+
+ return FileHelper.getOOoCompatibleFileURL( targetURL );
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+ protected final XModel loadDocument( final String _docURL ) throws Exception
+ {
+ final XComponentLoader loader = UnoRuntime.queryInterface( XComponentLoader.class,
+ getMSF().createInstance( "com.sun.star.frame.Desktop" ) );
+ return UnoRuntime.queryInterface( XModel.class,
+ loader.loadComponentFromURL( _docURL, "_blank", 0, new PropertyValue[] {} ) );
+ }
+
+ // --------------------------------------------------------------------------------------------------------
+// protected void assureException( Object _object, Class _unoInterfaceClass, String _methodName, Object[] _methodArgs,
+// Class _expectedExceptionClass )
+// {
+// assureException( UnoRuntime.queryInterface( _unoInterfaceClass, _object ), _methodName,
+// _methodArgs, _expectedExceptionClass );
+// }
+
+
+
+ protected XMultiServiceFactory getMSF()
+ {
+ final XMultiServiceFactory xMSF1 = UnoRuntime.queryInterface(XMultiServiceFactory.class, connection.getComponentContext().getServiceManager());
+ return xMSF1;
+ }
+
+ // setup and close connections
+ @BeforeClass public static void setUpConnection() throws Exception {
+ System.out.println("setUpConnection()");
+ connection.setUp();
+ }
+
+ @AfterClass public static void tearDownConnection()
+ throws InterruptedException, com.sun.star.uno.Exception
+ {
+ System.out.println("tearDownConnection()");
+ connection.tearDown();
+ }
+
+ private static final OfficeConnection connection = new OfficeConnection();
+
+}
diff --git a/dbaccess/qa/complex/dbaccess/UISettings.java b/dbaccess/qa/complex/dbaccess/UISettings.java
new file mode 100644
index 000000000000..8733f000f644
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/UISettings.java
@@ -0,0 +1,160 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+package complex.dbaccess;
+
+import com.sun.star.awt.FontSlant;
+import com.sun.star.awt.TextAlign;
+import com.sun.star.beans.XPropertySet;
+import com.sun.star.container.XNameAccess;
+import com.sun.star.form.runtime.XFormController;
+import com.sun.star.frame.XController;
+import com.sun.star.sdb.application.DatabaseObject;
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.util.XCloseable;
+import connectivity.tools.CRMDatabase;
+
+// ---------- junit imports -----------------
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.openoffice.test.OfficeConnection;
+import static org.junit.Assert.*;
+// ------------------------------------------
+
+public class UISettings extends TestCase
+{
+ // --------------------------------------------------------------------------------------------------------
+// public String[] getTestMethodNames()
+// {
+// return new String[] {
+// "checkTableFormattingPersistence",
+// "checkTransparentQueryColumnSettings"
+// };
+// }
+//
+// // --------------------------------------------------------------------------------------------------------
+// public String getTestObjectName()
+// {
+// return "UISettings";
+// }
+
+ // --------------------------------------------------------------------------------------------------------
+ /** verifies that aliases for inner queries work as expected
+ */
+ @Test public void checkTableFormattingPersistence() throws java.lang.Exception
+ {
+ // create, load, and connect a DB doc
+ CRMDatabase database = new CRMDatabase( getMSF(), true );
+
+ // display a table
+ XFormController tableViewController = UnoRuntime.queryInterface( XFormController.class,
+ database.loadSubComponent( DatabaseObject.TABLE, "customers" ) );
+ XPropertySet tableControlModel = UnoRuntime.queryInterface( XPropertySet.class,
+ tableViewController.getCurrentControl().getModel() );
+
+ // change the table's formatting
+ tableControlModel.setPropertyValue( "FontName", "Andale Sans UI" );
+ tableControlModel.setPropertyValue( "FontHeight", Float.valueOf( 20 ) );
+ tableControlModel.setPropertyValue( "FontSlant", FontSlant.ITALIC );
+
+ String docURL = database.getDatabase().getModel().getURL();
+
+ // save close the database document
+ database.saveAndClose();
+
+ // load a copy of the document
+ // normally, it should be sufficient to load the same doc. However, there might be objects in the Java VM
+ // which are not yet freed, and which effectively hold the document alive. More precise: The document (|doc|)
+ // is certainly disposed, but other objects might hold a reference to one of the many other components
+ // around the database document, the data source, the connection, etc. As long as those objects are
+ // not cleaned up, the "database model impl" - the structure holding all document data - will
+ // stay alive, and subsequent requests to load the doc will just reuse it, without really loading it.
+ docURL = copyToTempFile( docURL );
+ loadDocument( docURL );
+ database = new CRMDatabase( getMSF(), docURL );
+
+ // display the table, again
+ tableViewController = UnoRuntime.queryInterface( XFormController.class,
+ database.loadSubComponent( DatabaseObject.TABLE, "customers" ) );
+ tableControlModel = UnoRuntime.queryInterface( XPropertySet.class,
+ tableViewController.getCurrentControl().getModel() );
+
+ // verify the properties
+ assertEquals( "wrong font name", "Andale Sans UI", (String)tableControlModel.getPropertyValue( "FontName" ) );
+ assertEquals( "wrong font height", (float)20, ((Float)tableControlModel.getPropertyValue( "FontHeight" )).floatValue() );
+ assertEquals( "wrong font slant", FontSlant.ITALIC, (FontSlant)tableControlModel.getPropertyValue( "FontSlant" ) );
+
+ // close the doc
+ database.saveAndClose();
+ }
+
+ /**
+ * checks whether query columns use the settings of the underlying table column, if they do not (yet) have own
+ * settings
+ * @throws java.lang.Exception
+ */
+ @Test public void checkTransparentQueryColumnSettings() throws java.lang.Exception
+ {
+ // create, load, and connect a DB doc
+ CRMDatabase database = new CRMDatabase( getMSF(), true );
+
+ // display a table
+ XController tableView = database.loadSubComponent( DatabaseObject.TABLE, "customers" );
+ XFormController tableViewController = UnoRuntime.queryInterface( XFormController.class,
+ tableView );
+ XNameAccess tableControlModel = UnoRuntime.queryInterface( XNameAccess.class,
+ tableViewController.getCurrentControl().getModel() );
+
+ // change the formatting of a table column
+ XPropertySet idColumn = UnoRuntime.queryInterface( XPropertySet.class, tableControlModel.getByName( "ID" ) );
+ assertTrue( "precondition not met: column already centered",
+ ((Short)idColumn.getPropertyValue( "Align" )).shortValue() != TextAlign.CENTER );
+ idColumn.setPropertyValue( "Align", TextAlign.CENTER );
+
+ // close the table data view
+ XCloseable closeSubComponent = UnoRuntime.queryInterface( XCloseable.class, tableView.getFrame() );
+ closeSubComponent.close( true );
+
+ // create a query based on that column
+ database.getDatabase().getDataSource().createQuery( "q_customers", "SELECT * FROM \"customers\"" );
+
+ // load this query, and verify the table column settings was propagated to the query column
+ XFormController queryViewController = UnoRuntime.queryInterface( XFormController.class,
+ database.loadSubComponent( DatabaseObject.QUERY, "q_customers" ) );
+ tableControlModel = UnoRuntime.queryInterface( XNameAccess.class,
+ queryViewController.getCurrentControl().getModel() );
+ idColumn = UnoRuntime.queryInterface( XPropertySet.class, tableControlModel.getByName( "ID" ) );
+
+ assertTrue( "table column alignment was not propagated to the query column",
+ ((Short)idColumn.getPropertyValue( "Align" )).shortValue() == TextAlign.CENTER );
+
+ // save close the database document
+ database.saveAndClose();
+ }
+}
diff --git a/dbaccess/qa/complex/dbaccess/dbaccess.sce b/dbaccess/qa/complex/dbaccess/dbaccess.sce
new file mode 100644
index 000000000000..c5fa408ff273
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/dbaccess.sce
@@ -0,0 +1,12 @@
+-o complex.dbaccess.SingleSelectQueryComposer
+-o complex.dbaccess.RowSet
+-o complex.dbaccess.PropertyBag
+-o complex.dbaccess.Query
+-o complex.dbaccess.QueryInQuery
+-o complex.dbaccess.DatabaseDocument
+-o complex.dbaccess.DataSource
+-o complex.dbaccess.Parser
+-o complex.dbaccess.ApplicationController
+-o complex.dbaccess.CopyTableWizard
+-o complex.dbaccess.UISettings
+-o complex.dbaccess.Beamer
diff --git a/dbaccess/qa/complex/dbaccess/makefile.mk b/dbaccess/qa/complex/dbaccess/makefile.mk
new file mode 100755
index 000000000000..4a3e0426fe1d
--- /dev/null
+++ b/dbaccess/qa/complex/dbaccess/makefile.mk
@@ -0,0 +1,133 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+.IF "$(OOO_SUBSEQUENT_TESTS)" == ""
+nothing .PHONY:
+.ELSE
+
+PRJ = ../../..
+PRJNAME = dbaccess
+TARGET = qa_complex_dbaccess
+
+.IF "$(OOO_JUNIT_JAR)" != ""
+PACKAGE = complex/dbaccess
+
+# here store only Files which contain a @Test
+JAVATESTFILES = \
+ ApplicationController.java \
+ Beamer.java \
+ CRMBasedTestCase.java \
+ CopyTableWizard.java \
+ DataSource.java \
+ DatabaseDocument.java \
+ Parser.java \
+ PropertyBag.java \
+ Query.java \
+ QueryInQuery.java \
+ RowSet.java \
+ SingleSelectQueryComposer.java \
+ UISettings.java \
+ TestCase.java
+
+# put here all other files
+JAVAFILES = $(JAVATESTFILES) \
+ CopyTableInterActionHandler.java \
+ DatabaseApplication.java \
+ FileHelper.java \
+ RowSetEventListener.java
+
+
+JARFILES = OOoRunner.jar ridl.jar test.jar unoil.jar ConnectivityTools.jar
+EXTRAJARFILES = $(OOO_JUNIT_JAR)
+
+# Sample how to debug
+# JAVAIFLAGS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,address=9003,suspend=y
+
+.END
+
+.INCLUDE: settings.mk
+.INCLUDE: target.mk
+.INCLUDE: installationtest.mk
+
+ALLTAR : javatest
+
+.END
+
+
+#
+#
+# PRJ = ..$/..$/..
+# TARGET = DbaComplexTests
+# PRJNAME = $(TARGET)
+# PACKAGE = complex$/dbaccess
+#
+# # --- Settings -----------------------------------------------------
+# .INCLUDE: settings.mk
+#
+# .IF "$(SOLAR_JAVA)" == ""
+# all:
+# @echo "Java not available. Build skipped"
+#
+# .INCLUDE : target.mk
+# .ELSE
+#
+# #----- compile .java files -----------------------------------------
+#
+# JARFILES = ridl.jar unoil.jar jurt.jar juh.jar java_uno.jar OOoRunner.jar ConnectivityTools.jar
+# JAVAFILES := $(shell @$(FIND) ./*.java)
+# JAVACLASSFILES = $(foreach,i,$(JAVAFILES) $(CLASSDIR)$/$(PACKAGE)$/$(i:b).class)
+#
+# #----- make a jar from compiled files ------------------------------
+#
+# MAXLINELENGTH = 100000
+#
+# JARCLASSDIRS = $(PACKAGE)
+# JARTARGET = $(TARGET).jar
+# JARCOMPRESS = TRUE
+#
+# RUNNER_ARGS = -cp "$(CLASSPATH)$(PATH_SEPERATOR)$(SOLARBINDIR)$/OOoRunner.jar" org.openoffice.Runner -TestBase java_complex
+#
+# RUNNER_CALL = $(AUGMENT_LIBRARY_PATH) java
+#
+# # --- Targets ------------------------------------------------------
+#
+# .IF "$(depend)" == ""
+# ALL : ALLTAR
+# .ELSE
+# ALL: ALLDEP
+# .ENDIF
+#
+# .INCLUDE : target.mk
+#
+#
+# run: $(CLASSDIR)$/$(JARTARGET)
+# +$(RUNNER_CALL) $(RUNNER_ARGS) -sce dbaccess.sce
+#
+# run_%: $(CLASSDIR)$/$(JARTARGET)
+# +$(RUNNER_CALL) $(RUNNER_ARGS) -o complex.dbaccess.$(@:s/run_//)
+#
+# .ENDIF # "$(SOLAR_JAVA)" == ""
diff --git a/dbaccess/qa/unoapi/Test.java b/dbaccess/qa/unoapi/Test.java
new file mode 100644
index 000000000000..4f2409fdc8bd
--- /dev/null
+++ b/dbaccess/qa/unoapi/Test.java
@@ -0,0 +1,52 @@
+/*************************************************************************
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2000, 2010 Oracle and/or its affiliates.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* OpenOffice.org is free software: you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License version 3
+* only, as published by the Free Software Foundation.
+*
+* OpenOffice.org is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU Lesser General Public License version 3 for more details
+* (a copy is included in the LICENSE file that accompanied this code).
+*
+* You should have received a copy of the GNU Lesser General Public License
+* version 3 along with OpenOffice.org. If not, see
+* <http://www.openoffice.org/license.html>
+* for a copy of the LGPLv3 License.
+************************************************************************/
+
+package org.openoffice.dbaccess.qa.unoapi;
+
+import org.openoffice.Runner;
+import org.openoffice.test.OfficeConnection;
+import static org.junit.Assert.*;
+
+public final class Test {
+ @org.junit.Before public void setUp() throws Exception {
+ connection.setUp();
+ }
+
+ @org.junit.After public void tearDown()
+ throws InterruptedException, com.sun.star.uno.Exception
+ {
+ connection.tearDown();
+ }
+
+ @org.junit.Test public void test() {
+ assertTrue(
+ Runner.run(
+ "-sce", "dbaccess.sce", "-xcl", "knownissues.xcl", "-ini",
+ "dbaccess.props", "-tdoc", "testdocuments", "-cs",
+ connection.getDescription()));
+ }
+
+ private final OfficeConnection connection = new OfficeConnection();
+}
diff --git a/dbaccess/qa/unoapi/dbaccess.props b/dbaccess/qa/unoapi/dbaccess.props
new file mode 100644
index 000000000000..0380eda38ad2
--- /dev/null
+++ b/dbaccess/qa/unoapi/dbaccess.props
@@ -0,0 +1,6 @@
+#properties needed for dbbaccess
+
+jdbc.url=mysql://unoapi:3306/testDB
+jdbc.user=unoapi
+jdbc.password=unoapi
+mysql.url=sdbc:mysql:jdbc:unoapi:3306/TestDB
diff --git a/dbaccess/qa/unoapi/dbaccess.sce b/dbaccess/qa/unoapi/dbaccess.sce
new file mode 100644
index 000000000000..798a841d223d
--- /dev/null
+++ b/dbaccess/qa/unoapi/dbaccess.sce
@@ -0,0 +1,15 @@
+#i84113 -o dbaccess.ConnectionLineAccessibility
+-o dbaccess.DBContentLoader
+#i84114 -o dbaccess.JoinViewAccessibility
+-o dbaccess.OCommandDefinition
+-o dbaccess.ODatabaseContext
+-o dbaccess.ODatabaseSource
+-o dbaccess.ODatasourceAdministrationDialog
+#i98007 -o dbaccess.ODatasourceBrowser
+-o dbaccess.OInteractionHandler
+#i84116 -o dbaccess.OQueryDesign
+-o dbaccess.ORowSet
+-o dbaccess.OSQLMessageDialog
+-o dbaccess.OSingleSelectQueryComposer
+#i95611 -o dbaccess.SbaXGridControl
+#i84128 -o dbaccess.TableWindowAccessibility
diff --git a/dbaccess/qa/unoapi/knownissues.xcl b/dbaccess/qa/unoapi/knownissues.xcl
new file mode 100644
index 000000000000..26403dab10fe
--- /dev/null
+++ b/dbaccess/qa/unoapi/knownissues.xcl
@@ -0,0 +1,62 @@
+### 114044 ###
+dbaccess.ORowSet::com::sun::star::sdbc::XWarningsSupplier
+
+### i38209 ###
+dbaccess.ODatasourceAdministrationDialog::com::sun::star::sdb::DatasourceAdministrationDialog
+
+### i55579 ###
+dbaccess.OQueryDesign::com::sun::star::frame::XController
+
+### i84113 ###
+dbaccess.ConnectionLineAccessibility
+# -> disabled in dbaccess.sce
+
+### i84114 ###
+dbaccess.JoinViewAccessibility
+# -> disabled in dbaccess.sce
+
+### i84116 ###
+dbaccess.OQueryDesign
+# -> disabled in dbaccess.sce
+
+### i84125 ###
+dbaccess.SbaXGridControl::com::sun::star::view::XSelectionSupplier
+
+### i84127 ###
+dbaccess.SbaXGridControl::com::sun::star::awt::XWindow
+
+### i86990 ###
+dbaccess.ODatabaseSource::com::sun::star::beans::XPropertySet
+dbaccess.OCommandDefinition::com::sun::star::beans::XPropertySet
+
+### i84128 ###
+dbaccess.TableWindowAccessibility
+# -> disabled in dbaccess.sce
+
+### i87247 ###
+dbaccess.DBContentLoader::com::sun::star::frame::XFrameLoader
+
+### i88646 ###
+dbaccess.ODatabaseContext::com::sun::star::uno::XNamingService
+
+### i90358 ###
+dbaccess.SbaXGridControl::com::sun::star::awt::XView
+
+### i90359 ###
+dbaccess.ODatabaseSource::com::sun::star::sdb::DataSource
+
+### i95611 ###
+dbaccess.SbaXGridControl
+# -> disabled in dbaccess.sce
+
+### i95691 ###
+dbaccess.ORowSet::com::sun::star::sdbc::XRowUpdate
+dbaccess.ORowSet::com::sun::star::sdbc::XRow
+
+## i97860 ###
+dbaccess.ORowSet::com::sun::star::sdbcx::XDeleteRows
+dbaccess.ORowSet::com::sun::star::sdbc::XResultSetUpdate
+
+### i98007 ###
+dbaccess.ODatasourceBrowser
+# -> disabled in dbaccess.sce \ No newline at end of file
diff --git a/dbaccess/qa/unoapi/makefile.mk b/dbaccess/qa/unoapi/makefile.mk
new file mode 100644
index 000000000000..41ed9480f526
--- /dev/null
+++ b/dbaccess/qa/unoapi/makefile.mk
@@ -0,0 +1,48 @@
+#*************************************************************************
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#***********************************************************************/
+
+.IF "$(OOO_SUBSEQUENT_TESTS)" == ""
+nothing .PHONY:
+.ELSE
+
+PRJ = ../..
+PRJNAME = dbaccess
+TARGET = qa_unoapi
+
+.IF "$(OOO_JUNIT_JAR)" != ""
+PACKAGE = org/openoffice/dbaccess/qa/unoapi
+JAVATESTFILES = Test.java
+JAVAFILES = $(JAVATESTFILES)
+JARFILES = OOoRunner.jar ridl.jar test.jar
+EXTRAJARFILES = $(OOO_JUNIT_JAR)
+.END
+
+.INCLUDE: settings.mk
+.INCLUDE: target.mk
+.INCLUDE: installationtest.mk
+
+ALLTAR : javatest
+
+.END
diff --git a/dbaccess/qa/unoapi/testdocuments/TestDB/testDB.dbf b/dbaccess/qa/unoapi/testdocuments/TestDB/testDB.dbf
new file mode 100755
index 000000000000..c3af1e143938
--- /dev/null
+++ b/dbaccess/qa/unoapi/testdocuments/TestDB/testDB.dbf
Binary files differ
diff --git a/dbaccess/qa/unoapi/testdocuments/TestDB/testDB.dbt b/dbaccess/qa/unoapi/testdocuments/TestDB/testDB.dbt
new file mode 100755
index 000000000000..41cb9d24cdc4
--- /dev/null
+++ b/dbaccess/qa/unoapi/testdocuments/TestDB/testDB.dbt
Binary files differ