package org.sigmah.server.service;
/*
* #%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.Date;
import java.util.List;
import javax.persistence.NoResultException;
import javax.persistence.Query;
import org.sigmah.server.dao.AmendmentDAO;
import org.sigmah.server.dao.LayoutGroupIterationDAO;
import org.sigmah.server.dao.ProjectDAO;
import org.sigmah.server.dispatch.impl.UserDispatch.UserExecutionContext;
import org.sigmah.server.domain.Amendment;
import org.sigmah.server.domain.HistoryToken;
import org.sigmah.server.domain.IterationHistoryToken;
import org.sigmah.server.domain.PhaseModel;
import org.sigmah.server.domain.Project;
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.layout.LayoutGroupIteration;
import org.sigmah.server.domain.logframe.LogFrameCopyContext;
import org.sigmah.server.handler.GetLayoutGroupIterationsHandler;
import org.sigmah.server.service.base.AbstractEntityService;
import org.sigmah.server.service.util.PropertyMap;
import org.sigmah.shared.command.GetLayoutGroupIterations;
import org.sigmah.shared.command.result.ListResult;
import org.sigmah.shared.dto.AmendmentDTO;
import org.sigmah.shared.dto.layout.LayoutGroupIterationDTO;
import org.sigmah.shared.dto.referential.IndicatorCopyStrategy;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import com.google.inject.persist.Transactional;
/**
* Creates and updates project amendments.
*
* @author Raphaƫl Calabro (rcalabro@ideia.fr)
* @author Maxime Lombard (mlombard@ideia.fr)
* @author Denis Colliot (dcolliot@ideia.fr)
*/
@Singleton
public class AmendmentService extends AbstractEntityService<Amendment, Integer, AmendmentDTO> {
/**
* Injected {@link ProjectDAO}.
*/
@Inject
private ProjectDAO projectDAO;
@Inject
private AmendmentDAO amendmentDAO;
@Inject
private LayoutGroupIterationDAO layoutGroupIterationDAO;
/**
* {@inheritDoc}
*/
@Override
public Amendment create(final PropertyMap properties, final UserExecutionContext context) {
final String name = properties.get("name");
final Integer projectId = properties.get("projectId");
final Project project = projectDAO.findById(projectId);
return createAmendment(project, name);
}
/**
* {@inheritDoc}
*/
@Override
@Transactional
public Amendment update(final Integer entityId, final PropertyMap changes, final UserExecutionContext context) {
Amendment amendment = amendmentDAO.findById(entityId);
amendment.setName((String) changes.get("name"));
em().persist(amendment);
em().flush();
return amendment;
}
/**
* Creates a new {@link Amendment} for the given {@code project}.
*
* @param project
* The Project instance.
* @param name
* Name of the new amendment.
* @return The created {@link Amendment} instance.
*/
@Transactional
public Amendment createAmendment(final Project project, String name) {
final Amendment amendment = new Amendment();
amendment.setParentProject(project);
amendment.setLogFrame(project.getLogFrame().copy(LogFrameCopyContext.toProject(project).withStrategy(IndicatorCopyStrategy.REFERENCE)));
amendment.setState(project.getAmendmentState());
amendment.setName(name);
amendment.setVersion(project.getAmendmentVersion());
amendment.setRevision(project.getAmendmentRevision());
amendment.setDate(new Date());
em().persist(amendment);
// Running through every flexible element attached to the project [...] and saving the last history token in the
// values property.
// @see GetHistoryHandler
final List<HistoryToken> historyTokens = new ArrayList<HistoryToken>();
// Looking for all groups
final List<LayoutGroup> groups = new ArrayList<LayoutGroup>();
for (final PhaseModel phaseModel : project.getProjectModel().getPhaseModels()) {
groups.addAll(phaseModel.getLayout().getGroups());
}
groups.addAll(project.getProjectModel().getProjectDetails().getLayout().getGroups());
// Iterating on groups
for (final LayoutGroup group : groups) {
// simple group
if(!group.getHasIterations()) {
for (final LayoutConstraint constraint : group.getConstraints()) {
final FlexibleElement element = constraint.getElement();
// Since the transformation of amendments into project core
// versions, every value has to be saved.
storeValue(project.getId(), element.getId(), null, amendment, historyTokens);
}
}
// iterative group
List<LayoutGroupIteration> iterations = layoutGroupIterationDAO.findByLayoutGroupAndContainer(group.getId(), project.getId(), -1);
for(LayoutGroupIteration iteration : iterations) {
storeIteration(iteration, amendment);
for (final LayoutConstraint constraint : group.getConstraints()) {
final FlexibleElement element = constraint.getElement();
// Since the transformation of amendments into project core
// versions, every value has to be saved.
storeValue(project.getId(), element.getId(), iteration.getId(), amendment, historyTokens);
}
}
}
amendment.setValues(historyTokens);
em().merge(amendment);
return amendment;
}
private void storeIteration(LayoutGroupIteration iteration, Amendment amendment) {
IterationHistoryToken iterationToken = new IterationHistoryToken();
iterationToken.setDate(new Date());
iterationToken.setCoreVersion(amendment);
iterationToken.setLayoutGroup(iteration.getLayoutGroup());
iterationToken.setLayoutGroupIterationId(iteration.getId());
iterationToken.setName(iteration.getName());
iterationToken.setProjectId(iteration.getContainerId());
em().merge(iterationToken);
}
private void storeValue(Integer projectId, Integer elementId, Integer iterationId, Amendment amendment, List<HistoryToken> historyTokens) {
// The value of the current flexible element must be saved.
final Query maxDateQuery;
if(iterationId == null) {
maxDateQuery = em().createQuery("SELECT MAX(h.date) FROM HistoryToken h WHERE h.elementId = :elementId AND h.projectId = :projectId");
maxDateQuery.setParameter("projectId", projectId);
maxDateQuery.setParameter("elementId", elementId);
} else {
maxDateQuery = em().createQuery("SELECT MAX(h.date) FROM HistoryToken h WHERE h.elementId = :elementId AND h.projectId = :projectId AND h.layoutGroupIterationId = :iterationId");
maxDateQuery.setParameter("projectId", projectId);
maxDateQuery.setParameter("elementId", elementId);
maxDateQuery.setParameter("iterationId", iterationId);
}
try {
final Date maxDate = (Date) maxDateQuery.getSingleResult();
final Query query;
if(iterationId == null) {
query = em().createQuery("SELECT h FROM HistoryToken h WHERE h.elementId = :elementId AND h.projectId = :projectId AND h.date = :maxDate");
query.setParameter("projectId", projectId);
query.setParameter("elementId", elementId);
query.setParameter("maxDate", maxDate);
} else {
query = em().createQuery("SELECT h FROM HistoryToken h WHERE h.elementId = :elementId AND h.projectId = :projectId AND h.date = :maxDate AND h.layoutGroupIterationId = :iterationId");
query.setParameter("projectId", projectId);
query.setParameter("elementId", elementId);
query.setParameter("maxDate", maxDate);
query.setParameter("iterationId", iterationId);
}
final HistoryToken token = (HistoryToken) query.getSingleResult();
token.setCoreVersion(amendment);
em().merge(token);
historyTokens.add(token);
} catch (NoResultException e) {
// There is no history token for the given element. No action.
}
}
}