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 | 40559 | jjdelcerro | /**
|
---|---|---|---|
2 | * gvSIG. Desktop Geographic Information System.
|
||
3 | 40435 | jjdelcerro | *
|
4 | 40559 | jjdelcerro | * Copyright (C) 2007-2013 gvSIG Association.
|
5 | 40435 | jjdelcerro | *
|
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 | 40559 | jjdelcerro | * as published by the Free Software Foundation; either version 3
|
9 | 40435 | jjdelcerro | * 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 | 40559 | jjdelcerro | * For any additional information, do not hesitate to contact us
|
22 | * at info AT gvsig.com, or visit our website www.gvsig.com.
|
||
23 | 40435 | jjdelcerro | */
|
24 | 43925 | jjdelcerro | package org.gvsig.export.jdbc.service; |
25 | 40435 | jjdelcerro | |
26 | 43925 | jjdelcerro | import java.text.MessageFormat; |
27 | import org.apache.commons.lang3.StringUtils; |
||
28 | import org.cresques.cts.ICoordTrans; |
||
29 | import org.cresques.cts.IProjection; |
||
30 | 40435 | jjdelcerro | |
31 | import org.gvsig.fmap.dal.exception.DataException; |
||
32 | 43504 | jjdelcerro | import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor; |
33 | import org.gvsig.fmap.dal.feature.EditableFeatureType; |
||
34 | 43925 | jjdelcerro | 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 | 43504 | jjdelcerro | import org.gvsig.fmap.dal.feature.Feature; |
42 | import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor; |
||
43 | 43925 | jjdelcerro | import org.gvsig.fmap.dal.feature.FeatureSet; |
44 | 40435 | jjdelcerro | import org.gvsig.fmap.dal.feature.FeatureStore; |
45 | 43925 | jjdelcerro | 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 | 40435 | jjdelcerro | |
59 | /**
|
||
60 | * @author gvSIG Team
|
||
61 | * @version $Id$
|
||
62 | *
|
||
63 | */
|
||
64 | 43925 | jjdelcerro | public class ExportJDBCService |
65 | extends AbstractExportService
|
||
66 | implements ExportService
|
||
67 | { |
||
68 | 40435 | jjdelcerro | |
69 | 43925 | jjdelcerro | 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 | 43504 | jjdelcerro | |
79 | 43925 | jjdelcerro | protected ExportJDBCService(ExportServiceFactory factory, ExportJDBCParameters parameters) {
|
80 | super(factory, parameters);
|
||
81 | } |
||
82 | 40435 | jjdelcerro | |
83 | 43925 | jjdelcerro | @Override
|
84 | public ExportJDBCParameters getParameters() {
|
||
85 | return (ExportJDBCParameters) super.getParameters(); |
||
86 | 40435 | jjdelcerro | } |
87 | |||
88 | 43364 | jjdelcerro | @Override
|
89 | 43925 | jjdelcerro | 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 | 43504 | jjdelcerro | } |
128 | } |
||
129 | 43925 | jjdelcerro | |
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 | 43504 | jjdelcerro | } |
200 | 40435 | jjdelcerro | } |
201 | |||
202 | 43364 | jjdelcerro | @Override
|
203 | 43925 | jjdelcerro | 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 | 43364 | jjdelcerro | } |
220 | |||
221 | 43925 | jjdelcerro | 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 | 40435 | jjdelcerro | } |
234 | 43504 | jjdelcerro | |
235 | 43925 | jjdelcerro | 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 | 43504 | jjdelcerro | @Override
|
245 | 43925 | jjdelcerro | 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 | 43504 | jjdelcerro | } |
337 | } |
||
338 | 43925 | jjdelcerro | |
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 | 43504 | jjdelcerro | } |
358 | 43925 | jjdelcerro | 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 | 43504 | jjdelcerro | } |
421 | } |
||
422 | 43925 | jjdelcerro | |
423 | 40435 | jjdelcerro | } |