Statistics
| Revision:

svn-gvsig-desktop / 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 @ 40435

History | View | Annotate | Download (21.4 KB)

1
/* gvSIG. Geographic Information System of the Valencian Government
2
*
3
* Copyright (C) 2007-2008 Infrastructures and Transports Department
4
* of the Valencian Government (CIT)
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 2
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
*/
22

    
23
/*
24
* AUTHORS (In addition to CIT):
25
* 2009 IVER T.I   {{Task}}
26
*/
27

    
28
/**
29
 *
30
 */
31
package org.gvsig.fmap.dal.store.jdbc;
32

    
33
import java.sql.Connection;
34
import java.sql.PreparedStatement;
35
import java.sql.SQLException;
36
import java.sql.Statement;
37
import java.util.ArrayList;
38
import java.util.Arrays;
39
import java.util.Iterator;
40
import java.util.List;
41

    
42
import org.gvsig.fmap.dal.exception.DataException;
43
import org.gvsig.fmap.dal.exception.InitializeException;
44
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
45
import org.gvsig.fmap.dal.feature.FeatureRules;
46
import org.gvsig.fmap.dal.feature.FeatureType;
47
import org.gvsig.fmap.dal.feature.exception.PerformEditingException;
48
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
49
import org.gvsig.fmap.dal.feature.spi.FeatureReferenceProviderServices;
50
import org.gvsig.fmap.dal.spi.DataStoreProviderServices;
51
import org.gvsig.fmap.dal.store.db.FeatureTypeHelper;
52
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCExecutePreparedSQLException;
53
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCExecuteSQLException;
54
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCPreparingSQLException;
55
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCSQLException;
56
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCUpdateWithoutChangesException;
57
import org.gvsig.tools.dynobject.DynObject;
58
import org.slf4j.Logger;
59
import org.slf4j.LoggerFactory;
60

    
61
/**
62
 * @author jmvivo
63
 *
64
 */
