001/*
002 *  Copyright 2018 Anyware Services
003 *
004 *  Licensed under the Apache License, Version 2.0 (the "License");
005 *  you may not use this file except in compliance with the License.
006 *  You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *  Unless required by applicable law or agreed to in writing, software
011 *  distributed under the License is distributed on an "AS IS" BASIS,
012 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *  See the License for the specific language governing permissions and
014 *  limitations under the License.
015 */
016package org.ametys.plugins.contentio.export.component;
017
018import java.io.IOException;
019import java.sql.Connection;
020import java.sql.PreparedStatement;
021import java.sql.SQLException;
022import java.util.ArrayList;
023import java.util.Arrays;
024import java.util.Date;
025import java.util.LinkedList;
026import java.util.List;
027import java.util.Locale;
028import java.util.Map;
029import java.util.Map.Entry;
030
031import javax.jcr.RepositoryException;
032
033import org.apache.avalon.framework.component.Component;
034import org.apache.avalon.framework.context.ContextException;
035import org.apache.avalon.framework.service.ServiceException;
036import org.apache.avalon.framework.service.ServiceManager;
037import org.apache.avalon.framework.service.Serviceable;
038import org.apache.commons.lang.StringUtils;
039
040import org.ametys.cms.contenttype.ContentType;
041import org.ametys.cms.contenttype.ContentTypeExtensionPoint;
042import org.ametys.cms.contenttype.MetadataDefinition;
043import org.ametys.cms.contenttype.MetadataDefinitionHolder;
044import org.ametys.cms.contenttype.RepeaterDefinition;
045import org.ametys.cms.languages.LanguagesManager;
046import org.ametys.cms.repository.Content;
047import org.ametys.cms.repository.ContentQueryHelper;
048import org.ametys.cms.repository.ContentTypeExpression;
049import org.ametys.core.datasource.ConnectionHelper;
050import org.ametys.core.user.User;
051import org.ametys.core.user.UserIdentity;
052import org.ametys.core.user.UserManager;
053import org.ametys.core.util.I18nUtils;
054import org.ametys.plugins.contentio.export.ExportManager;
055import org.ametys.plugins.contentio.export.object.ExportConfiguration;
056import org.ametys.plugins.contentio.export.object.ExportCounter;
057import org.ametys.plugins.contentio.export.object.ExportTableInfo;
058import org.ametys.plugins.repository.AmetysObjectIterable;
059import org.ametys.plugins.repository.AmetysObjectResolver;
060import org.ametys.plugins.repository.AmetysRepositoryException;
061import org.ametys.plugins.repository.metadata.BinaryMetadata;
062import org.ametys.plugins.repository.metadata.CompositeMetadata;
063import org.ametys.plugins.repository.metadata.File;
064import org.ametys.plugins.repository.metadata.Folder;
065import org.ametys.plugins.repository.metadata.MultilingualString;
066import org.ametys.plugins.repository.metadata.Resource;
067import org.ametys.plugins.repository.metadata.RichText;
068import org.ametys.plugins.repository.metadata.UnknownMetadataException;
069import org.ametys.plugins.repository.metadata.jcr.JCRCompositeMetadata;
070import org.ametys.plugins.repository.query.expression.Expression.Operator;
071import org.ametys.plugins.repository.version.VersionableAmetysObject;
072import org.ametys.runtime.config.Config;
073import org.ametys.runtime.i18n.I18nizableText;
074import org.ametys.runtime.plugin.component.AbstractLogEnabled;
075
076/**
077 * Fill sql table component
078 */
079public class FillSqlTableComponent extends AbstractLogEnabled implements Component, Serviceable
080{
081    /** The component role */
082    public static final String ROLE = FillSqlTableComponent.class.getName();
083    
084    private static final String _EXCLUDE_XML_TAGS = "<(.*?)>";
085    
086    /** Content type extension point. */
087    protected ContentTypeExtensionPoint _contentTypeExtensionPoint;
088  
089    /** The ametys object resolver. */
090    protected AmetysObjectResolver _resolver;
091  
092    /** The normalise name component. */
093    protected NormalizeNameComponent _normaliseNameComponent;
094    
095    /** The configured list of content types to export associated to the SQL table name to use */
096    protected Map<String, String> _contentTypesToExport;
097    
098    /** The i18n translator. */
099    protected I18nUtils _i18nTranslator;
100    
101    /** The language manager */
102    protected LanguagesManager _languageManager;
103    
104    /** The user manager */
105    protected UserManager _userManager;
106
107    private Connection _connection;
108    private String _sqlTablePrefix;
109    private String _sqlPrefixConf;
110    private Map<String, ExportTableInfo> _tablesInfos;
111    private String _mappingPolicy;
112    private LinkedList<PreparedStatement> _stmtList;
113    private boolean _exportOnlyValidatedContent;
114    private boolean _exportNoMultiValuedTable;
115    private String _separator;
116    
117    public void service(ServiceManager manager) throws ServiceException
118    {
119        _contentTypeExtensionPoint = (ContentTypeExtensionPoint) manager.lookup(ContentTypeExtensionPoint.ROLE);
120        _resolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE);
121        _normaliseNameComponent = (NormalizeNameComponent) manager.lookup(NormalizeNameComponent.ROLE);
122        _i18nTranslator = (I18nUtils) manager.lookup(I18nUtils.ROLE);
123        _languageManager = (LanguagesManager) manager.lookup(LanguagesManager.ROLE);
124        _userManager = (UserManager) manager.lookup(UserManager.ROLE);
125    }
126    
127    /**
128     * Fill table with contents
129     * @param exportConfiguration the content export configuration
130     * @param tableInfo the map of table information
131     * @throws SQLException if a sql error occurred
132     * @throws ContextException if a context error occurred
133     * @throws AmetysRepositoryException if an ametys repository error occurred
134     */
135    public synchronized void fillTable(ExportConfiguration exportConfiguration, Map<String, ExportTableInfo> tableInfo) throws SQLException, AmetysRepositoryException, ContextException
136    {
137        // Get from configuration
138        _sqlTablePrefix = exportConfiguration.getTablePrefix();
139        _sqlPrefixConf = exportConfiguration.getTablePrefix();
140        _mappingPolicy = exportConfiguration.getMappingPolicy();
141        _contentTypesToExport = exportConfiguration.getContentTypesToExport();
142        _exportOnlyValidatedContent = exportConfiguration.exportOnlyValidatedContent();
143        _exportNoMultiValuedTable = exportConfiguration.exportNoMultiValuedTable();
144        _separator = exportConfiguration.getSeparator();
145
146        // Initialization
147        _tablesInfos = tableInfo;
148        _stmtList = new LinkedList<>();
149        
150        try
151        {
152            String datasourceId = Config.getInstance().getValue("org.ametys.plugins.contentio.content.export.datasource");
153            _connection = ConnectionHelper.getConnection(datasourceId); 
154            insertValues();
155        }
156        finally
157        {
158            ConnectionHelper.cleanup(_connection);
159            _sqlTablePrefix = null;
160            _sqlPrefixConf = null;
161            _mappingPolicy = null;
162            _contentTypesToExport = null;
163            _separator = null;
164            _stmtList = null;
165        }
166    }
167    
168    private void executeInsert() throws SQLException
169    {
170        for (PreparedStatement stmt : _stmtList)
171        {
172            try
173            {
174                if (getLogger().isDebugEnabled())
175                {
176                    getLogger().debug("Query : {}", stmt.toString());
177                }
178                stmt.executeBatch();
179            }
180            catch (SQLException e)
181            {
182                throw new SQLException(_i18nTranslator.translate(new I18nizableText("plugin.contentio", "PLUGINS_CONTENTIO_CONTENT_EXPORT_LOG_FILL_ERROR_SQL")), e);
183            }
184            finally
185            {
186                ConnectionHelper.cleanup(stmt);
187            }
188        }
189        
190        _stmtList.clear();
191    }
192
193    /**
194     * Fill the SQL tables with values from JCR
195     * @throws SQLException if a sql error occurred
196     * @throws ContextException if a context error occurred
197     * @throws AmetysRepositoryException if an ametys repository error occurred
198     */
199    protected void insertValues() throws SQLException, AmetysRepositoryException, ContextException
200    {
201        boolean isInfoEnabled = getLogger().isInfoEnabled();
202        
203        int nbTotalTypeContenu = _contentTypesToExport.entrySet().size();
204        if (isInfoEnabled && nbTotalTypeContenu != 0)
205        {
206            List<String> i18nParams = new ArrayList<>();
207            i18nParams.add(String.valueOf(nbTotalTypeContenu));
208            getLogger().info(_i18nTranslator.translate(new I18nizableText("plugin.contentio", "PLUGINS_CONTENTIO_CONTENT_EXPORT_LOG_FILL_ANALYZE_BEGIN", i18nParams)));
209        }
210        
211        int nbTypeContenu = 0;
212        int pourcentMax = 10;
213        for (Entry<String, String> entry : _contentTypesToExport.entrySet()) 
214        {
215            String contentTypeId = entry.getKey();
216            ContentType contentType = _contentTypeExtensionPoint.getExtension(contentTypeId);
217            
218            if (!contentType.isAbstract())
219            {
220                _sqlTablePrefix = entry.getValue();
221                
222                if (isInfoEnabled)
223                {
224                    List<String> i18nParams = new ArrayList<>();
225                    i18nParams.add(String.valueOf(entry.getValue()));
226                    getLogger().info(_i18nTranslator.translate(new I18nizableText("plugin.contentio", "PLUGINS_CONTENTIO_CONTENT_EXPORT_LOG_FILL_CONTENT_TYPE", i18nParams)));
227                }
228                
229                fillTableForContentType(contentTypeId);
230            }
231            
232            int pourcent = nbTypeContenu * 100 / nbTotalTypeContenu;
233            if (pourcent >= pourcentMax)
234            {
235                if (isInfoEnabled)
236                {
237                    List<String> i18nParams = new ArrayList<>();
238                    i18nParams.add(String.valueOf(pourcentMax));
239                    getLogger().info(_i18nTranslator.translate(new I18nizableText("plugin.contentio", "PLUGINS_CONTENTIO_CONTENT_EXPORT_LOG_FILL_ANALYZE", i18nParams)));
240                }
241                pourcentMax += 10;
242            }
243            
244            nbTypeContenu++;
245            _sqlTablePrefix = _sqlPrefixConf;
246        }
247        
248        if (isInfoEnabled)
249        {
250            getLogger().info(_i18nTranslator.translate(new I18nizableText("plugin.contentio", "PLUGINS_CONTENTIO_CONTENT_EXPORT_LOG_FILL_END")));
251        }
252    }
253    
254    /**
255     * Fill values from JCR request with specific content type
256     * @param contentTypeId the content type id
257     * @throws SQLException if a sql error occurred
258     * @throws ContextException if a context error occurred
259     * @throws AmetysRepositoryException if an ametys repository error occurred
260     */
261    protected void fillTableForContentType(String contentTypeId) throws SQLException, AmetysRepositoryException, ContextException
262    {
263        String tableName = getTableName(contentTypeId);
264        
265        ContentTypeExpression typeE = new ContentTypeExpression(Operator.EQ, contentTypeId);
266        String xpath = ContentQueryHelper.getContentXPathQuery(typeE);
267        AmetysObjectIterable<Content> contents = _resolver.query(xpath);
268        
269        ContentType cType = _contentTypeExtensionPoint.getExtension(contentTypeId);
270
271        boolean isInfoEnabled = getLogger().isInfoEnabled();
272        
273        int nbTotalContent = (int) contents.getSize();
274        if (isInfoEnabled && nbTotalContent != 0)
275        {
276            List<String> i18nParams = new ArrayList<>();
277            i18nParams.add(String.valueOf(nbTotalContent));
278            getLogger().info(_i18nTranslator.translate(new I18nizableText("plugin.contentio", "PLUGINS_CONTENTIO_CONTENT_EXPORT_LOG_FILL_NB_CONTENT_MAX", i18nParams)));
279        }
280        
281        int nbContent = 0;
282        int pourcentMax = 10;
283        for (Content content : contents)
284        {
285            List<String> labels = Arrays.asList(((VersionableAmetysObject) content).getAllLabels());
286            boolean exportContent = true;
287            if (_exportOnlyValidatedContent)
288            {
289                if (labels.contains("Live"))
290                {
291                    ((VersionableAmetysObject) content).switchToLabel("Live");
292                }
293                else
294                {
295                    exportContent = false;
296                }
297            }
298            
299            if (exportContent)
300            {
301                String id = content.getId();
302                PreparedStatement stmt = null;
303                try 
304                {
305                    stmt = getInsertPreparedStatementFromTableName(_sqlTablePrefix, tableName, _mappingPolicy);
306                    stmt.setString(1, id);
307                    
308                    getLogger().debug(" with id: {}", id);
309                    
310                    ExportCounter fillIndex = new ExportCounter(2);
311                    CompositeMetadata metadata = content.getMetadataHolder();
312                    fillCompositeMetadata(fillIndex, content, cType, metadata, tableName, "", id, stmt);
313                    stmt.execute();
314                }
315                finally
316                {
317                    ConnectionHelper.cleanup(stmt);
318                }
319                
320                _fillContentTable(id, tableName);
321                executeInsert();
322                
323                int pourcent = nbContent * 100 / nbTotalContent;
324                if (pourcent >= pourcentMax)
325                {
326                    if (isInfoEnabled)
327                    {
328                        List<String> i18nParams = new ArrayList<>();
329                        i18nParams.add(String.valueOf(pourcentMax));
330                        getLogger().info(_i18nTranslator.translate(new I18nizableText("plugin.contentio", "PLUGINS_CONTENTIO_CONTENT_EXPORT_LOG_FILL_NB_CONTENT_FILL", i18nParams)));
331                    }
332                    pourcentMax += 10;
333                }
334                
335                nbContent++;
336            }
337        }
338        
339        if (isInfoEnabled && nbTotalContent != 0)
340        {
341            getLogger().info(_i18nTranslator.translate(new I18nizableText("plugin.contentio", "PLUGINS_CONTENTIO_CONTENT_EXPORT_LOG_FILL_NB_CONTENT_FILL_MAX")));
342        }
343    }
344    
345    private void _fillContentTable(String idContent, String tableName) throws SQLException, ContextException
346    {
347        String dataTableName = _sqlPrefixConf + ExportManager.CONTENT_TABLE_NAME;
348        PreparedStatement stmt = getInsertPreparedStatementFromTableName(_sqlPrefixConf, dataTableName, "FULL");
349        _stmtList.add(stmt);
350        
351        stmt.setString(1, idContent);
352        stmt.setString(2, tableName);
353
354        stmt.addBatch();
355        
356        if (getLogger().isDebugEnabled())
357        {
358            getLogger().debug(stmt.toString());
359        }
360    }
361
362    /**
363     * Fill values from a repeater metadata
364     * @param metadataDef the metadata definition model
365     * @param metadata the composite metadata
366     * @param tableName the table name
367     * @param id the content id
368     * @throws SQLException if a sql error occurred
369     * @throws ContextException if a context error occurred
370     * @throws AmetysRepositoryException if an ametys repository error occurred
371     */
372    protected void fillTableForRepeater(MetadataDefinition metadataDef, CompositeMetadata metadata, String tableName, String id) throws SQLException, AmetysRepositoryException, ContextException
373    {
374        PreparedStatement stmt = getInsertPreparedStatementFromTableName(_sqlTablePrefix, tableName, _mappingPolicy);
375        _stmtList.add(stmt);
376        
377        int position = 1;
378        for (String name : metadata.getMetadataNames())
379        {
380            String idRepeater = id + "@" + name;
381
382            stmt.setString(1, idRepeater);
383            stmt.setString(2, id);
384            stmt.setInt(3, position);
385            position++;
386            
387            ExportCounter fillIndex = new ExportCounter(4);
388
389            CompositeMetadata metadataRepeater = metadata.getCompositeMetadata(name);
390
391            fillCompositeMetadata(fillIndex, null, metadataDef, metadataRepeater, tableName, "", idRepeater, stmt);
392            
393            if (getLogger().isDebugEnabled())
394            {
395                getLogger().debug(stmt.toString());
396            }
397            stmt.addBatch();
398        }
399    }
400
401    /**
402     * Fill values from a composite metadata
403     * @param fillIndex the position indicator in the insert statement 
404     * @param content the content
405     * @param metadataDef the metadata definition model
406     * @param metadata the composite metadata
407     * @param tableName the table name
408     * @param columnNamePrefix the column name prefix
409     * @param id the content id
410     * @param stmt the jdbc statement
411     * @throws SQLException if a sql error occurred
412     * @throws ContextException if a context error occurred
413     * @throws AmetysRepositoryException if an ametys repository error occurred
414     */
415    protected void fillCompositeMetadata(ExportCounter fillIndex, Content content, MetadataDefinitionHolder metadataDef, CompositeMetadata metadata, String tableName, String columnNamePrefix, String id, PreparedStatement stmt) throws SQLException, AmetysRepositoryException, ContextException
416    {
417        for (String childMetadataName : metadataDef.getMetadataNames())
418        {
419            MetadataDefinition metadataDefComposite = metadataDef.getMetadataDefinition(childMetadataName);
420            if (metadataDefComposite.isMultiple() && !_exportNoMultiValuedTable)
421            {
422                if (metadata != null && metadata.hasMetadata(childMetadataName))
423                {
424                    String newTableName = StringUtils.isBlank(columnNamePrefix) ? tableName + "_" + childMetadataName : tableName + "_" + columnNamePrefix + "_" + childMetadataName;
425                    fillTableForMultipleMetadata(metadataDefComposite, metadata, childMetadataName, newTableName, id);
426                }
427            }
428            else
429            {
430                fillMetadata(fillIndex, metadataDefComposite, metadata, childMetadataName, tableName, columnNamePrefix, id, stmt);
431            }
432        }
433        
434        fillAdditionnalValueForContentMetadata(fillIndex, content, stmt);
435    }
436    
437    
438    /**
439     * Add additional values for content (Title, type, language, creator, creationDate, ...)
440     * @param fillIndex the position indicator in the insert statement 
441     * @param content the content
442     * @param stmt the jdbc statement
443     * @throws SQLException if a sql error occurred
444     * @throws UnknownMetadataException if a metadata error occurred
445     * @throws AmetysRepositoryException if an ametys repository error occurred
446     */
447    protected void fillAdditionnalValueForContentMetadata(ExportCounter fillIndex, Content content, PreparedStatement stmt) throws UnknownMetadataException, AmetysRepositoryException, SQLException
448    {
449        if (content != null)
450        {
451            stmt.setString(fillIndex.getCount(), content.getTitle());
452            fillIndex.incrementCount();
453            stmt.setString(fillIndex.getCount(), content.getTypes()[0]);
454            fillIndex.incrementCount();
455            //TODO site for webContent
456            stmt.setString(fillIndex.getCount(), content.getLanguage());
457            fillIndex.incrementCount();
458            stmt.setString(fillIndex.getCount(), content.getCreator().getLogin());
459            fillIndex.incrementCount();
460            if (content.getCreationDate() != null)
461            {
462                java.sql.Date sqlCreationDate = new java.sql.Date(content.getCreationDate().getTime());
463                stmt.setDate(fillIndex.getCount(), sqlCreationDate);
464            }
465            else
466            {
467                stmt.setNull(fillIndex.getCount(), java.sql.Types.DATE);
468            }
469            fillIndex.incrementCount();
470            stmt.setString(fillIndex.getCount(), content.getLastContributor().getLogin());
471            fillIndex.incrementCount();
472            if (content.getLastModified() != null)
473            {
474                java.sql.Date sqlLastModificationDate = new java.sql.Date(content.getLastModified().getTime());
475                stmt.setDate(fillIndex.getCount(), sqlLastModificationDate);
476            }
477            else
478            {
479                stmt.setNull(fillIndex.getCount(), java.sql.Types.DATE);
480            }
481            fillIndex.incrementCount();
482            if (content.getLastValidationDate() != null)
483            {
484                java.sql.Date sqlLastValidationDate = new java.sql.Date(content.getLastValidationDate().getTime());
485                stmt.setDate(fillIndex.getCount(), sqlLastValidationDate);
486            }
487            else
488            {
489                stmt.setNull(fillIndex.getCount(), java.sql.Types.DATE);
490            }
491            fillIndex.incrementCount();
492            if (content.getLastMajorValidationDate() != null)
493            {
494                java.sql.Date sqlLastMajorValidationDate = new java.sql.Date(content.getLastMajorValidationDate().getTime());
495                stmt.setDate(fillIndex.getCount(), sqlLastMajorValidationDate);
496            }
497            else
498            {
499                stmt.setNull(fillIndex.getCount(), java.sql.Types.DATE);
500            }
501            fillIndex.incrementCount();
502        }
503    }
504
505    /**
506     * Fill values from a metadata
507     * @param fillIndex the position indicator in the insert statement 
508     * @param metadataDef the metadata definition model
509     * @param compositeMetadata the composite metadata
510     * @param metadataName the metadata name
511     * @param tableName the table name
512     * @param columnPrefix the column prefix
513     * @param id the content id
514     * @param stmt the jdbc statement
515     * @throws SQLException if a sql error occurred
516     * @throws ContextException if a context error occurred
517     * @throws AmetysRepositoryException if an ametys repository error occurred
518     */
519    protected void fillMetadata(ExportCounter fillIndex, MetadataDefinition metadataDef, CompositeMetadata compositeMetadata, String metadataName, String tableName, String columnPrefix, String id, PreparedStatement stmt) throws SQLException, AmetysRepositoryException, ContextException
520    {
521        boolean isMultiple = metadataDef.isMultiple();
522        switch (metadataDef.getType())
523        {
524            case USER:
525                fillColumnForUserMetadata(stmt, fillIndex, compositeMetadata, metadataName, isMultiple);
526                break;
527            case STRING:
528            case CONTENT:
529                fillColumnForStringMetadata(stmt, fillIndex, compositeMetadata, metadataName, isMultiple);
530                break;
531            case MULTILINGUAL_STRING:
532                fillColumnForMultilangualStringMetadata(stmt, fillIndex, compositeMetadata, metadataName, isMultiple);
533                break;
534            case LONG:
535                fillColumnForLongMetadata(stmt, fillIndex, compositeMetadata, metadataName, isMultiple);
536                break;
537            case BOOLEAN:
538                fillColumnForBooleanMetadata(stmt, fillIndex, compositeMetadata, metadataName, isMultiple);
539                break;
540            case DATE:
541            case DATETIME:
542                fillColumnForDateMetadata(stmt, fillIndex, compositeMetadata, metadataName, isMultiple);
543                break;
544            case DOUBLE:
545                fillColumnForDoubleMetadata(stmt, fillIndex, compositeMetadata, metadataName, isMultiple);
546                break;
547            case RICH_TEXT:
548                fillColumnForRichTextMetadata(stmt, fillIndex, compositeMetadata, metadataName, id);
549                break;
550            case FILE:
551                fillColumnForFileMetadata(stmt, fillIndex, compositeMetadata, metadataName);
552                break;
553            case BINARY:
554                fillColumnForBinaryMetadata(stmt, fillIndex, compositeMetadata, metadataName);
555                break;
556            case GEOCODE:
557                fillColumnForGeocodeMetadata(stmt, fillIndex, compositeMetadata, metadataName, isMultiple);
558                break;
559            case REFERENCE:
560            case COMPOSITE:
561                if (metadataDef instanceof RepeaterDefinition)
562                {
563                    if (compositeMetadata != null && compositeMetadata.hasMetadata(metadataName))
564                    {
565                        String newTableName = StringUtils.isBlank(columnPrefix) ? tableName + "_" + metadataName : tableName + "_" + columnPrefix + "_" + metadataName;
566                        fillTableForRepeater(metadataDef, compositeMetadata.getCompositeMetadata(metadataName), newTableName, id);
567                    }
568                }
569                else
570                {
571                    CompositeMetadata childCompositeMetadata = compositeMetadata.hasMetadata(metadataName) ? compositeMetadata.getCompositeMetadata(metadataName) : null;
572                    String newColumnPrefix = StringUtils.isBlank(columnPrefix) ? metadataName : columnPrefix + "_" + metadataName;
573                    fillCompositeMetadata(fillIndex, null, metadataDef, childCompositeMetadata, tableName, newColumnPrefix, id, stmt);
574                }
575                break;
576            default:
577                break;
578        }
579    }
580    
581    
582    /**
583     * Fill values from multiple metadata
584     * @param metadataDefComposite the metadata definition model
585     * @param metadataComposite the composite metadata
586     * @param metadataName the metadata name
587     * @param tableName the table name
588     * @param id the content id
589     * @throws SQLException if a sql error occurred
590     * @throws ContextException if a context error occurred
591     */
592    protected void fillTableForMultipleMetadata(MetadataDefinition metadataDefComposite, CompositeMetadata metadataComposite, String metadataName, String tableName, String id) throws SQLException, ContextException
593    {
594        PreparedStatement stmt = getInsertPreparedStatementFromTableName(_sqlTablePrefix, tableName, _mappingPolicy);
595        _stmtList.add(stmt);
596        
597        stmt.setString(1, id);
598        
599        ExportCounter fillIndex = new ExportCounter(2);
600        
601        fillMetadata(fillIndex, metadataDefComposite, metadataComposite, metadataName, tableName, "", id, stmt);
602    }
603
604    /**
605     * Fill column for Date metadata
606     * @param stmt the jdbc statement
607     * @param fillIndex the position indicator in the insert statement 
608     * @param metadata the composite metadata
609     * @param metadataName the metadata name
610     * @param multiple <code>true</code> if the metadata is multiple
611     * @throws SQLException if a sql error occurred
612     */
613    private void fillColumnForDateMetadata(PreparedStatement stmt, ExportCounter fillIndex, CompositeMetadata metadata, String metadataName, boolean multiple) throws SQLException
614    {
615        if (multiple)
616        {
617            if (_exportNoMultiValuedTable)
618            {
619                String multipleValue = "";
620                if (metadata.hasMetadata(metadataName))
621                {
622                    Date[] values = metadata.getDateArray(metadataName, new Date[0]);
623                    for (int i = 0; i < values.length; i++)
624                    {
625                        if (i != 0)
626                        {
627                            multipleValue += _separator;
628                        }
629                         
630                        multipleValue += String.valueOf(values[i]);
631                    }
632                }
633
634                if (StringUtils.isNotBlank(multipleValue))
635                {
636                    stmt.setString(fillIndex.getCount(), multipleValue);
637                }
638                else
639                {
640                    stmt.setNull(fillIndex.getCount(), java.sql.Types.VARCHAR);
641                }
642                fillIndex.incrementCount();
643            }
644            else
645            {
646                int position = 1;
647                for (Date value : metadata.getDateArray(metadataName, new Date[0]))
648                {
649                    java.sql.Date sqlDate = new java.sql.Date(value.getTime());
650                    stmt.setDate(2, sqlDate);
651                    stmt.setInt(3, position);
652                    position++;
653                    
654                    if (getLogger().isDebugEnabled())
655                    {
656                        getLogger().debug(stmt.toString());
657                    }
658                    stmt.addBatch();
659                }
660            }
661        }
662        else
663        {
664            if (metadata != null && metadata.hasMetadata(metadataName))
665            {
666                try
667                {
668                    java.sql.Date sqlDate = new java.sql.Date(metadata.getDate(metadataName).getTime());
669                    stmt.setDate(fillIndex.getCount(), sqlDate);
670                }
671                catch (AmetysRepositoryException e)
672                {
673                    List<String> i18nParams = new ArrayList<>();
674                    i18nParams.add(metadataName);
675                    i18nParams.add(_getCompositeMetadataPath(metadata));
676                    i18nParams.add("date");
677                    getLogger().error(_i18nTranslator.translate(new I18nizableText("plugin.contentio", "PLUGINS_CONTENTIO_CONTENT_EXPORT_LOG_FILL_ERROR_GET_VALUE", i18nParams)), e);
678                    stmt.setNull(fillIndex.getCount(), java.sql.Types.DATE);
679                }
680            }
681            else
682            {
683                stmt.setNull(fillIndex.getCount(), java.sql.Types.DATE);
684            }
685            fillIndex.incrementCount();
686        }
687    }
688
689    /**
690     * Fill column for Boolean metadata
691     * @param stmt the jdbc statement
692     * @param fillIndex the position indicator in the insert statement 
693     * @param metadata the composite metadata
694     * @param metadataName the metadata name
695     * @param multiple <code>true</code> if the metadata is multiple
696     * @throws SQLException if a sql error occurred
697     */
698    private void fillColumnForBooleanMetadata(PreparedStatement stmt, ExportCounter fillIndex, CompositeMetadata metadata, String metadataName, boolean multiple) throws SQLException
699    {
700        if (multiple)
701        {
702            int position = 1;
703            for (Boolean value : metadata.getBooleanArray(metadataName, new boolean[0]))
704            {
705                stmt.setBoolean(2, value);
706                stmt.setInt(3, position);
707                position++;
708                
709                if (getLogger().isDebugEnabled())
710                {
711                    getLogger().debug(stmt.toString());
712                }
713                stmt.addBatch();
714            }
715        }
716        else
717        {
718            if (metadata != null && metadata.hasMetadata(metadataName))
719            {
720                try
721                {
722                    stmt.setBoolean(fillIndex.getCount(), metadata.getBoolean(metadataName));
723                }
724                catch (AmetysRepositoryException e)
725                {
726                    List<String> i18nParams = new ArrayList<>();
727                    i18nParams.add(metadataName);
728                    i18nParams.add(_getCompositeMetadataPath(metadata));
729                    i18nParams.add("boolean");
730                    getLogger().error(_i18nTranslator.translate(new I18nizableText("plugin.contentio", "PLUGINS_CONTENTIO_CONTENT_EXPORT_LOG_FILL_ERROR_GET_VALUE", i18nParams)), e);
731                    stmt.setNull(fillIndex.getCount(), java.sql.Types.NULL);
732                }
733            }
734            else
735            {
736                stmt.setNull(fillIndex.getCount(), java.sql.Types.NULL);
737            }
738            fillIndex.incrementCount();
739        }
740    }
741
742    /**
743     * Fill column for Long metadata
744     * @param stmt the jdbc statement
745     * @param fillIndex the position indicator in the insert statement 
746     * @param metadata the composite metadata
747     * @param metadataName the metadata name
748     * @param multiple <code>true</code> if the metadata is multiple
749     * @throws SQLException if a sql error occurred
750     */
751    private void fillColumnForLongMetadata(PreparedStatement stmt, ExportCounter fillIndex, CompositeMetadata metadata, String metadataName, boolean multiple) throws SQLException
752    {
753        if (multiple)
754        {
755            if (_exportNoMultiValuedTable)
756            {
757                String multipleValue = "";
758                if (metadata.hasMetadata(metadataName))
759                {
760                    long[] values = metadata.getLongArray(metadataName);
761                    for (int i = 0; i < values.length; i++)
762                    {
763                        if (i != 0)
764                        {
765                            multipleValue += _separator;
766                        }
767                         
768                        multipleValue += String.valueOf(values[i]);
769                    }
770                }
771
772                if (StringUtils.isNotBlank(multipleValue))
773                {
774                    stmt.setString(fillIndex.getCount(), multipleValue);
775                }
776                else
777                {
778                    stmt.setNull(fillIndex.getCount(), java.sql.Types.VARCHAR);
779                }
780                fillIndex.incrementCount();
781            }
782            else
783            {
784                int position = 1;
785                for (Long value : metadata.getLongArray(metadataName, new long[0]))
786                {
787                    stmt.setLong(2, value);
788                    stmt.setInt(3, position);
789                    position++;
790                    
791                    if (getLogger().isDebugEnabled())
792                    {
793                        getLogger().debug(stmt.toString());
794                    }
795                    stmt.addBatch();
796                }
797            }
798        }
799        else
800        {
801            if (metadata != null && metadata.hasMetadata(metadataName))
802            {
803                try
804                {
805                    stmt.setLong(fillIndex.getCount(), metadata.getLong(metadataName));
806                }
807                catch (AmetysRepositoryException e)
808                {
809                    List<String> i18nParams = new ArrayList<>();
810                    i18nParams.add(metadataName);
811                    i18nParams.add(_getCompositeMetadataPath(metadata));
812                    i18nParams.add("long");
813                    getLogger().error(_i18nTranslator.translate(new I18nizableText("plugin.contentio", "PLUGINS_CONTENTIO_CONTENT_EXPORT_LOG_FILL_ERROR_GET_VALUE", i18nParams)), e);
814                    stmt.setNull(fillIndex.getCount(), java.sql.Types.INTEGER);
815                }
816            }
817            else
818            {
819                stmt.setNull(fillIndex.getCount(), java.sql.Types.INTEGER);
820            }
821            fillIndex.incrementCount();
822        }
823    }
824
825    /**
826     * Fill column for multilangual String metadata
827     * @param stmt the jdbc statement
828     * @param fillIndex the position indicator in the insert statement 
829     * @param metadata the composite metadata
830     * @param metadataName the metadata name
831     * @param multiple <code>true</code> if the metadata is multiple
832     * @throws SQLException if a sql error occurred
833     */
834    private void fillColumnForMultilangualStringMetadata(PreparedStatement stmt, ExportCounter fillIndex, CompositeMetadata metadata, String metadataName, boolean multiple) throws SQLException
835    {
836        if (multiple)
837        {
838            getLogger().warn("We don't handle multiple multilangual string");
839        }
840        else
841        {
842            if (metadata != null && metadata.hasMetadata(metadataName))
843            {
844                MultilingualString multilingualString = metadata.getMultilingualString(metadataName);
845                for (String lang : _languageManager.getAvailableLanguages().keySet())
846                {
847                    Locale locale = new Locale(lang);
848                    if (multilingualString.hasLocale(locale))
849                    {
850                        stmt.setString(fillIndex.getCount(), multilingualString.getValue(locale));
851                    }
852                    else
853                    {
854                        stmt.setNull(fillIndex.getCount(), java.sql.Types.VARCHAR);
855                    }
856                    fillIndex.incrementCount();
857                }
858            }
859            else
860            {
861                for (int i = 0; i < _languageManager.getAvailableLanguages().keySet().size(); i++)
862                {
863                    stmt.setNull(fillIndex.getCount(), java.sql.Types.VARCHAR);
864                    fillIndex.incrementCount();
865                }
866            }
867            
868        }
869    }
870    
871    /**
872     * Fill column for String metadata
873     * @param stmt the jdbc statement
874     * @param fillIndex the position indicator in the insert statement 
875     * @param metadata the composite metadata
876     * @param metadataName the metadata name
877     * @param multiple <code>true</code> if the metadata is multiple
878     * @throws SQLException if a sql error occurred
879     */
880    private void fillColumnForStringMetadata(PreparedStatement stmt, ExportCounter fillIndex, CompositeMetadata metadata, String metadataName, boolean multiple) throws SQLException
881    {
882        if (multiple)
883        {
884            if (_exportNoMultiValuedTable)
885            {
886                String multipleValue = "";
887                if (metadata.hasMetadata(metadataName))
888                {
889                    String[] values = metadata.getStringArray(metadataName);
890                    for (int i = 0; i < values.length; i++)
891                    {
892                        if (i != 0)
893                        {
894                            multipleValue += _separator;
895                        }
896                         
897                        multipleValue += values[i];
898                    }
899                }
900
901                if (StringUtils.isNotBlank(multipleValue))
902                {
903                    stmt.setString(fillIndex.getCount(), multipleValue);
904                }
905                else
906                {
907                    stmt.setNull(fillIndex.getCount(), java.sql.Types.VARCHAR);
908                }
909                fillIndex.incrementCount();
910            }
911            else
912            {
913                int position = 1;
914                String[] values = metadata.getStringArray(metadataName);
915                if (!(values.length == 1 && values[0].equals("")))
916                {
917                    if (values.length != 0)
918                    {
919                        for (String value : values)
920                        {
921                            stmt.setString(2, value);
922                            stmt.setInt(3, position);
923                            position++;
924                            
925                            if (getLogger().isDebugEnabled())
926                            {
927                                getLogger().debug(stmt.toString());
928                            }
929                            stmt.addBatch();
930                        }
931                    }
932                }
933            }
934        }
935        else
936        {
937            if (metadata != null && metadata.hasMetadata(metadataName))
938            {
939                stmt.setString(fillIndex.getCount(), metadata.getString(metadataName));
940            }
941            else
942            {
943                stmt.setNull(fillIndex.getCount(), java.sql.Types.VARCHAR);
944            }
945            fillIndex.incrementCount();
946        }
947    }
948    
949    /**
950     * Fill column for geocode metadata
951     * @param stmt the jdbc statement
952     * @param fillIndex the position indicator in the insert statement 
953     * @param metadata the composite metadata
954     * @param metadataName the metadata name
955     * @param multiple <code>true</code> if the metadata is multiple
956     * @throws SQLException if a sql error occurred
957     */
958    protected void fillColumnForGeocodeMetadata(PreparedStatement stmt, ExportCounter fillIndex, CompositeMetadata metadata, String metadataName, boolean multiple) throws SQLException
959    {
960        if (multiple)
961        {
962            getLogger().warn("We don't handle multiple geocode");
963        }
964        else
965        {
966            if (metadata.hasMetadata(metadataName))
967            {
968                CompositeMetadata values = metadata.getCompositeMetadata(metadataName);
969                
970                if (values.hasMetadata("latitude") && values.hasMetadata("longitude"))
971                {
972                    stmt.setDouble(fillIndex.getCount(), values.getDouble("longitude"));
973                    fillIndex.incrementCount();
974                    stmt.setDouble(fillIndex.getCount(), values.getDouble("latitude"));
975                    fillIndex.incrementCount();
976                }
977                else
978                {
979                    stmt.setNull(fillIndex.getCount(), java.sql.Types.DOUBLE);
980                    fillIndex.incrementCount();
981                    stmt.setNull(fillIndex.getCount(), java.sql.Types.DOUBLE);
982                    fillIndex.incrementCount();
983                }
984            }
985            else
986            {
987                stmt.setNull(fillIndex.getCount(), java.sql.Types.DOUBLE);
988                fillIndex.incrementCount();
989                stmt.setNull(fillIndex.getCount(), java.sql.Types.DOUBLE);
990                fillIndex.incrementCount();
991            }
992        }
993    }
994    
995    /**
996     * Fill column for User metadata
997     * @param stmt the jdbc statement
998     * @param fillIndex the position indicator in the insert statement 
999     * @param metadata the composite metadata
1000     * @param metadataName the metadata name
1001     * @param multiple <code>true</code> if the metadata is multiple
1002     * @throws SQLException if a sql error occurred
1003     */
1004    protected void fillColumnForUserMetadata(PreparedStatement stmt, ExportCounter fillIndex, CompositeMetadata metadata, String metadataName, boolean multiple) throws SQLException
1005    {
1006        if (multiple)
1007        {
1008            if (_exportNoMultiValuedTable)
1009            {
1010                String multipleValue = "";
1011                if (metadata.hasMetadata(metadataName))
1012                {
1013                    UserIdentity[] values = metadata.getUserArray(metadataName);
1014                    for (int i = 0; i < values.length; i++)
1015                    {
1016                        if (i != 0)
1017                        {
1018                            multipleValue += _separator;
1019                        }
1020                        
1021                        User user = _userManager.getUser(values[i]);
1022                        if (user != null)
1023                        {
1024                            multipleValue += user.getFullName();
1025                        }
1026                    }
1027                }
1028
1029                if (StringUtils.isNotBlank(multipleValue))
1030                {
1031                    stmt.setString(fillIndex.getCount(), multipleValue);
1032                }
1033                else
1034                {
1035                    stmt.setNull(fillIndex.getCount(), java.sql.Types.VARCHAR);
1036                }
1037                fillIndex.incrementCount();
1038            }
1039            else
1040            {
1041                int position = 1;
1042                UserIdentity[] values = metadata.getUserArray(metadataName, new UserIdentity[0]);
1043                for (UserIdentity value : values)
1044                {
1045                    stmt.setString(2, value.getLogin());
1046                    stmt.setString(3, value.getPopulationId());
1047                    stmt.setInt(4, position);
1048                    position++;
1049                    
1050                    if (getLogger().isDebugEnabled())
1051                    {
1052                        getLogger().debug(stmt.toString());
1053                    }
1054                    stmt.addBatch();
1055                }
1056            }
1057        }
1058        else
1059        {
1060            if (metadata != null && metadata.hasMetadata(metadataName))
1061            {
1062                UserIdentity user = metadata.getUser(metadataName);
1063                stmt.setString(fillIndex.getCount(), user.getLogin());
1064                fillIndex.incrementCount();
1065                stmt.setString(fillIndex.getCount(), user.getPopulationId());
1066                fillIndex.incrementCount();
1067            }
1068            else
1069            {
1070                stmt.setNull(fillIndex.getCount(), java.sql.Types.VARCHAR);
1071                fillIndex.incrementCount();
1072                stmt.setNull(fillIndex.getCount(), java.sql.Types.VARCHAR);
1073                fillIndex.incrementCount();
1074            }
1075        }
1076    }
1077    
1078    /**
1079     * Fill columns for file metadata
1080     * @param stmt the jdbc statement
1081     * @param fillIndex the position indicator in the insert statement 
1082     * @param metadata the composite metadata
1083     * @param metadataName the metadata name
1084     * @throws SQLException if a sql error occurred
1085     */
1086    protected void fillColumnForFileMetadata(PreparedStatement stmt, ExportCounter fillIndex, CompositeMetadata metadata, String metadataName) throws SQLException
1087    {
1088        if (metadata != null && metadata.hasMetadata(metadataName))
1089        {
1090            if (org.ametys.plugins.repository.metadata.CompositeMetadata.MetadataType.BINARY.equals(metadata.getType(metadataName)))
1091            {
1092                fillColumnForBinaryMetadata(stmt, fillIndex, metadata, metadataName);
1093            }
1094            else
1095            {
1096                String fileUrl = metadata.getString(metadataName);
1097                try
1098                {
1099                    org.ametys.plugins.explorer.resources.Resource resource = _resolver.resolveById(fileUrl);
1100                    stmt.setString(fillIndex.getCount(), resource.getName());
1101                    fillIndex.incrementCount();
1102                    if (resource.getLength() > 0)
1103                    {
1104                        stmt.setBlob(fillIndex.getCount(), resource.getInputStream());
1105                        fillIndex.incrementCount();
1106                    }
1107                    else
1108                    {
1109                        stmt.setNull(fillIndex.getCount(), java.sql.Types.BLOB);
1110                        fillIndex.incrementCount();
1111                    }
1112                    stmt.setString(fillIndex.getCount(), resource.getMimeType());
1113                    fillIndex.incrementCount();
1114                    stmt.setLong(fillIndex.getCount(), resource.getLength());
1115                    fillIndex.incrementCount();
1116                    java.sql.Date sqlDate = new java.sql.Date(resource.getLastModified().getTime());
1117                    stmt.setDate(fillIndex.getCount(), sqlDate);
1118                    fillIndex.incrementCount();
1119                }
1120                catch (Exception e)
1121                {
1122                    if (getLogger().isWarnEnabled())
1123                    {
1124                        List<String> i18nParams = new ArrayList<>();
1125                        i18nParams.add(fileUrl);
1126                        getLogger().warn(_i18nTranslator.translate(new I18nizableText("plugin.contentio", "PLUGINS_CONTENTIO_CONTENT_EXPORT_LOG_FILL_ERROR_GET_FILE", i18nParams)), e);
1127                    }
1128                }
1129            }
1130        }
1131        else
1132        {
1133            stmt.setNull(fillIndex.getCount(), java.sql.Types.VARCHAR);
1134            fillIndex.incrementCount();
1135            stmt.setNull(fillIndex.getCount(), java.sql.Types.BLOB);
1136            fillIndex.incrementCount();
1137            stmt.setNull(fillIndex.getCount(), java.sql.Types.VARCHAR);
1138            fillIndex.incrementCount();
1139            stmt.setNull(fillIndex.getCount(), java.sql.Types.INTEGER);
1140            fillIndex.incrementCount();
1141            stmt.setNull(fillIndex.getCount(), java.sql.Types.DATE);
1142            fillIndex.incrementCount();
1143        }
1144    }
1145    
1146    /**
1147     * Fill column for binary metadata
1148     * @param stmt the jdbc statement
1149     * @param fillIndex the position indicator in the insert statement 
1150     * @param metadata the composite metadata
1151     * @param metadataName the metadata name
1152     * @throws SQLException if a sql error occurred
1153     */
1154    protected void fillColumnForBinaryMetadata(PreparedStatement stmt, ExportCounter fillIndex, CompositeMetadata metadata, String metadataName) throws SQLException
1155    {
1156        if (metadata != null && metadata.hasMetadata(metadataName))
1157        {
1158            BinaryMetadata binary = metadata.getBinaryMetadata(metadataName);
1159            stmt.setString(fillIndex.getCount(), binary.getFilename());
1160            fillIndex.incrementCount();
1161            stmt.setBlob(fillIndex.getCount(), binary.getInputStream());
1162            fillIndex.incrementCount();
1163            stmt.setString(fillIndex.getCount(), binary.getMimeType());
1164            fillIndex.incrementCount();
1165            stmt.setLong(fillIndex.getCount(), binary.getLength());
1166            fillIndex.incrementCount();
1167            java.sql.Date sqlDate = new java.sql.Date(binary.getLastModified().getTime());
1168            stmt.setDate(fillIndex.getCount(), sqlDate);
1169            fillIndex.incrementCount();
1170        }
1171        else
1172        {
1173            stmt.setNull(fillIndex.getCount(), java.sql.Types.VARCHAR);
1174            fillIndex.incrementCount();
1175            stmt.setNull(fillIndex.getCount(), java.sql.Types.BLOB);
1176            fillIndex.incrementCount();
1177            stmt.setNull(fillIndex.getCount(), java.sql.Types.VARCHAR);
1178            fillIndex.incrementCount();
1179            stmt.setNull(fillIndex.getCount(), java.sql.Types.INTEGER);
1180            fillIndex.incrementCount();
1181            stmt.setNull(fillIndex.getCount(), java.sql.Types.DATE);
1182            fillIndex.incrementCount();
1183        }
1184    }
1185
1186    /**
1187     * Fill column for rich text metadata
1188     * @param stmt the jdbc statement
1189     * @param fillIndex the position indicator in the insert statement 
1190     * @param metadata the composite metadata
1191     * @param metadataName the metadata name
1192     * @param id the id
1193     * @throws SQLException if a sql error occurred
1194     * @throws ContextException if a context error occurred
1195     * @throws AmetysRepositoryException if an ametys repository error occurred
1196     */
1197    protected void fillColumnForRichTextMetadata(PreparedStatement stmt, ExportCounter fillIndex, CompositeMetadata metadata, String metadataName, String id) throws SQLException, AmetysRepositoryException, ContextException
1198    {
1199        if (metadata != null && metadata.hasMetadata(metadataName))
1200        {
1201            RichText richText = metadata.getRichText(metadataName);
1202            String richTextValue;
1203            try
1204            {
1205                richTextValue = org.apache.commons.io.IOUtils.toString(richText.getInputStream(),  "UTF-8").replaceAll(_EXCLUDE_XML_TAGS, "");
1206                stmt.setString(fillIndex.getCount(), richTextValue);
1207            }
1208            catch (IOException e)
1209            {
1210                getLogger().warn("Error with rich text of metadata '{}' of content '{}'.", metadataName, id);
1211                stmt.setNull(fillIndex.getCount(), java.sql.Types.BLOB);
1212            }
1213            
1214            fillColumnForRichTextData(richText, metadataName, id);
1215        }
1216        else
1217        {
1218            stmt.setNull(fillIndex.getCount(), java.sql.Types.BLOB);
1219        }
1220        fillIndex.incrementCount();
1221    }
1222    
1223    /**
1224     * Fill column for data in rich text
1225     * @param richText the rich text
1226     * @param metadataName the metadata name
1227     * @param contentId the content id
1228     * @throws AmetysRepositoryException if an error occurred
1229     * @throws SQLException if a sql error occurred
1230     * @throws ContextException if a context error occurred
1231     */
1232    protected void fillColumnForRichTextData(RichText richText, String metadataName, String contentId) throws AmetysRepositoryException, SQLException, ContextException
1233    {
1234        String dataTableName = _sqlPrefixConf + ExportManager.RICH_TEXT_DATA_TABLE_NAME;
1235        PreparedStatement stmt = getInsertPreparedStatementFromTableName(_sqlPrefixConf, dataTableName, "FULL");
1236        _stmtList.add(stmt);
1237        
1238        Folder folder = richText.getAdditionalDataFolder();
1239        int position = 1;
1240        for (File file : folder.getFiles())
1241        {
1242            Resource resource = file.getResource();
1243            String id = contentId + "@" + metadataName + ";" + file.getName();
1244            stmt.setString(1, id);
1245            stmt.setString(2, contentId);
1246            stmt.setString(3, metadataName);
1247            stmt.setString(4, file.getName());
1248            stmt.setBlob(5, resource.getInputStream());
1249            stmt.setString(6, resource.getMimeType());
1250            stmt.setLong(7, resource.getLength());
1251            java.sql.Date sqlDate = new java.sql.Date(resource.getLastModified().getTime());
1252            stmt.setDate(8, sqlDate);
1253            stmt.setInt(9, position);
1254            position++;
1255            
1256            if (getLogger().isDebugEnabled())
1257            {
1258                getLogger().debug(stmt.toString());
1259            }
1260            stmt.addBatch();
1261        }
1262    }
1263    
1264    /**
1265     * Fill column for Double metadata
1266     * @param stmt the jdbc statement
1267     * @param fillIndex the position indicator in the insert statement 
1268     * @param metadata the composite metadata
1269     * @param metadataName the name of the metadata
1270     * @param multiple <code>true</code> if the metadata is multiple
1271     * @throws SQLException if a sql error occurred
1272     */
1273    private void fillColumnForDoubleMetadata(PreparedStatement stmt, ExportCounter fillIndex, CompositeMetadata metadata, String metadataName, boolean multiple) throws SQLException
1274    {
1275        if (multiple)
1276        {
1277            if (_exportNoMultiValuedTable)
1278            {
1279                String multipleValue = "";
1280                if (metadata.hasMetadata(metadataName))
1281                {
1282                    double[] values = metadata.getDoubleArray(metadataName);
1283                    for (int i = 0; i < values.length; i++)
1284                    {
1285                        if (i != 0)
1286                        {
1287                            multipleValue += _separator;
1288                        }
1289                         
1290                        multipleValue += String.valueOf(values[i]);
1291                    }
1292                }
1293
1294                if (StringUtils.isNotBlank(multipleValue))
1295                {
1296                    stmt.setString(fillIndex.getCount(), multipleValue);
1297                }
1298                else
1299                {
1300                    stmt.setNull(fillIndex.getCount(), java.sql.Types.VARCHAR);
1301                }
1302                fillIndex.incrementCount();
1303            }
1304            else
1305            {
1306                int position = 1;
1307                for (Double value : metadata.getDoubleArray(metadataName, new double[0]))
1308                {
1309                    stmt.setDouble(2, value);
1310                    stmt.setInt(3, position);
1311                    position++;
1312                    
1313                    if (getLogger().isDebugEnabled())
1314                    {
1315                        getLogger().debug(stmt.toString());
1316                    }
1317                    stmt.addBatch();
1318                }
1319            }
1320        }
1321        else
1322        {
1323            if (metadata != null && metadata.hasMetadata(metadataName))
1324            {
1325                try
1326                {
1327                    stmt.setDouble(fillIndex.getCount(), metadata.getDouble(metadataName));
1328                }
1329                catch (AmetysRepositoryException e)
1330                {
1331                    List<String> i18nParams = new ArrayList<>();
1332                    i18nParams.add(metadataName);
1333                    i18nParams.add(_getCompositeMetadataPath(metadata));
1334                    i18nParams.add("double");
1335                    getLogger().error(_i18nTranslator.translate(new I18nizableText("plugin.contentio", "PLUGINS_CONTENTIO_CONTENT_EXPORT_LOG_FILL_ERROR_GET_VALUE", i18nParams)), e);
1336                    stmt.setNull(fillIndex.getCount(), java.sql.Types.DOUBLE);
1337                }
1338            }
1339            else
1340            {
1341                stmt.setNull(fillIndex.getCount(), java.sql.Types.DOUBLE);
1342            }
1343            fillIndex.incrementCount();
1344        }
1345    }
1346    
1347    /**
1348     * Prepare INSERT statement
1349     * @param prefix the table prefix
1350     * @param tableName the table name
1351     * @param mappingPolicy the mapping policy
1352     * @return the INSERT preparedStatement
1353     * @throws SQLException if a sql error occurred
1354     * @throws ContextException if a context error occurred
1355     */
1356    protected PreparedStatement getInsertPreparedStatementFromTableName(String prefix, String tableName, String mappingPolicy) throws SQLException, ContextException
1357    {
1358        StringBuilder sql = new StringBuilder();
1359        sql.append("INSERT INTO ");
1360        sql.append(_normaliseNameComponent.normalizedTableName(prefix, mappingPolicy, tableName, _connection));
1361        sql.append(" VALUES ( ?");
1362        
1363        ExportTableInfo tableInfo = _tablesInfos.get(tableName);
1364
1365        for (int i = 1; i < tableInfo.getNbColumns(); i++)
1366        {
1367            sql.append(", ?");
1368        }
1369        sql.append(")");
1370        
1371        if (getLogger().isDebugEnabled())
1372        {
1373            getLogger().debug("Executing: {}", sql.toString());
1374        }
1375        
1376        PreparedStatement stmt = _connection.prepareStatement(sql.toString());
1377        return stmt;
1378    }
1379
1380    private String _getCompositeMetadataPath (CompositeMetadata metadata)
1381    {
1382        try
1383        {
1384            if (metadata instanceof JCRCompositeMetadata)
1385            {
1386                return ((JCRCompositeMetadata) metadata).getNode().getPath();
1387            }
1388        }
1389        catch (RepositoryException e)
1390        {
1391            List<String> i18nParams = new ArrayList<>();
1392            i18nParams.add(metadata.toString());
1393            getLogger().error(_i18nTranslator.translate(new I18nizableText("plugin.contentio", "PLUGINS_CONTENTIO_CONTENT_EXPORT_LOG_FILL_ERROR_GET_PATH", i18nParams)), e);
1394        }
1395        
1396        return "";
1397    }
1398    
1399    /**
1400     * Get the name of SQL table for given content type
1401     * @param cTypeId The id of content type
1402     * @return the name of SQL table or null if not found
1403     */
1404    protected String getTableName (String cTypeId)
1405    {
1406        return _contentTypesToExport.get(cTypeId);
1407    }
1408    
1409}