001/*
002 *  Copyright 2016 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.synchronize.impl;
017
018import java.util.HashMap;
019import java.util.HashSet;
020import java.util.List;
021import java.util.Map;
022import java.util.Set;
023import java.util.TreeSet;
024import java.util.stream.Collectors;
025import java.util.stream.Stream;
026
027import org.apache.avalon.framework.configuration.Configuration;
028import org.apache.avalon.framework.configuration.ConfigurationException;
029import org.apache.avalon.framework.service.ServiceException;
030import org.apache.avalon.framework.service.ServiceManager;
031import org.apache.commons.lang.StringUtils;
032import org.slf4j.Logger;
033
034import org.ametys.core.util.JSONUtils;
035import org.ametys.plugins.contentio.synchronize.AbstractSimpleSynchronizableContentsCollection;
036import org.ametys.plugins.contentio.synchronize.SynchronizableContentsCollection;
037
038/**
039 * Abstract implementation of {@link SynchronizableContentsCollection} to be synchronized with a data source
040 */
041public abstract class AbstractDataSourceSynchronizableContentsCollection extends AbstractSimpleSynchronizableContentsCollection
042{
043    /** Name of parameter holding the data source id */
044    protected static final String __PARAM_DATASOURCE_ID = "datasourceId";
045    /** Name of parameter holding the data source id */
046    protected static final String __PARAM_FIELD_ID = "idField";
047    /** Name of parameter holding the fields mapping */
048    protected static final String __PARAM_MAPPING = "mapping";
049    /** Name of parameter into mapping holding the synchronized property */
050    protected static final String __PARAM_MAPPING_SYNCHRO = "synchro";
051    /** Name of parameter into mapping holding the path of metadata */
052    protected static final String __PARAM_MAPPING_METADATA_REF = "metadata-ref";
053    /** Name of parameter into mapping holding the remote attribute */
054    protected static final String __PARAM_MAPPING_ATTRIBUTE = "attribute";
055    
056    /** The JSON Utils */
057    protected JSONUtils _jsonUtils;
058    
059    /** Mapping of the metadata with source data */
060    protected Map<String, List<String>> _mapping;
061    /** Columns and criteria for search */
062    protected Set<String> _columnsAndCriteria;
063    /** Synchronized fields */
064    protected Set<String> _syncFields;
065    /** External fields */
066    protected Set<String> _extFields;
067    
068    @Override
069    public void service(ServiceManager smanager) throws ServiceException
070    {
071        super.service(smanager);
072        _jsonUtils = (JSONUtils) smanager.lookup(JSONUtils.ROLE);
073    }
074    
075    @Override
076    public String getIdField()
077    {
078        return (String) getParameterValues().get(__PARAM_FIELD_ID);
079    }
080    
081    /**
082     * Get the id of data source
083     * @return The id of data source
084     */
085    public String getDataSourceId()
086    {
087        return (String) getParameterValues().get(__PARAM_DATASOURCE_ID);
088    }
089    
090    @Override
091    protected void configureDataSource(Configuration configuration) throws ConfigurationException
092    {
093        _mapping = new HashMap<>();
094        _columnsAndCriteria = new TreeSet<>();
095        _syncFields = new HashSet<>();
096        _extFields = new HashSet<>();
097        String mappingAsString = (String) getParameterValues().get(__PARAM_MAPPING);
098        if (StringUtils.isNotEmpty(mappingAsString))
099        {
100            List<Object> mappingAsList = _jsonUtils.convertJsonToList(mappingAsString);
101            for (Object object : mappingAsList)
102            {
103                @SuppressWarnings("unchecked")
104                Map<String, Object> field = (Map<String, Object>) object;
105                String metadataRef = (String) field.get(__PARAM_MAPPING_METADATA_REF);
106                String[] mappingAttributes = ((String) field.get(__PARAM_MAPPING_ATTRIBUTE)).split(",");
107                List<String> attributes = Stream.of(mappingAttributes)
108                                                .map(String::trim)
109                                                .collect(Collectors.toList());
110                
111                _mapping.put(metadataRef, attributes);
112                for (String attribute : attributes)
113                {
114                    _columnsAndCriteria.add(attribute);
115                }
116
117                boolean isSynchronized = field.containsKey(__PARAM_MAPPING_SYNCHRO) ? (Boolean) field.get(__PARAM_MAPPING_SYNCHRO) : false;
118                if (isSynchronized)
119                {
120                    _syncFields.add(metadataRef);
121                }
122                else
123                {
124                    _extFields.add(metadataRef);
125                }
126            }
127        }
128    }
129    
130    @Override
131    protected void configureSearchModel()
132    {
133        for (String columnOrCriteria : _columnsAndCriteria)
134        {
135            _searchModelConfiguration.addCriterion(columnOrCriteria);
136            _searchModelConfiguration.addColumn(columnOrCriteria);
137        }
138    }
139
140    @Override
141    public Set<String> getExternalOnlyFields(Map<String, Object> additionalParameters)
142    {
143        return _extFields;
144    }
145    
146    @Override
147    public Set<String> getLocalAndExternalFields(Map<String, Object> additionalParameters)
148    {
149        return _syncFields;
150    }
151    
152    /**
153     * Get the field mapping
154     * @return The mapping
155     */
156    public Map<String, List<String>> getMapping()
157    {
158        return _mapping;
159    }
160    
161    @Override
162    protected Map<String, Object> putIdParameter(String idValue)
163    {
164        Map<String, Object> parameters = new HashMap<>();
165
166        List<String> remoteKeys = getMapping().get(getIdField());
167        if (remoteKeys != null && remoteKeys.size() > 0)
168        {
169            parameters.put(remoteKeys.get(0), idValue);
170        }
171        return parameters;
172    }
173    
174    @Override
175    protected Map<String, Map<String, List<Object>>> getRemoteValues(Map<String, Object> parameters, Logger logger)
176    {
177        Map<String, Map<String, Object>> results = internalSearch(parameters, 0, Integer.MAX_VALUE, null, logger);
178        return _sccHelper.organizeRemoteValuesByMetadata(results, getMapping());
179    }
180}