Statistics
| Revision:

svn-gvsig-desktop / branches / v2_0_0_prep / libraries / libFMap_daldb / src / org / gvsig / fmap / dal / store / jdbc / JDBCStoreProviderWriter.java @ 29289

History | View | Annotate | Download (19.3 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.FeatureType;
46
import org.gvsig.fmap.dal.feature.exception.PerformEditingException;
47
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
48
import org.gvsig.fmap.dal.feature.spi.FeatureReferenceProviderServices;
49
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCExecutePreparedSQLException;
50
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCExecuteSQLException;
51
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCPreparingSQLException;
52
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCSQLException;
53
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCUpdateWithoutChangesException;
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

    
67
        protected String appendModeSql;
68
        protected List appendModeAttributes;
69

    
70
        public JDBCStoreProviderWriter() {
71
                super();
72
        }
73

    
74
        public JDBCStoreProviderWriter(JDBCStoreParameters params)
75
                        throws InitializeException {
76
                super();
77
                this.init(params);
78
        }
79

    
80

    
81

    
82
        protected void addToListFeatureValues(FeatureProvider featureData,
83
                        FeatureAttributeDescriptor attrOfList,
84
                        FeatureAttributeDescriptor attr, List values) throws DataException {
85
                if (attr == null) {
86
                        if (attrOfList.isPrimaryKey()) {
87
                                // FIXME excepton
88
                                throw new RuntimeException("pk attribute '"
89
                                                + attrOfList.getName() + "' not found in feature");
90
                        }
91
                        values.add(helper
92
                                        .dalValueToJDBC(attr, attrOfList.getDefaultValue()));
93
                } else {
94
                        values.add(helper.dalValueToJDBC(attr, featureData.get(attr
95
                                        .getIndex())));
96
                }
97

    
98
        }
99

    
100
        protected void addToListFeatureValues(FeatureProvider featureData,
101
                        List attributes, List values) throws DataException {
102
                FeatureAttributeDescriptor attr, attrOfList;
103
                FeatureType fType = featureData.getType();
104
                for (int i = 0; i < attributes.size(); i++) {
105
                        attrOfList = (FeatureAttributeDescriptor) attributes.get(i);
106
                        attr = fType.getAttributeDescriptor(attrOfList.getName());
107
                        addToListFeatureValues(featureData, attrOfList, attr, values);
108
                }
109
        }
110

    
111
        protected void appendToSQLPreparedPkWhereClause(StringBuilder sql,
112
                        List pkAttributes) {
113
                sql.append(" Where ");
114
                FeatureAttributeDescriptor attr;
115
                for (int i = 0; i < pkAttributes.size() - 1; i++) {
116
                        attr = (FeatureAttributeDescriptor) pkAttributes.get(i);
117
                        sql.append(helper.escapeFieldName(attr.getName()));
118
                        sql.append(" = ? AND ");
119
                }
120
                attr = (FeatureAttributeDescriptor) pkAttributes.get(pkAttributes
121
                                .size() - 1);
122
                sql.append(helper.escapeFieldName(attr.getName()));
123
                sql.append(" = ? ");
124
        }
125

    
126
        protected void executeRemovePreparedStatement(Connection conn, String sql,
127
                        List attributes, Iterator featureReferences) throws DataException {
128
                                PreparedStatement st;
129
                                try {
130
                                        st = conn.prepareStatement(sql);
131
                                } catch (SQLException e) {
132
                                        throw new JDBCPreparingSQLException(sql, e);
133
                                }
134
                                try {
135
                                        List values = new ArrayList();
136
                                        FeatureReferenceProviderServices featureRef;
137
                                        FeatureType featureType;
138
                                        while (featureReferences.hasNext()) {
139
                                                st.clearParameters();
140
                                                featureRef = (FeatureReferenceProviderServices) featureReferences
141
                                                                .next();
142
                                                values.clear();
143
                                                featureType = this.store.getFeatureType(featureRef
144
                                                                .getFeatureTypeId());
145

    
146
                                                Iterator iter = attributes.iterator();
147
                                                FeatureAttributeDescriptor attr;
148
                                                while (iter.hasNext()) {
149
                                                        attr = (FeatureAttributeDescriptor) iter.next();
150
                                                        values.add(helper.dalValueToJDBC(attr, featureRef
151
                                                                        .getKeyValue(attr.getName())));
152
                                                }
153

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

    
167
                                                } catch (SQLException e) {
168
                                                        throw new JDBCExecutePreparedSQLException(sql, values, e);
169
                                                }
170

    
171
                                        }
172
                                } catch (SQLException e) {
173
                                        throw new JDBCSQLException(e);
174
                                } finally {
175
                                        try {st.close();} catch (SQLException e) {        };
176
                                }
177

    
178
                        }
