Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.library / org.gvsig.exportto / org.gvsig.exportto.swing / org.gvsig.exportto.swing.prov / org.gvsig.exportto.swing.prov.jdbc / src / main / java / org / gvsig / exportto / swing / prov / jdbc / ExporrtoJDBCService.java @ 43420

History | View | Annotate | Download (16.9 KB)

1 40559 jjdelcerro
/**
2
 * gvSIG. Desktop Geographic Information System.
3 40435 jjdelcerro
 *
4 40559 jjdelcerro
 * Copyright (C) 2007-2013 gvSIG Association.
5 40435 jjdelcerro
 *
6 41486 jjdelcerro
 * This program is free software; you can redistribute it and/or modify it under
7
 * the terms of the GNU General Public License as published by the Free Software
8
 * Foundation; either version 3 of the License, or (at your option) any later
9
 * version.
10 40435 jjdelcerro
 *
11 41486 jjdelcerro
 * This program is distributed in the hope that it will be useful, but WITHOUT
12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14
 * details.
15 40435 jjdelcerro
 *
16 41486 jjdelcerro
 * You should have received a copy of the GNU General Public License along with
17
 * this program; if not, write to the Free Software Foundation, Inc., 51
18
 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 40435 jjdelcerro
 *
20 41486 jjdelcerro
 * For any additional information, do not hesitate to contact us at info AT
21
 * gvsig.com, or visit our website www.gvsig.com.
22 40435 jjdelcerro
 */
23
package org.gvsig.exportto.swing.prov.jdbc;
24
25 41598 jjdelcerro
import java.util.Map;
26
import org.apache.commons.lang3.StringUtils;
27 40435 jjdelcerro
import org.cresques.cts.ICoordTrans;
28
import org.cresques.cts.IProjection;
29
import org.gvsig.exportto.ExporttoService;
30
import org.gvsig.exportto.ExporttoServiceException;
31
import org.gvsig.exportto.ExporttoServiceFinishAction;
32
import org.gvsig.fmap.dal.DALLocator;
33
import org.gvsig.fmap.dal.DataManager;
34
import org.gvsig.fmap.dal.DataTypes;
35
import org.gvsig.fmap.dal.feature.EditableFeature;
36
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
37
import org.gvsig.fmap.dal.feature.EditableFeatureType;
38
import org.gvsig.fmap.dal.feature.Feature;
39 41127 jldominguez
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
40 40435 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureSet;
41
import org.gvsig.fmap.dal.feature.FeatureStore;
42
import org.gvsig.fmap.dal.feature.FeatureType;
43 41492 jjdelcerro
import org.gvsig.fmap.dal.store.jdbc.JDBCNewStoreParameters;
44 40435 jjdelcerro
import org.gvsig.fmap.dal.store.jdbc.JDBCServerExplorer;
45 40606 jldominguez
import org.gvsig.fmap.dal.store.jdbc.JDBCStoreParameters;
46 40435 jjdelcerro
import org.gvsig.fmap.geom.Geometry;
47
import org.gvsig.tools.dispose.DisposableIterator;
48
import org.gvsig.tools.task.AbstractMonitorableTask;
49 41488 jjdelcerro
import org.slf4j.Logger;
50
import org.slf4j.LoggerFactory;
51 40435 jjdelcerro
52
/**
53
 * @author gvSIG Team
54
 * @version $Id$
55 41486 jjdelcerro
 *
56 40435 jjdelcerro
 */
