Statistics
| Revision:

svn-gvsig-desktop / tags / v1_0_2_Build_895 / libraries / libGDBMS / src / main / java / com / hardcode / gdbms / engine / data / DataSourceFactory.java @ 10328

History | View | Annotate | Download (55 KB)

1
package com.hardcode.gdbms.engine.data;
2

    
3
import java.io.ByteArrayInputStream;
4
import java.io.File;
5
import java.io.IOException;
6
import java.rmi.server.UID;
7
import java.sql.Connection;
8
import java.sql.SQLException;
9
import java.sql.Statement;
10
import java.util.ArrayList;
11
import java.util.HashMap;
12
import java.util.Hashtable;
13
import java.util.Iterator;
14

    
15
import com.hardcode.driverManager.Driver;
16
import com.hardcode.driverManager.DriverLoadException;
17
import com.hardcode.driverManager.DriverManager;
18
import com.hardcode.driverManager.WriterManager;
19
import com.hardcode.gdbms.engine.data.db.DBDataSource;
20
import com.hardcode.gdbms.engine.data.db.DBDataSourceFactory;
21
import com.hardcode.gdbms.engine.data.db.DBQuerySourceInfo;
22
import com.hardcode.gdbms.engine.data.db.DBSourceInfo;
23
import com.hardcode.gdbms.engine.data.db.DBTableSourceInfo;
24
import com.hardcode.gdbms.engine.data.db.SpatialDBTableSourceInfo;
25
import com.hardcode.gdbms.engine.data.driver.AlphanumericDBDriver;
26
import com.hardcode.gdbms.engine.data.driver.DBDriver;
27
import com.hardcode.gdbms.engine.data.driver.DriverException;
28
import com.hardcode.gdbms.engine.data.driver.FileDriver;
29
import com.hardcode.gdbms.engine.data.driver.GDBMSDriver;
30
import com.hardcode.gdbms.engine.data.driver.ObjectDriver;
31
import com.hardcode.gdbms.engine.data.file.FileCreationSourceInfo;
32
import com.hardcode.gdbms.engine.data.file.FileDataSource;
33
import com.hardcode.gdbms.engine.data.file.FileDataSourceFactory;
34
import com.hardcode.gdbms.engine.data.file.FileSourceInfo;
35
import com.hardcode.gdbms.engine.data.object.ObjectDataSource;
36
import com.hardcode.gdbms.engine.data.object.ObjectDataSourceFactory;
37
import com.hardcode.gdbms.engine.data.object.ObjectSourceInfo;
38
import com.hardcode.gdbms.engine.data.persistence.DataSourceLayerMemento;
39
import com.hardcode.gdbms.engine.data.persistence.Memento;
40
import com.hardcode.gdbms.engine.data.persistence.OperationLayerMemento;
41
import com.hardcode.gdbms.engine.instruction.Adapter;
42
import com.hardcode.gdbms.engine.instruction.ColRefAdapter;
43
import com.hardcode.gdbms.engine.instruction.CustomAdapter;
44
import com.hardcode.gdbms.engine.instruction.EvaluationException;
45
import com.hardcode.gdbms.engine.instruction.SelectAdapter;
46
import com.hardcode.gdbms.engine.instruction.SemanticException;
47
import com.hardcode.gdbms.engine.instruction.TableRefAdapter;
48
import com.hardcode.gdbms.engine.instruction.UnionAdapter;
49
import com.hardcode.gdbms.engine.instruction.Utilities;
50
import com.hardcode.gdbms.engine.strategies.OperationDataSource;
51
import com.hardcode.gdbms.engine.strategies.Strategy;
52
import com.hardcode.gdbms.engine.strategies.StrategyManager;
53
import com.hardcode.gdbms.parser.Node;
54
import com.hardcode.gdbms.parser.ParseException;
55
import com.hardcode.gdbms.parser.SQLEngine;
56
import com.hardcode.gdbms.parser.SimpleNode;
57

    
58
/**
59
 * Clase factor?a de DataSources. Contiene m?todos para registrar las fuentes de
60
 * datos (addXXXDataSource) y para obtener los DataSource's asociados a estas
61
 * createRandomDataSource. Adem?s proporciona un m?todo para ejecutar consultas
62
 * SQL a partir de la instrucci?n como cadena o a partir de la instrucci?n como
63
 * ?rbol de adaptadores
64
 *
65
 * @author Fernando Gonz?lez Cort?s
66
 */
