Revision 46543

View differences:

trunk/org.gvsig.desktop/org.gvsig.desktop.compat.cdc/org.gvsig.fmap.dal/org.gvsig.fmap.dal.db/org.gvsig.fmap.dal.db.jdbc/src/main/java/org/gvsig/fmap/dal/store/jdbc/JDBCStoreProviderWriter.java
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.fmap.dal.store.jdbc;
25

  
26
import java.sql.Connection;
27
import java.sql.PreparedStatement;
28
import java.sql.SQLException;
29
import java.sql.Statement;
30
import java.util.ArrayList;
31
import java.util.Arrays;
32
import java.util.Iterator;
33
import java.util.List;
34
import org.apache.commons.io.IOUtils;
35

  
36
import org.gvsig.fmap.dal.exception.DataException;
37
import org.gvsig.fmap.dal.exception.InitializeException;
38
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
39
import org.gvsig.fmap.dal.feature.FeatureRules;
40
import org.gvsig.fmap.dal.feature.FeatureType;
41
import org.gvsig.fmap.dal.feature.FeatureType.FeatureTypeChanged;
42
import org.gvsig.fmap.dal.feature.exception.PerformEditingException;
43
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
44
import org.gvsig.fmap.dal.feature.spi.FeatureReferenceProviderServices;
45
import org.gvsig.fmap.dal.spi.DataStoreProviderServices;
46
import org.gvsig.fmap.dal.store.db.FeatureTypeHelper;
47
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCExecutePreparedSQLException;
48
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCExecuteSQLException;
49
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCPreparingSQLException;
50
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCSQLException;
51
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCUpdateWithoutChangesException;
52
import org.gvsig.fmap.dal.store.jdbc2.JDBCUtils;
53
import org.gvsig.tools.dynobject.DynObject;
54
import org.slf4j.Logger;
55
import org.slf4j.LoggerFactory;
56

  
57
/**
58
 * @author jmvivo
59
 *
60
 */