65
public class JDBCStoreProviderWriter extends JDBCStoreProvider {
66

    
67
        final static private Logger logger = LoggerFactory
68
                        .getLogger(JDBCStoreProviderWriter.class);
69

    
70

    
71
        protected String appendModeSql;
72
        protected List<FeatureAttributeDescriptor> appendModeAttributes;
73

    
74

    
75
        public JDBCStoreProviderWriter(JDBCStoreParameters params,
76
                        DataStoreProviderServices storeServices)
77
                        throws InitializeException {
78
                super(params, storeServices);
79
        }
80

    
81
        protected JDBCStoreProviderWriter(JDBCStoreParameters params,
82
                        DataStoreProviderServices storeServices, DynObject metadata)
83
                        throws InitializeException {
84
                super(params, storeServices, metadata);
85
        }
86

    
87

    
88

    
89
        protected void addToListFeatureValues(FeatureProvider featureProvider,
90
                        FeatureAttributeDescriptor attrOfList,
91
                        FeatureAttributeDescriptor attr, List<Object> values) throws DataException {
92
                if (attr == null) {
93
                        if (attrOfList.isPrimaryKey()) {
94
                                throw new RuntimeException("pk attribute '"
95
                                                + attrOfList.getName() + "' not found in feature");
96
                        }
97
                        values.add(helper
98
                                        .dalValueToJDBC(attr, attrOfList.getDefaultValue()));
99
                } else {
100
                        values.add(helper.dalValueToJDBC(attr, featureProvider.get(attr
101
                                        .getIndex())));
102
                }
103

    
104
        }
105

    
106
        protected void addToListFeatureValues(FeatureProvider featureProvider,
107
                        List<FeatureAttributeDescriptor> attributes, List<Object> values) throws DataException {
108
                FeatureAttributeDescriptor attr, attrOfList;
109
                FeatureType fType = featureProvider.getType();
110
                for (int i = 0; i < attributes.size(); i++) {
111
                        attrOfList = (FeatureAttributeDescriptor) attributes.get(i);
112
                        attr = fType.getAttributeDescriptor(attrOfList.getName());
113
                        addToListFeatureValues(featureProvider, attrOfList, attr, values);
114
                }
115
        }
116

    
117
        protected void appendToSQLPreparedPkWhereClause(StringBuilder sql,
118
                        List<FeatureAttributeDescriptor> pkAttributes) {
119
                sql.append(" Where ");
120
                FeatureAttributeDescriptor attr;
121
                for (int i = 0; i < pkAttributes.size() - 1; i++) {
122
                        attr = (FeatureAttributeDescriptor) pkAttributes.get(i);
123
                        sql.append(helper.escapeFieldName(attr.getName()));
124
                        sql.append(" = ? AND ");
125
                }
126
                attr = (FeatureAttributeDescriptor) pkAttributes.get(pkAttributes
127
                                .size() - 1);
128
                sql.append(helper.escapeFieldName(attr.getName()));
129
                sql.append(" = ? ");
130
        }
131

    
132
        protected void executeRemovePreparedStatement(Connection conn, String sql,
133
                        List<FeatureAttributeDescriptor> attributes, Iterator<FeatureReferenceProviderServices> featureReferences) throws DataException {
134
                                PreparedStatement st;
135
                                try {
136
                                        st = conn.prepareStatement(sql);
137
                                } catch (SQLException e) {
138
                                        throw new JDBCPreparingSQLException(sql, e);
139
                                }
140
                                try {
141
                                        List<Object> values = new ArrayList<Object>();
142
                                        FeatureReferenceProviderServices featureRef;
143
//                                        FeatureType featureType;
144
                                        while (featureReferences.hasNext()) {
145
                                                st.clearParameters();
146
                                                featureRef = featureReferences.next();
147
                                                values.clear();
148
//                                                featureType = this.getFeatureStore()
149
//                                                        .getFeatureType(featureRef.getFeatureTypeId());
150

    
151
                                                Iterator<FeatureAttributeDescriptor> iter = attributes.iterator();
152
                                                FeatureAttributeDescriptor attr;
153
                                                while (iter.hasNext()) {
154
                                                        attr =  iter.next();
155
                                                        values.add( helper.dalValueToJDBC(attr, featureRef
156
                                                                        .getKeyValue(attr.getName())));
157
                                                }
158

    
159
                                                for (int i = 0; i < values.size(); i++) {
160
                                                        st.setObject(i + 1, values.get(i));
161
                                                }
162
                                                try {
163
                                                        int nAffected =st.executeUpdate();
164
                                                        if (nAffected == 0) {
165
                                                                throw new JDBCUpdateWithoutChangesException(sql, values);
166
                                                        }
167
                                                        if (nAffected > 1){
168
                                                                logger.warn("Remove statement affectst to {} rows: {}",
169
                                                                                nAffected, sql);
170
                                                        }
171

    
172
                                                } catch (SQLException e) {
173
                                                        throw new JDBCExecutePreparedSQLException(sql, values, e);
174
                                                }
175

    
176
                                        }
177
                                } catch (SQLException e) {
178
                                        throw new JDBCSQLException(e);
179
                                } finally {
180
                                        try {st.close();} catch (SQLException e) {        };
181
                                }
182

    
183
                        }
184

    
185
        protected void executeUpdatePreparedStatement(Connection conn, String sql,
186
                        List<FeatureAttributeDescriptor> attributes, Iterator<FeatureProvider> featureProviders) throws DataException {
187
                                PreparedStatement st;
188
                                try {
189
                                        st = conn.prepareStatement(sql);
190
                                } catch (SQLException e) {
191
                                        throw new JDBCPreparingSQLException(sql, e);
192
                                }
193
                                try {
194
                                        List<Object> values = new ArrayList<Object>();
195
                                        FeatureProvider featureProvider;
196
                                        while (featureProviders.hasNext()) {
197
                                                st.clearParameters();
198
                                                featureProvider = (FeatureProvider) featureProviders.next();
199
                                                values.clear();
200
                                                addToListFeatureValues(featureProvider, attributes, values);
201
                                                for (int i = 0; i < values.size(); i++) {
202
                                                        st.setObject(i + 1, values.get(i));
203
                                                }
204
                                                try {
205
                                                        if (st.executeUpdate() == 0) {
206
                                                                throw new JDBCUpdateWithoutChangesException(sql, values);
207
                                                        }
208
                                                } catch (SQLException e) {
209
                                                        throw new JDBCExecutePreparedSQLException(sql, values, e);
210
                                                }
211

    
212
                                        }
213
                                } catch (SQLException e) {
214
                                        throw new JDBCSQLException(e);
215
                                } finally {
216
                                        try {st.close();} catch (SQLException e) {        };
217
                                }
218

    
219
                        }
220

    
221
        protected void performDeletes(Connection conn, Iterator<FeatureReferenceProviderServices> deleteds, List<FeatureAttributeDescriptor> pkAttributes)
222
                        throws DataException {
223

    
224
                                if (pkAttributes.size() < 0) {
225
                                        throw new RuntimeException("Operation requires missing pk");
226
                                }
227

    
228
                                // ************ Prepare SQL ****************
229
                                StringBuilder sqlb = new StringBuilder();
230
                                sqlb.append("Delete from ");
231
                                sqlb.append(getJDBCParameters().tableID());
232
                                appendToSQLPreparedPkWhereClause(sqlb, pkAttributes);
233
                                String sql = sqlb.toString();
234
                                // ************ Prepare SQL (end) ****************
235

    
236
                                executeRemovePreparedStatement(conn, sql, pkAttributes, deleteds);
237
                        }
238

    
239
        protected String getSqlStatementAddField(FeatureAttributeDescriptor attr,
240
                        List<String> additionalStatement) throws DataException {
241
                StringBuilder strb = new StringBuilder();
242
                strb.append("ADD ");
243
                strb.append(this.helper.getSqlFieldDescription(attr));
244
                return strb.toString();
245
        }
246

    
247
        protected String getSqlStatementDropField(FeatureAttributeDescriptor attr,List<String> additionalStatement) {
248
                // DROP [ COLUMN ] column
249
                return " DROP COLUMN "
250
                                + this.helper.escapeFieldName(attr.getName());
251

    
252
        }
253

    
254
        public boolean supportsAppendMode() {
255
                return true;
256
        }
257

    
258
        public void endAppend() throws DataException {
259
                appendModeSql = null;
260
                appendModeAttributes = null;
261
        }
262

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

    
278
                        actions.add(strb.toString());
279
                }
