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

History | View | Annotate | Download (22.3 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
/* gvSIG. Geographic Information System of the Valencian Government
25
*
26
* Copyright (C) 2007-2008 Infrastructures and Transports Department
27
* of the Valencian Government (CIT)
28
*
29
* This program is free software; you can redistribute it and/or
30
* modify it under the terms of the GNU General Public License
31
* as published by the Free Software Foundation; either version 2
32
* of the License, or (at your option) any later version.
33
*
34
* This program is distributed in the hope that it will be useful,
35
* but WITHOUT ANY WARRANTY; without even the implied warranty of
36
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
37
* GNU General Public License for more details.
38
*
39
* You should have received a copy of the GNU General Public License
40
* along with this program; if not, write to the Free Software
41
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
42
* MA  02110-1301, USA.
43
*
44
*/
45

    
46
/*
47
* AUTHORS (In addition to CIT):
48
* 2009 IVER T.I   {{Task}}
49
*/
50

    
51
/**
52
 *
53
 */
54
package org.gvsig.fmap.dal.store.jdbc;
55

    
56
import java.sql.Connection;
57
import java.sql.PreparedStatement;
58
import java.sql.SQLException;
59
import java.sql.Statement;
60
import java.util.ArrayList;
61
import java.util.Arrays;
62
import java.util.Iterator;
63
import java.util.List;
64

    
65
import org.gvsig.fmap.dal.exception.DataException;
66
import org.gvsig.fmap.dal.exception.InitializeException;
67
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
68
import org.gvsig.fmap.dal.feature.FeatureRules;
69
import org.gvsig.fmap.dal.feature.FeatureType;
70
import org.gvsig.fmap.dal.feature.exception.PerformEditingException;
71
import org.gvsig.fmap.dal.feature.spi.FeatureProvider;
72
import org.gvsig.fmap.dal.feature.spi.FeatureReferenceProviderServices;
73
import org.gvsig.fmap.dal.spi.DataStoreProviderServices;
74
import org.gvsig.fmap.dal.store.db.FeatureTypeHelper;
75
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCExecutePreparedSQLException;
76
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCExecuteSQLException;
77
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCPreparingSQLException;
78
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCSQLException;
79
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCUpdateWithoutChangesException;
80
import org.gvsig.tools.dynobject.DynObject;
81
import org.slf4j.Logger;
82
import org.slf4j.LoggerFactory;
83

    
84
/**
85
 * @author jmvivo
86
 *
87
 */
88
public class JDBCStoreProviderWriter extends JDBCStoreProvider {
89

    
90
        final static private Logger logger = LoggerFactory
91
                        .getLogger(JDBCStoreProviderWriter.class);
92

    
93

    
94
        protected String appendModeSql;
95
        protected List<FeatureAttributeDescriptor> appendModeAttributes;
96

    
97

    
98
        public JDBCStoreProviderWriter(JDBCStoreParameters params,
99
                        DataStoreProviderServices storeServices)
100
                        throws InitializeException {
101
                super(params, storeServices);
102
        }
103

    
104
        protected JDBCStoreProviderWriter(JDBCStoreParameters params,
105
                        DataStoreProviderServices storeServices, DynObject metadata)
106
                        throws InitializeException {
107
                super(params, storeServices, metadata);
108
        }
109

    
110

    
111

    
112
        protected void addToListFeatureValues(FeatureProvider featureProvider,
113
                        FeatureAttributeDescriptor attrOfList,
114
                        FeatureAttributeDescriptor attr, List<Object> values) throws DataException {
115
                if (attr == null) {
116
                        if (attrOfList.isPrimaryKey()) {
117
                                throw new RuntimeException("pk attribute '"
118
                                                + attrOfList.getName() + "' not found in feature");
119
                        }
120
                        values.add(helper
121
                                        .dalValueToJDBC(attr, attrOfList.getDefaultValue()));
122
                } else {
123
                        values.add(helper.dalValueToJDBC(attr, featureProvider.get(attr
124
                                        .getIndex())));
125
                }
126

    
127
        }
128

    
129
        protected void addToListFeatureValues(FeatureProvider featureProvider,
130
                        List<FeatureAttributeDescriptor> attributes, List<Object> values) throws DataException {
131
                FeatureAttributeDescriptor attr, attrOfList;
132
                FeatureType fType = featureProvider.getType();
133
                for (int i = 0; i < attributes.size(); i++) {
134
                        attrOfList = (FeatureAttributeDescriptor) attributes.get(i);
135
                        attr = fType.getAttributeDescriptor(attrOfList.getName());
136
                        addToListFeatureValues(featureProvider, attrOfList, attr, values);
137
                }
138
        }
139

    
140
        protected void appendToSQLPreparedPkWhereClause(StringBuilder sql,
141
                        List<FeatureAttributeDescriptor> pkAttributes) {
142
                sql.append(" Where ");
143
                FeatureAttributeDescriptor attr;
144
                for (int i = 0; i < pkAttributes.size() - 1; i++) {
145
                        attr = (FeatureAttributeDescriptor) pkAttributes.get(i);
146
                        sql.append(helper.escapeFieldName(attr.getName()));
147
                        sql.append(" = ? AND ");
148
                }
149
                attr = (FeatureAttributeDescriptor) pkAttributes.get(pkAttributes
150
                                .size() - 1);
151
                sql.append(helper.escapeFieldName(attr.getName()));
152
                sql.append(" = ? ");
153
        }
154

    
155
        protected void executeRemovePreparedStatement(Connection conn, String sql,
156
                        List<FeatureAttributeDescriptor> attributes, Iterator<FeatureReferenceProviderServices> featureReferences) throws DataException {
157
                                PreparedStatement st;
158
                                try {
159
                                        st = conn.prepareStatement(sql);
160
                                } catch (SQLException e) {
161
                                        throw new JDBCPreparingSQLException(sql, e);
162
                                }
163
                                try {
164
                                        List<Object> values = new ArrayList<Object>();
165
                                        FeatureReferenceProviderServices featureRef;
166
//                                        FeatureType featureType;
167
                                        while (featureReferences.hasNext()) {
168
                                                st.clearParameters();
169
                                                featureRef = featureReferences.next();
170
                                                values.clear();
171
//                                                featureType = this.getFeatureStore()
172
//                                                        .getFeatureType(featureRef.getFeatureTypeId());
173

    
174
                                                Iterator<FeatureAttributeDescriptor> iter = attributes.iterator();
175
                                                FeatureAttributeDescriptor attr;
176
                                                while (iter.hasNext()) {
177
                                                        attr =  iter.next();
178
                                                        values.add( helper.dalValueToJDBC(attr, featureRef
179
                                                                        .getKeyValue(attr.getName())));
180
                                                }
181

    
182
                                                for (int i = 0; i < values.size(); i++) {
183
                                                        st.setObject(i + 1, values.get(i));
184
                                                }
185
                                                try {
186
                                                        int nAffected =st.executeUpdate();
187
                                                        if (nAffected == 0) {
188
                                                                throw new JDBCUpdateWithoutChangesException(sql, values);
189
                                                        }
190
                                                        if (nAffected > 1){
191
                                                                logger.warn("Remove statement affectst to {} rows: {}",
192
                                                                                nAffected, sql);
193
                                                        }
194

    
195
                                                } catch (SQLException e) {
196
                                                        throw new JDBCExecutePreparedSQLException(sql, values, e);
197
                                                }
198

    
199
                                        }
200
                                } catch (SQLException e) {
201
                                        throw new JDBCSQLException(e);
202
                                } finally {
203
                                        try {st.close();} catch (SQLException e) {        };
204
                                }
205

    
206
                        }
207

    
208
        protected void executeUpdatePreparedStatement(Connection conn, String sql,
209
                        List<FeatureAttributeDescriptor> attributes, Iterator<FeatureProvider> featureProviders) throws DataException {
210
                                PreparedStatement st;
211
                                try {
212
                                        st = conn.prepareStatement(sql);
213
                                } catch (SQLException e) {
214
                                        throw new JDBCPreparingSQLException(sql, e);
215
                                }
216
                                try {
217
                                        List<Object> values = new ArrayList<Object>();
218
                                        FeatureProvider featureProvider;
219
                                        while (featureProviders.hasNext()) {
220
                                                st.clearParameters();
221
                                                featureProvider = (FeatureProvider) featureProviders.next();
222
                                                values.clear();
223
                                                addToListFeatureValues(featureProvider, attributes, values);
224
                                                for (int i = 0; i < values.size(); i++) {
225
                                                        st.setObject(i + 1, values.get(i));
226
                                                }
227
                                                try {
228
                                                        if (st.executeUpdate() == 0) {
229
                                                                throw new JDBCUpdateWithoutChangesException(sql, values);
230
                                                        }
231
                                                } catch (SQLException e) {
232
                                                        throw new JDBCExecutePreparedSQLException(sql, values, e);
233
                                                }
234

    
235
                                        }
236
                                } catch (SQLException e) {
237
                                        throw new JDBCSQLException(e);
238
                                } finally {
239
                                        try {st.close();} catch (SQLException e) {        };
240
                                }
241

    
242
                        }
243

    
244
        protected void performDeletes(Connection conn, Iterator<FeatureReferenceProviderServices> deleteds, List<FeatureAttributeDescriptor> pkAttributes)
245
                        throws DataException {
246

    
247
                                if (pkAttributes.size() < 0) {
248
                                        throw new RuntimeException("Operation requires missing pk");
249
                                }
250

    
251
                                // ************ Prepare SQL ****************
252
                                StringBuilder sqlb = new StringBuilder();
253
                                sqlb.append("Delete from ");
254
                                sqlb.append(getJDBCParameters().tableID());
255
                                appendToSQLPreparedPkWhereClause(sqlb, pkAttributes);
256
                                String sql = sqlb.toString();
257
                                // ************ Prepare SQL (end) ****************
258

    
259
                                executeRemovePreparedStatement(conn, sql, pkAttributes, deleteds);
260
                        }
261

    
262
        protected String getSqlStatementAddField(FeatureAttributeDescriptor attr,
263
                        List<String> additionalStatement) throws DataException {
264
                StringBuilder strb = new StringBuilder();
265
                strb.append("ADD ");
266
                strb.append(this.helper.getSqlFieldDescription(attr));
267
                return strb.toString();
268
        }
269

    
270
        protected String getSqlStatementDropField(FeatureAttributeDescriptor attr,List<String> additionalStatement) {
271
                // DROP [ COLUMN ] column
272
                return " DROP COLUMN "
273
                                + this.helper.escapeFieldName(attr.getName());
274

    
275
        }
276

    
277
        public boolean supportsAppendMode() {
278
                return true;
279
        }
280

    
281
        public void endAppend() throws DataException {
282
                appendModeSql = null;
283
                appendModeAttributes = null;
284
        }
285

    
286
        protected List<String> getSqlStatementAlterField(
287
                        FeatureAttributeDescriptor attrOrg,
288
                        FeatureAttributeDescriptor attrTrg, List<String> additionalStatement)
289
                        throws DataException {
290
                //
291
                List<String> actions = new ArrayList<String>();
292
                StringBuilder strb;
293
                if (attrOrg.getDataType() != attrTrg.getDataType()) {
294
                        // ALTER COLUMN {col} TYPE {type} character varying(35)
295
                        strb = new StringBuilder();
296
                        strb.append("ALTER COLUMN ");
297
                        strb.append(helper.escapeFieldName(attrTrg.getName()));
298
                        strb.append(" ");
299
                        strb.append(helper.getSqlColumnTypeDescription(attrTrg));
300

    
301
                        actions.add(strb.toString());
302
                }
303

    
304
                if (attrOrg.allowNull() != attrTrg.allowNull()) {
305
                        // ALTER [ COLUMN ] column { SET | DROP } NOT NULL
306

    
307
                        strb = new StringBuilder();
308
                        strb.append("ALTER COLUMN ");
309
                        strb.append(helper.escapeFieldName(attrTrg.getName()));
310
                        strb.append(' ');
311
                        if (attrTrg.allowNull()) {
312
                                strb.append("SET ");
313
                        } else {
314
                                strb.append("DROP ");
315
                        }
316
                        strb.append("NOT NULL");
317
                        actions.add(strb.toString());
318
                }
319

    
320
                if (attrOrg.getDefaultValue() != attrTrg.getDefaultValue()) {
321
                        if (attrTrg.getDefaultValue() == null) {
322
                                // ALTER [ COLUMN ] column DROP DEFAULT
323

    
324
                                strb = new StringBuilder();
325
                                strb.append("ALTER COLUMN ");
326
                                strb.append(helper.escapeFieldName(attrTrg.getName()));
327
                                strb.append(" DROP DEFAULT");
328
                                actions.add(strb.toString());
329
                        } else if (!attrTrg.getDefaultValue().equals(
330
                                        attrOrg.getDefaultValue())) {
331
                                // ALTER [ COLUMN ] column DROP DEFAULT
332

    
333
                                strb = new StringBuilder();
334
                                strb.append("ALTER COLUMN ");
335
                                strb.append(helper.escapeFieldName(attrTrg.getName()));
336
                                strb.append(" SET DEFAULT");
337
                                strb.append(helper.dalValueToJDBC(attrTrg, attrTrg
338
                                                .getDefaultValue()));
339
                                actions.add(strb.toString());
340
                        }
341
                }
342

    
343
                return actions;
344
        }
345

    
346
        protected void performUpdateTable(Connection conn, FeatureType original,
347
                        FeatureType target) throws DataException {
348

    
349
                /*
350
                 *
351
                 * ALTER TABLE [ ONLY ] name [ * ] action [, ... ]
352
                 */
353

    
354
                List<String> toDrop = new ArrayList<String>();
355
                List<String> toAdd = new ArrayList<String>();
356
                List<String> toAlter = new ArrayList<String>();
357

    
358
                List<String> additionalStatement = new ArrayList<String>();
359

    
360
                FeatureAttributeDescriptor attrOrg;
361
                FeatureAttributeDescriptor attrTrg;
362
                Iterator<FeatureAttributeDescriptor> attrs = FeatureTypeHelper.iterator(original);
363
                while (attrs.hasNext()) {
364
                        attrOrg = (FeatureAttributeDescriptor) attrs.next();
365
                        attrTrg = target.getAttributeDescriptor(attrOrg.getName());
366
                        if (attrTrg == null) {
367
                                toDrop.add(getSqlStatementDropField(attrOrg,
368
                                                additionalStatement));
369
                        } else {
370
                                toAlter.addAll(getSqlStatementAlterField(attrOrg, attrTrg,additionalStatement));
371
                        }
372

    
373
                }
374
                attrs = FeatureTypeHelper.iterator(target);
375
                while (attrs.hasNext()) {
376
                        attrTrg = (FeatureAttributeDescriptor) attrs.next();
377
                        if (original.getAttributeDescriptor(attrTrg.getName()) == null) {
378
                                toAdd.add(getSqlStatementAddField(attrTrg,
379
                                                                additionalStatement));
380
                        }
381
                }
382

    
383
                StringBuilder sqlb = new StringBuilder();
384

    
385
                sqlb.append("ALTER TABLE ");
386
                sqlb.append(getJDBCParameters().tableID());
387
                sqlb.append(' ');
388

    
389
                List<String> actions = new ArrayList<String>();
390
                actions.addAll(toDrop);
391
                actions.addAll(toAlter);
392
                actions.addAll(toAdd);
393

    
394
                Iterator<String> it = actions.iterator();
395
                while (it.hasNext()) {
396
                        if (it.next() == null) {
397
                                it.remove();
398
                        }
399
                }
400

    
401
                it = additionalStatement.iterator();
402
                while (it.hasNext()) {
403
                        if (it.next() == null) {
404
                                it.remove();
405
                        }
406
                }
407

    
408
                if (actions.size() < 1) {
409
                        return;
410
                }
411

    
412
                helper.stringJoin(actions, ", ", sqlb);
413

    
414
                String sql = sqlb.toString();
415

    
416
                Statement st = null;
417

    
418
                try {
419
                        st = conn.createStatement();
420
                } catch (SQLException e1) {
421
                        throw new JDBCSQLException(e1);
422
                }
423
                try {
424
                        st.execute(sql);
425
                        Iterator<String> iter = additionalStatement.iterator();
426
                        while (iter.hasNext()) {
427
                                sql = (String) iter.next();
428
                                st.execute(sql);
429
                        }
430
                } catch (SQLException e1) {
431
                        throw new JDBCExecuteSQLException(sql, e1);
432
                } finally {
433
                        try {
434
                                st.close();
435
                        } catch (Exception e) {
436
                                logger.error("Exception closing statement", e);
437
                        }
438
                        ;
439
                }
440

    
441
        }
442

    
443

    
444
        private void perfomInsert(Connection conn, PreparedStatement insertSt,
445
                        String sql, FeatureProvider feature, List<FeatureAttributeDescriptor> attributes)
446
                        throws DataException {
447

    
448
                try {
449
                        insertSt.clearParameters();
450
                        List<Object> values = new ArrayList<Object>();
451
                        addToListFeatureValues(feature, attributes, values);
452
//                        FeatureAttributeDescriptor attr;
453
                        int j = 1;
454
                        for (int i = 0; i < values.size(); i++) {
455
                                insertSt.setObject(j, values.get(i));
456
                                j++;
457
                        }
458
                        if (logger.isDebugEnabled()) {
459
                                logger.debug("Executing insert. sql={} value={}", new Object[] {
460
                                                sql, values });
461
                        }
462
                        try {
463
                                insertSt.execute();
464
                        } catch (SQLException e) {
465
                                throw new JDBCExecutePreparedSQLException(sql, values, e);
466
                        }
467

    
468
                } catch (SQLException e1) {
469
                        throw new JDBCSQLException(e1);
470
                }
471
        }
472

    
473
        public void append(final FeatureProvider featureProvider) throws DataException {
474
                TransactionalAction action = new TransactionalAction() {
475
                        public Object action(Connection conn) throws DataException {
476

    
477
                                PreparedStatement st;
478
                                try {
479
                                        st = conn.prepareStatement(appendModeSql);
480
                                } catch (SQLException e) {
481
                                        throw new JDBCPreparingSQLException(appendModeSql, e);
482
                                }
483
                                try {
484
                                        perfomInsert(conn, st, appendModeSql, featureProvider,
485
                                                        appendModeAttributes);
486
                                } finally {
487
                                        try {
488
                                                st.close();
489
                                        } catch (SQLException e) {
490
                                        }
491
                                        ;
492
                                }
493
                                return null;
494
                        }
495

    
496
                        public boolean continueTransactionAllowed() {
497
                                return false;
498
                        }
499
                };
500
                try {
501
                        this.helper.doConnectionAction(action);
502

    
503
                        resetCount();
504

    
505
                } catch (Exception e) {
506
                        throw new PerformEditingException(this.getProviderName(), e);
507
                }
508
        }
509

    
510
        protected void prepareAttributeForUpdate(FeatureAttributeDescriptor attr,
511
                        List<String> values) {
512
                values.add(helper.escapeFieldName(attr.getName()) + " = ?");
513
        }
514

    
515
        protected void prepareAttributeForInsert(FeatureAttributeDescriptor attr,
516
                        List<String> fields, List<String> values) {
517

    
518
                fields.add(helper.escapeFieldName(attr.getName()));
519
                values.add("?");
520

    
521
        }
522

    
523

    
524
        protected void prepareSQLAndAttributeListForInsert(StringBuilder sqlb,
525
                        List<FeatureAttributeDescriptor> attributes) throws DataException {
526
                /*
527
                 * INSERT INTO table [ ( column [, ...] ) ] { DEFAULT VALUES | VALUES (
528
                 * { expression | DEFAULT } [, ...] ) [, ...] | query } [ RETURNING * |
529
                 * output_expression [ AS output_name ] [, ...] ]
530
                 */
531

    
532
                sqlb.append("INSERT INTO ");
533
                sqlb.append(getJDBCParameters().tableID());
534

    
535
                sqlb.append(" (");
536

    
537
                FeatureType type = this.getFeatureStore().getDefaultFeatureType();
538

    
539
                List<String> fields = new ArrayList<String>();
540
                List<String> values = new ArrayList<String>();
541

    
542
                Iterator<FeatureAttributeDescriptor> iter = FeatureTypeHelper.iterator(type);
543
                FeatureAttributeDescriptor attr;
544
                while (iter.hasNext()) {
545
                        attr = iter.next();
546
                        if (attr.isAutomatic() || attr.isReadOnly()) {
547
                                continue;
548
                        }
549
                        attributes.add(attr);
550
                        prepareAttributeForInsert(attr, fields, values);
551

    
552
                }
553
                if (attributes.size() < 1) {
554
                        throw new RuntimeException("no fields to set");
555
                }
556

    
557
                helper.stringJoin(fields, ", ", sqlb);
558

    
559
                sqlb.append(") VALUES (");
560
                helper.stringJoin(values, ", ", sqlb);
561

    
562
                sqlb.append(") ");
563

    
564
        }
565

    
566

    
567
        protected void performInserts(Connection conn, Iterator<FeatureProvider> inserteds)
568
                        throws DataException {
569

    
570
                StringBuilder sqlb = new StringBuilder();
571
                List<FeatureAttributeDescriptor> attrs = new ArrayList<FeatureAttributeDescriptor>();
572

    
573
                prepareSQLAndAttributeListForInsert(sqlb, attrs);
574

    
575
                String sql = sqlb.toString();
576
                PreparedStatement st;
577
                try {
578
                        st = conn.prepareStatement(sql);
579
                } catch (SQLException e) {
580
                        throw new JDBCPreparingSQLException(sql, e);
581
                }
582
                try {
583
                        while (inserteds.hasNext()) {
584
                                perfomInsert(conn, st, sql, inserteds.next(),
585
                                                attrs);
586
                        }
587
                } finally {
588
                        try {st.close();} catch (SQLException e) {logger.error("Error closing statement", e);};
589
                }
590
        }
591

    
592
        protected void performUpdates(Connection conn, Iterator<FeatureProvider> updateds,
593
                        List<FeatureAttributeDescriptor> pkAttributes) throws DataException {
594
                /*
595
                 * UPDATE [ ONLY ] table [ [ AS ] alias ] SET { column = { expression |
596
                 * DEFAULT } | ( column [, ...] ) = ( { expression | DEFAULT } [, ...] )
597
                 * } [, ...] [ FROM fromlist ] [ WHERE condition ] [ RETURNING * |
598
                 * output_expression [ AS output_name ] [, ...] ]
599
                 */
600

    
601
                if (pkAttributes.size() < 0) {
602
                        throw new RuntimeException("Operation requires missing pk");
603
                }
604

    
605
                // ************ Prepare SQL ****************
606

    
607
                StringBuilder sqlb = new StringBuilder();
608
                sqlb.append("UPDATE ");
609
                sqlb.append(getJDBCParameters().tableID());
610

    
611
                sqlb.append(" SET ");
612

    
613
                List<String> values = new ArrayList<String>();
614

    
615
                FeatureType type = this.getFeatureStore().getDefaultFeatureType();
616

    
617
                Iterator<FeatureAttributeDescriptor> iter = FeatureTypeHelper.iterator(type);
618
                FeatureAttributeDescriptor attr;
619
                List<FeatureAttributeDescriptor> updateAttrs = new ArrayList<FeatureAttributeDescriptor>();
620
                while (iter.hasNext()) {
621
                        attr = iter.next();
622
                        if (attr.isPrimaryKey() || attr.isAutomatic() || attr.isReadOnly()) {
623
                                continue;
624
                        }
625
                        updateAttrs.add(attr);
626
                        prepareAttributeForUpdate(attr, values);
627

    
628
                }
629
                if (updateAttrs.size() < 1) {
630
                        throw new RuntimeException("no fields to set");
631
                }
632

    
633
                helper.stringJoin(values, ", ", sqlb);
634

    
635
                sqlb.append(' ');
636
                appendToSQLPreparedPkWhereClause(sqlb, pkAttributes);
637

    
638
                String sql = sqlb.toString();
639
                // ************ Prepare SQL (end) ****************
640

    
641
                updateAttrs.addAll(pkAttributes);
642

    
643
                executeUpdatePreparedStatement(conn, sql, updateAttrs, updateds);
644
        }
645

    
646

    
647
        public void beginAppend() throws DataException {
648
                StringBuilder sqlb = new StringBuilder();
649
                List<FeatureAttributeDescriptor> attrs = new ArrayList<FeatureAttributeDescriptor>();
650

    
651
                prepareSQLAndAttributeListForInsert(sqlb, attrs);
652

    
653
                appendModeSql = sqlb.toString();
654
                appendModeAttributes = attrs;
655
        }
656

    
657

    
658
        protected TransactionalAction getPerformChangesAction(
659
                        final Iterator<FeatureReferenceProviderServices> deleteds, 
660
                        final Iterator<FeatureProvider> inserteds,
661
                        final Iterator<FeatureProvider> updateds, 
662
                        final Iterator<FeatureTypeChanged> featureTypesChanged) {
663

    
664
                TransactionalAction action = new TransactionalAction() {
665

    
666
                        public Object action(Connection conn) throws DataException {
667

    
668
                                if (featureTypesChanged.hasNext()) {
669

    
670
                                        FeatureTypeChanged item = featureTypesChanged.next();
671
                                        performUpdateTable(conn, item.getSource(), item.getTarget());
672
                                }
673

    
674
                                List<FeatureAttributeDescriptor> pkAttributes = null;
675
                                if (deleteds.hasNext() || updateds.hasNext()) {
676
                                        pkAttributes = Arrays.asList(getFeatureStore()
677
                                                        .getDefaultFeatureType()
678
                                                        .getPrimaryKey());
679
                                }
680

    
681
                                if (deleteds.hasNext()) {
682
                                        performDeletes(conn, deleteds, pkAttributes);
683
                                }
684

    
685
                                if (updateds.hasNext()) {
686
                                        performUpdates(conn, updateds, pkAttributes);
687
                                }
688

    
689
                                if (inserteds.hasNext()) {
690
                                        performInserts(conn, inserteds);
691
                                }
692

    
693
                                return null;
694
                        }
695

    
696
                        public boolean continueTransactionAllowed() {
697
                                return false;
698
                        }
699

    
700
                };
701

    
702
                return action;
703

    
704
        }
705

    
706
        @SuppressWarnings("unchecked")
707
        public void performChanges(Iterator deleteds, Iterator inserteds,
708
                        Iterator updateds, Iterator featureTypesChanged)
709
                        throws PerformEditingException {
710

    
711
                boolean countChanged = deleteds.hasNext() || inserteds.hasNext();
712

    
713
                try {
714
                        this.helper.doConnectionAction(getPerformChangesAction(deleteds,
715
                                        inserteds, updateds, featureTypesChanged));
716

    
717
                        /*
718
                         * Get rules before initializing feature type
719
                         */
720
                        FeatureRules old_rules = getFeatureStore().getDefaultFeatureType().getRules();
721
                        
722
                        /*
723
                         * This initialization loses the feature type rules
724
                         */
725
                        this.initFeatureType();
726
                        
727
                        /*
728
                         * Get new feature type, clear rules and add
729
                         * the ones saved previously
730
                         */
731
                        FeatureType ft = getFeatureStore().getDefaultFeatureType();
732
                        FeatureRules new_rules = ft.getRules();
733
                        new_rules.clear();
734
                        for (int i=0; i<old_rules.size(); i++) {
735
                            new_rules.add(old_rules.getRule(i));
736
                        }
737
                        // ===================================================
738
                        
739
                        if (countChanged) {
740
                                resetCount();
741
                        }
742

    
743
                } catch (Exception e) {
744
                        throw new PerformEditingException(this.getProviderName(), e);
745
                }
746
        }
747

    
748

    
749
        public boolean allowWrite() {
750
                if (directSQLMode) {
751
                        return false;
752
                }
753
                if (getJDBCParameters().getPkFields() == null
754
                                || getJDBCParameters().getPkFields().length > 0) {
755
                        FeatureType ft = null;
756
                        try {
757
                                ft = this.getFeatureStore().getDefaultFeatureType();
758
                        } catch (DataException e) {
759
                                logger.error("Excepton get default Feature Type", e);
760
                        }
761

    
762
                        if (ft == null) {
763
                                return false;
764
                        }
765
                        FeatureAttributeDescriptor attr;
766
                        Iterator<FeatureAttributeDescriptor> iter = FeatureTypeHelper.iterator(ft);
767
                        while (iter.hasNext()) {
768
                                attr = (FeatureAttributeDescriptor) iter.next();
769
                                if (attr.isPrimaryKey()) {
770
                                        return true;
771
                                }
772
                        }
773
                        return false;
774

    
775
                } else {
776
                        return true;
777
                }
778
        }
779
}