001/*
002 *  Copyright 2010 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.workspaces.project.notification;
017
018import java.util.ArrayList;
019import java.util.Iterator;
020import java.util.List;
021import java.util.Map;
022
023import org.apache.avalon.framework.service.ServiceException;
024import org.apache.avalon.framework.service.ServiceManager;
025import org.apache.commons.lang.StringUtils;
026
027import org.ametys.cms.transformation.xslt.ResolveURIComponent;
028import org.ametys.core.observation.Event;
029import org.ametys.core.user.User;
030import org.ametys.core.user.UserIdentity;
031import org.ametys.plugins.explorer.ObservationConstants;
032import org.ametys.plugins.explorer.resources.Resource;
033import org.ametys.plugins.repository.AmetysObject;
034import org.ametys.plugins.workspaces.documents.DocumentWorkspaceModule;
035import org.ametys.plugins.workspaces.project.modules.WorkspaceModuleExtensionPoint;
036import org.ametys.plugins.workspaces.project.objects.Project;
037import org.ametys.runtime.i18n.I18nizableText;
038import org.ametys.web.renderingcontext.RenderingContext;
039
040/**
041 * This observer observes event of resources to notify concerned users
042 */
043public class ResourcesMailNotifierObserver extends AbstractSendNotificationObserver
044{
045    private static final int __MAX_RESOURCE_LINK = 20;
046
047    /** Webdav Notify Helper */
048    protected ResourceNotifierHelper _webdavNotifyHelper;
049    
050    private DocumentWorkspaceModule _documentModule;
051    
052    @Override
053    public void service(ServiceManager smanager) throws ServiceException
054    {
055        super.service(smanager);
056        WorkspaceModuleExtensionPoint moduleManager = (WorkspaceModuleExtensionPoint) smanager.lookup(WorkspaceModuleExtensionPoint.ROLE);
057        _documentModule = moduleManager.getModule(DocumentWorkspaceModule.DODUMENT_MODULE_ID);
058        _webdavNotifyHelper = (ResourceNotifierHelper) smanager.lookup(ResourceNotifierHelper.ROLE);
059    }
060    
061    @Override
062    public boolean supports(Event event)
063    {
064        return event.getId().equals(ObservationConstants.EVENT_RESOURCE_CREATED)
065                || event.getId().equals(ObservationConstants.EVENT_RESOURCE_UPDATED)
066                || event.getId().equals(ObservationConstants.EVENT_RESOURCE_DELETED);
067    }
068    
069    @Override
070    protected void notifyEvent(Project project, String eventId, Map<String, Object> eventParams, User issuer)
071    {
072        String resourceId = (String) eventParams.getOrDefault(ObservationConstants.ARGS_ID, null);
073        if (eventId.equals(ObservationConstants.EVENT_RESOURCE_UPDATED) && _webdavNotifyHelper.resourceRecentlyModified(resourceId))
074        {
075            return;
076        }
077        
078        // Subject
079        String mailSubjecti18nKey = _getSubjectI18nKey(eventId, eventParams);
080        List<String> mailSubjectParams = _getSubjectParams (eventId, project, issuer, eventParams);
081        
082        // Body
083        String mailBodyi18nKey = _getBodyI18nKey(eventId, eventParams);
084        List<String>  mailBodyParams = _getBodyParams(eventId, project, issuer, eventParams);
085        
086        String parentId = (String) eventParams.get(ObservationConstants.ARGS_PARENT_ID);
087        AmetysObject ao = _resolver.resolveById(parentId);
088        List<UserIdentity> recipients = getUsersToNotify(eventId, ao);
089        
090        sendMail(eventId, recipients, mailBodyi18nKey, mailSubjecti18nKey, mailBodyParams, mailSubjectParams);
091        
092    }
093    
094    /**
095     * Get the i18n subject key
096     * @param eventType The type of event
097     * @param eventParams The optional event parameters
098     * @return the i18 key
099     */
100    protected String _getSubjectI18nKey (String eventType, Map<String, Object> eventParams)
101    {
102        String key = "PROJECT_MAIL_NOTIFICATION_SUBJECT_" + StringUtils.replaceChars(eventType.toUpperCase(), '.', '_');
103        
104        if (eventType.equals(ObservationConstants.EVENT_RESOURCE_CREATED))
105        {
106            @SuppressWarnings("unchecked")
107            Map<String, Resource> resources = (Map<String, Resource>) eventParams.get(ObservationConstants.ARGS_RESOURCES);
108            if (resources.size() > 1)
109            {
110                key += "_MULTIPLE";
111            }
112        }
113        
114        return key;
115    }
116    
117    /**
118     * Get the i18n parameters for subject key
119     * @param eventType The event type
120     * @param project The parent project
121     * @param issuer The user responsible of the action
122     * @param eventParams The optional event parameters
123     * @return the i18n parameters
124     */
125    @SuppressWarnings("unchecked")
126    protected List<String> _getSubjectParams (String eventType, Project project, User issuer, Map<String, Object> eventParams)
127    {
128        List<String> i18nparams = new ArrayList<>();
129        i18nparams.add(project.getTitle()); // {0}
130        
131        if (eventType.equals(ObservationConstants.EVENT_RESOURCE_CREATED))
132        {
133            Map<String, Resource> resources = (Map<String, Resource>) eventParams.get(ObservationConstants.ARGS_RESOURCES);
134            
135            if (resources.size() > 1)
136            {
137                i18nparams.add(String.valueOf(resources.size())); // {1}
138            }
139            else
140            {
141                i18nparams.add(resources.values().iterator().next().getName()); // {1}
142            }
143        }
144        else
145        {
146            i18nparams.add(eventParams.get("oldName") != null ? (String) eventParams.get("oldName") : (String) eventParams.get(ObservationConstants.ARGS_NAME)); // {1}
147        }
148        return i18nparams;
149    }
150    
151    /**
152     * Get the i18n subject key
153     * @param eventType The type of event
154     * @param eventParams The optional event parameters
155     * @return the i18n key
156     */
157    protected String _getBodyI18nKey (String eventType, Map<String, Object> eventParams)
158    {
159        String key = "PROJECT_MAIL_NOTIFICATION_BODY_" + StringUtils.replaceChars(eventType.toUpperCase(), '.', '_');
160        
161        if (eventType.equals(ObservationConstants.EVENT_RESOURCE_CREATED))
162        {
163            @SuppressWarnings("unchecked")
164            Map<String, Resource> resources = (Map<String, Resource>) eventParams.get(ObservationConstants.ARGS_RESOURCES);
165            if (resources.size() > 1)
166            {
167                key += "_MULTIPLE";
168            }
169        }
170        
171        return key;
172    }
173    
174    /**
175     * Get the i18n parameters for body key
176     * @param eventType The event type
177     * @param project The parent project
178     * @param issuer The user responsible of the action
179     * @param eventParams The optional event parameters
180     * @return he i18n parameters
181     */
182    @SuppressWarnings("unchecked")
183    protected List<String> _getBodyParams (String eventType, Project project, User issuer, Map<String, Object> eventParams)
184    {
185        List<String> i18nparams = getMailCommonParams(project, issuer, (String) eventParams.get(ObservationConstants.ARGS_PARENT_ID));
186        
187        String rootPath = _documentModule.getModuleRoot(project, false).getPath();
188        
189        if (eventType.equals(ObservationConstants.EVENT_RESOURCE_CREATED))
190        {
191            Map<String, Resource> resources = (Map<String, Resource>) eventParams.get(ObservationConstants.ARGS_RESOURCES);
192            // {4} document name
193            i18nparams.add(resources.values().iterator().next().getName());
194            // {5} document url(s)
195            i18nparams.add(_getDownloadURL(project, resources));
196            if (resources.size() > 1)
197            {
198                // {6} parent collection path
199                i18nparams.add(_getPath (rootPath, (String) eventParams.get(ObservationConstants.ARGS_PARENT_PATH))); 
200            }
201            else
202            {
203                // {6} document path
204                i18nparams.add(_getPath (rootPath, resources.values().iterator().next().getPath())); 
205            }
206        }
207        else
208        {
209            // {4} document name
210            i18nparams.add((String) eventParams.get(ObservationConstants.ARGS_NAME));
211            // {5} document url
212            i18nparams.add(eventParams.get(ObservationConstants.ARGS_ID) != null ? _getDownloadURL(project, (String) eventParams.get(ObservationConstants.ARGS_ID)) : ""); 
213            // {6} document path
214            i18nparams.add(eventParams.get(ObservationConstants.ARGS_PATH) != null ? _getPath (rootPath, (String) eventParams.get(ObservationConstants.ARGS_PATH)) : ""); 
215        }
216        
217        // {7} document old name
218        i18nparams.add(eventParams.get("oldName") != null ? (String) eventParams.get("oldName") : "");
219        // {8} document old path
220        i18nparams.add(eventParams.get("oldPath") != null ? _getPath (rootPath, (String) eventParams.get("oldPath")) : "");
221        // {9} document new path
222        i18nparams.add(eventParams.get("toPath") != null ? _getPath (rootPath, (String) eventParams.get("toPath")) : "");
223        
224        if (eventType.equals(ObservationConstants.EVENT_RESOURCE_CREATED))
225        {
226            // {10} Number of concerned resources
227            Map<String, Resource> resources = (Map<String, Resource>) eventParams.get(ObservationConstants.ARGS_RESOURCES);
228            i18nparams.add(String.valueOf(resources.size())); 
229        }
230        else
231        {
232            i18nparams.add("1"); // {10} 
233        }
234        
235        return i18nparams;
236    }
237    
238    @Override
239    protected String getUrl(Project project, String objectId)
240    {
241        return getModuleUrl(project, DocumentWorkspaceModule.DODUMENT_MODULE_ID, objectId);
242    }
243    
244    @Override
245    protected String getRightIdForNotify()
246    {
247        return "Plugins_Projects_Document_Mail_Notification";
248    }
249    
250    private String _getDownloadURL (Project project, Map<String, Resource> resources)
251    {
252        if (resources.size() == 1)
253        {
254            return _getDownloadURL(project, resources.keySet().iterator().next());
255        }
256        else
257        {
258            StringBuilder sb = new StringBuilder();
259            
260            int nbResources = resources.size();
261            Iterator<String> it = resources.keySet().iterator();
262            
263            int count = 0;
264            while (it.hasNext() && count < __MAX_RESOURCE_LINK)
265            {
266                String id = it.next();
267                Resource resource = resources.get(id);
268                sb.append("\n");
269                sb.append("* ").append(resource.getName()).append(" : ").append(_getDownloadURL(project, id));
270                
271                count++;
272            }
273            
274            if (nbResources - __MAX_RESOURCE_LINK > 0)
275            {
276                List<String> i18nparams = new ArrayList<>();
277                i18nparams.add(String.valueOf(nbResources - __MAX_RESOURCE_LINK));
278                I18nizableText moreLinks = new I18nizableText("plugin." + _pluginName, "PROJECT_MAIL_NOTIFICATION_BODY_RESOURCE_CREATED_MULTIPLE_MORE_LINKS", i18nparams);
279                sb.append(_i18nUtils.translate(moreLinks));
280            }
281            
282            return sb.toString();
283        }
284    }
285    
286    /**
287     * Get the url to download file
288     * @param project The project
289     * @param id The id of resource
290     * @return The download url
291     */
292    protected String _getDownloadURL (Project project, String id)
293    {
294        RenderingContext currentContext = _renderingContextHandler.getRenderingContext();
295        
296        try
297        {
298            _renderingContextHandler.setRenderingContext(RenderingContext.FRONT);
299            
300            return ResolveURIComponent.resolve("project-resource", id, true, true);
301        }
302        finally 
303        {
304            _renderingContextHandler.setRenderingContext(currentContext);
305        }
306    }
307}
308