From dc2b74b4f110f010b6b80c9bddbbcca7acf25e13 Mon Sep 17 00:00:00 2001 From: Susana Montes Pedreira Date: Thu, 15 Oct 2009 16:23:37 +0200 Subject: [PATCH] ItEr30S09ClasificacionTraballoItEr29S10: Allocation / deallocation of criterions to resources. --- .../entities/CriterionSatisfaction.java | 23 +- .../business/resources/entities/Resource.java | 195 ++++++++++-- .../daos/CriterionSatisfactionDAOTest.java | 9 + .../test/resources/entities/ResourceTest.java | 82 ++++- .../web/common/InvalidInputsChecker.java | 2 +- .../worker/AssignedCriterionsModel.java | 140 +++++---- .../worker/CriterionSatisfactionDTO.java | 24 +- .../worker/CriterionsController.java | 281 ++++++++++++++++-- .../worker/IAssignedCriterionsModel.java | 6 +- .../web/resources/worker/IWorkerModel.java | 2 + .../worker/WorkerCRUDController.java | 90 +++--- .../web/resources/worker/WorkerModel.java | 10 + .../webapp/resources/worker/_criterions.zul | 40 ++- .../main/webapp/resources/worker/worker.zul | 5 +- 14 files changed, 710 insertions(+), 199 deletions(-) diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/CriterionSatisfaction.java b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/CriterionSatisfaction.java index ddf1aad89..42df5704d 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/CriterionSatisfaction.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/CriterionSatisfaction.java @@ -27,7 +27,6 @@ import org.apache.commons.lang.Validate; import org.apache.commons.lang.builder.ToStringBuilder; import org.hibernate.validator.NotNull; import org.navalplanner.business.common.BaseEntity; - /** * Declares a interval of time in which the criterion is satisfied
* @author Óscar González Fernández @@ -164,8 +163,11 @@ public class CriterionSatisfaction extends BaseEntity { } public void finish(Date finish) { - Validate.notNull(finish); - Validate.isTrue(startDate.equals(finish) || startDate.before(finish)); + Validate.isTrue(finish == null || getStartDate() == null + || getStartDate().equals(finish) || getStartDate().before(finish)); + Validate.isTrue(finishDate == null || isNewObject() || + getEndDate().equals(finish) || getEndDate().before(finish)); + if(finish !=null) finish = new Date(finish.getTime()); this.finishDate = finish; } @@ -174,10 +176,15 @@ public class CriterionSatisfaction extends BaseEntity { } public void setEndDate(Date date) { - finishDate = date; + if(date != null) finish(date); + this.finishDate = date; } public void setStartDate(Date date) { + if(date != null){ + Validate.isTrue(startDate == null || isNewObject() || + getStartDate().equals(date) || getStartDate().after(date)); + } startDate = date; } @@ -201,6 +208,14 @@ public class CriterionSatisfaction extends BaseEntity { Interval thisInterval = getInterval(); return !thisInterval.overlapsWith(other.getInterval()); } + } + public void validate(){ + Validate.notNull(resource); + Validate.notNull(startDate); + Validate.notNull(criterion); + Validate.isTrue(finishDate == null || finishDate.after(startDate)); + Validate.isTrue(finishDate == null || startDate.equals(finishDate) + || startDate.before(finishDate)); } } diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/Resource.java b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/Resource.java index 243816d87..eca6b10b7 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/Resource.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/Resource.java @@ -19,7 +19,6 @@ */ package org.navalplanner.business.resources.entities; - import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -31,6 +30,7 @@ import java.util.List; import java.util.ListIterator; import java.util.Map; import java.util.Set; +import java.util.Calendar; import org.apache.commons.lang.Validate; import org.joda.time.Days; @@ -79,7 +79,13 @@ public abstract class Resource extends BaseEntity{ return list; } public Set getCriterionSatisfactions() { - return criterionSatisfactions; + Set satisfactionActives = + new HashSet(); + for(CriterionSatisfaction satisfaction:criterionSatisfactions){ + if(!satisfaction.isIsDeleted()) + satisfactionActives.add(satisfaction); + } + return satisfactionActives; } public abstract String getDescription(); @@ -156,7 +162,18 @@ public abstract class Resource extends BaseEntity{ */ public List result() { ArrayList result = new ArrayList(); - for (CriterionSatisfaction criterionSatisfaction : criterionSatisfactions) { + for (CriterionSatisfaction criterionSatisfaction : getCriterionSatisfactions()) { + if (isAcceptedByAllPredicates(criterionSatisfaction)) { + result.add(criterionSatisfaction); + } + } + Collections.sort(result, CriterionSatisfaction.BY_START_COMPARATOR); + return result; + } + + public List result(Set list) { + ArrayList result = new ArrayList(); + for (CriterionSatisfaction criterionSatisfaction : list) { if (isAcceptedByAllPredicates(criterionSatisfaction)) { result.add(criterionSatisfaction); } @@ -289,21 +306,18 @@ public abstract class Resource extends BaseEntity{ } public CriterionSatisfaction addSatisfaction( - CriterionWithItsType criterionWithItsType, Interval interval) { + CriterionWithItsType criterionWithItsType, Interval interval){ Criterion criterion = criterionWithItsType.getCriterion(); ICriterionType type = criterionWithItsType.getType(); CriterionSatisfaction newSatisfaction = createNewSatisfaction(interval, criterion); if (canAddSatisfaction(criterionWithItsType, interval)) { - Date finish = getFinishDate(type, newSatisfaction, interval); - if (finish != null) { - newSatisfaction.finish(finish); - } + newSatisfaction.validate(); criterionSatisfactions.add(newSatisfaction); return newSatisfaction; } else { - throw new IllegalStateException( - "this resource is activaved for other criterion of the same type"); + throw new IllegalStateException(" The "+criterion.getName()+ + " can not be assigned to this resource. Its interval overlap with other criterion"); } } @@ -316,7 +330,8 @@ public abstract class Resource extends BaseEntity{ private Date getFinishDate(ICriterionType type, CriterionSatisfaction newSatisfaction, Interval interval) { if (!type.isAllowSimultaneousCriterionsPerResource()) { - CriterionSatisfaction posterior = getNext(type, newSatisfaction); + CriterionSatisfaction posterior = getNext(type, newSatisfaction, + this.getCriterionSatisfactions()); if (posterior != null && posterior.overlapsWith(interval)) { assert !posterior.overlapsWith(Interval.range(interval .getStart(), posterior.getStartDate())); @@ -365,20 +380,71 @@ public abstract class Resource extends BaseEntity{ return result; } + public void modifySatisfaction(CriterionSatisfaction original, + Interval interval){ + /* Create a temporal criterion satisfaction. */ + CriterionType type = original.getCriterion().getType(); + CriterionSatisfaction temporal = createNewSatisfaction(interval, + original.getCriterion()); + temporal.setResource(this); + + boolean canAdd=false; + if (contains(original)) { + try{ + removeCriterionSatisfaction(original); + canAdd = canAddSatisfaction(type, temporal); + if(canAdd){ + //update original + original.setStartDate(interval.getStart()); + original.finish(interval.getEnd()); + } + original.validate(); + criterionSatisfactions.add(original); + if(!canAdd){ + throw new IllegalStateException( + "This interval "+original.getCriterion().getName()+" not is valid because exists overlap with other criterion satisfaction"); + } + }catch(IllegalArgumentException e){ + throw new IllegalArgumentException (original.getCriterion().getName()+" : "+e.getMessage()); + } + }else{ + throw new IllegalStateException( + "The criterion satisfaction "+original.getCriterion().getName()+" not is activated for this resource"); + } + } + public boolean canAddSatisfaction( CriterionWithItsType criterionWithItsType, Interval interval) { ICriterionType type = criterionWithItsType.getType(); + Criterion criterion = criterionWithItsType.getCriterion(); if (!type.criterionCanBeRelatedTo(getClass())) { return false; } - if (type.isAllowSimultaneousCriterionsPerResource()) { + CriterionSatisfaction newSatisfaction = createNewSatisfaction(interval, + criterion); + + CriterionSatisfaction previousSameCriterion = getPreviousSameCriterion + (criterion, newSatisfaction,this.getCriterionSatisfactions()); + CriterionSatisfaction posteriorSameCriterion = getNextSameCriterion + (criterion, newSatisfaction,this.getCriterionSatisfactions()); + + boolean canAdd = ((previousSameCriterion == null || + !previousSameCriterion.overlapsWith(interval)) && + ( posteriorSameCriterion == null || + !posteriorSameCriterion.overlapsWith(interval))); + + if(!canAdd) return false; + if (type.isAllowSimultaneousCriterionsPerResource()){ return true; } - CriterionSatisfaction newSatisfaction = createNewSatisfaction(interval, - criterionWithItsType.getCriterion()); + CriterionSatisfaction previous = getPrevious(criterionWithItsType - .getType(), newSatisfaction); - return previous == null || !previous.overlapsWith(interval); + .getType(), newSatisfaction,this.getCriterionSatisfactions()); + CriterionSatisfaction posterior = getNext(criterionWithItsType + .getType(), newSatisfaction,this.getCriterionSatisfactions()); + + return (previous == null || !previous.overlapsWith(interval)) && + ( posterior == null || !posterior.overlapsWith(interval)); } public boolean canAddSatisfaction(ICriterionType type, @@ -389,8 +455,8 @@ public abstract class Resource extends BaseEntity{ } private CriterionSatisfaction getNext(ICriterionType type, - CriterionSatisfaction newSatisfaction) { - List ordered = query().from(type).result(); + CriterionSatisfaction newSatisfaction,Set list) { + List ordered = query().from(type).result(list); int position = findPlace(ordered, newSatisfaction); CriterionSatisfaction next = position != ordered.size() ? ordered .get(position) : null; @@ -398,8 +464,27 @@ public abstract class Resource extends BaseEntity{ } private CriterionSatisfaction getPrevious(ICriterionType type, - CriterionSatisfaction newSatisfaction) { - List ordered = query().from(type).result(); + CriterionSatisfaction newSatisfaction,Set list) { + List ordered = query().from(type).result(list); + int position = findPlace(ordered, newSatisfaction); + CriterionSatisfaction previous = position > 0 ? ordered + .get(position - 1) : null; + return previous; + } + + + private CriterionSatisfaction getNextSameCriterion(Criterion criterion, + CriterionSatisfaction newSatisfaction,Set list) { + List ordered = query().from(criterion).result(list); + int position = findPlace(ordered, newSatisfaction); + CriterionSatisfaction next = position != ordered.size() ? ordered + .get(position) : null; + return next; + } + + private CriterionSatisfaction getPreviousSameCriterion(Criterion criterion, + CriterionSatisfaction newSatisfaction,Set list) { + List ordered = query().from(criterion).result(list); int position = findPlace(ordered, newSatisfaction); CriterionSatisfaction previous = position > 0 ? ordered .get(position - 1) : null; @@ -420,7 +505,7 @@ public abstract class Resource extends BaseEntity{ private List getRelatedTypes() { List types = new ArrayList(); - for (CriterionSatisfaction criterionSatisfaction : getAllSatisfactions()) { + for (CriterionSatisfaction criterionSatisfaction : this.getCriterionSatisfactions()) { types.add(criterionSatisfaction.getCriterion().getType()); } return types; @@ -536,4 +621,72 @@ public abstract class Resource extends BaseEntity{ return sum; } + public Date date(int year,int month, int day) { + Calendar calendar = Calendar.getInstance(); + calendar.clear(); + calendar.set(Calendar.YEAR, year); + calendar.set(Calendar.MONTH, month); + calendar.set(Calendar.DAY_OF_MONTH, day); + return calendar.getTime(); + } + + public void addSatisfactions(Set addlist){ + //Create a newList with new Satisfactions and the old satisfactions + Set newList = new HashSet(addlist); + for(CriterionSatisfaction satisfaction : criterionSatisfactions){ + if(!newList.contains(satisfaction)){ + newList.add(satisfaction); + } + } + //Create a activeList with not eliminated Satifaction + Set activeList = new HashSet(); + for(CriterionSatisfaction satisfaction : addlist){ + if(!satisfaction.isIsDeleted()){ + activeList.add(satisfaction); + } + } + if(isValidSatisfactions(activeList)){ + criterionSatisfactions.clear(); + criterionSatisfactions.addAll(newList); + }else + throw new IllegalStateException( + "This set of satisfaction not is " + + "valid because exists overlap with others criterions satisfaction"); + } + + public boolean isValidSatisfactions(Set newList){ + for(CriterionSatisfaction satisfaction : newList){ + //Copied list without the satisfaction to check + Set checkedList = new HashSet(newList); + checkedList.remove(satisfaction); + + CriterionType type = satisfaction.getCriterion().getType(); + Criterion criterion = satisfaction.getCriterion(); + Interval interval = satisfaction.getInterval(); + + CriterionSatisfaction previousSameCriterion = getPreviousSameCriterion + (criterion, satisfaction,checkedList); + CriterionSatisfaction posteriorSameCriterion = getNextSameCriterion + (criterion, satisfaction,checkedList); + + boolean canAdd = ((previousSameCriterion == null || + !previousSameCriterion.overlapsWith(interval)) && + ( posteriorSameCriterion == null || + !posteriorSameCriterion.overlapsWith(interval))); + + if(!canAdd) return false; + if (type.isAllowSimultaneousCriterionsPerResource()){ + return true; + } + + CriterionSatisfaction previous = getPrevious(type,satisfaction,checkedList); + CriterionSatisfaction posterior = getNext(type,satisfaction,checkedList); + + return (previous == null || !previous.overlapsWith(interval)) && + ( posterior == null || !posterior.overlapsWith(interval)); + } + return true; + } + + } diff --git a/navalplanner-business/src/test/java/org/navalplanner/business/test/resources/daos/CriterionSatisfactionDAOTest.java b/navalplanner-business/src/test/java/org/navalplanner/business/test/resources/daos/CriterionSatisfactionDAOTest.java index ab837d8d7..4e2b91550 100644 --- a/navalplanner-business/src/test/java/org/navalplanner/business/test/resources/daos/CriterionSatisfactionDAOTest.java +++ b/navalplanner-business/src/test/java/org/navalplanner/business/test/resources/daos/CriterionSatisfactionDAOTest.java @@ -116,6 +116,15 @@ public class CriterionSatisfactionDAOTest { return calendar.getTime(); } + public static Date date(int year,int month, int day) { + Calendar calendar = Calendar.getInstance(); + calendar.clear(); + calendar.set(Calendar.YEAR, year); + calendar.set(Calendar.MONTH, month); + calendar.set(Calendar.DAY_OF_MONTH, day); + return calendar.getTime(); + } + @Test public void testRemove() throws InstanceNotFoundException { CriterionSatisfaction satisfaction = createValidCriterionSatisfaction(2008); diff --git a/navalplanner-business/src/test/java/org/navalplanner/business/test/resources/entities/ResourceTest.java b/navalplanner-business/src/test/java/org/navalplanner/business/test/resources/entities/ResourceTest.java index da57d1e80..7dd10f478 100644 --- a/navalplanner-business/src/test/java/org/navalplanner/business/test/resources/entities/ResourceTest.java +++ b/navalplanner-business/src/test/java/org/navalplanner/business/test/resources/entities/ResourceTest.java @@ -19,7 +19,7 @@ */ package org.navalplanner.business.test.resources.entities; - +import java.util.Date; import static org.hamcrest.CoreMatchers.equalTo; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; @@ -27,6 +27,7 @@ import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.navalplanner.business.test.resources.daos.CriterionSatisfactionDAOTest.year; +import static org.navalplanner.business.test.resources.daos.CriterionSatisfactionDAOTest.date; import java.util.ArrayList; import java.util.Arrays; @@ -99,11 +100,11 @@ public class ResourceTest { createTypeThatMatches(otherCriterion), otherCriterion); Worker worker = Worker.create("firstName", "surName", "2333232"); worker.addSatisfaction(criterionWithItsType, Interval - .from(CriterionSatisfactionDAOTest.year(2000))); + .range(year(2000),year(3000))); worker.addSatisfaction(otherCriterionWithItsType, Interval - .from(CriterionSatisfactionDAOTest.year(2000))); + .from(year(2000))); worker.addSatisfaction(criterionWithItsType, Interval - .from(CriterionSatisfactionDAOTest.year(4000))); + .from(year(4000))); assertEquals(2, worker.getSatisfactionsFor(criterionType).size()); assertEquals(1, worker.getCurrentSatisfactionsFor(criterionType).size()); } @@ -121,13 +122,13 @@ public class ResourceTest { Worker worker = Worker.create("firstName", "surName", "2333232"); assertThat(worker.getCurrentCriterionsFor(type).size(), equalTo(0)); worker.addSatisfaction(criterionWithItsType, Interval - .from(CriterionSatisfactionDAOTest.year(2000))); + .range(year(2000),year(2010))); assertThat(worker.getCurrentCriterionsFor(type).size(), equalTo(1)); worker.addSatisfaction(criterionWithItsType, Interval - .from(CriterionSatisfactionDAOTest.year(2002))); + .from(year(2010))); assertThat(worker.getCurrentCriterionsFor(type).size(), equalTo(1)); worker.addSatisfaction(otherCriterionWithItsType, Interval - .from(CriterionSatisfactionDAOTest.year(2000))); + .from(year(2000))); assertThat(worker.getCurrentCriterionsFor(type).size(), equalTo(2)); } @@ -180,18 +181,18 @@ public class ResourceTest { Worker worker = Worker.create("firstName", "surName", "2333232"); worker.addSatisfaction(criterionWithItsType, Interval - .from(CriterionSatisfactionDAOTest.year(2000))); + .range(year(2000),year(2002))); worker.addSatisfaction(criterionWithItsType, Interval - .from(CriterionSatisfactionDAOTest.year(2003))); + .from(year(2003))); worker.addSatisfaction(otherCriterionWithItsType, Interval - .from(CriterionSatisfactionDAOTest.year(2000))); + .from(year(2000))); assertEquals(2, worker.getSatisfactionsFor(criterionType).size()); - assertEquals(1, worker.query().from(criterionType).enforcedInAll( + assertEquals(0, worker.query().from(criterionType).enforcedInAll( Interval.range(year(2001), year(2005))).current().result() .size()); - assertEquals(2, worker.query().from(criterionType).enforcedInAll( - Interval.range(year(2004), year(2005))).current().result() + assertEquals(1, worker.query().from(criterionType).enforcedInAll( + Interval.range(year(2000), year(2001))).result() .size()); assertEquals(0, worker.query().from(criterionType).enforcedInAll( Interval.range(year(1999), year(2005))).current().result() @@ -254,7 +255,7 @@ public class ResourceTest { worker.addSatisfaction(new CriterionWithItsType(criterionType, criterion), Interval.range(year(5000), year(6000))); worker.addSatisfaction(new CriterionWithItsType(criterionType, - criterion), Interval.from(year(4000))); + criterion), Interval.range(year(4000),year(5000))); assertThat(worker.query().from(criterion).enforcedInAll( Interval.range(year(4001), year(4999))).result().size(), @@ -294,7 +295,7 @@ public class ResourceTest { worker.addSatisfaction(new CriterionWithItsType(criterionType, criterion), Interval.from(year(4000))); worker.addSatisfaction(new CriterionWithItsType(criterionType, - otherCriterion), Interval.from(year(3500))); + otherCriterion), Interval.range(year(3500),year(4000))); assertThat(worker.getSatisfactionsFor(otherCriterion).size(), equalTo(1)); CriterionSatisfaction satisfaction = worker.getSatisfactionsFor( @@ -363,6 +364,57 @@ public class ResourceTest { } } + @Test + public void testCantAddCriterionSatisfactionWithOverlap() { + Criterion criterion = CriterionDAOTest.createValidCriterion(); + Criterion otherCriterion = CriterionDAOTest.createValidCriterion(); + Worker worker = Worker.create("firstName", "surName", "2333232"); + ICriterionType criterionType = createTypeThatMatches(false, + criterion,otherCriterion); + + Interval intervalA = Interval.range(date(2009,10,14),date(2009,10,26)); + Interval intervalB = Interval.range(date(2009,10,15),date(2009,10,24)); + Interval intervalC = Interval.range(date(2009,10,12),date(2009,10,16)); + Interval intervalE = Interval.range(date(2009,10,26),date(2009,10,30)); + worker.addSatisfaction(new CriterionWithItsType(criterionType, + criterion), intervalA); + //Same Criterion + assertFalse(worker.canAddSatisfaction(new CriterionWithItsType( + criterionType, criterion), intervalB)); + assertFalse(worker.canAddSatisfaction(new CriterionWithItsType( + criterionType, criterion), intervalC)); + //Distict Criterion + assertFalse(worker.canAddSatisfaction(new CriterionWithItsType( + criterionType, otherCriterion), intervalC)); + assertTrue(worker.canAddSatisfaction(new CriterionWithItsType( + criterionType, criterion), intervalE)); + } + + @Test + public void testCantAddCriterionSatisfactionWithTypeAllowMultipleResource() { + Criterion criterion = CriterionDAOTest.createValidCriterion(); + Criterion otherCriterion = CriterionDAOTest.createValidCriterion(); + Worker worker = Worker.create("firstName", "surName", "2333232"); + ICriterionType criterionType = createTypeThatMatches(true, + criterion,otherCriterion); + + Interval intervalA = Interval.range(date(2009,10,8),date(2009,10,25)); + Interval intervalB = Interval.range(date(2009,10,5),date(2009,10,9)); + Interval intervalC = Interval.range(date(2009,11,12),date(2009,11,16)); + Interval intervalE = Interval.range(date(2009,10,26),date(2009,10,30)); + worker.addSatisfaction(new CriterionWithItsType(criterionType, + criterion), intervalA); + //Same Criterion + assertFalse(worker.canAddSatisfaction(new CriterionWithItsType( + criterionType, criterion), intervalB)); + //Distinct Criterion + assertTrue(worker.canAddSatisfaction(new CriterionWithItsType( + criterionType, otherCriterion), intervalC)); + //without overlap + assertTrue(worker.canAddSatisfaction(new CriterionWithItsType( + criterionType, criterion), intervalE)); + } + public void testAddCriterionSatisfaction() throws Exception { Criterion criterion = CriterionDAOTest.createValidCriterion(); Worker worker = Worker.create("firstName", "surName", "2333232"); diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/common/InvalidInputsChecker.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/common/InvalidInputsChecker.java index 6d9d2f65a..f8a3e1daa 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/common/InvalidInputsChecker.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/common/InvalidInputsChecker.java @@ -47,7 +47,7 @@ public class InvalidInputsChecker { return false; } - private static boolean isInvalid(Component child) { + public static boolean isInvalid(Component child) { if (child instanceof InputElement) { InputElement input = (InputElement) child; if (!input.isValid()) { diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/worker/AssignedCriterionsModel.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/worker/AssignedCriterionsModel.java index 32982cef3..7ac48b7f5 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/worker/AssignedCriterionsModel.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/worker/AssignedCriterionsModel.java @@ -12,16 +12,19 @@ import java.util.List; import java.util.Set; import org.hibernate.validator.ClassValidator; +import static org.navalplanner.web.I18nHelper._; import org.hibernate.validator.InvalidValue; import org.navalplanner.business.common.exceptions.ValidationException; import org.navalplanner.business.resources.daos.ICriterionTypeDAO; import org.navalplanner.business.resources.daos.IResourceDAO; +import org.navalplanner.business.resources.daos.IWorkerDAO; import org.navalplanner.business.resources.entities.Criterion; import org.navalplanner.business.resources.entities.CriterionSatisfaction; import org.navalplanner.business.resources.entities.CriterionType; import org.navalplanner.business.resources.entities.CriterionWithItsType; import org.navalplanner.business.resources.entities.ICriterionType; import org.navalplanner.business.resources.entities.Interval; +import org.navalplanner.business.resources.entities.Resource; import org.navalplanner.business.resources.entities.Worker; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.config.BeanDefinition; @@ -40,12 +43,18 @@ import org.zkoss.zul.Listbox; @Scope(BeanDefinition.SCOPE_PROTOTYPE) public class AssignedCriterionsModel implements IAssignedCriterionsModel { - private ClassValidator satisfactionValidator = new ClassValidator( + private ClassValidator satisfactionDTOValidator = new ClassValidator( CriterionSatisfactionDTO.class); + private ClassValidator satisfactionValidator = new ClassValidator( + CriterionSatisfaction.class); + @Autowired private IResourceDAO resourceDAO; + @Autowired + private IWorkerDAO workerDAO; + @Autowired private ICriterionTypeDAO criterionTypeDAO; @@ -65,6 +74,11 @@ public class AssignedCriterionsModel implements IAssignedCriterionsModel { } } + public void prepareForCreate(Worker worker){ + this.worker = worker; + this.criterionSatisfactionDTOs = new HashSet(); + } + private void initDTOs(){ criterionSatisfactionDTOs = new HashSet(); for(CriterionSatisfaction criterionSatisfaction : @@ -96,15 +110,15 @@ public class AssignedCriterionsModel implements IAssignedCriterionsModel { @Override @Transactional(readOnly = true) public void reattachmentWorker(){ - resourceDAO.save(worker); - for(CriterionSatisfaction criterionSatisfaction : - worker.getCriterionSatisfactions()){ - criterionSatisfaction.getCriterion().getName(); - criterionSatisfaction.getCriterion().getType().getName(); - if(criterionSatisfaction.getCriterion().getParent() != null){ - criterionSatisfaction.getCriterion().getParent().getName(); + resourceDAO.save(worker); + for(CriterionSatisfaction criterionSatisfaction : + worker.getCriterionSatisfactions()){ + criterionSatisfaction.getCriterion().getName(); + criterionSatisfaction.getCriterion().getType().getName(); + if(criterionSatisfaction.getCriterion().getParent() != null){ + criterionSatisfaction.getCriterion().getParent().getName(); + } } - } } @Override @@ -149,20 +163,23 @@ public class AssignedCriterionsModel implements IAssignedCriterionsModel { criterionsWithItsTypes = new ArrayList(); List listTypes = criterionTypeDAO.getCriterionTypes(); for(CriterionType criterionType : listTypes){ - Set listCriterion = getDirectCriterions(criterionType); - getCriterionWithItsType(criterionType,listCriterion ); + if(criterionType.isEnabled()){ + Set listCriterion = getDirectCriterions(criterionType); + getCriterionWithItsType(criterionType,listCriterion ); + } } return criterionsWithItsTypes; } private void getCriterionWithItsType(CriterionType type, Set children){ for(Criterion criterion : children){ - //Create the criterion with its criterionType and its Hierarchy label - CriterionWithItsType criterionAndType = new CriterionWithItsType(type,criterion); - - //Add to the list - criterionsWithItsTypes.add(criterionAndType); - getCriterionWithItsType(type,criterion.getChildren()); + if(criterion.isActive()){ + //Create the criterion with its criterionType and its Hierarchy label + CriterionWithItsType criterionAndType = new CriterionWithItsType(type,criterion); + //Add to the list + criterionsWithItsTypes.add(criterionAndType); + getCriterionWithItsType(type,criterion.getChildren()); + } } } @@ -201,6 +218,8 @@ public class AssignedCriterionsModel implements IAssignedCriterionsModel { private boolean existSameCriterionTypeAndInterval(CriterionSatisfactionDTO satisfaction){ for(CriterionSatisfactionDTO otherSatisfaction : criterionSatisfactionDTOs){ if((!otherSatisfaction.equals(satisfaction))&& + (!otherSatisfaction.isIsDeleted())&& + (!satisfaction.isIsDeleted())&& (sameCriterionType(otherSatisfaction,satisfaction)) && (sameInterval(otherSatisfaction,satisfaction))) { return true; @@ -212,6 +231,8 @@ public class AssignedCriterionsModel implements IAssignedCriterionsModel { private boolean existSameCriterionAndInterval(CriterionSatisfactionDTO satisfaction){ for(CriterionSatisfactionDTO otherSatisfaction : criterionSatisfactionDTOs){ if((!otherSatisfaction.equals(satisfaction))&& + (!otherSatisfaction.isIsDeleted())&& + (!satisfaction.isIsDeleted())&& (sameCriterion(otherSatisfaction,satisfaction)) && (sameInterval(otherSatisfaction,satisfaction))) { return true; @@ -242,51 +263,68 @@ public class AssignedCriterionsModel implements IAssignedCriterionsModel { CriterionSatisfactionDTO satisfaction){ if(otherSatisfaction.getStartDate() == null) return false; Interval otherInterval = otherSatisfaction.getInterval(); - if(satisfaction.overlapsWith(otherInterval)) + Interval interval = satisfaction.getInterval(); + if((satisfaction.overlapsWith(otherInterval))|| + (otherSatisfaction.overlapsWith(interval))) return true; return false; } - public void save()throws ValidationException { - InvalidValue[] invalidValues; - for(CriterionSatisfactionDTO satisfactionDTO : this.criterionSatisfactionDTOs){ - invalidValues = satisfactionValidator.getInvalidValues(satisfactionDTO); - if (invalidValues.length > 0) + @Override + public void validate() + throws ValidationException,IllegalStateException { + validateDTOs(); + } + + @Override + public void confirm() + throws ValidationException,IllegalStateException { + updateDTOs(); + } + + private void validateDTOs() throws ValidationException{ + Set listDTOs = + new HashSet(criterionSatisfactionDTOs); + for(CriterionSatisfactionDTO satisfactionDTO : listDTOs){ + InvalidValue[] invalidValues; + invalidValues = satisfactionDTOValidator.getInvalidValues(satisfactionDTO); + if (invalidValues.length > 0){ throw new ValidationException(invalidValues); - save(satisfactionDTO); + } + Criterion criterion = satisfactionDTO.getCriterionWithItsType().getCriterion(); + if(checkSameCriterionAndSameInterval(satisfactionDTO)){ + throw new IllegalStateException(_(" The "+criterion.getName()+ + " can not be assigned to this resource. Its interval overlap with other criterion")); + } + if(checkNotAllowSimultaneousCriterionsPerResource(satisfactionDTO)){ + throw new IllegalStateException(_(" The "+criterion.getName()+ + "is not valid, the criterionType overlap other criterionSatisfaction whith same criterionType")); + } } } - private void save(CriterionSatisfactionDTO satisfactionDTO){ - if(satisfactionDTO.isIsNewObject()){ - addNewSatisfaction(satisfactionDTO); + + private void updateDTOs()throws ValidationException,IllegalStateException { + //Create a new list of Criterion satisfaction + Set newList = new HashSet(); + for(CriterionSatisfactionDTO satisfactionDTO :criterionSatisfactionDTOs){ + CriterionSatisfaction satisfaction; + if(satisfactionDTO.isIsNewObject()){ + Criterion criterion = satisfactionDTO.getCriterionWithItsType().getCriterion(); + Interval interval = satisfactionDTO.getInterval(); + satisfaction = CriterionSatisfaction.create(criterion, worker, interval); + }else{ + satisfaction = satisfactionDTO.getCriterionSatisfaction(); if(satisfactionDTO.isIsDeleted()){ - removeSatisfaction(satisfactionDTO); - }else { - updateSatisfaction(satisfactionDTO); + satisfaction.setIsDeleted(true); + }else{ + satisfaction.setStartDate(satisfactionDTO.getStartDate()); + satisfaction.finish(satisfactionDTO.getEndDate()); } } + newList.add(satisfaction); + } + worker.addSatisfactions(newList); } - - private void addNewSatisfaction(CriterionSatisfactionDTO satisfactionDTO){ - Interval interval = satisfactionDTO.getInterval(); - worker.addSatisfaction(satisfactionDTO.getCriterionWithItsType(), interval); - } - - private void removeSatisfaction(CriterionSatisfactionDTO satisfactionDTO){ - CriterionSatisfaction satisfaction = satisfactionDTO.getCriterionSatisfaction(); - satisfaction.setIsDeleted(true); - } - - private void updateSatisfaction(CriterionSatisfactionDTO satisfactionDTO){ - CriterionSatisfaction satisfaction = satisfactionDTO.getCriterionSatisfaction(); - Criterion newCriterion = satisfactionDTO.getCriterionWithItsType().getCriterion(); - Date newStartDate = satisfactionDTO.getStartDate(); - Date newEndDate = satisfactionDTO.getEndDate(); - satisfaction.setCriterion(newCriterion); - satisfaction.setStartDate(newStartDate); - satisfaction.setEndDate(newEndDate); - } - } diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/worker/CriterionSatisfactionDTO.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/worker/CriterionSatisfactionDTO.java index 824e214b3..816e0d5dc 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/worker/CriterionSatisfactionDTO.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/worker/CriterionSatisfactionDTO.java @@ -5,6 +5,7 @@ package org.navalplanner.web.resources.worker; +import java.util.Calendar; import java.util.Comparator; import java.util.Date; import org.hibernate.validator.NotNull; @@ -20,6 +21,10 @@ import org.navalplanner.business.resources.entities.Interval; */ public class CriterionSatisfactionDTO { + public static final String START_DATE = "startDate"; + + public static final String CRITERION_WITH_ITS_TYPE = "criterionWithItsType"; + private String state; private String criterionAndType; @@ -39,9 +44,11 @@ public class CriterionSatisfactionDTO { private CriterionSatisfaction criterionSatisfaction; public CriterionSatisfactionDTO(){ - this.setIsNewObject(Boolean.TRUE); + this.setIsNewObject(true); this.state = ""; this.criterionAndType = ""; + this.startDate = new Date(); + this.endDate = null; } public CriterionSatisfactionDTO(CriterionSatisfaction criterionSatisfaction) { @@ -56,19 +63,13 @@ public class CriterionSatisfactionDTO { this.setCriterionWithItsType(new CriterionWithItsType(type,criterion)); } - public String getCriterionAndType() { - if(criterionWithItsType == null) return criterionAndType; - return criterionWithItsType.getNameAndType(); - } - public void setCriterionAndType(String criterionAndType) { this.criterionAndType = criterionAndType; } public String getState() { if(startDate == null) return ""; - if(!isFinished()) return "In force"; - if(isCurrent()) return "In force"; + if( !isFinished() || isCurrent() ) return "Current"; return "Expired"; } @@ -174,13 +175,16 @@ public class CriterionSatisfactionDTO { if(isNewObject) return true; if((getEndDate() == null) || (endDate == null)) return true; + if(getCriterionSatisfaction().getEndDate() == null) + return true; if(endDate.compareTo(getCriterionSatisfaction().getEndDate()) >= 0) return true; return false; } - public String getNameAndType(){ - if(criterionWithItsType == null) return ""; + public String getCriterionAndType() { + if(criterionWithItsType == null) return criterionAndType; return criterionWithItsType.getNameAndType(); + } } diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/worker/CriterionsController.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/worker/CriterionsController.java index 708f8dc61..6854a3e7c 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/worker/CriterionsController.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/worker/CriterionsController.java @@ -4,9 +4,11 @@ */ package org.navalplanner.web.resources.worker; +import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Set; +import org.hibernate.validator.InvalidValue; import org.navalplanner.web.common.Util; import org.zkoss.zk.ui.Component; import org.zkoss.zk.ui.WrongValueException; @@ -14,15 +16,26 @@ import org.zkoss.zk.ui.WrongValueException; import org.zkoss.zul.Constraint; import static org.navalplanner.web.I18nHelper._; import org.navalplanner.business.common.exceptions.ValidationException; +import org.navalplanner.business.resources.entities.CriterionSatisfaction; +import static org.navalplanner.web.common.InvalidInputsChecker.thereAreInvalidInputsOn; +import static org.navalplanner.web.common.InvalidInputsChecker.isInvalid; import org.navalplanner.business.resources.entities.CriterionWithItsType; import org.navalplanner.business.resources.entities.Worker; +import org.navalplanner.web.common.IMessagesForUser; +import org.navalplanner.web.common.Level; +import org.navalplanner.web.common.MessagesForUser; import org.zkoss.zk.ui.util.GenericForwardComposer; import org.zkoss.zul.Bandbox; +import org.zkoss.zul.Column; import org.zkoss.zul.Combobox; import org.zkoss.zul.Comboitem; +import org.zkoss.zul.Datebox; import org.zkoss.zul.Grid; +import org.zkoss.zul.Hbox; +import org.zkoss.zul.ListModelExt; import org.zkoss.zul.Listitem; import org.zkoss.zul.Row; +import org.zkoss.zul.Rows; /** * @@ -31,30 +44,48 @@ import org.zkoss.zul.Row; public class CriterionsController extends GenericForwardComposer { private IAssignedCriterionsModel assignedCriterionsModel; - private Combobox comboboxFilter; + private Combobox comboboxfilter; private Grid listingCriterions; + private IMessagesForUser messages; + private Component messagesContainer; - CriterionsController() { + CriterionsController(IWorkerModel workerModel) { + assignedCriterionsModel = workerModel.getAssignedCriterionsModel(); } @Override public void doAfterCompose(Component comp) throws Exception { super.doAfterCompose(comp); + if (messagesContainer == null) + throw new RuntimeException(_("MessagesContainer is needed")); + messages = new MessagesForUser(messagesContainer); comp.setVariable("assignedCriterionsController", this, true); - comboboxFilter = (Combobox) comp.getFellow("comboboxfilter"); - listingCriterions = (Grid) comp.getFellow("listingCriterions"); + //comboboxFilter = (Combobox) comp.getFellow("comboboxfilter"); + //listingCriterions = (Grid) comp.getFellow("listingCriterions"); + } + + public IAssignedCriterionsModel getModel(){ + return this.assignedCriterionsModel; } public void prepareForEdit(Worker worker) { this.assignedCriterionsModel.prepareForEdit(worker); + reload(); } - public Set getCriterionSatisfactionDTOs() { - Comboitem comboitem = comboboxFilter.getSelectedItem(); - if((comboitem != null) && (comboitem.getLabel().equals("in force"))) { - return assignedCriterionsModel.getFilterCriterionSatisfactions(); - } - return assignedCriterionsModel.getAllCriterionSatisfactions(); + public void prepareForCreate(Worker worker) { + this.assignedCriterionsModel.prepareForCreate(worker); + } + + public List getCriterionSatisfactionDTOs() { + List list = new ArrayList(); + Comboitem comboitem = comboboxfilter.getSelectedItem(); + if((comboitem != null) && (comboitem.getLabel().equals("Currents"))) { + list.addAll(assignedCriterionsModel.getFilterCriterionSatisfactions()); + }else{ + list.addAll(assignedCriterionsModel.getAllCriterionSatisfactions()); + } + return list; } public void addCriterionSatisfaction() { @@ -68,6 +99,18 @@ public class CriterionsController extends GenericForwardComposer { public void reload() { Util.reloadBindings(listingCriterions); + forceSortGridSatisfaction(); + } + + public void forceSortGridSatisfaction() { + Column column = (Column) listingCriterions.getColumns().getFirstChild(); + ListModelExt model = (ListModelExt) listingCriterions.getModel(); + if ("ascending".equals(column.getSortDirection())) { + model.sort(column.getSortAscending(), true); + } + if ("descending".equals(column.getSortDirection())) { + model.sort(column.getSortDescending(), false); + } } public void remove(CriterionSatisfactionDTO criterionSatisfactionDTO){ @@ -107,7 +150,14 @@ public class CriterionsController extends GenericForwardComposer { } } - public void changeDate(Component comp){ + public void changeStartDate(Component comp,Date value){ + CriterionSatisfactionDTO criterionSatisfactionDTO = + (CriterionSatisfactionDTO)((Row) comp.getParent()).getValue(); + validateCriterionWithItsType(criterionSatisfactionDTO,comp); + reload(); + } + + public void changeEndDate(Component comp,Date value){ CriterionSatisfactionDTO criterionSatisfactionDTO = (CriterionSatisfactionDTO)((Row) comp.getParent()).getValue(); validateCriterionWithItsType(criterionSatisfactionDTO,comp); @@ -119,39 +169,206 @@ public class CriterionsController extends GenericForwardComposer { @Override public void validate(Component comp, Object value) throws WrongValueException { - CriterionSatisfactionDTO criterionSatisfactionDTO = - (CriterionSatisfactionDTO)((Row) comp.getParent()).getValue(); - if(!criterionSatisfactionDTO.isLessToEndDate((Date) value)){ - throw new WrongValueException(comp, - _("Start date is not valid, the new start date must be lower than the end date")); - }else if(!criterionSatisfactionDTO.isPreviousStartDate((Date) value)){ - throw new WrongValueException(comp, - _("End date is not valid, the new end date must be later the current end date")); - } + validateStartDate(comp,value); } }; } + private void validateStartDate(Component comp, Object value){ + CriterionSatisfactionDTO criterionSatisfactionDTO = + (CriterionSatisfactionDTO)((Row) comp.getParent()).getValue(); + if(!criterionSatisfactionDTO.isLessToEndDate((Date) value)){ + throw new WrongValueException(comp, + _("Start date is not valid, the new start date must be lower than the end date")); + }else if(!criterionSatisfactionDTO.isPreviousStartDate((Date) value)){ + throw new WrongValueException(comp, + _("End date is not valid, the new end date must be later the current end date")); + } + } + public Constraint validateEndDate(){ return new Constraint() { @Override public void validate(Component comp, Object value) throws WrongValueException { - CriterionSatisfactionDTO criterionSatisfactionDTO = - (CriterionSatisfactionDTO)((Row) comp.getParent()).getValue(); - if(!criterionSatisfactionDTO.isGreaterStartDate((Date) value)){ - throw new WrongValueException(comp, - _("End date is not valid, the new end date must be greater than the start date")); - }else if(!criterionSatisfactionDTO.isPostEndDate((Date) value)){ - throw new WrongValueException(comp, - _("End date is not valid, the new end date must be later the current end date")); - } - validateCriterionWithItsType(criterionSatisfactionDTO,comp); + validateEndDate(comp,value); } }; } - public void save() throws ValidationException{ - assignedCriterionsModel.save(); + + private void validateEndDate(Component comp, Object value){ + CriterionSatisfactionDTO criterionSatisfactionDTO = + (CriterionSatisfactionDTO)((Row) comp.getParent()).getValue(); + if(!criterionSatisfactionDTO.isGreaterStartDate((Date) value)){ + throw new WrongValueException(comp, + _("End date is not valid, the new end date must be greater than the start date")); + }else if(!criterionSatisfactionDTO.isPostEndDate((Date) value)){ + throw new WrongValueException(comp, + _("End date is not valid, the new end date must be later the current end date")); + } + } + + /** + * Shows invalid values for {@link CriterionSatisfaction} + * entities + * + * @param e + */ + public boolean validate() throws ValidationException{ + try{ + if(thereAreInvalidInputsOn(this.listingCriterions)){ + showInvalidInputs(); + return false; + } + assignedCriterionsModel.validate(); + reload(); + } catch (ValidationException e) { + showInvalidValues(e); + for (InvalidValue invalidValue : e.getInvalidValues()) { + messages.showMessage(Level.ERROR, invalidValue.getPropertyName()+invalidValue.getMessage()); + return false; + } + } catch (IllegalStateException e) { + messages.showMessage(Level.ERROR,e.getMessage()); + return false; + } + catch (IllegalArgumentException e) { + messages.showMessage(Level.ERROR,e.getMessage()); + return false; + } + return true; + } + + /** + * Shows invalid inputs for {@link CriterionSatisfactionDTO} entities + * + * @param + */ + private void showInvalidInputs(){ + if(listingCriterions != null){ + Rows rows = listingCriterions.getRows(); + List listRows = rows.getChildren(); + for(Row row : listRows){ + //Validate endDate Domain Restricctions. + Datebox endDate = getEndDatebox(row); + if(isInvalid(endDate)){ + validateEndDate(endDate, endDate.getValue()); + } + //Validate startDate Domain Restricctions. + Datebox startDate = getStartDatebox(row); + if(isInvalid(startDate)){ + validateStartDate(startDate, startDate.getValue()); + } + //Validate endDate Domain Restricctions. + Bandbox bandCriterion = getBandType(row); + if(isInvalid(bandCriterion)){ + CriterionSatisfactionDTO satisfactionDTO = + (CriterionSatisfactionDTO)row.getValue(); + validateCriterionWithItsType(satisfactionDTO,bandCriterion); + } + } + } + } + + /** + * Shows invalid values for {@link CriterionSatisfactionDTO} entities + * + * @param e + */ + private void showInvalidValues(ValidationException e) { + for (InvalidValue invalidValue : e.getInvalidValues()) { + Object value = invalidValue.getBean(); + if(value instanceof CriterionSatisfactionDTO){ + validateCriterionSatisfactionDTO(invalidValue, + (CriterionSatisfactionDTO)value); + } + } + } + + /** + * Validates {@link CriterionSatisfactionDTO} data constraints + * + * @param invalidValue + */ + private void validateCriterionSatisfactionDTO(InvalidValue invalidValue, + CriterionSatisfactionDTO satisfactionDTO) { + if(listingCriterions != null){ + + // Find which listItem contains CriterionSatisfaction inside listBox + Row row = findRowOfCriterionSatisfactionDTO(listingCriterions.getRows(), + satisfactionDTO); + + if (row != null) { + String propertyName = invalidValue.getPropertyName(); + + if (CriterionSatisfactionDTO.START_DATE.equals(propertyName)) { + // Locate TextboxResource + Datebox startDate = getStartDatebox(row); + // Value is incorrect, clear + startDate.setValue(null); + throw new WrongValueException(startDate, + _("The start date cannot be null")); + } + if (CriterionSatisfactionDTO.CRITERION_WITH_ITS_TYPE.equals(propertyName)) { + // Locate TextboxResource + Bandbox bandType = getBandType(row); + // Value is incorrect, clear + bandType.setValue(null); + throw new WrongValueException(bandType, + _("The criterion and its type cannot be null")); + } + } + } + } + + /** + * Locates which {@link row} is bound to {@link WorkReportLine} in + * rows + * + * @param Rows + * @param CriterionSatisfactionDTO + * @return + */ + private Row findRowOfCriterionSatisfactionDTO(Rows rows, + CriterionSatisfactionDTO satisfactionDTO) { + List listRows = (List) rows.getChildren(); + for (Row row : listRows) { + if (satisfactionDTO.equals(row.getValue())) { + return row; + } + } + return null; + } + + /** + * Locates {@link Datebox} criterion satisfaction in {@link row} + * + * @param row + * @return + */ + private Datebox getStartDatebox(Row row) { + return (Datebox) (row.getChildren().get(1)); + } + + /** + * Locates {@link Datebox} criterion satisfaction in {@link row} + * + * @param row + * @return + */ + private Datebox getEndDatebox(Row row) { + return (Datebox) (row.getChildren().get(2)); + } + + /** + * Locates {@link Bandbox} criterion satisfaction in {@link row} + * + * @param row + * @return + */ + private Bandbox getBandType(Row row) { + return (Bandbox)((Hbox) row.getChildren().get(0)) + .getChildren().get(0); } } diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/worker/IAssignedCriterionsModel.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/worker/IAssignedCriterionsModel.java index 709947351..e55397897 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/worker/IAssignedCriterionsModel.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/worker/IAssignedCriterionsModel.java @@ -24,11 +24,15 @@ public interface IAssignedCriterionsModel { void prepareForEdit(Worker worker); + void prepareForCreate(Worker worker); + void addCriterionSatisfaction(); void reattachmentWorker(); - void save()throws ValidationException; + void confirm()throws ValidationException; + + void validate()throws ValidationException; void remove(CriterionSatisfactionDTO criterionSatisfactionDTO); diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/worker/IWorkerModel.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/worker/IWorkerModel.java index 2b69cec8f..bdb5aecc3 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/worker/IWorkerModel.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/worker/IWorkerModel.java @@ -122,4 +122,6 @@ public interface IWorkerModel { void setCalendar(ResourceCalendar resourceCalendar); ResourceCalendar getCalendar(); + + IAssignedCriterionsModel getAssignedCriterionsModel(); } \ No newline at end of file diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/worker/WorkerCRUDController.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/worker/WorkerCRUDController.java index 1d85b109d..0e7e062ab 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/worker/WorkerCRUDController.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/worker/WorkerCRUDController.java @@ -57,8 +57,6 @@ import org.zkoss.zul.api.Window; public class WorkerCRUDController extends GenericForwardComposer implements IWorkerCRUDControllerEntryPoints { - private Window createWindow; - private Window listWindow; private Window editWindow; @@ -79,9 +77,7 @@ public class WorkerCRUDController extends GenericForwardComposer implements private Component messagesContainer; - private CriterionsController criterionsEditController; - - private CriterionsController criterionsCreateController; + private CriterionsController criterionsController; private WorkRelationshipsController addWorkRelationship; @@ -104,14 +100,13 @@ public class WorkerCRUDController extends GenericForwardComposer implements public WorkerCRUDController() { } - public WorkerCRUDController(Window createWindow, Window listWindow, + public WorkerCRUDController( Window listWindow, Window editWindow, Window workRelationshipsWindow, Window addWorkRelationshipWindow, Window editWorkRelationshipWindow, Window editCalendarWindow, IWorkerModel workerModel, IMessagesForUser messages, IWorkerCRUDControllerEntryPoints workerCRUD) { - this.createWindow = createWindow; this.listWindow = listWindow; this.editWindow = editWindow; this.workRelationshipsWindow = workRelationshipsWindow; @@ -138,16 +133,14 @@ public class WorkerCRUDController extends GenericForwardComposer implements } public void save() { - - if(thereAreInvalidInputsOn(getCurrentWindow())){ - return; - } try { if (baseCalendarEditionController != null) { baseCalendarEditionController.save(); } - if (criterionsEditController != null) { - criterionsEditController.save(); + if(criterionsController != null){ + if(!criterionsController.validate()){ + return; + } } workerModel.save(); goToList(); @@ -155,7 +148,7 @@ public class WorkerCRUDController extends GenericForwardComposer implements messages.showMessage(Level.INFO, _("Worker saved")); } catch (ValidationException e) { for (InvalidValue invalidValue : e.getInvalidValues()) { - messages.showMessage(Level.INFO, invalidValue.getPropertyName()+invalidValue.getMessage()); + messages.showMessage(Level.ERROR, invalidValue.getPropertyName()+invalidValue.getMessage()); return; } } @@ -171,20 +164,23 @@ public class WorkerCRUDController extends GenericForwardComposer implements } public void goToEditForm(Worker worker) { - getBookmarker().goToEditForm(worker); - workerModel.prepareEditFor(worker); - criterionsEditController.prepareForEdit( workerModel.getWorker()); - if (isCalendarNotNull()) { - editCalendar(); - } - getVisibility().showOnly(editWindow); - Util.reloadBindings(editWindow); + getBookmarker().goToEditForm(worker); + workerModel.prepareEditFor(worker); + if (isCalendarNotNull()) { + editCalendar(); + } + editAsignedCriterions(); + editWindow.setTitle(_("Edit Worker")); + getVisibility().showOnly(editWindow); + Util.reloadBindings(editWindow); + } public void goToEditForm() { if (isCalendarNotNull()) { editCalendar(); } + editWindow.setTitle(_("Edit Worker")); getVisibility().showOnly(editWindow); Util.reloadBindings(editWindow); } @@ -205,11 +201,12 @@ public class WorkerCRUDController extends GenericForwardComposer implements } public void goToCreateForm() { - getBookmarker().goToCreateForm(); - workerModel.prepareForCreate(); - criterionsEditController.prepareForEdit(workerModel.getWorker()); - getVisibility().showOnly(createWindow); - Util.reloadBindings(createWindow); + getBookmarker().goToCreateForm(); + workerModel.prepareForCreate(); + createAsignedCriterions(); + editWindow.setTitle(_("Create Worker")); + getVisibility().showOnly(editWindow); + Util.reloadBindings(editWindow); } public void goToEditWorkRelationshipForm(CriterionSatisfaction satisfaction) { @@ -226,7 +223,7 @@ public class WorkerCRUDController extends GenericForwardComposer implements localizationsForEditionController = createLocalizationsController(comp, "editWindow"); localizationsForCreationController = createLocalizationsController( - comp, "createWindow"); + comp, "editWindow"); comp.setVariable("controller", this, true); if (messagesContainer == null) throw new RuntimeException(_("MessagesContainer is needed")); @@ -244,15 +241,30 @@ public class WorkerCRUDController extends GenericForwardComposer implements .getRedirectorFor(IWorkerCRUDControllerEntryPoints.class); handler.registerListener(this, page); getVisibility().showOnly(listWindow); - - criterionsEditController = setupCriterionsController(editWindow); - criterionsCreateController = setupCriterionsController(createWindow); } - private CriterionsController setupCriterionsController(Window comp)throws Exception { - CriterionsController controller = new CriterionsController(); - controller.doAfterCompose(comp.getFellow("criterionsContainer")); - return controller; + private void editAsignedCriterions(){ + try{ + setupCriterionsController(); + criterionsController.prepareForEdit( workerModel.getWorker()); + }catch(Exception e){ + throw new RuntimeException(e); + } + } + + private void createAsignedCriterions(){ + try{ + setupCriterionsController(); + criterionsController.prepareForCreate( workerModel.getWorker()); + }catch(Exception e){ + throw new RuntimeException(e); + } + } + + private void setupCriterionsController()throws Exception { + criterionsController = new CriterionsController(workerModel); + criterionsController.doAfterCompose(getCurrentWindow(). + getFellow("criterionsContainer")); } public BaseCalendarEditionController getEditionController() { @@ -280,8 +292,8 @@ public class WorkerCRUDController extends GenericForwardComposer implements private OnlyOneVisible getVisibility() { if (visibility == null) { visibility = new OnlyOneVisible(listWindow, editWindow, - createWindow, workRelationshipsWindow, - addWorkRelationshipWindow, editWorkRelationshipWindow); + workRelationshipsWindow,addWorkRelationshipWindow, + editWorkRelationshipWindow); } return visibility; } @@ -397,11 +409,7 @@ public class WorkerCRUDController extends GenericForwardComposer implements } private Window getCurrentWindow() { - if (workerModel.isCreating()) { - return createWindow; - } else { return editWindow; - } } private void updateCalendarController() { diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/worker/WorkerModel.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/worker/WorkerModel.java index 4dd020127..2d3d32fe3 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/worker/WorkerModel.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/worker/WorkerModel.java @@ -92,6 +92,9 @@ public class WorkerModel implements IWorkerModel { @Qualifier("subclass") private IBaseCalendarModel baseCalendarModel; + @Autowired + private IAssignedCriterionsModel assignedCriterionsModel; + @Autowired public WorkerModel(IResourceDAO resourceDAO, ICriterionDAO criterionDAO) { @@ -114,6 +117,9 @@ public class WorkerModel implements IWorkerModel { throw new ValidationException(invalidValues); } getLocalizationsAssigner().applyChanges(); + if(assignedCriterionsModel != null){ + assignedCriterionsModel.confirm(); + } resourceDAO.save(worker); worker.checkNotOverlaps(); worker = null; @@ -486,4 +492,8 @@ public class WorkerModel implements IWorkerModel { return null; } + public IAssignedCriterionsModel getAssignedCriterionsModel() { + return assignedCriterionsModel; + } + } diff --git a/navalplanner-webapp/src/main/webapp/resources/worker/_criterions.zul b/navalplanner-webapp/src/main/webapp/resources/worker/_criterions.zul index 90c1b90d3..2e3261812 100644 --- a/navalplanner-webapp/src/main/webapp/resources/worker/_criterions.zul +++ b/navalplanner-webapp/src/main/webapp/resources/worker/_criterions.zul @@ -1,5 +1,4 @@ - - + @@ -9,16 +8,15 @@ - + - + @@ -27,13 +25,13 @@ - - @@ -43,19 +41,20 @@ - + - - + + + onChange="assignedCriterionsController.changeEndDate(self,self.value);" width="150px"/> - diff --git a/navalplanner-webapp/src/main/webapp/resources/worker/worker.zul b/navalplanner-webapp/src/main/webapp/resources/worker/worker.zul index 3b308852d..84886c568 100644 --- a/navalplanner-webapp/src/main/webapp/resources/worker/worker.zul +++ b/navalplanner-webapp/src/main/webapp/resources/worker/worker.zul @@ -36,11 +36,12 @@ sclass="workerwindow"> + - + +