67
public class DataSourceFactory {
68
        public final static int MANUAL_OPENING = 0;
69

    
70
        public final static int AUTOMATIC_OPENING = 1;
71

    
72
        public final static int DATA_WARE_DIRECT_MODE = 0;
73

    
74
        public final static int DATA_WARE_COHERENT_ROW_ORDER = 1;
75

    
76
        final static int DEFAULT_DELAY = 5000;
77

    
78
        /**
79
         * Asocia los nombres de las tablas con la informaci?n del origen de datos
80
         */
81
        private HashMap tableSource = new HashMap();
82

    
83
        /** Associates a name with the operation layer DataSource with that name */
84
        private HashMap nameOperationDataSource = new HashMap();
85

    
86
        /**
87
         * Asocia los nombres de los or?genes de datos de base de datos con el
88
         * nombre de la tabla en el sistema de gesti?n original
89
         */
90
        private HashMap nameTable = new HashMap();
91

    
92
        private HashMap sourceInfoServerViewInfo = new HashMap();
93

    
94
        private DriverManager dm;
95

    
96
        private ModuleSupport ms = new ModuleSupport();
97

    
98
        private long delay = DEFAULT_DELAY;
99

    
100
        private boolean delegating = false;
101

    
102
        private File tempDir = new File(".");
103

    
104
        private WriterManager wm;
105
        
106
        private Hashtable driversNamesAliases = new Hashtable();
107

    
108
        /**
109
         * Get's a unique id in the tableSource and nameOperationDataSource key sets
110
         *
111
         * @return unique id
112
         */
113
        private String getUID() {
114
                UID uid = new UID();
115
                
116
                String name = "gdbms" + uid.toString().replace(':','_').replace('-','_');
117
                return name;
118
        }
119
        
120
        /**
121
         * Removes all associations between names and data sources of any layer.
122
         */
123
        public void removeAllDataSources() {
124
                tableSource.clear();
125
                nameOperationDataSource.clear();
126
        }
127

    
128
        /**
129
         * Removes the association between the name and the data sources
130
         *
131
         * @param ds
132
         *            Name of the data source to remove
133
         *
134
         * @throws DriverException
135
         *             If ds is a database data source it's associated view must be
136
         *             deleted. Thrown if could not be deleted.
137
         * @throws RuntimeException
138
         *             If there is no data source registered with that name
139
         */
140
        public void remove(DataSource ds) throws DriverException {
141
                String name = ds.getName();
142

    
143
                if (tableSource.remove(name) == null) {
144
                        if (nameOperationDataSource.remove(name) == null) {
145
                                throw new RuntimeException(
146
                                                "No datasource with the name. Data source name changed since the DataSource instance was retrieved?");
147
                        }
148
                }
149
        }
150

    
151
        /**
152
         * Removes de View of the data source 'ds'
153
         *
154
         * @param ds
155
         *            DataSource whose view will be deleted
156
         *
157
         * @throws DriverException
158
         *             If the view could not be deleted
159
         */
160
        private void clearView(DBDataSource ds) throws DriverException {
161
                DBTableSourceInfo dbInfo = (DBTableSourceInfo) ds.getSourceInfo();
162
                String sql = "DROP VIEW " + dbInfo.tableName;
163
                ds.execute(sql);
164
        }
165

    
166
        /**
167
         * Removes the views created at query delegation
168
         *
169
         * @throws DriverException
170
         *             If any view could not be removed
171
         */
172
        public void clearViews() throws DriverException {
173
                Iterator i = sourceInfoServerViewInfo.values().iterator();
174

    
175
                while (i.hasNext()) {
176
                        ServerViewInfo svi = (ServerViewInfo) i.next();
177
                        clearView(svi.adapter);
178
                }
179

    
180
                sourceInfoServerViewInfo.clear();
181
        }
182

    
183
        /**
184
         * A?ade una fuente de datos de objeto. Dado un objeto que implemente la
185
         * interfaz del driver, se toma como fuente de datos y se le asocia un
186
         * nombre
187
         *
188
         * @param rd
189
         *            objeto con la informaci?n
190
         * @param name
191
         *            Nombre de la fuente de datos
192
         */
193
        public void addDataSource(ObjectDriver rd, String name) {
194
                ObjectSourceInfo info = new ObjectSourceInfo();
195
                info.driver = rd;
196
                tableSource.put(name, info);
197
        }
198

    
199
        /**
200
         * A?ade una fuente de datos de objeto. Dado un objeto que implemente la
201
         * interfaz del driver, se toma como fuente de datos y se le asocia un
202
         * nombre
203
         *
204
         * @param rd
205
         *            objeto con la informaci?n
206
         *
207
         * @return the name of the data source
208
         */
209
        public String addDataSource(ObjectDriver rd) {
210
                String ret = getUID();
211
                addDataSource(rd, ret);
212

    
213
                return ret;
214
        }
215

    
216
        /**
217
         * Adds a new data source to the system. If the file doesn't exists it is
218
         * created when necessary
219
         *
220
         * @param driverName
221
         *            Nombre del driver asociado a la fuente de datos
222
         * @param name
223
         *            Nombre de la tabla con el que se har? referencia en las
224
         *            instrucciones
225
         * @param file
226
         *            Fichero con los datos
227
         */
228
        public void createFileDataSource(String driverName, String name,
229
                        String file, String[] fieldNames, int[] fieldTypes) {
230
                FileCreationSourceInfo info = (FileCreationSourceInfo) getFileSourceInfo(
231
                                new FileCreationSourceInfo(), driverName, name, file, false);
232
                info.fieldNames = fieldNames;
233
                info.fieldTypes = fieldTypes;
234
                tableSource.put(name, info);
235
        }
236

    
237
        /**
238
         * A?ade un origen de datos de fichero al sistema. Cuando se cree un
239
         * DataSource mediante la invocaci?n createRandomDataSource(String) se
240
         * crear? una instancia del driver cuyo nombre es driverName
241
         *
242
         * @param driverName
243
         *            Nombre del driver asociado a la fuente de datos
244
         * @param name
245
         *            Nombre de la tabla con el que se har? referencia en las
246
         *            instrucciones
247
         * @param file
248
         *            Fichero con los datos
249
         */
250
        public void addFileDataSource(String driverName, String name, String file) {
251
                FileSourceInfo info = getFileSourceInfo(new FileSourceInfo(),
252
                                driverName, name, file, false);
253
                tableSource.put(name, info);
254
        }
255

    
256
        /**
257
         * Gets a FileSourceInfo with the values passed in the parameters
258
         *
259
         * @param driverName
260
         * @param name
261
         * @param file
262
         *
263
         * @return FileSourceInfo
264
         */
265
        private FileSourceInfo getFileSourceInfo(FileSourceInfo info,
266
                        String driverName, String name, String file, boolean spatial) {
267
                info.name = name;
268
                info.file = file;
269
                info.driverName = driverName;
270
                info.spatial = spatial;
271

    
272
                return info;
273
        }
274

    
275
        /**
276
         * Adds a spatial file data source to the system.
277
         *
278
         * @param driverName
279
         *            driver used to obtain the data
280
         * @param name
281
         *            name of the data source
282
         * @param file
283
         *            file with the data
284
         */
285
        public void addSpatialFileDataSource(String driverName, String name,
286
                        String file) {
287
                FileSourceInfo info = getFileSourceInfo(new FileSourceInfo(),
288
                                driverName, name, file, true);
289
                tableSource.put(name, info);
290
        }
291

    
292
        /**
293
         * Adds a spatial file data source to the system.
294
         *
295
         * @param driverName
296
         *            driver used to obtain the data
297
         * @param file
298
         *            file with the data
299
         *
300
         * @return String Generated name of the added data source
301
         */
302
        public String addSpatialFileDataSource(String driverName, String file) {
303
                String ret = getUID();
304
                addSpatialFileDataSource(driverName, ret, file);
305

    
306
                return ret;
307
        }
308

    
309
        /**
310
         * A?ade un origen de datos de fichero al sistema. Cuando se cree un
311
         * DataSource mediante la invocaci?n createRandomDataSource(String) se
312
         * crear? una instancia del driver cuyo nombre es driverName
313
         *
314
         * @param driverName
315
         *            Nombre del driver asociado a la fuente de datos
316
         * @param file
317
         *            Fichero con los datos
318
         *
319
         * @return Nombre ?nico que se asocia a la tabla
320
         */
321
        public String addFileDataSource(String driverName, String file) {
322
                String ret = getUID();
323
                addFileDataSource(driverName, ret, file);
324

    
325
                return ret;
326
        }
327

    
328
        /**
329
         * Obtiene la informaci?n de la fuente de datos cuyo nombre se pasa como
330
         * par?metro
331
         *
332
         * @param dataSourceName
333
         *            Nombre de la base de datos
334
         *
335
         * @return Debido a las distintas formas en las que se puede registrar un
336
         *         datasource, se devuelve un Object, que podr? ser una instancia de
337
         *         DataSourceFactory.FileDriverInfo, DataSourceFactory.DBDriverInfo
338
         *         o ReadDriver
339
         */
340
        public SourceInfo getDriverInfo(String dataSourceName) {
341
                return (SourceInfo) tableSource.get(dataSourceName);
342
        }
343

    
344
        /**
345
         * Gets the information of all data sources registered in the system
346
         *
347
         * @return DriverInfo[]
348
         */
349
        public SourceInfo[] getDriverInfos() {
350
                ArrayList ret = new ArrayList();
351
                Iterator it = tableSource.values().iterator();
352

    
353
                while (it.hasNext()) {
354
                        SourceInfo di = (SourceInfo) it.next();
355
                        ret.add(di);
356
                }
357

    
358
                return (SourceInfo[]) ret.toArray(new SourceInfo[0]);
359
        }
360

    
361
        /**
362
         * A?ade un origen de datos de base de datos al sistema
363
         *
364
         * @param name
365
         *            Nombre de la tabla con el que se har? referencia en las
366
         *            instrucciones
367
         * @param host
368
         *            Cadena de conexi?n para conectar con el sgbd donde se
369
         *            encuentra la tabla
370
         * @param port
371
         *            Nombre del sgbd capaz de ejecutar SQL en el que reside la
372
         *            tabla. Generalmente ser? la parte de la cadena de conexi?n
373
         *            correspondiente a host, puerto y nombre de la base de datos
374
         * @param user
375
         *            Nombre de usuario. Null para acceso sin usuario
376
         * @param password
377
         *            Si el usuario es null se ignora el password
378
         * @param dbName
379
         *            Nombre de la base de datos a la que se accede
380
         * @param tableName
381
         *            Nombre de la tabla en la base de datos
382
         * @param driverInfo
383
         *            Informaci?n para saber qu? driver debe acceder a la
384
         *            informaci?n. Se escoger? el driver cuyo valor de retorno del
385
         *            m?todo getType coincida con este valor
386
         */
387
        public void addDBDataSourceByTable(String name, String host, int port,
388
                        String user, String password, String dbName, String tableName,
389
                        String driverInfo) {
390
                DBTableSourceInfo info = new DBTableSourceInfo();
391
                fillDBTableSourceInfo(info, name, host, port, user, password, dbName,
392
                                tableName, driverInfo);
393
                tableSource.put(name, info);
394
                nameTable.put(name, tableName);
395
        }
396
        
397
        
398
        /**
399
         * A?ade un origen de datos de base de datos al sistema
400
         *
401
         * @param name
402
         *            Nombre de la tabla con el que se har? referencia en las
403
         *            instrucciones
404
         * @param Connection
405
         *            Conexion JDBC a la Base de datos ya abierta (el DataSource
406
         *            la usara, pero no la abrira/cerrara)
407
         * @param tableName
408
         *            Nombre de la tabla en la base de datos
409
         * @param driverInfo
410
         *            Informaci?n para saber qu? driver debe acceder a la
411
         *            informaci?n. Se escoger? el driver cuyo valor de retorno del
412
         *            m?todo getType coincida con este valor
413
         */
414
        public void addDBDataSourceByTable(String name, Connection connection, String tableName,
415
                        String driverInfo) {
416
                DBTableSourceInfo info = new DBTableSourceInfo();
417
                fillDBTableSourceInfo(info, name, connection,
418
                                tableName, driverInfo);
419
                tableSource.put(name, info);
420
                nameTable.put(name, tableName);
421
        }
422
        
423
        
424
        
425

    
426
        /**
427
         * Fills the info struct with the values passed in the parameters
428
         *
429
         * @param info
430
         *            struct to populate
431
         * @param name
432
         *            Name of the data source
433
         * @param host
434
         *            host where the data is
435
         * @param port
436
         *            port number
437
         * @param user
438
         *            user name or null.
439
         * @param password
440
         *            if user name is null is ignored
441
         * @param dbName
442
         *            database name
443
         * @param tableName
444
         *            table name
445
         * @param driverInfo
446
         *            name of the driver used to access the data
447
         */
448
        private void fillDBTableSourceInfo(DBTableSourceInfo info, String name,
449
                        String host, int port, String user, String password, String dbName,
450
                        String tableName, String driverInfo) {
451
                info.name = name;
452
                info.host = host;
453
                info.port = port;
454
                info.user = user;
455
                info.password = password;
456
                info.dbName = dbName;
457
                info.dbms = host + ":" + port + "/" + dbName + "," + user + ","
458
                                + password;
459
                info.tableName = tableName;
460
                info.driverName = driverInfo;
461
        }
462

    
463
        /**
464
         * Fills the info struct with the values passed in the parameters
465
         *
466
         * @param info
467
         *            struct to populate
468
         * @param name
469
         *            Name of the data source
470
         * @param Connection
471
         *            JDBC opened data base Connection
472
         * @param port
473
         *            port number
474
         * @param user
475
         *            user name or null.
476
         * @param password
477
         *            if user name is null is ignored
478
         * @param dbName
479
         *            database name
480
         * @param tableName
481
         *            table name
482
         * @param driverInfo
483
         *            name of the driver used to access the data
484
         */
485
        private void fillDBTableSourceInfo(DBTableSourceInfo info, String name,
486
                        Connection conection, String tableName, String driverInfo) {
487
                info.name = name;
488
                info.host = "";
489
                info.port = -1;
490
                info.user = "";
491
                info.password = "";
492
                info.dbName = "";
493
                info.dbms = "";
494
                info.connection= conection;
495
                info.tableName = tableName;
496
                info.driverName = driverInfo;
497
        }        
498
        
499
        
500

    
501
        
502
        
503
        
504
        
505
        
506
        /**
507
         * Adds a spatial database data source
508
         *
509
         * @param name
510
         *            Name of the data source
511
         * @param host
512
         *            host where the data is
513
         * @param port
514
         *            port number
515
         * @param user
516
         *            user name or null.
517
         * @param password
518
         *            if user name is null is ignored
519
         * @param dbName
520
         *            database name
521
         * @param tableName
522
         *            table name
523
         * @param geometryFieldName
524
         *            name of the field that has the geometry
525
         * @param driverInfo
526
         *            name of the driver used to access the data
527
         */
528
        public void addSpatialDBDataSource(String name, String host, int port,
529
                        String user, String password, String dbName, String tableName,
530
                        String geometryFieldName, String driverInfo) {
531
                SpatialDBTableSourceInfo info = new SpatialDBTableSourceInfo();
532
                fillDBTableSourceInfo(info, name, host, port, user, password, dbName,
533
                                tableName, driverInfo);
534
                info.geometryField = geometryFieldName;
535
                tableSource.put(name, info);
536
                nameTable.put(name, tableName);
537
        }
538

    
539
        
540
        /**
541
         * Adds a spatial database data source
542
         *
543
         * @param connection
544
         *
545
         * @param tableName
546
         *            table name
547
         * @param geometryFieldName
548
         *            name of the field that has the geometry
549
         * @param driverInfo
550
         *            name of the driver used to access the data
551
         */
552
        public void addSpatialDBDataSource(String name, Connection connection, String tableName,
553
                        String geometryFieldName, String driverInfo) {
554
                SpatialDBTableSourceInfo info = new SpatialDBTableSourceInfo();
555
                fillDBTableSourceInfo(info, name, connection,
556
                                tableName, driverInfo);
557
                info.geometryField = geometryFieldName;
558
                tableSource.put(name, info);
559
                nameTable.put(name, tableName);
560
        }        
561
        
562
        
563
        
564
        
565
        
566
        
567
        
568
        
569
        /**
570
         * Adds a spatial database data source
571
         *
572
         * @param host
573
         *            host where the data is
574
         * @param port
575
         *            port number
576
         * @param user
577
         *            user name or null.
578
         * @param password
579
         *            if user name is null is ignored
580
         * @param dbName
581
         *            database name
582
         * @param tableName
583
         *            table name
584
         * @param geometryFieldName
585
         *            name of the field that has the geometry
586
         * @param driverInfo
587
         *            name of the driver used to access the data
588
         *
589
         * @return generated name of the added data source
590
         */
591
        public String addSpatialDBDataSource(String host, int port, String user,
592
                        String password, String dbName, String tableName,
593
                        String geometryFieldName, String driverInfo) {
594
                String ret = getUID();
595
                addSpatialDBDataSource(ret, host, port, user, password, dbName,
596
                                tableName, geometryFieldName, driverInfo);
597

    
598
                return ret;
599
        }
600

    
601
        
602
        /**
603
         * Adds a spatial database data source
604
         *
605
         * @param connection
606
         *            
607
         * @param tableName
608
         *            table name
609
         * @param geometryFieldName
610
         *            name of the field that has the geometry
611
         * @param driverInfo
612
         *            name of the driver used to access the data
613
         *
614
         * @return generated name of the added data source
615
         */
616
        public String addSpatialDBDataSource(Connection connection, String tableName,
617
                        String geometryFieldName, String driverInfo) {
618
                String ret = getUID();
619
                addSpatialDBDataSource(ret, connection,
620
                                tableName, geometryFieldName, driverInfo);
621

    
622
                return ret;
623
        }
624
        
625
        
626
        
627
        
628
        
629
        /**
630
         * A?ade un origen de datos de base de datos al sistema
631
         *
632
         * @param host
633
         *            Cadena de conexi?n para conectar con el sgbd donde se
634
         *            encuentra la tabla
635
         * @param port
636
         *            Nombre del sgbd capaz de ejecutar SQL en el que reside la
637
         *            tabla. Generalmente ser? la parte de la cadena de conexi?n
638
         *            correspondiente a host, puerto y nombre de la base de datos
639
         * @param user
640
         *            Nombre de usuario. Null para acceso sin usuario
641
         * @param password
642
         *            Si el usuario es null se ignora el password
643
         * @param dbName
644
         *            Nombre de la base de datos a la que se accede
645
         * @param tableName
646
         *            Nombre de la tabla en la base de datos
647
         * @param driverInfo
648
         *            Informaci?n para saber qu? driver debe acceder a la
649
         *            informaci?n. Se escoger? el driver cuyo valor de retorno del
650
         *            m?todo getType coincida con este valor
651
         *
652
         * @return Nombre de la tabla con el que se har? referencia en las
653
         *         instrucciones
654
         */
655
        public String addDBDataSourceByTable(String host, int port, String user,
656
                        String password, String dbName, String tableName, String driverInfo) {
657
                String name = getUID();
658
                addDBDataSourceByTable(name, host, port, user, password, dbName,
659
                                tableName, driverInfo);
660

    
661
                return name;
662
        }
663

    
664
        
665
        
666
        /**
667
         * A?ade un origen de datos de base de datos al sistema
668
         *
669
         * @param connection
670
         *            Conexion JDBC abierta a la base de datos(el DataSource
671
         *            usara la conexion, pero no la abrira/cerrara)
672
         * @param tableName
673
         *            Nombre de la tabla en la base de datos
674
         * @param driverInfo
675
         *            Informaci?n para saber qu? driver debe acceder a la
676
         *            informaci?n. Se escoger? el driver cuyo valor de retorno del
677
         *            m?todo getType coincida con este valor
678
         *
679
         * @return Nombre de la tabla con el que se har? referencia en las
680
         *         instrucciones
681
         */
682
        public String addDBDataSourceByTable(Connection connection, String tableName, String driverInfo) {
683
                String name = getUID();
684
                addDBDataSourceByTable(name, connection,
685
                                tableName, driverInfo);
686

    
687
                return name;
688
        }
689
        
690
        
691
        
692
        
693
        
694
        
695
        
696
        
697
        
698
        
699
        
700
        
701
        
702
        
703
        
704
        
705
        
706
        
707
        
708
        
709
        
710
        /**
711
         * A?ade un origen de datos de base de datos al sistema
712
         *
713
         * @param name
714
         *            Nombre de la tabla con el que se har? referencia en las
715
         *            instrucciones
716
         * @param host
717
         *            Cadena de conexi?n para conectar con el sgbd donde se
718
         *            encuentra la tabla
719
         * @param port
720
         *            Nombre del sgbd capaz de ejecutar SQL en el que reside la
721
         *            tabla. Generalmente ser? la parte de la cadena de conexi?n
722
         *            correspondiente a host, puerto y nombre de la base de datos
723
         * @param user
724
         *            Nombre de usuario. Null para acceso sin usuario
725
         * @param password
726
         *            Si el usuario es null se ignora el password
727
         * @param dbName
728
         *            Nombre de la base de datos a la que se accede
729
         * @param sql
730
         *            Instrucci?n SQL que define los datos de la tabla
731
         * @param driverInfo
732
         *            Informaci?n para saber qu? driver debe acceder a la
733
         *            informaci?n. Se escoger? el driver cuyo valor de retorno del
734
         *            m?todo getType coincida con este valor
735
         */
736
        public void addDBDataSourceBySQL(String name, String host, int port,
737
                        String user, String password, String dbName, String sql,
738
                        String driverInfo) {
739
                DBQuerySourceInfo info = new DBQuerySourceInfo();
740
                info.name = name;
741
                info.host = host;
742
                info.port = port;
743
                info.user = user;
744
                info.password = password;
745
                info.dbName = dbName;
746
                info.dbms = host + ":" + port + "/" + dbName + "," + user + ","
747
                                + password;
748
                info.sql = sql;
749
                info.driverName = driverInfo;
750
                tableSource.put(name, info);
751
        }
752

    
753
        
754
        /**
755
         * A?ade un origen de datos de base de datos al sistema
756
         *
757
         * @param name
758
         *            Nombre de la tabla con el que se har? referencia en las
759
         *            instrucciones
760
         * @param connection
761
         *            Conexion de JDBC a la base de datos ya abierta (el 
762
         *            DataSource la usara, pero no la abrira/cerrara)
763
         * @param sql
764
         *            Instrucci?n SQL que define los datos de la tabla
765
         * @param driverInfo
766
         *            Informaci?n para saber qu? driver debe acceder a la
767
         *            informaci?n. Se escoger? el driver cuyo valor de retorno del
768
         *            m?todo getType coincida con este valor
769
         */
770
        public void addDBDataSourceBySQL(String name, Connection connection, String sql,
771
                        String driverInfo) {
772
                DBQuerySourceInfo info = new DBQuerySourceInfo();
773
                info.name = name;
774
                info.host = "";
775
                info.port = -1;
776
                info.user = "";
777
                info.password = "";
778
                info.dbName = "";
779
                info.dbms ="";
780
                info.connection = connection;
781
                info.sql = sql;
782
                info.driverName = driverInfo;
783
                tableSource.put(name, info);
784
        }
785
        
786
        
787
        
788
        
789
        
790
        
791
        
792
        /**
793
         * A?ade un origen de datos de base de datos al sistema
794
         *
795
         * @param host
796
         *            Cadena de conexi?n para conectar con el sgbd donde se
797
         *            encuentra la tabla
798
         * @param port
799
         *            Nombre del sgbd capaz de ejecutar SQL en el que reside la
800
         *            tabla. Generalmente ser? la parte de la cadena de conexi?n
801
         *            correspondiente a host, puerto y nombre de la base de datos
802
         * @param user
803
         *            Nombre de usuario. Null para acceso sin usuario
804
         * @param password
805
         *            Si el usuario es null se ignora el password
806
         * @param dbName
807
         *            Nombre de la base de datos a la que se accede
808
         * @param sql
809
         *            Instrucci?n SQL que define los datos de la tabla
810
         * @param driverInfo
811
         *            Informaci?n para saber qu? driver debe acceder a la
812
         *            informaci?n. Se escoger? el driver cuyo valor de retorno del
813
         *            m?todo getType coincida con este valor
814
         *
815
         * @return Nombre de la tabla con el que se har? referencia en las
816
         *         instrucciones
817
         */
818
        public String addDBDataSourceBySQL(String host, int port, String user,
819
                        String password, String dbName, String sql, String driverInfo) {
820
                String ret = getUID();
821
                addDBDataSourceBySQL(ret, host, port, user, password, dbName, sql,
822
                                driverInfo);
823

    
824
                return ret;
825
        }
826
        
827
        /**
828
         * A?ade un origen de datos de base de datos al sistema
829
         *
830
         * @param connection
831
         *            Conexion de JDBC ya abierta (el DataSource la usara
832
         *            pero no la abrira/cerrara)
833
         * @param sql
834
         *            Instrucci?n SQL que define los datos de la tabla
835
         * @param driverInfo
836
         *            Informaci?n para saber qu? driver debe acceder a la
837
         *            informaci?n. Se escoger? el driver cuyo valor de retorno del
838
         *            m?todo getType coincida con este valor
839
         *
840
         * @return Nombre de la tabla con el que se har? referencia en las
841
         *         instrucciones
842
         */
843
        public String addDBDataSourceBySQL(Connection connection, String sql, String driverInfo) {
844
                String ret = getUID();
845
                addDBDataSourceBySQL(ret, connection, sql,
846
                                driverInfo);
847

    
848
                return ret;
849
        }
850
        
851

    
852
        /**
853
         * Cambia el nombre de una fuente de datos. Las consultas SQL que se
854
         * ejecuten con el nombre anterior fallar?n
855
         *
856
         * @param oldName
857
         *            Nombre actual de la fuente de datos que se quiere cambiar
858
         * @param newName
859
         *            Nombre que se le quiere poner a la fuente de datos
860
         *
861
         * @throws NoSuchTableException
862
         *             Si no hay ninguna fuente de datos de nombre 'oldName'
863
         */
864
        public void changeDataSourceName(String oldName, String newName)
865
                        throws NoSuchTableException {
866
                SourceInfo di = (SourceInfo) tableSource.remove(oldName);
867

    
868
                if (di == null) {
869
                        throw new NoSuchTableException(oldName);
870
                }
871

    
872
                tableSource.put(newName, di);
873
        }
874

    
875
        /**
876
         * Gets the data source passed by adding the AutomaticDataSource decorator
877
         * if factory mode is AUTOMATIC.
878
         *
879
         * @param ds
880
         *            DataSource
881
         * @param mode
882
         *            opening mode
883
         *
884
         * @return DataSource
885
         */
886
        private DataSource getModedDataSource(DataSource ds, int mode) {
887
                if (mode == AUTOMATIC_OPENING) {
888
                        return new AutomaticDataSource(ds, delay);
889
                } else {
890
                        return ds;
891
                }
892
        }
893

    
894
        /**
895
         * Sets the minimum delay between accesses needed to close the DataSource.
896
         * If accesses are delayed more than 'delay' the DataSource MAY be closed.
897
         * Only applies when the mode is set to AUTOMATIC_MODE
898
         *
899
         * @param delay
900
         *            time un milliseconds
901
         */
902
        public void setClosingDelay(long delay) {
903
                this.delay = delay;
904
        }
905

    
906
        /**
907
         * Dado el nombre de una tabla, se busca la fuente de datos asociada a dicha
908
         * tabla y se obtiene un datasource adecuado en funcion del tipo de fuente
909
         * de datos accediendo al subsistema de drivers
910
         *
911
         * @param tableName
912
         *            Nombre de la fuente de datos
913
         *
914
         * @return DataSource que accede a dicha fuente
915
         *
916
         * @throws DriverLoadException
917
         * @throws NoSuchTableException
918
         * @throws DriverException
919
         */
920
        public DataSource createRandomDataSource(String tableName)
921
                        throws DriverLoadException, NoSuchTableException, DriverException {
922
                return createRandomDataSource(tableName, tableName, MANUAL_OPENING);
923
        }
924

    
925
        /**
926
         * Dado el nombre de una tabla, se busca la fuente de datos asociada a dicha
927
         * tabla y se obtiene un datasource adecuado en funcion del tipo de fuente
928
         * de datos accediendo al subsistema de drivers
929
         *
930
         * @param tableName
931
         *            Nombre de la fuente de datos
932
         * @param mode
933
         *            opening mode: AUTOMATIC_OPENING -> the DataSource opens
934
         *            automatically and closes after a while. It can be closed
935
         *            manually. MANUAL_OPENING -> the DataSource opens and closes
936
         *            manually
937
         *
938
         * @return DataSource que accede a dicha fuente
939
         *
940
         * @throws DriverLoadException
941
         * @throws NoSuchTableException
942
         * @throws DriverException
943
         */
944
        public DataSource createRandomDataSource(String tableName, int mode)
945
                        throws DriverLoadException, NoSuchTableException, DriverException {
946
                return createRandomDataSource(tableName, tableName, mode);
947
        }
948

    
949
        /**
950
         * Dado el nombre de una tabla, se busca la fuente de datos asociada a dicha
951
         * tabla y se obtiene un datasource adecuado en funcion del tipo de fuente
952
         * de datos accediendo al subsistema de drivers. Se utiliza internamente
953
         * como nombre del DataSource el alias que se pasa como par?metro
954
         *
955
         * @param tableName
956
         *            Nombre de la fuente de datos
957
         * @param tableAlias
958
         *            Alias que tiene el DataSource en una instrucci?n
959
         *
960
         * @return DataSource que accede a dicha fuente de datos si la fuente de
961
         *         datos es alfanum?rica o SpatialDataSource si la fuente de datos
962
         *         es espacial
963
         *
964
         * @throws NoSuchTableException
965
         *             Si no hay una fuente de datos registrada con ese nombre
966
         * @throws DriverLoadException
967
         *             Si hay alg?n error con el sistema de carga de drivers
968
         * @throws DriverException
969
         *             If the created DataSource have to access some data this
970
         *             access fails
971
         * @throws RuntimeException
972
         *             bug
973
         */
974
        public DataSource createRandomDataSource(String tableName, String tableAlias)
975
                        throws NoSuchTableException, DriverLoadException, DriverException {
976
                return createRandomDataSource(tableName, tableAlias, MANUAL_OPENING);
977
        }
978

    
979
        /**
980
         * Dado el nombre de una tabla, se busca la fuente de datos asociada a dicha
981
         * tabla y se obtiene un datasource adecuado en funcion del tipo de fuente
982
         * de datos accediendo al subsistema de drivers. Se utiliza internamente
983
         * como nombre del DataSource el alias que se pasa como par?metro
984
         *
985
         * @param tableName
986
         *            Nombre de la fuente de datos
987
         * @param tableAlias
988
         *            Alias que tiene el DataSource en una instrucci?n
989
         * @param mode
990
         *            openning mode
991
         *
992
         * @return DataSource que accede a dicha fuente de datos si la fuente de
993
         *         datos es alfanum?rica o SpatialDataSource si la fuente de datos
994
         *         es espacial
995
         *
996
         * @throws NoSuchTableException
997
         *             Si no hay una fuente de datos registrada con ese nombre
998
         * @throws DriverLoadException
999
         *             Si hay alg?n error con el sistema de carga de drivers
1000
         * @throws DriverException
1001
         *             If the created DataSource have to access some data this
1002
         *             access fails
1003
         * @throws RuntimeException
1004
         *             bug
1005
         */
1006
        public DataSource createRandomDataSource(String tableName,
1007
                        String tableAlias, int mode) throws NoSuchTableException,
1008
                        DriverLoadException, DriverException {
1009
                Object o = tableSource.get(tableName);
1010

    
1011
                if (o == null) {
1012
                        // may be a operation layer DataSource
1013
                        OperationDataSource ret = (OperationDataSource) nameOperationDataSource
1014
                                        .get(tableName);
1015

    
1016
                        if (ret != null) {
1017
                                ret.setName(tableAlias);
1018

    
1019
                                return getModedDataSource(ret, mode);
1020
                        }
1021

    
1022
                        // table not found
1023
                        throw new NoSuchTableException(tableName);
1024
                }
1025

    
1026
                SourceInfo info = (SourceInfo) o;
1027
                info.name = tableAlias;
1028

    
1029
                if (info instanceof FileSourceInfo) {
1030
                        FileSourceInfo fileInfo = (FileSourceInfo) info;
1031

    
1032
                        Driver d = this.getDriver(fileInfo.driverName);
1033

    
1034
                        if (info instanceof FileCreationSourceInfo) {
1035
                                FileCreationSourceInfo creationInfo = (FileCreationSourceInfo) info;
1036
                                try {
1037
                                        if (!new File(creationInfo.file).exists()) {
1038
                                                ((FileDriver) d).createSource(creationInfo.file,
1039
                                                                creationInfo.fieldNames,
1040
                                                                creationInfo.fieldTypes);
1041
                                        }
1042
                                } catch (IOException e) {
1043
                                        throw new DriverException(e);
1044
                                }
1045
                        }
1046

    
1047
                        FileDataSource adapter;
1048

    
1049
                        if (fileInfo.spatial) {
1050
                                adapter = FileDataSourceFactory.newSpatialInstance();
1051
                        } else {
1052
                                adapter = FileDataSourceFactory.newInstance();
1053
                        }
1054

    
1055
                        ((GDBMSDriver) d).setDataSourceFactory(this);
1056
                        adapter.setDriver((FileDriver) d);
1057
                        adapter.setSourceInfo(fileInfo);
1058
                        adapter.setDataSourceFactory(this);
1059

    
1060
                        return getModedDataSource(adapter, mode);
1061
                } else if (info instanceof DBQuerySourceInfo) {
1062
                        DBQuerySourceInfo dbInfo = (DBQuerySourceInfo) info;
1063

    
1064
                        String driverInfo = dbInfo.driverName;
1065
                        Driver d = this.getDriver(driverInfo);
1066

    
1067
                        ((GDBMSDriver) d).setDataSourceFactory(this);
1068
                        return getModedDataSource(getDataSourceByQuery(dbInfo.sql,
1069
                                        (AlphanumericDBDriver) d, dbInfo), mode);
1070
                } else if (info instanceof DBTableSourceInfo) {
1071
                        DBTableSourceInfo dbInfo = (DBTableSourceInfo) info;
1072

    
1073
                        String driverInfo = dbInfo.driverName;
1074
                        Driver d = this.getDriver(driverInfo);
1075

    
1076
                        DBDataSource adapter;
1077

    
1078
                        if (info instanceof SpatialDBTableSourceInfo) {
1079
                                adapter = DBDataSourceFactory.newSpatialDataSourceInstance();
1080
                        } else {
1081
                                adapter = DBDataSourceFactory.newDataSourceInstance();
1082
                        }
1083

    
1084
                        ((GDBMSDriver) d).setDataSourceFactory(this);
1085
                        adapter.setDriver((DBDriver) d);
1086
                        adapter.setSourceInfo(dbInfo);
1087
                        adapter.setDataSourceFactory(this);
1088

    
1089
                        return getModedDataSource(adapter, mode);
1090
                } else if (info instanceof ObjectSourceInfo) {
1091
                        ObjectSourceInfo driverInfo = (ObjectSourceInfo) o;
1092
                        ObjectDataSource adapter = ObjectDataSourceFactory.newInstance();
1093
                        driverInfo.driver.setDataSourceFactory(this);
1094
                        adapter.setDriver(driverInfo.driver);
1095
                        adapter.setSourceInfo((ObjectSourceInfo) driverInfo);
1096
                        adapter.setDataSourceFactory(this);
1097

    
1098
                        return getModedDataSource(adapter, mode);
1099
                } else {
1100
                        throw new RuntimeException();
1101
                }
1102
        }
1103

    
1104
        /**
1105
         * Creates a DataSource from a memento object with the manual opening mode
1106
         *
1107
         * @param m
1108
         *            memento
1109
         *
1110
         * @return DataSource
1111
         *
1112
         * @throws RuntimeException
1113
         *             If the DataSource class cannot be instatiated
1114
         */
1115
        public DataSource createRandomDataSource(Memento m) {
1116
                return createRandomDataSource(m, DataSourceFactory.MANUAL_OPENING);
1117
        }
1118

    
1119
        /**
1120
         * Creates a DataSource from a memento object with the specified opening
1121
         * mode
1122
         *
1123
         * @param m
1124
         *            memento
1125
         * @param mode
1126
         *            opening mode
1127
         *
1128
         * @return DataSource
1129
         *
1130
         * @throws RuntimeException
1131
         *             If the DataSource class cannot be instatiated
1132
         */
1133
        public DataSource createRandomDataSource(Memento m, int mode) {
1134
                if (m instanceof DataSourceLayerMemento) {
1135
                        DataSourceLayerMemento mem = (DataSourceLayerMemento) m;
1136

    
1137
                        try {
1138
                                return createRandomDataSource(mem.getTableName(), mem
1139
                                                .getTableAlias(), mode);
1140
                        } catch (DriverLoadException e) {
1141
                                throw new RuntimeException(
1142
                                                "La informaci?n guardada no es consistente", e);
1143
                        } catch (NoSuchTableException e) {
1144
                                throw new RuntimeException(
1145
                                                "La informaci?n guardada no es consistente", e);
1146
                        } catch (DriverException e) {
1147
                                throw new RuntimeException(e);
1148
                        }
1149
                } else {
1150
                        OperationLayerMemento mem = (OperationLayerMemento) m;
1151

    
1152
                        try {
1153
                                return executeSQL(mem.getSql(), mode);
1154
                        } catch (DriverLoadException e) {
1155
                                throw new RuntimeException(
1156
                                                "La informaci?n guardada no es consistente", e);
1157
                        } catch (ParseException e) {
1158
                                throw new RuntimeException(
1159
                                                "La informaci?n guardada no es consistente", e);
1160
                        } catch (DriverException e) {
1161
                                throw new RuntimeException(
1162
                                                "La informaci?n guardada no es consistente", e);
1163
                        } catch (SemanticException e) {
1164
                                throw new RuntimeException(
1165
                                                "La informaci?n guardada no es consistente", e);
1166
                        } catch (IOException e) {
1167
                                throw new RuntimeException(
1168
                                                "La informaci?n guardada no es consistente", e);
1169
                        } catch (EvaluationException e) {
1170
                                throw new RuntimeException(
1171
                                                "La informaci?n guardada no es consistente", e);
1172
                        }
1173
                }
1174
        }
1175

    
1176
        /**
1177
         * Devuelve true si todas las tablas provienen del mismo data base
1178
         * management system
1179
         *
1180
         * @param tables
1181
         *            Array de tablas
1182
         *
1183
         * @return boolean
1184
         */
1185
        private boolean sameDBMS(DataSource[] tables) {
1186
                if (!(tables[0] instanceof DBDataSource)) {
1187
                        return false;
1188
                }
1189

    
1190
                String dbms = ((DBDataSource) tables[0]).getDBMS();
1191

    
1192
                for (int i = 1; i < tables.length; i++) {
1193
                        if (!(tables[i] instanceof DBDataSource)) {
1194
                                return false;
1195
                        }
1196

    
1197
                        if (!dbms.equals(((DBDataSource) tables[1]).getDBMS())) {
1198
                                return false;
1199
                        }
1200
                }
1201

    
1202
                return true;
1203
        }
1204

    
1205
        /**
1206
         * A partir de una instrucci?n select se encarga de obtener el DataSource
1207
         * resultado de la ejecuci?n de dicha instrucci?n
1208
         *
1209
         * @param instr
1210
         *            Instrucci?n select origen del datasource
1211
         * @param mode
1212
         *            opening mode
1213
         *
1214
         * @return DataSource que accede a los datos resultado de ejecutar la select
1215
         *
1216
         * @throws DriverLoadException
1217
         * @throws DriverException
1218
         *             Si fallo la lectura de la fuente de datos por parte del
1219
         *             driver
1220
         * @throws SemanticException
1221
         *             Si la instrucci?n tiene errores sem?nticos
1222
         * @throws IOException
1223
         *             Si se produce un error accediendo a las estructuras de datos
1224
         *             internas
1225
         * @throws EvaluationException
1226
         *             If there's an error evaluating any expression
1227
         */
1228
        public DataSource createRandomDataSource(SelectAdapter instr, int mode)
1229
                        throws DriverLoadException, DriverException, SemanticException,
1230
                        IOException, EvaluationException {
1231
                return getModedDataSource(getDataSource(instr), mode);
1232
        }
1233

    
1234
        /**
1235
         * Creates a view in the database management system that hosts the data
1236
         * source 'dbds'. The view is defined by the sql parameter
1237
         *
1238
         * @param dbds
1239
         *            DataSource used to execute the query
1240
         * @param sql
1241
         *            The SQL query defining the view
1242
         *
1243
         * @return Name of the view
1244
         *
1245
         * @throws DriverException
1246
         *             If the view cannot be created
1247
         */
1248
        private String getView(DBDataSource dbds, String sql)
1249
                        throws DriverException {
1250
                ServerViewInfo svi = (ServerViewInfo) sourceInfoServerViewInfo.get(dbds
1251
                                .getSourceInfo());
1252

    
1253
                /*
1254
                 * Return the view name if it's already created or create the view if
1255
                 * it's not created
1256
                 */
1257
                if (svi != null) {
1258
                        return svi.viewName;
1259
                } else {
1260
                        // create the view
1261
                        String viewName = getUID();
1262
                        String viewQuery = "CREATE VIEW " + viewName + " AS " + sql;
1263
                        dbds.execute(viewQuery);
1264

    
1265
                        // Register the view created
1266
                        sourceInfoServerViewInfo.put(dbds.getSourceInfo(),
1267
                                        new ServerViewInfo(dbds, viewName));
1268

    
1269
                        return viewName;
1270
                }
1271
        }
1272

    
1273
        /**
1274
         * Gets a DataSource implementation with the sql instruction as the data
1275
         * source by creating a view in the underlaying datasource management system
1276
         *
1277
         * @param sql
1278
         *            Instruction definig the data source
1279
         * @param driver
1280
         *            Driver used to access the data source
1281
         * @param dbInfo
1282
         *            data source info
1283
         *
1284
         * @return DataSource
1285
         *
1286
         * @throws DriverException
1287
         *             If cannot create the view
1288
         */
1289
        private DBDataSource getDataSourceByQuery(String sql,
1290
                        AlphanumericDBDriver driver, DBTableSourceInfo dbInfo)
1291
                        throws DriverException {
1292
                // Create the adapter
1293
                DBDataSource adapter = DBDataSourceFactory.newDataSourceInstance();
1294

    
1295
                // set the driver
1296
                adapter.setDriver(driver);
1297

    
1298
                // Create the query
1299
                adapter.setSourceInfo(dbInfo);
1300

    
1301
                // Gets the view name
1302
                String viewName = getView(adapter, sql);
1303

    
1304
                // Complete the source info with the view name
1305
                dbInfo.tableName = viewName;
1306

    
1307
                // Register the name association
1308
                nameTable.put(dbInfo.name, viewName);
1309

    
1310
                // setup the adapter
1311
                adapter.setSourceInfo(dbInfo);
1312
                adapter.setDataSourceFactory(this);
1313

    
1314
                return adapter;
1315
        }
1316

    
1317
        /**
1318
         * A partir de una instrucci?n select se encarga de obtener el DataSource
1319
         * resultado de la ejecuci?n de dicha instrucci?n
1320
         *
1321
         * @param instr
1322
         *            Instrucci?n select origen del datasource
1323
         *
1324
         * @return DataSource que accede a los datos resultado de ejecutar la select
1325
         *
1326
         * @throws DriverException
1327
         * @throws SemanticException
1328
         * @throws IOException
1329
         * @throws EvaluationException
1330
         * @throws RuntimeException
1331
         *             bug
1332
         */
1333
        private DataSource getDataSource(SelectAdapter instr)
1334
                        throws DriverException, SemanticException, IOException,
1335
                        EvaluationException {
1336
                DataSource[] tables = instr.getTables();
1337

    
1338
                // Estrategia de delegaci?n de la instrucci?n en el sgbd original de la
1339
                // tabla
1340
                if (sameDBMS(tables) && delegating) {
1341
                        String sql = translateInstruction(instr, tables);
1342

    
1343
                        DBDataSource table = (DBDataSource) tables[0];
1344

    
1345
                        // Set the driver info
1346
                        DBSourceInfo source = (DBSourceInfo) table.getSourceInfo();
1347
                        String dataSourceName = addDBDataSourceBySQL(source.host,
1348
                                        source.port, source.user, source.password, source.dbName,
1349
                                        sql, source.driverName);
1350

    
1351
                        try {
1352
                                return createRandomDataSource(dataSourceName,
1353
                                                DataSourceFactory.MANUAL_OPENING);
1354
                        } catch (NoSuchTableException e) {
1355
                                throw new RuntimeException(e);
1356
                        } catch (DriverLoadException e) {
1357
                                throw new RuntimeException(e);
1358
                        } catch (DriverException e) {
1359
                                throw new RuntimeException(e);
1360
                        }
1361
                }
1362

    
1363
                // Estrategia normal
1364
                Strategy strategy = StrategyManager.getStrategy(instr);
1365

    
1366
                OperationDataSource ret = strategy.select(instr);
1367

    
1368
                ret.setName(getUID());
1369
                nameOperationDataSource.put(ret.getName(), ret);
1370

    
1371
                return ret;
1372
        }
1373

    
1374
        /**
1375
         * Translates the table references by changind the gdbms name with the
1376
         * underlaying database management system table name
1377
         *
1378
         * @param instr
1379
         *            root of the adapted tree
1380
         * @param tables
1381
         *            DataSources involved in the instruction
1382
         *
1383
         * @return The translated sql query
1384
         *
1385
         * @throws DriverException
1386
         *             If driver access fails
1387
         * @throws SemanticException
1388
         *             If the instruction is not semantically correct
1389
         */
1390
        private String translateInstruction(Adapter instr, DataSource[] tables)
1391
                        throws DriverException, SemanticException {
1392
                HashMap instrNameDBName = new HashMap();
1393

    
1394
                translateFromTables(instr, instrNameDBName);
1395
                translateColRefs(instr, instrNameDBName, tables);
1396

    
1397
                return Utilities.getText(instr.getEntity());
1398
        }
1399

    
1400
        /**
1401
         * Gets the name of the table where the field is in
1402
         *
1403
         * @param fieldName
1404
         *            field whose table wants to be guessed
1405
         * @param tables
1406
         *            tables involved in the search
1407
         *
1408
         * @return table name
1409
         *
1410
         * @throws DriverException
1411
         *             If driver access fails
1412
         * @throws SemanticException
1413
         *             If the instruction is not semantically correct
1414
         */
1415
        private String guessTableName(String fieldName, DataSource[] tables)
1416
                        throws DriverException, SemanticException {
1417
                int tableIndex = -1;
1418

    
1419
                for (int i = 0; i < tables.length; i++) {
1420
                        tables[i].start();
1421

    
1422
                        if (tables[i].getFieldIndexByName(fieldName) != -1) {
1423
                                if (tableIndex != -1) {
1424
                                        throw new SemanticException("ambiguous column reference: "
1425
                                                        + fieldName);
1426
                                } else {
1427
                                        tableIndex = i;
1428
                                }
1429
                        }
1430

    
1431
                        tables[i].stop();
1432
                }
1433

    
1434
                if (tableIndex == -1) {
1435
                        throw new SemanticException("Field not found: " + fieldName);
1436
                }
1437

    
1438
                return tables[tableIndex].getName();
1439
        }
1440

    
1441
        /**
1442
         * Translates the table references by changind the gdbms name with the
1443
         * underlaying database management system table name
1444
         *
1445
         * @param adapter
1446
         *            adapter processed
1447
         * @param instrNameDBName
1448
         *            hasmap with the gdbms names a s the keys and the database name
1449
         *            as the values.
1450
         * @param tables
1451
         *            tables involved in the instruction
1452
         *
1453
         * @throws DriverException
1454
         *             If driver access fails
1455
         * @throws SemanticException
1456
         *             If the instruction is not semantically correct
1457
         */
1458
        private void translateColRefs(Adapter adapter, HashMap instrNameDBName,
1459
                        DataSource[] tables) throws DriverException, SemanticException {
1460
                if (adapter instanceof ColRefAdapter) {
1461
                        ColRefAdapter tra = (ColRefAdapter) adapter;
1462
                        SimpleNode s = tra.getEntity();
1463

    
1464
                        if (s.first_token != s.last_token) {
1465
                                String name = s.first_token.image;
1466
                                s.first_token.image = instrNameDBName.get(name).toString();
1467
                        } else {
1468
                                String tableName = guessTableName(s.first_token.image, tables);
1469
                                s.first_token.image = instrNameDBName.get(tableName) + "."
1470
                                                + s.first_token.image;
1471
                        }
1472
                } else {
1473
                        Adapter[] hijos = adapter.getChilds();
1474

    
1475
                        for (int i = 0; i < hijos.length; i++) {
1476
                                translateColRefs(hijos[i], instrNameDBName, tables);
1477
                        }
1478
                }
1479
        }
1480

    
1481
        /**
1482
         * Translates the table references by changind the gdbms name with the
1483
         * underlaying database management system table name
1484
         *
1485
         * @param adapter
1486
         *            adapter processed
1487
         * @param instrNameDBName
1488
         *            hasmap with the gdbms names a s the keys and the database name
1489
         *            as the values.
1490
         */
1491
        private void translateFromTables(Adapter adapter, HashMap instrNameDBName) {
1492
                if (adapter instanceof TableRefAdapter) {
1493
                        TableRefAdapter tra = (TableRefAdapter) adapter;
1494
                        SimpleNode s = tra.getEntity();
1495

    
1496
                        if (s.first_token == s.last_token) {
1497
                                String alias = "gdbms" + System.currentTimeMillis();
1498
                                String name = s.first_token.image;
1499
                                s.first_token.image = nameTable.get(name) + " " + alias;
1500
                                instrNameDBName.put(name, alias);
1501
                        } else {
1502
                                String alias = s.last_token.image;
1503
                                String name = s.first_token.image;
1504
                                s.first_token.image = nameTable.get(name).toString();
1505
                                instrNameDBName.put(alias, alias);
1506
                        }
1507
                } else {
1508
                        Adapter[] hijos = adapter.getChilds();
1509

    
1510
                        for (int i = 0; i < hijos.length; i++) {
1511
                                translateFromTables(hijos[i], instrNameDBName);
1512
                        }
1513
                }
1514
        }
1515

    
1516
        /**
1517
         * Obtiene el DataSource resultado de ejecutar la instrucci?n de union
1518
         *
1519
         * @param instr
1520
         *            instrucci?n de union
1521
         * @param mode
1522
         *            opening mode
1523
         *
1524
         * @return DataSource
1525
         *
1526
         * @throws DriverException
1527
         *             Si fallo la lectura de la fuente de datos por parte del
1528
         *             driver
1529
         * @throws IOException
1530
         *             Si se produce un error de entrada/salida
1531
         * @throws SemanticException
1532
         *             Si la instrucci?n tiene errores sem?nticos
1533
         * @throws EvaluationException
1534
         *             If there's any problem during expresion evaluation
1535
         * @throws ParseException
1536
         *             If there is a select statement embeeded in the union
1537
         *             statement and its parse fails
1538
         */
1539
        public DataSource createRandomDataSource(UnionAdapter instr, int mode)
1540
                        throws DriverException, IOException, SemanticException,
1541
                        EvaluationException, ParseException {
1542
                return getModedDataSource(getDataSource(instr), mode);
1543
        }
1544

    
1545
        /**
1546
         * Obtiene el DataSource resultado de ejecutar la instrucci?n de union
1547
         *
1548
         * @param instr
1549
         *            instrucci?n de union
1550
         *
1551
         * @return DataSource
1552
         *
1553
         * @throws DriverException
1554
         *             Si fallo la lectura de la fuente de datos por parte del
1555
         *             driver
1556
         * @throws IOException
1557
         *             Si se produce un error de entrada/salida
1558
         * @throws SemanticException
1559
         *             Si la instrucci?n tiene errores sem?nticos
1560
         * @throws ParseException
1561
         *             If there is a select statement embeeded in the union
1562
         *             statement and its parse fails
1563
         * @throws EvaluationException
1564
         *             If there's any problem during expresion evaluation
1565
         */
1566
        private DataSource getDataSource(UnionAdapter instr)
1567
                        throws DriverException, IOException, SemanticException,
1568
                        ParseException, EvaluationException {
1569
                try {
1570
                        Strategy strategy = StrategyManager.getStrategy(instr);
1571

    
1572
                        OperationDataSource ret;
1573
                        ret = strategy.union(instr);
1574

    
1575
                        ret.setName(getUID());
1576
                        nameOperationDataSource.put(ret.getName(), ret);
1577

    
1578
                        return ret;
1579
                } catch (DriverLoadException e) {
1580
                        throw new DriverException(e);
1581
                }
1582

    
1583
        }
1584

    
1585
        /**
1586
         * Creates a DataSource as a result of a custom query
1587
         *
1588
         * @param instr
1589
         *            Root node of the adapter tree of the custom query instruction
1590
         * @param mode
1591
         *            opening mode
1592
         *
1593
         * @return DataSource with the custom query result
1594
         *
1595
         * @throws SemanticException
1596
         *             if there is any semantic error in the instruction
1597
         */
1598
        public DataSource getDataSource(CustomAdapter instr, int mode)
1599
                        throws SemanticException {
1600
                return getModedDataSource(getDataSource(instr), mode);
1601
        }
1602

    
1603
        /**
1604
         * Creates a DataSource as a result of a custom query
1605
         *
1606
         * @param instr
1607
         *            Root node of the adapter tree of the custom query instruction
1608
         *
1609
         * @return DataSource with the custom query result
1610
         *
1611
         * @throws SemanticException
1612
         *             if there is any semantic error in the instruction
1613
         */
1614
        private DataSource getDataSource(CustomAdapter instr)
1615
                        throws SemanticException {
1616
                Strategy strategy = StrategyManager.getStrategy(instr);
1617

    
1618
                OperationDataSource ret = strategy.custom(instr);
1619

    
1620
                ret.setName(getUID());
1621
                nameOperationDataSource.put(ret.getName(), ret);
1622

    
1623
                return ret;
1624
        }
1625

    
1626
        /**
1627
         * Ejecuta la instrucci?n SQL que se pasa como par?metro obteniendo un
1628
         * DataSource con el resultado de la ejecuci?n
1629
         *
1630
         * @param sql
1631
         *            instrucci?n sql que se quiere ejecutar
1632
         * @param mode
1633
         *            opening mode
1634
         *
1635
         * @return DataSource con el resultado
1636
         *
1637
         * @throws ParseException
1638
         *             Si se produce un error de parse de la instrucci?n
1639
         * @throws DriverLoadException
1640
         *             Si no se pueden cargar los drivers
1641
         * @throws DriverException
1642
         *             Si se produce un error accediendo a los drivers
1643
         * @throws SemanticException
1644
         *             Si la instrucci?n tiene alg?n error sem?ntico
1645
         * @throws IOException
1646
         *             Si se produce un error accediendo a las estructuras de datos
1647
         *             internas usadas para los c?lculos
1648
         * @throws EvaluationException
1649
         *             If there's an error evaluating any expression
1650
         */
1651
        public DataSource executeSQL(String sql, int mode) throws ParseException,
1652
                        DriverLoadException, DriverException, SemanticException,
1653
                        IOException, EvaluationException {
1654
                ByteArrayInputStream bytes = new ByteArrayInputStream(sql.getBytes());
1655
                SQLEngine parser = new SQLEngine(bytes);
1656

    
1657
                parser.SQLStatement();
1658

    
1659
                Node root = parser.getRootNode();
1660
                Adapter rootAdapter = Utilities.buildTree(root.jjtGetChild(0), sql,
1661
                                this);
1662

    
1663
                Utilities.simplify(rootAdapter);
1664

    
1665
                DataSource result = null;
1666

    
1667
                if (rootAdapter instanceof SelectAdapter) {
1668
                        result = getDataSource((SelectAdapter) rootAdapter);
1669
                } else if (rootAdapter instanceof UnionAdapter) {
1670
                        result = getDataSource((UnionAdapter) rootAdapter);
1671
                } else if (rootAdapter instanceof CustomAdapter) {
1672
                        result = getDataSource((CustomAdapter) rootAdapter);
1673
                }
1674

    
1675
                // if operation was delegated it isn't a OperationDataSource
1676
                if (result instanceof OperationDataSource) {
1677
                        ((OperationDataSource) result).setSQL(sql);
1678
                }
1679

    
1680
                result.setDataSourceFactory(this);
1681

    
1682
                return getModedDataSource(result, mode);
1683
        }
1684

    
1685
        /**
1686
         * Establece el DriverManager que se usar? para instanciar DataSource's.
1687
         * Este metodo debe ser invocado antes que ning?n otro
1688
         *
1689
         * @param dm
1690
         *            El manager que se encarga de cargar los drivers
1691
         */
1692
        public void setDriverManager(DriverManager dm) {
1693
                this.dm = dm;
1694
        }
1695
        /**
1696
         * Establece el WriterManager que se usar? para instanciar DataSource's.
1697
         * Este metodo debe ser invocado antes que ning?n otro
1698
         *
1699
         * @param dm
1700
         *            El manager que se encarga de cargar los drivers
1701
         */
1702
        public void setWriterManager(WriterManager wm) {
1703
                this.wm = wm;
1704
        }
1705
        /**
1706
         * Get's the module with the specified name
1707
         *
1708
         * @param name
1709
         *            name of the wanted module
1710
         *
1711
         * @return instance of the module
1712
         */
1713
        public Object getModule(String name) {
1714
                return ms.getModule(name);
1715
        }
1716

    
1717
        /**
1718
         * Registers a module in the system with the specified name
1719
         *
1720
         * @param name
1721
         *            name of the module
1722
         * @param instance
1723
         *            module instance
1724
         */
1725
        public void registerModule(String name, Object instance) {
1726
                ms.registerModule(name, instance);
1727
        }
1728

    
1729
        /**
1730
         * Gets a driver manager reference
1731
         *
1732
         * @return DriverManagers.
1733
         */
1734
        public DriverManager getDriverManager() {
1735
                return dm;
1736
        }
1737
        /**
1738
         * Gets a writer manager reference
1739
         *
1740
         * @return WriterManagers.
1741
         */
1742
        public WriterManager getWriterManager() {
1743
                return wm;
1744
        }
1745
        /**
1746
         * Sets if this factory will check for delegating instructions at the server
1747
         * (true) or will execute all queries internally (false). By delegating at
1748
         * the server, lots of queries will be defined in the database management
1749
         * system where the execution is delegated. Invoke clearViews to remove all
1750
         * created views.
1751
         *
1752
         * @param b
1753
         */
1754
        public void setDelegating(boolean b) {
1755
                this.delegating = b;
1756
        }
1757

    
1758
        /**
1759
         * Creates a new table on the specified database
1760
         *
1761
         * @param database
1762
         *            name of the database where the table will be created
1763
         * @param pkNames
1764
         *            Names of the primary key fields
1765
         * @param names
1766
         *            names of the fields
1767
         * @param types
1768
         *            types of the fields. Must have the same length than names
1769
         *
1770
         * @return the table name
1771
         *
1772
         * @throws SQLException
1773
         *             if the creation fails
1774
         */
1775
        public String createTable(String database, String[] pkNames,
1776
                        String[] names, int[] types) throws SQLException {
1777
                // Get a name for the table
1778
                String tableName = getUID();
1779

    
1780
                // Create the table
1781
                InnerDBUtils.execute(database, InnerDBUtils.getCreateStatementWithPK(
1782
                                tableName, pkNames, names, types));
1783

    
1784
                return tableName;
1785
        }
1786

    
1787
        /**
1788
         * Frees all resources used during execution
1789
         *
1790
         * @throws SQLException
1791
         *             If cannot free internal resources
1792
         * @throws DriverException
1793
         *             If drivers cannot free remote resources
1794
         */        
1795
        public void finalizeThis()  throws SQLException, DriverException {
1796
                
1797
                try {
1798
                        clearViews();
1799
                } finally {
1800
                        Connection c = null;
1801
                        try {
1802
                                c = java.sql.DriverManager.getConnection(
1803
                                                "jdbc:hsqldb:file:", "", "");
1804
                        } catch (Exception e) {
1805
                                return;
1806
                        }
1807
                        Statement st = c.createStatement();
1808
                        st.execute("SHUTDOWN");
1809
                        st.close();
1810
                        c.close();
1811
                }
1812
                
1813
        }
1814

    
1815
        /**
1816
         * Initializes the system.
1817
         *
1818
         * @throws InitializationException
1819
         *             If the initialization
1820
         */
1821
        public void initialize() throws InitializationException {
1822
                initialize(".");
1823
        }
1824

    
1825
        /**
1826
         * Initializes the system
1827
         *
1828
         * @param tempDir
1829
         *            temporary directory to write data
1830
         *
1831
         * @throws InitializationException
1832
         *             If the initialization fails
1833
         */
1834
        public void initialize(String tempDir) throws InitializationException {
1835
                try {
1836
                        this.tempDir = new File(tempDir);
1837

    
1838
                        if (!this.tempDir.exists()) {
1839
                                this.tempDir.mkdirs();
1840
                        }
1841

    
1842
                        Class.forName("org.hsqldb.jdbcDriver");
1843
                } catch (ClassNotFoundException e) {
1844
                        throw new InitializationException(e);
1845
                }
1846
                fillDriversNamesAliases();
1847
        }
1848

    
1849
        /**
1850
         * Gets the URL of a file in the temporary directory. Does not creates any
1851
         * file
1852
         *
1853
         * @return String
1854
         */
1855
        public String getTempFile() {
1856
                return tempDir.getAbsolutePath() + File.separator + "gdmbs"
1857
                                + System.currentTimeMillis();
1858
        }
1859

    
1860
        /**
1861
         * Registra alias de nombres de los drivers
1862
         * por si ha sido necesario modificar el nombre
1863
         * de alguno, y se necesita compatibilidad
1864
         * 
1865
         */
1866
        private void fillDriversNamesAliases() {
1867
                
1868
        }
1869
        
1870
        private Driver getDriver(String name) {
1871
                if (this.driversNamesAliases.containsKey(name)) {
1872
                        name = (String)this.driversNamesAliases.get(name);
1873
                }
1874
                return this.dm.getDriver(name);
1875
                
1876
        }
1877

    
1878
        /**
1879
         * Information to delete the view on the server: name of the view and the
1880
         * adapter to remove it
1881
         */
1882
        private class ServerViewInfo {
1883
                public DBDataSource adapter;
1884

    
1885
                public String viewName;
1886

    
1887
                /**
1888
                 * Crea un nuevo ServerViewInfo.
1889
                 *
1890
                 * @param ds
1891
                 *            DOCUMENT ME!
1892
                 * @param name
1893
                 *            DOCUMENT ME!
1894
                 */
1895
                public ServerViewInfo(DBDataSource ds, String name) {
1896
                        adapter = ds;
1897
                        viewName = name;
1898
                }
1899
        }
1900
        
1901
}