179

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

    
207
                                        }
208
                                } catch (SQLException e) {
209
                                        throw new JDBCSQLException(e);
210
                                } finally {
211
                                        try {st.close();} catch (SQLException e) {        };
212
                                }
213

    
214
                        }
215

    
216
        protected void performDeletes(Connection conn, Iterator deleteds, List pkAttributes)
217
                        throws DataException {
218

    
219
                                if (pkAttributes.size() < 0) {
220
                                        // FIXME Exception
221
                                        throw new RuntimeException("Operation requires missing pk");
222
                                }
223

    
224
                                // ************ Prepare SQL ****************
225
                                StringBuilder sqlb = new StringBuilder();
226
                                sqlb.append("Delete from ");
227
                                sqlb.append(params.tableID());
228
                                appendToSQLPreparedPkWhereClause(sqlb, pkAttributes);
229
                                String sql = sqlb.toString();
230
                                // ************ Prepare SQL (end) ****************
231

    
232
                                executeRemovePreparedStatement(conn, sql, pkAttributes, deleteds);
233
                        }
234

    
235
        protected String getSqlStatementAddField(FeatureAttributeDescriptor attr,
236
                        List additionalStatement) throws DataException {
237
                StringBuilder strb = new StringBuilder();
238
                strb.append("ADD ");
239
                strb.append(this.helper.getSqlFieldDescription(attr));
240
                return strb.toString();
241
        }
242

    
243
        protected String getSqlStatementDropField(FeatureAttributeDescriptor attr,List additionalStatement) {
244
                // DROP [ COLUMN ] column
245
                return " DROP COLUMN "
246
                                + this.helper.escapeFieldName(attr.getName());
247

    
248
        }
249

    
250
        public boolean supportsAppendMode() {
251
                return true;
252
        }
253

    
254
        public void endAppend() throws DataException {
255
                this.loadMetadata();
256
                appendModeSql = null;
257
                appendModeAttributes = null;
258
        }
259

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

    
275
                        actions.add(strb.toString());
276
                }
277

    
278
                if (attrOrg.allowNull() != attrTrg.allowNull()) {
279
                        // ALTER [ COLUMN ] column { SET | DROP } NOT NULL
280

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

    
294
                if (attrOrg.getDefaultValue() != attrTrg.getDefaultValue()) {
295
                        if (attrTrg.getDefaultValue() == null) {
296
                                // ALTER [ COLUMN ] column DROP DEFAULT
297

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

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

    
317
                return actions;
318
        }
319

    
320
        protected void performUpdateTable(Connection conn, FeatureType original,
321
                        FeatureType target) throws DataException {
322

    
323
                /*
324
                 *
325
                 * ALTER TABLE [ ONLY ] name [ * ] action [, ... ]
326
                 */
327

    
328
                List toDrop = new ArrayList();
329
                List toAdd = new ArrayList();
330
                List toAlter = new ArrayList();
331

    
332
                List additionalStatement = new ArrayList();
333

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

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

    
359
                StringBuilder sqlb = new StringBuilder();
360

    
361
                sqlb.append("ALTER TABLE ");
362
                sqlb.append(params.tableID());
363
                sqlb.append(' ');
364

    
365
                List actions = new ArrayList();
366
                actions.addAll(toDrop);
367
                actions.addAll(toAlter);
368
                actions.addAll(toAdd);
369

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

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

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

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

    
390
                String sql = sqlb.toString();
391

    
392
                Statement st = null;
393

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

    
417
        }
418

    
419

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

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

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

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

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

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

    
479
                        resetCount();
480

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

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

    
491
        protected void prepareAttributeForInsert(FeatureAttributeDescriptor attr,
492
                        List fields, List values) {
493

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

    
497
        }
498

    
499

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

    
508
                sqlb.append("INSERT INTO ");
509
                sqlb.append(params.tableID());
510

    
511
                sqlb.append(" (");
512

    
513
                FeatureType type = this.store.getDefaultFeatureType();
514

    
515
                List fields = new ArrayList();
516
                List values = new ArrayList();
517

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

    
528
                }
529
                if (attributes.size() < 1) {
530
                        // FIXME exception
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 inserteds)
545
                        throws DataException {
546

    
547
                StringBuilder sqlb = new StringBuilder();
548
                List attrs = new ArrayList();
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, (FeatureProvider) 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 updateds,
570
                        List 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
                        // FIXME Exception
580
                        throw new RuntimeException("Operation requires missing pk");
581
                }
582

    
583
                // ************ Prepare SQL ****************
584

    
585
                StringBuilder sqlb = new StringBuilder();
586
                sqlb.append("UPDATE ");
587
                sqlb.append(params.tableID());
588

    
589
                sqlb.append(" SET ");
590

    
591
                List values = new ArrayList();
592

    
593
                FeatureType type = this.store.getDefaultFeatureType();
594

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

    
606
                }