57
public class ExporrtoJDBCService extends AbstractMonitorableTask implements
58 41486 jjdelcerro
        ExporttoService {
59 40435 jjdelcerro
60 41488 jjdelcerro
    private static final Logger logger = LoggerFactory.getLogger(ExporrtoJDBCService.class);
61
62 41486 jjdelcerro
    public static final int CHECK_NONE = 0;
63
    public static final int CHECK_IF_CORRUPT = 1;
64
    public static final int CHECK_IF_VALID = 2;
65 40435 jjdelcerro
66 41486 jjdelcerro
    public static final int ACTION_SET_GEOMETRY_TO_NULL = 0;
67
    public static final int ACTION_SKIP_FEATURE = 1;
68
    public static final int ACTION_ABORT = 2;
69 40435 jjdelcerro
70
    private ExporttoServiceFinishAction exporttoServiceFinishAction = null;
71 41598 jjdelcerro
    private ExporttoJDBCOptions options;
72
//    private Map<String,String> translationIds;
73 40435 jjdelcerro
74 41598 jjdelcerro
    public ExporrtoJDBCService(ExporttoJDBCOptions options) {
75
        this.options = options;
76 40435 jjdelcerro
    }
77
78 41598 jjdelcerro
    protected String getTranslatedIdentifier(String identifier) {
79
        String s = identifier;
80 41681 jjdelcerro
        if (this.options.getTranslateIdentifiersToLowerCase()) {
81 41598 jjdelcerro
            s = s.toLowerCase();
82
        }
83 43377 jjdelcerro
        if( this.options.getTranslateHyphens()) {
84
            s = s.replace("-", "_");
85
        }
86 41681 jjdelcerro
        if (this.options.getRemoveSpacesInIdentifiers()) {
87 41598 jjdelcerro
            s = StringUtils.normalizeSpace(s).replace(" ", "_");
88
        }
89
        return s;
90
    }
91 41681 jjdelcerro
92 41486 jjdelcerro
    protected void createTable(JDBCServerExplorer explorer) throws Exception {
93 40435 jjdelcerro
94 41488 jjdelcerro
        FeatureType targetFeatureType;
95
        EditableFeatureType targetEditableFeatureType;
96 40435 jjdelcerro
97 41598 jjdelcerro
        targetFeatureType = options.getSource().getDefaultFeatureType().getCopy();
98 41486 jjdelcerro
        targetEditableFeatureType = targetFeatureType.getEditable();
99 41681 jjdelcerro
100
        if (this.options.getTranslateIdentifiersToLowerCase()
101 43377 jjdelcerro
                || this.options.getRemoveSpacesInIdentifiers()
102
                || this.options.getTranslateHyphens()) {
103 41681 jjdelcerro
            for (int i = 0; i < targetEditableFeatureType.size(); i++) {
104
                EditableFeatureAttributeDescriptor x = (EditableFeatureAttributeDescriptor) targetEditableFeatureType.get(i);
105 41598 jjdelcerro
                x.setName(getTranslatedIdentifier(x.getName()));
106
            }
107
        }
108 41681 jjdelcerro
109 41598 jjdelcerro
        if (this.options.getPrimaryKey() != null) {
110
            EditableFeatureAttributeDescriptor pk = (EditableFeatureAttributeDescriptor) targetEditableFeatureType.get(getTranslatedIdentifier(options.getPrimaryKey()));
111 41488 jjdelcerro
            if (pk == null) {
112 41598 jjdelcerro
                pk = targetEditableFeatureType.add(
113 41681 jjdelcerro
                        getTranslatedIdentifier(this.options.getPrimaryKey()),
114 41598 jjdelcerro
                        DataTypes.LONG
115
                );
116 41488 jjdelcerro
                pk.setIsPrimaryKey(true);
117
                pk.setIsAutomatic(true);
118
            } else {
119
                pk.setIsPrimaryKey(true);
120
            }
121 41486 jjdelcerro
        }
122
123 41681 jjdelcerro
        if (this.options.getCreateIndexInGeometryRow()) {
124
            EditableFeatureAttributeDescriptor x = (EditableFeatureAttributeDescriptor) targetEditableFeatureType.getDefaultGeometryAttribute();
125 41638 jjdelcerro
            x.setIsIndexed(true);
126
        }
127 41681 jjdelcerro
128 41486 jjdelcerro
        // ======================================================
129
        // Reprojection: set SRS of geometry field to target SRS
130
        EditableFeatureAttributeDescriptor attrdescriptor
131
                = (EditableFeatureAttributeDescriptor) targetEditableFeatureType.getDefaultGeometryAttribute();
132
        if (attrdescriptor != null) {
133 41598 jjdelcerro
            attrdescriptor.setSRS(this.options.getTargetProjection());
134 41486 jjdelcerro
        }
135
136
        // ======================================
137 41492 jjdelcerro
        JDBCNewStoreParameters createTableParams = (JDBCNewStoreParameters) explorer.getAddParameters();
138 41486 jjdelcerro
139 41655 jjdelcerro
        createTableParams.setSelectRole(this.options.getSelectRole());
140
        createTableParams.setInsertRole(this.options.getInsertRole());
141
        createTableParams.setUpdateRole(this.options.getUpdateRole());
142
        createTableParams.setDeleteRole(this.options.getDeleteRole());
143
        createTableParams.setTruncateRole(this.options.getTruncateRole());
144
        createTableParams.setReferenceRole(this.options.getReferenceRole());
145
        createTableParams.setTriggerRole(this.options.getTriggerRole());
146
        createTableParams.setAllRole(this.options.getAllRole());
147 41681 jjdelcerro
148 41655 jjdelcerro
        createTableParams.setSchema(this.options.getSchema());
149
        createTableParams.setPostCreatingStatement(this.options.getPostCreatingStatement());
150 41681 jjdelcerro
151 41486 jjdelcerro
        createTableParams.setDefaultFeatureType(targetEditableFeatureType);
152 41681 jjdelcerro
        createTableParams.setTable(this.options.getTableName());
153 41486 jjdelcerro
        explorer.add(explorer.getStoreName(), createTableParams, true);
154
    }
155
156
    private static class InvalidGeometryException extends ExporttoServiceException {
157
158
        public InvalidGeometryException(Feature feature, String checkMessage) {
159
            super(checkMessage, null, checkMessage, 0);
160
            this.feature = feature;
161
        }
162
    }
163
164
    public void export(FeatureSet featureSet) throws ExporttoServiceException {
165
        Geometry.ValidationStatus geometryCheck;
166
167
        DisposableIterator it = null;
168
        EditableFeature targetFeature = null;
169 40435 jjdelcerro
        FeatureStore target = null;
170 41488 jjdelcerro
171 40435 jjdelcerro
        try {
172 41488 jjdelcerro
173 40435 jjdelcerro
            // ======================================
174 42708 fdiaz
            // Reprojection
175 41598 jjdelcerro
            FeatureAttributeDescriptor geo_att = this.options.getSource().getDefaultFeatureType().getDefaultGeometryAttribute();
176 41127 jldominguez
            IProjection sourceProjection = null;
177 40435 jjdelcerro
            ICoordTrans coord_trans = null;
178 41486 jjdelcerro
            Geometry reproj_geom = null;
179 42708 fdiaz
            IProjection targetProjection = this.options.getTargetProjection();
180 41127 jldominguez
            if (geo_att != null) {
181
                sourceProjection = geo_att.getSRS();
182
                // this comparison is perhaps too preventive
183
                // we could  have two instances of same projection
184
                // so we would do more computations than needed
185 42708 fdiaz
                if (sourceProjection != null && targetProjection != null && sourceProjection != targetProjection) {
186
                    coord_trans = sourceProjection.getCT(targetProjection);
187 41127 jldominguez
                }
188 40435 jjdelcerro
            }
189
            // ============================================
190
191 41486 jjdelcerro
            DataManager dataManager = DALLocator.getDataManager();
192 40435 jjdelcerro
193 41486 jjdelcerro
            JDBCServerExplorer explorer = (JDBCServerExplorer) dataManager.openServerExplorer(
194 41598 jjdelcerro
                    this.options.getExplorerParameters().getExplorerName(),
195
                    this.options.getExplorerParameters()
196 41486 jjdelcerro
            );
197
198 41681 jjdelcerro
            if (this.options.canCreatetable()) {
199 41880 jjdelcerro
                logger.debug("Creating table");
200 41654 jjdelcerro
                taskStatus.message("Creating table");
201 41486 jjdelcerro
                this.createTable(explorer);
202
            }
203
204
            JDBCStoreParameters openParams = (JDBCStoreParameters) explorer.getOpenParameters();
205 41664 jjdelcerro
            openParams.setSchema(this.options.getSchema());
206 41598 jjdelcerro
            openParams.setTable(this.options.getTableName());
207 42708 fdiaz
            openParams.setCRS(targetProjection);
208 41486 jjdelcerro
            openParams.setDefaultGeometryField(
209 41598 jjdelcerro
                    this.options.getSource().getDefaultFeatureType().getDefaultGeometryAttributeName()
210 41486 jjdelcerro
            );
211
            target = (FeatureStore) explorer.open(openParams);
212
213
            FeatureType targetFeatureType = target.getDefaultFeatureType();
214 41598 jjdelcerro
            FeatureType sourceFeatureType = featureSet.getDefaultFeatureType();
215 41681 jjdelcerro
216 40435 jjdelcerro
            target.edit(FeatureStore.MODE_APPEND);
217
218
            int featureCount = 1;
219 41486 jjdelcerro
            taskStatus.setRangeOfValues(0, featureSet.getSize());
220
221 41681 jjdelcerro
            int targetGeometryIndex = -1;
222
            int sourceGeometryIndex = -1;
223 42708 fdiaz
            if( getGeometryColumnCount(sourceFeatureType)==1
224 41681 jjdelcerro
                    && getGeometryColumnCount(targetFeatureType)==1 ) {
225 43420 jjdelcerro
                // Si solo hay una columna de geometria asignaremos las geometrias
226 41681 jjdelcerro
                // independientemente de como se llamen los campos.
227
                targetGeometryIndex = targetFeatureType.getDefaultGeometryAttributeIndex();
228
                sourceGeometryIndex = sourceFeatureType.getDefaultGeometryAttributeIndex();
229 43420 jjdelcerro
            } else {
230
                FeatureAttributeDescriptor attr = sourceFeatureType.getDefaultGeometryAttribute();
231
                sourceGeometryIndex = attr.getIndex();
232
                targetGeometryIndex = targetFeatureType.getAttributeDescriptor(attr.getName()).getIndex();
233 41681 jjdelcerro
            }
234 42708 fdiaz
235 41880 jjdelcerro
            logger.debug("Inserting rows");
236 41654 jjdelcerro
            taskStatus.message("Inserting rows");
237 41486 jjdelcerro
            it = featureSet.fastIterator();
238
            while (it.hasNext()) {
239
                Feature feature = (Feature) it.next();
240 41681 jjdelcerro
                this.taskStatus.setCurValue(featureCount);
241
242 41486 jjdelcerro
                targetFeature = target.createNewFeature(targetFeatureType, feature);
243 41681 jjdelcerro
                for (int i = 0; i < sourceFeatureType.size(); i++) {
244
                    if (i == sourceGeometryIndex) {
245
                        // Es facil que los campos geometria no se llamen igual, asi que
246
                        // el campo geometria lo asignamos a capon.
247
                        // Esto puede ocasionar problemas cuando la tabla destino no tenga
248
                        // geometria o tenga mas de una.
249
                        targetFeature.set(targetGeometryIndex, feature.get(sourceGeometryIndex));
250
                    } else {
251
                        FeatureAttributeDescriptor x = sourceFeatureType.getAttributeDescriptor(i);
252
                        int targetAttributeIndex = targetFeatureType.getIndex(getTranslatedIdentifier(x.getName()));
253
                        if (targetAttributeIndex < 0) {
254
                            throw new RuntimeException("Can't locate column '" + x.getName() + "' in the target table.");
255
                        }
256
                        targetFeature.set(targetAttributeIndex, feature.get(x.getName()));
257
                    }
258 41598 jjdelcerro
                }
259 41486 jjdelcerro
260 43420 jjdelcerro
                Geometry geometry = targetFeature.getGeometry(targetGeometryIndex);
261 41488 jjdelcerro
                if (geometry != null) {
262 41598 jjdelcerro
                    switch (this.options.getGeometryChecks()) {
263 41488 jjdelcerro
                        case CHECK_IF_CORRUPT:
264
                            geometryCheck = geometry.getValidationStatus();
265
                            if (geometryCheck.getStatusCode() == Geometry.ValidationStatus.CURRUPTED) {
266 41598 jjdelcerro
                                switch (this.options.getGeometryChecksAction()) {
267 41488 jjdelcerro
                                    case ACTION_SET_GEOMETRY_TO_NULL:
268
                                        targetFeature.setDefaultGeometry(null);
269
                                        break;
270
                                    case ACTION_SKIP_FEATURE:
271
                                        continue;
272
                                    case ACTION_ABORT:
273
                                    default:
274
                                        throw new InvalidGeometryException(targetFeature, geometryCheck.getMessage());
275
                                }
276 41486 jjdelcerro
                            }
277
278 41488 jjdelcerro
                            break;
279 41486 jjdelcerro
280 41488 jjdelcerro
                        case CHECK_IF_VALID:
281
                            geometryCheck = geometry.getValidationStatus();
282
                            if (!geometryCheck.isValid()) {
283
                                Geometry g = null;
284 41681 jjdelcerro
                                if (this.options.getTryToFixGeometry()) {
285 41488 jjdelcerro
                                    g = geometry.makeValid();
286
                                    if (g != null) {
287
                                        targetFeature.setDefaultGeometry(g);
288
                                    }
289
                                }
290
                                if (g == null) {
291 41598 jjdelcerro
                                    switch (this.options.getGeometryChecksAction()) {
292 41488 jjdelcerro
                                        case ACTION_SET_GEOMETRY_TO_NULL:
293
                                            targetFeature.setDefaultGeometry(null);
294
                                            break;
295
                                        case ACTION_SKIP_FEATURE:
296
                                            continue;
297
                                        case ACTION_ABORT:
298
                                        default:
299
                                            throw new InvalidGeometryException(targetFeature, geometryCheck.getMessage());
300
                                    }
301
                                }
302 41486 jjdelcerro
                            }
303
304 41488 jjdelcerro
                            break;
305
                        case CHECK_NONE:
306
                        default:
307
                            break;
308
                    }
309
                    // ================================================
310 42708 fdiaz
                    // Reprojection
311 41488 jjdelcerro
                    if (geo_att != null && coord_trans != null) {
312
                        reproj_geom = targetFeature.getDefaultGeometry();
313
                        reproj_geom = reproj_geom.cloneGeometry();
314
                        reproj_geom.reProject(coord_trans);
315
                        targetFeature.setDefaultGeometry(reproj_geom);
316
                    }
317
                    // ================================================
318 41486 jjdelcerro
                }
319
320
                target.insert(targetFeature);
321 40435 jjdelcerro
322
                if (this.taskStatus.isCancellationRequested()) {
323
                    return;
324
                }
325
                featureCount++;
326
            }
327 41486 jjdelcerro
            targetFeature = null;
328 40435 jjdelcerro
            target.finishEditing();
329 41681 jjdelcerro
330
            if (this.options.getUpdateTableStatistics()) {
331 41880 jjdelcerro
                logger.debug("Updating statistics");
332 41654 jjdelcerro
                taskStatus.message("Updating statistics");
333 43020 jjdelcerro
                explorer.updateTableStatistics(
334
                        openParams.getDBName(),
335
                        openParams.getSchema(),
336
                        openParams.getTable()
337
                );
338 41638 jjdelcerro
            }
339 41880 jjdelcerro
            logger.debug("finish");
340 40435 jjdelcerro
341
            if (exporttoServiceFinishAction != null) {
342 41127 jldominguez
                exporttoServiceFinishAction.finished(
343 41598 jjdelcerro
                        this.options.getTableName() + " (" + explorer.getStoreName() + ")",
344 41486 jjdelcerro
                        openParams);
345 40435 jjdelcerro
            }
346 41654 jjdelcerro
            taskStatus.message("Exportation finished");
347 41681 jjdelcerro
348 40435 jjdelcerro
        } catch (Exception e) {
349 41488 jjdelcerro
            logger.warn("Can't export data.", e);
350 41654 jjdelcerro
            taskStatus.message("Problems exporting data");
351 41486 jjdelcerro
            throw new ExporttoServiceException(e, targetFeature);
352
353 40435 jjdelcerro
        } finally {
354 41486 jjdelcerro
            if (it != null) {
355
                it.dispose();
356 40435 jjdelcerro
            }
357
            featureSet.dispose();
358
            if (target != null) {
359 43408 jjdelcerro
                if( target.isAppending() ) {
360
                    try {
361
                        target.cancelEditing();
362
                    } catch(Exception ex) {
363
                        // Do nothing
364
                    }
365
                }
366 40435 jjdelcerro
                target.dispose();
367
            }
368
            this.taskStatus.terminate();
369
            this.taskStatus.remove();
370
        }
371
    }
372 42708 fdiaz
373 41681 jjdelcerro
    private int getGeometryColumnCount(FeatureType featureType) {
374
        int count = 0;
375
        for( int i=0; i<featureType.size(); i++ ) {
376
            if( featureType.getAttributeDescriptor(i).getType()==DataTypes.GEOMETRY ) {
377
                count++;
378
            }
379
        }
380
        return count;
381
    }
382 40435 jjdelcerro
383
    public void setFinishAction(
384 41486 jjdelcerro
            ExporttoServiceFinishAction exporttoServiceFinishAction) {
385 40435 jjdelcerro
        this.exporttoServiceFinishAction = exporttoServiceFinishAction;
386
    }
387
388
}