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