diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/DerivedAllocation.java b/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/DerivedAllocation.java new file mode 100644 index 000000000..79c42fe6e --- /dev/null +++ b/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/DerivedAllocation.java @@ -0,0 +1,143 @@ +/* + * This file is part of ###PROJECT_NAME### + * + * Copyright (C) 2009 Fundación para o Fomento da Calidade Industrial e + * Desenvolvemento Tecnolóxico de Galicia + * + * 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 . + */ +package org.navalplanner.business.planner.entities; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; + +import org.apache.commons.lang.Validate; +import org.hibernate.validator.NotNull; +import org.joda.time.LocalDate; +import org.navalplanner.business.common.BaseEntity; +import org.navalplanner.business.resources.entities.Machine; +import org.navalplanner.business.resources.entities.MachineWorkersConfigurationUnit; + +/** + * @author Óscar González Fernández + * + */ +public class DerivedAllocation extends BaseEntity { + + private static boolean isIfGenericContainsMachine( + ResourceAllocation derivedFrom, + MachineWorkersConfigurationUnit configurationUnit) { + if (derivedFrom instanceof GenericResourceAllocation) { + GenericResourceAllocation generic = (GenericResourceAllocation) derivedFrom; + return generic.getAssociatedResources().contains( + configurationUnit.getMachine()); + } + return true; + } + + private static boolean isIfSpecificSameMachine( + ResourceAllocation derivedFrom, + MachineWorkersConfigurationUnit configurationUnit) { + if (derivedFrom instanceof SpecificResourceAllocation) { + SpecificResourceAllocation specific = (SpecificResourceAllocation) derivedFrom; + return specific.getResource() + .equals(configurationUnit.getMachine()); + } + return true; + } + + @NotNull + private ResourceAllocation derivedFrom; + + @NotNull + private MachineWorkersConfigurationUnit configurationUnit; + + private HashSet assignments; + + public static DerivedAllocation create(ResourceAllocation derivedFrom, + MachineWorkersConfigurationUnit configurationUnit) { + return create(new DerivedAllocation(derivedFrom, configurationUnit)); + } + + /** + * Constructor for hibernate. DO NOT USE! + */ + public DerivedAllocation() { + + } + + public DerivedAllocation(ResourceAllocation derivedFrom, + MachineWorkersConfigurationUnit configurationUnit) { + Validate.notNull(derivedFrom); + Validate.notNull(configurationUnit); + Validate + .isTrue(isIfSpecificSameMachine(derivedFrom, configurationUnit)); + Validate.isTrue(isIfGenericContainsMachine(derivedFrom, + configurationUnit)); + this.derivedFrom = derivedFrom; + this.configurationUnit = configurationUnit; + } + + public MachineWorkersConfigurationUnit getConfigurationUnit() { + return configurationUnit; + } + + public ResourceAllocation getDerivedFrom() { + return derivedFrom; + } + + public void resetAssignmentsTo(List dayAssignments) { + checkAreValid(dayAssignments); + this.assignments = new HashSet(dayAssignments); + } + + private void checkAreValid(List dayAssignments) { + for (DerivedDayAssignment each : dayAssignments) { + checkIsValid(each); + } + } + + private void checkIsValid(DerivedDayAssignment dayAssingment) { + Machine machine = configurationUnit.getMachine(); + if (!dayAssingment.getResource().equals(machine)) { + throw new IllegalArgumentException(dayAssingment + + " has the resource: " + dayAssingment.getResource() + + " but this derived allocation has the resource: " + + machine); + } + if (!dayAssingment.getAllocation().equals(this)) { + throw new IllegalArgumentException(dayAssingment + + " is related to " + dayAssingment.getAllocation() + + " instead of this: " + this); + } + } + + public void resetAssignmentsTo(LocalDate startInclusive, + LocalDate endExclusive, List newAssignments) { + List toBeRemoved = DayAssignment.getAtInterval( + getAssignments(), startInclusive, endExclusive); + assignments.removeAll(toBeRemoved); + checkAreValid(newAssignments); + assignments.addAll(DayAssignment.getAtInterval(newAssignments, + startInclusive, endExclusive)); + } + + public List getAssignments() { + return DayAssignment.orderedByDay(new ArrayList( + assignments)); + } + + +} diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/DerivedDayAssignment.java b/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/DerivedDayAssignment.java new file mode 100644 index 000000000..249ecb983 --- /dev/null +++ b/navalplanner-business/src/main/java/org/navalplanner/business/planner/entities/DerivedDayAssignment.java @@ -0,0 +1,61 @@ +/* + * This file is part of ###PROJECT_NAME### + * + * Copyright (C) 2009 Fundación para o Fomento da Calidade Industrial e + * Desenvolvemento Tecnolóxico de Galicia + * + * 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 . + */ +package org.navalplanner.business.planner.entities; + +import org.apache.commons.lang.Validate; +import org.hibernate.validator.NotNull; +import org.joda.time.LocalDate; +import org.navalplanner.business.resources.entities.Machine; +import org.navalplanner.business.resources.entities.Resource; + + +/** + * @author Óscar González Fernández + * + */ +public class DerivedDayAssignment extends DayAssignment { + + public static DerivedDayAssignment create(LocalDate day, int hours, + Resource resource, DerivedAllocation derivedAllocation) { + return create(new DerivedDayAssignment(day, hours, resource, + derivedAllocation)); + } + + @NotNull + private DerivedAllocation allocation; + + private DerivedDayAssignment(LocalDate day, int hours, Resource resource, + DerivedAllocation derivedAllocation) { + super(day, hours, resource); + Validate.notNull(derivedAllocation); + Validate.isTrue(resource instanceof Machine); + this.allocation = derivedAllocation; + } + + @Override + protected void detachFromAllocation() { + this.allocation = null; + } + + public DerivedAllocation getAllocation() { + return allocation; + } + +} diff --git a/navalplanner-business/src/test/java/org/navalplanner/business/test/planner/entities/DerivedAllocationTest.java b/navalplanner-business/src/test/java/org/navalplanner/business/test/planner/entities/DerivedAllocationTest.java new file mode 100644 index 000000000..a2b004f38 --- /dev/null +++ b/navalplanner-business/src/test/java/org/navalplanner/business/test/planner/entities/DerivedAllocationTest.java @@ -0,0 +1,221 @@ +/*x + * This file is part of ###PROJECT_NAME### + * + * Copyright (C) 2009 Fundación para o Fomento da Calidade Industrial e + * Desenvolvemento Tecnolóxico de Galicia + * + * 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 . + */ +package org.navalplanner.business.test.planner.entities; + +import static org.easymock.EasyMock.expect; +import static org.easymock.classextension.EasyMock.createNiceMock; +import static org.easymock.classextension.EasyMock.replay; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.joda.time.LocalDate; +import org.junit.Test; +import org.navalplanner.business.planner.entities.DerivedAllocation; +import org.navalplanner.business.planner.entities.DerivedDayAssignment; +import org.navalplanner.business.planner.entities.GenericResourceAllocation; +import org.navalplanner.business.planner.entities.ResourceAllocation; +import org.navalplanner.business.planner.entities.SpecificResourceAllocation; +import org.navalplanner.business.resources.entities.Machine; +import org.navalplanner.business.resources.entities.MachineWorkersConfigurationUnit; +import org.navalplanner.business.resources.entities.Resource; +import org.navalplanner.business.resources.entities.Worker; + +/** + * @author Óscar González Fernández + */ +public class DerivedAllocationTest { + + private Machine machine = Machine.create(); + + private MachineWorkersConfigurationUnit configurationUnit; + + private ResourceAllocation derivedFrom; + + private DerivedAllocation derivedAllocation; + + private List dayAssignments; + + private void givenConfigurationUnit(Machine machine) { + configurationUnit = createNiceMock(MachineWorkersConfigurationUnit.class); + expect(configurationUnit.getMachine()).andReturn(machine).anyTimes(); + replay(configurationUnit); + } + + private void givenConfigurationUnit() { + givenConfigurationUnit(machine); + } + + private void givenADerivedAllocation() { + givenDerivedFrom(); + givenConfigurationUnit(); + derivedAllocation = DerivedAllocation.create(derivedFrom, + configurationUnit); + } + + private void givenDayAssignments(LocalDate start, Resource resource, int... hours) { + givenDayAssignments(derivedAllocation, start, resource, hours); + } + + private void givenDayAssignments(DerivedAllocation derivedAllocation, + LocalDate start, Resource resource, int... hours) { + dayAssignments = new ArrayList(); + for (int i = 0; i < hours.length; i++) { + LocalDate current = start.plusDays(i); + DerivedDayAssignment d = DerivedDayAssignment.create(current, + hours[i], resource, derivedAllocation); + dayAssignments.add(d); + } + } + + private Machine createMachine() { + Machine result = createNiceMock(Machine.class); + replay(result); + return result; + } + + private void givenSpecificDerivedFrom(Resource resource) { + derivedFrom = createNiceMock(SpecificResourceAllocation.class); + SpecificResourceAllocation specific = (SpecificResourceAllocation) derivedFrom; + expect(specific.getResource()).andReturn(resource).anyTimes(); + replay(derivedFrom); + } + + private void givenGenericDerivedFrom(Resource... resources) { + derivedFrom = createNiceMock(GenericResourceAllocation.class); + GenericResourceAllocation generic = (GenericResourceAllocation) derivedFrom; + expect(generic.getAssociatedResources()).andReturn( + Arrays.asList(resources)); + replay(derivedFrom); + } + + private void givenDerivedFrom() { + givenSpecificDerivedFrom(machine); + } + + @Test + public void aDerivedAllocationHasAMachineWorkerConfigurationUnitAndAResourceAllocation() { + givenConfigurationUnit(); + givenDerivedFrom(); + DerivedAllocation result = DerivedAllocation.create(derivedFrom, + configurationUnit); + assertNotNull(result); + assertThat(result.getConfigurationUnit(), equalTo(configurationUnit)); + assertEquals(result.getDerivedFrom(), derivedFrom); + } + + @Test(expected = IllegalArgumentException.class) + public void theConfigurationUnitMachineMustBeTheSameThanTheAllocationIfItIsSpecific() { + givenConfigurationUnit(createMachine()); + givenSpecificDerivedFrom(createMachine()); + DerivedAllocation.create(derivedFrom, configurationUnit); + } + + @Test(expected = IllegalArgumentException.class) + public void theMachineOfTheConfigurationUnitMustBeInTheResourcesOfTheGenericAlloation() { + givenConfigurationUnit(); + givenGenericDerivedFrom(Worker.create(), Worker.create()); + DerivedAllocation.create(derivedFrom, configurationUnit); + } + + @Test(expected = IllegalArgumentException.class) + public void theDerivedFromMustBeNotNull() { + givenConfigurationUnit(); + DerivedAllocation.create(derivedFrom, configurationUnit); + } + + @Test(expected = IllegalArgumentException.class) + public void theConfigurationUnitMustBeNotNull() { + givenDerivedFrom(); + DerivedAllocation.create(derivedFrom, configurationUnit); + } + + @Test + public void aJustCreatedDerivedAllocationIsANewObject() { + givenDerivedFrom(); + givenConfigurationUnit(); + DerivedAllocation result = DerivedAllocation.create(derivedFrom, + configurationUnit); + assertTrue(result.isNewObject()); + } + + @Test + public void aDerivedAllocationCanBeResetToSomeDayAssignmentsAndIsOrderedByDay() { + givenADerivedAllocation(); + givenDayAssignments(new LocalDate(2008, 12, 1), machine, 8, 8, 8, 8); + derivedAllocation.resetAssignmentsTo(dayAssignments); + assertThat(derivedAllocation.getAssignments(), equalTo(dayAssignments)); + } + + @Test(expected = IllegalArgumentException.class) + public void theDerivedDayAssignmentsMustBeForTheSameMachine() { + givenADerivedAllocation(); + final Machine otherMachine = Machine.create(); + givenDayAssignments(new LocalDate(2008, 12, 1), otherMachine, 8, 8, + 8); + derivedAllocation.resetAssignmentsTo(dayAssignments); + } + + @Test(expected = IllegalArgumentException.class) + public void theDerivedDayAssignmentsMustBeForTheSameDerivedAllocation() { + givenADerivedAllocation(); + DerivedAllocation another = DerivedAllocation.create(derivedFrom, + configurationUnit); + givenDayAssignments(another, new LocalDate(2008, 12, 1), machine, 8, 8, + 8); + derivedAllocation.resetAssignmentsTo(dayAssignments); + } + + @Test + public void theAssignmentsCanBeResetOnAnInterval() { + givenADerivedAllocation(); + LocalDate start = new LocalDate(2008, 12, 1); + givenDayAssignments(start, machine, 8, 8, 8, 8); + derivedAllocation.resetAssignmentsTo(dayAssignments); + final LocalDate startInterval = start.plusDays(2); + final LocalDate finishInterval = start.plusDays(4); + DerivedDayAssignment newAssignment = DerivedDayAssignment.create( + startInterval, 3, machine, derivedAllocation); + derivedAllocation.resetAssignmentsTo(startInterval, finishInterval, + Arrays.asList(newAssignment)); + assertThat(derivedAllocation.getAssignments(), equalTo(Arrays.asList( + dayAssignments.get(0), dayAssignments.get(1), newAssignment))); + } + + @Test + public void whenResettingAssignmentsOnIntervalOnlyTheOnesAtTheIntervalAreAdded() { + givenADerivedAllocation(); + LocalDate start = new LocalDate(2008, 12, 1); + givenDayAssignments(start, machine, 8, 8, 8, 8); + derivedAllocation.resetAssignmentsTo(dayAssignments); + DerivedDayAssignment newAssignment = DerivedDayAssignment.create(start + .minusDays(1), 3, machine, derivedAllocation); + derivedAllocation.resetAssignmentsTo(start, start.plusDays(4), Arrays + .asList(newAssignment)); + assertTrue(derivedAllocation.getAssignments().isEmpty()); + } + +}