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 / export / jdbc / service / ExportJDBCService.java @ 43925

History | View | Annotate | Download (18.6 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
package org.gvsig.export.jdbc.service;
25

    
26
import java.text.MessageFormat;
27
import org.apache.commons.lang3.StringUtils;
28
import org.cresques.cts.ICoordTrans;
29
import org.cresques.cts.IProjection;
30

    
31
import org.gvsig.fmap.dal.exception.DataException;
32
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
33
import org.gvsig.fmap.dal.feature.EditableFeatureType;
34
import org.gvsig.fmap.dal.feature.FeatureType;
35
import org.gvsig.fmap.dal.DALLocator;
36
import org.gvsig.fmap.dal.DataManager;
37
import org.gvsig.fmap.dal.DataTypes;
38
import org.gvsig.fmap.dal.NewDataStoreParameters;
39
import org.gvsig.fmap.dal.OpenDataStoreParameters;
40
import org.gvsig.fmap.dal.feature.EditableFeature;
41
import org.gvsig.fmap.dal.feature.Feature;
42
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
43
import org.gvsig.fmap.dal.feature.FeatureSet;
44
import org.gvsig.fmap.dal.feature.FeatureStore;
45
import org.gvsig.fmap.dal.feature.FeatureStoreProviderFactory;
46
import org.gvsig.fmap.dal.store.jdbc.JDBCNewStoreParameters;
47
import org.gvsig.fmap.dal.store.jdbc.JDBCServerExplorer;
48
import org.gvsig.fmap.dal.store.jdbc.JDBCStoreParameters;
49
import org.gvsig.fmap.geom.Geometry;
50
import org.gvsig.tools.dispose.DisposableIterator;
51
import org.gvsig.export.ExportException;
52
import org.gvsig.export.ExportLocator;
53
import org.gvsig.export.spi.ExportService;
54
import org.gvsig.export.spi.AbstractExportService;
55
import org.gvsig.export.spi.ExportServiceFactory;
56
import org.gvsig.export.spi.ExportServiceManager;
57
import org.gvsig.export.spi.ExportServiceManager.FixGeometryStatus;
58

    
59
/**
60
 * @author gvSIG Team
61
 * @version $Id$
62
 * 
63
 */
64
public class ExportJDBCService 
65
        extends AbstractExportService 
66
        implements ExportService 
67
    {
68

    
69
    private static class InvalidGeometryException extends ExportException {
70

    
71
        public InvalidGeometryException(Feature feature, String checkMessage) {
72
            super(checkMessage, feature);
73
        }
74
    }
75

    
76
    private FeatureType targetFeatureType;
77

    
78
    
79
    protected ExportJDBCService(ExportServiceFactory factory, ExportJDBCParameters parameters) {
80
        super(factory, parameters);
81
    }
82

    
83
    @Override
84
    public ExportJDBCParameters getParameters() {
85
        return (ExportJDBCParameters) super.getParameters(); 
86
    }
87

    
88
    @Override
89
    protected JDBCServerExplorer createServerExplorer() throws ExportException{
90
        try {
91
            DataManager dataManager = DALLocator.getDataManager();
92

    
93
            JDBCServerExplorer explorer = (JDBCServerExplorer) dataManager.openServerExplorer(
94
                    this.getParameters().getExplorerParameters().getExplorerName(),
95
                    this.getParameters().getExplorerParameters()
96
            );
97
            return explorer;
98
        } catch (Exception e) {
99
            throw new ExportException(e);
100
        }
101
    }
102

    
103
    @Override
104
    protected NewDataStoreParameters createTargetNewStoreParameters() throws ExportException {
105
        try {
106
            FeatureType targetTempFeatureType;
107
            EditableFeatureType targetEditableFeatureType;
108
            
109
            JDBCServerExplorer explorer = this.createServerExplorer();
110

    
111

    
112
            DataManager manager = DALLocator.getDataManager();
113
            FeatureStoreProviderFactory factory = (FeatureStoreProviderFactory) manager.getStoreProviderFactory(explorer.getStoreName());
114

    
115
            boolean preferNotToUseNonNullRestrictions = factory.preferNotToUseNonNullRestrictions();
116

    
117
            targetTempFeatureType = getParameters().getSourceFeatureType().getCopy();
118
            targetEditableFeatureType = targetTempFeatureType.getEditable();
119

    
120
            // Remove inherited primary keys from the data source and remove NotNull
121
            // restrictions if proceed.
122
            for (int i = 0; i < targetEditableFeatureType.size(); i++) {
123
                EditableFeatureAttributeDescriptor x = (EditableFeatureAttributeDescriptor) targetEditableFeatureType.get(i);
124
                x.setIsPrimaryKey(false);
125
                if( preferNotToUseNonNullRestrictions ) {
126
                    x.setAllowNull(true);
127
                }
128
            }
129

    
130
            if (this.getParameters().getTranslateIdentifiersToLowerCase()
131
                    || this.getParameters().getRemoveSpacesInIdentifiers() 
132
                    || this.getParameters().getTranslateHyphens()) {
133
                for (int i = 0; i < targetEditableFeatureType.size(); i++) {
134
                    EditableFeatureAttributeDescriptor x = (EditableFeatureAttributeDescriptor) targetEditableFeatureType.get(i);
135
                    x.setName(getTranslatedIdentifier(x.getName()));
136
                }
137
            }
138

    
139
            if (this.getParameters().getPrimaryKey() != null) {
140
                EditableFeatureAttributeDescriptor pk = (EditableFeatureAttributeDescriptor) targetEditableFeatureType.get(getTranslatedIdentifier(getParameters().getPrimaryKey()));
141
                if (pk == null) {
142
                    pk = targetEditableFeatureType.add(
143
                            getTranslatedIdentifier(this.getParameters().getPrimaryKey()),
144
                            DataTypes.LONG
145
                    );
146
                    pk.setIsPrimaryKey(true);
147
                    pk.setIsAutomatic(true);
148
                } else {
149
                    pk.setIsPrimaryKey(true);
150
                }
151
            }
152

    
153
            if (this.getParameters().getCreateIndexInGeometryRow()) {
154
                EditableFeatureAttributeDescriptor x = (EditableFeatureAttributeDescriptor) targetEditableFeatureType.getDefaultGeometryAttribute();
155
                x.setIsIndexed(true);
156
            }
157

    
158
            // ======================================================
159
            // Reprojection: set SRS of geometry field to target SRS
160
            EditableFeatureAttributeDescriptor attrdescriptor
161
                    = (EditableFeatureAttributeDescriptor) targetEditableFeatureType.getDefaultGeometryAttribute();
162
            if (attrdescriptor != null) {
163
                attrdescriptor.setSRS(this.getParameters().getTargetProjection());
164
            }
165

    
166
            // ======================================
167
            // Remove index to improve performance
168
            this.targetFeatureType = targetEditableFeatureType.getNotEditableCopy();
169
            for (int i = 0; i < targetEditableFeatureType.size(); i++) {
170
                EditableFeatureAttributeDescriptor x = (EditableFeatureAttributeDescriptor) targetEditableFeatureType.get(i);
171
                //x.setIsPrimaryKey(false);
172
                x.setIsIndexed(false);
173
            }
174

    
175
            // ======================================
176

    
177

    
178
            JDBCNewStoreParameters createTableParams = (JDBCNewStoreParameters) explorer.getAddParameters();
179

    
180
            createTableParams.setSelectRole(this.getParameters().getSelectRole());
181
            createTableParams.setInsertRole(this.getParameters().getInsertRole());
182
            createTableParams.setUpdateRole(this.getParameters().getUpdateRole());
183
            createTableParams.setDeleteRole(this.getParameters().getDeleteRole());
184
            createTableParams.setTruncateRole(this.getParameters().getTruncateRole());
185
            createTableParams.setReferenceRole(this.getParameters().getReferenceRole());
186
            createTableParams.setTriggerRole(this.getParameters().getTriggerRole());
187
            createTableParams.setAllRole(this.getParameters().getAllRole());
188

    
189
            createTableParams.setSchema(this.getParameters().getSchema());
190
            createTableParams.setPostCreatingStatement(this.getParameters().getPostCreatingStatement());
191

    
192
            createTableParams.setDefaultFeatureType(targetEditableFeatureType);
193
            createTableParams.setTable(this.getParameters().getTableName());
194
            
195
            return createTableParams;
196
            
197
        } catch (Exception ex) {
198
            throw new ExportException(ex);
199
        }
200
    }
201

    
202
    @Override
203
    public OpenDataStoreParameters createTargetOpenStoreParameters() throws ExportException {
204
        try {
205
            DataManager dataManager = DALLocator.getDataManager();
206
            JDBCServerExplorer explorer = this.createServerExplorer();
207

    
208
            JDBCStoreParameters openStoreParameters = (JDBCStoreParameters) explorer.getOpenParameters();
209
            openStoreParameters.setSchema(this.getParameters().getSchema());
210
            openStoreParameters.setTable(this.getParameters().getTableName());
211
            openStoreParameters.setCRS(this.getParameters().getTargetProjection());
212
            openStoreParameters.setDefaultGeometryField(
213
                    this.getParameters().getSourceFeatureType().getDefaultGeometryAttributeName()
214
            );
215
            return openStoreParameters;
216
        } catch (DataException ex) {
217
            throw new ExportException(ex);
218
        }
219
    }
220

    
221
    protected String getTranslatedIdentifier(String identifier) {
222
        String s = identifier;
223
        if (this.getParameters().getTranslateIdentifiersToLowerCase()) {
224
            s = s.toLowerCase();
225
        }
226
        if( this.getParameters().getTranslateHyphens()) {
227
            s = s.replace("-", "_");
228
        }
229
        if (this.getParameters().getRemoveSpacesInIdentifiers()) {
230
            s = StringUtils.normalizeSpace(s).replace(" ", "_");
231
        }
232
        return s;
233
    }
234

    
235
    private int getGeometryColumnCount(FeatureType featureType) {
236
        int count = 0;
237
        for( int i=0; i<featureType.size(); i++ ) {
238
            if( featureType.getAttributeDescriptor(i).getType()==DataTypes.GEOMETRY ) {
239
                count++;
240
            }
241
        }
242
        return count;
243
    }
244
    @Override
245
    public void export(FeatureSet featureSet) throws ExportException {
246
        Geometry.ValidationStatus geometryCheck;
247

    
248
        DisposableIterator it = null;
249
        EditableFeature targetFeature = null;
250
        FeatureStore target = null;
251

    
252
        try {
253
            ExportServiceManager serviceManager = ExportLocator.getServiceManager();
254

    
255
            // ======================================
256
            // Reprojection
257
            FeatureAttributeDescriptor geo_att = this.getParameters().getSourceFeatureType().getDefaultGeometryAttribute();
258
            IProjection sourceProjection;
259
            ICoordTrans coord_trans = null;
260
            Geometry reproj_geom;
261
            IProjection targetProjection = this.getParameters().getTargetProjection();
262
            if (geo_att != null) {
263
                sourceProjection = geo_att.getSRS();
264
                // this comparison is perhaps too preventive
265
                // we could  have two instances of same projection
266
                // so we would do more computations than needed
267
                if (sourceProjection != null && targetProjection != null && sourceProjection != targetProjection) {
268
                    coord_trans = sourceProjection.getCT(targetProjection);
269
                }
270
            }
271
            // ============================================
272

    
273
            DataManager dataManager = DALLocator.getDataManager();
274

    
275
            
276
            JDBCServerExplorer explorer = this.createServerExplorer();
277

    
278
            if (this.getParameters().canCreatetable()) {
279
                LOG.debug("Creating table");
280
                getTaskStatus().message("Creating table");
281
                NewDataStoreParameters targetNewStoreParameters = this.createTargetNewStoreParameters();
282
                explorer.add(
283
                        targetNewStoreParameters.getDataStoreName(),
284
                        targetNewStoreParameters,
285
                        true
286
                );
287
            }
288

    
289
            JDBCStoreParameters openParams = (JDBCStoreParameters) this.createTargetOpenStoreParameters();
290
            target = (FeatureStore) explorer.open(openParams);
291

    
292
            FeatureType theTargetFeatureType = target.getDefaultFeatureType();
293
            FeatureType theSourceFeatureType = featureSet.getDefaultFeatureType();
294

    
295
            target.edit(FeatureStore.MODE_APPEND);
296

    
297
            long featureCount = 1;
298
            getTaskStatus().setRangeOfValues(0, featureSet.getSize());
299

    
300
            int targetGeometryIndex;
301
            int sourceGeometryIndex;
302
            if( getGeometryColumnCount(theSourceFeatureType)==1
303
                    && getGeometryColumnCount(theTargetFeatureType)==1 ) {
304
                // Si solo hay una columna de geometria asignaremos las geometrias
305
                // independientemente de como se llamen los campos.
306
                targetGeometryIndex = theTargetFeatureType.getDefaultGeometryAttributeIndex();
307
                sourceGeometryIndex = theSourceFeatureType.getDefaultGeometryAttributeIndex();
308
            } else {
309
                FeatureAttributeDescriptor attr = theSourceFeatureType.getDefaultGeometryAttribute();
310
                sourceGeometryIndex = attr.getIndex();
311
                targetGeometryIndex = theTargetFeatureType.getAttributeDescriptor(attr.getName()).getIndex();
312
            }
313

    
314
            LOG.debug("Inserting rows");
315
            getTaskStatus().message("Inserting rows");
316
            it = featureSet.fastIterator();
317
            while (it.hasNext()) {
318
                Feature feature = (Feature) it.next();
319
                this.getTaskStatus().setCurValue(featureCount);
320

    
321
                targetFeature = target.createNewFeature(theTargetFeatureType, feature);
322
                for (int i = 0; i < theSourceFeatureType.size(); i++) {
323
                    if (i == sourceGeometryIndex) {
324
                        // Es facil que los campos geometria no se llamen igual, asi que
325
                        // el campo geometria lo asignamos a capon.
326
                        // Esto puede ocasionar problemas cuando la tabla destino no tenga
327
                        // geometria o tenga mas de una.
328
                        targetFeature.set(targetGeometryIndex, feature.get(sourceGeometryIndex));
329
                    } else {
330
                        FeatureAttributeDescriptor x = theSourceFeatureType.getAttributeDescriptor(i);
331
                        int targetAttributeIndex = theTargetFeatureType.getIndex(getTranslatedIdentifier(x.getName()));
332
                        if (targetAttributeIndex < 0) {
333
                            throw new RuntimeException("Can't locate column '" + x.getName() + "' in the target table.");
334
                        }
335
                        targetFeature.set(targetAttributeIndex, feature.get(x.getName()));
336
                    }
337
                }
338

    
339
                Geometry geometry = targetFeature.getGeometry(targetGeometryIndex);
340
                FixGeometryStatus check = serviceManager.fixGeometry(getParameters(), coord_trans, geometry);
341
                switch(check.getState()) {
342
                    case FixGeometryStatus.STATE_OK:
343
                        targetFeature.setDefaultGeometry(check.getGeometry());
344
                        break;
345
                    case FixGeometryStatus.STATE_SKIP:
346
                        continue;
347
                    case FixGeometryStatus.STATE_ABORT:
348
                        throw new InvalidGeometryException(targetFeature, check.getMessage());
349
                }
350

    
351
                target.insert(targetFeature);
352

    
353
                if (this.getTaskStatus().isCancellationRequested()) {
354
                    return;
355
                }
356
                featureCount++;
357
            }
358
            String msgRowCount = MessageFormat.format(" ({0,number, #,###} rows)",featureCount);
359
            targetFeature = null;
360
            getTaskStatus().setIndeterminate();
361
            LOG.debug("Finish editing"+msgRowCount);
362
            if( featureCount > 50000 ) {
363
                getTaskStatus().message("Finishing insertion of records, may take a while" + msgRowCount);
364
            } else {
365
                getTaskStatus().message("Finishing insertion of records"+msgRowCount);
366
            }
367
            target.finishEditing();
368
            
369
             if (this.getParameters().canCreatetable()) {
370
                getTaskStatus().message("Preparing the update of the indices"+msgRowCount);
371
                target.edit();
372
                EditableFeatureType ft = target.getDefaultFeatureType().getEditable();
373
                for( FeatureAttributeDescriptor attr : this.targetFeatureType) {
374
                    EditableFeatureAttributeDescriptor attr2 = (EditableFeatureAttributeDescriptor) ft.getAttributeDescriptor(attr.getName());
375
                    if( attr2!=null ) {
376
                        //attr2.setIsPrimaryKey(attr.isPrimaryKey());
377
                        attr2.setIsIndexed(attr.isIndexed());
378
                        attr2.setIsAutomatic(attr.isAutomatic());
379
                    }
380
                }
381
                target.update(ft);
382
                getTaskStatus().message("Updating the indices"+msgRowCount);
383
                target.finishEditing();
384
            }
385
            if (this.getParameters().getUpdateTableStatistics()) {
386
                LOG.debug("Updating statistics");
387
                getTaskStatus().message("Updating statistics"+msgRowCount);
388
                explorer.updateTableStatistics(
389
                        openParams.getDBName(),
390
                        openParams.getSchema(),
391
                        openParams.getTable()
392
                );
393
            }
394
            LOG.debug("finish");
395
            getTaskStatus().message("Exportation finished");
396
            getTaskStatus().terminate();
397

    
398
        } catch (Exception e) {
399
            LOG.warn("Can't export data.", e);
400
            getTaskStatus().message("Problems exporting data");
401
            throw new ExportException(e, targetFeature);
402

    
403
        } finally {
404
            if (it != null) {
405
                it.dispose();
406
            }
407
            featureSet.dispose();
408
            if (target != null) {
409
                if( target.isAppending() ) {
410
                    try {
411
                        target.cancelEditing();
412
                    } catch(Exception ex) {
413
                        LOG.warn("Can't cancel editing.",ex);
414
                    }
415
                }
416
                target.dispose();
417
            }
418
            this.getTaskStatus().terminate();
419
            this.getTaskStatus().remove();
420
        }
421
    }
422
        
423
}