280

    
281
                if (attrOrg.allowNull() != attrTrg.allowNull()) {
282
                        // ALTER [ COLUMN ] column { SET | DROP } NOT NULL
283

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

    
297
                if (attrOrg.getDefaultValue() != attrTrg.getDefaultValue()) {
298
                        if (attrTrg.getDefaultValue() == null) {
299
                                // ALTER [ COLUMN ] column DROP DEFAULT
300

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

    
310
                                strb = new StringBuilder();
311
                                strb.append("ALTER COLUMN ");
312
                                strb.append(helper.escapeFieldName(attrTrg.getName()));
313
                                strb.append(" SET DEFAULT");
314
                                strb.append(helper.dalValueToJDBC(attrTrg, attrTrg
315
                                                .getDefaultValue()));
316
                                actions.add(strb.toString());
317
                        }
318
                }
319

    
320
                return actions;
321
        }
322

    
323
        protected void performUpdateTable(Connection conn, FeatureType original,
324
                        FeatureType target) throws DataException {
325

    
326
                /*
327
                 *
328
                 * ALTER TABLE [ ONLY ] name [ * ] action [, ... ]
329
                 */
330

    
331
                List<String> toDrop = new ArrayList<String>();
332
                List<String> toAdd = new ArrayList<String>();
333
                List<String> toAlter = new ArrayList<String>();
334

    
335
                List<String> additionalStatement = new ArrayList<String>();
336

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

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

    
360
                StringBuilder sqlb = new StringBuilder();
361

    
362
                sqlb.append("ALTER TABLE ");
363
                sqlb.append(getJDBCParameters().tableID());
364
                sqlb.append(' ');
365

    
366
                List<String> actions = new ArrayList<String>();
367
                actions.addAll(toDrop);
368
                actions.addAll(toAlter);
369
                actions.addAll(toAdd);
370

    
371
                Iterator<String> it = actions.iterator();
372
                while (it.hasNext()) {
373
                        if (it.next() == null) {
374
                                it.remove();
375
                        }
376
                }
377

    
378
                it = additionalStatement.iterator();
379
                while (it.hasNext()) {
380
                        if (it.next() == null) {
381
                                it.remove();
382
                        }
383
                }
384

    
385
                if (actions.size() < 1) {
386
                        return;
387
                }
388

    
389
                helper.stringJoin(actions, ", ", sqlb);
390

    
391
                String sql = sqlb.toString();
392

    
393
                Statement st = null;
394

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

    
418
        }
