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.userdirectory.clientsideelement;
017
018import java.util.ArrayList;
019import java.util.Arrays;
020import java.util.HashMap;
021import java.util.List;
022import java.util.Map;
023import java.util.stream.Collectors;
024
025import javax.jcr.Node;
026import javax.jcr.RepositoryException;
027import javax.jcr.Value;
028
029import org.apache.avalon.framework.service.ServiceException;
030import org.apache.avalon.framework.service.ServiceManager;
031import org.apache.jackrabbit.value.StringValue;
032
033import org.ametys.core.observation.Event;
034import org.ametys.core.observation.ObservationManager;
035import org.ametys.core.ui.Callable;
036import org.ametys.core.util.LambdaUtils;
037import org.ametys.plugins.repository.AmetysObjectResolver;
038import org.ametys.plugins.repository.jcr.JCRAmetysObject;
039import org.ametys.plugins.userdirectory.OrganisationChartPageHandler;
040import org.ametys.plugins.userdirectory.observation.ObservationConstants;
041import org.ametys.plugins.userdirectory.page.VirtualOrganisationChartPageFactory;
042import org.ametys.runtime.i18n.I18nizableText;
043import org.ametys.web.clientsideelement.AbstractPageClientSideElement;
044import org.ametys.web.repository.page.Page;
045
046/**
047 * Client side element for a controller wich set/remove the organisation chart root page
048 */
049public class SetOrganisationChartRootClientSideElement extends AbstractPageClientSideElement
050{
051    /** Observer manager. */
052    protected ObservationManager _observationManager;
053
054    /** The organisation chart page handler */
055    protected OrganisationChartPageHandler _pageHandler;
056    
057    @Override
058    public void service(ServiceManager smanager) throws ServiceException
059    {
060        super.service(smanager);
061        _observationManager = (ObservationManager) smanager.lookup(ObservationManager.ROLE);
062        _pageHandler = (OrganisationChartPageHandler) smanager.lookup(OrganisationChartPageHandler.ROLE);
063    }
064    
065    /**
066     * Gets the status of the given page
067     * @param pageId The page id
068     * @return the status of the given page
069     */
070    @Callable
071    public Map<String, Object> getStatus(String pageId)
072    {
073        Map<String, Object> result = new HashMap<>();
074        
075        Map<String, Object> parameters = this._script.getParameters();
076        
077        Page page = _resolver.resolveById(pageId);
078
079        if (page instanceof JCRAmetysObject)
080        {
081            if (_pageHandler.isOrganisationChartRootPage((JCRAmetysObject) page))
082            {
083                List<String> i18nParameters = new ArrayList<>();
084                i18nParameters.add(page.getTitle());
085    
086                I18nizableText ed = (I18nizableText) parameters.get("organisation-chart-page-description");
087                I18nizableText msg = new I18nizableText(ed.getCatalogue(), ed.getKey(), i18nParameters);
088                result.put("organisation-chart-page-title", msg);
089                
090                ed = (I18nizableText) parameters.get("remove-organisation-chart-page-description");
091                msg = new I18nizableText(ed.getCatalogue(), ed.getKey(), i18nParameters);
092                result.put("remove-organisation-chart-page-title", msg);
093                
094                result.put("organisation-chart-page-id", new I18nizableText(page.getId()));
095            }
096            else if (_pageHandler.getOrganisationChartRootPages(page.getSiteName(), page.getSitemapName()) != null)
097            {
098                I18nizableText ed = (I18nizableText) parameters.get("organisation-chart-root-already-exist");
099                result.put("organisation-chart-root-already-exist", ed);
100            }
101            else
102            {
103                List<String> i18nParameters = new ArrayList<>();
104                i18nParameters.add(page.getTitle());
105    
106                I18nizableText ed = (I18nizableText) parameters.get("add-organisation-chart-page-description");
107                I18nizableText msg = new I18nizableText(ed.getCatalogue(), ed.getKey(), i18nParameters);
108                
109                result.put("add-organisation-chart-page-id", new I18nizableText(page.getId()));
110                result.put("add-organisation-chart-page-title", msg);
111            }
112        }
113        else
114        {
115            List<String> noJcrI18nParameters = new ArrayList<>();
116            noJcrI18nParameters.add(page.getTitle());
117
118            I18nizableText ed = (I18nizableText) parameters.get("no-jcr-page-description");
119            I18nizableText msg = new I18nizableText(ed.getCatalogue(), ed.getKey(), noJcrI18nParameters);
120            
121            result.put("no-jcr-page-id", new I18nizableText(page.getId()));
122            result.put("no-jcr-page-title", msg);
123        }
124        
125        return result;
126    }
127    
128    /**
129     * Sets the given page as the root of a organisation chart
130     * @param pageId The id of the page
131     * @return A result map
132     * @throws RepositoryException if a repository error occured
133     */
134    @Callable
135    public Map<String, Object> setOrganisationChartRoot(String pageId) throws RepositoryException
136    {
137        Map<String, Object> result = new HashMap<>();
138        
139        Page page = _resolver.resolveById(pageId);
140        
141        if (_pageHandler.getOrganisationChartRootPages(page.getSiteName(), page.getSitemapName()) != null)
142        {
143            result.put("error", "already-exist");
144            return result;
145        }
146        
147        Map<String, Object> eventParams = new HashMap<>();
148        eventParams.put(org.ametys.web.ObservationConstants.ARGS_PAGE, page);
149        
150        _addOrganisationChartRootProperty(page);
151        
152        // Live synchronization
153        _notifyPageUpdated(page);
154        
155        // Indexation
156        _observationManager.notify(new Event(ObservationConstants.EVENT_ORGANISATION_CHART_ROOT_UPDATED, _currentUserProvider.getUser(), eventParams));
157        return result;
158    }
159    
160    /**
161     * Remove the organisation chart root status to the given page
162     * @param pageId The id of the page
163     * @return A result map
164     * @throws RepositoryException if a repository error occured
165     */
166    @Callable
167    public Map<String, Object> removeOrganisationChartRoot(String pageId) throws RepositoryException
168    {
169        Map<String, Object> result = new HashMap<>();
170        
171        Page page = _resolver.resolveById(pageId);
172        
173        if (page instanceof JCRAmetysObject)
174        {
175            if (!_pageHandler.isOrganisationChartRootPage((JCRAmetysObject) page))
176            {
177                result.put("error", "no-root");
178                return result;
179            }
180            
181            Map<String, Object> eventParams = new HashMap<>();
182            eventParams.put(org.ametys.web.ObservationConstants.ARGS_PAGE, page);
183            
184            // Unindex pages for all workspaces before the properties were removed 
185            _observationManager.notify(new Event(ObservationConstants.EVENT_ORGANISATION_CHART_ROOT_DELETING, _currentUserProvider.getUser(), eventParams));
186            
187            _removeUserDirectoryRootProperty(page);
188            
189            _notifyPageUpdated(page);
190            
191            // After live synchronization
192            _observationManager.notify(new Event(ObservationConstants.EVENT_ORGANISATION_CHART_ROOT_DELETED, _currentUserProvider.getUser(), eventParams));
193        }
194        else
195        {
196            result.put("error", "no-root");
197        }
198        return result;
199    }
200    
201    private void _addOrganisationChartRootProperty(Page page) throws RepositoryException
202    {
203        if (page instanceof JCRAmetysObject)
204        {
205            JCRAmetysObject jcrPage = (JCRAmetysObject) page;
206            Node node = jcrPage.getNode();
207            
208            List<Value> values = new ArrayList<>();
209            if (node.hasProperty(AmetysObjectResolver.VIRTUAL_PROPERTY))
210            {
211                values.addAll(Arrays.asList(node.getProperty(AmetysObjectResolver.VIRTUAL_PROPERTY).getValues()));
212            }
213            
214            StringValue virtualUserDirectoryPageFactoryClassName = new StringValue(VirtualOrganisationChartPageFactory.class.getName());
215            if (!values.contains(virtualUserDirectoryPageFactoryClassName))
216            {
217                values.add(virtualUserDirectoryPageFactoryClassName);
218            }
219            
220            node.setProperty(AmetysObjectResolver.VIRTUAL_PROPERTY, values.toArray(new Value[values.size()]));
221            jcrPage.saveChanges();
222        }
223    }
224    
225    private void _removeUserDirectoryRootProperty(Page page) throws RepositoryException
226    {
227        if (page instanceof JCRAmetysObject)
228        {
229            JCRAmetysObject jcrPage = (JCRAmetysObject) page;
230            Node node = jcrPage.getNode();
231            
232            if (node.hasProperty(AmetysObjectResolver.VIRTUAL_PROPERTY))
233            {
234                List<Value> values = new ArrayList<>(Arrays.asList(node.getProperty(AmetysObjectResolver.VIRTUAL_PROPERTY).getValues()));
235                int index = values.stream()
236                        .map(LambdaUtils.wrap(Value::getString))
237                        .collect(Collectors.toList())
238                        .indexOf(VirtualOrganisationChartPageFactory.class.getName());
239                
240                if (index != -1)
241                {
242                    values.remove(index);
243                    node.setProperty(AmetysObjectResolver.VIRTUAL_PROPERTY, values.toArray(new Value[values.size()]));
244                }
245                
246                jcrPage.saveChanges();
247            }
248        }
249    }
250    
251    private void _notifyPageUpdated(Page page)
252    {
253        Map<String, Object> eventParams = new HashMap<>();
254        eventParams.put(org.ametys.web.ObservationConstants.ARGS_PAGE, page);
255        _observationManager.notify(new Event(org.ametys.web.ObservationConstants.EVENT_PAGE_UPDATED, _currentUserProvider.getUser(), eventParams));
256    }
257}