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

History | View | Annotate | Download (21.4 KB)

1
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 3
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
24
package org.gvsig.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

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

    
54
/**
55
 * @author jmvivo
56
 *
57
 */
58
public class JDBCStoreProviderWriter extends JDBCStoreProvider {
59

    
60
        final static private Logger logger = LoggerFactory
61
                        .getLogger(JDBCStoreProviderWriter.class);
62

    
63

    
64
        protected String appendModeSql;
65
        protected List<FeatureAttributeDescriptor> appendModeAttributes;
66

    
67

    
68
        public JDBCStoreProviderWriter(JDBCStoreParameters params,
69
                        DataStoreProviderServices storeServices)
70
                        throws InitializeException {
71
                super(params, storeServices);
72
        }
73

    
74
        protected JDBCStoreProviderWriter(JDBCStoreParameters params,
75
                        DataStoreProviderServices storeServices, DynObject metadata)
76
                        throws InitializeException {
77
                super(params, storeServices, metadata);
78
        }
79

    
80

    
81

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

    
97
        }
98

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

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

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

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

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

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

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

    
176
                        }
177

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

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

    
212
                        }
213

    
214
        protected void performDeletes(Connection conn, Iterator<FeatureReferenceProviderServices> deleteds, List<FeatureAttributeDescriptor> pkAttributes)
215
                        throws DataException {
216

    
217
                                if (pkAttributes.size() < 0) {
218
                                        throw new RuntimeException("Operation requires missing pk");
219
                                }
220

    
221
                                // ************ Prepare SQL ****************
222
                                StringBuilder sqlb = new StringBuilder();
223
                                sqlb.append("Delete from ");
224
                                sqlb.append(getJDBCParameters().tableID());
225
                                appendToSQLPreparedPkWhereClause(sqlb, pkAttributes);
226
                                String sql = sqlb.toString();
227
                                // ************ Prepare SQL (end) ****************
228

    
229
                                executeRemovePreparedStatement(conn, sql, pkAttributes, deleteds);
230
                        }
231

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

    
240
        protected String getSqlStatementDropField(FeatureAttributeDescriptor attr,List<String> additionalStatement) {
241
                // DROP [ COLUMN ] column
242
                return " DROP COLUMN "
243
                                + this.helper.escapeFieldName(attr.getName());
244

    
245
        }
246

    
247
        public boolean supportsAppendMode() {
248
                return true;
249
        }
250

    
251
        public void endAppend() throws DataException {
252
                appendModeSql = null;
253
                appendModeAttributes = null;
254
        }
255

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

    
271
                        actions.add(strb.toString());
272
                }
273

    
274
                if (attrOrg.allowNull() != attrTrg.allowNull()) {
275
                        // ALTER [ COLUMN ] column { SET | DROP } NOT NULL
276

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

    
290
                if (attrOrg.getDefaultValue() != attrTrg.getDefaultValue()) {
291
                        if (attrTrg.getDefaultValue() == null) {
292
                                // ALTER [ COLUMN ] column DROP DEFAULT
293

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

    
303
                                strb = new StringBuilder();
304
                                strb.append("ALTER COLUMN ");
305
                                strb.append(helper.escapeFieldName(attrTrg.getName()));
306
                                strb.append(" SET DEFAULT");
307
                                strb.append(helper.dalValueToJDBC(attrTrg, attrTrg
308
                                                .getDefaultValue()));
309
                                actions.add(strb.toString());
310
                        }
311
                }
312

    
313
                return actions;
314
        }
