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    
066    @Override
067    public void service(ServiceManager smanager) throws ServiceException
068    {
069        super.service(smanager);
070        _jsonUtils = (JSONUtils) smanager.lookup(JSONUtils.ROLE);
071    }
072    
073    @Override
074    public String getIdField()
075    {
076        return (String) getParameterValues().get(__PARAM_FIELD_ID);
077    }
078    
079    /**
080     * Get the id of data source
081     * @return The id of data source
082     */
083    public String getDataSourceId()
084    {
085        return (String) getParameterValues().get(__PARAM_DATASOURCE_ID);
086    }
087    
088    @Override
089    protected void configureDataSource(Configuration configuration) throws ConfigurationException
090    {
091        _mapping = new HashMap<>();
092        _columnsAndCriteria = new TreeSet<>();
093        _syncFields = new HashSet<>();
094        String mappingAsString = (String) getParameterValues().get(__PARAM_MAPPING);
095        if (StringUtils.isNotEmpty(mappingAsString))
096        {
097            List<Object> mappingAsList = _jsonUtils.convertJsonToList(mappingAsString);
098            for (Object object : mappingAsList)
099            {
100                @SuppressWarnings("unchecked")
101                Map<String, Object> field = (Map<String, Object>) object;
102                String metadataRef = (String) field.get(__PARAM_MAPPING_METADATA_REF);
103                String[] mappingAttributes = ((String) field.get(__PARAM_MAPPING_ATTRIBUTE)).split(",");
104                List<String> attributes = Stream.of(mappingAttributes)
105                                                .map(String::trim)
106                                                .collect(Collectors.toList());
107                
108                _mapping.put(metadataRef, attributes);
109                for (String attribute : attributes)
110                {
111                    _columnsAndCriteria.add(attribute);
112                }
113
114                boolean isSynchronized = field.containsKey(__PARAM_MAPPING_SYNCHRO) ? (Boolean) field.get(__PARAM_MAPPING_SYNCHRO) : false;
115                if (isSynchronized)
116                {
117                    _syncFields.add(metadataRef);
118                }
119            }
120        }
121    }
122    
123    @Override
124    protected void configureSearchModel()
125    {
126        for (String columnOrCriteria : _columnsAndCriteria)
127        {
128            _searchModelConfiguration.addCriterion(columnOrCriteria);
129            _searchModelConfiguration.addColumn(columnOrCriteria);
130        }
131    }
132
133    @Override
134    public Set<String> getLocalAndExternalFields(Map<String, Object> additionalParameters)
135    {
136        return _syncFields;
137    }
138    
139    /**
140     * Get the field mapping
141     * @return The mapping
142     */
143    public Map<String, List<String>> getMapping()
144    {
145        return _mapping;
146    }
147    
148    @Override
149    protected Map<String, Object> putIdParameter(String idValue)
150    {
151        Map<String, Object> parameters = new HashMap<>();
152
153        List<String> remoteKeys = getMapping().get(getIdField());
154        if (remoteKeys != null && remoteKeys.size() > 0)
155        {
156            parameters.put(remoteKeys.get(0), idValue);
157        }
158        return parameters;
159    }
160    
161    @Override
162    protected Map<String, Map<String, List<Object>>> getRemoteValues(Map<String, Object> searchParameters, Logger logger)
163    {
164        Map<String, Map<String, Object>> results = internalSearch(searchParameters, 0, Integer.MAX_VALUE, null, logger);
165        return _sccHelper.organizeRemoteValuesByAttribute(results, getMapping());
166    }
167}