419

    
420

    
421
        private void perfomInsert(Connection conn, PreparedStatement insertSt,
422
                        String sql, FeatureProvider feature, List<FeatureAttributeDescriptor> attributes)
423
                        throws DataException {
424

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

    
445
                } catch (SQLException e1) {
446
                        throw new JDBCSQLException(e1);
447
                }
448
        }
449

    
450
        public void append(final FeatureProvider featureProvider) throws DataException {
451
                TransactionalAction action = new TransactionalAction() {
452
                        public Object action(Connection conn) throws DataException {
453

    
454
                                PreparedStatement st;
455
                                try {
456
                                        st = conn.prepareStatement(appendModeSql);
457
                                } catch (SQLException e) {
458
                                        throw new JDBCPreparingSQLException(appendModeSql, e);
459
                                }
460
                                try {
461
                                        perfomInsert(conn, st, appendModeSql, featureProvider,
462
                                                        appendModeAttributes);
463
                                } finally {
464
                                        try {
465
                                                st.close();
466
                                        } catch (SQLException e) {
467
                                        }
468
                                        ;
469
                                }
470
                                return null;
471
                        }
472

    
473
                        public boolean continueTransactionAllowed() {
474
                                return false;
475
                        }
476
                };
477
                try {
478
                        this.helper.doConnectionAction(action);
479

    
480
                        resetCount();
481

    
482
                } catch (Exception e) {
483
                        throw new PerformEditingException(this.getProviderName(), e);
484
                }
485
        }
486

    
487
        protected void prepareAttributeForUpdate(FeatureAttributeDescriptor attr,
488
                        List<String> values) {
489
                values.add(helper.escapeFieldName(attr.getName()) + " = ?");
490
        }
491

    
492
        protected void prepareAttributeForInsert(FeatureAttributeDescriptor attr,
493
                        List<String> fields, List<String> values) {
494

    
495
                fields.add(helper.escapeFieldName(attr.getName()));
496
                values.add("?");
497

    
498
        }
499

    
500

    
501
        protected void prepareSQLAndAttributeListForInsert(StringBuilder sqlb,
502
                        List<FeatureAttributeDescriptor> attributes) throws DataException {
503
                /*
504
                 * INSERT INTO table [ ( column [, ...] ) ] { DEFAULT VALUES | VALUES (
505
                 * { expression | DEFAULT } [, ...] ) [, ...] | query } [ RETURNING * |
506
                 * output_expression [ AS output_name ] [, ...] ]
507
                 */
508

    
509
                sqlb.append("INSERT INTO ");
510
                sqlb.append(getJDBCParameters().tableID());
511

    
512
                sqlb.append(" (");
513

    
514
                FeatureType type = this.getFeatureStore().getDefaultFeatureType();
515

    
516
                List<String> fields = new ArrayList<String>();
517
                List<String> values = new ArrayList<String>();
518

    
519
                Iterator<FeatureAttributeDescriptor> iter = FeatureTypeHelper.iterator(type);
520
                FeatureAttributeDescriptor attr;
521
                while (iter.hasNext()) {
522
                        attr = iter.next();
523
                        if (attr.isAutomatic() || attr.isReadOnly()) {
524
                                continue;
525
                        }
526
                        attributes.add(attr);
527
                        prepareAttributeForInsert(attr, fields, values);
528

    
529
                }
530
                if (attributes.size() < 1) {
531
                        throw new RuntimeException("no fields to set");
532
                }
533

    
534
                helper.stringJoin(fields, ", ", sqlb);
535

    
536
                sqlb.append(") VALUES (");
537
                helper.stringJoin(values, ", ", sqlb);
538

    
539
                sqlb.append(") ");
540

    
541
        }
