Prevent exiting by accept if goals are not satisfied

FEA: ItEr74S04BugFixing
This commit is contained in:
Óscar González Fernández 2011-04-18 01:39:40 +02:00
parent 6cf707573a
commit 1e701e1adc
8 changed files with 191 additions and 25 deletions

View file

@ -0,0 +1,92 @@
/*
* This file is part of NavalPlan
*
* Copyright (C) 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.navalplanner.business.common;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
/**
* Wraps a value with several arbitrary flags.
*
* @author Oscar Gonzalez Fernandez <ogonzalez@igalia.com>
*
* @param <T>
* the value that can have flags associated with it
* @param <F>
* the type of the flags
*/
public class Flagged<T, F> {
public static <T, F> Flagged<T, F> justValue(T value) {
return new Flagged<T, F>(value, new HashSet<F>());
}
public static <T, F> Flagged<T, F> withFlags(T value, F... flags) {
return new Flagged<T, F>(value, new HashSet<F>(Arrays.asList(flags)));
}
private final T value;
private final Set<F> flags;
private Flagged(T value, Set<F> flags) {
this.value = value;
this.flags = Collections.unmodifiableSet(flags);
}
public Flagged<T, F> withFlag(F flag) {
Set<F> newFlags = new HashSet<F>(flags);
newFlags.add(flag);
return new Flagged<T, F>(value, newFlags);
}
public Flagged<T, F> withoutFlag(F flag) {
Set<F> newFlags = new HashSet<F>(flags);
newFlags.remove(flag);
return new Flagged<T, F>(value, newFlags);
}
public T getValue() {
return value;
}
public boolean isFlagged() {
return !this.flags.isEmpty();
}
public Set<? extends F> getFlags() {
return this.flags;
}
public boolean isFlaggedWith(F flag){
return this.flags.contains(flag);
}
public boolean isFlaggedWithSomeOf(F... flags) {
for (F each : flags) {
if (this.isFlaggedWith(each)) {
return true;
}
}
return false;
}
}

View file

