001/* 002 * Copyright 2018 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.translationflagging; 017 018import java.util.ArrayList; 019import java.util.HashMap; 020import java.util.HashSet; 021import java.util.List; 022import java.util.Map; 023import java.util.Map.Entry; 024import java.util.Set; 025 026import org.apache.avalon.framework.component.Component; 027import org.apache.avalon.framework.logger.AbstractLogEnabled; 028import org.apache.avalon.framework.service.ServiceException; 029import org.apache.avalon.framework.service.ServiceManager; 030import org.apache.avalon.framework.service.Serviceable; 031 032import org.ametys.core.observation.Event; 033import org.ametys.core.observation.ObservationManager; 034import org.ametys.core.user.CurrentUserProvider; 035import org.ametys.plugins.repository.AmetysObjectResolver; 036import org.ametys.plugins.repository.UnknownAmetysObjectException; 037import org.ametys.plugins.repository.data.holder.ModelLessDataHolder; 038import org.ametys.plugins.repository.data.holder.ModifiableModelLessDataHolder; 039import org.ametys.web.ObservationConstants; 040import org.ametys.web.repository.page.ModifiablePage; 041import org.ametys.web.repository.page.Page; 042 043/** 044 * Translation page DAO 045 */ 046public class TranslationPageDAO extends AbstractLogEnabled implements Serviceable, Component 047{ 048 /** Avalon Role */ 049 public static final String ROLE = TranslationPageDAO.class.getName(); 050 051 private AmetysObjectResolver _resolver; 052 private CurrentUserProvider _currentUserProvider; 053 private ObservationManager _observationManager; 054 055 @Override 056 public void service(ServiceManager smanager) throws ServiceException 057 { 058 _resolver = (AmetysObjectResolver) smanager.lookup(AmetysObjectResolver.ROLE); 059 _currentUserProvider = (CurrentUserProvider) smanager.lookup(CurrentUserProvider.ROLE); 060 _observationManager = (ObservationManager) smanager.lookup(ObservationManager.ROLE); 061 } 062 063 /** 064 * Set the translations for a specific page 065 * @param pageId The current page id 066 * @param pages the map of translated page 067 * @return The list of updated pages. 068 */ 069 public List<String> setTranslations(String pageId, Map<String, Page> pages) 070 { 071 Page currentPage = _resolver.resolveById(pageId); 072 073 // Get the collection of pages to clean. 074 Set<Page> pagesToClean = new HashSet<>(getTranslations(currentPage).values()); 075 076 // Compute all modified pages to notify the observer. 077 Set<Page> modifiedPages = new HashSet<>(pagesToClean); 078 modifiedPages.addAll(pages.values()); 079 080 // The old pages minus the new ones will be the pages to clean. 081 pagesToClean.removeAll(pages.values()); 082 083 // Clean the old pages: remove the translations metadata. 084 for (Page page : pagesToClean) 085 { 086 if (page instanceof ModifiablePage) 087 { 088 _cleanPage((ModifiablePage) page); 089 } 090 } 091 092 // Set the translations. 093 for (Page page : pages.values()) 094 { 095 if (page instanceof ModifiablePage) 096 { 097 _setTranslations((ModifiablePage) page, pages); 098 } 099 } 100 101 // Notify observers that page data has been changed 102 103 List<String> modifiedPageIds = new ArrayList<>(); 104 for (Page modifiedPage : modifiedPages) 105 { 106 if (modifiedPage != null) 107 { 108 modifiedPageIds.add(modifiedPage.getId()); 109 110 Map<String, Object> eventParams = new HashMap<>(); 111 eventParams.put(ObservationConstants.ARGS_PAGE, modifiedPage); 112 113 _observationManager.notify(new Event(ObservationConstants.EVENT_PAGE_UPDATED, _currentUserProvider.getUser(), eventParams)); 114 } 115 } 116 117 return modifiedPageIds; 118 } 119 120 /** 121 * Get the translations of a given page. 122 * @param page the page. 123 * @return the translated pages as a Map of pages, indexed by sitemap name (language). 124 */ 125 public Map<String, Page> getTranslations(Page page) 126 { 127 Map<String, Page> translations = new HashMap<>(); 128 129 ModelLessDataHolder translationsComposite = page.getComposite(TranslationFlaggingClientSideElement.TRANSLATIONS_META); 130 131 if (translationsComposite != null) 132 { 133 for (String lang : translationsComposite.getDataNames()) 134 { 135 String translatedPageId = translationsComposite.getValue(lang); 136 137 try 138 { 139 Page translatedPage = _resolver.resolveById(translatedPageId); 140 translations.put(lang, translatedPage); 141 } 142 catch (UnknownAmetysObjectException e) 143 { 144 // Ignore : a removed page should be ignored 145 } 146 } 147 } 148 else 149 { 150 // Ignore : the translations composite doesn't exist, just return an empty map. 151 } 152 153 return translations; 154 } 155 156 /** 157 * Set the translations of a page in its data. 158 * @param page the page. 159 * @param pages the translated pages to set. 160 */ 161 protected void _setTranslations(ModifiablePage page, Map<String, Page> pages) 162 { 163 ModifiableModelLessDataHolder translationsComposite = page.getComposite(TranslationFlaggingClientSideElement.TRANSLATIONS_META, true); 164 165 for (Entry<String, Page> entry : pages.entrySet()) 166 { 167 if (!entry.getKey().equals(page.getSitemapName())) 168 { 169 if (entry.getValue() == null) 170 { 171 // Remove data. 172 if (translationsComposite.hasValue(entry.getKey())) 173 { 174 translationsComposite.removeValue(entry.getKey()); 175 } 176 } 177 else 178 { 179 translationsComposite.setValue(entry.getKey(), entry.getValue().getId()); 180 } 181 } 182 } 183 184 page.saveChanges(); 185 } 186 187 /** 188 * Clean a page of its translations data. 189 * @param page the page to clean. 190 */ 191 protected void _cleanPage(ModifiablePage page) 192 { 193 if (page.hasValue(TranslationFlaggingClientSideElement.TRANSLATIONS_META)) 194 { 195 page.removeValue(TranslationFlaggingClientSideElement.TRANSLATIONS_META); 196 page.saveChanges(); 197 } 198 } 199}