Statistics
| Revision:

root / trunk / org.gvsig.postgresql / org.gvsig.postgresql.provider / src / main / java / org / gvsig / fmap / dal / store / postgresql / PostgreSQLStoreProvider.java @ 46

History | View | Annotate | Download (12.5 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
package org.gvsig.fmap.dal.store.postgresql;
29

    
30
import java.sql.DatabaseMetaData;
31
import java.sql.ResultSet;
32
import java.sql.SQLException;
33
import java.sql.Statement;
34
import java.util.Iterator;
35
import java.util.List;
36
import java.util.Properties;
37
import java.util.regex.Matcher;
38
import java.util.regex.Pattern;
39

    
40
import org.gvsig.fmap.dal.DALLocator;
41
import org.gvsig.fmap.dal.DataManager;
42
import org.gvsig.fmap.dal.DataServerExplorer;
43
import org.gvsig.fmap.dal.DataTypes;
44
import org.gvsig.fmap.dal.exception.DataException;
45
import org.gvsig.fmap.dal.exception.InitializeException;
46
import org.gvsig.fmap.dal.exception.ReadException;
47
import org.gvsig.fmap.dal.exception.ValidateDataParametersException;
48
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
49
import org.gvsig.fmap.dal.feature.FeatureQuery;
50
import org.gvsig.fmap.dal.feature.FeatureType;
51
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
52
import org.gvsig.fmap.dal.feature.spi.FeatureSetProvider;
53
import org.gvsig.fmap.dal.resource.exception.AccessResourceException;
54
import org.gvsig.fmap.dal.spi.DataStoreProviderServices;
55
import org.gvsig.fmap.dal.store.db.DBHelper;
56
import org.gvsig.fmap.dal.store.jdbc.JDBCHelper;
57
import org.gvsig.fmap.dal.store.jdbc.JDBCStoreProviderWriter;
58
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCExecuteSQLException;
59
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCSQLException;
60
import org.gvsig.fmap.geom.Geometry;
61
import org.slf4j.Logger;
62
import org.slf4j.LoggerFactory;
63

    
64
public class PostgreSQLStoreProvider extends JDBCStoreProviderWriter {
65

    
66
        public final static Logger logger = LoggerFactory
67
                        .getLogger(PostgreSQLStoreProvider.class);
68

    
69
        public static final String NAME = "PostgreSQL";
70
        public static final String DESCRIPTION = "PostgreSQL source";
71

    
72
        public static final String METADATA_DEFINITION_NAME = NAME;
73
        
74
        public PostgreSQLStoreProvider(PostgreSQLStoreParameters params,
75
                        DataStoreProviderServices storeServices)
76
                        throws InitializeException {
77
                super(params, storeServices, DBHelper.newMetadataContainer(METADATA_DEFINITION_NAME));
78
        }
79

    
80
        private PostgreSQLStoreParameters getPGParameters() {
81
                return (PostgreSQLStoreParameters) this.getParameters();
82
        }
83

    
84
        protected JDBCHelper createHelper() throws InitializeException {
85
            JDBCHelper resp = new PostgreSQLHelper(this, getPGParameters());
86
            
87
            return resp;
88
        }
89

    
90

    
91

    
92
        protected String fixFilter(String _filter) {
93
                if (_filter == null) {
94
                        return null;
95
                }
96
                
97
                String filter = fixFunctionNames(_filter);
98

    
99
                // Transform SRS to code
100
                // GeomFromText\s*\(\s*'[^']*'\s*,\s*('[^']*')\s*\)
101
                
102
                String geom_from_text = this.getFunctionName("ST_GeomFromText");
103
                Pattern pattern = Pattern
104
                                .compile(geom_from_text + "\\s*\\(\\s*'[^']*'\\s*,\\s*'([^']*)'\\s*\\)");
105
                Matcher matcher = pattern.matcher(filter);
106
                StringBuilder strb = new StringBuilder();
107
                int pos = 0;
108
                String srsCode;
109
                while (matcher.find(pos)) {
110
                        strb.append(filter.substring(pos, matcher.start(1)));
111
                        srsCode = matcher.group(1).trim();
112
                        if (srsCode.startsWith("'")) {
113
                                srsCode = srsCode.substring(1);
114
                        }
115
                        if (srsCode.endsWith("'")) {
116
                                srsCode = srsCode.substring(0, srsCode.length() - 1);
117
                        }
118
                        strb.append(helper.getProviderSRID(srsCode));
119
                        strb.append(filter.substring(matcher.end(1), matcher.end()));
120
                        pos = matcher.end();
121

    
122
                }
123
                strb.append(filter.substring(pos));
124

    
125
                return strb.toString();
126
        }
127

    
128

    
129
    public String getName() {
130
                return NAME;
131
        }
132

    
133
        public FeatureSetProvider createSet(FeatureQuery query,
134
                        FeatureType featureType) throws DataException {
135

    
136
                return new PostgreSQLSetProvider(this, query, featureType);
137
        }
138

    
139

    
140
        public DataServerExplorer getExplorer() throws ReadException {
141
                DataManager manager = DALLocator.getDataManager();
142
                PostgreSQLServerExplorerParameters exParams;
143
                PostgreSQLStoreParameters params = getPGParameters();
144
                try {
145
                        exParams = (PostgreSQLServerExplorerParameters) manager
146
                                        .createServerExplorerParameters(PostgreSQLServerExplorer.NAME);
147
                        exParams.setUrl(params.getUrl());
148
                        exParams.setHost(params.getHost());
149
                        exParams.setPort(params.getPort());
150
                        exParams.setDBName(params.getDBName());
151
                        exParams.setUser(params.getUser());
152
                        exParams.setPassword(params.getPassword());
153
                        exParams.setCatalog(params.getCatalog());
154
                        exParams.setSchema(params.getSchema());
155
                        exParams.setJDBCDriverClassName(params.getJDBCDriverClassName());
156
                        exParams.setUseSSL(params.getUseSSL());
157

    
158
                        return manager.openServerExplorer(PostgreSQLServerExplorer.NAME, exParams);
159
                } catch (DataException e) {
160
                        throw new ReadException(this.getName(), e);
161
                } catch (ValidateDataParametersException e) {
162
                        throw new ReadException(this.getName(), e);
163
                }
164
        }
165

    
166
        public boolean allowAutomaticValues() {
167
                return true;
168
        }
169

    
170

    
171
        public boolean hasGeometrySupport() {
172
                return true;
173
        }
174

    
175

    
176
        protected PostgreSQLHelper getPgHelper() {
177
                return (PostgreSQLHelper) getHelper();
178
        }
179

    
180

    
181

    
182
        public boolean canWriteGeometry(int geometryType, int geometrySubtype)
183
                        throws DataException {
184
                FeatureType type = getFeatureStore().getDefaultFeatureType();
185
                FeatureAttributeDescriptor geomAttr = type.getAttributeDescriptor(type
186
                                                                .getDefaultGeometryAttributeName());
187
                if (geomAttr == null) {
188
                        return false;
189
                }
190
                if (geometrySubtype != geomAttr.getGeometrySubType()) {
191
                        return false;
192
                }
193
                switch (geomAttr.getGeometryType()) {
194
                case Geometry.TYPES.GEOMETRY:
195
                        return true;
196

    
197
                case Geometry.TYPES.MULTISURFACE:
198
                        return geometryType == Geometry.TYPES.MULTISURFACE
199
                                        || geometryType == Geometry.TYPES.SURFACE;
200

    
201
                case Geometry.TYPES.MULTIPOINT:
202
                        return geometryType == Geometry.TYPES.MULTIPOINT
203
                                        || geometryType == Geometry.TYPES.POINT;
204

    
205
                case Geometry.TYPES.MULTICURVE:
206
                        return geometryType == Geometry.TYPES.MULTICURVE
207
                                        || geometryType == Geometry.TYPES.CURVE;
208

    
209
                case Geometry.TYPES.MULTISOLID:
210
                        return geometryType == Geometry.TYPES.MULTISOLID
211
                                        || geometryType == Geometry.TYPES.SOLID;
212

    
213
                default:
214
                        return geometryType == geomAttr.getGeometryType();
215
                }
216

    
217
        }
218

    
219

    
220
        protected void addToListFeatureValues(FeatureProvider featureProvider,
221
                        FeatureAttributeDescriptor attrOfList,
222
                        FeatureAttributeDescriptor attr,
223
                        List<Object> values) throws DataException {
224

    
225
                super.addToListFeatureValues(featureProvider, attrOfList, attr, values);
226
                if (attr.getType() == DataTypes.GEOMETRY) {
227
                        values.add(helper.getProviderSRID(attr.getSRS()));
228
                }
229
        }
230

    
231
        protected void prepareAttributeForInsert(
232
                        FeatureAttributeDescriptor attr, List<String> fields, List<String> values) {
233

    
234
                if (attr.getType() == DataTypes.GEOMETRY) {
235
                        fields.add(helper.escapeFieldName(attr.getName()));
236
                        values.add(getFunctionName("ST_GeomFromWKB") + "(?,?)");
237
                } else {
238
                        super.prepareAttributeForInsert(attr, fields, values);
239
                }
240

    
241
        }
242

    
243
        protected void prepareAttributeForUpdate(FeatureAttributeDescriptor attr,
244
                        List<String> values) {
245
                if (attr.getType() == DataTypes.GEOMETRY) {
246
                        values.add(helper.escapeFieldName(attr.getName())
247
                                        + " = " + getFunctionName("ST_GeomFromWKB") + "(?,?)");
248
                } else {
249
                        super.prepareAttributeForUpdate(attr, values);
250
                }
251
        }
252

    
253
        protected String getSqlStatementAddField(FeatureAttributeDescriptor attr,
254
                        List<String> additionalStatement) throws DataException {
255
                if (attr.getType() == DataTypes.GEOMETRY) {
256
                        PostgreSQLStoreParameters params = getPGParameters();
257
                        additionalStatement.addAll(        ((PostgreSQLHelper) helper)
258
                                        .getSqlGeometyFieldAdd(attr, params.getTable(), params
259
                                                        .getSchema()));
260

    
261
                }
262
                return super.getSqlStatementAddField(attr, additionalStatement);
263

    
264
        }
265
        private String getSqlGeometyFieldDrop(FeatureAttributeDescriptor attr) {
266
                StringBuilder strb = new StringBuilder();
267
                PostgreSQLStoreParameters params = getPGParameters();
268
                strb.append("Delete from geometry_columns where f_geometry_column = '");
269
                strb.append(attr.getName());
270
                strb.append("' and f_table_nam = '");
271
                strb.append(params.getTable());
272
                strb.append("' and f_table_schema = ");
273
                if (params.getSchema() == null || params.getSchema().length() == 0) {
274
                        strb.append("current_schema()");
275
                } else {
276
                        strb.append("'");
277
                        strb.append(params.getSchema());
278
                        strb.append("'");
279
                }
280
                if (params.getCatalog() != null && params.getCatalog().length() > 0) {
281
                        strb.append(" and f_table_catalog = '");
282
                        strb.append(params.getCatalog());
283
                        strb.append("'");
284
                }
285
                return strb.toString();
286
        }
287

    
288
        protected String getSqlStatementDropField(FeatureAttributeDescriptor attr,
289
                        List<String> additionalStatement) {
290
                String result = super.getSqlStatementDropField(attr,
291
                                additionalStatement);
292
                if (attr.getType() == DataTypes.GEOMETRY) {
293
                        additionalStatement.add(getSqlGeometyFieldDrop(attr));
294
                }
295
                return result;
296
        }
297

    
298
        protected List<String> getSqlStatementAlterField(
299
                        FeatureAttributeDescriptor attrOrg,
300
                        FeatureAttributeDescriptor attrTrg, List<String> additionalStatement)
301
                        throws DataException {
302
                //
303
                List<String> actions = super.getSqlStatementAlterField(attrOrg, attrTrg,
304
                                additionalStatement);
305
                PostgreSQLStoreParameters params = getPGParameters();
306
                if (attrOrg.getDataType() != attrTrg.getDataType()) {
307
                        if (attrOrg.getType() == DataTypes.GEOMETRY) {
308
                                additionalStatement.add(getSqlGeometyFieldDrop(attrOrg));
309
                        }
310
                        if (attrTrg.getType() == DataTypes.GEOMETRY) {
311
                                additionalStatement.addAll(((PostgreSQLHelper) helper)
312
                                                .getSqlGeometyFieldAdd(attrTrg, params.getTable(),
313
                                                                params.getSchema()));
314
                        }
315
                }
316
                if (attrOrg.getDataType() == attrTrg.getDataType()
317
                                && attrTrg.getType() == DataTypes.GEOMETRY) {
318
                        // TODO Checks SRS and GeomType/Subtype
319
                }
320

    
321
                return actions;
322
        }
323
        
324

    
325
        private String getFunctionName(String newFunctionName) {
326
        
327
        PostgreSQLHelper hpr = getPgHelper();
328
        if (hpr == null) {
329
            logger.info("Unable to get PG helper.", new Exception("Helper is null"));
330
            return newFunctionName;
331
        } else {
332
            return hpr.getFunctionName(newFunctionName);
333
        }
334
    }
335
        
336
    private String fixFunctionNames(String _filter) {
337
        
338
        Properties props = this.getPgHelper().getBeforePostgis13Properties();
339
        Iterator iter = props.keySet().iterator();
340
        String kstr = null;
341
        String vstr = null;
342
        
343
        String resp = _filter;
344
        
345
        while (iter.hasNext()) {
346
            kstr = (String) iter.next();
347
            vstr = getPgHelper().getFunctionName(kstr);
348
            resp = replace(resp, kstr, vstr);
349
        }
350
        return resp;
351
    }
352

    
353
    private String replace(String str, String oldstr, String newstr) {
354
        
355
        if (oldstr == null || newstr == null ||
356
            oldstr.length() == 0 || oldstr.equals(newstr)) {
357
            return str;
358
        }
359
        
360
        String lowerstr = str.toLowerCase();
361
        String lowerold = oldstr.toLowerCase();
362
        
363
        if (lowerstr.indexOf(lowerold) == -1) {
364
            // nothing to do
365
            return str;
366
        }
367
        
368
        Pattern p = Pattern.compile(lowerold, Pattern.LITERAL);
369
        String[] parts = p.split(lowerstr); 
370
        
371
        StringBuffer resp = new StringBuffer();
372
        int auxind = 0;
373
        resp.append(str.subSequence(0, parts[0].length()));
374
        for (int i=1; i<parts.length; i++) {
375
            resp.append(newstr);
376
            auxind = getIndex(parts, i-1, oldstr.length());
377
            resp.append(str.subSequence(auxind, auxind + parts[i].length()));
378
        }
379
        return resp.toString();
380
    }
381

    
382
    /**
383
     * This method gets the index where the n-th part (0-based)
384
     * starts in the original string
385
     * 
386
     * @param parts
387
     * @param n
388
     * @param length
389
     * @return
390
     */
391
    private int getIndex(String[] parts, int till_n, int length) {
392
        
393
        int resp = 0;
394
        for (int i=0; i<(till_n+1); i++) {
395
            resp = resp + parts[i].length();
396
            resp = resp + length;
397
        }
398
        return resp;
399
    }
400

    
401
    
402
}