61
public class JDBCStoreProviderWriter extends JDBCStoreProvider {
62

  
63
	final static private Logger logger = LoggerFactory
64
			.getLogger(JDBCStoreProviderWriter.class);
65

  
66
        protected Appender appender;
67

  
68
	public JDBCStoreProviderWriter(JDBCStoreParameters params,
69
			DataStoreProviderServices storeServices)
70
			throws InitializeException {
71
		super(params, storeServices);
72
                this.appender = this.createAppender();
73
	}
74

  
75
	protected JDBCStoreProviderWriter(JDBCStoreParameters params,
76
			DataStoreProviderServices storeServices, DynObject metadata)
77
			throws InitializeException {
78
		super(params, storeServices, metadata);
79
                this.appender = this.createAppender();
80
	}
81

  
82
        protected Appender createAppender() {
83
            return new JDBCAppender(this);
84
        }
85

  
86
        public boolean supportsAppendMode() {
87
            return true;
88
        }
89

  
90
        public void endAppend() throws DataException {
91
            this.appender.end();
92
        }
93

  
94
        public void beginAppend() throws DataException {
95
            this.appender.begin();
96
        }
97

  
98
        public void append(final FeatureProvider featureProvider) throws DataException {
99
            this.appender.append(featureProvider);
100
        }
101

  
102
	protected void addToListFeatureValues(FeatureProvider featureProvider,
103
			FeatureAttributeDescriptor attrOfList,
104
			FeatureAttributeDescriptor attr, List<Object> values) throws DataException {
105
		if (attr == null) {
106
			if (attrOfList.isPrimaryKey()) {
107
				throw new RuntimeException("pk attribute '"
108
						+ attrOfList.getName() + "' not found in feature");
109
			}
110
			values.add(helper
111
					.dalValueToJDBC(attr, attrOfList.getDefaultValue()));
112
		} else {
113
			values.add(helper.dalValueToJDBC(attr, featureProvider.get(attr
114
					.getIndex())));
115
		}
116

  
117
	}
118

  
119
	protected void addToListFeatureValues(FeatureProvider featureProvider,
120
			List<FeatureAttributeDescriptor> attributes, List<Object> values) throws DataException {
121
		FeatureAttributeDescriptor attr, attrOfList;
122
		FeatureType fType = featureProvider.getType();
123
		for (int i = 0; i < attributes.size(); i++) {
124
			attrOfList = (FeatureAttributeDescriptor) attributes.get(i);
125
			attr = fType.getAttributeDescriptor(attrOfList.getName());
126
			addToListFeatureValues(featureProvider, attrOfList, attr, values);
127
		}
128
	}
129

  
130
	protected void appendToSQLPreparedPkWhereClause(StringBuilder sql,
131
			List<FeatureAttributeDescriptor> pkAttributes) {
132
		sql.append(" Where ");
133
		FeatureAttributeDescriptor attr;
134
		for (int i = 0; i < pkAttributes.size() - 1; i++) {
135
			attr = (FeatureAttributeDescriptor) pkAttributes.get(i);
136
			sql.append(helper.escapeFieldName(attr.getName()));
137
			sql.append(" = ? AND ");
138
		}
139
		attr = (FeatureAttributeDescriptor) pkAttributes.get(pkAttributes
140
				.size() - 1);
141
		sql.append(helper.escapeFieldName(attr.getName()));
142
		sql.append(" = ? ");
143
	}
144

  
145
	protected void executeRemovePreparedStatement(Connection conn, String sql,
146
			List<FeatureAttributeDescriptor> attributes, Iterator<FeatureReferenceProviderServices> featureReferences) throws DataException {
147
				PreparedStatement st;
148
				try {
149
					st = conn.prepareStatement(sql);
150
				} catch (SQLException e) {
151
					throw new JDBCPreparingSQLException(sql, e);
152
				}
153
				try {
154
					List<Object> values = new ArrayList<Object>();
155
					FeatureReferenceProviderServices featureRef;
156
//					FeatureType featureType;
157
					while (featureReferences.hasNext()) {
158
						st.clearParameters();
159
						featureRef = featureReferences.next();
160
						values.clear();
161
//						featureType = this.getFeatureStore()
162
//							.getFeatureType(featureRef.getFeatureTypeId());
163

  
164
						Iterator<FeatureAttributeDescriptor> iter = attributes.iterator();
165
						FeatureAttributeDescriptor attr;
166
						while (iter.hasNext()) {
167
							attr =  iter.next();
168
							values.add( helper.dalValueToJDBC(attr, featureRef
169
									.getKeyValue(attr.getName())));
170
						}
171

  
172
						for (int i = 0; i < values.size(); i++) {
173
							st.setObject(i + 1, values.get(i));
174
						}
175
						try {
176
							int nAffected =JDBCHelper.executeUpdate(st);
177
							if (nAffected == 0) {
178
								throw new JDBCUpdateWithoutChangesException(sql, values);
179
							}
180
							if (nAffected > 1){
181
								logger.warn("Remove statement affectst to {} rows: {}",
182
										nAffected, sql);
183
							}
184

  
185
						} catch (SQLException e) {
186
							throw new JDBCExecutePreparedSQLException(sql, values, e);
187
						}
188

  
189
					}
190
				} catch (SQLException e) {
191
					throw new JDBCSQLException(e);
192
				} finally {
193
                                    JDBCUtils.closeQuietly(st);
194
				}
195

  
196
			}
197

  
198
	protected void executeUpdatePreparedStatement(Connection conn, String sql,
199
			List<FeatureAttributeDescriptor> attributes, Iterator<FeatureProvider> featureProviders) throws DataException {
200
				PreparedStatement st;
201
				try {
202
					st = conn.prepareStatement(sql);
203
				} catch (SQLException e) {
204
					throw new JDBCPreparingSQLException(sql, e);
205
				}
206
				try {
207
					List<Object> values = new ArrayList<Object>();
208
					FeatureProvider featureProvider;
209
					while (featureProviders.hasNext()) {
210
						st.clearParameters();
211
						featureProvider = (FeatureProvider) featureProviders.next();
212
						values.clear();
213
						addToListFeatureValues(featureProvider, attributes, values);
214
						for (int i = 0; i < values.size(); i++) {
215
							st.setObject(i + 1, values.get(i));
216
						}
217
						try {
218
							if ( JDBCHelper.executeUpdate(st) == 0) {
219
								throw new JDBCUpdateWithoutChangesException(sql, values);
220
							}
221
						} catch (SQLException e) {
222
							throw new JDBCExecutePreparedSQLException(sql, values, e);
223
						}
224

  
225
					}
226
				} catch (SQLException e) {
227
					throw new JDBCSQLException(e,sql);
228
				} finally {
229
                                    JDBCUtils.closeQuietly(st);
230
				}
231

  
232
			}
233

  
234
	protected void performDeletes(Connection conn, Iterator<FeatureReferenceProviderServices> deleteds, List<FeatureAttributeDescriptor> pkAttributes)
235
			throws DataException {
236

  
237
				if (pkAttributes.size() < 0) {
238
					throw new RuntimeException("Operation requires missing pk");
239
				}
240

  
241
				// ************ Prepare SQL ****************
242
				StringBuilder sqlb = new StringBuilder();
243
				sqlb.append("Delete from ");
244
				sqlb.append(getJDBCParameters().tableID());
245
				appendToSQLPreparedPkWhereClause(sqlb, pkAttributes);
246
				String sql = sqlb.toString();
247
				// ************ Prepare SQL (end) ****************
248

  
249
				executeRemovePreparedStatement(conn, sql, pkAttributes, deleteds);
250
			}
251

  
252
	protected String getSqlStatementAddField(FeatureAttributeDescriptor attr,
253
			List<String> additionalStatement) throws DataException {
254
		StringBuilder strb = new StringBuilder();
255
		strb.append("ADD ");
256
		strb.append(this.helper.getSqlFieldDescription(attr));
257
		return strb.toString();
258
	}
259

  
260
	protected String getSqlStatementDropField(FeatureAttributeDescriptor attr,List<String> additionalStatement) {
261
		// DROP [ COLUMN ] column
262
		return " DROP COLUMN "
263
				+ this.helper.escapeFieldName(attr.getName());
264

  
265
	}
266

  
267
	protected List<String> getSqlStatementAlterField(
268
			FeatureAttributeDescriptor attrOrg,
269
			FeatureAttributeDescriptor attrTrg, List<String> additionalStatement)
270
			throws DataException {
271
		//
272
		List<String> actions = new ArrayList<String>();
273
		StringBuilder strb;
274
		if (attrOrg.getDataType() != attrTrg.getDataType()) {
275
			// ALTER COLUMN {col} TYPE {type} character varying(35)
276
			strb = new StringBuilder();
277
			strb.append("ALTER COLUMN ");
278
			strb.append(helper.escapeFieldName(attrTrg.getName()));
279
			strb.append(" ");
280
			strb.append(helper.getSqlColumnTypeDescription(attrTrg));
281

  
282
			actions.add(strb.toString());
283
		}
284

  
285
		if (attrOrg.allowNull() != attrTrg.allowNull()) {
286
			// ALTER [ COLUMN ] column { SET | DROP } NOT NULL
287

  
288
			strb = new StringBuilder();
289
			strb.append("ALTER COLUMN ");
290
			strb.append(helper.escapeFieldName(attrTrg.getName()));
291
			strb.append(' ');
292
			if (attrTrg.allowNull()) {
293
				strb.append("SET ");
294
			} else {
295
				strb.append("DROP ");
296
			}
297
			strb.append("NOT NULL");
298
			actions.add(strb.toString());
299
		}
300

  
301
		if (attrOrg.getDefaultValue() != attrTrg.getDefaultValue()) {
302
			if (attrTrg.getDefaultValue() == null) {
303
				// ALTER [ COLUMN ] column DROP DEFAULT
304

  
305
				strb = new StringBuilder();
306
				strb.append("ALTER COLUMN ");
307
				strb.append(helper.escapeFieldName(attrTrg.getName()));
308
				strb.append(" DROP DEFAULT");
309
				actions.add(strb.toString());
310
			} else if (!attrTrg.getDefaultValue().equals(
311
					attrOrg.getDefaultValue())) {
312
				// ALTER [ COLUMN ] column DROP DEFAULT
313

  
314
				strb = new StringBuilder();
315
				strb.append("ALTER COLUMN ");
316
				strb.append(helper.escapeFieldName(attrTrg.getName()));
317
				strb.append(" SET DEFAULT");
318
				strb.append(helper.dalValueToJDBC(attrTrg, attrTrg
319
						.getDefaultValue()));
320
				actions.add(strb.toString());
321
			}
322
		}
323

  
324
		return actions;
325
	}
326

  
327
	protected void performUpdateTable(Connection conn, FeatureType original,
328
			FeatureType target) throws DataException {
329

  
330
		/*
331
		 *
332
		 * ALTER TABLE [ ONLY ] name [ * ] action [, ... ]
333
		 */
334

  
335
		List<String> toDrop = new ArrayList<String>();
336
		List<String> toAdd = new ArrayList<String>();
337
		List<String> toAlter = new ArrayList<String>();
338

  
339
		List<String> additionalStatement = new ArrayList<String>();
340

  
341
		FeatureAttributeDescriptor attrOrg;
342
		FeatureAttributeDescriptor attrTrg;
343
		Iterator<FeatureAttributeDescriptor> attrs = FeatureTypeHelper.iterator(original);
344
		while (attrs.hasNext()) {
345
			attrOrg = (FeatureAttributeDescriptor) attrs.next();
346
			attrTrg = target.getAttributeDescriptor(attrOrg.getName());
347
			if (attrTrg == null) {
348
				toDrop.add(getSqlStatementDropField(attrOrg,
349
						additionalStatement));
350
			} else {
351
				toAlter.addAll(getSqlStatementAlterField(attrOrg, attrTrg,additionalStatement));
352
			}
353

  
354
		}
355
		attrs = FeatureTypeHelper.iterator(target);
356
		while (attrs.hasNext()) {
357
			attrTrg = (FeatureAttributeDescriptor) attrs.next();
358
			if (original.getAttributeDescriptor(attrTrg.getName()) == null) {
359
				toAdd.add(getSqlStatementAddField(attrTrg,
360
								additionalStatement));
361
			}
362
		}
363

  
364
		StringBuilder sqlb = new StringBuilder();
365

  
366
		sqlb.append("ALTER TABLE ");
367
		sqlb.append(getJDBCParameters().tableID());
368
		sqlb.append(' ');
369

  
370
		List<String> actions = new ArrayList<String>();
371
		actions.addAll(toDrop);
372
		actions.addAll(toAlter);
373
		actions.addAll(toAdd);
374

  
375
		Iterator<String> it = actions.iterator();
376
		while (it.hasNext()) {
377
			if (it.next() == null) {
378
				it.remove();
379
			}
380
		}
381

  
382
		it = additionalStatement.iterator();
383
		while (it.hasNext()) {
384
			if (it.next() == null) {
385
				it.remove();
386
			}
387
		}
388

  
389
		if (actions.size() < 1) {
390
			return;
391
		}
392

  
393
		helper.stringJoin(actions, ", ", sqlb);
394

  
395
		String sql = sqlb.toString();
396

  
397
		Statement st = null;
398

  
399
		try {
400
			st = conn.createStatement();
401
		} catch (SQLException e1) {
402
			throw new JDBCSQLException(e1,sql);
403
		}
404
		try {
405
			JDBCHelper.execute(st, sql);
406
			Iterator<String> iter = additionalStatement.iterator();
407
			while (iter.hasNext()) {
408
				sql = (String) iter.next();
409
                                JDBCHelper.execute(st, sql);
410
			}
411
		} catch (SQLException e1) {
412
			throw new JDBCExecuteSQLException(sql, e1);
413
		} finally {
414
			try {
415
				st.close();
416
			} catch (Exception e) {
417
				logger.error("Exception closing statement", e);
418
			}
419
			;
420
		}
421

  
422
	}
423

  
424

  
425
	public void perfomInsert(Connection conn, PreparedStatement insertSt,
426
			String sql, FeatureProvider feature, List<FeatureAttributeDescriptor> attributes)
427
			throws DataException {
428

  
429
		try {
430
			insertSt.clearParameters();
431
			List<Object> values = new ArrayList<Object>();
432
			addToListFeatureValues(feature, attributes, values);
433
//			FeatureAttributeDescriptor attr;
434
			int j = 1;
435
			for (int i = 0; i < values.size(); i++) {
436
				insertSt.setObject(j, values.get(i));
437
				j++;
438
			}
439
			if (logger.isDebugEnabled()) {
440
				logger.debug("Executing insert. sql={} value={}", new Object[] {
441
						sql, values });
442
			}
443
			try {
444
                                JDBCHelper.execute(insertSt, sql);
445
			} catch (SQLException e) {
446
				throw new JDBCExecutePreparedSQLException(sql, values, e);
447
			}
448

  
449
		} catch (Exception e1) {
450
			throw new JDBCExecuteSQLException(sql, e1);
451
		}
452
	}
453

  
454

  
455
	protected void prepareAttributeForUpdate(FeatureAttributeDescriptor attr,
456
			List<String> values) {
457
		values.add(helper.escapeFieldName(attr.getName()) + " = ?");
458
	}
459

  
460
	protected void prepareAttributeForInsert(FeatureAttributeDescriptor attr,
461
			List<String> fields, List<String> values) {
462

  
463
		fields.add(helper.escapeFieldName(attr.getName()));
464
		values.add("?");
465

  
466
	}
467

  
468

  
469
	protected void prepareSQLAndAttributeListForInsert(StringBuilder sqlb,
470
			List<FeatureAttributeDescriptor> attributes) throws DataException {
471
		/*
472
		 * INSERT INTO table [ ( column [, ...] ) ] { DEFAULT VALUES | VALUES (
473
		 * { expression | DEFAULT } [, ...] ) [, ...] | query } [ RETURNING * |
474
		 * output_expression [ AS output_name ] [, ...] ]
475
		 */
476

  
477
		sqlb.append("INSERT INTO ");
478
		sqlb.append(getJDBCParameters().tableID());
479

  
480
		sqlb.append(" (");
481

  
482
		FeatureType type = this.getFeatureStore().getDefaultFeatureType();
483

  
484
		List<String> fields = new ArrayList<String>();
485
		List<String> values = new ArrayList<String>();
486

  
487
		Iterator<FeatureAttributeDescriptor> iter = FeatureTypeHelper.iterator(type);
488
		FeatureAttributeDescriptor attr;
489
		while (iter.hasNext()) {
490
			attr = iter.next();
491
			if (attr.isAutomatic() || attr.isReadOnly()) {
492
				continue;
493
			}
494
			attributes.add(attr);
495
			prepareAttributeForInsert(attr, fields, values);
496

  
497
		}
498
		if (attributes.size() < 1) {
499
			throw new RuntimeException("no fields to set");
500
		}
501

  
502
		helper.stringJoin(fields, ", ", sqlb);
503

  
504
		sqlb.append(") VALUES (");
505
		helper.stringJoin(values, ", ", sqlb);
506

  
507
		sqlb.append(") ");
508

  
509
	}
510

  
511

  
512
	protected void performInserts(Connection conn, Iterator<FeatureProvider> inserteds)
513
			throws DataException {
514

  
515
		StringBuilder sqlb = new StringBuilder();
516
		List<FeatureAttributeDescriptor> attrs = new ArrayList<FeatureAttributeDescriptor>();
517

  
518
		prepareSQLAndAttributeListForInsert(sqlb, attrs);
519

  
520
		String sql = sqlb.toString();
521
		PreparedStatement st;
522
		try {
523
			st = conn.prepareStatement(sql);
524
		} catch (SQLException e) {
525
			throw new JDBCPreparingSQLException(sql, e);
526
		}
527
		try {
528
			while (inserteds.hasNext()) {
529
				perfomInsert(conn, st, sql, inserteds.next(),
530
						attrs);
531
			}
532
		} finally {
533
			try {st.close();} catch (SQLException e) {logger.error("Error closing statement", e);};
534
		}
535
	}
536

  
537
	protected void performUpdates(Connection conn, Iterator<FeatureProvider> updateds,
538
			List<FeatureAttributeDescriptor> pkAttributes) throws DataException {
539
		/*
540
		 * UPDATE [ ONLY ] table [ [ AS ] alias ] SET { column = { expression |
541
		 * DEFAULT } | ( column [, ...] ) = ( { expression | DEFAULT } [, ...] )
542
		 * } [, ...] [ FROM fromlist ] [ WHERE condition ] [ RETURNING * |
543
		 * output_expression [ AS output_name ] [, ...] ]
544
		 */
545

  
546
		if (pkAttributes.size() < 0) {
547
			throw new RuntimeException("Operation requires missing pk");
548
		}
549

  
550
		// ************ Prepare SQL ****************
551

  
552
		StringBuilder sqlb = new StringBuilder();
553
		sqlb.append("UPDATE ");
554
		sqlb.append(getJDBCParameters().tableID());
555

  
556
		sqlb.append(" SET ");
557

  
558
		List<String> values = new ArrayList<String>();
559

  
560
		FeatureType type = this.getFeatureStore().getDefaultFeatureType();
561

  
562
		Iterator<FeatureAttributeDescriptor> iter = FeatureTypeHelper.iterator(type);
563
		FeatureAttributeDescriptor attr;
564
		List<FeatureAttributeDescriptor> updateAttrs = new ArrayList<FeatureAttributeDescriptor>();
565
		while (iter.hasNext()) {
566
			attr = iter.next();
567
			if (attr.isPrimaryKey() || attr.isAutomatic() || attr.isReadOnly()) {
568
				continue;
569
			}
570
			updateAttrs.add(attr);
571
			prepareAttributeForUpdate(attr, values);
572

  
573
		}
574
		if (updateAttrs.size() < 1) {
575
			throw new RuntimeException("no fields to set");
576
		}
577

  
578
		helper.stringJoin(values, ", ", sqlb);
579

  
580
		sqlb.append(' ');
581
		appendToSQLPreparedPkWhereClause(sqlb, pkAttributes);
582

  
583
		String sql = sqlb.toString();
584
		// ************ Prepare SQL (end) ****************
585

  
586
		updateAttrs.addAll(pkAttributes);
587

  
588
		executeUpdatePreparedStatement(conn, sql, updateAttrs, updateds);
589
	}
590

  
591

  
592

  
593
	protected TransactionalAction getPerformChangesAction(
594
			final Iterator<FeatureReferenceProviderServices> deleteds, 
595
			final Iterator<FeatureProvider> inserteds,
596
			final Iterator<FeatureProvider> updateds, 
597
			final Iterator<FeatureTypeChanged> featureTypesChanged) {
598

  
599
		TransactionalAction action = new TransactionalAction() {
600

  
601
			public Object action(Connection conn) throws DataException {
602

  
603
				if (featureTypesChanged.hasNext()) {
604

  
605
					FeatureTypeChanged item = featureTypesChanged.next();
606
					performUpdateTable(conn, item.getSource(), item.getTarget());
607
				}
608

  
609
				List<FeatureAttributeDescriptor> pkAttributes = null;
610
				if (deleteds.hasNext() || updateds.hasNext()) {
611
					pkAttributes = Arrays.asList(getFeatureStore()
612
							.getDefaultFeatureType()
613
							.getPrimaryKey());
614
				}
615

  
616
				if (deleteds.hasNext()) {
617
					performDeletes(conn, deleteds, pkAttributes);
618
				}
619

  
620
				if (updateds.hasNext()) {
621
					performUpdates(conn, updateds, pkAttributes);
622
				}
623

  
624
				if (inserteds.hasNext()) {
625
					performInserts(conn, inserteds);
626
				}
627

  
628
				return null;
629
			}
630

  
631
			public boolean continueTransactionAllowed() {
632
				return false;
633
			}
634

  
635
		};
636

  
637
		return action;
638

  
639
	}
640

  
641
	@SuppressWarnings("unchecked")
642
	public void performChanges(Iterator deleteds, Iterator inserteds,
643
			Iterator updateds, Iterator featureTypesChanged)
644
			throws PerformEditingException {
645

  
646
		boolean countChanged = deleteds.hasNext() || inserteds.hasNext();
647

  
648
		try {
649
			this.helper.doConnectionAction(getPerformChangesAction(deleteds,
650
					inserteds, updateds, featureTypesChanged));
651

  
652
			/*
653
			 * Get rules before initializing feature type
654
			 */
655
			FeatureRules old_rules = getFeatureStore().getDefaultFeatureType().getRules();
656
			
657
			/*
658
			 * This initialization loses the feature type rules
659
			 */
660
			this.initFeatureType();
661
			
662
			/*
663
			 * Get new feature type, clear rules and add
664
			 * the ones saved previously
665
			 */
666
			FeatureType ft = getFeatureStore().getDefaultFeatureType();
667
			FeatureRules new_rules = ft.getRules();
668
			new_rules.clear();
669
			for (int i=0; i<old_rules.size(); i++) {
670
			    new_rules.add(old_rules.getRule(i));
671
			}
672
			// ===================================================
673
			
674
			if (countChanged) {
675
				resetCount();
676
			}
677

  
678
		} catch (Exception e) {
679
			throw new PerformEditingException(this.getSourceId().toString(), e);
680
		}
681
	}
682

  
683

  
684
	public boolean allowWrite() {
685
		if (directSQLMode) {
686
			return false;
687
		}
688
		
689
        FeatureType ft = null;
690
        try {
691
            ft = this.getFeatureStore().getDefaultFeatureType();
692
        } catch (DataException e) {
693
            logger.error("While getting default Feature Type", e);
694
        }
695
        
696
        String[] storePK = getPK(ft);
697
        JDBCHelper helper = this.getHelper();
698
        String[] dbPK = null;
699
        try {
700
            Connection conn = helper.getConnection();
701
            dbPK = helper.getPksFrom(conn, getJDBCParameters());
702
            conn.close();
703
        } catch (Exception exc) {
704
            logger.error("While getting PK from DB", exc);
705
            return false;
706
        }
707
        return sameStrings(storePK, dbPK);
708
	}
709

  
710
    private boolean sameStrings(String[] a, String[] b) {
711
        
712
        if (a==null || b==null || a.length!=b.length || a.length==0) {
713
            /*
714
             * Must not be empty
715
             */
716
            return false;
717
        }
718
        int len = a.length;
719
        boolean found = false;
720
        /*
721
         * Check same 
722
         */
723
        for (int ai=0; ai<len; ai++) {
724
            found = false;
725
            for (int bi=0; bi<len; bi++) {
726
                if (b[bi].compareTo(a[ai]) == 0) {
727
                    found = true;
728
                    break;
729
                }
730
            }
731
            if (! found) {
732
                return false;
733
            }
734
        }
735
        return true;
736
    }
737

  
738
    private String[] getPK(FeatureType ft) {
739
        
740
        List resp = new ArrayList();
741
        FeatureAttributeDescriptor attr;
742
        Iterator<FeatureAttributeDescriptor> iter = FeatureTypeHelper.iterator(ft);
743
        while (iter.hasNext()) {
744
            attr = (FeatureAttributeDescriptor) iter.next();
745
            if (attr.isPrimaryKey()) {
746
                resp.add(attr.getName());
747
            }
748
        }
749
        return (String[]) resp.toArray(new String[0]);
750
    }
751
}
trunk/org.gvsig.desktop/org.gvsig.desktop.compat.cdc/org.gvsig.fmap.dal/org.gvsig.fmap.dal.db/org.gvsig.fmap.dal.db.jdbc/src/main/java/org/gvsig/fmap/dal/store/jdbc/JDBCLibrary.java
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 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
 *
