1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package fr.paris.lutece.plugins.importexport.business.importdata;
35
36 import fr.paris.lutece.plugins.importexport.business.AbstractImportExportDAO;
37 import fr.paris.lutece.plugins.importexport.business.ColumnType;
38 import fr.paris.lutece.plugins.importexport.business.ImportExportElement;
39 import fr.paris.lutece.plugins.importexport.business.TableColumn;
40 import fr.paris.lutece.portal.service.i18n.I18nService;
41 import fr.paris.lutece.portal.service.plugin.Plugin;
42 import fr.paris.lutece.portal.service.util.AppException;
43 import fr.paris.lutece.portal.service.util.AppLogService;
44 import fr.paris.lutece.util.sql.DAOUtil;
45 import fr.paris.lutece.util.sql.Transaction;
46
47 import java.sql.Date;
48 import java.sql.SQLException;
49 import java.sql.Timestamp;
50 import java.sql.Types;
51 import java.text.DateFormat;
52 import java.text.ParseException;
53 import java.util.Iterator;
54 import java.util.List;
55 import java.util.Locale;
56
57 import org.apache.commons.codec.DecoderException;
58 import org.apache.commons.codec.binary.Hex;
59 import org.apache.commons.lang3.StringUtils;
60
61
62
63
64
65 public class ImportDataDAO extends AbstractImportExportDAO
66 {
67 private static final String SQL_QUERY_SELECT = " SELECT ";
68 private static final String SQL_QUERY_FROM = " FROM ";
69 private static final String SQL_QUERY_INSERT_INTO = " INSERT INTO ";
70 private static final String SQL_QUERY_VALUES = " VALUES ";
71 private static final String SQL_QUERY_UPDATE = " UPDATE ";
72 private static final String SQL_QUERY_UPDATE_SET = " SET ";
73 private static final String SQL_QUERY_EQUALS = " = ? ";
74 private static final String SQL_QUERY_WHERE = " WHERE ";
75 private static final String SQL_QUERY_AND = " AND ";
76 private static final String SQL_QUERY_DELETE_FROM = " DELETE FROM ";
77
78 private static final String CONSTANT_QUESTION_MARK = "?";
79 private static final String CONSTANT_COMA = ",";
80 private static final String CONSTANT_OPEN_PARENTHESIS = " ( ";
81 private static final String CONSTANT_CLOSE_PARENTHESIS = " ) ";
82 private static final String CONSTANT_SEMICOLON = ";";
83 private static final String CONSTANT_STRING_NULL = "null";
84 private static final String CONSTANT_HEXA_START = "0x";
85
86 private static final String ERROR_EMPTY_TABLE_NAME = "importexport.import_data.errors.emptyTableName";
87 private static final String ERROR_EMPTY_COLUMN_LIST = "importexport.import_data.errors.emptyColumnList";
88 private static final String ERROR_MESSAGE_TRANSACTION_CLOSED = "importexport.import_data.errors.transactionClosed";
89 private static final String ERROR_MESSAGE_WRONG_LIST_ELEMENTS_SIZE = "importexport.import_data.errors.emptyColumnList";
90
91 private String _strSqlInsert;
92 private String _strSqlUpdate;
93 private String _sqlCheckElement;
94 private List<TableColumn> _listTableColumns;
95 private String _strTableName;
96 private Transaction _transaction;
97 private Plugin _plugin;
98 private Locale _locale;
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115 public ImportDataDAO( List<String> listTableColumns, String strTableName, Plugin plugin, Locale locale ) throws AppException
116 {
117 if ( StringUtils.isEmpty( strTableName ) )
118 {
119 throw new AppException( I18nService.getLocalizedString( ERROR_EMPTY_TABLE_NAME, locale ) );
120 }
121 if ( listTableColumns == null || listTableColumns.size( ) == 0 )
122 {
123 throw new AppException( I18nService.getLocalizedString( ERROR_EMPTY_COLUMN_LIST, locale ) );
124 }
125
126
127 this._strTableName = strTableName;
128 this._plugin = plugin;
129 this._locale = locale;
130 this._listTableColumns = getTableColumns( listTableColumns, strTableName, plugin, locale );
131 _transaction = new Transaction( );
132 if ( _transaction.getStatus( ) != Transaction.OPENED )
133 {
134 throw new AppException( I18nService.getLocalizedString( ERROR_MESSAGE_TRANSACTION_CLOSED, _locale ) );
135 }
136 }
137
138
139
140
141
142
143
144
145
146
147
148
149
150 public void insertElement( List<ImportExportElement> listElements ) throws AppException, SQLException
151 {
152 if ( _transaction == null || _transaction.getStatus( ) != Transaction.OPENED )
153 {
154 throw new AppException( I18nService.getLocalizedString( ERROR_MESSAGE_TRANSACTION_CLOSED, _locale ) );
155 }
156 if ( listElements == null || listElements.size( ) != _listTableColumns.size( ) )
157 {
158 AppException appException = new AppException( I18nService.getLocalizedString( ERROR_MESSAGE_WRONG_LIST_ELEMENTS_SIZE, _locale ) );
159 int nElemNumber = 0;
160 if ( listElements != null )
161 {
162 nElemNumber = listElements.size( );
163 }
164 AppLogService.info( appException.getMessage( ) + " expected " + _listTableColumns.size( ) + " elements, found " + nElemNumber );
165 throw appException;
166 }
167 _transaction.prepareStatement( getSqlInsert( ) );
168 int nIndex = 1;
169 Iterator<TableColumn> columnIterator = _listTableColumns.iterator( );
170 for ( ImportExportElement element : listElements )
171 {
172 TableColumn tableColumn = columnIterator.next( );
173
174 if ( !StringUtils.equalsIgnoreCase( tableColumn.getColumnName( ), element.getColumnName( ) ) )
175 {
176 throw new AppException( I18nService.getLocalizedString( ERROR_MESSAGE_WRONG_LIST_ELEMENTS_SIZE, _locale ) );
177 }
178 addSqlParameter( nIndex++, element.getValue( ), tableColumn.getColumnType( ) );
179 }
180 _transaction.executeStatement( );
181 }
182
183
184
185
186
187
188
189
190
191
192
193
194
195 public void updateElement( List<ImportExportElement> listElements ) throws AppException, SQLException
196 {
197 if ( _transaction == null || _transaction.getStatus( ) != Transaction.OPENED )
198 {
199 throw new AppException( I18nService.getLocalizedString( ERROR_MESSAGE_TRANSACTION_CLOSED, _locale ) );
200 }
201 if ( listElements == null || listElements.size( ) != _listTableColumns.size( ) )
202 {
203 AppException appException = new AppException( I18nService.getLocalizedString( ERROR_MESSAGE_WRONG_LIST_ELEMENTS_SIZE, _locale ) );
204 int nElemNumber = 0;
205 if ( listElements != null )
206 {
207 nElemNumber = listElements.size( );
208 }
209 AppLogService.info( appException.getMessage( ) + " expected " + _listTableColumns.size( ) + " elements, found " + nElemNumber );
210 throw appException;
211 }
212 _transaction.prepareStatement( getSqlUpdate( ) );
213 int nIndex = 1;
214 Iterator<TableColumn> columnIterator = _listTableColumns.iterator( );
215 for ( ImportExportElement element : listElements )
216 {
217 TableColumn tableColumn = columnIterator.next( );
218
219 if ( !tableColumn.getIsPrimaryKey( ) )
220 {
221
222 if ( !StringUtils.equalsIgnoreCase( tableColumn.getColumnName( ), element.getColumnName( ) ) )
223 {
224 throw new AppException( I18nService.getLocalizedString( ERROR_MESSAGE_WRONG_LIST_ELEMENTS_SIZE, _locale ) );
225 }
226 addSqlParameter( nIndex++, element.getValue( ), tableColumn.getColumnType( ) );
227 }
228 }
229
230 columnIterator = _listTableColumns.iterator( );
231 for ( ImportExportElement element : listElements )
232 {
233 TableColumn tableColumn = columnIterator.next( );
234 if ( tableColumn.getIsPrimaryKey( ) )
235 {
236 if ( !StringUtils.equalsIgnoreCase( tableColumn.getColumnName( ), element.getColumnName( ) ) )
237 {
238 throw new AppException( I18nService.getLocalizedString( ERROR_MESSAGE_WRONG_LIST_ELEMENTS_SIZE, _locale ) );
239 }
240 addSqlParameter( nIndex++, element.getValue( ), tableColumn.getColumnType( ) );
241 }
242 }
243 _transaction.executeStatement( );
244 }
245
246
247
248
249
250
251
252
253
254
255 public boolean checkElementExists( List<ImportExportElement> listElements ) throws SQLException
256 {
257 if ( listElements == null || listElements.size( ) != _listTableColumns.size( ) )
258 {
259 AppException appException = new AppException( I18nService.getLocalizedString( ERROR_MESSAGE_WRONG_LIST_ELEMENTS_SIZE, _locale ) );
260 int nElemNumber = 0;
261 if ( listElements != null )
262 {
263 nElemNumber = listElements.size( );
264 }
265 AppLogService.info( appException.getMessage( ) + " expected " + _listTableColumns.size( ) + " elements, found " + nElemNumber );
266 throw appException;
267 }
268 DAOUtil daoUtil = new DAOUtil( getSqlCheckElementExists( ), _plugin );
269 boolean bResult = false;
270 try
271 {
272 String strPrimaryKey = listElements.get( 0 ).getValue( );
273 addSqlParameter( 1, strPrimaryKey, _listTableColumns.get( 0 ).getColumnType( ), daoUtil );
274 daoUtil.executeQuery( );
275 if ( daoUtil.next( ) )
276 {
277 bResult = true;
278 }
279 }
280 catch( SQLException e )
281 {
282 AppLogService.error( e.getMessage( ), e );
283 }
284 finally
285 {
286 daoUtil.free( );
287 }
288
289 return bResult;
290 }
291
292
293
294
295
296
297
298 public void emptyTable( ) throws SQLException
299 {
300 _transaction.prepareStatement( SQL_QUERY_DELETE_FROM + _strTableName );
301 _transaction.executeStatement( );
302 }
303
304
305
306
307 public void commitTransaction( )
308 {
309 if ( _transaction != null )
310 {
311 _transaction.commit( );
312 _transaction = null;
313 }
314 else
315 {
316 SQLException sqlException = new SQLException( I18nService.getLocalizedString( ERROR_MESSAGE_TRANSACTION_CLOSED, _locale ) );
317 AppLogService.error( sqlException.getMessage( ), sqlException );
318 }
319 }
320
321
322
323
324 public void rollbackTransaction( )
325 {
326 if ( _transaction != null )
327 {
328 _transaction.rollback( );
329 _transaction = null;
330 }
331 else
332 {
333 SQLException sqlException = new SQLException( I18nService.getLocalizedString( ERROR_MESSAGE_TRANSACTION_CLOSED, _locale ) );
334 AppLogService.error( sqlException.getMessage( ), sqlException );
335 }
336 }
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352 private void addSqlParameter( int nIndex, String strElementValue, ColumnType columnType ) throws SQLException, AppException
353 {
354 try
355 {
356 switch( columnType )
357 {
358 case TYPE_INT:
359 if ( isStringBlankOrNull( strElementValue ) )
360 {
361 _transaction.getStatement( ).setNull( nIndex, Types.INTEGER );
362 }
363 else
364 {
365 _transaction.getStatement( ).setInt( nIndex, Integer.parseInt( strElementValue ) );
366 }
367 break;
368 case TYPE_LONG:
369 if ( isStringBlankOrNull( strElementValue ) )
370 {
371 _transaction.getStatement( ).setNull( nIndex, Types.BIGINT );
372 }
373 else
374 {
375 _transaction.getStatement( ).setLong( nIndex, Long.parseLong( strElementValue ) );
376 }
377 break;
378 case TYPE_DOUBLE:
379 if ( isStringBlankOrNull( strElementValue ) )
380 {
381 _transaction.getStatement( ).setNull( nIndex, Types.DOUBLE );
382 }
383 else
384 {
385 _transaction.getStatement( ).setDouble( nIndex, Double.parseDouble( strElementValue ) );
386 }
387 break;
388 case TYPE_STRING:
389 _transaction.getStatement( ).setString( nIndex, strElementValue );
390 break;
391 case TYPE_TIMESTAMP:
392 Timestamp timestamp;
393 if ( isStringBlankOrNull( strElementValue ) )
394 {
395 timestamp = null;
396 }
397 else
398 {
399
400 if ( StringUtils.isNumeric( strElementValue ) )
401 {
402 timestamp = new Timestamp( Long.parseLong( strElementValue ) );
403 }
404 else
405 {
406
407 try
408 {
409 timestamp = Timestamp.valueOf( strElementValue );
410 }
411 catch( IllegalArgumentException e )
412 {
413 throw new SQLException( e );
414 }
415 }
416 }
417 _transaction.getStatement( ).setTimestamp( nIndex, timestamp );
418 break;
419 case TYPE_DATE:
420 Date date;
421 if ( isStringBlankOrNull( strElementValue ) )
422 {
423 date = null;
424 }
425 else
426 {
427 try
428 {
429 date = new Date( DateFormat.getDateInstance( ).parse( strElementValue ).getTime( ) );
430 }
431 catch( ParseException e )
432 {
433 throw new SQLException( e );
434 }
435 }
436 _transaction.getStatement( ).setDate( nIndex, date );
437 break;
438 case TYPE_BYTE:
439 byte [ ] blobItem;
440 if ( isStringBlankOrNull( strElementValue ) )
441 {
442 blobItem = null;
443 }
444 else
445 {
446 String strValue = strElementValue;
447
448
449 if ( strValue.startsWith( CONSTANT_HEXA_START ) )
450 {
451 strValue = strValue.substring( CONSTANT_HEXA_START.length( ) );
452 }
453 try
454 {
455 blobItem = Hex.decodeHex( strValue.toCharArray( ) );
456 }
457 catch( DecoderException e )
458 {
459 throw new SQLException( e );
460 }
461 }
462 _transaction.getStatement( ).setBytes( nIndex, blobItem );
463 break;
464 default:
465 AppLogService.error( "Unknown column type : " + columnType );
466 }
467 }
468 catch( SQLException e )
469 {
470 AppLogService.error( e.getMessage( ), e );
471 throw e;
472 }
473 }
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491 private void addSqlParameter( int nIndex, String strElementValue, ColumnType columnType, DAOUtil daoUtil ) throws AppException, SQLException
492 {
493 try
494 {
495 switch( columnType )
496 {
497 case TYPE_INT:
498 if ( isStringBlankOrNull( strElementValue ) )
499 {
500 daoUtil.setIntNull( nIndex );
501 }
502 else
503 {
504 daoUtil.setInt( nIndex, Integer.parseInt( strElementValue ) );
505 }
506 break;
507 case TYPE_LONG:
508 if ( isStringBlankOrNull( strElementValue ) )
509 {
510 daoUtil.setLongNull( nIndex );
511 }
512 else
513 {
514 daoUtil.setLong( nIndex, Long.parseLong( strElementValue ) );
515 }
516 break;
517 case TYPE_DOUBLE:
518 if ( isStringBlankOrNull( strElementValue ) )
519 {
520 daoUtil.setDoubleNull( nIndex );
521 }
522 else
523 {
524 daoUtil.setDouble( nIndex, Double.parseDouble( strElementValue ) );
525 }
526 break;
527 case TYPE_STRING:
528 daoUtil.setString( nIndex, strElementValue );
529 break;
530 case TYPE_TIMESTAMP:
531 Timestamp timestamp;
532 if ( isStringBlankOrNull( strElementValue ) )
533 {
534 timestamp = null;
535 }
536 else
537 {
538
539 if ( StringUtils.isNumeric( strElementValue ) )
540 {
541 timestamp = new Timestamp( Long.parseLong( strElementValue ) );
542 }
543 else
544 {
545
546 try
547 {
548 timestamp = Timestamp.valueOf( strElementValue );
549 }
550 catch( IllegalArgumentException e )
551 {
552 throw new AppException( );
553 }
554 }
555 }
556 daoUtil.setTimestamp( nIndex, timestamp );
557 break;
558 case TYPE_DATE:
559 Date date;
560 if ( isStringBlankOrNull( strElementValue ) )
561 {
562 date = null;
563 }
564 else
565 {
566 try
567 {
568 date = new Date( DateFormat.getDateInstance( ).parse( strElementValue ).getTime( ) );
569 }
570 catch( ParseException e )
571 {
572 throw new SQLException( e );
573 }
574 }
575 daoUtil.setDate( nIndex, date );
576 break;
577 case TYPE_BYTE:
578 byte [ ] blobItem;
579 try
580 {
581 blobItem = Hex.decodeHex( strElementValue.toCharArray( ) );
582 }
583 catch( DecoderException e )
584 {
585 throw new SQLException( e );
586 }
587 daoUtil.setBytes( nIndex, blobItem );
588 break;
589 default:
590 AppLogService.error( "Unknown column type : " + columnType );
591 }
592 }
593 catch( SQLException e )
594 {
595 AppLogService.error( e.getMessage( ), e );
596 throw e;
597 }
598 }
599
600
601
602
603
604
605 private String getSqlInsert( )
606 {
607 if ( StringUtils.isNotBlank( _strSqlInsert ) )
608 {
609 return _strSqlInsert;
610 }
611 int nListSize = _listTableColumns.size( );
612 StringBuilder sbSql = new StringBuilder( SQL_QUERY_INSERT_INTO );
613 sbSql.append( _strTableName );
614 sbSql.append( CONSTANT_OPEN_PARENTHESIS );
615 sbSql.append( _listTableColumns.get( 0 ).getColumnName( ) );
616 for ( int i = 1; i < nListSize; i++ )
617 {
618 sbSql.append( CONSTANT_COMA );
619 sbSql.append( _listTableColumns.get( i ).getColumnName( ) );
620 }
621 sbSql.append( CONSTANT_CLOSE_PARENTHESIS );
622 sbSql.append( SQL_QUERY_VALUES );
623 sbSql.append( CONSTANT_OPEN_PARENTHESIS );
624 sbSql.append( CONSTANT_QUESTION_MARK );
625 for ( int i = 1; i < nListSize; i++ )
626 {
627 sbSql.append( CONSTANT_COMA );
628 sbSql.append( CONSTANT_QUESTION_MARK );
629 }
630 sbSql.append( CONSTANT_CLOSE_PARENTHESIS );
631 sbSql.append( CONSTANT_SEMICOLON );
632
633 _strSqlInsert = sbSql.toString( );
634 return _strSqlInsert;
635 }
636
637
638
639
640
641
642 private String getSqlUpdate( )
643 {
644 if ( StringUtils.isNotBlank( _strSqlUpdate ) )
645 {
646 return _strSqlUpdate;
647 }
648 StringBuilder sbSql = new StringBuilder( SQL_QUERY_UPDATE );
649 sbSql.append( _strTableName );
650 sbSql.append( SQL_QUERY_UPDATE_SET );
651
652 boolean bIsFirstColumn = true;
653 for ( TableColumn tableColumn : _listTableColumns )
654 {
655 if ( !tableColumn.getIsPrimaryKey( ) )
656 {
657 if ( bIsFirstColumn )
658 {
659 bIsFirstColumn = false;
660 }
661 else
662 {
663 sbSql.append( CONSTANT_COMA );
664 }
665 sbSql.append( tableColumn.getColumnName( ) );
666 sbSql.append( SQL_QUERY_EQUALS );
667 }
668 }
669 sbSql.append( SQL_QUERY_WHERE );
670 bIsFirstColumn = true;
671 for ( TableColumn tableColumn : _listTableColumns )
672 {
673 if ( tableColumn.getIsPrimaryKey( ) )
674 {
675 if ( bIsFirstColumn )
676 {
677 bIsFirstColumn = false;
678 }
679 else
680 {
681 sbSql.append( SQL_QUERY_AND );
682 }
683 sbSql.append( tableColumn.getColumnName( ) );
684 sbSql.append( SQL_QUERY_EQUALS );
685 }
686 }
687
688 _strSqlUpdate = sbSql.toString( );
689 return _strSqlUpdate;
690 }
691
692
693
694
695
696
697 private String getSqlCheckElementExists( )
698 {
699 if ( StringUtils.isNotBlank( _sqlCheckElement ) )
700 {
701 return _sqlCheckElement;
702 }
703 StringBuilder sbSql = new StringBuilder( SQL_QUERY_SELECT );
704 sbSql.append( _listTableColumns.get( 0 ).getColumnName( ) );
705 sbSql.append( SQL_QUERY_FROM );
706 sbSql.append( _strTableName );
707 sbSql.append( SQL_QUERY_WHERE );
708 sbSql.append( _listTableColumns.get( 0 ).getColumnName( ) );
709 sbSql.append( SQL_QUERY_EQUALS );
710 _sqlCheckElement = sbSql.toString( );
711 return _sqlCheckElement;
712 }
713
714
715
716
717
718
719
720
721 private boolean isStringBlankOrNull( String strString )
722 {
723 return StringUtils.isBlank( strString ) || StringUtils.equalsIgnoreCase( strString, CONSTANT_STRING_NULL );
724 }
725
726
727
728
729
730
731
732 @Override
733 protected void finalize( ) throws Throwable
734 {
735 if ( _transaction != null )
736 {
737 _transaction.rollback( );
738 }
739 super.finalize( );
740 }
741 }