@ -34,6 +34,16 @@ import org.navalplanner.business.resources.entities.Resource;
*/
public abstract class AllocationModification {
public static boolean allFullfiled(
Collection<? extends AllocationModification> modificationsDone) {
for (AllocationModification each : modificationsDone) {
if (!each.satisfiesModificationRequested()) {
return false;
}
}
return true;
}
public static List<ResourceAllocation<?>> getBeingModified(
Collection<? extends AllocationModification> allocationModifications) {
List<ResourceAllocation<?>> result = new ArrayList<ResourceAllocation<?>>();

View file

@ -29,6 +29,7 @@ import java.util.Set;
import org.joda.time.LocalDate;
import org.navalplanner.business.calendars.entities.ThereAreHoursOnWorkHoursCalculator.CapacityResult;
import org.navalplanner.business.common.Flagged;
import org.navalplanner.business.orders.entities.HoursGroup;
import org.navalplanner.business.planner.entities.CalculatedValue;
import org.navalplanner.business.planner.entities.DerivedAllocationGenerator.IWorkerFinder;
@ -229,7 +230,11 @@ public class AllocationRowsHandler {
return result;
}
public AllocationResult doAllocation() {
public enum Warnings {
SOME_GOALS_NOT_FULFILLED;
}
public Flagged<AllocationResult, Warnings> doAllocation() {
checkInvalidValues();
if (!currentRows.isEmpty()) {
List<? extends AllocationModification> modificationsDone;
@ -238,10 +243,20 @@ public class AllocationRowsHandler {
AllocationRow.loadDataFromLast(currentRows, modificationsDone);
createDerived();
AllocationResult result = createResult();
if (AllocationModification.allFullfiled(modificationsDone)) {
return Flagged.justValue(result);
} else {
return Flagged.withFlags(result,
Warnings.SOME_GOALS_NOT_FULFILLED);
}
}
AllocationResult result = AllocationResult.create(task,
return Flagged.justValue(createResult());
}
private AllocationResult createResult() {
return AllocationResult.create(task,
calculatedValue, currentRows, getWorkableDaysIfApplyable());
return result;
}
private List<? extends AllocationModification> doSuitableAllocation() {

View file

@ -34,6 +34,7 @@ import org.apache.commons.lang.Validate;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.navalplanner.business.common.Flagged;
import org.navalplanner.business.common.ProportionalDistributor;
import org.navalplanner.business.planner.entities.AggregateOfResourceAllocations;
import org.navalplanner.business.planner.entities.CalculatedValue;
@ -48,6 +49,7 @@ import org.navalplanner.web.common.Level;
import org.navalplanner.web.common.Util;
import org.navalplanner.web.common.components.NewAllocationSelectorCombo;
import org.navalplanner.web.common.components.ResourceAllocationBehaviour;
import org.navalplanner.web.planner.allocation.AllocationRowsHandler.Warnings;
import org.navalplanner.web.planner.allocation.IResourceAllocationModel.IResourceAllocationContext;
import org.navalplanner.web.planner.taskedition.TaskPropertiesController;
import org.zkoss.util.Locales;
@ -486,14 +488,35 @@ public class FormBinder {
}
public void doApply() {
lastAllocation = resourceAllocationModel
AllocationResult allocationResult = resourceAllocationModel
.onAllocationContext(new IResourceAllocationContext<AllocationResult>() {
@Override
public AllocationResult doInsideTransaction() {
return allocationRowsHandler.doAllocation();
return allocationRowsHandler.doAllocation().getValue();
}
});
allocationProduced(allocationResult);
}
/**
*
* @return <code>true</code> if and only if operation completed and must
* exit the edition form
*/
public boolean accept() {
Flagged<AllocationResult, Warnings> result = resourceAllocationModel
.accept();
// result can be null when editing milestones
if (result != null && result.isFlagged()) {
allocationProduced(result.getValue());
}
return result == null || !result.isFlagged();
}
private void allocationProduced(AllocationResult allocationResult) {
lastAllocation = allocationResult;
aggregate = lastAllocation.getAggregate();
allResourcesPerDayVisibilityRule();
sumResourcesPerDayFromRowsAndAssignToAllResourcesPerDay();
@ -861,5 +884,4 @@ public class FormBinder {
this.behaviour = behaviour;
}
}

View file

@ -24,10 +24,12 @@ package org.navalplanner.web.planner.allocation;
import java.util.Date;
import java.util.List;
import org.navalplanner.business.common.Flagged;
import org.navalplanner.business.common.ProportionalDistributor;
import org.navalplanner.business.orders.entities.AggregatedHoursGroup;
import org.navalplanner.business.planner.entities.Task;
import org.navalplanner.business.planner.entities.TaskElement;
import org.navalplanner.web.planner.allocation.AllocationRowsHandler.Warnings;
import org.navalplanner.web.planner.order.PlanningState;
import org.zkoss.ganttz.extensions.IContextWithPlannerTask;
@ -50,8 +52,10 @@ public interface IResourceAllocationModel extends INewAllocationsAdder {
/**
* Save task
*
* @return
*/
void accept();
Flagged<AllocationResult, Warnings> accept();
/**
* Starts the use case

View file

@ -597,9 +597,17 @@ public class ResourceAllocationController extends GenericForwardComposer {
allocationsGrid.setModel(new SimpleListModel(Collections.emptyList()));
}
public void accept() {
resourceAllocationModel.accept();
clear();
/**
*
* @return <code>true</code> if it must exist <code>false</code> if exit
* must be prevented
*/
public boolean accept() {
boolean mustExit = formBinder.accept();
if (mustExit) {
clear();
}
return mustExit;
}
private class ResourceAllocationRenderer implements RowRenderer {

View file

@ -28,6 +28,7 @@ import java.util.List;
import java.util.Set;
import org.hibernate.Hibernate;
import org.navalplanner.business.common.Flagged;
import org.navalplanner.business.common.IAdHocTransactionService;
import org.navalplanner.business.common.IOnTransaction;
import org.navalplanner.business.common.ProportionalDistributor;
@ -39,11 +40,11 @@ import org.navalplanner.business.planner.daos.ITaskElementDAO;
import org.navalplanner.business.planner.daos.ITaskSourceDAO;
import org.navalplanner.business.planner.entities.DayAssignment;
import org.navalplanner.business.planner.entities.DerivedAllocation;
import org.navalplanner.business.planner.entities.DerivedAllocationGenerator.IWorkerFinder;
import org.navalplanner.business.planner.entities.GenericResourceAllocation;
import org.navalplanner.business.planner.entities.ResourceAllocation;
import org.navalplanner.business.planner.entities.Task;
import org.navalplanner.business.planner.entities.TaskElement;
import org.navalplanner.business.planner.entities.DerivedAllocationGenerator.IWorkerFinder;
import org.navalplanner.business.resources.daos.ICriterionDAO;
import org.navalplanner.business.resources.daos.IResourceDAO;
import org.navalplanner.business.resources.daos.IResourcesSearcher;
@ -55,6 +56,7 @@ import org.navalplanner.business.resources.entities.MachineWorkersConfigurationU
import org.navalplanner.business.resources.entities.Resource;
import org.navalplanner.business.resources.entities.ResourceEnum;
import org.navalplanner.business.resources.entities.Worker;
import org.navalplanner.web.planner.allocation.AllocationRowsHandler.Warnings;
import org.navalplanner.web.planner.order.PlanningState;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
@ -169,42 +171,52 @@ public class ResourceAllocationModel implements IResourceAllocationModel {
}
@Override
public void accept() {
public Flagged<AllocationResult, Warnings> accept() {
if (context != null) {
applyAllocationWithDateChangesNotification(new IOnTransaction<Void>() {
return applyDateChangesNotificationIfNoFlags(new IOnTransaction<Flagged<AllocationResult, Warnings>>() {
@Override
public Void execute() {
public Flagged<AllocationResult, Warnings> execute() {
stepsBeforeDoingAllocation();
allocationRowsHandler.doAllocation().applyTo(
planningState.getCurrentScenario(), task);
return null;
Flagged<AllocationResult, Warnings> allocationResult = allocationRowsHandler
.doAllocation();
if (!allocationResult.isFlagged()) {
allocationResult.getValue().applyTo(
planningState.getCurrentScenario(), task);
}
return allocationResult;
}
});
}
return null;
}
@Override
public void accept(final AllocationResult modifiedAllocationResult) {
if (context != null) {
applyAllocationWithDateChangesNotification(new IOnTransaction<Void>() {
applyDateChangesNotificationIfNoFlags(new IOnTransaction<Flagged<Void, Void>>() {
@Override
public Void execute() {
public Flagged<Void, Void> execute() {
stepsBeforeDoingAllocation();
modifiedAllocationResult.applyTo(planningState
.getCurrentScenario(), task);
return null;
return Flagged.justValue(null);
}
});
}
}
private void applyAllocationWithDateChangesNotification(
IOnTransaction<?> allocationDoer) {
private <V, T extends Flagged<V, ?>> T applyDateChangesNotificationIfNoFlags(
IOnTransaction<T> allocationDoer) {
org.zkoss.ganttz.data.Task ganttTask = context.getTask();
GanttDate previousStartDate = ganttTask.getBeginDate();
GanttDate previousEnd = ganttTask.getEndDate();
transactionService.runOnReadOnlyTransaction(allocationDoer);
ganttTask.fireChangesForPreviousValues(previousStartDate, previousEnd);
T result = transactionService.runOnReadOnlyTransaction(allocationDoer);
if (!result.isFlagged()) {
ganttTask.fireChangesForPreviousValues(previousStartDate,
previousEnd);
}
return result;
}
private void stepsBeforeDoingAllocation() {

View file

@ -282,7 +282,10 @@ public class EditTaskController extends GenericForwardComposer {
ResourceAllocationTypeEnum currentState = taskPropertiesController.getCurrentState();
if (ResourceAllocationTypeEnum.NON_LIMITING_RESOURCES.equals(currentState)) {
editTaskTabbox.setSelectedPanelApi(resourceAllocationTabpanel);
resourceAllocationController.accept();
boolean mustNotExit = !resourceAllocationController.accept();
if (mustNotExit) {
return;
}
} else if (ResourceAllocationTypeEnum.SUBCONTRACT.equals(currentState)) {
editTaskTabbox.setSelectedPanelApi(subcontractTabpanel);
subcontractController.accept();