11
 * 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
 *
16
 * 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
 *
20
 * For any additional information, do not hesitate to contact us at info AT
21
 * gvsig.com, or visit our website www.gvsig.com.
22
 */
23
package org.gvsig.fmap.dal.store.jdbc;
24

  
25
import org.gvsig.fmap.dal.DALLibrary;
26
import org.gvsig.fmap.dal.DALLocator;
27
import org.gvsig.fmap.dal.resource.db.DBResourceLibrary;
28
import org.gvsig.fmap.dal.resource.spi.ResourceManagerProviderServices;
29
import org.gvsig.fmap.dal.spi.DataManagerProviderServices;
30
import org.gvsig.fmap.dal.store.db.DBHelper;
31
import org.gvsig.fmap.dal.store.db.DBStoreLibrary;
32
import org.gvsig.metadata.exceptions.MetadataException;
33
import org.gvsig.tools.library.AbstractLibrary;
34
import org.gvsig.tools.library.LibraryException;
35

  
36
/**
37
 * Initialize JDBC Provider Library
38
 *
39
 */
40
public class JDBCLibrary extends AbstractLibrary {
41

  
42
    public static final String NAME = "JDBC";
43

  
44
    @Override
45
    public void doRegistration() {
46
        registerAsServiceOf(DALLibrary.class);
47
        require(DBStoreLibrary.class);
48
        require(DBResourceLibrary.class);
49
    }
50

  
51
    @Override
52
    protected void doInitialize() throws LibraryException {
53
    }
54

  
55
    @Override
56
    protected void doPostInitialize() throws LibraryException {
57
        LibraryException ex = null;
58

  
59
        DBHelper.registerParametersDefinition(
60
                NAME + "StoreParameters",
61
                JDBCStoreParameters.class,
62
                NAME + "Parameters.xml"
63
        );
64
        DBHelper.registerParametersDefinition(
65
                NAME + "NewStoreParameters",
66
                JDBCNewStoreParameters.class,
67
                NAME + "Parameters.xml"
68
        );
69
        DBHelper.registerParametersDefinition(
70
                NAME + "ServerExplorerParameters",
71
                JDBCServerExplorerParameters.class,
72
                NAME + "Parameters.xml"
73
        );
74
        DBHelper.registerParametersDefinition(
75
                NAME + "ResourceParameters",
76
                JDBCResourceParameters.class,
77
                NAME + "Parameters.xml"
78
        );
79

  
80
        try {
81
            DBHelper.registerMetadataDefinition(
82
                    NAME,
83
                    JDBCStoreProvider.class,
84
                    NAME + "Metadata.xml"
85
            );
86
        } catch (MetadataException e) {
87
            ex = new LibraryException(this.getClass(), e);
88
        }
89

  
90
        ResourceManagerProviderServices resman = (ResourceManagerProviderServices) DALLocator
91
                .getResourceManager();
92

  
93
        if (!resman.getResourceProviders().contains(NAME)) {
94
            resman.register(
95
                    JDBCResource.NAME,
96
                    JDBCResource.DESCRIPTION,
97
                    JDBCResource.class,
98
                    JDBCResourceParameters.class
99
            );
100
        }
101

  
102
        DataManagerProviderServices dataman = (DataManagerProviderServices) DALLocator
103
                .getDataManager();
104

  
105
        if (!dataman.getStoreProviders().contains(NAME)) {
106
            dataman.registerStoreProviderFactory(new JDBCStoreProviderFactory());
107
        }
108

  
109
        if (!dataman.getServerExplorerRegister().exits(JDBCStoreProvider.NAME)) {
110
            dataman.registerServerExplorerFactory(new JDBCServerExplorerFactory());
111
        }
112

  
113
        if (ex != null) {
114
            throw ex;
115
        }
116
    }
117
}
trunk/org.gvsig.desktop/org.gvsig.desktop.compat.cdc/org.gvsig.fmap.dal/org.gvsig.fmap.dal.db/org.gvsig.fmap.dal.db.jdbc/src/main/java/org/gvsig/fmap/dal/store/jdbc/JDBCSetProvider.java
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.fmap.dal.store.jdbc;
25

  
26
import java.util.ArrayList;
27
import java.util.Arrays;
28
import java.util.Iterator;
29
import java.util.List;
30
import java.util.NoSuchElementException;
31

  
32
import org.gvsig.fmap.dal.DataTypes;
33
import org.gvsig.fmap.dal.exception.DataException;
34
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
35
import org.gvsig.fmap.dal.feature.FeatureQuery;
36
import org.gvsig.fmap.dal.feature.FeatureQueryOrder;
37
import org.gvsig.fmap.dal.feature.FeatureType;
38
import org.gvsig.fmap.dal.feature.FeatureQueryOrder.FeatureQueryOrderMember;
39
import org.gvsig.fmap.dal.feature.spi.AbstractFeatureSetProvider;
40
import org.gvsig.tools.evaluator.Evaluator;
41
import org.gvsig.tools.evaluator.EvaluatorFieldValue;
42
import org.gvsig.tools.evaluator.EvaluatorFieldsInfo;
43
import org.gvsig.tools.exception.BaseException;
44
import org.slf4j.Logger;
45
import org.slf4j.LoggerFactory;
46

  
47
/**
48
 * @author jmvivo
49
 *
50
 */
