001/*
002 *  Copyright 2017 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;
017
018import java.util.Collection;
019import java.util.HashMap;
020import java.util.LinkedHashMap;
021import java.util.List;
022import java.util.Map;
023import java.util.Objects;
024import java.util.stream.Collectors;
025import java.util.stream.Stream;
026
027import org.apache.avalon.framework.component.Component;
028import org.apache.avalon.framework.service.ServiceException;
029import org.apache.avalon.framework.service.ServiceManager;
030import org.apache.avalon.framework.service.Serviceable;
031
032/**
033 * Helper for Synchronizable Contents Collections.
034 */
035public class SynchronizableContentsCollectionHelper implements Serviceable, Component
036{
037    /** The Avalon Role */
038    public static final String ROLE = SynchronizableContentsCollectionHelper.class.getName();
039    
040    /** SCC DAO */
041    protected SynchronizableContentsCollectionDAO _sccDAO;
042    
043    @Override
044    public void service(ServiceManager smanager) throws ServiceException
045    {
046        _sccDAO = (SynchronizableContentsCollectionDAO) smanager.lookup(SynchronizableContentsCollectionDAO.ROLE);
047    }
048    
049    /**
050     * Get the first {@link SynchronizableContentsCollection} found for the given SCC model id.
051     * @param modelId Id of the SCC model
052     * @return The first SCC found or null
053     */
054    public SynchronizableContentsCollection getSCCFromModelId(String modelId)
055    {
056        SynchronizableContentsCollection collection = null;
057
058        // Get the first collection corresponding to the SCC model
059        for (SynchronizableContentsCollection scc : _sccDAO.getSynchronizableContentsCollections())
060        {
061            if (scc.getSynchronizeCollectionModelId().equals(modelId))
062            {
063                collection = scc;
064                break;
065            }
066        }
067        
068        return collection;
069    }
070
071    /**
072     * Transform results to be organized by metadata, and remove the null values.
073     * @param searchResult Remote values from a search by content and column or attribute
074     * @param mapping Mapping between metadata and columns/attributes
075     * @return A {@link Map} of possible metadata values organized by content synchronization key and metadata name
076     */
077    public Map<String, Map<String, List<Object>>> organizeRemoteValuesByMetadata(Map<String, Map<String, Object>> searchResult, Map<String, List<String>> mapping)
078    {
079        Map<String, Map<String, List<Object>>> result = new LinkedHashMap<>();
080        
081        // For each searchResult line (1 line = 1 content)
082        for (String resultKey : searchResult.keySet())
083        {
084            Map<String, Object> searchItem = searchResult.get(resultKey);
085            Map<String, List<Object>> contentResult = new HashMap<>();
086            
087            // For each metadata in the mapping
088            for (String metadataRef : mapping.keySet())
089            {
090                List<String> columns = mapping.get(metadataRef); // Get the columns for the current metadata
091                List<Object> values = columns.stream() // For each column corresponding to the metadata
092                        .map(searchItem::get) // Map the values
093                        .flatMap(o ->
094                        {
095                            if (o instanceof Collection<?>)
096                            {
097                                return ((Collection<?>) o).stream();
098                            }
099                            return Stream.of(o);
100                        }) // If it's a list of objects, get a flat stream
101                        .filter(Objects::nonNull) // Remove null values
102                        .collect(Collectors.toList()); // Collect it into a List
103                contentResult.put(metadataRef, values); // Add the retrieved metadata values list to the contentResult
104            }
105            
106            result.put(resultKey, contentResult);
107        }
108        
109        return result;
110    }
111    
112}