Statistics
| Revision:

svn-gvsig-desktop / branches / v2_0_0_prep / libraries / libFMap_daldb / src / org / gvsig / fmap / dal / store / jdbc / JDBCStoreProvider.java @ 29289

History | View | Annotate | Download (22.9 KB)

1
/* gvSIG. Geographic Information System of the Valencian Government
2
*
3
* Copyright (C) 2007-2008 Infrastructures and Transports Department
4
* of the Valencian Government (CIT)
5
*
6
* This program is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU General Public License
8
* as published by the Free Software Foundation; either version 2
9
* of the License, or (at your option) any later version.
10
*
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
* GNU General Public License for more details.
15
*
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
* MA  02110-1301, USA.
20
*
21
*/
22

    
23
/*
24
* AUTHORS (In addition to CIT):
25
* 2009 IVER T.I   {{Task}}
26
*/
27

    
28
/**
29
 *
30
 */
31
package org.gvsig.fmap.dal.store.jdbc;
32

    
33
import java.security.InvalidParameterException;
34
import java.sql.Connection;
35
import java.sql.PreparedStatement;
36
import java.sql.ResultSet;
37
import java.sql.SQLException;
38
import java.sql.Statement;
39
import java.util.ArrayList;
40
import java.util.Iterator;
41
import java.util.List;
42

    
43
import org.cresques.cts.IProjection;
44
import org.gvsig.fmap.dal.DALLocator;
45
import org.gvsig.fmap.dal.DataManager;
46
import org.gvsig.fmap.dal.DataServerExplorer;
47
import org.gvsig.fmap.dal.DataStoreNotification;
48
import org.gvsig.fmap.dal.DataTypes;
49
import org.gvsig.fmap.dal.exception.CloseException;
50
import org.gvsig.fmap.dal.exception.DataException;
51
import org.gvsig.fmap.dal.exception.InitializeException;
52
import org.gvsig.fmap.dal.exception.OpenException;
53
import org.gvsig.fmap.dal.exception.ReadException;
54
import org.gvsig.fmap.dal.exception.ValidateDataParametersException;
55
import org.gvsig.fmap.dal.feature.EditableFeatureType;
56
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
57
import org.gvsig.fmap.dal.feature.FeatureQuery;
58
import org.gvsig.fmap.dal.feature.FeatureStore;
59
import org.gvsig.fmap.dal.feature.FeatureType;
60
import org.gvsig.fmap.dal.feature.spi.AbstractFeatureStoreProvider;
61
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
62
import org.gvsig.fmap.dal.feature.spi.FeatureReferenceProviderServices;
63
import org.gvsig.fmap.dal.feature.spi.FeatureSetProvider;
64
import org.gvsig.fmap.dal.feature.spi.FeatureStoreProvider;
65
import org.gvsig.fmap.dal.feature.spi.FeatureStoreProviderServices;
66
import org.gvsig.fmap.dal.resource.Resource;
67
import org.gvsig.fmap.dal.resource.exception.ResourceBeginException;
68
import org.gvsig.fmap.dal.resource.spi.ResourceProvider;
69
import org.gvsig.fmap.dal.store.jdbc.exception.InvalidResultSetIdException;
70
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCException;
71
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCExecuteSQLException;
72
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCSQLException;
73
import org.gvsig.fmap.geom.Geometry;
74
import org.gvsig.fmap.geom.operation.towkb.ToWKB;
75
import org.gvsig.fmap.geom.primitive.Envelope;
76
import org.gvsig.tools.ToolsLocator;
77
import org.gvsig.tools.dynobject.DelegatedDynObject;
78
import org.gvsig.tools.dynobject.DynClass;
79
import org.gvsig.tools.dynobject.DynObjectManager;
80
import org.gvsig.tools.exception.BaseException;
81
import org.slf4j.Logger;
82
import org.slf4j.LoggerFactory;
83

    
84

    
85
/**
86
 * @author jmvivo
87
 *
88
 */