51
public class JDBCSetProvider extends AbstractFeatureSetProvider {
52

  
53
	final static private Logger logger = LoggerFactory
54
			.getLogger(JDBCSetProvider.class);
55

  
56
	protected String filter;
57
	protected String order;
58
	protected Long size = null;
59
	protected Boolean isEmpty = null;
60

  
61
	protected List resultSetIDReferenced;
62

  
63
	private JDBCHelper helper = null;
64

  
65
	private int defaultFetchSize = 1000;
66

  
67
	private long limit = -1l;
68

  
69
    private boolean directSQLMode;
70

  
71
	public JDBCSetProvider(JDBCStoreProvider store, FeatureQuery query,
72
			FeatureType featureType) throws DataException {
73
		super(store, query, featureType);
74
		this.helper = store.getHelper();
75
		this.resultSetIDReferenced = new ArrayList();
76
		this.directSQLMode =  store.isDirectSQLMode();
77
	
78
		if (query.hasFilter() && this.canFilter()) {
79
			setFilter(query.getFilter());
80
		} else {
81
			setFilter(null);
82
		}
83

  
84
		if (query.hasOrder() && canOrder()) {
85
			setOrder(query.getOrder());
86
		} else {
87
			setOrder(null);
88
		}
89

  
90
		if (query != null) {
91
			limit = query.getLimit();
92
		}
93
	}
94

  
95
	/**
96
	 * @return the defaultFetchSize
97
	 */
98
	public int getDefaultFetchSize() {
99
		return defaultFetchSize;
100
	}
101

  
102
	/**
103
	 * @param defaultFetchSize
104
	 *            the defaultFetchSize to set
105
	 */
106
	public void setDefaultFetchSize(int defaultFetchSize) {
107
		this.defaultFetchSize = defaultFetchSize;
108
	}
109

  
110
	protected String getSqlForEvaluator(Evaluator filter) {
111
		if (filter == null) {
112
			return null;
113
		}
114
		EvaluatorFieldsInfo info = filter.getFieldsInfo();
115
		String filterString = filter.getSQL();
116
		if (info == null) {
117
			return filterString;
118
		}
119
		String[] filterNames = info.getFieldNames();
120
		String[] finalNames = new String[filterNames.length];
121
		EvaluatorFieldValue[] fValues;
122

  
123
		List values = new ArrayList();
124

  
125
		FeatureAttributeDescriptor attr;
126
		for (int i = 0; i < filterNames.length; i++) {
127
			attr = getFeatureType().getAttributeDescriptor(filterNames[i]);
128
			if (attr == null) {
129
				finalNames[i] = filterNames[i];
130
				continue;
131
			}
132
			finalNames[i] = getEscapedFieldName(attr.getName());
133

  
134
		}
135

  
136
		for (int i = 0; i < filterNames.length; i++) {
137
			if (!filterNames[i].equals(finalNames[i])) {
138
				filterString = filterString.replaceAll(
139
						"\\b" + filterNames[i] + "\\b",
140
						finalNames[i]);
141
			}
142
		}
143

  
144
		return filterString;
145
	}
146

  
147

  
148
	protected String getEscapedFieldName(String fieldName) {
149
		if (helper == null) {
150
			helper = getJDBCStoreProvider().getHelper();
151
		}
152
		return helper.escapeFieldName(fieldName);
153
	}
154

  
155

  
156
	protected void setOrder(FeatureQueryOrder order) {
157
		if (order == null || order.size() == 0) {
158
			this.order = null;
159
			return;
160
		}
161

  
162
		StringBuilder buffer = new StringBuilder();
163
		Iterator iter = order.iterator();
164
		FeatureQueryOrderMember menber;
165
		while (true) {
166
			menber = (FeatureQueryOrderMember) iter.next();
167
			if (menber.hasEvaluator()) {
168
				buffer.append(getSqlForEvaluator(menber.getEvaluator()));
169
			} else {
170
				buffer.append(getEscapedFieldName(menber.getAttributeName()));
171
			}
172
			if (menber.getAscending()) {
173
				buffer.append(" ASC");
174
			} else {
175
				buffer.append(" DESC");
176
			}
177
			if (iter.hasNext()) {
178
				buffer.append(", ");
179
			} else {
180
				buffer.append(' ');
181
				break;
182
			}
183
		}
184

  
185
		this.order = buffer.toString();
186
	}
187

  
188
	protected void setFilter(Evaluator filter) {
189
		this.filter = getSqlForEvaluator(filter);
190
	}
191

  
192

  
193

  
194
	/* (non-Javadoc)
195
	 * @see org.gvsig.fmap.dal.feature.spi.FeatureSetProvider#canFilter()
196
	 */
197
	public boolean canFilter() {
198
		Evaluator filter = getQuery().getFilter();
199
		if (directSQLMode){
200
		    return false;
201
		}
202
		if (filter != null) {
203
			if (filter.getSQL() == null || filter.getSQL().length() == 0) {
204
				return false;
205
			} else {
206
				// TODO Check Geom fields if
207
				EvaluatorFieldsInfo fInfo = filter.getFieldsInfo();
208
				if (fInfo == null || fInfo.getFieldNames() == null) {
209
					return true;
210
				}
211
				Iterator names = Arrays.asList(fInfo.getFieldNames())
212
						.iterator();
213
				String name;
214
				int type;
215
				while (names.hasNext()) {
216
					name = (String) names.next();
217
					type =
218
							this.getFeatureType()
219
									.getAttributeDescriptor(name)
220
							.getType();
221
					if (type == DataTypes.GEOMETRY
222
							&& !this.helper.supportsGeometry()) {
223
						return false;
224
					}
225

  
226

  
227

  
228
				}
229

  
230
				return true;
231
			}
232

  
233
		} else{
234
			return false;
235
		}
236
	}
237

  
238
	/* (non-Javadoc)
239
	 * @see org.gvsig.fmap.dal.feature.spi.FeatureSetProvider#canIterateFromIndex()
240
	 */
241
	public boolean canIterateFromIndex() {
242
		return helper.supportOffset();
243
	}
244

  
245
	/* (non-Javadoc)
246
	 * @see org.gvsig.fmap.dal.feature.spi.FeatureSetProvider#canOrder()
247
	 */
248
	public boolean canOrder() {
249
	    if (directSQLMode){
250
	        return false;
251
	    }
252
		// TODO Check Geom fields if postgis not are available
253
		FeatureQuery query = getQuery();
254
		if (query.hasOrder()) {
255
			Iterator iter = query.getOrder().iterator();
256
			FeatureQueryOrderMember menber;
257
			String sql;
258
			while (iter.hasNext()){
259
				menber = (FeatureQueryOrderMember) iter.next();
260
				if (menber.hasEvaluator()){
261
					sql = menber.getEvaluator().getSQL();
262
					if (sql == null || sql.length() == 0) {
263
						return false;
264
					}
265
				}
266
			}
267
		}
268
		return true;
269
	}
270

  
271
	private JDBCStoreProvider getJDBCStoreProvider() {
272
		return (JDBCStoreProvider) getStore();
273
	}
274

  
275
	@Override
276
	protected void doDispose() throws BaseException {
277
		if (resultSetIDReferenced != null) {
278
			Iterator iter = resultSetIDReferenced.iterator();
279
			Integer resID;
280
			while (iter.hasNext()) {
281
				resID = (Integer) iter.next();
282
				if (resID != null) {
283
					logger.warn(
284
						"ResultSet (ID {}) not closed on dispose, will close",
285
						resID);
286
					try {
287
						getJDBCStoreProvider().closeResulset(resID.intValue());
288
					} catch (DataException e) {
289
						logger.error("Close resulset Exception", e);
290
					}
291
				}
292
				iter.remove();
293
			}
294
		}
295
		resultSetIDReferenced = null;
296
		filter = null;
297
		order = null;
298
		size = null;
299
		isEmpty = null;
300
	}
301

  
302
	protected String getSQL(long fromIndex) throws DataException {
303
		return getJDBCStoreProvider().compoundSelect(getFeatureType(), filter,
304
				order, limit, fromIndex);
305

  
306
	}
307

  
308
	/* (non-Javadoc)
309
	 * @see org.gvsig.fmap.dal.feature.spi.FeatureSetProvider#getSize()
310
	 */
311
	public long getSize() throws DataException {
312
		if (size == null) {
313
			size = new Long(getJDBCStoreProvider().getCount(filter));
314
		}
315
		return size.longValue();
316
	}
317

  
318
	/* (non-Javadoc)
319
	 * @see org.gvsig.fmap.dal.feature.spi.FeatureSetProvider#isEmpty()
320
	 */
321
	public boolean isEmpty() throws DataException {
322
		JDBCStoreProvider store = getJDBCStoreProvider();
323
		if (isEmpty == null) {
324
			if (size == null) {
325
				String sql =
326
						store.compoundSelect(getFeatureType(), filter, null, 1,
327
								0);
328
				int rsID = store.createResultSet(sql, getFetchSize());
329
				isEmpty = new Boolean(!store.resulsetNext(rsID));
330
				store.closeResulset(rsID);
331
			} else {
332
				isEmpty = new Boolean(size.longValue() < 1);
333
			}
334
		}
335
		return isEmpty.booleanValue();
336
	}
337

  
338
	protected int getFetchSize() {
339
		long pageSize = -1;
340
		if (getQuery() != null) {
341
			pageSize = getQuery().getPageSize();
342
			pageSize =
343
					pageSize > Integer.MAX_VALUE ? Integer.MAX_VALUE : pageSize;
344
		}
345
		return (pageSize > 0 ? (int) pageSize : defaultFetchSize);
346
	}
347

  
348
	protected JDBCIterator createFastIterator(long index) throws DataException {
349
		if (isEmpty != null && isEmpty.booleanValue()) {
350
			return new EmptyJDBCIterator(getJDBCStoreProvider());
351
		}
352
		int rsID =
353
				getJDBCStoreProvider().createResultSet(getSQL(index),
354
						getFetchSize());
355
		return createDefaultFastIterator(rsID);
356
	}
357

  
358
	protected JDBCIterator createDefaultFastIterator(int resultSetID)
359
			throws DataException {
360
		return new JDBCFastIterator(getJDBCStoreProvider(), this,
361
				getFeatureType(), resultSetID);
362
	}
363

  
364
	protected JDBCIterator createIterator(long index) throws DataException {
365
        if (isEmpty != null && isEmpty.booleanValue()) {
366
            return new EmptyJDBCIterator(getJDBCStoreProvider());
367
        }
368
        int rsID =
369
                getJDBCStoreProvider().createResultSet(getSQL(index),
370
                        getFetchSize());
371
        return createDefaultIterator(rsID);
372
	}
373

  
374
	protected JDBCIterator createDefaultIterator(int resultSetID)
375
			throws DataException {
376
		return new JDBCIterator(getJDBCStoreProvider(), this, getFeatureType(),
377
				resultSetID);
378
	}
379

  
380
	public void addResulsetReference(int resulsetID) {
381
		this.resultSetIDReferenced.add(new Integer(resulsetID));
382
	}
383

  
384
	public void removeResulsetReference(int resulsetID) {
385
		this.resultSetIDReferenced.remove(new Integer(resulsetID));
386
	}
387

  
388
	private class EmptyJDBCIterator extends JDBCIterator {
389

  
390
		protected EmptyJDBCIterator(JDBCStoreProvider store) throws DataException {
391
			super(store, null, null, -1);
392
		}
393

  
394
		@Override
395
		protected boolean internalHasNext() {
396
			return false;
397
		}
398

  
399
		@Override
400
		protected Object internalNext() {
401
			throw new NoSuchElementException();
402
		}
403

  
404
		@Override
405
		protected void doDispose() throws BaseException {
406
			// nothing to do
407
		}
408

  
409
	}
410

  
411
}
trunk/org.gvsig.desktop/org.gvsig.desktop.compat.cdc/org.gvsig.fmap.dal/org.gvsig.fmap.dal.db/org.gvsig.fmap.dal.db.jdbc/src/main/java/org/gvsig/fmap/dal/store/jdbc/JDBCStoreProvider.java
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.fmap.dal.store.jdbc;
25

  
26
import java.security.InvalidParameterException;
27
import java.sql.Connection;
28
import java.sql.PreparedStatement;
29
import java.sql.ResultSet;
30
import java.sql.SQLException;
31
import java.sql.Statement;
32
import java.util.ArrayList;
33
import java.util.Collections;
34
import java.util.Iterator;
35
import java.util.List;
36

  
37
import org.cresques.cts.IProjection;
38
import org.gvsig.fmap.dal.DALLocator;
39
import org.gvsig.fmap.dal.DataManager;
40
import org.gvsig.fmap.dal.DataServerExplorer;
41
import org.gvsig.fmap.dal.DataStore;
42
import org.gvsig.fmap.dal.DataStoreNotification;
43
import org.gvsig.fmap.dal.DataTypes;
44
import org.gvsig.fmap.dal.exception.CloseException;
45
import org.gvsig.fmap.dal.exception.DataException;
46
import org.gvsig.fmap.dal.exception.InitializeException;
47
import org.gvsig.fmap.dal.exception.OpenException;
48
import org.gvsig.fmap.dal.exception.ReadException;
49
import org.gvsig.fmap.dal.exception.ValidateDataParametersException;
50
import org.gvsig.fmap.dal.feature.EditableFeatureType;
51
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
52
import org.gvsig.fmap.dal.feature.FeatureQuery;
53
import org.gvsig.fmap.dal.feature.FeatureType;
54
import org.gvsig.fmap.dal.feature.spi.AbstractFeatureStoreProvider;
55
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
56
import org.gvsig.fmap.dal.feature.spi.FeatureReferenceProviderServices;
57
import org.gvsig.fmap.dal.feature.spi.FeatureSetProvider;
58
import org.gvsig.fmap.dal.resource.ResourceAction;
59
import org.gvsig.fmap.dal.resource.exception.ResourceExecuteException;
60
import org.gvsig.fmap.dal.resource.spi.ResourceProvider;
61
import org.gvsig.fmap.dal.spi.DataStoreProviderServices;
62
import org.gvsig.fmap.dal.store.db.DBHelper;
63
import org.gvsig.fmap.dal.store.db.FeatureTypeHelper;
64
import org.gvsig.fmap.dal.store.jdbc.exception.InvalidResultSetIdException;
65
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCException;
66
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCExecutePreparedSQLException;
67
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCSQLException;
68
import org.gvsig.fmap.geom.Geometry;
69
import org.gvsig.fmap.geom.GeometryLocator;
70
import org.gvsig.fmap.geom.GeometryManager;
71
import org.gvsig.fmap.geom.primitive.Envelope;
72
import org.gvsig.tools.dynobject.DynObject;
73
import org.gvsig.tools.dynobject.exception.DynFieldNotFoundException;
74
import org.gvsig.tools.exception.BaseException;
75
import org.slf4j.Logger;
76
import org.slf4j.LoggerFactory;
77

  
78

  
79
/**
80
 * @author jmvivo
81
 *
82
 */