315

    
316
        protected void performUpdateTable(Connection conn, FeatureType original,
317
                        FeatureType target) throws DataException {
318

    
319
                /*
320
                 *
321
                 * ALTER TABLE [ ONLY ] name [ * ] action [, ... ]
322
                 */
323

    
324
                List<String> toDrop = new ArrayList<String>();
325
                List<String> toAdd = new ArrayList<String>();
326
                List<String> toAlter = new ArrayList<String>();
327

    
328
                List<String> additionalStatement = new ArrayList<String>();
329

    
330
                FeatureAttributeDescriptor attrOrg;
331
                FeatureAttributeDescriptor attrTrg;
332
                Iterator<FeatureAttributeDescriptor> attrs = FeatureTypeHelper.iterator(original);
333
                while (attrs.hasNext()) {
334
                        attrOrg = (FeatureAttributeDescriptor) attrs.next();
335
                        attrTrg = target.getAttributeDescriptor(attrOrg.getName());
336
                        if (attrTrg == null) {
337
                                toDrop.add(getSqlStatementDropField(attrOrg,
338
                                                additionalStatement));
339
                        } else {
340
                                toAlter.addAll(getSqlStatementAlterField(attrOrg, attrTrg,additionalStatement));
341
                        }
342

    
343
                }
344
                attrs = FeatureTypeHelper.iterator(target);
345
                while (attrs.hasNext()) {
346
                        attrTrg = (FeatureAttributeDescriptor) attrs.next();
347
                        if (original.getAttributeDescriptor(attrTrg.getName()) == null) {
348
                                toAdd.add(getSqlStatementAddField(attrTrg,
349
                                                                additionalStatement));
350
                        }
351
                }
352

    
353
                StringBuilder sqlb = new StringBuilder();
354

    
355
                sqlb.append("ALTER TABLE ");
356
                sqlb.append(getJDBCParameters().tableID());
357
                sqlb.append(' ');
358

    
359
                List<String> actions = new ArrayList<String>();
360
                actions.addAll(toDrop);
361
                actions.addAll(toAlter);
362
                actions.addAll(toAdd);
363

    
364
                Iterator<String> it = actions.iterator();
365
                while (it.hasNext()) {
366
                        if (it.next() == null) {
367
                                it.remove();
368
                        }
369
                }
370

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

    
378
                if (actions.size() < 1) {
379
                        return;
380
                }
381

    
382
                helper.stringJoin(actions, ", ", sqlb);
383

    
384
                String sql = sqlb.toString();
385

    
386
                Statement st = null;
387

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

    
411
        }
412

    
413

    
414
        private void perfomInsert(Connection conn, PreparedStatement insertSt,
415
                        String sql, FeatureProvider feature, List<FeatureAttributeDescriptor> attributes)
416
                        throws DataException {
417

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

    
438
                } catch (SQLException e1) {
439
                        throw new JDBCSQLException(e1);
440
                }
441
        }
442

    
443
        public void append(final FeatureProvider featureProvider) throws DataException {
444
                TransactionalAction action = new TransactionalAction() {
445
                        public Object action(Connection conn) throws DataException {
446

    
447
                                PreparedStatement st;
448
                                try {
449
                                        st = conn.prepareStatement(appendModeSql);
450
                                } catch (SQLException e) {
451
                                        throw new JDBCPreparingSQLException(appendModeSql, e);
452
                                }
453
                                try {
454
                                        perfomInsert(conn, st, appendModeSql, featureProvider,
455
                                                        appendModeAttributes);
456
                                } finally {
457
                                        try {
458
                                                st.close();
459
                                        } catch (SQLException e) {
460
                                        }
461
                                        ;
462
                                }
463
                                return null;
464
                        }
465

    
466
                        public boolean continueTransactionAllowed() {
467
                                return false;
468
                        }
469
                };
470
                try {
471
                        this.helper.doConnectionAction(action);
472

    
473
                        resetCount();
474

    
475
                } catch (Exception e) {
476
                        throw new PerformEditingException(this.getProviderName(), e);
477
                }
478
        }
479

    
480
        protected void prepareAttributeForUpdate(FeatureAttributeDescriptor attr,
481
                        List<String> values) {
482
                values.add(helper.escapeFieldName(attr.getName()) + " = ?");
483
        }
484

    
485
        protected void prepareAttributeForInsert(FeatureAttributeDescriptor attr,
486
                        List<String> fields, List<String> values) {
487

    
488
                fields.add(helper.escapeFieldName(attr.getName()));
489
                values.add("?");
490

    
491
        }
