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

History | View | Annotate | Download (20.2 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 java.util.Objects;
28
import org.cresques.cts.ICoordTrans;
29
import org.gvsig.export.ExportAttributes;
30
import org.gvsig.export.ExportException;
31
import org.gvsig.export.ExportLocator;
32
import org.gvsig.export.spi.AbstractExportService;
33
import org.gvsig.export.spi.ExportService;
34
import org.gvsig.export.spi.ExportServiceFactory;
35
import org.gvsig.export.spi.ExportServiceManager;
36
import org.gvsig.export.spi.ExportServiceManager.FixGeometryStatus;
37
import org.gvsig.expressionevaluator.Expression;
38
import org.gvsig.expressionevaluator.ExpressionUtils;
39
import org.gvsig.fmap.dal.DALLocator;
40
import org.gvsig.fmap.dal.DataManager;
41
import org.gvsig.fmap.dal.DataStoreProviderFactory;
42
import org.gvsig.fmap.dal.DataTransaction;
43
import org.gvsig.fmap.dal.DataTypes;
44
import org.gvsig.fmap.dal.NewDataStoreParameters;
45
import org.gvsig.fmap.dal.OpenDataStoreParameters;
46
import org.gvsig.fmap.dal.exception.DataException;
47
import org.gvsig.fmap.dal.feature.EditableFeature;
48
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
49
import org.gvsig.fmap.dal.feature.EditableFeatureType;
50
import org.gvsig.fmap.dal.feature.Feature;
51
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
52
import org.gvsig.fmap.dal.feature.FeatureSet;
53
import org.gvsig.fmap.dal.feature.FeatureStore;
54
import org.gvsig.fmap.dal.feature.FeatureStoreProviderFactory;
55
import org.gvsig.fmap.dal.feature.FeatureType;
56
import org.gvsig.fmap.dal.store.jdbc.JDBCNewStoreParameters;
57
import org.gvsig.fmap.dal.store.jdbc.JDBCServerExplorer;
58
import org.gvsig.fmap.dal.store.jdbc.JDBCStoreParameters;
59
import org.gvsig.fmap.geom.Geometry;
60
import org.gvsig.fmap.geom.GeometryCoercionContext;
61
import org.gvsig.tools.dispose.DisposableIterator;
62

    
63
/**
64
 * @author gvSIG Team
65
 * @version $Id$
66
 *
67
 */
68
public class ExportJDBCService
69
        extends AbstractExportService
70
        implements ExportService {
71

    
72
    private FeatureType targetFeatureType;
73

    
74
    protected ExportJDBCService(ExportServiceFactory factory, ExportJDBCParameters parameters) {
75
        super(factory, parameters);
76
    }
77

    
78
    @Override
79
    public ExportJDBCParameters getParameters() {
80
        return (ExportJDBCParameters) super.getParameters();
81
    }
82

    
83
    @Override
84
    protected JDBCServerExplorer createServerExplorer() throws ExportException {
85
        try {
86
            DataManager dataManager = DALLocator.getDataManager();
87

    
88
            JDBCServerExplorer explorer = (JDBCServerExplorer) dataManager.openServerExplorer(
89
                    this.getParameters().getExplorerParameters().getExplorerName(),
90
                    this.getParameters().getExplorerParameters()
91
            );
92
            return explorer;
93
        } catch (Exception e) {
94
            throw new ExportException(e);
95
        }
96
    }
97

    
98
    @Override
99
    protected NewDataStoreParameters createTargetNewStoreParameters() throws ExportException {
100
        try {
101
            FeatureType targetTempFeatureType;
102
            EditableFeatureType targetEditableFeatureType;
103

    
104
            JDBCServerExplorer explorer = this.createServerExplorer();
105

    
106
            DataManager manager = DALLocator.getDataManager();
107
            FeatureStoreProviderFactory factory = (FeatureStoreProviderFactory) manager.getStoreProviderFactory(explorer.getStoreName());
108

    
109
            boolean preferNotToUseNonNullRestrictions = factory.preferNotToUseNonNullRestrictions();
110
            ExportAttributes exportAttributes = getParameters().getExportAttributes();
111

    
112

    
113
            targetTempFeatureType = exportAttributes.getTargetFeatureType().getCopy();
114
            targetEditableFeatureType = targetTempFeatureType.getEditable();
115
            targetEditableFeatureType.setHasOID(false);
116

    
117
            // Remove inherited primary keys from the data source and remove NotNull
118
            // restrictions if proceed.
119
            for (int i = 0; i < targetEditableFeatureType.size(); i++) {
120
                EditableFeatureAttributeDescriptor eAttr = (EditableFeatureAttributeDescriptor) targetEditableFeatureType.get(i);
121
                if( eAttr.isPrimaryKey() && factory.allowEditableFeatureType()!=DataStoreProviderFactory.NO) {
122
                    eAttr.setIsPrimaryKey(false);
123
                    eAttr.setAllowNull(false);
124
                } else {
125
                    if (preferNotToUseNonNullRestrictions) {
126
                        eAttr.setAllowNull(true);
127
                    }
128
                }
129
            }
130

    
131

    
132
            String pkname = getParameters().getPrimaryKey();
133
            if (pkname != null) { 
134
                // pkname it's not part of exportattributes list.
135
                pkname = this.getParameters().getExportAttributes().getTargetName(pkname);
136
                EditableFeatureAttributeDescriptor pk = (EditableFeatureAttributeDescriptor) targetEditableFeatureType.get(pkname);
137
                if (pk == null) {
138
                    pkname = getParameters().getExportAttributes().getNamesTranslator().getSuggestion(pkname);
139
                    pk = targetEditableFeatureType.add(pkname, DataTypes.LONG);
140
                    pk.setIsPrimaryKey(true);
141
                    pk.setIsAutomatic(true);
142
                    pk.setIsReadOnly(true);
143
                } else {
144
                    pk.setIsPrimaryKey(true);
145
//                    pk.setIsReadOnly(true);
146
                }
147
            }
148

    
149
            EditableFeatureAttributeDescriptor attrdescriptor = (EditableFeatureAttributeDescriptor) targetEditableFeatureType.getDefaultGeometryAttribute();
150
            if (attrdescriptor != null && this.getParameters().getCreateIndexInGeometryRow()) {
151
                attrdescriptor.setIsIndexed(true);
152
            }
153

    
154
            // ======================================================
155
            // Reprojection: set SRS of geometry field to target SRS
156
            if (attrdescriptor != null) {
157
                attrdescriptor.setSRS(this.getParameters().getTargetProjection());
158
                attrdescriptor.setGeometryType(this.getParameters().getTargetGeometryType());
159
            }
160

    
161
            // ======================================
162
            // Remove index to improve performance
163
            this.targetFeatureType = targetEditableFeatureType.getNotEditableCopy();
164
            if( factory.allowEditableFeatureType()!=DataStoreProviderFactory.NO) {
165
                for (int i = 0; i < targetEditableFeatureType.size(); i++) {
166
                    EditableFeatureAttributeDescriptor x = (EditableFeatureAttributeDescriptor) targetEditableFeatureType.get(i);
167
                    //x.setIsPrimaryKey(false);
168
                    x.setIsIndexed(false);
169
                }
170
            }
171

    
172
            // ======================================
173
            JDBCNewStoreParameters createTableParams = (JDBCNewStoreParameters) explorer.getAddParameters();
174

    
175
            createTableParams.setSelectRole(this.getParameters().getSelectRole());
176
            createTableParams.setInsertRole(this.getParameters().getInsertRole());
177
            createTableParams.setUpdateRole(this.getParameters().getUpdateRole());
178
            createTableParams.setDeleteRole(this.getParameters().getDeleteRole());
179
            createTableParams.setTruncateRole(this.getParameters().getTruncateRole());
180
            createTableParams.setReferenceRole(this.getParameters().getReferenceRole());
181
            createTableParams.setTriggerRole(this.getParameters().getTriggerRole());
182
            createTableParams.setAllRole(this.getParameters().getAllRole());
183

    
184
            createTableParams.setSchema(this.getParameters().getSchema());
185
            createTableParams.setPostCreatingStatement(this.getParameters().getPostCreatingStatement());
186

    
187
            createTableParams.setDefaultFeatureType(targetEditableFeatureType);
188
            createTableParams.setTable(this.getParameters().getTableName());
189

    
190
            return createTableParams;
191

    
192
        } catch (Exception ex) {
193
            throw new ExportException(ex);
194
        }
195
    }
196

    
197
    @Override
198
    public OpenDataStoreParameters createTargetOpenStoreParameters() throws ExportException {
199
        try {
200
            DataManager dataManager = DALLocator.getDataManager();
201
            JDBCServerExplorer explorer = this.createServerExplorer();
202

    
203
            JDBCStoreParameters openStoreParameters = (JDBCStoreParameters) explorer.getOpenParameters();
204
            openStoreParameters.setSchema(this.getParameters().getSchema());
205
            openStoreParameters.setTable(this.getParameters().getTableName());
206
            openStoreParameters.setCRS(this.getParameters().getTargetProjection());
207
            openStoreParameters.setDefaultGeometryField(
208
                    this.getParameters().getTargetFeatureType().getDefaultGeometryAttributeName()
209
            );
210
            return openStoreParameters;
211
        } catch (DataException ex) {
212
            throw new ExportException(ex);
213
        }
214
    }
215

    
216

    
217

    
218
    private int getGeometryColumnCount(FeatureType featureType) {
219
        int count = 0;
220
        for (int i = 0; i < featureType.size(); i++) {
221
            if (featureType.getAttributeDescriptor(i).getType() == DataTypes.GEOMETRY) {
222
                count++;
223
            }
224
        }
225
        return count;
226
    }
227

    
228
    @Override
229
    public void export(FeatureSet featureSet) throws ExportException {
230
        Geometry.ValidationStatus geometryCheck;
231

    
232
        DisposableIterator it = null;
233
        EditableFeature targetFeature = null;
234
        FeatureStore target = null;
235
        Feature feature = null;
236
        DataManager dataManager = DALLocator.getDataManager();
237
        DataTransaction trans = dataManager.createTransaction();
238
        try {
239
            ExportServiceManager serviceManager = ExportLocator.getServiceManager();
240

    
241
            // ======================================
242
            // Reprojection
243
            ICoordTrans coord_trans = this.getParameters().getTransformationToUse();
244
            // ============================================
245

    
246

    
247
            JDBCServerExplorer explorer = this.createServerExplorer();
248
            trans.add(explorer);
249

    
250
            if (this.getParameters().canCreatetable()) {
251
                LOG.debug("Creating table");
252
                getTaskStatus().message("Creating table");
253
                NewDataStoreParameters targetNewStoreParameters = this.createTargetNewStoreParameters();
254
                explorer.add(
255
                        targetNewStoreParameters.getDataStoreName(),
256
                        targetNewStoreParameters,
257
                        true
258
                );
259
                
260
                //We collect the name of the table of targetNewStoreParameters 
261
                //because the provider has been able to make changes to it
262
                this.getParameters().setTableName(((JDBCNewStoreParameters)targetNewStoreParameters).getTable());
263
            }
264

    
265
            JDBCStoreParameters openParams = (JDBCStoreParameters) this.createTargetOpenStoreParameters();
266
            try {
267
                 LOG.info("Start export "+Objects.toString(openParams));
268
            } catch (Throwable t){
269
                 LOG.info("Start export");              
270
            }
271
            target = (FeatureStore) explorer.open(openParams);
272

    
273
            FeatureType theTargetFeatureType = target.getDefaultFeatureType();
274
            FeatureType theSourceFeatureType = featureSet.getDefaultFeatureType();
275
            
276
            if (!this.getParameters().canCreatetable() && this.getParameters().isDeleteRows()) {
277
                Expression filter = this.getParameters().getDeleteRowsFilter();
278
                if(ExpressionUtils.isPhraseEmpty(filter)){
279
                    filter = ExpressionUtils.createExpression("1=1");
280
                }
281
                target.edit(FeatureStore.MODE_PASS_THROUGH);
282
                target.delete(filter);
283
                target.finishEditing();
284
                
285
            }
286
            
287

    
288
            target.edit(FeatureStore.MODE_APPEND);
289

    
290
            long featureCount = 1;
291
            getTaskStatus().setRangeOfValues(1, featureSet.getSize());
292

    
293
            int targetGeometryIndex = -1;
294
            int sourceGeometryIndex = -1;
295
            if (getGeometryColumnCount(theSourceFeatureType) == 1
296
                    && getGeometryColumnCount(theTargetFeatureType) == 1) {
297
                // Si solo hay una columna de geometria asignaremos las geometrias
298
                // independientemente de como se llamen los campos.
299
                targetGeometryIndex = theTargetFeatureType.getDefaultGeometryAttributeIndex();
300
                sourceGeometryIndex = theSourceFeatureType.getDefaultGeometryAttributeIndex();
301
            } else {
302
                FeatureAttributeDescriptor attr = theSourceFeatureType.getDefaultGeometryAttribute();
303
                if (attr!=null && theTargetFeatureType.getAttributeDescriptor(attr.getName())!=null) {
304
                    sourceGeometryIndex = attr.getIndex();
305
                    targetGeometryIndex = theTargetFeatureType.getAttributeDescriptor(attr.getName()).getIndex();
306
                }
307
            }
308

    
309
            if(targetGeometryIndex != -1){
310
                GeometryCoercionContext coercionContext = (GeometryCoercionContext) theTargetFeatureType.getAttributeDescriptor(targetGeometryIndex).getCoercionContext();
311
                if(coercionContext!=null){
312
                    coercionContext.setMode(GeometryCoercionContext.MODE_ONERROR_NULL);
313
                }
314
            }
315
            LOG.debug("Inserting rows");
316
            getTaskStatus().message("Inserting rows");
317
            it = featureSet.fastIterator();
318
            while (it.hasNext()) {
319
                feature = (Feature) it.next();
320

    
321
                targetFeature = target.createNewFeature(theTargetFeatureType, true);
322
                targetFeature.copyFrom(feature);
323
                for (int i = 0; i < theSourceFeatureType.size(); i++) {
324
                    if (i == sourceGeometryIndex) {
325
                        // Es facil que los campos geometria no se llamen igual, asi que
326
                        // el campo geometria lo asignamos a capon.
327
                        // Esto puede ocasionar problemas cuando la tabla destino no tenga
328
                        // geometria o tenga mas de una.
329
                        targetFeature.set(targetGeometryIndex, feature.get(sourceGeometryIndex));
330
                    } else {
331
                        FeatureAttributeDescriptor sourceField = theSourceFeatureType.getAttributeDescriptor(i);
332
//                        String name = getTranslatedIdentifier(x.getName());
333
                        if (!this.getParameters().getExportAttributes().getExportAttribute(sourceField.getName()).isExported()) {
334
                            continue;
335
                        }
336
                        String targetField = this.getParameters().getExportAttributes().getTargetName(sourceField.getName());
337
                        int targetAttributeIndex = theTargetFeatureType.getIndex(targetField);
338
                        if (targetAttributeIndex < 0 ) {
339
                            continue;
340
                            //throw new RuntimeException("Can't locate column '" + x.getName() + "' in the target table.");
341
                        }
342
                        if (theTargetFeatureType.getAttributeDescriptor(targetField).isReadOnly() ) {
343
                            continue;
344
                        }
345
                        targetFeature.set(targetAttributeIndex, feature.get(sourceField.getName()));
346
                    }
347
                }
348

    
349
                if (targetGeometryIndex!=-1) {
350
                    Geometry geometry = targetFeature.getGeometry(targetGeometryIndex);
351
                
352
                    FixGeometryStatus check = serviceManager.fixGeometry(getParameters(), coord_trans, geometry);
353
                    switch (check.getState()) {
354
                        case FixGeometryStatus.STATE_OK:
355
                            targetFeature.setDefaultGeometry(check.getGeometry());
356
                            break;
357
                        case FixGeometryStatus.STATE_SKIP:
358
                            continue;
359
                        case FixGeometryStatus.STATE_ABORT:
360
                            throw new InvalidGeometryException(targetFeature, check.getMessage());
361
                    }
362
                }
363

    
364
                target.insert(targetFeature);
365

    
366
                this.getTaskStatus().incrementCurrentValue();
367
                if (this.getTaskStatus().isCancellationRequested()) {
368
                    return;
369
                }
370
                featureCount++;
371
            }
372
            String msgRowCount = MessageFormat.format(" ({0,number, #,###} rows)", featureCount);
373
            targetFeature = null;
374
            getTaskStatus().setIndeterminate();
375
            LOG.debug("Finish editing" + msgRowCount);
376
            if (featureCount > 50000) {
377
                getTaskStatus().message("Finishing insertion of records, may take a while" + msgRowCount);
378
            } else {
379
                getTaskStatus().message("Finishing insertion of records" + msgRowCount);
380
            }
381
            target.finishEditing();
382

    
383
            if (this.getParameters().canCreatetable() && ((FeatureStoreProviderFactory)target.getProviderFactory()).allowEditableFeatureType()!=DataStoreProviderFactory.NO) {
384
                getTaskStatus().message("Preparing the update of the indices" + msgRowCount);
385
                target.edit();
386
                EditableFeatureType ft = target.getDefaultFeatureType().getEditable();
387
                for (FeatureAttributeDescriptor attr : this.targetFeatureType) {
388
                    EditableFeatureAttributeDescriptor attr2 = (EditableFeatureAttributeDescriptor) ft.getAttributeDescriptor(attr.getName());
389
                    if (attr2 != null) {
390
                        if( attr2.isPrimaryKey() ) {
391
                            attr2.setAllowNull(false);
392
                        }
393
                        //attr2.setIsPrimaryKey(attr.isPrimaryKey()); ????
394
                        attr2.setIsIndexed(attr.isIndexed());
395
                        attr2.setIsAutomatic(attr.isAutomatic());
396
                        attr2.setIsReadOnly(attr.isReadOnly());
397
                    }
398
                }
399
                target.update(ft);
400
                getTaskStatus().message("Updating the indices" + msgRowCount);
401
                target.finishEditing();
402
            }
403
            if (this.getParameters().getUpdateTableStatistics()) {
404
                LOG.debug("Updating statistics");
405
                getTaskStatus().message("Updating statistics" + msgRowCount);
406
                explorer.updateTableStatistics(
407
                        openParams.getDBName(),
408
                        openParams.getSchema(),
409
                        openParams.getTable()
410
                );
411
            }
412
            LOG.info("Finish export");
413
            trans.commit();
414
            getTaskStatus().message("Exportation finished");
415
            getTaskStatus().terminate();
416

    
417
        } catch (Exception e) {
418
            LOG.warn("Can't export data.", e);
419
            trans.rollbackQuietly();
420
            getTaskStatus().message("Problems exporting data");
421
            throw new ExportException(e, targetFeature);
422

    
423
        } finally {
424
            if (it != null) {
425
                it.dispose();
426
            }
427
            featureSet.dispose();
428
            if (target != null) {
429
                if (target.isAppending()) {
430
                    try {
431
                        target.cancelEditing();
432
                    } catch (Exception ex) {
433
                        LOG.warn("Can't cancel editing.", ex);
434
                    }
435
                }
436
                target.dispose();
437
            }
438
            DataTransaction.close(trans);
439
            this.getTaskStatus().terminate();
440
            this.getTaskStatus().remove();
441
        }
442
    }
443

    
444
}