001/*
002 *  Copyright 2020 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;
017
018import java.util.ArrayList;
019import java.util.List;
020import java.util.Map;
021import java.util.Objects;
022import java.util.Optional;
023
024import org.apache.avalon.framework.component.Component;
025import org.apache.avalon.framework.context.Context;
026import org.apache.avalon.framework.context.ContextException;
027import org.apache.avalon.framework.context.Contextualizable;
028import org.apache.avalon.framework.service.ServiceException;
029import org.apache.avalon.framework.service.ServiceManager;
030import org.apache.avalon.framework.service.Serviceable;
031import org.apache.cocoon.Constants;
032import org.apache.cocoon.components.ContextHelper;
033import org.apache.cocoon.environment.Request;
034import org.apache.commons.lang3.StringUtils;
035
036import org.ametys.cms.content.indexing.solr.SolrResourceGroupedMimeTypes;
037import org.ametys.core.user.UserIdentity;
038import org.ametys.core.util.URIUtils;
039import org.ametys.plugins.explorer.resources.Resource;
040import org.ametys.plugins.repository.tag.TaggableAmetysObject;
041import org.ametys.plugins.workspaces.project.ProjectManager;
042import org.ametys.plugins.workspaces.project.objects.Project;
043import org.ametys.plugins.workspaces.tags.ProjectTagsDAO;
044import org.ametys.runtime.plugin.component.AbstractLogEnabled;
045import org.ametys.web.URIPrefixHandler;
046import org.ametys.web.WebHelper;
047import org.ametys.web.repository.site.Site;
048import org.ametys.web.repository.site.SiteManager;
049import org.ametys.web.repository.sitemap.Sitemap;
050
051/**
052 * Utility classes for workspaces
053 *
054 */
055public class WorkspacesHelper extends AbstractLogEnabled implements Component, Serviceable, Contextualizable
056{
057    /** Avalon role */
058    public static final String ROLE = WorkspacesHelper.class.getName();
059    
060    /**
061     * Enumeration for file type
062     */
063    public enum FileType
064    {
065        /** Text document */
066        TEXT,
067        /** PDF document */
068        PDF,
069        /** Spreadsheet */
070        SPREADSHEET,
071        /** Presentation */
072        PRES,
073        /** Image */
074        IMAGE,
075        /** Video */
076        VIDEO,
077        /** Audio */
078        AUDIO,
079        /** Archive */
080        ARCHIVE,
081        /** Unknown type */
082        UNKNOWN
083    }
084
085    private Context _context;
086    private org.apache.cocoon.environment.Context _cocoonContext;
087    private URIPrefixHandler _prefixHandler;
088    private ProjectTagsDAO _projectTagsDAO;
089    private SiteManager _siteManager;
090    private ProjectManager _projectManager;
091    
092    public void contextualize(Context context) throws ContextException
093    {
094        _context = context;
095        _cocoonContext = (org.apache.cocoon.environment.Context) _context.get(Constants.CONTEXT_ENVIRONMENT_CONTEXT);
096    }
097    
098    public void service(ServiceManager smanager) throws ServiceException
099    {
100        _prefixHandler = (URIPrefixHandler) smanager.lookup(URIPrefixHandler.ROLE);
101        _projectTagsDAO = (ProjectTagsDAO) smanager.lookup(ProjectTagsDAO.ROLE);
102        _projectManager = (ProjectManager) smanager.lookup(ProjectManager.ROLE);
103        _siteManager = (SiteManager) smanager.lookup(SiteManager.ROLE);
104    }
105    
106    /**
107     * Determines if the resource file is an image
108     * @param file the resource
109     * @return true if the resource file is an image
110     */
111    public boolean isImage(Resource file)
112    {
113        return SolrResourceGroupedMimeTypes.getGroup(file.getMimeType())
114            .map(groupMimeType -> FileType.IMAGE == FileType.valueOf(groupMimeType.toUpperCase()))
115            .orElse(false);
116    }
117    
118    /**
119     * Get the file type of a resource file
120     * @param file the resource
121     * @return the {@link FileType}
122     */
123    public FileType getFileType(Resource file)
124    {
125        Optional<String> group = SolrResourceGroupedMimeTypes.getGroup(file.getMimeType());
126        
127        return group
128                .map(groupMimeType -> FileType.valueOf(groupMimeType.toUpperCase()))
129                .orElse(FileType.UNKNOWN);
130    }
131    
132    /**
133     * Get the file type of a resource from its name
134     * @param filename the resource's name
135     * @return the {@link FileType}
136     */
137    public FileType getFileType(String filename)
138    {
139        String mimeType = _cocoonContext.getMimeType(filename);
140        Optional<String> group = SolrResourceGroupedMimeTypes.getGroup(mimeType);
141        
142        return group
143                .map(groupMimeType -> FileType.valueOf(groupMimeType.toUpperCase()))
144                .orElse(FileType.UNKNOWN);
145    }
146
147    /**
148     * Get user avatar
149     * @param userIdentity the user identity
150     * @param lang the lang for user's content
151     * @param size the size in pixel of image
152     * @return the avatar url
153     */
154    public String getAvatar(UserIdentity userIdentity, String lang, int size)
155    {
156        StringBuilder sb = new StringBuilder();
157        
158        String siteName = WebHelper.getSiteName(_getRequest());
159        sb.append(_prefixHandler.getUriPrefix(siteName))
160            .append("/_plugins/user-directory/user/")
161            .append(userIdentity.getPopulationId())
162            .append("/")
163            .append(URIUtils.encodePath(userIdentity.getLogin()))
164            .append("/image_")
165            .append(size)
166            .append("?lang=")
167            .append(lang);
168        
169        return sb.toString();
170    }
171    
172    private Request _getRequest()
173    {
174        return ContextHelper.getRequest(_context);
175    }
176    
177    /**
178     * Get current project from request
179     * @return the current project or null if not found.
180     */
181    public Project getProjectFromRequest()
182    {
183        Request request = _getRequest();
184        String projectName = (String) request.getAttribute(WorkspacesConstants.REQUEST_ATTR_PROJECT_NAME);
185        
186        if (StringUtils.isNotEmpty(projectName))
187        {
188            return _projectManager.getProject(projectName);
189        }
190        
191        String siteName = WebHelper.getSiteName(request);
192        if (StringUtils.isNotEmpty(siteName) && _siteManager.hasSite(siteName))
193        {
194            Site site = _siteManager.getSite(siteName);
195            List<Project> projects = _projectManager.getProjectsForSite(site);
196            if (!projects.isEmpty())
197            {
198                return projects.get(0);
199            }
200        }
201        
202        return null;
203    }
204    
205    /**
206     * Handle tags for the edition of a TaggableAmetysObject
207     * @param taggableAmetysObject the object to edit
208     * @param tags the tags
209     * @return the created tags
210     */
211    public List<Map<String, Object>> handleTags(TaggableAmetysObject taggableAmetysObject, List<Object> tags)
212    {
213        List<String> createdTags = new ArrayList<>();
214        List<Map<String, Object>> createdTagsJson = new ArrayList<>();
215        // Tag new tags
216        for (Object tag : tags)
217        {
218            // Tag doesn't exist so create the tag
219            if (tag instanceof Map)
220            {
221                @SuppressWarnings("unchecked")
222                String tagText = (String) ((Map<String, Object>) tag).get("text");
223                List<Map<String, Object>> newTags = _projectTagsDAO.addTags(new String[] {tagText});
224                String newTag = (String) newTags.get(0).get("name");
225                taggableAmetysObject.tag(newTag);
226                createdTags.add(newTag);
227                createdTagsJson.addAll(newTags);
228            }
229            else
230            {
231                taggableAmetysObject.tag((String) tag);
232            }
233        }
234        // Untag unused tags
235        for (String tag : taggableAmetysObject.getTags())
236        {
237            if (!tags.contains(tag) && !createdTags.contains(tag))
238            {
239                taggableAmetysObject.untag(tag);
240            }
241        }
242        return createdTagsJson;
243    }
244
245    /**
246     * Get the lang for this project, or en if none found
247     * @param project the project to check
248     * @return a lang in this project
249     */
250    public String getLang(Project project)
251    {
252        /*
253         * get the site, then the sitemaps (transformed back to a stream of sitemap)
254         * then get the name
255         * return the 1st one, or "en" by default if none is available, or if the site could not be found
256         */
257        
258        Site site = project.getSite();
259        
260        if (site != null)
261        {
262            return site.getSitemaps()
263                       .stream()
264                       .filter(Objects::nonNull)
265                       .map(Sitemap::getName)
266                       .findFirst()
267                       .orElse("en");
268        }
269        else
270        {
271            return "en";
272        }
273    }
274}