83
public class JDBCStoreProvider extends AbstractFeatureStoreProvider
84
		implements JDBCHelperUser {
85

  
86
	final static private Logger logger = LoggerFactory
87
			.getLogger(JDBCStoreProvider.class);
88

  
89
	private List<ResultSetInfo> resulsetList;
90

  
91
	public static String NAME = "JDBC";
92
	public static String DESCRIPTION = "JDBC generic store";
93

  
94
	public static final String METADATA_DEFINITION_NAME = NAME;
95

  
96
	private long mlsecondsToZombie = 1000 * 60 * 10; // 10 Min
97

  
98
	protected JDBCHelper helper;
99

  
100
	protected boolean directSQLMode;
101

  
102
	private Long totalCount = null;
103
	private GeometryManager geomManager = null;
104

  
105
	public JDBCStoreProvider(JDBCStoreParameters params,
106
			DataStoreProviderServices storeServices) throws InitializeException {
107
		this(
108
				params, 
109
				storeServices,
110
				DBHelper.newMetadataContainer(METADATA_DEFINITION_NAME)
111
		);
112
	}
113

  
114
	protected JDBCStoreProvider(JDBCStoreParameters params,
115
			DataStoreProviderServices storeServices, DynObject metadata)
116
			throws InitializeException {
117
		super(params, storeServices, metadata);
118
		geomManager = GeometryLocator.getGeometryManager();
119
		
120
		resulsetList = new ArrayList<ResultSetInfo>(10);
121

  
122
		helper = createHelper();
123
		if (params.getSQL() != null && (params.getSQL()).trim().length() > 0) {
124
			directSQLMode = true;
125
		}
126

  
127
		this.initFeatureType();
128
	}
129

  
130
	public Object getDynValue(String name) throws DynFieldNotFoundException {
131
		try {
132
			if( DataStore.METADATA_ENVELOPE.equalsIgnoreCase(name) ) {
133
				Envelope env = this.getEnvelope();
134
				if( env != null ) {
135
					return env;
136
				}
137
			} else if( DataStore.METADATA_CRS.equalsIgnoreCase(name) ) {
138
				IProjection proj;
139
				proj = this.getFeatureStore().getDefaultFeatureType().getDefaultSRS();
140
				if( proj != null ) {
141
					return proj;
142
				}
143
			}
144
		} catch (DataException e) {
145
			throw new RuntimeException(e);
146
		}
147
		return super.getDynValue(name);
148
	}
149
	
150

  
151
	protected JDBCStoreParameters getJDBCParameters() {
152
		return (JDBCStoreParameters) this.getParameters();
153
	}
154

  
155

  
156
	/**
157
	 * Load data form a resulset.<br>
158
	 *
159
	 * <strong>Note:</strong><br>
160
	 * this method have to perform <code>resouceBegin</code> at the begining and
161
	 * <code>resourceEnd</code> at the end of execution.
162
	 *
163
	 *
164
	 * @param data
165
	 * @param resulsetID
166
	 *
167
	 * @return
168
	 * @throws DataException
169
	 */
170
	public void loadFeatureProvider(final FeatureProvider data, final int resultsetID)
171
			throws DataException {
172
		getResource().execute(new ResourceAction() {
173
			public Object run() throws Exception {
174
				ResultSet rs = getResultSet(resultsetID);
175
				FeatureAttributeDescriptor attr;
176
				Iterator<FeatureAttributeDescriptor> iter = FeatureTypeHelper.iterator(data.getType());
177
				while (iter.hasNext()) {
178
					attr = iter.next();
179
					loadFeatureProviderValue(data, rs, attr);
180
				}
181
				return null;
182
			}
183
                        public String toString() {
184
                            return "loadFeature";
185
                        }
186

  
187
		});
188
	}
189

  
190
	protected void loadFeatureProviderValue(FeatureProvider data, ResultSet rs,
191
			FeatureAttributeDescriptor attr) throws DataException {
192
		if (attr.getType() == DataTypes.GEOMETRY) {
193
			byte[] buffer;
194
			try {
195
				buffer = rs.getBytes(attr.getIndex() + 1);
196
				if (buffer == null) {
197
					data.set(attr.getIndex(), null);
198
				} else {
199
					data.set(attr.getIndex(), this.helper.getGeometry(buffer));
200
				}
201
			} catch (SQLException e) {
202
				throw new JDBCSQLException(e);
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff