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 java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.persistence.NoResultException;
import javax.persistence.TypedQuery;
import org.sigmah.server.dispatch.impl.UserDispatch.UserExecutionContext;
import org.sigmah.server.domain.report.KeyQuestion;
import org.sigmah.server.domain.report.ProjectReport;
import org.sigmah.server.domain.report.ProjectReportModel;
import org.sigmah.server.domain.report.ProjectReportModelSection;
import org.sigmah.server.domain.report.ProjectReportVersion;
import org.sigmah.server.domain.report.RichTextElement;
import org.sigmah.server.handler.base.AbstractCommandHandler;
import org.sigmah.shared.command.GetProjectReport;
import org.sigmah.shared.dispatch.CommandException;
import org.sigmah.shared.dto.report.KeyQuestionDTO;
import org.sigmah.shared.dto.report.ProjectReportContent;
import org.sigmah.shared.dto.report.ProjectReportDTO;
import org.sigmah.shared.dto.report.ProjectReportSectionDTO;
import org.sigmah.shared.dto.report.RichTextElementDTO;
/**
* Handler for {@link GetProjectReport} command.
*
* @author Raphaƫl Calabro (rcalabro@ideia.fr) (v1.3)
* @author Maxime Lombard (mlombard@ideia.fr) (v2.0)
* @author Denis Colliot (dcolliot@ideia.fr) (v2.0)
*/
public class GetProjectReportHandler extends AbstractCommandHandler<GetProjectReport, ProjectReportDTO> {
/**
* {@inheritDoc}
*/
@Override
public ProjectReportDTO execute(final GetProjectReport cmd, final UserExecutionContext context) throws CommandException {
final TypedQuery<ProjectReport> query = em().createQuery("SELECT r FROM ProjectReport r WHERE r.id = :reportId", ProjectReport.class);
query.setParameter("reportId", cmd.getReportId());
try {
final ProjectReport report = query.getSingleResult();
ProjectReportVersion version = report.getCurrentVersion();
// Looking for a draft
final TypedQuery<ProjectReportVersion> queryVersion =
em().createQuery("SELECT v FROM ProjectReportVersion v WHERE v.report.id = :reportId AND v.editor = :user AND v.version IS NULL",
ProjectReportVersion.class);
queryVersion.setParameter("reportId", cmd.getReportId());
queryVersion.setParameter("user", context.getUser());
try {
version = queryVersion.getSingleResult();
} catch (final NoResultException e) {
// No draft for the current user.
}
return toDTO(report, version);
} catch (NoResultException e) {
// Bad report id.
}
return null;
}
/**
* Convert the given report into a ProjectReportDTO.
*
* @param report
* A project report.
* @param version
* A version of this report.
* @return A ProjectReportDTO.
*/
public static ProjectReportDTO toDTO(final ProjectReport report, final ProjectReportVersion version) {
final ProjectReportDTO reportDTO = new ProjectReportDTO();
reportDTO.setId(report.getId());
reportDTO.setVersionId(version.getId());
reportDTO.setName(report.getName());
reportDTO.setPhaseName(version.getPhaseName());
reportDTO.setDraft(version.getVersion() == null);
reportDTO.setLastEditDate(version.getEditDate());
reportDTO.setEditorName(version.getEditorShortName());
if (report.getProject() != null) {
reportDTO.setProjectId(report.getProject().getId());
}
if (report.getOrgUnit() != null) {
reportDTO.setOrgUnitId(report.getOrgUnit().getId());
}
final ProjectReportModel model = report.getModel();
final List<ProjectReportModelSection> sectionModels = model.getSections();
final Map<Integer, List<RichTextElement>> richTextElements = organizeElementsBySection(version.getTexts());
final List<ProjectReportSectionDTO> sectionDTOs = new ArrayList<ProjectReportSectionDTO>();
for (ProjectReportModelSection sectionModel : sectionModels) {
sectionDTOs.add(iterateOnSection(sectionModel, richTextElements));
}
reportDTO.setSections(sectionDTOs);
return reportDTO;
}
/**
* Order the rich text elements by section.
*
* @param elements
* Rich text elements.
* @return A map containing lists of rich text elements.
*/
private static Map<Integer, List<RichTextElement>> organizeElementsBySection(final List<RichTextElement> elements) {
final Map<Integer, List<RichTextElement>> map = new HashMap<Integer, List<RichTextElement>>();
for (final RichTextElement element : elements) {
List<RichTextElement> list = map.get(element.getSectionId());
if (list == null) {
list = new ArrayList<RichTextElement>();
map.put(element.getSectionId(), list);
}
list.add(element);
}
return map;
}
private static ProjectReportSectionDTO iterateOnSection(final ProjectReportModelSection sectionModel,
final Map<Integer, List<RichTextElement>> richTextElements) {
final ProjectReportSectionDTO sectionDTO = new ProjectReportSectionDTO();
sectionDTO.setId(sectionModel.getId());
sectionDTO.setName(sectionModel.getName());
List<RichTextElement> elementList = richTextElements.get(sectionModel.getId());
if (elementList == null)
elementList = Collections.emptyList();
final Iterator<RichTextElement> elementIterator = elementList.iterator();
final Iterator<KeyQuestion> keyQuestionIterator = sectionModel.getKeyQuestions().iterator();
final Iterator<ProjectReportModelSection> subSectionIterator = sectionModel.getSubSections().iterator();
// Children of this section
final ArrayList<ProjectReportContent> children = new ArrayList<ProjectReportContent>();
// Next rich text element
RichTextElement nextElement;
if (elementIterator.hasNext()) {
nextElement = elementIterator.next();
} else {
nextElement = null;
}
// Key questions
int keys = 0;
while (keyQuestionIterator.hasNext()) {
final KeyQuestion keyQuestion = keyQuestionIterator.next();
final KeyQuestionDTO keyQuestionDTO = new KeyQuestionDTO();
keyQuestionDTO.setId(keyQuestion.getId());
keyQuestionDTO.setLabel(keyQuestion.getLabel());
final RichTextElementDTO elementDTO = new RichTextElementDTO();
elementDTO.setId(nextElement.getId());
elementDTO.setText(nextElement.getText());
keyQuestionDTO.setRichTextElementDTO(elementDTO);
if (elementIterator.hasNext()) {
nextElement = elementIterator.next();
} else {
nextElement = null;
}
children.add(keyQuestionDTO);
keys++;
}
// Sub sections
while (subSectionIterator.hasNext()) {
final ProjectReportModelSection subSectionModel = subSectionIterator.next();
while (nextElement != null && nextElement.getIndex() - keys < subSectionModel.getIndex()) {
final RichTextElementDTO elementDTO = new RichTextElementDTO();
elementDTO.setId(nextElement.getId());
elementDTO.setText(nextElement.getText());
children.add(elementDTO);
if (elementIterator.hasNext()) {
nextElement = elementIterator.next();
} else {
nextElement = null;
}
}
final ProjectReportSectionDTO subSectionDTO = iterateOnSection(subSectionModel, richTextElements);
children.add(subSectionDTO);
}
// Remaining elements
while (nextElement != null) {
final RichTextElementDTO elementDTO = new RichTextElementDTO();
elementDTO.setId(nextElement.getId());
elementDTO.setText(nextElement.getText());
children.add(elementDTO);
if (elementIterator.hasNext()) {
nextElement = elementIterator.next();
} else {
nextElement = null;
}
}
sectionDTO.setChildren(children);
return sectionDTO;
}
}