542

    
543

    
544
        protected void performInserts(Connection conn, Iterator<FeatureProvider> inserteds)
545
                        throws DataException {
546

    
547
                StringBuilder sqlb = new StringBuilder();
548
                List<FeatureAttributeDescriptor> attrs = new ArrayList<FeatureAttributeDescriptor>();
549

    
550
                prepareSQLAndAttributeListForInsert(sqlb, attrs);
551

    
552
                String sql = sqlb.toString();
553
                PreparedStatement st;
554
                try {
555
                        st = conn.prepareStatement(sql);
556
                } catch (SQLException e) {
557
                        throw new JDBCPreparingSQLException(sql, e);
558
                }
559
                try {
560
                        while (inserteds.hasNext()) {
561
                                perfomInsert(conn, st, sql, inserteds.next(),
562
                                                attrs);
563
                        }
564
                } finally {
565
                        try {st.close();} catch (SQLException e) {logger.error("Error closing statement", e);};
566
                }
567
        }
568

    
569
        protected void performUpdates(Connection conn, Iterator<FeatureProvider> updateds,
570
                        List<FeatureAttributeDescriptor> pkAttributes) throws DataException {
571
                /*
572
                 * UPDATE [ ONLY ] table [ [ AS ] alias ] SET { column = { expression |
573
                 * DEFAULT } | ( column [, ...] ) = ( { expression | DEFAULT } [, ...] )
574
                 * } [, ...] [ FROM fromlist ] [ WHERE condition ] [ RETURNING * |
575
                 * output_expression [ AS output_name ] [, ...] ]
576
                 */
577

    
578
                if (pkAttributes.size() < 0) {
579
                        throw new RuntimeException("Operation requires missing pk");
580
                }
581

    
582
                // ************ Prepare SQL ****************
583

    
584
                StringBuilder sqlb = new StringBuilder();
585
                sqlb.append("UPDATE ");
586
                sqlb.append(getJDBCParameters().tableID());
587

    
588
                sqlb.append(" SET ");
589

    
590
                List<String> values = new ArrayList<String>();
591

    
592
                FeatureType type = this.getFeatureStore().getDefaultFeatureType();
593

    
594
                Iterator<FeatureAttributeDescriptor> iter = FeatureTypeHelper.iterator(type);
595
                FeatureAttributeDescriptor attr;
596
                List<FeatureAttributeDescriptor> updateAttrs = new ArrayList<FeatureAttributeDescriptor>();
597
                while (iter.hasNext()) {
598
                        attr = iter.next();
599
                        if (attr.isPrimaryKey() || attr.isAutomatic() || attr.isReadOnly()) {
600
                                continue;
601
                        }
602
                        updateAttrs.add(attr);
603
                        prepareAttributeForUpdate(attr, values);
604

    
605
                }
606
                if (updateAttrs.size() < 1) {
607
                        throw new RuntimeException("no fields to set");
608
                }
609

    
610
                helper.stringJoin(values, ", ", sqlb);
611

    
612
                sqlb.append(' ');
613
                appendToSQLPreparedPkWhereClause(sqlb, pkAttributes);
614

    
615
                String sql = sqlb.toString();
616
                // ************ Prepare SQL (end) ****************
617

    
618
                updateAttrs.addAll(pkAttributes);
619

    
620
                executeUpdatePreparedStatement(conn, sql, updateAttrs, updateds);
621
        }
622

    
623

    
624
        public void beginAppend() throws DataException {
625
                StringBuilder sqlb = new StringBuilder();
626
                List<FeatureAttributeDescriptor> attrs = new ArrayList<FeatureAttributeDescriptor>();
627

    
628
                prepareSQLAndAttributeListForInsert(sqlb, attrs);
629

    
630
                appendModeSql = sqlb.toString();
631
                appendModeAttributes = attrs;
632
        }