492

    
493

    
494
        protected void prepareSQLAndAttributeListForInsert(StringBuilder sqlb,
495
                        List<FeatureAttributeDescriptor> attributes) throws DataException {
496
                /*
497
                 * INSERT INTO table [ ( column [, ...] ) ] { DEFAULT VALUES | VALUES (
498
                 * { expression | DEFAULT } [, ...] ) [, ...] | query } [ RETURNING * |
499
                 * output_expression [ AS output_name ] [, ...] ]
500
                 */
501

    
502
                sqlb.append("INSERT INTO ");
503
                sqlb.append(getJDBCParameters().tableID());
504

    
505
                sqlb.append(" (");
506

    
507
                FeatureType type = this.getFeatureStore().getDefaultFeatureType();
508

    
509
                List<String> fields = new ArrayList<String>();
510
                List<String> values = new ArrayList<String>();
511

    
512
                Iterator<FeatureAttributeDescriptor> iter = FeatureTypeHelper.iterator(type);
513
                FeatureAttributeDescriptor attr;
514
                while (iter.hasNext()) {
515
                        attr = iter.next();
516
                        if (attr.isAutomatic() || attr.isReadOnly()) {
517
                                continue;
518
                        }
519
                        attributes.add(attr);
520
                        prepareAttributeForInsert(attr, fields, values);
521

    
522
                }
523
                if (attributes.size() < 1) {
524
                        throw new RuntimeException("no fields to set");
525
                }
526

    
527
                helper.stringJoin(fields, ", ", sqlb);
528

    
529
                sqlb.append(") VALUES (");
530
                helper.stringJoin(values, ", ", sqlb);
531

    
532
                sqlb.append(") ");
533

    
534
        }
535

    
536

    
537
        protected void performInserts(Connection conn, Iterator<FeatureProvider> inserteds)
538
                        throws DataException {
539

    
540
                StringBuilder sqlb = new StringBuilder();
541
                List<FeatureAttributeDescriptor> attrs = new ArrayList<FeatureAttributeDescriptor>();
542

    
543
                prepareSQLAndAttributeListForInsert(sqlb, attrs);
544

    
545
                String sql = sqlb.toString();
546
                PreparedStatement st;
547
                try {
548
                        st = conn.prepareStatement(sql);
549
                } catch (SQLException e) {
550
                        throw new JDBCPreparingSQLException(sql, e);
551
                }
552
                try {
553
                        while (inserteds.hasNext()) {
554
                                perfomInsert(conn, st, sql, inserteds.next(),
555
                                                attrs);
556
                        }
557
                } finally {
558
                        try {st.close();} catch (SQLException e) {logger.error("Error closing statement", e);};
559
                }
560
        }
561

    
562
        protected void performUpdates(Connection conn, Iterator<FeatureProvider> updateds,
563
                        List<FeatureAttributeDescriptor> pkAttributes) throws DataException {
564
                /*
565
                 * UPDATE [ ONLY ] table [ [ AS ] alias ] SET { column = { expression |
566
                 * DEFAULT } | ( column [, ...] ) = ( { expression | DEFAULT } [, ...] )
567
                 * } [, ...] [ FROM fromlist ] [ WHERE condition ] [ RETURNING * |
568
                 * output_expression [ AS output_name ] [, ...] ]
569
                 */
570

    
571
                if (pkAttributes.size() < 0) {
572
                        throw new RuntimeException("Operation requires missing pk");
573
                }
574

    
575
                // ************ Prepare SQL ****************
576

    
577
                StringBuilder sqlb = new StringBuilder();
578
                sqlb.append("UPDATE ");
579
                sqlb.append(getJDBCParameters().tableID());
580

    
581
                sqlb.append(" SET ");
582

    
583
                List<String> values = new ArrayList<String>();
584

    
585
                FeatureType type = this.getFeatureStore().getDefaultFeatureType();
586

    
587
                Iterator<FeatureAttributeDescriptor> iter = FeatureTypeHelper.iterator(type);
588
                FeatureAttributeDescriptor attr;
589
                List<FeatureAttributeDescriptor> updateAttrs = new ArrayList<FeatureAttributeDescriptor>();
590
                while (iter.hasNext()) {
591
                        attr = iter.next();
592
                        if (attr.isPrimaryKey() || attr.isAutomatic() || attr.isReadOnly()) {
593
                                continue;
594
                        }
595
                        updateAttrs.add(attr);
596
                        prepareAttributeForUpdate(attr, values);
597

    
598
                }
599
                if (updateAttrs.size() < 1) {
600
                        throw new RuntimeException("no fields to set");
601
                }
602

    
603
                helper.stringJoin(values, ", ", sqlb);
604

    
605
                sqlb.append(' ');
606
                appendToSQLPreparedPkWhereClause(sqlb, pkAttributes);
607

    
608
                String sql = sqlb.toString();
609
                // ************ Prepare SQL (end) ****************
610

    
611
                updateAttrs.addAll(pkAttributes);
612

    
613
                executeUpdatePreparedStatement(conn, sql, updateAttrs, updateds);
614
        }