89
public class JDBCStoreProvider extends AbstractFeatureStoreProvider
90
                implements JDBCHelperUser {
91

    
92
        final static private Logger logger = LoggerFactory
93
                        .getLogger(JDBCStoreProvider.class);
94

    
95
        private List resulsetList;
96

    
97
        public static String NAME = "JDBC";
98
        private static final String DYNCLASS_NAME = "JDBCStore";
99
        public static String DESCRIPTION = "JDBC source";
100
        private static DynClass DYNCLASS = null;
101

    
102
        private long mlsecondsToZombie = 1000 * 60 * 10; // 10 Min
103

    
104
        protected JDBCStoreParameters params;
105
        protected JDBCHelper helper;
106

    
107
        protected boolean directSQLMode;
108

    
109
        private Long totalCount = null;
110

    
111

    
112
        public JDBCStoreProvider() {
113
                super();
114
                resulsetList = new ArrayList(10);
115
        }
116

    
117
        public JDBCStoreProvider(JDBCStoreParameters params)
118
                        throws InitializeException {
119
                this();
120
                this.init(params);
121
        }
122

    
123

    
124
        protected static void registerDynClass() {
125
                DynObjectManager dynman = ToolsLocator.getDynObjectManager();
126
                DynClass dynClass;
127
                if (DYNCLASS == null) {
128
                        dynClass = dynman.add(DYNCLASS_NAME, DESCRIPTION);
129

    
130
                        dynClass.extend(dynman.get(FeatureStore.DYNCLASS_NAME));
131
                        DYNCLASS = dynClass;
132
                }
133
        }
134

    
135
        /**
136
         * Load data form a resulset.<br>
137
         *
138
         * <strong>Note:</strong><br>
139
         * this method have to perform <code>resouceBegin</code> at the begining and
140
         * <code>resourceEnd</code> at the end of execution.
141
         *
142
         *
143
         * @param data
144
         * @param resulsetID
145
         *
146
         * @return
147
         * @throws DataException
148
         */
149
        public void loadFeatureData(FeatureProvider data, int resultsetID)
150
                        throws DataException {
151
                this.resourceBegin();
152
                try {
153
                        ResultSet rs = getResultSet(resultsetID);
154
                        FeatureAttributeDescriptor attr;
155
                        Iterator iter = data.getType().iterator();
156
                        while (iter.hasNext()) {
157
                                attr = (FeatureAttributeDescriptor) iter.next();
158
                                loadFeatureDataValue(data, rs, attr);
159
                        }
160
                } finally {
161
                        this.resourceEnd();
162
                }
163

    
164

    
165

    
166
        }
167

    
168

    
169
        protected void loadFeatureDataValue(FeatureProvider data, ResultSet rs,
170
                        FeatureAttributeDescriptor attr) throws DataException {
171
                if (attr.getDataType() == DataTypes.GEOMETRY) {
172
                        byte[] buffer;
173
                        try {
174
                                buffer = rs.getBytes(attr.getIndex() + 1);
175
                                if (buffer == null) {
176
                                        data.set(attr.getIndex(), null);
177
                                } else {
178
                                        data.set(attr.getIndex(), this.helper.getGeometry(buffer));
179
                                }
180
                        } catch (SQLException e) {
181
                                throw new JDBCSQLException(e);
182
                        } catch (BaseException e) {
183
                                throw new ReadException(getName(), e);
184
                        }
185

    
186
                } else {
187
                        try {
188
                                data.set(attr.getIndex(), rs.getObject(attr.getIndex() + 1));
189
                        } catch (SQLException e) {
190
                                throw new JDBCSQLException(e);
191
                        }
192
                }
193
        }
194

    
195
        public long getTimeToResulSetZombie() {
196
                return mlsecondsToZombie;
197
        }
198

    
199
        public void setTimeToResulSetZombie(long mlSeconds) {
200
                mlsecondsToZombie = mlSeconds;
201
        }
202

    
203
        private class ResultSetInfo{
204
                private ResultSet resultSet = null;
205
                private long lastUse = 0;
206

    
207
                public ResultSetInfo(ResultSet resulSet) {
208
                        this.resultSet = resulSet;
209
                        used();
210
                }
211

    
212
                private void used() {
213
                        lastUse = System.currentTimeMillis();
214
                }
215

    
216

    
217
                public ResultSet get() {
218
                        used();
219
                        return resultSet;
220
                }
221

    
222
                public boolean isZombie() {
223
                        return System.currentTimeMillis() - lastUse > mlsecondsToZombie;
224
                }
225
        }
226

    
227
        public final int createResultSet(String sql)
228
                        throws DataException {
229
                return createResultSet(sql, null);
230
        }
231

    
232
        public final int createResultSet(String sql, Object[] values)
233
                        throws DataException {
234
                synchronized (this) {
235
                        checksResulsets();
236
                        resourceBegin();
237
                        try {
238
                                ResultSetInfo newRs = new ResultSetInfo(createNewResultSet(sql,
239
                                                values));
240
                                int newId = getNewId();
241
                                if (newId < 0) {
242
                                        newId = resulsetList.size();
243
                                        resulsetList.add(newRs);
244
                                } else {
245
                                        resulsetList.set(newId, newRs);
246
                                }
247
                                if (logger.isDebugEnabled()) {
248
                                        logger.debug(" id: {} (total {})", newId,
249
                                                        getResultsetOpenCount());
250
                                }
251

    
252
                                return newId;
253
                        } finally {
254
                                resourceEnd();
255
                        }
256

    
257
                }
258
        }
259

    
260
        private int getNewId() {
261
                int newId;
262
                if (resulsetList.size() < 1) {
263
                        return -1;
264
                }
265
                for (newId = 0; newId < resulsetList.size(); newId++) {
266
                        if (resulsetList.get(newId) == null) {
267
                                return newId;
268
                        }
269
                }
270
                return -1;
271
        }
272

    
273
        protected final void forceCloseAllResultSet()
274
                        throws ResourceBeginException,
275
                        JDBCException {
276
                synchronized (this) {
277
                        Iterator iter = resulsetList.iterator();
278
                        Integer rsID = null;
279
                        while (iter.hasNext()) {
280
                                rsID = (Integer) iter.next();
281
                                if (rsID != null) {
282
                                        try {
283
                                                forceCloseResultSet(rsID.intValue());
284
                                        } catch (InvalidResultSetIdException e) {
285
                                                continue;
286
                                        }
287
                                }
288
                                iter.remove();
289
                        }
290

    
291
                }
292
        }
293

    
294
        protected final void forceCloseResultSet(int rsID)
295
                        throws ResourceBeginException, JDBCException,
296
                        InvalidResultSetIdException {
297
                logger.warn("Close forced of resultSet ({})", rsID);
298
                closeResulset(rsID);
299
        }
300

    
301
        protected final ResultSet getResultSet(int resultsetID)
302
                        throws InvalidResultSetIdException {
303
                if (resultsetID >= resulsetList.size()) {
304
                        throw new InvalidResultSetIdException(resultsetID);
305
                }
306
                ResultSetInfo rsInfo = (ResultSetInfo) resulsetList.get(resultsetID);
307
                if (rsInfo == null) {
308
                        throw new InvalidResultSetIdException(resultsetID);
309
                }
310
                return rsInfo.get();
311

    
312
        }
313

    
314
        private ResultSet dropResultSet(int resultsetID)
315
                        throws InvalidResultSetIdException {
316
                if (resultsetID >= resulsetList.size()) {
317
                        throw new InvalidResultSetIdException(resultsetID);
318
                }
319
                ResultSetInfo rsInfo = (ResultSetInfo) resulsetList.get(resultsetID);
320
                if (rsInfo == null) {
321
                        throw new InvalidResultSetIdException(resultsetID);
322
                }
323
                if (resultsetID == resulsetList.size() - 1) {
324
                        resulsetList.remove(resultsetID);
325
                } else {
326
                        resulsetList.set(resultsetID, null);
327
                }
328
                return rsInfo.get();
329
        }
330

    
331

    
332
        public final boolean resulsetNext(int resultsetID) throws JDBCException,
333
                        InvalidResultSetIdException, ResourceBeginException {
334
                ResultSet rs = getResultSet(resultsetID);
335
                resourceBegin();
336
                try {
337
                        return rs.next();
338
                } catch (SQLException e) {
339
                        throw new JDBCSQLException(e);
340
                } finally {
341
                        resourceEnd();
342
                }
343
        }
344

    
345
        public final void closeResulset(int resultsetID)
346
                        throws JDBCException,
347
                        InvalidResultSetIdException, ResourceBeginException {
348
                synchronized (this) {
349
                        resourceBegin();
350
                        try {
351
                                ResultSet rs = dropResultSet(resultsetID);
352
                                closeResulset(rs);
353
                                if (logger.isDebugEnabled()) {
354
                                        logger.debug(" id: " + resultsetID + " (total "
355
                                                        + getResultsetOpenCount() + ")");
356
                                }
357

    
358
                        } finally {
359
                                resourceEnd();
360
                        }
361
                        checksResulsets();
362
                }
363
        }
364

    
365
        public final void checksResulsets() throws JDBCException,
366
                        InvalidResultSetIdException, ResourceBeginException {
367
                synchronized (this) {
368
                        resourceBegin();
369
                        try {
370
                                ResultSetInfo rsInfo;
371
                                for (int i = 0; i < resulsetList.size(); i++) {
372
                                        rsInfo = (ResultSetInfo) resulsetList.get(i);
373
                                        if (rsInfo == null) {
374
                                                continue;
375
                                        }
376
                                        if (rsInfo.isZombie()) {
377
                                                forceCloseResultSet(i);
378
                                        }
379
                                }
380

    
381
                        } finally {
382
                                resourceEnd();
383
                        }
384

    
385
                }
386
        }
387

    
388

    
389
        private int getResultsetOpenCount() {
390
                int count = 0;
391
                Iterator iter = resulsetList.iterator();
392
                while (iter.hasNext()) {
393
                        if (iter.next() != null) {
394
                                count++;
395
                        }
396
                }
397
                return count;
398
        }
399

    
400
        protected void closeResulset(ResultSet rs) throws JDBCException,
401
                        ResourceBeginException {
402
                resourceBegin();
403
                try {
404
                        Statement st = rs.getStatement();
405
                        Connection con = st.getConnection();
406
                        try {
407
                                rs.close();
408
                        } finally {
409
                                // TODO revisar esto
410
                                try{ st.close();  } catch (Exception ex){ };
411
                                try{ con.close(); } catch (Exception ex){ };
412
                        }
413
                } catch (SQLException e) {
414
                        throw new JDBCSQLException(e);
415
                } finally {
416
                        resourceEnd();
417
                }
418

    
419
        }
420

    
421
        protected final int openResulsetCount() {
422
                int count = 0;
423
                Iterator iter = resulsetList.iterator();
424
                while (iter.hasNext()) {
425
                        if (iter.next() != null) {
426
                                count++;
427
                        }
428
                }
429
                return count;
430
        }
431

    
432
        public boolean closeResourceRequested(ResourceProvider resource) {
433
                try {
434
                        checksResulsets();
435
                        return openResulsetCount() == 0 && closeResource(resource);
436
                } catch (DataException e) {
437
                        logger.error("Exception throws", e);
438
                        return false;
439
                }
440
        }
441

    
442

    
443
        protected String fixFilter(String filter) {
444
                if (filter == null) {
445
                        return null;
446
                }
447

    
448
                return filter;
449
        }
450

    
451
        public void init(JDBCStoreParameters params) throws InitializeException {
452
                this.params = params;
453
                helper = createHelper();
454
                if (params.getSQL() != null && (params.getSQL()).trim().length() > 0) {
455
                        directSQLMode = true;
456
                }
457

    
458
                this.metadata = (DelegatedDynObject) ToolsLocator
459
                                .getDynObjectManager().createDynObject(DYNCLASS);
460

    
461
                this.metadata.setDynValue("DefaultSRS", null);
462
                this.metadata.setDynValue("Envelope", null);
463

    
464
        }
465

    
466
        protected JDBCHelper createHelper() throws InitializeException {
467
                return new JDBCHelper(this, params);
468
        }
469

    
470
        protected JDBCHelper getHelper() {
471
                return helper;
472
        }
473

    
474
        protected void resetCount() {
475
                totalCount = null;
476
        }
477

    
478
        /**
479
         * Get feature count for a <code>filter</code>.<br>
480
         *
481
         * <code>filter</code> can be <code>null</code>.<br>
482
         *
483
         * <strong>Note:</strong><br>
484
         * this method have to perform <code>resouceBegin</code> at the begining and
485
         * <code>resourceEnd</code> at the end of execution.
486
         *
487
         *
488
         * @param filter
489
         * @return
490
         * @throws DataException
491
         */
492
        protected long getCount(String filter) throws DataException {
493
                this.open();
494
                if (filter == null && totalCount != null) {
495
                        return totalCount.longValue();
496
                }
497
                long count = 0;
498
                String sql = compoundCountSelect(filter);
499
                resourceBegin();
500
                try {
501
                        ResultSet rs = createNewResultSet(sql, null);
502
                        try {
503
                                if (rs.next()) {
504
                                        count = rs.getLong(1);
505
                                }
506
                        } catch (SQLException e) {
507
                                throw new JDBCSQLException(e);
508
                        } finally {
509
                                closeResulset(rs);
510
                        }
511
                } finally {
512
                        resourceEnd();
513
                }
514
                if (filter == null) {
515
                        totalCount = new Long(count);
516
                }
517
                return count;
518
        }
519

    
520
        public void close() throws CloseException {
521
                helper.close();
522
        }
523

    
524
        public void open() throws OpenException {
525
                helper.open();
526
        }
527

    
528

    
529
        public FeatureProvider getFeatureDataByReference(
530
                        FeatureReferenceProviderServices reference) throws DataException {
531
                return getFeatureDataByReference(reference, store
532
                                .getDefaultFeatureType());
533
        }
534

    
535
        public FeatureProvider getFeatureDataByReference(
536
                        FeatureReferenceProviderServices reference, FeatureType featureType)
537
                        throws DataException {
538
                open();
539
                resourceBegin();
540
                try {
541
                        StringBuilder filter = new StringBuilder();
542
                        FeatureAttributeDescriptor[] pk = store.getFeatureType(
543
                                        featureType.getId()).getPrimaryKey();
544

    
545
                        List values = new ArrayList();
546

    
547
                        int i;
548
                        for (i = 0; i < pk.length - 1; i++) {
549
                                values.add(helper.dalValueToJDBC(pk[i], reference
550
                                                .getKeyValue(pk[i].getName())));
551
                                filter.append(helper.getSqlFieldName(pk[i]));
552
                                filter.append(" = ? AND ");
553
                        }
554
                        values.add(helper.dalValueToJDBC(pk[i], reference.getKeyValue(pk[i]
555
                                        .getName())));
556
                        filter.append(helper.getSqlFieldName(pk[i]));
557
                        filter.append(" = ? ");
558

    
559
                        String sql = compoundSelect(featureType, filter.toString(), null,
560
                                        1, 0);
561

    
562
                        FeatureProvider data;
563
                        int rsId = createResultSet(sql, values.toArray());
564
                        try {
565
                                if (!resulsetNext(rsId)) {
566
                                        // FIXME Exception
567
                                        throw new RuntimeException("Reference Not found");
568
                                }
569
                                data = createFeatureData(featureType);
570
                                loadFeatureData(data, rsId);
571
                        } finally {
572
                                closeResulset(rsId);
573
                        }
574

    
575
                        return data;
576

    
577
                } finally {
578
                        resourceEnd();
579
                }
580

    
581
        }
582

    
583
        public int getOIDType() {
584
                return DataTypes.UNKNOWN;
585
        }
586

    
587
        protected void initFeatureType() throws InitializeException {
588

    
589
                EditableFeatureType edFType = null;
590
                try {
591
                        edFType = this.store.createFeatureType();
592

    
593
                        helper.loadFeatureType(edFType, params);
594

    
595
                } catch (DataException e) {
596
                        throw new InitializeException(this.getName(), e);
597
                }
598

    
599
                FeatureType defaultType = edFType.getNotEditableCopy();
600
                List types = new ArrayList(1);
601
                types.add(defaultType);
602
                this.store.setFeatureTypes(types, defaultType);
603
                try {
604
                        loadMetadata();
605
                } catch (DataException e) {
606
                        throw new InitializeException(e);
607
                }
608
        }
609

    
610
        protected ResultSet createNewResultSet(String sql, Object[] values)
611
                        throws DataException {
612
                this.open();
613
                Connection conn = null;
614
                PreparedStatement st = null;
615
                ResultSet rs = null;
616
                this.resourceBegin();
617
                try {
618
                        conn = this.helper.getConnection();
619
                        st = conn.prepareStatement(sql);
620

    
621
                        if (values != null) {
622
                                Object value;
623
                                for (int i = 0; i < values.length; i++) {
624
                                        value = values[i];
625
                                        if (value instanceof Geometry) {
626
                                                byte[] bytes;
627
                                                try {
628
                                                        bytes = (byte[]) ((Geometry) value)
629
                                                                        .invokeOperation(ToWKB.CODE, null);
630
                                                } catch (BaseException e) {
631
                                                        // FIXME
632
                                                        throw new InvalidParameterException();
633
                                                }
634
                                                st.setBytes(i + 1, bytes);
635
                                        }
636
                                        st.setObject(i + 1, value);
637
                                }
638

    
639
                        }
640

    
641
                        try {
642
                                rs = st.executeQuery();
643
                        } catch (SQLException e1) {
644
                                try {st.close();} catch (Exception e2) {};
645
                                try {conn.close();} catch (Exception e2) {}        ;
646
                                throw new JDBCExecuteSQLException(sql, e1);
647
                        }
648
                        rs.setFetchSize(5000); // TODO add to params?
649
                        return rs;
650
                } catch (SQLException e) {
651
                        // TODO throw exception ???
652
                        try {rs.close();} catch (Exception e1) {};
653
                        try {st.close();} catch (Exception e1) {};
654
                        try {conn.close();} catch (Exception e1) {};
655
                        throw new JDBCSQLException(e);
656
                } finally {
657
                        this.resourceEnd();
658
                }
659
        }
660

    
661
        /**
662
         * Permform a {@link Resource#begin()} to the current provider resources.
663
         *
664
         */
665

    
666
        protected void resourceBegin() throws ResourceBeginException {
667
                this.helper.begin();
668

    
669
        }
670

    
671
        /**
672
         * Permform a {@link Resource#end()} to the current provider resources.
673
         */
674

    
675
        protected void resourceEnd() {
676
                this.helper.end();
677
        }
678

    
679
        protected boolean closeResource(ResourceProvider resource) {
680
                try {
681
                        this.helper.close();
682
                } catch (CloseException e) {
683
                        logger.error("Exception in close Request", e);
684
                }
685
                return !this.helper.isOpen();
686
        }
687

    
688
        protected String compoundCountSelect(String filter) {
689
                if (this.directSQLMode) {
690
                        return null;
691
                }
692
                // Select
693
                StringBuilder sql = new StringBuilder();
694
                sql.append("Select count(");
695
                String[] pkFields = params.getPkFields();
696
                if (pkFields != null && pkFields.length == 1) {
697
                        sql.append(helper.escapeFieldName(pkFields[0]));
698
                } else {
699
                        sql.append('*');
700

    
701
                }
702
                sql.append(") ");
703

    
704
                sql.append("from ");
705

    
706
                sql.append(params.tableID());
707
                sql.append(' ');
708

    
709
                appendWhere(sql, filter);
710

    
711
                return sql.toString();
712
        }
713

    
714
        protected void appendWhere(StringBuilder sql, String filter) {
715
                filter = fixFilter(filter);
716
                String initialFilter = params.getInitialFilter();
717
                if ((initialFilter != null && initialFilter.length() != 0)
718
                                || (filter != null && filter.length() != 0)) {
719
                        sql.append("where (");
720

    
721
                        if (initialFilter != null && initialFilter.length() != 0
722
                                        && filter != null && filter.length() != 0) {
723
                                // initialFilter + filter
724
                                sql.append('(');
725
                                sql.append(initialFilter);
726
                                sql.append(") and (");
727
                                sql.append(filter);
728
                                sql.append(')');
729
                        } else if (initialFilter != null && initialFilter.length() != 0) {
730
                                // initialFilter only
731
                                sql.append(initialFilter);
732
                        } else {
733
                                // filter only
734
                                sql.append(filter);
735
                        }
736
                        sql.append(") ");
737
                }
738
        }
739

    
740
        protected void loadMetadata() throws DataException {
741
                IProjection srs = params.getSRS();
742

    
743
                if (srs == null) {
744
                        srs = store.getDefaultFeatureType().getDefaultSRS();
745
                }
746

    
747
                this.metadata.setDynValue("DefaultSRS", srs);
748

    
749
                String defGeomName = this.store.getDefaultFeatureType()
750
                                .getDefaultGeometryAttributeName();
751
                Envelope env = null;
752
                if (defGeomName != null && defGeomName.length() > 0) {
753
                        env = this.helper.getFullEnvelopeOfField(this.params, defGeomName,
754
                                        this.params.getWorkingArea());
755

    
756
                }
757
                this.metadata.setDynValue("Envelope", env);
758

    
759
        }
760

    
761
        public void closeDone() throws DataException {
762
                clearMetadata();
763

    
764
        }
765

    
766
        public void opendDone() throws DataException {
767
                // Nothing to do
768
        }
769

    
770
        public Envelope getEnvelope() throws DataException {
771
                this.open();
772
                return (Envelope) this.metadata.getDynValue("Envelope");
773
        }
774

    
775
        public void resourceChanged(ResourceProvider resource) {
776
                this.store.notifyChange(DataStoreNotification.RESOURCE_CHANGED,
777
                                resource);
778
        }
779

    
780
        protected void clearMetadata() {
781
                this.metadata.setDynValue("DefaultSRS", null);
782
                this.metadata.setDynValue("Envelope", null);
783
        }
784

    
785
        public boolean allowAutomaticValues() {
786
                return this.helper.allowAutomaticValues();
787
        }
788

    
789
        public DataServerExplorer getExplorer() throws ReadException {
790
                DataManager manager = DALLocator.getDataManager();
791
                JDBCServerExplorerParameters exParams;
792
                try {
793
                        exParams = (JDBCServerExplorerParameters) manager
794
                                        .createServerExplorerParameters(JDBCServerExplorer.NAME);
795
                        exParams.setHost(params.getHost());
796
                        exParams.setPort(params.getPort());
797
                        exParams.setDBName(params.getDBName());
798
                        exParams.setUser(params.getUser());
799
                        exParams.setPassword(params.getPassword());
800
                        exParams.setUrl(params.getUrl());
801
                        exParams.setCatalog(params.getCatalog());
802
                        exParams.setSchema(params.getSchema());
803
                        exParams.setJDBCDriverClassName(params.getJDBCDriverClassName());
804

    
805
                        return manager.createServerExplorer(exParams);
806
                } catch (DataException e) {
807
                        throw new ReadException(this.getName(), e);
808
                } catch (ValidateDataParametersException e) {
809
                        // TODO Auto-generated catch block
810
                        throw new ReadException(this.getName(), e);
811
                }
812
        }
813

    
814
        public void dispose() throws CloseException {
815
                this.close();
816
                resulsetList = null;
817
                this.helper.dispose();
818
                super.dispose();
819
        }
820

    
821
        public FeatureStoreProvider initialize(FeatureStoreProviderServices store)
822
                        throws InitializeException {
823
                super.initialize(store);
824
                this.initFeatureType();
825
                return this;
826
        }
827

    
828
        public Object createNewOID() {
829
                return null;
830
        }
831

    
832
        public String compoundSelect(FeatureType type, String filter, String order,
833
                        long limit, long offset) throws DataException {
834
                StringBuilder sql = new StringBuilder();
835
                if (directSQLMode) {
836
                        if (filter != null || order != null) {
837
                                // FIXME Exception
838
                                throw new UnsupportedOperationException();
839
                        }
840
                        sql.append(params.getSQL());
841
                        sql.append(' ');
842
                } else {
843
                        FeatureAttributeDescriptor[] fields = type
844
                                        .getAttributeDescriptors();
845

    
846
                        // Select
847
                        sql.append("Select ");
848
                        for (int i = 0; i < fields.length - 1; i++) {
849
                                sql.append(helper.getSqlFieldName(fields[i]));
850
                                sql.append(", ");
851
                        }
852
                        sql.append(helper.getSqlFieldName(fields[fields.length - 1]));
853
                        sql.append(' ');
854

    
855
                        FeatureAttributeDescriptor[] pkFields = store
856
                                        .getProviderFeatureType(type.getId()).getPrimaryKey();
857

    
858
                        if (pkFields != null && pkFields.length > 0) {
859
                                // checks for pk fields are in select
860
                                boolean toAdd;
861
                                for (int i = 0; i < pkFields.length; i++) {
862
                                        toAdd = true;
863
                                        for (int j = 0; j < fields.length; j++) {
864
                                                if (pkFields[i].getName().equals(fields[j].getName())) {
865
                                                        toAdd = false;
866
                                                        break;
867
                                                }
868
                                                if (toAdd) {
869
                                                        sql.append(", ");
870
                                                        sql.append(helper.getSqlFieldName(pkFields[i]));
871
                                                }
872
                                        }
873
                                }
874
                                sql.append(' ');
875
                        }
876

    
877
                        // table
878
                        sql.append("from ");
879
                        sql.append(params.tableID());
880
                        sql.append(' ');
881

    
882
                        // Where
883
                        appendWhere(sql, filter);
884

    
885
                        // Order
886
                        if ((params.getInitialOrder() != null && params.getInitialOrder()
887
                                        .length() != 0)
888
                                        || (order != null && order.length() != 0)) {
889
                                sql.append("order by ");
890

    
891
                                if (order != null && order.length() != 0) {
892
                                        // order
893
                                        sql.append(order);
894
                                } else {
895
                                        // initial order
896
                                        sql.append(params.getInitialOrder());
897
                                }
898
                                sql.append(' ');
899
                        }
900
                }
901
                // limit offset
902
                if (limit >= 1 || offset >= 1) {
903
                        sql.append(helper.compoundLimitAndOffset(limit,offset));
904
                }
905
                return sql.toString();
906
        }
907

    
908
        public long getFeatureCount() throws DataException {
909
                return getCount(null);
910
        }
911

    
912
        public String getName() {
913
                return NAME;
914
        }
915

    
916
        public Iterator getChilds() {
917
                return null;
918
        }
919

    
920
        public boolean hasGeometrySupport() {
921
                return false;
922
        }
923

    
924
        public FeatureSetProvider createSet(FeatureQuery query,
925
                        FeatureType featureType) throws DataException {
926

    
927
                return new JDBCSetProvider(this, query, featureType);
928
        }
929

    
930
        public Object getSourceId() {
931
                return this.params.getSourceId();
932
        }
933

    
934
}