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 org.sigmah.client.util.AdminUtil;
import org.sigmah.server.dispatch.impl.UserDispatch.UserExecutionContext;
import org.sigmah.server.domain.category.CategoryType;
import org.sigmah.server.domain.element.BudgetElement;
import org.sigmah.server.domain.element.BudgetSubField;
import org.sigmah.server.domain.element.FlexibleElement;
import org.sigmah.server.domain.element.QuestionChoiceElement;
import org.sigmah.server.domain.element.QuestionElement;
import org.sigmah.server.domain.layout.Layout;
import org.sigmah.server.domain.layout.LayoutConstraint;
import org.sigmah.server.domain.layout.LayoutGroup;
import org.sigmah.server.mapper.Mapper;
import org.sigmah.server.service.base.AbstractEntityService;
import org.sigmah.server.service.util.PropertyMap;
import org.sigmah.shared.dto.layout.LayoutGroupDTO;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
/**
* Create layout group policy.
*
* @author nrebiai
* @author Maxime Lombard (mlombard@ideia.fr)
* @author Denis Colliot (dcolliot@ideia.fr)
*/
@Singleton
public class LayoutGroupService extends AbstractEntityService<LayoutGroup, Integer, LayoutGroupDTO> {
/**
* Injected application mapper.
*/
@Inject
private Mapper mapper;
/**
* {@inheritDoc}
*/
@Override
public LayoutGroup create(final PropertyMap properties, final UserExecutionContext context) {
final LayoutGroupDTO layoutGroupDTOToPersist = (LayoutGroupDTO) properties.get(AdminUtil.PROP_NEW_GROUP_LAYOUT);
LayoutGroup groupToPersist = mapper.map(layoutGroupDTOToPersist, new LayoutGroup());
if (layoutGroupDTOToPersist.getId() != null) {
final int groupId = layoutGroupDTOToPersist.getId();
// Find current order.
final TypedQuery<Integer> rowQuery = em().createQuery("SELECT lg.row FROM LayoutGroup lg where lg.id = :id", Integer.class);
rowQuery.setParameter("id", groupId);
final int oldRow = rowQuery.getSingleResult();
final int row = groupToPersist.getRow();
// Update.
groupToPersist = em().merge(groupToPersist);
if (oldRow != row) {
// Groups have been reordered.
final int change = row > oldRow ? -1 : 1;
final int impact = Math.max(row, oldRow);
final Layout layout = em().find(Layout.class, groupToPersist.getParentLayout().getId());
for (final LayoutGroup other : layout.getGroups()) {
if (groupId != other.getId() && other.getRow() <= impact) {
other.setRow(other.getRow() + change);
em().persist(other);
}
}
}
} else {
// New group.
final Layout layout = groupToPersist.getParentLayout();
// Moving down existing groups.
for (final LayoutGroup layoutGroup : layout.getGroups()) {
if (layoutGroup.getRow() >= groupToPersist.getRow()) {
layoutGroup.setRow(layoutGroup.getRow() + 1);
}
}
// Adding a row to the parent layout.
layout.setRowsCount(layout.getRowsCount() + 1);
em().merge(layout);
em().persist(groupToPersist);
}
return groupToPersist;
}
/**
* {@inheritDoc}
*/
@Override
public LayoutGroup update(Integer entityId, PropertyMap changes, final UserExecutionContext context) {
throw new UnsupportedOperationException("No policy update operation implemented for '" + entityClass.getSimpleName() + "' entity.");
}
public void saveLayoutGroups(List<LayoutGroup> layoutGroups) {
EntityManager entityManager = em();
if (layoutGroups == null) {
return;
}
for (LayoutGroup layoutGroup : layoutGroups) {
List<LayoutConstraint> layoutConstraints = layoutGroup.getConstraints();
if (layoutConstraints == null) {
continue;
}
for (LayoutConstraint layoutConstraint : layoutConstraints) {
if (layoutConstraint.getElement() == null) {
continue;
}
if (layoutConstraint.getElement() instanceof QuestionElement) {
List<QuestionChoiceElement> questionChoiceElements = ((QuestionElement) layoutConstraint.getElement()).getChoices();
CategoryType type = ((QuestionElement) layoutConstraint.getElement()).getCategoryType();
if (questionChoiceElements != null || type != null) {
FlexibleElement parent = layoutConstraint.getElement();
((QuestionElement) parent).setChoices(null);
((QuestionElement) parent).setCategoryType(null);
entityManager.persist(parent);
// Save QuestionChoiceElement with their QuestionElement parent(saved above)
if (questionChoiceElements != null) {
for (QuestionChoiceElement questionChoiceElement : questionChoiceElements) {
if (questionChoiceElement != null) {
questionChoiceElement.setId(null);
questionChoiceElement.setParentQuestion((QuestionElement) parent);
// BUGFIX #652: Removed the duplication of the category element.
entityManager.persist(questionChoiceElement);
}
}
// Set saved QuestionChoiceElement to QuestionElement parent and update it
((QuestionElement) parent).setChoices(questionChoiceElements);
}
// Save the Category type of QuestionElement parent(saved above)
if (type != null) {
// Set the saved CategoryType to QuestionElement parent and update it
((QuestionElement) parent).setCategoryType(type);
}
// Update the QuestionElement parent
entityManager.merge(parent);
} else {
entityManager.persist(layoutConstraint.getElement());
}
} else if (layoutConstraint.getElement() instanceof BudgetElement) {
List<BudgetSubField> budgetSubFields = ((BudgetElement) layoutConstraint.getElement()).getBudgetSubFields();
if (budgetSubFields != null) {
FlexibleElement parent = layoutConstraint.getElement();
((BudgetElement) parent).setBudgetSubFields(null);
((BudgetElement) parent).setRatioDividend(null);
((BudgetElement) parent).setRatioDivisor(null);
for (BudgetSubField budgetSubField : budgetSubFields) {
if (budgetSubField != null) {
budgetSubField.setId(null);
if (budgetSubField.getType() != null) {
switch (budgetSubField.getType()) {
case PLANNED:
((BudgetElement) parent).setRatioDivisor(budgetSubField);
break;
case RECEIVED:
break;
case SPENT:
((BudgetElement) parent).setRatioDividend(budgetSubField);
break;
default:
throw new IllegalStateException("Unknown BudgetSubFieldType : " + budgetSubField.getType());
}
}
budgetSubField.setBudgetElement((BudgetElement) parent);
entityManager.persist(budgetSubField);
}
}
entityManager.persist(parent);
} else {
entityManager.persist(layoutConstraint.getElement());
}
} else {
entityManager.persist(layoutConstraint.getElement());
}
}
}
}
}