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.web.repository.page;
017
018import java.util.ArrayList;
019import java.util.HashMap;
020import java.util.List;
021import java.util.Map;
022import java.util.Set;
023
024import org.apache.avalon.framework.component.Component;
025import org.apache.avalon.framework.logger.AbstractLogEnabled;
026import org.apache.avalon.framework.service.ServiceException;
027import org.apache.avalon.framework.service.ServiceManager;
028import org.apache.avalon.framework.service.Serviceable;
029import org.apache.commons.lang3.StringUtils;
030
031import org.ametys.core.right.RightManager;
032import org.ametys.core.right.RightManager.RightResult;
033import org.ametys.core.ui.Callable;
034import org.ametys.core.user.CurrentUserProvider;
035import org.ametys.core.user.UserIdentity;
036import org.ametys.plugins.repository.AmetysObject;
037import org.ametys.plugins.repository.AmetysObjectIterable;
038import org.ametys.plugins.repository.AmetysObjectResolver;
039import org.ametys.plugins.repository.UnknownAmetysObjectException;
040import org.ametys.web.repository.site.Site;
041import org.ametys.web.repository.site.SiteManager;
042import org.ametys.web.repository.sitemap.Sitemap;
043import org.ametys.web.sitemap.SitemapDecorator;
044import org.ametys.web.sitemap.SitemapDecoratorsHandler;
045import org.ametys.web.sitemap.SitemapIcon;
046
047/**
048 * DAO for manipulating pages
049 */
050public class SitemapDAO extends AbstractLogEnabled implements Serviceable, Component
051{
052    /** The component's role */
053    public static final String ROLE = SitemapDAO.class.getName();
054    
055    private AmetysObjectResolver _resolver;
056    private RightManager _rightManager;
057    private CurrentUserProvider _currentUserProvider;
058    private SiteManager _siteManager;
059    private SitemapDecoratorsHandler _sitemapHandler;
060    
061    @Override
062    public void service(ServiceManager smanager) throws ServiceException
063    {
064        _resolver = (AmetysObjectResolver) smanager.lookup(AmetysObjectResolver.ROLE);
065        _rightManager = (RightManager) smanager.lookup(RightManager.ROLE);
066        _currentUserProvider = (CurrentUserProvider) smanager.lookup(CurrentUserProvider.ROLE);
067        _siteManager = (SiteManager) smanager.lookup(SiteManager.ROLE);
068        _sitemapHandler = (SitemapDecoratorsHandler) smanager.lookup(SitemapDecoratorsHandler.ROLE);
069    }
070    
071    /**
072     * Get sitemap properties
073     * @param sitemapId the sitemap ID
074     * @return the sitemap's properties or null if not found
075     */
076    @Callable
077    public Map<String, Object> getSitemap (String sitemapId)
078    {
079        try
080        {
081            Sitemap sitemap = _resolver.resolveById(sitemapId);
082            
083            Map<String, Object> infos = new HashMap<>();
084            
085            infos.put("id", sitemap.getId());
086            infos.put("name", sitemap.getName());
087            infos.put("siteName", sitemap.getSiteName());
088            infos.put("isModifiable", true);
089            infos.put("rights", getUserRights(sitemap));
090            
091            return infos;
092        }
093        catch (UnknownAmetysObjectException e)
094        {
095            return null;
096        }
097    }
098    
099    /**
100     * Get properties of a site, sitemap or on sites root node
101     * @param siteName the site name. Set to null to get properties of sites root node
102     * @param lang the sitemap language. Set to null to get properties of site node
103     * @return the properties
104     */
105    @Callable
106    public Map<String, Object> getProperties (String siteName, String lang)
107    {
108        Map<String, Object> result = new HashMap<>();
109        
110        if (StringUtils.isEmpty(siteName))
111        {
112            // Get information on root sites node
113            AmetysObject root = _siteManager.getRoot();
114            result.put("id", root.getId());  
115            result.put("name", root.getId());
116        }
117        else if (StringUtils.isEmpty(lang))
118        {
119            // Get properties on site node
120            Site site = _siteManager.getSite(siteName);
121            result.put("id", site.getId());  
122            result.put("name", site.getName());
123            result.put("title", site.getTitle());
124        }
125        else
126        {
127            // Get properties on sitemap node
128            result = getSitemapProperties(siteName, lang, null);
129        }
130                
131        return result;
132    }
133    
134    /**
135     * Get the sitemap properties as JSON object
136     * @param siteName the site name. Set to null to get properties of sites root node
137     * @param lang the sitemap language. Set to null to get properties of site node
138     * @param rights If not null, the sitemap properties will contain a 'isAllowed' property based on user rights. Can be null.
139     * @return the sitemap properties
140     */
141    @Callable
142    public Map<String, Object> getSitemapProperties (String siteName, String lang, List<String> rights)
143    {
144        Site site = _siteManager.getSite(siteName);
145        Sitemap sitemap = site.getSitemap(lang);
146        
147        return getSitemapProperties(sitemap, rights);
148    }
149    
150    /**
151     * Get the sitemap properties into a JSON object
152     * @param sitemap The sitemap
153     * @param rightsToCheck If not null, the sitemap properties will contain a 'isAllowed' property based on user rights. Can be null.
154     * @return the sitemap properties
155     */
156    public Map<String, Object> getSitemapProperties (Sitemap sitemap, List<String> rightsToCheck)
157    {
158        Map<String, Object> jsonObject = new HashMap<>();
159        
160        jsonObject.put("id", sitemap.getId());
161        jsonObject.put("name", sitemap.getName());
162        jsonObject.put("lang", sitemap.getName());
163        jsonObject.put("siteName", sitemap.getSiteName());
164        
165        if (rightsToCheck != null)
166        {
167            jsonObject.put("isAllowed", isCurrentUserAllowed(sitemap, rightsToCheck));
168        }
169        
170        return jsonObject;
171    }
172    
173    /**
174     * Get the properties of a page in order to display it into a sitemap tree
175     * @param pageId The page's id
176     * @return The page's properties
177     */
178    @Callable
179    public Map<String, Object> getPageProperties (String pageId)
180    {
181        return getPageProperties((Page) _resolver.resolveById(pageId));
182    }
183    
184    /**
185     * Get the properties of a page in order to display it into a sitemap tree
186     * @param page The page
187     * @return The page's properties
188     */
189    public Map<String, Object> getPageProperties (Page page)
190    {
191        return getPageProperties(page, null);
192    }
193    
194    /**
195     * Get the properties of a page in order to display it into a sitemap tree
196     * @param page The page
197     * @param rightsToCheck If not null, the page properties will contain a 'isAllowed' property based on user rights
198     * @return The page's properties
199     */
200    public Map<String, Object> getPageProperties (Page page, List<String> rightsToCheck)
201    {
202        boolean hasChild = page.getChildrenPages().iterator().hasNext();
203        
204        Map<String, Object> jsonObject = new HashMap<>();
205        
206        jsonObject.put("id", page.getId());
207        jsonObject.put("name", page.getName());
208        jsonObject.put("siteName", page.getSiteName());
209        jsonObject.put("lang", page.getSitemapName());
210        jsonObject.put("title", page.getTitle());
211        jsonObject.put("longTitle", page.getLongTitle());   
212        jsonObject.put("type", page.getType());
213        jsonObject.put("template", page.getTemplate());
214        jsonObject.put("path", page.getPathInSitemap());
215        jsonObject.put("moveable", page instanceof MoveablePage);
216        jsonObject.put("modifiable", page instanceof ModifiablePage);
217        jsonObject.put("hasChild", hasChild);
218        
219        SitemapIcon icon = _sitemapHandler.getIcon(page);
220        
221        jsonObject.put("iconGlyph", icon.getIconGlyph());
222        jsonObject.put("iconDecorator", icon.getIconDecorator());
223        jsonObject.put("iconSmall", icon.getIcon());
224        
225        List<String> decorators = new ArrayList<>();
226        for (SitemapDecorator decorator : _sitemapHandler.getDecorators(page))
227        {
228            decorators.add(decorator.getId());
229        }
230        jsonObject.put("decorators", StringUtils.join(decorators, ","));
231        
232        if (!hasChild)
233        {
234            jsonObject.put("pages", new ArrayList<>());
235        }
236        
237        if (rightsToCheck != null)
238        {
239            jsonObject.put("isAllowed", isCurrentUserAllowed(page, rightsToCheck));
240        }
241        return jsonObject;
242    }
243    
244    /**
245     * Determines if the current user has the requested right on this pages container
246     * @param pageContainer The pages container
247     * @param rights The rights to check
248     * @return true if the current user is allowed
249     */
250    public boolean isCurrentUserAllowed (PagesContainer pageContainer, List<String> rights)
251    {
252        if (rights == null || rights.isEmpty())
253        {
254            return true;
255        }
256        
257        for (String rightId : rights)
258        {
259            if (_rightManager.currentUserHasRight(rightId, pageContainer) != RightResult.RIGHT_ALLOW)
260            {
261                return false;
262            }
263        }
264        
265        return true;
266    }
267    
268    /**
269     * Get the path of pages which match filter regexp
270     * @param id The id of page or sitemap to start search
271     * @param value the value to match
272     * @return the matching paths
273     */
274    @Callable
275    public List<String> filterPagesByRegExp(String id, String value)
276    {
277        List<String> matchingPaths = new ArrayList<>();
278
279        PagesContainer container = _resolver.resolveById(id);
280        
281        String toMatch = StringUtils.stripAccents(value.toLowerCase()).trim();
282        
283        AmetysObjectIterable< ? extends Page> childrenPages = container.getChildrenPages();
284        for (Page childPage : childrenPages)
285        {
286            _getMatchingPages(childPage, toMatch, matchingPaths);
287        }
288        
289        return matchingPaths;
290    }
291    
292    private void _getMatchingPages(Page page, String value, List<String> matchingPaths)
293    {
294        String title =  StringUtils.stripAccents(page.getTitle().toLowerCase());
295        if (title.contains(value))
296        {
297            matchingPaths.add(page.getPathInSitemap());
298        }
299        
300        AmetysObjectIterable< ? extends Page> childrenPages = page.getChildrenPages();
301        for (Page childPage : childrenPages)
302        {
303            _getMatchingPages (childPage, value, matchingPaths);
304        }
305    }
306    
307    /**
308     * Get the sitemap's decorators
309     * @param siteName the site name
310     * @return the list of decorators
311     */
312    @Callable
313    public List<Map<String, Object>> getDecorators (String siteName)
314    {
315        Site site = _siteManager.getSite(siteName);
316        
317        List<Map<String, Object>> decorators = new ArrayList<>();
318        
319        for (SitemapDecorator decorator : _sitemapHandler.getDecorators(site))
320        {
321            Map<String, Object> object = new HashMap<>();
322            object.put("id", decorator.getId());
323            object.put("label", decorator.getLabel());
324            
325            if (StringUtils.isNotBlank(decorator.getIcon()))
326            {
327                object.put("icon", decorator.getIcon());
328            }
329            if (StringUtils.isNotBlank(decorator.getIconGlyph()))
330            {
331                object.put("iconGlyph", decorator.getIconGlyph());
332            }
333            
334            decorators.add(object);
335        }
336        
337        return decorators;
338    }
339    
340    /**
341     * Get the id of a page from its site name, language and sitemap's path
342     * @param siteName The site name
343     * @param lang The language
344     * @param path the page's path. Can be null to get sitemap's id
345     * @return the page id or null if not found
346     */
347    @Callable
348    public String convertPathToId (String siteName, String lang, String path)
349    {
350        assert lang != null;
351        assert siteName != null;
352
353        Site site = _siteManager.getSite(siteName);
354        assert site != null;
355        
356        Sitemap sitemap = site.getSitemap(lang);
357        assert sitemap != null;
358
359        try
360        {
361            if (path != null)
362            {
363                return sitemap.getChild(path).getId();
364            }
365            else
366            {
367                return sitemap.getId();
368            }
369        }
370        catch (UnknownAmetysObjectException e)
371        {
372            return null;
373        }
374    }
375    
376    
377    /**
378     * Get the user rights on a sitemap
379     * @param sitemap the sitemap
380     * @return The user's rights
381     */
382    protected Set<String> getUserRights (Sitemap sitemap)
383    {
384        UserIdentity user = _currentUserProvider.getUser();
385        return _rightManager.getUserRights(user, sitemap);
386    }
387}