001/* 002 * Copyright 2015 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.odf.program; 017 018import java.util.HashMap; 019import java.util.Map; 020import java.util.Map.Entry; 021 022import org.apache.avalon.framework.component.Component; 023import org.apache.avalon.framework.service.ServiceException; 024import org.apache.avalon.framework.service.ServiceManager; 025import org.apache.avalon.framework.service.Serviceable; 026 027import org.ametys.cms.ObservationConstants; 028import org.ametys.cms.repository.ModifiableContent; 029import org.ametys.cms.repository.WorkflowAwareContent; 030import org.ametys.cms.workflow.ContentWorkflowHelper; 031import org.ametys.core.observation.Event; 032import org.ametys.core.observation.ObservationManager; 033import org.ametys.core.ui.Callable; 034import org.ametys.core.user.CurrentUserProvider; 035import org.ametys.core.user.UserIdentity; 036import org.ametys.odf.ODFHelper; 037import org.ametys.odf.observation.OdfObservationConstants; 038import org.ametys.odf.translation.TranslationHelper; 039import org.ametys.plugins.repository.AmetysObjectResolver; 040import org.ametys.plugins.repository.UnknownAmetysObjectException; 041 042/** 043 * DAO for manipulating ODF programs. 044 * 045 */ 046public class ProgramDAO implements Serviceable, Component 047{ 048 /** The Avalon role */ 049 public static final String ROLE = ProgramDAO.class.getName(); 050 051 /** The ametys object resolver */ 052 protected AmetysObjectResolver _resolver; 053 /** Observer manager. */ 054 protected ObservationManager _observationManager; 055 /** The current user provider. */ 056 protected CurrentUserProvider _currentUserProvider; 057 /** ODF helper */ 058 protected ODFHelper _odfHelper; 059 /** The content workflow helper */ 060 protected ContentWorkflowHelper _contentWorkflowHelper; 061 062 @Override 063 public void service(ServiceManager manager) throws ServiceException 064 { 065 _resolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE); 066 _observationManager = (ObservationManager) manager.lookup(ObservationManager.ROLE); 067 _currentUserProvider = (CurrentUserProvider) manager.lookup(CurrentUserProvider.ROLE); 068 _odfHelper = (ODFHelper) manager.lookup(ODFHelper.ROLE); 069 _contentWorkflowHelper = (ContentWorkflowHelper) manager.lookup(ContentWorkflowHelper.ROLE); 070 } 071 072 /** 073 * Translates a given program in a language 074 * @param contentId The program id 075 * @param language The language in which to translate 076 * @param fullCopy True if full copy 077 * @return A Map with id of translated program or an error message 078 * @throws Exception if an error occurs 079 */ 080 @Callable 081 public Map<String, String> translateProgram (String contentId, String language, boolean fullCopy) throws Exception 082 { 083 Map<String, String> result = new HashMap<>(); 084 085 Program program = _resolver.resolveById(contentId); 086 087 if (program.getLanguage().equals(language)) 088 { 089 result.put("error", "same-language"); 090 return result; 091 } 092 093 Map<String, String> translatedContents = new HashMap<>(); 094 095 String translatedProgramId = null; 096 097 // Get existing translations 098 Map<String, String> translations = TranslationHelper.getTranslations(program); 099 100 if (!translations.containsKey(language)) 101 { 102 ModifiableContent translatedProgram = _odfHelper.copyProgramItem(program, null, language, null, fullCopy, translatedContents, translatedContents, translatedContents, translatedContents, translatedContents, translatedContents); 103 translatedProgramId = translatedProgram.getId(); 104 } 105 else 106 { 107 translatedProgramId = translations.get(language); 108 // Check if content exists 109 try 110 { 111 _resolver.resolveById(translatedProgramId); 112 result.put("error", "already-exists"); 113 } 114 catch (UnknownAmetysObjectException e) 115 { 116 ModifiableContent translatedProgram = _odfHelper.copyProgramItem(program, null, language, null, fullCopy, translatedContents, translatedContents, translatedContents, translatedContents, translatedContents, translatedContents); 117 translatedProgramId = translatedProgram.getId(); 118 } 119 } 120 121 linkTranslations(translatedContents); 122 123 // Add the workflow step, send notifications and extract outgoing references 124 for (String newContentId : translatedContents.values()) 125 { 126 WorkflowAwareContent newContent = _resolver.resolveById(newContentId); 127 _contentWorkflowHelper.doAction(newContent, getCopyActionId()); 128 } 129 130 result.put("translated-program-id", translatedProgramId); 131 132 return result; 133 } 134 135 /** 136 * Store links to the other translations for all copied contents 137 * @param translatedContents The translated contents 138 */ 139 protected void linkTranslations(Map<String, String> translatedContents) 140 { 141 for (Entry<String, String> entry : translatedContents.entrySet()) 142 { 143 ModifiableContent originalContent = _resolver.resolveById(entry.getKey()); 144 ModifiableContent translatedContent = _resolver.resolveById(entry.getValue()); 145 146 linkTranslations(originalContent, translatedContent); 147 148 originalContent.saveChanges(); 149 translatedContent.saveChanges(); 150 151 Map<String, Object> eventParams = new HashMap<>(); 152 eventParams.put(ObservationConstants.ARGS_CONTENT, originalContent); 153 154 _observationManager.notify(new Event(OdfObservationConstants.ODF_CONTENT_TRANSLATED, _getCurrentUser(), eventParams)); 155 } 156 } 157 158 /** 159 * Store links to the other translations in all the translated objects. 160 * @param originalContent The original content 161 * @param translatedContent The translated content 162 */ 163 protected void linkTranslations(ModifiableContent originalContent, ModifiableContent translatedContent) 164 { 165 Map<String, String> translations = TranslationHelper.getTranslations(originalContent); 166 167 // Add the original and translated references. 168 translations.put(originalContent.getLanguage(), originalContent.getId()); 169 translations.put(translatedContent.getLanguage(), translatedContent.getId()); 170 171 for (String contentId : translations.values()) 172 { 173 ModifiableContent content = _resolver.resolveById(contentId); 174 175 Map<String, String> otherTranslations = new HashMap<>(translations); 176 otherTranslations.remove(content.getLanguage()); 177 178 TranslationHelper.setTranslations(content, otherTranslations); 179 } 180 } 181 182 /** 183 * Provides the current user. 184 * @return the identity which cannot be <code>null</code>. 185 */ 186 protected UserIdentity _getCurrentUser() 187 { 188 return _currentUserProvider.getUser(); 189 } 190 191 /** 192 * Get the workflow action id for copy. 193 * @return The workflow action id 194 */ 195 protected int getCopyActionId() 196 { 197 return 210; 198 } 199}