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