607
                if (updateAttrs.size() < 1) {
608
                        // FIXME exception
609
                        throw new RuntimeException("no fields to set");
610
                }
611

    
612
                helper.stringJoin(values, ", ", sqlb);
613

    
614
                sqlb.append(' ');
615
                appendToSQLPreparedPkWhereClause(sqlb, pkAttributes);
616

    
617
                String sql = sqlb.toString();
618
                // ************ Prepare SQL (end) ****************
619

    
620
                updateAttrs.addAll(pkAttributes);
621

    
622
                executeUpdatePreparedStatement(conn, sql, updateAttrs, updateds);
623
        }
624

    
625

    
626
        public void beginAppend() throws DataException {
627
                StringBuilder sqlb = new StringBuilder();
628
                List attrs = new ArrayList();
629

    
630
                prepareSQLAndAttributeListForInsert(sqlb, attrs);
631

    
632
                appendModeSql = sqlb.toString();
633
                appendModeAttributes = attrs;
634
        }
635

    
636

    
637
        protected TransactionalAction getPerformChangesAction(
638
                        final Iterator deleteds, final Iterator inserteds,
639
                        final Iterator updateds, final Iterator 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 = (FeatureTypeChanged) featureTypesChanged
648
                                                        .next();
649
                                        performUpdateTable(conn, item.getSource(), item.getTarget());
650
                                }
651

    
652
                                List pkAttributes = null;
653
                                if (deleteds.hasNext() || updateds.hasNext()) {
654
                                        pkAttributes = Arrays.asList(store.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
        public void performChanges(Iterator deleteds, Iterator inserteds,
684
                        Iterator updateds, Iterator featureTypesChanged)
685
                        throws PerformEditingException {
686

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

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

    
693
                        this.initFeatureType();
694
                        if (countChanged) {
695
                                resetCount();
696
                        }
697

    
698
                } catch (Exception e) {
699
                        throw new PerformEditingException(this.getName(), e);
700
                }
701
        }
702

    
703

    
704
        public boolean allowWrite() {
705
                if (directSQLMode) {
706
                        return false;
707
                }
708
                if (params.getPkFields() == null || params.getPkFields().length > 0) {
709
                        FeatureType ft = null;
710
                        try {
711
                                ft = this.store.getDefaultFeatureType();
712
                        } catch (DataException e) {
713
                                logger.error("Excepton get default Feature Type", e);
714
                        }
715

    
716
                        if (ft == null) {
717
                                return false;
718
                        }
719
                        FeatureAttributeDescriptor attr;
720
                        Iterator iter = ft.iterator();
721
                        while (iter.hasNext()) {
722
                                attr = (FeatureAttributeDescriptor) iter.next();
723
                                if (attr.isPrimaryKey()) {
724
                                        return true;
725
                                }
726
                        }
727
                        return false;
728

    
729
                } else {
730
                        return true;
731
                }
732
        }
733
}