/*
* This file is part of LibrePlan
*
* Copyright (C) 2009-2010 Fundación para o Fomento da Calidade Industrial e
* Desenvolvemento Tecnolóxico de Galicia
* Copyright (C) 2010-2011 Igalia, S.L.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.libreplan.web.scenarios;
import static org.libreplan.business.common.exceptions.ValidationException.invalidValue;
import static org.libreplan.web.I18nHelper._;
import java.util.List;
import java.util.Set;
import org.apache.commons.lang3.Validate;
import org.libreplan.business.common.exceptions.InstanceNotFoundException;
import org.libreplan.business.common.exceptions.ValidationException;
import org.libreplan.business.orders.daos.IOrderDAO;
import org.libreplan.business.orders.daos.IOrderElementDAO;
import org.libreplan.business.orders.entities.Order;
import org.libreplan.business.scenarios.IScenarioManager;
import org.libreplan.business.scenarios.bootstrap.PredefinedScenarios;
import org.libreplan.business.scenarios.daos.IOrderVersionDAO;
import org.libreplan.business.scenarios.daos.IScenarioDAO;
import org.libreplan.business.scenarios.entities.OrderVersion;
import org.libreplan.business.scenarios.entities.Scenario;
import org.libreplan.business.users.daos.IUserDAO;
import org.libreplan.business.users.entities.User;
import org.libreplan.web.common.concurrentdetection.OnConcurrentModification;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* Model for UI operations related to {@link Scenario}.
*
* @author Manuel Rego Casasnovas <mrego@igalia.com>
*/
@Service
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
@Qualifier("main")
@OnConcurrentModification(goToPage = "/scenarios/scenarios.zul")
public class ScenarioModel implements IScenarioModel {
/**
* Conversation state
*/
private Scenario scenario;
@Autowired
private IScenarioDAO scenarioDAO;
@Autowired
private IOrderDAO orderDAO;
@Autowired
private IUserDAO userDAO;
@Autowired
private IOrderElementDAO orderElementDAO;
@Autowired
private IOrderVersionDAO orderVersionDAO;
@Autowired
private IScenarioManager scenarioManager;
/*
* Non conversational steps
*/
@Override
@Transactional(readOnly = true)
public List<Scenario> getScenarios() {
return scenarioDAO.getAll();
}
@Override
@Transactional(readOnly = true)
public List<Scenario> getDerivedScenarios(Scenario scenario) {
return scenarioDAO.getDerivedScenarios(scenario);
}
@Override
@Transactional
public void remove(Scenario scenario) {
remove(scenario, true);
}
@Override
@Transactional
public void remove(Scenario scenario, boolean forceLoad) {
if (forceLoad) {
forceLoad(scenario);
}
boolean isMainScenario = PredefinedScenarios.MASTER.getScenario().getId().equals(scenario.getId());
if (isMainScenario) {
throw new IllegalArgumentException(
_("You cannot remove the default scenario \"{0}\"", PredefinedScenarios.MASTER.getName()));
}
Scenario currentScenario = scenarioManager.getCurrent();
boolean isCurrentScenario = currentScenario.getId().equals(
scenario.getId());
if (isCurrentScenario) {
throw new IllegalArgumentException(
_("You cannot remove the current scenario"));
}
List<Scenario> derivedScenarios = getDerivedScenarios(scenario);
if (!derivedScenarios.isEmpty()) {
throw new IllegalArgumentException(
_("You cannot remove a scenario with derived scenarios"));
}
List<User> users = userDAO.findByLastConnectedScenario(scenario);
for (User user : users) {
user.setLastConnectedScenario(PredefinedScenarios.MASTER
.getScenario());
userDAO.save(user);
}
for (Order order : scenario.getOrders().keySet()) {
if (order.getScenarios().size() == 1) {
if (!orderElementDAO
.isAlreadyInUseThisOrAnyOfItsChildren(order)) {
try {
orderDAO.remove(order.getId());
} catch (InstanceNotFoundException e) {
throw new RuntimeException(e);
}
}
} else {
order.disassociateFrom(scenario);
orderDAO.save(order);
}
}
for (OrderVersion orderVersion : orderVersionDAO
.getOrderVersionByOwnerScenario(scenario)) {
try {
orderVersionDAO.remove(orderVersion.getId());
} catch (InstanceNotFoundException e) {
throw new RuntimeException(e);
}
}
try {
scenarioDAO.remove(scenario.getId());
} catch (InstanceNotFoundException e) {
throw new RuntimeException(e);
}
}
/*
* Initial conversation steps
*/
@Override
@Transactional(readOnly = true)
public void initEdit(Scenario scenario) {
Validate.notNull(scenario);
forceLoad(scenario);
this.scenario = scenario;
}
private void forceLoad(Scenario scenario) {
scenarioDAO.reattach(scenario);
Set<Order> orders = scenario.getOrders().keySet();
for (Order order : orders) {
orderDAO.reattach(order);
order.getName();
}
}
@Override
@Transactional(readOnly = true)
public void initCreateDerived(Scenario scenario) {
Validate.notNull(scenario);
forceLoad(scenario);
this.scenario = scenario.newDerivedScenario();
}
/*
* Intermediate conversation steps
*/
@Override
public Scenario getScenario() {
return scenario;
}
/*
* Final conversation steps
*/
@Override
@Transactional
public void confirmSave() throws ValidationException {
if (scenarioDAO.thereIsOtherWithSameName(scenario)) {
throw new ValidationException(_("Could not save the scenario"),
invalidValue(_("{0} already exists", scenario.getName()),
"name", scenario.getName(), scenario));
}
scenarioDAO.save(scenario);
}
@Override
public void cancel() {
resetState();
}
private void resetState() {
scenario = null;
}
}