001/*
002 *  Copyright 2019 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.observation;
017
018import java.util.Collections;
019import java.util.HashMap;
020import java.util.Map;
021
022import org.apache.avalon.framework.service.ServiceException;
023import org.apache.avalon.framework.service.ServiceManager;
024import org.apache.avalon.framework.service.Serviceable;
025import org.apache.commons.lang3.ArrayUtils;
026
027import org.ametys.cms.ObservationConstants;
028import org.ametys.cms.repository.Content;
029import org.ametys.cms.workflow.ContentWorkflowHelper;
030import org.ametys.cms.workflow.EditContentFunction;
031import org.ametys.core.observation.Event;
032import org.ametys.core.observation.Observer;
033import org.ametys.core.util.JSONUtils;
034import org.ametys.odf.course.Course;
035import org.ametys.odf.course.ShareableCourseConstants;
036import org.ametys.odf.course.ShareableCourseHelper;
037import org.ametys.odf.enumeration.OdfReferenceTableHelper;
038import org.ametys.odf.orgunit.OrgUnit;
039import org.ametys.odf.program.Program;
040import org.ametys.plugins.repository.AmetysObjectIterable;
041import org.ametys.plugins.workflow.AbstractWorkflowComponent;
042import org.ametys.plugins.workflow.component.CheckRightsCondition;
043import org.ametys.runtime.plugin.component.AbstractLogEnabled;
044
045import com.opensymphony.workflow.WorkflowException;
046
047/**
048 * Observer to unlink the shareable field of a {@link Course} on {@link Content} deletion.
049 */
050public class ShareableFieldCourseObserver extends AbstractLogEnabled implements Observer, Serviceable
051{
052    private ContentWorkflowHelper _contentWorkflowHelper;
053    private ShareableCourseHelper _shareableCourseHelper;
054    private JSONUtils _jsonUtils;
055    
056    @Override
057    public void service(ServiceManager manager) throws ServiceException
058    {
059        _contentWorkflowHelper = (ContentWorkflowHelper) manager.lookup(ContentWorkflowHelper.ROLE);
060        _shareableCourseHelper = (ShareableCourseHelper) manager.lookup(ShareableCourseHelper.ROLE);
061        _jsonUtils = (JSONUtils) manager.lookup(JSONUtils.ROLE);
062    }
063    
064    @Override
065    public boolean supports(Event event)
066    {
067        if (event.getId().equals(ObservationConstants.EVENT_CONTENT_DELETING))
068        {
069            Content content = (Content) event.getArguments().get(ObservationConstants.ARGS_CONTENT);
070            return _isProgramContent(content)
071                || _isOrgUnitContent(content)
072                || _isDegreeContent(content)
073                || _isPeriodContent(content);
074        }
075        
076        return false;
077    }
078
079    @Override
080    public int getPriority(Event event)
081    {
082        return 0;
083    }
084
085    @Override
086    public void observe(Event event, Map<String, Object> transientVars) throws Exception
087    {
088        Content content = (Content) event.getArguments().get(ObservationConstants.ARGS_CONTENT);
089        String contentId = content.getId();
090        
091        if (_isProgramContent(content))
092        {
093            _editShareableField(_shareableCourseHelper.getShareableCourses(contentId, null, null, null), contentId, ShareableCourseConstants.PROGRAMS_FIELD_ATTRIBUTE_NAME);
094        }
095        else if (_isDegreeContent(content))
096        {
097            _editShareableField(_shareableCourseHelper.getShareableCourses(null, contentId, null, null), contentId, ShareableCourseConstants.DEGREES_FIELD_ATTRIBUTE_NAME);
098        }
099        else if (_isPeriodContent(content))
100        {
101            _editShareableField(_shareableCourseHelper.getShareableCourses(null, null, contentId, null), contentId, ShareableCourseConstants.PERIODS_FIELD_ATTRIBUTE_NAME);
102        }
103        else if (_isOrgUnitContent(content))
104        {
105            _editShareableField(_shareableCourseHelper.getShareableCourses(null, null, null, contentId), contentId, ShareableCourseConstants.ORGUNITS_FIELD_ATTRIBUTE_NAME);
106        }
107    }
108
109    /**
110     * Edit shareable fields
111     * @param courses the list of courses to edit shareable fields
112     * @param contentId the content id to remove from sharebale fields
113     * @param attributeNameToRemove the attribute name of the shareable field
114     * @throws WorkflowException if an error occurred
115     */
116    protected void _editShareableField(AmetysObjectIterable<Course> courses, String contentId, String attributeNameToRemove) throws WorkflowException
117    {
118        for (Course course : courses)
119        {
120            Map<String, Object> paramsEdit = new HashMap<>();
121            paramsEdit.put(CheckRightsCondition.FORCE, true); // Ignore the right condition
122            
123            Map<String, Object> contextParameters = new HashMap<>();
124            contextParameters.put("quit", true);
125            
126            Map<String, Object> values = new HashMap<>();
127            values.put(EditContentFunction.FORM_ELEMENTS_PREFIX + attributeNameToRemove, _jsonUtils.convertObjectToJson(Collections.singleton(contentId)));
128            values.put(EditContentFunction.INTERNAL_FORM_ELEMENTS_PREFIX + attributeNameToRemove + ".mode", "remove");
129            contextParameters.put("values", values);
130            
131            paramsEdit.put(AbstractWorkflowComponent.CONTEXT_PARAMETERS_KEY, contextParameters);
132            _contentWorkflowHelper.doAction(course, 222, paramsEdit);
133        }
134    }
135    
136    private boolean _isProgramContent(Content content)
137    {
138        return content instanceof Program;
139    }
140    
141    private boolean _isOrgUnitContent(Content content)
142    {
143        return content instanceof OrgUnit;
144    }
145    
146    private boolean _isDegreeContent(Content content)
147    {
148        return ArrayUtils.contains(content.getTypes(), OdfReferenceTableHelper.DEGREE);
149    }
150    
151    private boolean _isPeriodContent(Content content)
152    {
153        return ArrayUtils.contains(content.getTypes(), OdfReferenceTableHelper.PERIOD);
154    }
155    
156}