615

    
616

    
617
        public void beginAppend() throws DataException {
618
                StringBuilder sqlb = new StringBuilder();
619
                List<FeatureAttributeDescriptor> attrs = new ArrayList<FeatureAttributeDescriptor>();
620

    
621
                prepareSQLAndAttributeListForInsert(sqlb, attrs);
622

    
623
                appendModeSql = sqlb.toString();
624
                appendModeAttributes = attrs;
625
        }
626

    
627

    
628
        protected TransactionalAction getPerformChangesAction(
629
                        final Iterator<FeatureReferenceProviderServices> deleteds, 
630
                        final Iterator<FeatureProvider> inserteds,
631
                        final Iterator<FeatureProvider> updateds, 
632
                        final Iterator<FeatureTypeChanged> featureTypesChanged) {
633

    
634
                TransactionalAction action = new TransactionalAction() {
635

    
636
                        public Object action(Connection conn) throws DataException {
637

    
638
                                if (featureTypesChanged.hasNext()) {
639

    
640
                                        FeatureTypeChanged item = featureTypesChanged.next();
641
                                        performUpdateTable(conn, item.getSource(), item.getTarget());
642
                                }
643

    
644
                                List<FeatureAttributeDescriptor> pkAttributes = null;
645
                                if (deleteds.hasNext() || updateds.hasNext()) {
646
                                        pkAttributes = Arrays.asList(getFeatureStore()
647
                                                        .getDefaultFeatureType()
648
                                                        .getPrimaryKey());
649
                                }
650

    
651
                                if (deleteds.hasNext()) {
652
                                        performDeletes(conn, deleteds, pkAttributes);
653
                                }
654

    
655
                                if (updateds.hasNext()) {
656
                                        performUpdates(conn, updateds, pkAttributes);
657
                                }
658

    
659
                                if (inserteds.hasNext()) {
660
                                        performInserts(conn, inserteds);
661
                                }
662

    
663
                                return null;
664
                        }
665

    
666
                        public boolean continueTransactionAllowed() {
667
                                return false;
668
                        }
669

    
670
                };
671

    
672
                return action;
673

    
674
        }
675

    
676
        @SuppressWarnings("unchecked")
677
        public void performChanges(Iterator deleteds, Iterator inserteds,
678
                        Iterator updateds, Iterator featureTypesChanged)
679
                        throws PerformEditingException {
680

    
681
                boolean countChanged = deleteds.hasNext() || inserteds.hasNext();
682

    
683
                try {
684
                        this.helper.doConnectionAction(getPerformChangesAction(deleteds,
685
                                        inserteds, updateds, featureTypesChanged));
686

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

    
713
                } catch (Exception e) {
714
                        throw new PerformEditingException(this.getProviderName(), e);
715
                }
716
        }
717

    
718

    
719
        public boolean allowWrite() {
720
                if (directSQLMode) {
721
                        return false;
722
                }
723
                if (getJDBCParameters().getPkFields() == null
724
                                || getJDBCParameters().getPkFields().length > 0) {
725
                        FeatureType ft = null;
726
                        try {
727
                                ft = this.getFeatureStore().getDefaultFeatureType();
728
                        } catch (DataException e) {
729
                                logger.error("Excepton get default Feature Type", e);
730
                        }
731

    
732
                        if (ft == null) {
733
                                return false;
734
                        }
735
                        FeatureAttributeDescriptor attr;
736
                        Iterator<FeatureAttributeDescriptor> iter = FeatureTypeHelper.iterator(ft);
737
                        while (iter.hasNext()) {
738
                                attr = (FeatureAttributeDescriptor) iter.next();
739
                                if (attr.isPrimaryKey()) {
740
                                        return true;
741
                                }
742
                        }
743
                        return false;
744

    
745
                } else {
746
                        return true;
747
                }
748
        }
749
}