633

    
634

    
635
        protected TransactionalAction getPerformChangesAction(
636
                        final Iterator<FeatureReferenceProviderServices> deleteds, 
637
                        final Iterator<FeatureProvider> inserteds,
638
                        final Iterator<FeatureProvider> updateds, 
639
                        final Iterator<FeatureTypeChanged> featureTypesChanged) {
640

    
641
                TransactionalAction action = new TransactionalAction() {
642

    
643
                        public Object action(Connection conn) throws DataException {
644

    
645
                                if (featureTypesChanged.hasNext()) {
646

    
647
                                        FeatureTypeChanged item = featureTypesChanged.next();
648
                                        performUpdateTable(conn, item.getSource(), item.getTarget());
649
                                }
650

    
651
                                List<FeatureAttributeDescriptor> pkAttributes = null;
652
                                if (deleteds.hasNext() || updateds.hasNext()) {
653
                                        pkAttributes = Arrays.asList(getFeatureStore()
654
                                                        .getDefaultFeatureType()
655
                                                        .getPrimaryKey());
656
                                }
657

    
658
                                if (deleteds.hasNext()) {
659
                                        performDeletes(conn, deleteds, pkAttributes);
660
                                }
661

    
662
                                if (updateds.hasNext()) {
663
                                        performUpdates(conn, updateds, pkAttributes);
664
                                }
665

    
666
                                if (inserteds.hasNext()) {
667
                                        performInserts(conn, inserteds);
668
                                }
669

    
670
                                return null;
671
                        }
672

    
673
                        public boolean continueTransactionAllowed() {
674
                                return false;
675
                        }
676

    
677
                };
678

    
679
                return action;
680

    
681
        }
682

    
683
        @SuppressWarnings("unchecked")
684
        public void performChanges(Iterator deleteds, Iterator inserteds,
685
                        Iterator updateds, Iterator featureTypesChanged)
686
                        throws PerformEditingException {
687

    
688
                boolean countChanged = deleteds.hasNext() || inserteds.hasNext();
689

    
690
                try {
691
                        this.helper.doConnectionAction(getPerformChangesAction(deleteds,
692
                                        inserteds, updateds, featureTypesChanged));
693

    
694
                        /*
695
                         * Get rules before initializing feature type
696
                         */
697
                        FeatureRules old_rules = getFeatureStore().getDefaultFeatureType().getRules();
698
                        
699
                        /*
700
                         * This initialization loses the feature type rules
701
                         */
702
                        this.initFeatureType();
703
                        
704
                        /*
705
                         * Get new feature type, clear rules and add
706
                         * the ones saved previously
707
                         */
708
                        FeatureType ft = getFeatureStore().getDefaultFeatureType();
709
                        FeatureRules new_rules = ft.getRules();
710
                        new_rules.clear();
711
                        for (int i=0; i<old_rules.size(); i++) {
712
                            new_rules.add(old_rules.getRule(i));
713
                        }
714
                        // ===================================================
715
                        
716
                        if (countChanged) {
717
                                resetCount();
718
                        }
719

    
720
                } catch (Exception e) {
721
                        throw new PerformEditingException(this.getProviderName(), e);
722
                }
723
        }
724

    
725

    
726
        public boolean allowWrite() {
727
                if (directSQLMode) {
728
                        return false;
729
                }
730
                if (getJDBCParameters().getPkFields() == null
731
                                || getJDBCParameters().getPkFields().length > 0) {
732
                        FeatureType ft = null;
733
                        try {
734
                                ft = this.getFeatureStore().getDefaultFeatureType();
735
                        } catch (DataException e) {
736
                                logger.error("Excepton get default Feature Type", e);
737
                        }
738

    
739
                        if (ft == null) {
740
                                return false;
741
                        }
742
                        FeatureAttributeDescriptor attr;
743
                        Iterator<FeatureAttributeDescriptor> iter = FeatureTypeHelper.iterator(ft);
744
                        while (iter.hasNext()) {
745
                                attr = (FeatureAttributeDescriptor) iter.next();
746
                                if (attr.isPrimaryKey()) {
747
                                        return true;
748
                                }
749
                        }
750
                        return false;
751

    
752
                } else {
753
                        return true;
754
                }
755
        }
756
}