1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir * 7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * This file is part of OpenOffice.org. 10*cdf0e10cSrcweir * 11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir * 15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir * 21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir * 26*cdf0e10cSrcweir ************************************************************************/ 27*cdf0e10cSrcweir package connectivity.tools; 28*cdf0e10cSrcweir 29*cdf0e10cSrcweir import com.sun.star.beans.PropertyValue; 30*cdf0e10cSrcweir import com.sun.star.beans.PropertyState; 31*cdf0e10cSrcweir import com.sun.star.container.ElementExistException; 32*cdf0e10cSrcweir import com.sun.star.container.NoSuchElementException; 33*cdf0e10cSrcweir import com.sun.star.frame.XComponentLoader; 34*cdf0e10cSrcweir import com.sun.star.frame.XController; 35*cdf0e10cSrcweir import com.sun.star.frame.XModel; 36*cdf0e10cSrcweir import com.sun.star.io.IOException; 37*cdf0e10cSrcweir import com.sun.star.lang.IllegalArgumentException; 38*cdf0e10cSrcweir import com.sun.star.lang.WrappedTargetException; 39*cdf0e10cSrcweir import com.sun.star.lang.XComponent; 40*cdf0e10cSrcweir import com.sun.star.lang.XMultiServiceFactory; 41*cdf0e10cSrcweir import com.sun.star.sdb.XSingleSelectQueryComposer; 42*cdf0e10cSrcweir import com.sun.star.sdb.application.XDatabaseDocumentUI; 43*cdf0e10cSrcweir import com.sun.star.sdbc.SQLException; 44*cdf0e10cSrcweir import com.sun.star.sdbcx.XTablesSupplier; 45*cdf0e10cSrcweir import com.sun.star.uno.UnoRuntime; 46*cdf0e10cSrcweir import com.sun.star.util.XRefreshable; 47*cdf0e10cSrcweir import connectivity.tools.sdb.Connection; 48*cdf0e10cSrcweir 49*cdf0e10cSrcweir /** implements a small Customer Relationship Management database 50*cdf0e10cSrcweir * 51*cdf0e10cSrcweir * Not finished, by far. Feel free to add features as you need them. 52*cdf0e10cSrcweir */ 53*cdf0e10cSrcweir public class CRMDatabase 54*cdf0e10cSrcweir { 55*cdf0e10cSrcweir private static final String INTEGER = "INTEGER"; 56*cdf0e10cSrcweir private static final String VARCHAR50 = "VARCHAR(50)"; 57*cdf0e10cSrcweir private final XMultiServiceFactory m_orb; 58*cdf0e10cSrcweir private final HsqlDatabase m_database; 59*cdf0e10cSrcweir private final DataSource m_dataSource; 60*cdf0e10cSrcweir private final Connection m_connection; 61*cdf0e10cSrcweir 62*cdf0e10cSrcweir /** constructs the CRM database 63*cdf0e10cSrcweir */ 64*cdf0e10cSrcweir public CRMDatabase( XMultiServiceFactory _orb, boolean _withUI ) throws Exception 65*cdf0e10cSrcweir { 66*cdf0e10cSrcweir m_orb = _orb; 67*cdf0e10cSrcweir 68*cdf0e10cSrcweir m_database = new HsqlDatabase( m_orb ); 69*cdf0e10cSrcweir m_dataSource = m_database.getDataSource(); 70*cdf0e10cSrcweir 71*cdf0e10cSrcweir if ( _withUI ) 72*cdf0e10cSrcweir { 73*cdf0e10cSrcweir final XComponentLoader loader = UnoRuntime.queryInterface( XComponentLoader.class, 74*cdf0e10cSrcweir m_orb.createInstance( "com.sun.star.frame.Desktop" ) ); 75*cdf0e10cSrcweir PropertyValue[] loadArgs = new PropertyValue[] { 76*cdf0e10cSrcweir new PropertyValue( "PickListEntry", 0, false, PropertyState.DIRECT_VALUE ) 77*cdf0e10cSrcweir }; 78*cdf0e10cSrcweir loader.loadComponentFromURL( m_database.getDocumentURL(), "_blank", 0, loadArgs ); 79*cdf0e10cSrcweir getDocumentUI().connect(); 80*cdf0e10cSrcweir m_connection = new Connection( getDocumentUI().getActiveConnection() ); 81*cdf0e10cSrcweir } 82*cdf0e10cSrcweir else 83*cdf0e10cSrcweir { 84*cdf0e10cSrcweir m_connection = m_database.defaultConnection(); 85*cdf0e10cSrcweir } 86*cdf0e10cSrcweir 87*cdf0e10cSrcweir createTables(); 88*cdf0e10cSrcweir createQueries(); 89*cdf0e10cSrcweir } 90*cdf0e10cSrcweir 91*cdf0e10cSrcweir /** 92*cdf0e10cSrcweir * creates a CRMDatabase from an existing document, given by URL 93*cdf0e10cSrcweir * @param _orb 94*cdf0e10cSrcweir * @param _existingDocumentURL 95*cdf0e10cSrcweir * @throws Exceptio 96*cdf0e10cSrcweir */ 97*cdf0e10cSrcweir public CRMDatabase( XMultiServiceFactory _orb, final String _existingDocumentURL ) throws Exception 98*cdf0e10cSrcweir { 99*cdf0e10cSrcweir m_orb = _orb; 100*cdf0e10cSrcweir 101*cdf0e10cSrcweir m_database = new HsqlDatabase( m_orb, _existingDocumentURL ); 102*cdf0e10cSrcweir m_dataSource = m_database.getDataSource(); 103*cdf0e10cSrcweir m_connection = m_database.defaultConnection(); 104*cdf0e10cSrcweir } 105*cdf0e10cSrcweir 106*cdf0e10cSrcweir // -------------------------------------------------------------------------------------------------------- 107*cdf0e10cSrcweir /** returns the database document underlying the CRM database 108*cdf0e10cSrcweir */ 109*cdf0e10cSrcweir public final HsqlDatabase getDatabase() 110*cdf0e10cSrcweir { 111*cdf0e10cSrcweir return m_database; 112*cdf0e10cSrcweir } 113*cdf0e10cSrcweir 114*cdf0e10cSrcweir // -------------------------------------------------------------------------------------------------------- 115*cdf0e10cSrcweir /** returns the default connection to the database 116*cdf0e10cSrcweir */ 117*cdf0e10cSrcweir public final Connection getConnection() 118*cdf0e10cSrcweir { 119*cdf0e10cSrcweir return m_connection; 120*cdf0e10cSrcweir } 121*cdf0e10cSrcweir 122*cdf0e10cSrcweir // -------------------------------------------------------------------------------------------------------- 123*cdf0e10cSrcweir public void saveAndClose() throws SQLException, IOException 124*cdf0e10cSrcweir { 125*cdf0e10cSrcweir XDatabaseDocumentUI ui = getDocumentUI(); 126*cdf0e10cSrcweir if ( ui != null ) 127*cdf0e10cSrcweir ui.closeSubComponents(); 128*cdf0e10cSrcweir m_database.store(); 129*cdf0e10cSrcweir m_database.closeAndDelete(); 130*cdf0e10cSrcweir } 131*cdf0e10cSrcweir 132*cdf0e10cSrcweir // -------------------------------------------------------------------------------------------------------- 133*cdf0e10cSrcweir public XDatabaseDocumentUI getDocumentUI() 134*cdf0e10cSrcweir { 135*cdf0e10cSrcweir XModel docModel = UnoRuntime.queryInterface( XModel.class, m_database.getDatabaseDocument() ); 136*cdf0e10cSrcweir return UnoRuntime.queryInterface( XDatabaseDocumentUI.class, docModel.getCurrentController() ); 137*cdf0e10cSrcweir } 138*cdf0e10cSrcweir 139*cdf0e10cSrcweir // -------------------------------------------------------------------------------------------------------- 140*cdf0e10cSrcweir public XController loadSubComponent( final int _objectType, final String _name ) throws IllegalArgumentException, SQLException, NoSuchElementException 141*cdf0e10cSrcweir { 142*cdf0e10cSrcweir XDatabaseDocumentUI docUI = getDocumentUI(); 143*cdf0e10cSrcweir if ( !docUI.isConnected() ) 144*cdf0e10cSrcweir docUI.connect(); 145*cdf0e10cSrcweir 146*cdf0e10cSrcweir XComponent subComponent = docUI.loadComponent( _objectType, _name, false ); 147*cdf0e10cSrcweir XController controller = UnoRuntime.queryInterface( XController.class, subComponent ); 148*cdf0e10cSrcweir if ( controller != null ) 149*cdf0e10cSrcweir return controller; 150*cdf0e10cSrcweir XModel document = UnoRuntime.queryInterface( XModel.class, subComponent ); 151*cdf0e10cSrcweir return document.getCurrentController(); 152*cdf0e10cSrcweir } 153*cdf0e10cSrcweir 154*cdf0e10cSrcweir // -------------------------------------------------------------------------------------------------------- 155*cdf0e10cSrcweir private void createTables() throws SQLException 156*cdf0e10cSrcweir { 157*cdf0e10cSrcweir HsqlTableDescriptor table = new HsqlTableDescriptor( "categories", 158*cdf0e10cSrcweir new HsqlColumnDescriptor[] { 159*cdf0e10cSrcweir new HsqlColumnDescriptor( "ID",INTEGER, HsqlColumnDescriptor.PRIMARY ), 160*cdf0e10cSrcweir new HsqlColumnDescriptor( "Name",VARCHAR50), 161*cdf0e10cSrcweir new HsqlColumnDescriptor( "Description", "VARCHAR(1024)" ), 162*cdf0e10cSrcweir new HsqlColumnDescriptor( "Image", "LONGVARBINARY" ) } ); 163*cdf0e10cSrcweir m_database.createTable( table, true ); 164*cdf0e10cSrcweir 165*cdf0e10cSrcweir m_database.executeSQL( "INSERT INTO \"categories\" ( \"ID\", \"Name\" ) VALUES ( 1, 'Food' )" ); 166*cdf0e10cSrcweir m_database.executeSQL( "INSERT INTO \"categories\" ( \"ID\", \"Name\" ) VALUES ( 2, 'Furniture' )" ); 167*cdf0e10cSrcweir 168*cdf0e10cSrcweir table = new HsqlTableDescriptor( "products", 169*cdf0e10cSrcweir new HsqlColumnDescriptor[] { 170*cdf0e10cSrcweir new HsqlColumnDescriptor( "ID",INTEGER, HsqlColumnDescriptor.PRIMARY ), 171*cdf0e10cSrcweir new HsqlColumnDescriptor( "Name",VARCHAR50), 172*cdf0e10cSrcweir new HsqlColumnDescriptor( "CategoryID",INTEGER, HsqlColumnDescriptor.REQUIRED, "categories", "ID" ) } ); 173*cdf0e10cSrcweir m_database.createTable( table, true ); 174*cdf0e10cSrcweir 175*cdf0e10cSrcweir m_database.executeSQL( "INSERT INTO \"products\" VALUES ( 1, 'Oranges', 1 )" ); 176*cdf0e10cSrcweir m_database.executeSQL( "INSERT INTO \"products\" VALUES ( 2, 'Apples', 1 )" ); 177*cdf0e10cSrcweir m_database.executeSQL( "INSERT INTO \"products\" VALUES ( 3, 'Pears', 1 )" ); 178*cdf0e10cSrcweir m_database.executeSQL( "INSERT INTO \"products\" VALUES ( 4, 'Strawberries', 1 )" ); 179*cdf0e10cSrcweir 180*cdf0e10cSrcweir table = new HsqlTableDescriptor( "customers", 181*cdf0e10cSrcweir new HsqlColumnDescriptor[] { 182*cdf0e10cSrcweir new HsqlColumnDescriptor( "ID",INTEGER, HsqlColumnDescriptor.PRIMARY ), 183*cdf0e10cSrcweir new HsqlColumnDescriptor( "Name",VARCHAR50), 184*cdf0e10cSrcweir new HsqlColumnDescriptor( "Address",VARCHAR50), 185*cdf0e10cSrcweir new HsqlColumnDescriptor( "City",VARCHAR50), 186*cdf0e10cSrcweir new HsqlColumnDescriptor( "Postal",VARCHAR50), 187*cdf0e10cSrcweir new HsqlColumnDescriptor( "Comment","LONGVARCHAR")} ); 188*cdf0e10cSrcweir m_database.createTable( table, true ); 189*cdf0e10cSrcweir 190*cdf0e10cSrcweir m_database.executeSQL( "INSERT INTO \"customers\" VALUES(1,'Food, Inc.','Down Under','Melbourne','509','Prefered') " ); 191*cdf0e10cSrcweir m_database.executeSQL( "INSERT INTO \"customers\" VALUES(2,'Simply Delicious','Down Under','Melbourne','518',null) " ); 192*cdf0e10cSrcweir m_database.executeSQL( "INSERT INTO \"customers\" VALUES(3,'Pure Health','10 Fish St.','San Francisco','94107',null) " ); 193*cdf0e10cSrcweir m_database.executeSQL( "INSERT INTO \"customers\" VALUES(4,'Milk And More','Arlington Road 21','Dublin','31021','Good one.') " ); 194*cdf0e10cSrcweir 195*cdf0e10cSrcweir table = new HsqlTableDescriptor( "orders", 196*cdf0e10cSrcweir new HsqlColumnDescriptor[] { 197*cdf0e10cSrcweir new HsqlColumnDescriptor( "ID",INTEGER, HsqlColumnDescriptor.PRIMARY ), 198*cdf0e10cSrcweir new HsqlColumnDescriptor( "CustomerID",INTEGER, HsqlColumnDescriptor.REQUIRED, "customers", "ID" ), 199*cdf0e10cSrcweir new HsqlColumnDescriptor( "OrderDate", "DATE" ), 200*cdf0e10cSrcweir new HsqlColumnDescriptor( "ShipDate", "DATE" ) } ); 201*cdf0e10cSrcweir m_database.createTable( table, true ); 202*cdf0e10cSrcweir 203*cdf0e10cSrcweir m_database.executeSQL( "INSERT INTO \"orders\" (\"ID\", \"CustomerID\", \"OrderDate\") VALUES(1, 1, {D '2009-01-01'})" ); 204*cdf0e10cSrcweir m_database.executeSQL( "INSERT INTO \"orders\" VALUES(2, 2, {D '2009-01-01'}, {D '2009-01-23'})" ); 205*cdf0e10cSrcweir 206*cdf0e10cSrcweir table = new HsqlTableDescriptor( "orders_details", 207*cdf0e10cSrcweir new HsqlColumnDescriptor[] { 208*cdf0e10cSrcweir new HsqlColumnDescriptor( "OrderID",INTEGER, HsqlColumnDescriptor.PRIMARY, "orders", "ID" ), 209*cdf0e10cSrcweir new HsqlColumnDescriptor( "ProductID",INTEGER, HsqlColumnDescriptor.PRIMARY, "products", "ID" ), 210*cdf0e10cSrcweir new HsqlColumnDescriptor( "Quantity",INTEGER) } ); 211*cdf0e10cSrcweir m_database.createTable( table, true ); 212*cdf0e10cSrcweir 213*cdf0e10cSrcweir m_database.executeSQL( "INSERT INTO \"orders_details\" VALUES(1, 1, 100)" ); 214*cdf0e10cSrcweir m_database.executeSQL( "INSERT INTO \"orders_details\" VALUES(1, 2, 100)" ); 215*cdf0e10cSrcweir m_database.executeSQL( "INSERT INTO \"orders_details\" VALUES(2, 2, 2000)" ); 216*cdf0e10cSrcweir m_database.executeSQL( "INSERT INTO \"orders_details\" VALUES(2, 3, 2000)" ); 217*cdf0e10cSrcweir m_database.executeSQL( "INSERT INTO \"orders_details\" VALUES(2, 4, 2000)" ); 218*cdf0e10cSrcweir 219*cdf0e10cSrcweir // since we created the tables by directly executing the SQL statements, we need to refresh 220*cdf0e10cSrcweir // the tables container 221*cdf0e10cSrcweir m_connection.refreshTables(); 222*cdf0e10cSrcweir } 223*cdf0e10cSrcweir 224*cdf0e10cSrcweir // -------------------------------------------------------------------------------------------------------- 225*cdf0e10cSrcweir private void validateUnparseable() 226*cdf0e10cSrcweir { 227*cdf0e10cSrcweir /* 228*cdf0e10cSrcweir // The "unparseable" query should be indeed be unparseable by OOo (though a valid HSQL query) 229*cdf0e10cSrcweir XSingleSelectQueryComposer composer; 230*cdf0e10cSrcweir QueryDefinition unparseableQuery; 231*cdf0e10cSrcweir try 232*cdf0e10cSrcweir { 233*cdf0e10cSrcweir final XMultiServiceFactory factory = UnoRuntime.queryInterface( 234*cdf0e10cSrcweir XMultiServiceFactory.class, m_database.defaultConnection().getXConnection() ); 235*cdf0e10cSrcweir composer = UnoRuntime.queryInterface( 236*cdf0e10cSrcweir XSingleSelectQueryComposer.class, factory.createInstance( "com.sun.star.sdb.SingleSelectQueryComposer" ) ); 237*cdf0e10cSrcweir unparseableQuery = m_dataSource.getQueryDefinition( "unparseable" ); 238*cdf0e10cSrcweir } 239*cdf0e10cSrcweir catch( Exception e ) 240*cdf0e10cSrcweir { 241*cdf0e10cSrcweir throw new RuntimeException( "caught an unexpected exception: " + e.getMessage() ); 242*cdf0e10cSrcweir } 243*cdf0e10cSrcweir 244*cdf0e10cSrcweir boolean caughtExpected = false; 245*cdf0e10cSrcweir try 246*cdf0e10cSrcweir { 247*cdf0e10cSrcweir composer.setQuery( unparseableQuery.getCommand() ); 248*cdf0e10cSrcweir } 249*cdf0e10cSrcweir catch (WrappedTargetException e) { } 250*cdf0e10cSrcweir catch( SQLException e ) 251*cdf0e10cSrcweir { 252*cdf0e10cSrcweir caughtExpected = true; 253*cdf0e10cSrcweir } 254*cdf0e10cSrcweir 255*cdf0e10cSrcweir if ( !caughtExpected ) 256*cdf0e10cSrcweir throw new RuntimeException( "Somebody improved the parser! This is bad :), since we need an unparsable query here!" ); 257*cdf0e10cSrcweir */ 258*cdf0e10cSrcweir } 259*cdf0e10cSrcweir 260*cdf0e10cSrcweir // -------------------------------------------------------------------------------------------------------- 261*cdf0e10cSrcweir private void createQueries() throws ElementExistException, WrappedTargetException, com.sun.star.lang.IllegalArgumentException 262*cdf0e10cSrcweir { 263*cdf0e10cSrcweir m_database.getDataSource().createQuery( 264*cdf0e10cSrcweir "all orders", 265*cdf0e10cSrcweir "SELECT \"orders\".\"ID\" AS \"Order No.\", " + 266*cdf0e10cSrcweir "\"customers\".\"Name\" AS \"Customer Name\", " + 267*cdf0e10cSrcweir "\"orders\".\"OrderDate\" AS \"Order Date\", " + 268*cdf0e10cSrcweir "\"orders\".\"ShipDate\" AS \"Ship Date\", " + 269*cdf0e10cSrcweir "\"orders_details\".\"Quantity\", " + 270*cdf0e10cSrcweir "\"products\".\"Name\" AS \"Product Name\" " + 271*cdf0e10cSrcweir "FROM \"orders_details\" AS \"orders_details\", " + 272*cdf0e10cSrcweir "\"orders\" AS \"orders\", " + 273*cdf0e10cSrcweir "\"products\" AS \"products\", " + 274*cdf0e10cSrcweir "\"customers\" AS \"customers\" " + 275*cdf0e10cSrcweir "WHERE ( \"orders_details\".\"OrderID\" = \"orders\".\"ID\" " + 276*cdf0e10cSrcweir "AND \"orders_details\".\"ProductID\" = \"products\".\"ID\" " + 277*cdf0e10cSrcweir "AND \"orders\".\"CustomerID\" = \"customers\".\"ID\" )" 278*cdf0e10cSrcweir ); 279*cdf0e10cSrcweir 280*cdf0e10cSrcweir m_database.getDataSource().createQuery( 281*cdf0e10cSrcweir "unshipped orders", 282*cdf0e10cSrcweir "SELECT * " + 283*cdf0e10cSrcweir "FROM \"all orders\"" + 284*cdf0e10cSrcweir "WHERE ( \"ShipDate\" IS NULL )" 285*cdf0e10cSrcweir ); 286*cdf0e10cSrcweir 287*cdf0e10cSrcweir m_database.getDataSource().createQuery( "parseable", "SELECT * FROM \"customers\"" ); 288*cdf0e10cSrcweir m_database.getDataSource().createQuery( "parseable native", "SELECT * FROM INFORMATION_SCHEMA.SYSTEM_VIEWS", false ); 289*cdf0e10cSrcweir /* 290*cdf0e10cSrcweir m_database.getDataSource().createQuery( "unparseable", 291*cdf0e10cSrcweir "SELECT {fn DAYOFMONTH ('2001-01-01')} AS \"ID_VARCHAR\" FROM \"products\"", false ); 292*cdf0e10cSrcweir */ 293*cdf0e10cSrcweir validateUnparseable(); 294*cdf0e10cSrcweir } 295*cdf0e10cSrcweir } 296