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 @ 43920

History | View | Annotate | Download (17.1 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 43648 jjdelcerro
import java.text.MessageFormat;
26 41598 jjdelcerro
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 43920 jjdelcerro
import org.gvsig.exportto.swing.spi.ExportGeometryUtils;
33
import org.gvsig.exportto.swing.spi.ExportGeometryUtils.FixGeometryStatus;
34 40435 jjdelcerro
import org.gvsig.fmap.dal.DALLocator;
35
import org.gvsig.fmap.dal.DataManager;
36
import org.gvsig.fmap.dal.DataTypes;
37
import org.gvsig.fmap.dal.feature.EditableFeature;
38
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
39
import org.gvsig.fmap.dal.feature.EditableFeatureType;
40
import org.gvsig.fmap.dal.feature.Feature;
41 41127 jldominguez
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
42 40435 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureSet;
43
import org.gvsig.fmap.dal.feature.FeatureStore;
44 43687 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureStoreProviderFactory;
45 40435 jjdelcerro
import org.gvsig.fmap.dal.feature.FeatureType;
46 41492 jjdelcerro
import org.gvsig.fmap.dal.store.jdbc.JDBCNewStoreParameters;
47 40435 jjdelcerro
import org.gvsig.fmap.dal.store.jdbc.JDBCServerExplorer;
48 40606 jldominguez
import org.gvsig.fmap.dal.store.jdbc.JDBCStoreParameters;
49 40435 jjdelcerro
import org.gvsig.fmap.geom.Geometry;
50
import org.gvsig.tools.dispose.DisposableIterator;
51
import org.gvsig.tools.task.AbstractMonitorableTask;
52 41488 jjdelcerro
import org.slf4j.Logger;
53
import org.slf4j.LoggerFactory;
54 40435 jjdelcerro
55
/**
56
 * @author gvSIG Team
57
 * @version $Id$
58 41486 jjdelcerro
 *
59 40435 jjdelcerro
 */
60
public class ExporrtoJDBCService extends AbstractMonitorableTask implements
61 41486 jjdelcerro
        ExporttoService {
62 40435 jjdelcerro
63 41488 jjdelcerro
    private static final Logger logger = LoggerFactory.getLogger(ExporrtoJDBCService.class);
64
65 40435 jjdelcerro
    private ExporttoServiceFinishAction exporttoServiceFinishAction = null;
66 43648 jjdelcerro
    private final ExporttoJDBCOptions options;
67
    private FeatureType targetFeatureType = null;
68 41598 jjdelcerro
//    private Map<String,String> translationIds;
69 40435 jjdelcerro
70 41598 jjdelcerro
    public ExporrtoJDBCService(ExporttoJDBCOptions options) {
71
        this.options = options;
72 40435 jjdelcerro
    }
73
74 41598 jjdelcerro
    protected String getTranslatedIdentifier(String identifier) {
75
        String s = identifier;
76 41681 jjdelcerro
        if (this.options.getTranslateIdentifiersToLowerCase()) {
77 41598 jjdelcerro
            s = s.toLowerCase();
78
        }
79 43377 jjdelcerro
        if( this.options.getTranslateHyphens()) {
80
            s = s.replace("-", "_");
81
        }
82 41681 jjdelcerro
        if (this.options.getRemoveSpacesInIdentifiers()) {
83 41598 jjdelcerro
            s = StringUtils.normalizeSpace(s).replace(" ", "_");
84
        }
85
        return s;
86
    }
87 41681 jjdelcerro
88 41486 jjdelcerro
    protected void createTable(JDBCServerExplorer explorer) throws Exception {
89 40435 jjdelcerro
90 43648 jjdelcerro
        FeatureType targetTempFeatureType;
91 41488 jjdelcerro
        EditableFeatureType targetEditableFeatureType;
92 40435 jjdelcerro
93 43687 jjdelcerro
        DataManager manager = DALLocator.getDataManager();
94
        FeatureStoreProviderFactory factory = (FeatureStoreProviderFactory) manager.getStoreProviderFactory(explorer.getStoreName());
95
96
        boolean preferNotToUseNonNullRestrictions = factory.preferNotToUseNonNullRestrictions();
97
98 43920 jjdelcerro
        targetTempFeatureType = options.getSourceFeatureType().getCopy();
99 43648 jjdelcerro
        targetEditableFeatureType = targetTempFeatureType.getEditable();
100 41681 jjdelcerro
101 43687 jjdelcerro
        // Remove inherited primary keys from the data source and remove NotNull
102
        // restrictions if proceed.
103 43648 jjdelcerro
        for (int i = 0; i < targetEditableFeatureType.size(); i++) {
104
            EditableFeatureAttributeDescriptor x = (EditableFeatureAttributeDescriptor) targetEditableFeatureType.get(i);
105
            x.setIsPrimaryKey(false);
106 43687 jjdelcerro
            if( preferNotToUseNonNullRestrictions ) {
107
                x.setAllowNull(true);
108
            }
109 43648 jjdelcerro
        }
110
111 41681 jjdelcerro
        if (this.options.getTranslateIdentifiersToLowerCase()
112 43377 jjdelcerro
                || this.options.getRemoveSpacesInIdentifiers()
113
                || this.options.getTranslateHyphens()) {
114 41681 jjdelcerro
            for (int i = 0; i < targetEditableFeatureType.size(); i++) {
115
                EditableFeatureAttributeDescriptor x = (EditableFeatureAttributeDescriptor) targetEditableFeatureType.get(i);
116 41598 jjdelcerro
                x.setName(getTranslatedIdentifier(x.getName()));
117
            }
118
        }
119 41681 jjdelcerro
120 41598 jjdelcerro
        if (this.options.getPrimaryKey() != null) {
121
            EditableFeatureAttributeDescriptor pk = (EditableFeatureAttributeDescriptor) targetEditableFeatureType.get(getTranslatedIdentifier(options.getPrimaryKey()));
122 41488 jjdelcerro
            if (pk == null) {
123 41598 jjdelcerro
                pk = targetEditableFeatureType.add(
124 41681 jjdelcerro
                        getTranslatedIdentifier(this.options.getPrimaryKey()),
125 41598 jjdelcerro
                        DataTypes.LONG
126
                );
127 41488 jjdelcerro
                pk.setIsPrimaryKey(true);
128
                pk.setIsAutomatic(true);
129
            } else {
130
                pk.setIsPrimaryKey(true);
131
            }
132 41486 jjdelcerro
        }
133
134 41681 jjdelcerro
        if (this.options.getCreateIndexInGeometryRow()) {
135
            EditableFeatureAttributeDescriptor x = (EditableFeatureAttributeDescriptor) targetEditableFeatureType.getDefaultGeometryAttribute();
136 41638 jjdelcerro
            x.setIsIndexed(true);
137
        }
138 41681 jjdelcerro
139 41486 jjdelcerro
        // ======================================================
140
        // Reprojection: set SRS of geometry field to target SRS
141
        EditableFeatureAttributeDescriptor attrdescriptor
142
                = (EditableFeatureAttributeDescriptor) targetEditableFeatureType.getDefaultGeometryAttribute();
143
        if (attrdescriptor != null) {
144 41598 jjdelcerro
            attrdescriptor.setSRS(this.options.getTargetProjection());
145 41486 jjdelcerro
        }
146
147
        // ======================================
148 43648 jjdelcerro
        // Remove index to improve performance
149
        this.targetFeatureType = targetEditableFeatureType.getNotEditableCopy();
150
        for (int i = 0; i < targetEditableFeatureType.size(); i++) {
151
            EditableFeatureAttributeDescriptor x = (EditableFeatureAttributeDescriptor) targetEditableFeatureType.get(i);
152
            //x.setIsPrimaryKey(false);
153
            x.setIsIndexed(false);
154
        }
155
156
        // ======================================
157 43687 jjdelcerro
158 43648 jjdelcerro
159 41492 jjdelcerro
        JDBCNewStoreParameters createTableParams = (JDBCNewStoreParameters) explorer.getAddParameters();
160 41486 jjdelcerro
161 41655 jjdelcerro
        createTableParams.setSelectRole(this.options.getSelectRole());
162
        createTableParams.setInsertRole(this.options.getInsertRole());
163
        createTableParams.setUpdateRole(this.options.getUpdateRole());
164
        createTableParams.setDeleteRole(this.options.getDeleteRole());
165
        createTableParams.setTruncateRole(this.options.getTruncateRole());
166
        createTableParams.setReferenceRole(this.options.getReferenceRole());
167
        createTableParams.setTriggerRole(this.options.getTriggerRole());
168
        createTableParams.setAllRole(this.options.getAllRole());
169 41681 jjdelcerro
170 41655 jjdelcerro
        createTableParams.setSchema(this.options.getSchema());
171
        createTableParams.setPostCreatingStatement(this.options.getPostCreatingStatement());
172 41681 jjdelcerro
173 41486 jjdelcerro
        createTableParams.setDefaultFeatureType(targetEditableFeatureType);
174 41681 jjdelcerro
        createTableParams.setTable(this.options.getTableName());
175 41486 jjdelcerro
        explorer.add(explorer.getStoreName(), createTableParams, true);
176
    }
177
178
    private static class InvalidGeometryException extends ExporttoServiceException {
179
180 43648 jjdelcerro
        private static final long serialVersionUID = 3082742759529054747L;
181
182 41486 jjdelcerro
        public InvalidGeometryException(Feature feature, String checkMessage) {
183
            super(checkMessage, null, checkMessage, 0);
184
            this.feature = feature;
185
        }
186
    }
187
188 43648 jjdelcerro
    @Override
189 41486 jjdelcerro
    public void export(FeatureSet featureSet) throws ExporttoServiceException {
190
        Geometry.ValidationStatus geometryCheck;
191
192
        DisposableIterator it = null;
193
        EditableFeature targetFeature = null;
194 40435 jjdelcerro
        FeatureStore target = null;
195 41488 jjdelcerro
196 40435 jjdelcerro
        try {
197 41488 jjdelcerro
198 40435 jjdelcerro
            // ======================================
199 42708 fdiaz
            // Reprojection
200 43920 jjdelcerro
            FeatureAttributeDescriptor geo_att = this.options.getSourceFeatureType().getDefaultGeometryAttribute();
201 43648 jjdelcerro
            IProjection sourceProjection;
202 40435 jjdelcerro
            ICoordTrans coord_trans = null;
203 43648 jjdelcerro
            Geometry reproj_geom;
204 42708 fdiaz
            IProjection targetProjection = this.options.getTargetProjection();
205 41127 jldominguez
            if (geo_att != null) {
206
                sourceProjection = geo_att.getSRS();
207
                // this comparison is perhaps too preventive
208
                // we could  have two instances of same projection
209
                // so we would do more computations than needed
210 42708 fdiaz
                if (sourceProjection != null && targetProjection != null && sourceProjection != targetProjection) {
211
                    coord_trans = sourceProjection.getCT(targetProjection);
212 41127 jldominguez
                }
213 40435 jjdelcerro
            }
214
            // ============================================
215
216 41486 jjdelcerro
            DataManager dataManager = DALLocator.getDataManager();
217 40435 jjdelcerro
218 41486 jjdelcerro
            JDBCServerExplorer explorer = (JDBCServerExplorer) dataManager.openServerExplorer(
219 41598 jjdelcerro
                    this.options.getExplorerParameters().getExplorerName(),
220
                    this.options.getExplorerParameters()
221 41486 jjdelcerro
            );
222
223 41681 jjdelcerro
            if (this.options.canCreatetable()) {
224 41880 jjdelcerro
                logger.debug("Creating table");
225 41654 jjdelcerro
                taskStatus.message("Creating table");
226 41486 jjdelcerro
                this.createTable(explorer);
227
            }
228
229
            JDBCStoreParameters openParams = (JDBCStoreParameters) explorer.getOpenParameters();
230 41664 jjdelcerro
            openParams.setSchema(this.options.getSchema());
231 41598 jjdelcerro
            openParams.setTable(this.options.getTableName());
232 42708 fdiaz
            openParams.setCRS(targetProjection);
233 41486 jjdelcerro
            openParams.setDefaultGeometryField(
234 43920 jjdelcerro
                    this.options.getSourceFeatureType().getDefaultGeometryAttributeName()
235 41486 jjdelcerro
            );
236
            target = (FeatureStore) explorer.open(openParams);
237
238
            FeatureType targetFeatureType = target.getDefaultFeatureType();
239 41598 jjdelcerro
            FeatureType sourceFeatureType = featureSet.getDefaultFeatureType();
240 41681 jjdelcerro
241 40435 jjdelcerro
            target.edit(FeatureStore.MODE_APPEND);
242
243 43648 jjdelcerro
            long featureCount = 1;
244 41486 jjdelcerro
            taskStatus.setRangeOfValues(0, featureSet.getSize());
245
246 43648 jjdelcerro
            int targetGeometryIndex;
247
            int sourceGeometryIndex;
248 42708 fdiaz
            if( getGeometryColumnCount(sourceFeatureType)==1
249 41681 jjdelcerro
                    && getGeometryColumnCount(targetFeatureType)==1 ) {
250 43420 jjdelcerro
                // Si solo hay una columna de geometria asignaremos las geometrias
251 41681 jjdelcerro
                // independientemente de como se llamen los campos.
252
                targetGeometryIndex = targetFeatureType.getDefaultGeometryAttributeIndex();
253
                sourceGeometryIndex = sourceFeatureType.getDefaultGeometryAttributeIndex();
254 43420 jjdelcerro
            } else {
255
                FeatureAttributeDescriptor attr = sourceFeatureType.getDefaultGeometryAttribute();
256
                sourceGeometryIndex = attr.getIndex();
257
                targetGeometryIndex = targetFeatureType.getAttributeDescriptor(attr.getName()).getIndex();
258 41681 jjdelcerro
            }
259 42708 fdiaz
260 41880 jjdelcerro
            logger.debug("Inserting rows");
261 41654 jjdelcerro
            taskStatus.message("Inserting rows");
262 41486 jjdelcerro
            it = featureSet.fastIterator();
263
            while (it.hasNext()) {
264
                Feature feature = (Feature) it.next();
265 41681 jjdelcerro
                this.taskStatus.setCurValue(featureCount);
266
267 41486 jjdelcerro
                targetFeature = target.createNewFeature(targetFeatureType, feature);
268 41681 jjdelcerro
                for (int i = 0; i < sourceFeatureType.size(); i++) {
269
                    if (i == sourceGeometryIndex) {
270
                        // Es facil que los campos geometria no se llamen igual, asi que
271
                        // el campo geometria lo asignamos a capon.
272
                        // Esto puede ocasionar problemas cuando la tabla destino no tenga
273
                        // geometria o tenga mas de una.
274
                        targetFeature.set(targetGeometryIndex, feature.get(sourceGeometryIndex));
275
                    } else {
276
                        FeatureAttributeDescriptor x = sourceFeatureType.getAttributeDescriptor(i);
277
                        int targetAttributeIndex = targetFeatureType.getIndex(getTranslatedIdentifier(x.getName()));
278
                        if (targetAttributeIndex < 0) {
279
                            throw new RuntimeException("Can't locate column '" + x.getName() + "' in the target table.");
280
                        }
281
                        targetFeature.set(targetAttributeIndex, feature.get(x.getName()));
282
                    }
283 41598 jjdelcerro
                }
284 41486 jjdelcerro
285 43420 jjdelcerro
                Geometry geometry = targetFeature.getGeometry(targetGeometryIndex);
286 43920 jjdelcerro
                FixGeometryStatus check = ExportGeometryUtils.fixGeometry(options, coord_trans, geometry);
287
                switch(check.getState()) {
288
                    case FixGeometryStatus.STATE_OK:
289
                        targetFeature.setDefaultGeometry(check.getGeometry());
290
                        break;
291
                    case FixGeometryStatus.STATE_SKIP:
292
                        continue;
293
                    case FixGeometryStatus.STATE_ABORT:
294
                        throw new InvalidGeometryException(targetFeature, check.getMessage());
295 41486 jjdelcerro
                }
296
297
                target.insert(targetFeature);
298 40435 jjdelcerro
299
                if (this.taskStatus.isCancellationRequested()) {
300
                    return;
301
                }
302
                featureCount++;
303
            }
304 43648 jjdelcerro
            String msgRowCount = MessageFormat.format(" ({0,number, #,###} rows)",featureCount);
305 41486 jjdelcerro
            targetFeature = null;
306 43648 jjdelcerro
            taskStatus.setIndeterminate();
307
            logger.debug("Finish editing"+msgRowCount);
308
            if( featureCount > 50000 ) {
309
                taskStatus.message("Finishing insertion of records, may take a while" + msgRowCount);
310
            } else {
311
                taskStatus.message("Finishing insertion of records"+msgRowCount);
312
            }
313 40435 jjdelcerro
            target.finishEditing();
314 43648 jjdelcerro
315
             if (this.options.canCreatetable()) {
316
                taskStatus.message("Preparing the update of the indices"+msgRowCount);
317
                target.edit();
318
                EditableFeatureType ft = target.getDefaultFeatureType().getEditable();
319
                for( FeatureAttributeDescriptor attr : this.targetFeatureType) {
320
                    EditableFeatureAttributeDescriptor attr2 = (EditableFeatureAttributeDescriptor) ft.getAttributeDescriptor(attr.getName());
321
                    if( attr2!=null ) {
322
                        //attr2.setIsPrimaryKey(attr.isPrimaryKey());
323
                        attr2.setIsIndexed(attr.isIndexed());
324
                        attr2.setIsAutomatic(attr.isAutomatic());
325
                    }
326
                }
327
                target.update(ft);
328
                taskStatus.message("Updating the indices"+msgRowCount);
329
                target.finishEditing();
330
            }
331 41681 jjdelcerro
            if (this.options.getUpdateTableStatistics()) {
332 41880 jjdelcerro
                logger.debug("Updating statistics");
333 43648 jjdelcerro
                taskStatus.message("Updating statistics"+msgRowCount);
334 43020 jjdelcerro
                explorer.updateTableStatistics(
335
                        openParams.getDBName(),
336
                        openParams.getSchema(),
337
                        openParams.getTable()
338
                );
339 41638 jjdelcerro
            }
340 41880 jjdelcerro
            logger.debug("finish");
341 43648 jjdelcerro
            taskStatus.message("Exportation finished");
342
            this.taskStatus.terminate();
343 40435 jjdelcerro
344
            if (exporttoServiceFinishAction != null) {
345 41127 jldominguez
                exporttoServiceFinishAction.finished(
346 41598 jjdelcerro
                        this.options.getTableName() + " (" + explorer.getStoreName() + ")",
347 41486 jjdelcerro
                        openParams);
348 40435 jjdelcerro
            }
349 41681 jjdelcerro
350 40435 jjdelcerro
        } catch (Exception e) {
351 41488 jjdelcerro
            logger.warn("Can't export data.", e);
352 41654 jjdelcerro
            taskStatus.message("Problems exporting data");
353 41486 jjdelcerro
            throw new ExporttoServiceException(e, targetFeature);
354
355 40435 jjdelcerro
        } finally {
356 41486 jjdelcerro
            if (it != null) {
357
                it.dispose();
358 40435 jjdelcerro
            }
359
            featureSet.dispose();
360
            if (target != null) {
361 43408 jjdelcerro
                if( target.isAppending() ) {
362
                    try {
363
                        target.cancelEditing();
364
                    } catch(Exception ex) {
365 43648 jjdelcerro
                        logger.warn("Can't cancel editing.",ex);
366 43408 jjdelcerro
                    }
367
                }
368 40435 jjdelcerro
                target.dispose();
369
            }
370
            this.taskStatus.terminate();
371
            this.taskStatus.remove();
372
        }
373
    }
374 42708 fdiaz
375 41681 jjdelcerro
    private int getGeometryColumnCount(FeatureType featureType) {
376
        int count = 0;
377
        for( int i=0; i<featureType.size(); i++ ) {
378
            if( featureType.getAttributeDescriptor(i).getType()==DataTypes.GEOMETRY ) {
379
                count++;
380
            }
381
        }
382
        return count;
383
    }
384 40435 jjdelcerro
385 43648 jjdelcerro
    @Override
386 40435 jjdelcerro
    public void setFinishAction(
387 41486 jjdelcerro
            ExporttoServiceFinishAction exporttoServiceFinishAction) {
388 40435 jjdelcerro
        this.exporttoServiceFinishAction = exporttoServiceFinishAction;
389
    }
390
391
}