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.search;
017
018import java.util.HashMap;
019import java.util.HashSet;
020import java.util.List;
021import java.util.Locale;
022import java.util.Map;
023import java.util.Set;
024
025import org.apache.avalon.framework.component.Component;
026import org.apache.avalon.framework.service.ServiceException;
027import org.apache.avalon.framework.service.ServiceManager;
028import org.apache.avalon.framework.service.Serviceable;
029
030import org.ametys.cms.repository.Content;
031import org.ametys.cms.repository.ModifiableDefaultContent;
032import org.ametys.core.ui.Callable;
033import org.ametys.plugins.contentio.synchronize.SynchronizableContentsCollection;
034import org.ametys.plugins.contentio.synchronize.SynchronizableContentsCollectionDAO;
035import org.ametys.plugins.repository.AmetysObjectResolver;
036import org.ametys.runtime.plugin.component.AbstractLogEnabled;
037
038import com.google.common.collect.ImmutableList;
039import com.google.common.collect.ImmutableMap;
040
041/**
042 * Helper for SCC callables.
043 */
044public class SCCSearchToolHelper extends AbstractLogEnabled implements Component, Serviceable
045{
046    /** SCC DAO */
047    protected SynchronizableContentsCollectionDAO _synchronizableContentsCollectionDAO;
048    
049    /** The Ametys resolver */
050    protected AmetysObjectResolver _resolver;
051
052    @Override
053    public void service(ServiceManager manager) throws ServiceException
054    {
055        _synchronizableContentsCollectionDAO = (SynchronizableContentsCollectionDAO) manager.lookup(SynchronizableContentsCollectionDAO.ROLE);
056        _resolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE);
057    }
058
059    /**
060     * Get the {@link SCCSearchModelConfiguration} from the collectionId.
061     * @param collectionId Collection ID
062     * @return The {@link SCCSearchModelConfiguration}
063     */
064    @Callable
065    public Map<String, Object> getSearchModelConfiguration(String collectionId)
066    {
067        SynchronizableContentsCollection collection = _synchronizableContentsCollectionDAO.getSynchronizableContentsCollection(collectionId);
068        SCCSearchModelConfiguration searchModelConfiguration = collection.getSearchModelConfiguration();
069        return searchModelConfiguration.toJSON();
070    }
071
072    /**
073     * Import the content specified by the id in the specified collection.
074     * @param collectionId Collection ID
075     * @param id Synchonization ID of the content
076     * @param additionalParameters Additional parameters
077     * @return Imported contents
078     */
079    @Callable
080    public Map<String, Object> importContent(String collectionId, String id, Map<String, Object> additionalParameters)
081    {
082        Map<String, Object> result = new HashMap<>();
083        
084        try
085        {
086            Locale defaultLocale = additionalParameters.containsKey("language") ? new Locale((String) additionalParameters.get("language")) : null;
087            Set<Map<String, String>> contentsList = new HashSet<>();
088            
089            SynchronizableContentsCollection collection = _synchronizableContentsCollectionDAO.getSynchronizableContentsCollection(collectionId);
090            Content existingContent = collection.getContent(null, id);
091            if (existingContent == null)
092            {
093                List<ModifiableDefaultContent> contents = collection.importContent(id, additionalParameters, getLogger());
094                for (ModifiableDefaultContent content : contents)
095                {
096                    Map<String, String> contentMap = new HashMap<>();
097                    contentMap.put("id", content.getId());
098                    contentMap.put("title", content.getTitle(defaultLocale));
099                    contentMap.put("lang", content.getLanguage());
100                    contentsList.add(contentMap);
101                }
102                result.put("contents", contentsList);
103                result.put("total", contents.size());
104            }
105            else
106            {
107                result.put("contents", ImmutableList.of(ImmutableMap.of("id", existingContent.getId(), "title", existingContent.getTitle(defaultLocale), "lang", existingContent.getLanguage())));
108                result.put("error", "alreadyImported");
109            }
110        }
111        catch (Exception e)
112        {
113            String errorMessage = "An exception occured during import of the content '" + id + "' on SCC '" + collectionId + "'";
114            getLogger().error(errorMessage, e);
115            throw new IllegalStateException(errorMessage);
116        }
117        
118        return result;
119    }
120    
121    /**
122     * Synchronize the content on the given collection with the given synchronization code.
123     * @param collectionId Collection ID
124     * @param contentId Content ID
125     * @param syncCode Synchronization code
126     * @return true if an error occured
127     */
128    @Callable
129    public boolean synchronizeContent(String collectionId, String contentId, String syncCode)
130    {
131        ModifiableDefaultContent content = _resolver.resolveById(contentId);
132        boolean hasErrors = false;
133        
134        try
135        {
136            SynchronizableContentsCollection collection = _synchronizableContentsCollectionDAO.getSynchronizableContentsCollection(collectionId);
137            
138            Map<String, Object> searchParameters = new HashMap<>();
139            searchParameters.put(collection.getIdField(), syncCode);
140            
141            if (collection.getTotalCount(searchParameters, getLogger()) > 0)
142            {
143                collection.updateSyncInformations(content, syncCode, getLogger());
144                collection.synchronizeContent(content, getLogger());
145            }
146            else
147            {
148                getLogger().warn("In the collection '{}', there is not content matching with the synchronization code '{}'.", collectionId, syncCode);
149                hasErrors = true;
150            }
151        }
152        catch (Exception e)
153        {
154            getLogger().error("An error occured while synchronizing the content '{}' with the synchronization code '{}' from the '{}' collection.", contentId, syncCode, collectionId, e);
155            hasErrors = true;
156        }
157        
158        return hasErrors;
159    }
160    
161    /**
162     * Get the value of the synchronization field.
163     * @param collectionId Collection ID
164     * @param contentId Content ID
165     * @return The value of the synchronization field
166     */
167    @Callable
168    public String getSyncCode(String contentId, String collectionId)
169    {
170        SynchronizableContentsCollection collection = _synchronizableContentsCollectionDAO.getSynchronizableContentsCollection(collectionId);
171        Content content = _resolver.resolveById(contentId);
172        
173        String syncCode = null;
174        if (content.getMetadataHolder().hasMetadata(collection.getIdField()))
175        {
176            syncCode = content.getMetadataHolder().getString(collection.getIdField());
177        }
178        return syncCode;
179    }
180}