package org.sigmah.server.handler; /* * #%L * Sigmah * %% * Copyright (C) 2010 - 2016 URD * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program. If not, see * <http://www.gnu.org/licenses/gpl-3.0.html>. * #L% */ import com.google.inject.Inject; import com.google.inject.Singleton; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import javax.persistence.NoResultException; import javax.persistence.TypedQuery; import org.sigmah.offline.presenter.TreeGridFileModel; import org.sigmah.server.dao.impl.FileHibernateDAO; import org.sigmah.server.dispatch.impl.UserDispatch; import org.sigmah.server.domain.OrgUnit; import org.sigmah.server.domain.OrgUnitDetails; import org.sigmah.server.domain.PhaseModel; import org.sigmah.server.domain.Project; import org.sigmah.server.domain.ProjectDetails; import org.sigmah.server.domain.element.FilesListElement; import org.sigmah.server.domain.element.FlexibleElement; import org.sigmah.server.domain.layout.LayoutConstraint; import org.sigmah.server.domain.layout.LayoutGroup; import org.sigmah.server.domain.value.FileVersion; import org.sigmah.server.file.FileStorageProvider; import org.sigmah.server.handler.base.AbstractCommandHandler; import org.sigmah.server.handler.util.Handlers; import org.sigmah.shared.command.GetFilesFromFavoriteProjects; import org.sigmah.shared.command.result.ListResult; import org.sigmah.shared.dispatch.CommandException; import org.sigmah.shared.dto.ProjectDTO; import org.sigmah.shared.dto.orgunit.OrgUnitDTO; import org.sigmah.shared.dto.value.FileDTO; import org.sigmah.shared.dto.value.FileVersionDTO; import org.sigmah.shared.util.ValueResultUtils; /** * * @author Raphaƫl Calabro (rcalabro@ideia.fr) */ @Singleton public class GetFilesFromFavoriteProjectsHandler extends AbstractCommandHandler<GetFilesFromFavoriteProjects, ListResult<TreeGridFileModel>> { /** * DAO to search for files in the database. */ @Inject private FileHibernateDAO fileHibernateDAO; /** * Allow access to the files. */ @Inject private FileStorageProvider fileStorageProvider; @Override protected ListResult<TreeGridFileModel> execute(GetFilesFromFavoriteProjects command, UserDispatch.UserExecutionContext context) throws CommandException { // Result final List<TreeGridFileModel> models = new ArrayList<>(); // Creating queries final TypedQuery<Project> projectQuery = em().createQuery("SELECT p FROM Project p WHERE :user MEMBER OF p.favoriteUsers", Project.class); final TypedQuery<String> valueQuery = em().createQuery("SELECT v.value FROM Value v WHERE v.containerId = :containerId AND v.element.id = :elementId", String.class); // Searching for favorites projects of the current user projectQuery.setParameter("user", context.getUser()); final List<Project> projects = projectQuery.getResultList(); // Searching every FilesListElement of the found projects for(final Project project : projects) { final List<Integer> fileIds = new ArrayList<>(); for(final PhaseModel phaseModel : project.getProjectModel().getPhaseModels()) { getFilesFromGroups(phaseModel.getLayout().getGroups(), valueQuery, project.getId(), fileIds); } final ProjectDetails projectDetails = project.getProjectModel().getProjectDetails(); if(projectDetails != null) { getFilesFromGroups(projectDetails.getLayout().getGroups(), valueQuery, project.getId(), fileIds); } if(!fileIds.isEmpty()) { final List<FileVersionDTO> versions = getLastVersions(fileIds); if(!versions.isEmpty()) { final ProjectDTO projectDTO = mapper().map(project, new ProjectDTO()); final TreeGridFileModel model = new TreeGridFileModel(projectDTO); model.setChildren(versions); models.add(model); } } } // BUGFIX #785: Searching files from org units final Set<OrgUnit> units = new HashSet<>(); // Crawl the org units hierarchy from the user root org unit. Handlers.crawlUnits(context.getUser(), units, true); for(final OrgUnit unit : units) { final List<Integer> fileIds = new ArrayList<>(); final OrgUnitDetails orgUnitDetails = unit.getOrgUnitModel().getDetails(); if(orgUnitDetails != null) { getFilesFromGroups(orgUnitDetails.getLayout().getGroups(), valueQuery, unit.getId(), fileIds); } if(!fileIds.isEmpty()) { final List<FileVersionDTO> versions = getLastVersions(fileIds); if(!versions.isEmpty()) { final OrgUnitDTO orgUnitDTO = mapper().map(unit, new OrgUnitDTO()); final TreeGridFileModel model = new TreeGridFileModel(orgUnitDTO); model.setChildren(versions); models.add(model); } } } return new ListResult<>(models); } /** * Creates a list from the last versions of the given files. * * File versions will only be added if they exists on the server. * * @param fileIds Files to search. * @return A list of FileVersionDTO. */ private List<FileVersionDTO> getLastVersions(final List<Integer> fileIds) { final List<FileVersion> result = fileHibernateDAO.findVersions(fileIds, FileDTO.LoadingScope.LAST_VERSION_FROM_NOT_DELETED_FILES); final List<FileVersionDTO> versions = new ArrayList<>(mapper().mapCollection(result, FileVersionDTO.class)); final Iterator<FileVersionDTO> iterator = versions.iterator(); while(iterator.hasNext()) { final FileVersionDTO version = iterator.next(); version.setAvailable(fileStorageProvider.exists(version.getPath())); if(!version.isAvailable()) { iterator.remove(); } } return versions; } /** * Adds every file ids for the given groups in the given container. * * @param groups Layout groups. * @param valueQuery Request to fill. * @param containerId Identifier of the parent (project id or org unit id). * @param fileIds List where to add results. */ private void getFilesFromGroups(final List<LayoutGroup> groups, final TypedQuery<String> valueQuery, int containerId, final List<Integer> fileIds) { for(final LayoutGroup group : groups) { for(final LayoutConstraint constraint : group.getConstraints()) { final FlexibleElement flexibleElement = constraint.getElement(); if(flexibleElement instanceof FilesListElement) { // Retrieving the file ids valueQuery.setParameter("containerId", containerId); valueQuery.setParameter("elementId", flexibleElement.getId()); try { final String value = valueQuery.getSingleResult(); if(value != null) { fileIds.addAll(ValueResultUtils.splitValuesAsInteger(value)); } } catch (NoResultException | ClassCastException e) { // No value } } } } } }