Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.compat.cdc / org.gvsig.fmap.dal / org.gvsig.fmap.dal.db / org.gvsig.fmap.dal.db.jdbc / src / main / java / org / gvsig / fmap / dal / store / jdbc / JDBCSetProvider.java @ 40559

History | View | Annotate | Download (11.4 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
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 3
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
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
/* gvSIG. Geographic Information System of the Valencian Government
25
*
26
* Copyright (C) 2007-2008 Infrastructures and Transports Department
27
* of the Valencian Government (CIT)
28
*
29
* This program is free software; you can redistribute it and/or
30
* modify it under the terms of the GNU General Public License
31
* as published by the Free Software Foundation; either version 2
32
* of the License, or (at your option) any later version.
33
*
34
* This program is distributed in the hope that it will be useful,
35
* but WITHOUT ANY WARRANTY; without even the implied warranty of
36
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
37
* GNU General Public License for more details.
38
*
39
* You should have received a copy of the GNU General Public License
40
* along with this program; if not, write to the Free Software
41
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
42
* MA  02110-1301, USA.
43
*
44
*/
45

    
46
/*
47
* AUTHORS (In addition to CIT):
48
* 2009 IVER T.I   {{Task}}
49
*/
50

    
51
/**
52
 *
53
 */
54
package org.gvsig.fmap.dal.store.jdbc;
55

    
56
import java.util.ArrayList;
57
import java.util.Arrays;
58
import java.util.Iterator;
59
import java.util.List;
60
import java.util.NoSuchElementException;
61

    
62
import org.gvsig.fmap.dal.DataTypes;
63
import org.gvsig.fmap.dal.exception.DataException;
64
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
65
import org.gvsig.fmap.dal.feature.FeatureQuery;
66
import org.gvsig.fmap.dal.feature.FeatureQueryOrder;
67
import org.gvsig.fmap.dal.feature.FeatureType;
68
import org.gvsig.fmap.dal.feature.FeatureQueryOrder.FeatureQueryOrderMember;
69
import org.gvsig.fmap.dal.feature.spi.AbstractFeatureSetProvider;
70
import org.gvsig.tools.evaluator.Evaluator;
71
import org.gvsig.tools.evaluator.EvaluatorFieldValue;
72
import org.gvsig.tools.evaluator.EvaluatorFieldsInfo;
73
import org.gvsig.tools.exception.BaseException;
74
import org.slf4j.Logger;
75
import org.slf4j.LoggerFactory;
76

    
77
/**
78
 * @author jmvivo
79
 *
80
 */
81
public class JDBCSetProvider extends AbstractFeatureSetProvider {
82

    
83
        final static private Logger logger = LoggerFactory
84
                        .getLogger(JDBCSetProvider.class);
85

    
86
        protected String filter;
87
        protected String order;
88
        protected Long size = null;
89
        protected Boolean isEmpty = null;
90

    
91
        protected List resultSetIDReferenced;
92

    
93
        private JDBCHelper helper = null;
94

    
95
        private int defaultFetchSize = 1000;
96

    
97
        private long limit = -1l;
98

    
99
    private boolean directSQLMode;
100

    
101
        public JDBCSetProvider(JDBCStoreProvider store, FeatureQuery query,
102
                        FeatureType featureType) throws DataException {
103
                super(store, query, featureType);
104
                this.helper = store.getHelper();
105
                this.resultSetIDReferenced = new ArrayList();
106
                this.directSQLMode =  store.isDirectSQLMode();
107
        
108
                if (query.hasFilter() && this.canFilter()) {
109
                        setFilter(query.getFilter());
110
                } else {
111
                        setFilter(null);
112
                }
113

    
114
                if (query.hasOrder() && canOrder()) {
115
                        setOrder(query.getOrder());
116
                } else {
117
                        setOrder(null);
118
                }
119

    
120
                if (query != null) {
121
                        limit = query.getLimit();
122
                }
123
        }
124

    
125
        /**
126
         * @return the defaultFetchSize
127
         */
128
        public int getDefaultFetchSize() {
129
                return defaultFetchSize;
130
        }
131

    
132
        /**
133
         * @param defaultFetchSize
134
         *            the defaultFetchSize to set
135
         */
136
        public void setDefaultFetchSize(int defaultFetchSize) {
137
                this.defaultFetchSize = defaultFetchSize;
138
        }
139

    
140
        protected String getSqlForEvaluator(Evaluator filter) {
141
                if (filter == null) {
142
                        return null;
143
                }
144
                EvaluatorFieldsInfo info = filter.getFieldsInfo();
145
                String filterString = filter.getSQL();
146
                if (info == null) {
147
                        return filterString;
148
                }
149
                String[] filterNames = info.getFieldNames();
150
                String[] finalNames = new String[filterNames.length];
151
                EvaluatorFieldValue[] fValues;
152

    
153
                List values = new ArrayList();
154

    
155
                FeatureAttributeDescriptor attr;
156
                for (int i = 0; i < filterNames.length; i++) {
157
                        attr = getFeatureType().getAttributeDescriptor(filterNames[i]);
158
                        if (attr == null) {
159
                                finalNames[i] = filterNames[i];
160
                                continue;
161
                        }
162
                        finalNames[i] = getEscapedFieldName(attr.getName());
163

    
164
                }
165

    
166
                for (int i = 0; i < filterNames.length; i++) {
167
                        if (!filterNames[i].equals(finalNames[i])) {
168
                                filterString.replaceAll("\\b" + filterNames[i] + "\\b",
169
                                                finalNames[i]);
170
                        }
171
                }
172

    
173
                return filterString;
174
        }
175

    
176

    
177
        protected String getEscapedFieldName(String fieldName) {
178
                if (helper == null) {
179
                        helper = getJDBCStoreProvider().getHelper();
180
                }
181
                return helper.escapeFieldName(fieldName);
182
        }
183

    
184

    
185
        protected void setOrder(FeatureQueryOrder order) {
186
                if (order == null || order.size() == 0) {
187
                        this.order = null;
188
                        return;
189
                }
190

    
191
                StringBuilder buffer = new StringBuilder();
192
                Iterator iter = order.iterator();
193
                FeatureQueryOrderMember menber;
194
                while (true) {
195
                        menber = (FeatureQueryOrderMember) iter.next();
196
                        if (menber.hasEvaluator()) {
197
                                buffer.append(getSqlForEvaluator(menber.getEvaluator()));
198
                        } else {
199
                                buffer.append(getEscapedFieldName(menber.getAttributeName()));
200
                        }
201
                        if (menber.getAscending()) {
202
                                buffer.append(" ASC");
203
                        } else {
204
                                buffer.append(" DESC");
205
                        }
206
                        if (iter.hasNext()) {
207
                                buffer.append(", ");
208
                        } else {
209
                                buffer.append(' ');
210
                                break;
211
                        }
212
                }
213

    
214
                this.order = buffer.toString();
215
        }
216

    
217
        protected void setFilter(Evaluator filter) {
218
                this.filter = getSqlForEvaluator(filter);
219
        }
220

    
221

    
222

    
223
        /* (non-Javadoc)
224
         * @see org.gvsig.fmap.dal.feature.spi.FeatureSetProvider#canFilter()
225
         */
226
        public boolean canFilter() {
227
                Evaluator filter = getQuery().getFilter();
228
                if (directSQLMode){
229
                    return false;
230
                }
231
                if (filter != null) {
232
                        if (filter.getSQL() == null || filter.getSQL().length() == 0) {
233
                                return false;
234
                        } else {
235
                                // TODO Check Geom fields if
236
                                EvaluatorFieldsInfo fInfo = filter.getFieldsInfo();
237
                                if (fInfo == null || fInfo.getFieldNames() == null) {
238
                                        return true;
239
                                }
240
                                Iterator names = Arrays.asList(fInfo.getFieldNames())
241
                                                .iterator();
242
                                String name;
243
                                int type;
244
                                while (names.hasNext()) {
245
                                        name = (String) names.next();
246
                                        type =
247
                                                        this.getFeatureType()
248
                                                                        .getAttributeDescriptor(name)
249
                                                        .getType();
250
                                        if (type == DataTypes.GEOMETRY
251
                                                        && !this.helper.supportsGeometry()) {
252
                                                return false;
253
                                        }
254

    
255

    
256

    
257
                                }
258

    
259
                                return true;
260
                        }
261

    
262
                } else{
263
                        return false;
264
                }
265
        }
266

    
267
        /* (non-Javadoc)
268
         * @see org.gvsig.fmap.dal.feature.spi.FeatureSetProvider#canIterateFromIndex()
269
         */
270
        public boolean canIterateFromIndex() {
271
                return helper.supportOffset();
272
        }
273

    
274
        /* (non-Javadoc)
275
         * @see org.gvsig.fmap.dal.feature.spi.FeatureSetProvider#canOrder()
276
         */
277
        public boolean canOrder() {
278
            if (directSQLMode){
279
                return false;
280
            }
281
                // TODO Check Geom fields if postgis not are available
282
                FeatureQuery query = getQuery();
283
                if (query.hasOrder()) {
284
                        Iterator iter = query.getOrder().iterator();
285
                        FeatureQueryOrderMember menber;
286
                        String sql;
287
                        while (iter.hasNext()){
288
                                menber = (FeatureQueryOrderMember) iter.next();
289
                                if (menber.hasEvaluator()){
290
                                        sql = menber.getEvaluator().getSQL();
291
                                        if (sql == null || sql.length() == 0) {
292
                                                return false;
293
                                        }
294
                                }
295
                        }
296
                }
297
                return true;
298
        }
299

    
300
        private JDBCStoreProvider getJDBCStoreProvider() {
301
                return (JDBCStoreProvider) getStore();
302
        }
303

    
304
        @Override
305
        protected void doDispose() throws BaseException {
306
                if (resultSetIDReferenced != null) {
307
                        Iterator iter = resultSetIDReferenced.iterator();
308
                        Integer resID;
309
                        while (iter.hasNext()) {
310
                                resID = (Integer) iter.next();
311
                                if (resID != null) {
312
                                        logger.warn(
313
                                                "ResultSet (ID {}) not closed on dispose, will close",
314
                                                resID);
315
                                        try {
316
                                                getJDBCStoreProvider().closeResulset(resID.intValue());
317
                                        } catch (DataException e) {
318
                                                logger.error("Close resulset Exception", e);
319
                                        }
320
                                }
321
                                iter.remove();
322
                        }
323
                }
324
                resultSetIDReferenced = null;
325
                filter = null;
326
                order = null;
327
                size = null;
328
                isEmpty = null;
329
        }
330

    
331
        protected String getSQL(long fromIndex) throws DataException {
332
                return getJDBCStoreProvider().compoundSelect(getFeatureType(), filter,
333
                                order, limit, fromIndex);
334

    
335
        }
336

    
337
        /* (non-Javadoc)
338
         * @see org.gvsig.fmap.dal.feature.spi.FeatureSetProvider#getSize()
339
         */
340
        public long getSize() throws DataException {
341
                if (size == null) {
342
                        size = new Long(getJDBCStoreProvider().getCount(filter));
343
                }
344
                return size.longValue();
345
        }
346

    
347
        /* (non-Javadoc)
348
         * @see org.gvsig.fmap.dal.feature.spi.FeatureSetProvider#isEmpty()
349
         */
350
        public boolean isEmpty() throws DataException {
351
                JDBCStoreProvider store = getJDBCStoreProvider();
352
                if (isEmpty == null) {
353
                        if (size == null) {
354
                                String sql =
355
                                                store.compoundSelect(getFeatureType(), filter, null, 1,
356
                                                                0);
357
                                int rsID = store.createResultSet(sql, getFetchSize());
358
                                isEmpty = new Boolean(!store.resulsetNext(rsID));
359
                                store.closeResulset(rsID);
360
                        } else {
361
                                isEmpty = new Boolean(size.longValue() < 1);
362
                        }
363
                }
364
                return isEmpty.booleanValue();
365
        }
366

    
367
        protected int getFetchSize() {
368
                long pageSize = -1;
369
                if (getQuery() != null) {
370
                        pageSize = getQuery().getPageSize();
371
                        pageSize =
372
                                        pageSize > Integer.MAX_VALUE ? Integer.MAX_VALUE : pageSize;
373
                }
374
                return (pageSize > 0 ? (int) pageSize : defaultFetchSize);
375
        }
376

    
377
        protected JDBCIterator createFastIterator(long index) throws DataException {
378
                if (isEmpty != null && isEmpty.booleanValue()) {
379
                        return new EmptyJDBCIterator(getJDBCStoreProvider());
380
                }
381
                int rsID =
382
                                getJDBCStoreProvider().createResultSet(getSQL(index),
383
                                                getFetchSize());
384
                return createDefaultFastIterator(rsID);
385
        }
386

    
387
        protected JDBCIterator createDefaultFastIterator(int resultSetID)
388
                        throws DataException {
389
                return new JDBCFastIterator(getJDBCStoreProvider(), this,
390
                                getFeatureType(), resultSetID);
391
        }
392

    
393
        protected JDBCIterator createIterator(long index) throws DataException {
394
        if (isEmpty != null && isEmpty.booleanValue()) {
395
            return new EmptyJDBCIterator(getJDBCStoreProvider());
396
        }
397
        int rsID =
398
                getJDBCStoreProvider().createResultSet(getSQL(index),
399
                        getFetchSize());
400
        return createDefaultIterator(rsID);
401
        }
402

    
403
        protected JDBCIterator createDefaultIterator(int resultSetID)
404
                        throws DataException {
405
                return new JDBCIterator(getJDBCStoreProvider(), this, getFeatureType(),
406
                                resultSetID);
407
        }
408

    
409
        public void addResulsetReference(int resulsetID) {
410
                this.resultSetIDReferenced.add(new Integer(resulsetID));
411
        }
412

    
413
        public void removeResulsetReference(int resulsetID) {
414
                this.resultSetIDReferenced.remove(new Integer(resulsetID));
415
        }
416

    
417
        private class EmptyJDBCIterator extends JDBCIterator {
418

    
419
                protected EmptyJDBCIterator(JDBCStoreProvider store) throws DataException {
420
                        super(store, null, null, -1);
421
                }
422

    
423
                @Override
424
                protected boolean internalHasNext() {
425
                        return false;
426
                }
427

    
428
                @Override
429
                protected Object internalNext() {
430
                        throw new NoSuchElementException();
431
                }
432

    
433
                @Override
434
                protected void doDispose() throws BaseException {
435
                        // nothing to do
436
                }
437

    
438
        }
439

    
440
}