diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/Criterion.java b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/Criterion.java
index 868fa6b95..3fca9d4ca 100644
--- a/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/Criterion.java
+++ b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/Criterion.java
@@ -55,11 +55,12 @@ public class Criterion implements ICriterion {
@Override
public boolean isSatisfiedBy(Resource resource) {
- return !resource.getActiveSatisfactionsFor(this).isEmpty();
+ return !resource.getCurrentSatisfactionsFor(this).isEmpty();
}
public boolean isSatisfiedBy(Resource resource, Date start, Date end) {
- return !resource.getActiveSatisfactionsForIn(this, start, end)
+ return !resource.query().from(this)
+ .enforcedInAll(Interval.range(start, end)).result()
.isEmpty();
}
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 40ab932f9..3d3aaaf97 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
@@ -1,11 +1,9 @@
package org.navalplanner.business.resources.entities;
+import java.util.Comparator;
import java.util.Date;
import org.apache.commons.lang.Validate;
-import org.navalplanner.business.common.exceptions.InstanceNotFoundException;
-import org.navalplanner.business.resources.daos.ICriterionSatisfactionDAO;
-import org.springframework.beans.factory.annotation.Autowired;
/**
* Declares a interval of time in which the criterion is satisfied
@@ -13,18 +11,24 @@ import org.springframework.beans.factory.annotation.Autowired;
*/
public class CriterionSatisfaction {
+ public static final Comparator BY_START_COMPARATOR;
+
+ static {
+ BY_START_COMPARATOR = new Comparator() {
+
+ @Override
+ public int compare(CriterionSatisfaction o1,
+ CriterionSatisfaction o2) {
+ return o1.getStartDate().compareTo(o2.getStartDate());
+ }
+ };
+ }
+
private Long id;
@SuppressWarnings("unused")
private long version;
- @Autowired
- private ICriterionSatisfactionDAO criterionSatisfactionDAO;
-
-
- /**
- * Required by hibernate. Do not use directly
- */
public CriterionSatisfaction() {
}
@@ -39,6 +43,14 @@ public class CriterionSatisfaction {
this.resource = resource;
}
+ public CriterionSatisfaction(Criterion criterion, Resource resource,
+ Interval interval) {
+ this(interval.getStart(), criterion, resource);
+ if (interval.getEnd() != null) {
+ this.finish(interval.getEnd());
+ }
+ }
+
public Long getId() {
return id;
}
@@ -52,44 +64,54 @@ public class CriterionSatisfaction {
private Resource resource;
public Date getStartDate() {
- return startDate==null ? null: new Date(startDate.getTime());
+ return startDate != null ? new Date(startDate.getTime()) : null;
}
public Date getEndDate() {
- if (isFinished() ) {
+ if (isFinished()) {
return new Date(finishDate.getTime());
} else {
return null;
}
}
+ public Interval getInterval() {
+ return Interval.range(startDate, finishDate);
+ }
+
public Criterion getCriterion() {
return criterion;
}
+ public void setCriterion(Criterion criterion) {
+ this.criterion = criterion;
+ }
+
public Resource getResource() {
return resource;
}
- public boolean isActiveNow() {
+ public void setResource(Resource resource) {
+ this.resource = resource;
+ }
+
+ public boolean isCurrent() {
Date now = new Date();
- return isActiveAt(now);
+ return isEnforcedAt(now);
}
- public boolean isActiveAt(Date date) {
- return (startDate.before(date) || startDate.equals(date))
- && (finishDate == null || date.before(finishDate));
+ public boolean isEnforcedAt(Date date) {
+ return getInterval().contains(date);
}
- public boolean isActiveIn(Date start, Date end) {
- return (startDate.equals(start) || startDate.before(start))
- && (finishDate == null || end.before(finishDate));
+ public boolean isAlwaysEnforcedIn(Interval interval) {
+ return getInterval().includes(interval);
}
public void finish(Date finish) {
Validate.notNull(finish);
Validate.isTrue(startDate.equals(finish) || startDate.before(finish));
- finishDate = finish;
+ this.finishDate = finish;
}
public boolean isFinished() {
@@ -97,13 +119,20 @@ public class CriterionSatisfaction {
}
public void setEndDate(Date date) {
- if ( (startDate.equals(date) || startDate.before(date)) )
+ if (date == null) {
+ finishDate = null;
+ }
+ if ((startDate.equals(date) || startDate.before(date)))
finishDate = date;
}
public void setStartDate(Date date) {
- if ( (finishDate == null || finishDate.after(date)) )
+ if ((finishDate == null || finishDate.after(date)))
startDate = date;
}
+ public boolean overlapsWith(Interval interval) {
+ return getInterval().overlapsWith(interval);
+ }
+
}
diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/CriterionTypeBase.java b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/CriterionTypeBase.java
index 413afa12f..0d6803a53 100644
--- a/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/CriterionTypeBase.java
+++ b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/CriterionTypeBase.java
@@ -10,7 +10,7 @@ public abstract class CriterionTypeBase implements ICriterionType {
private final boolean allowHierarchy;
- private final boolean allowMultipleCriterionsPerResource;
+ private final boolean allowSimultaneousCriterionsPerResource;
private final String name;
@@ -19,11 +19,11 @@ public abstract class CriterionTypeBase implements ICriterionType {
private final boolean allowEditing;
protected CriterionTypeBase(String name, boolean allowHierarchy,
- boolean allowMultipleCriterionsPerResource, boolean allowAdding,
- boolean allowEditing) {
+ boolean allowSimultaneousCriterionsPerResource,
+ boolean allowAdding, boolean allowEditing) {
Validate.notNull(name, "name is not null");
this.allowHierarchy = allowHierarchy;
- this.allowMultipleCriterionsPerResource = allowMultipleCriterionsPerResource;
+ this.allowSimultaneousCriterionsPerResource = allowSimultaneousCriterionsPerResource;
this.name = name;
this.allowAdding = allowAdding;
this.allowEditing = allowEditing;
@@ -35,8 +35,8 @@ public abstract class CriterionTypeBase implements ICriterionType {
}
@Override
- public boolean allowMultipleActiveCriterionsPerResource() {
- return allowMultipleCriterionsPerResource;
+ public boolean allowSimultaneousCriterionsPerResource() {
+ return allowSimultaneousCriterionsPerResource;
}
public String getName() {
diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/ICriterionType.java b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/ICriterionType.java
index a23d23cae..fca4140b6 100644
--- a/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/ICriterionType.java
+++ b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/ICriterionType.java
@@ -8,7 +8,7 @@ public interface ICriterionType {
public String getName();
- public boolean allowMultipleActiveCriterionsPerResource();
+ public boolean allowSimultaneousCriterionsPerResource();
public boolean allowHierarchy();
diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/Interval.java b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/Interval.java
new file mode 100644
index 000000000..228b3d298
--- /dev/null
+++ b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/Interval.java
@@ -0,0 +1,157 @@
+package org.navalplanner.business.resources.entities;
+
+import java.util.Date;
+
+import org.apache.commons.lang.Validate;
+
+/**
+ * Represents a time interval
+ * @author Óscar González Fernández
+ */
+public abstract class Interval {
+ protected final Date start;
+ protected final Date end;
+
+ public static Interval from(Date start) {
+ return new OpenEndedInterval(start);
+ }
+
+ public static Interval point(Date date) {
+ return new Point(date);
+ }
+
+ public static Interval range(Date start, Date end) {
+ Validate.notNull(start, "start date must be not null");
+ if (end == null)
+ return from(start);
+ if (start.equals(end))
+ return point(start);
+ return new Range(start, end);
+ }
+
+ protected Interval(Date start, Date end) {
+ Validate.notNull(start, "start date must be not null");
+ if (end != null) {
+ Validate.isTrue(start.compareTo(end) <= 0,
+ "start date must be equal or before than end date");
+ }
+ this.start = start;
+ this.end = end;
+ }
+
+ public abstract boolean contains(Date date);
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof Interval) {
+ Interval interval = (Interval) obj;
+ return dateEquals(start, interval.start)
+ && dateEquals(end, interval.end);
+ }
+ return false;
+ }
+
+ private boolean dateEquals(Date date1, Date date2) {
+ return date1 == date2
+ || (date1 != null && date2 != null && date1.equals(date2));
+ }
+
+ public abstract boolean includes(Interval included);
+
+ public abstract boolean overlapsWith(Interval interval);
+
+ public boolean before(Date date) {
+ return start.before(date);
+ }
+
+ public Date getStart() {
+ return new Date(start.getTime());
+ }
+
+ public Date getEnd() {
+ return end != null ? new Date(end.getTime()) : null;
+ }
+
+}
+
+class Range extends Interval {
+
+ Range(Date start, Date end) {
+ super(start, end);
+ Validate.notNull(start);
+ Validate.notNull(end);
+ }
+
+ @Override
+ public boolean contains(Date date) {
+ return date.compareTo(start) >= 0 && date.compareTo(end) < 0;
+ }
+
+ @Override
+ public boolean includes(Interval included) {
+ if (included instanceof Point) {
+ Point point = (Point) included;
+ return point.overlapsWith(this);
+ }
+ return start.compareTo(included.start) <= 0 && included.end != null
+ && end.after(included.end);
+ }
+
+ @Override
+ public boolean overlapsWith(Interval interval) {
+ if (interval instanceof Point) {
+ Point point = (Point) interval;
+ return point.overlapsWith(this);
+ }
+ return contains(interval.start)
+ || (interval.end != null ? contains(interval.end)
+ && !interval.end.equals(start) : end
+ .compareTo(interval.start) > 0);
+ }
+
+}
+
+class OpenEndedInterval extends Interval {
+ OpenEndedInterval(Date start) {
+ super(start, null);
+ }
+
+ @Override
+ public boolean contains(Date date) {
+ return date.compareTo(start) >= 0;
+ }
+
+ @Override
+ public boolean includes(Interval included) {
+ return start.compareTo(included.start) <= 0;
+ }
+
+ @Override
+ public boolean overlapsWith(Interval interval) {
+ return start.before(interval.start) || interval.end == null
+ || start.before(interval.end);
+ }
+}
+
+class Point extends Interval {
+
+ Point(Date date) {
+ super(date, date);
+ }
+
+ @Override
+ public boolean contains(Date date) {
+ return start.equals(date);
+ }
+
+ @Override
+ public boolean includes(Interval included) {
+ return equals(included);
+ }
+
+ @Override
+ public boolean overlapsWith(Interval interval) {
+ return interval.contains(end) && !interval.start.equals(end);
+ }
+
+}
\ No newline at end of file
diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/PredefinedCriterionTypes.java b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/PredefinedCriterionTypes.java
index 359d2ad91..c5fc037f7 100644
--- a/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/PredefinedCriterionTypes.java
+++ b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/PredefinedCriterionTypes.java
@@ -30,7 +30,7 @@ public enum PredefinedCriterionTypes implements ICriterionType {
private final boolean allowHierarchy;
- private final boolean allowMultipleActiveCriterionsPerResource;
+ private final boolean allowSimultaneousCriterionsPerResource;
private final boolean allowAdding;
@@ -39,11 +39,11 @@ public enum PredefinedCriterionTypes implements ICriterionType {
private List> classes;
private PredefinedCriterionTypes(boolean allowHierarchy,
- boolean allowMultipleActiveCriterionsPerResource,
+ boolean allowSimultaneousCriterionsPerResource,
boolean allowAdding, boolean allowEditing,
Class extends Resource>... klasses) {
this.allowHierarchy = allowHierarchy;
- this.allowMultipleActiveCriterionsPerResource = allowMultipleActiveCriterionsPerResource;
+ this.allowSimultaneousCriterionsPerResource = allowSimultaneousCriterionsPerResource;
this.allowAdding = allowAdding;
this.allowEditing = allowEditing;
this.classes = Arrays.asList(klasses);
@@ -64,8 +64,8 @@ public enum PredefinedCriterionTypes implements ICriterionType {
}
@Override
- public boolean allowMultipleActiveCriterionsPerResource() {
- return allowMultipleActiveCriterionsPerResource;
+ public boolean allowSimultaneousCriterionsPerResource() {
+ return allowSimultaneousCriterionsPerResource;
}
@Override
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 5a57947a8..858fb47f0 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
@@ -1,11 +1,11 @@
package org.navalplanner.business.resources.entities;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
@@ -20,6 +20,7 @@ import org.navalplanner.business.resources.daos.ResourcesDaoRegistry;
// child another simple resource, general methods like getChilds() do not make
// sense for simple entities, etc.). In consequence, I prefer the modeling
// option shown below.
+
/**
* This class acts as the base class for all resources.
* @author Fernando Bellas Permuy
@@ -27,9 +28,126 @@ import org.navalplanner.business.resources.daos.ResourcesDaoRegistry;
public abstract class Resource {
private Long id;
+
private long version;
+
private Set criterionSatisfactions = new HashSet();
+ private interface Predicate {
+ public boolean accepts(CriterionSatisfaction satisfaction);
+ }
+
+ public class Query {
+
+ private List predicates = new ArrayList();
+ private boolean sort = false;
+
+ private Query() {
+
+ }
+
+ public Query from(final ICriterionType> type) {
+ return withNewPredicate(new Predicate() {
+
+ @Override
+ public boolean accepts(CriterionSatisfaction satisfaction) {
+ return type.contains(satisfaction.getCriterion());
+ }
+ });
+ }
+
+ private Query withNewPredicate(Predicate newPredicate) {
+ predicates.add(newPredicate);
+ return this;
+ }
+
+ public Query at(Date date) {
+ return enforcedInAll(Interval.point(date));
+ }
+
+ public Query between(Date start, Date end) {
+ return enforcedInAll(Interval.range(start, end));
+ }
+
+ public Query enforcedInAll(final Interval interval) {
+ return withNewPredicate(new Predicate() {
+
+ @Override
+ public boolean accepts(CriterionSatisfaction satisfaction) {
+ return satisfaction.isAlwaysEnforcedIn(interval);
+ }
+ });
+ }
+
+ public Query overlapsWith(final Interval interval) {
+ return withNewPredicate(new Predicate() {
+
+ @Override
+ public boolean accepts(CriterionSatisfaction satisfaction) {
+ return satisfaction.overlapsWith(interval);
+ }
+ });
+ }
+
+ public Query from(final ICriterion criterion) {
+ return withNewPredicate(new Predicate() {
+
+ @Override
+ public boolean accepts(CriterionSatisfaction satisfaction) {
+ return satisfaction.getCriterion().isEquivalent(criterion);
+ }
+ });
+ }
+
+ public Query sortByStartDate() {
+ sort = true;
+ return this;
+ }
+
+ public List result() {
+ ArrayList result = new ArrayList();
+ for (CriterionSatisfaction criterionSatisfaction : criterionSatisfactions) {
+ if (isAcceptedByAllPredicates(criterionSatisfaction)) {
+ result.add(criterionSatisfaction);
+ }
+ }
+ Collections.sort(result, CriterionSatisfaction.BY_START_COMPARATOR);
+ return result;
+ }
+
+ private boolean isAcceptedByAllPredicates(
+ CriterionSatisfaction criterionSatisfaction) {
+ for (Predicate predicate : predicates) {
+ if (!predicate.accepts(criterionSatisfaction))
+ return false;
+ }
+ return true;
+ }
+
+ public Query current() {
+ return withNewPredicate(new Predicate() {
+
+ @Override
+ public boolean accepts(CriterionSatisfaction satisfaction) {
+ return satisfaction.isCurrent();
+ }
+ });
+ }
+
+ public List asCriterions() {
+ LinkedHashSet result = new LinkedHashSet();
+ for (CriterionSatisfaction criterionSatisfaction : result()) {
+ result.add(criterionSatisfaction.getCriterion());
+ }
+ return new ArrayList(result);
+ }
+
+ }
+
+ public Query query() {
+ return new Query();
+ }
+
public Long getId() {
return id;
}
@@ -63,207 +181,194 @@ public abstract class Resource {
}
public Set getAllSatisfactions() {
- return new HashSet(criterionSatisfactions);
+ return new HashSet(criterionSatisfactions);
}
public Collection getSatisfactionsFor(
ICriterionType> type) {
- Set allSatisfactions = getAllSatisfactions();
- ArrayList result = new ArrayList();
- for (CriterionSatisfaction criterionSatisfaction : allSatisfactions) {
- if (type.contains(criterionSatisfaction.getCriterion())) {
- result.add(criterionSatisfaction);
- }
- }
- return result;
+ return query().from(type).result();
}
public List getSatisfactionsFor(ICriterion criterion) {
- ArrayList result = new ArrayList();
- for (CriterionSatisfaction criterionSatisfaction : getAllSatisfactions()) {
- if (criterionSatisfaction.getCriterion().isEquivalent(criterion)) {
- result.add(criterionSatisfaction);
- }
- }
- return result;
+ return query().from(criterion).result();
}
- public Set getActiveCriterionsFor(ICriterionType> type) {
- Set result = new HashSet();
- Collection active = getActiveSatisfactionsFor(type);
- for (CriterionSatisfaction satisfaction : active) {
- result.add(satisfaction.getCriterion());
- }
- return result;
+ public List getCurrentCriterionsFor(ICriterionType> type) {
+ return query().from(type).current().asCriterions();
}
- public Collection getActiveSatisfactionsFor(
+ public Collection getCurrentSatisfactionsFor(
ICriterionType> criterionType) {
- Collection satisfactionsFor = getSatisfactionsFor(criterionType);
- ArrayList result = new ArrayList();
- for (CriterionSatisfaction criterionSatisfaction : satisfactionsFor) {
- if (criterionSatisfaction.isActiveNow()) {
- result.add(criterionSatisfaction);
- }
- }
- return result;
+ return query().from(criterionType).current().result();
}
- public Collection getActiveSatisfactionsForIn(
- ICriterionType> criterionType, Date start, Date end) {
- Validate.notNull(criterionType);
- Validate.isTrue(end == null || start.before(end));
- Collection satisfactionsFor = getSatisfactionsFor(criterionType);
- ArrayList result = new ArrayList();
- for (CriterionSatisfaction criterionSatisfaction : satisfactionsFor) {
- if (end == null && criterionSatisfaction.isActiveAt(start) || end != null && criterionSatisfaction.isActiveIn(start, end)) {
- result.add(criterionSatisfaction);
- }
- }
- return result;
- }
-
- public Collection getActiveSatisfactionsAt(
- ICriterionType> criterionType, Date pointInTime) {
- return getActiveSatisfactionsForIn(criterionType, pointInTime, null);
- }
-
- public Collection getActiveSatisfactionsFor(
+ public List getCurrentSatisfactionsFor(
ICriterion criterion) {
- Set result = new HashSet();
- for (CriterionSatisfaction criterionSatisfaction : getAllSatisfactionsFor(criterion)) {
- if (criterionSatisfaction.isActiveNow()) {
- result.add(criterionSatisfaction);
+ return query().from(criterion).current().result();
+ }
+
+ public CriterionSatisfaction addSatisfaction(
+ CriterionWithItsType criterionWithItsType) {
+ return addSatisfaction(criterionWithItsType, Interval.from(new Date()));
+ }
+
+ private static class EnsureSatisfactionIsCorrect {
+
+ private EnsureSatisfactionIsCorrect(Resource resource,
+ ICriterionType> type, CriterionSatisfaction satisfaction) {
+ Validate.notNull(resource);
+ Validate.notNull(satisfaction.getResource());
+ Validate.notNull(satisfaction);
+ if (!satisfaction.getResource().equals(resource)) {
+ throw new IllegalArgumentException(
+ "the satisfaction is not related to this resource");
}
+ this.type = new CriterionWithItsType(type, satisfaction
+ .getCriterion());
+ this.interval = satisfaction.getInterval();
+ this.resource = resource;
}
- return result;
- }
- private Collection getAllSatisfactionsFor(
- ICriterion criterion) {
- Set result = new HashSet();
- for (CriterionSatisfaction satisfaction : criterionSatisfactions) {
- if (satisfaction.getCriterion().isEquivalent(criterion)) {
- result.add(satisfaction);
- }
+ final Resource resource;
+
+ final CriterionWithItsType type;
+
+ final Interval interval;
+
+ CriterionSatisfaction addSatisfaction() {
+ return resource.addSatisfaction(type, interval);
}
- return result;
- }
- public Collection getActiveSatisfactionsForIn(
- ICriterion criterion, Date start, Date end) {
- Validate.isTrue(end == null || start.before(end));
- ArrayList result = new ArrayList();
- Collection allSatisfactionsFor = getAllSatisfactionsFor(criterion);
- for (CriterionSatisfaction criterionSatisfaction : allSatisfactionsFor) {
- if (criterionSatisfaction.isActiveIn(start, end)) {
- result.add(criterionSatisfaction);
- }
+ boolean canAddSatisfaction() {
+ return resource.canAddSatisfaction(type, interval);
}
- return result;
+
}
- public void activate(CriterionWithItsType criterionWithItsType) {
- activate(criterionWithItsType, new Date());
+ public CriterionSatisfaction addSatisfaction(
+ ICriterionType type, CriterionSatisfaction satisfaction) {
+ return new EnsureSatisfactionIsCorrect(this, type, satisfaction)
+ .addSatisfaction();
}
- public void activate(CriterionWithItsType criterionWithItsType, Date start) {
- activate(criterionWithItsType, start, null);
- }
-
- public void activate(CriterionWithItsType criterionWithItsType, Date start,
- Date finish) {
- ICriterionType> type = criterionWithItsType.getType();
+ public CriterionSatisfaction addSatisfaction(
+ CriterionWithItsType criterionWithItsType, Interval interval) {
Criterion criterion = criterionWithItsType.getCriterion();
- if (canBeActivated(criterionWithItsType, start, finish)) {
- CriterionSatisfaction newSatisfaction = new CriterionSatisfaction(
- start, criterion, this);
- criterionSatisfactions.add(newSatisfaction);
+ 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);
}
- if (!type.allowMultipleActiveCriterionsPerResource()) {
- for (CriterionSatisfaction criterionSatisfaction : getActiveSatisfactionsAt(
- type, start)) {
- if (newSatisfaction != criterionSatisfaction) {
- criterionSatisfaction.finish(start);
- }
- }
- Set posterior = getSatisfactionsPosteriorTo(
- type, newSatisfaction);
- Date earliest = getEarliestStartDate(posterior);
- if (earliest != null) {
- newSatisfaction.finish(earliest);
- }
- }
+ criterionSatisfactions.add(newSatisfaction);
+ return newSatisfaction;
} else {
throw new IllegalStateException(
"this resource is activaved for other criterion of the same type");
}
-
}
- private static Date getEarliestStartDate(
- Set posterior) {
- Date earliest = null;
- for (CriterionSatisfaction criterionSatisfaction : posterior) {
- if (earliest == null) {
- earliest = criterionSatisfaction.getStartDate();
+ private CriterionSatisfaction createNewSatisfaction(Interval interval,
+ Criterion criterion) {
+ CriterionSatisfaction newSatisfaction = new CriterionSatisfaction(
+ criterion, this, interval);
+ return newSatisfaction;
+ }
+
+ private Date getFinishDate(ICriterionType> type,
+ CriterionSatisfaction newSatisfaction, Interval interval) {
+ if (!type.allowSimultaneousCriterionsPerResource()) {
+ CriterionSatisfaction posterior = getNext(type, newSatisfaction);
+ if (posterior != null && posterior.overlapsWith(interval)) {
+ assert !posterior.overlapsWith(Interval.range(interval
+ .getStart(), posterior.getStartDate()));
+ return posterior.getStartDate();
}
- earliest = Collections.min(Arrays.asList(earliest,
- criterionSatisfaction.getStartDate()));
}
- return earliest;
+ return interval.getEnd();
}
- private Set getSatisfactionsPosteriorTo(
- ICriterionType> type, CriterionSatisfaction newSatisfaction) {
- Date start = newSatisfaction.getStartDate();
- Date finish = newSatisfaction.isFinished() ? newSatisfaction.getEndDate() : null;
- Set posterior = new HashSet();
- if (finish != null) {
- posterior.addAll(getActiveSatisfactionsAt(type, finish));
+ /**
+ * @param orderedSatisfactions
+ * @param newSatisfaction
+ * @return the position in which if newSatisfaction is inserted would comply
+ * with the following:
+ *
+ * - newSatisfaction startDate would be equal or posterior to all
+ * the previous satisfactions
+ * - newSatisfaction startDate would be previous to all the
+ * posterior satisfactions
+ *
+ */
+ private int findPlace(List orderedSatisfactions,
+ CriterionSatisfaction newSatisfaction) {
+ int position = Collections.binarySearch(orderedSatisfactions,
+ newSatisfaction, CriterionSatisfaction.BY_START_COMPARATOR);
+ if (position >= 0) {
+ return position + 1;
} else {
- ArrayList result = new ArrayList();
- for (CriterionSatisfaction satisfaction : getSatisfactionsFor(type)) {
- if (!satisfaction.isFinished() && satisfaction.getStartDate().after(start)) {
- result.add(satisfaction);
- }
- }
- posterior.addAll(result);
- }
- posterior.remove(newSatisfaction);
- return posterior;
- }
-
- public void deactivate(CriterionWithItsType criterionWithItsType) {
- for (CriterionSatisfaction criterionSatisfaction : getActiveSatisfactionsFor(criterionWithItsType.getCriterion())) {
- criterionSatisfaction.finish(new Date());
+ return Math.abs(position) - 1;
}
}
- private boolean noneOf(CriterionWithItsType criterionWithItsType,
- Date start, Date end) {
+ public List finish(
+ CriterionWithItsType criterionWithItsType) {
+ return finishEnforcedAt(criterionWithItsType, new Date());
+ }
+
+ public List finishEnforcedAt(
+ CriterionWithItsType criterionWithItsType, Date date) {
+ ArrayList result = new ArrayList();
+ for (CriterionSatisfaction criterionSatisfaction : query().from(
+ criterionWithItsType.getType()).at(date).result()) {
+ criterionSatisfaction.finish(date);
+ result.add(criterionSatisfaction);
+ }
+ return result;
+ }
+
+ public boolean canAddSatisfaction(
+ CriterionWithItsType criterionWithItsType, Interval interval) {
ICriterionType> type = criterionWithItsType.getType();
- Criterion criterion = criterionWithItsType.getCriterion();
- return getActiveSatisfactionsForIn(type, start, end).size() == getActiveSatisfactionsForIn(
- criterion, start, end).size();
+ if (!type.criterionCanBeRelatedTo(getClass())) {
+ return false;
+ }
+ if (type.allowSimultaneousCriterionsPerResource()) {
+ return true;
+ }
+ CriterionSatisfaction newSatisfaction = createNewSatisfaction(interval,
+ criterionWithItsType.getCriterion());
+ CriterionSatisfaction previous = getPrevious(criterionWithItsType
+ .getType(), newSatisfaction);
+ return previous == null || !previous.overlapsWith(interval);
}
- public boolean canBeActivated(CriterionWithItsType criterionWithItsType) {
- return canBeActivated(criterionWithItsType, new Date());
+ public boolean canAddSatisfaction(ICriterionType> type,
+ CriterionSatisfaction satisfaction) {
+ return new EnsureSatisfactionIsCorrect(this, type, satisfaction)
+ .canAddSatisfaction();
}
- public boolean canBeActivated(CriterionWithItsType criterionWithItsType,
- Date start) {
- return canBeActivated(criterionWithItsType, start, null);
+ private CriterionSatisfaction getNext(ICriterionType> type,
+ CriterionSatisfaction newSatisfaction) {
+ List ordered = query().from(type)
+ .sortByStartDate().result();
+ int position = findPlace(ordered, newSatisfaction);
+ CriterionSatisfaction next = position != ordered.size() ? ordered
+ .get(position) : null;
+ return next;
}
- public boolean canBeActivated(CriterionWithItsType criterionWithItsType,
- Date start, Date finish) {
- ICriterionType> type = criterionWithItsType.getType();
- return type.criterionCanBeRelatedTo(getClass()) && (type.allowMultipleActiveCriterionsPerResource() || noneOf(
- criterionWithItsType, start, finish));
+ private CriterionSatisfaction getPrevious(ICriterionType> type,
+ CriterionSatisfaction newSatisfaction) {
+ List ordered = query().from(type)
+ .sortByStartDate().result();
+ int position = findPlace(ordered, newSatisfaction);
+ CriterionSatisfaction previous = position > 0 ? ordered
+ .get(position - 1) : null;
+ return previous;
}
public void removeCriterionSatisfaction(CriterionSatisfaction satisfaction)
@@ -271,4 +376,8 @@ public abstract class Resource {
criterionSatisfactions.remove(satisfaction);
}
+ public boolean contains(CriterionSatisfaction satisfaction) {
+ return criterionSatisfactions.contains(satisfaction);
+ }
+
}
diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/resources/services/impl/CriterionServiceImpl.java b/navalplanner-business/src/main/java/org/navalplanner/business/resources/services/impl/CriterionServiceImpl.java
index a0e0f8794..e812f74f2 100644
--- a/navalplanner-business/src/main/java/org/navalplanner/business/resources/services/impl/CriterionServiceImpl.java
+++ b/navalplanner-business/src/main/java/org/navalplanner/business/resources/services/impl/CriterionServiceImpl.java
@@ -14,6 +14,7 @@ import org.navalplanner.business.resources.entities.CriterionSatisfaction;
import org.navalplanner.business.resources.entities.ICriterion;
import org.navalplanner.business.resources.entities.ICriterionOnData;
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.services.CriterionService;
import org.navalplanner.business.resources.services.ResourceService;
@@ -100,7 +101,7 @@ public class CriterionServiceImpl implements CriterionService {
ICriterionType> criterionType) {
ArrayList result = new ArrayList();
for (Resource resource : resourceService.getResources()) {
- result.addAll(resource.getActiveSatisfactionsFor(criterionType));
+ result.addAll(resource.getCurrentSatisfactionsFor(criterionType));
}
return result;
}
@@ -110,8 +111,8 @@ public class CriterionServiceImpl implements CriterionService {
ICriterionType> criterionType, Date start, Date end) {
ArrayList result = new ArrayList();
for (Resource resource : resourceService.getResources()) {
- result.addAll(resource.getActiveSatisfactionsForIn(criterionType,
- start, end));
+ result.addAll(resource.query().from(criterionType).enforcedInAll(
+ Interval.range(start, end)).result());
}
return result;
}
diff --git a/navalplanner-business/src/test/java/org/navalplanner/business/test/resources/entities/CriterionSatisfactionTest.java b/navalplanner-business/src/test/java/org/navalplanner/business/test/resources/entities/CriterionSatisfactionTest.java
index 65200e3dc..53096ce29 100644
--- a/navalplanner-business/src/test/java/org/navalplanner/business/test/resources/entities/CriterionSatisfactionTest.java
+++ b/navalplanner-business/src/test/java/org/navalplanner/business/test/resources/entities/CriterionSatisfactionTest.java
@@ -1,17 +1,23 @@
package org.navalplanner.business.test.resources.entities;
+import java.util.ArrayList;
+import java.util.Collections;
import java.util.Date;
+import java.util.List;
import org.junit.Test;
import org.navalplanner.business.resources.entities.Criterion;
import org.navalplanner.business.resources.entities.CriterionSatisfaction;
+import org.navalplanner.business.resources.entities.Interval;
import org.navalplanner.business.resources.entities.Worker;
import org.navalplanner.business.test.resources.daos.CriterionDAOTest;
-import org.navalplanner.business.test.resources.daos.CriterionSatisfactionDAOTest;
import static junit.framework.Assert.assertEquals;
+import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
+import static org.navalplanner.business.test.resources.daos.CriterionSatisfactionDAOTest.year;
/**
* Tests for {@link CriterionSatisfaction}
@@ -24,8 +30,8 @@ public class CriterionSatisfactionTest {
final Criterion criterion = CriterionDAOTest.createValidCriterion();
Worker worker = new Worker("firstName", "surName", "2333232", 10);
CriterionSatisfaction criterionSatisfaction = new CriterionSatisfaction(
- CriterionSatisfactionDAOTest.year(2000), criterion, worker);
- Date end = CriterionSatisfactionDAOTest.year(2006);
+ year(2000), criterion, worker);
+ Date end = year(2006);
criterionSatisfaction.finish(end);
assertTrue(criterionSatisfaction.isFinished());
assertEquals(end, criterionSatisfaction.getEndDate());
@@ -38,7 +44,7 @@ public class CriterionSatisfactionTest {
public void canFinishWhenItStarted() throws Exception {
final Criterion criterion = CriterionDAOTest.createValidCriterion();
Worker worker = new Worker("firstName", "surName", "2333232", 10);
- Date start = CriterionSatisfactionDAOTest.year(2000);
+ Date start = year(2000);
CriterionSatisfaction criterionSatisfaction = new CriterionSatisfaction(
start, criterion, worker);
criterionSatisfaction.finish(start);
@@ -50,29 +56,75 @@ public class CriterionSatisfactionTest {
final Criterion criterion = CriterionDAOTest.createValidCriterion();
Worker worker = new Worker("firstName", "surName", "2333232", 10);
CriterionSatisfaction criterionSatisfaction = new CriterionSatisfaction(
- CriterionSatisfactionDAOTest.year(2000), criterion, worker);
- criterionSatisfaction.finish(CriterionSatisfactionDAOTest.year(1999));
+ year(2000), criterion, worker);
+ criterionSatisfaction.finish(year(1999));
}
@Test
- public void isValidAtDate() {
+ public void testIsEnforcedAtDate() {
final Criterion criterion = CriterionDAOTest.createValidCriterion();
Worker worker = new Worker("firstName", "surName", "2333232", 10);
CriterionSatisfaction criterionSatisfaction = new CriterionSatisfaction(
- CriterionSatisfactionDAOTest.year(2000), criterion, worker);
- assertTrue(criterionSatisfaction
- .isActiveAt(CriterionSatisfactionDAOTest.year(3000)));
- assertTrue(criterionSatisfaction
- .isActiveAt(CriterionSatisfactionDAOTest.year(2000)));
- assertFalse(criterionSatisfaction
- .isActiveAt(CriterionSatisfactionDAOTest.year(1999)));
- criterionSatisfaction.finish(CriterionSatisfactionDAOTest.year(2005));
- assertFalse(criterionSatisfaction
- .isActiveAt(CriterionSatisfactionDAOTest.year(3000)));
- assertTrue(criterionSatisfaction
- .isActiveAt(CriterionSatisfactionDAOTest.year(2000)));
- assertFalse(criterionSatisfaction
- .isActiveAt(CriterionSatisfactionDAOTest.year(1999)));
+ year(2000), criterion, worker);
+ assertTrue(criterionSatisfaction.isEnforcedAt(year(3000)));
+ assertTrue(criterionSatisfaction.isEnforcedAt(year(2000)));
+ assertFalse(criterionSatisfaction.isEnforcedAt(year(1999)));
+ criterionSatisfaction.finish(year(2005));
+ assertFalse(criterionSatisfaction.isEnforcedAt(year(3000)));
+ assertFalse(criterionSatisfaction.isAlwaysEnforcedIn(Interval.range(
+ year(2001), year(2006))));
+ assertTrue(criterionSatisfaction.isEnforcedAt(year(2000)));
+ assertTrue(criterionSatisfaction.isEnforcedAt(year(2001)));
+ assertFalse(criterionSatisfaction.isEnforcedAt(year(1999)));
}
+ @Test
+ public void testEnforcedAtSomePointInInterval() {
+ final Criterion criterion = CriterionDAOTest.createValidCriterion();
+ Worker worker = new Worker("firstName", "surName", "2333232", 10);
+ CriterionSatisfaction criterionSatisfaction = new CriterionSatisfaction(
+ year(2000), criterion, worker);
+ assertTrue(criterionSatisfaction.overlapsWith(Interval.range(
+ year(2001), year(4000))));
+ assertTrue(criterionSatisfaction.overlapsWith(Interval.range(
+ year(2005), year(4000))));
+ assertTrue(criterionSatisfaction.overlapsWith(Interval.range(
+ year(1999), year(2001))));
+
+ criterionSatisfaction.finish(year(2004));
+
+ assertTrue(criterionSatisfaction.overlapsWith(Interval.range(
+ year(2002), year(4000))));
+ assertTrue(criterionSatisfaction.overlapsWith(Interval.range(
+ year(2002), null)));
+ assertFalse(criterionSatisfaction.overlapsWith(Interval.range(
+ year(2005), year(4000))));
+ assertTrue(criterionSatisfaction.overlapsWith(Interval.range(
+ year(1999), null)));
+ assertFalse(criterionSatisfaction.overlapsWith(Interval.range(
+ year(1990), year(1995))));
+ }
+
+ @Test
+ public void testCriterionSatisfactionsStartComparator() {
+ final Criterion criterion = CriterionDAOTest.createValidCriterion();
+ Worker worker = new Worker("firstName", "surName", "2333232", 10);
+ Interval[] intervals = { Interval.from(year(1000)),
+ Interval.range(year(1100), year(9000)),
+ Interval.point(year(1101)), Interval.from(year(1200)),
+ Interval.range(year(3000), year(4000)) };
+ List orderedSatisfactions = new ArrayList();
+ for (Interval interval : intervals) {
+ orderedSatisfactions.add(new CriterionSatisfaction(criterion,
+ worker, interval));
+ }
+ List copy = new ArrayList(
+ orderedSatisfactions);
+ assertThat(copy, equalTo(orderedSatisfactions));
+ for (int i = 0; i < 20; i++) {
+ Collections.shuffle(copy);
+ Collections.sort(copy, CriterionSatisfaction.BY_START_COMPARATOR);
+ assertThat(copy, equalTo(orderedSatisfactions));
+ }
+ }
}
diff --git a/navalplanner-business/src/test/java/org/navalplanner/business/test/resources/entities/IntervalTest.java b/navalplanner-business/src/test/java/org/navalplanner/business/test/resources/entities/IntervalTest.java
new file mode 100644
index 000000000..80c351c56
--- /dev/null
+++ b/navalplanner-business/src/test/java/org/navalplanner/business/test/resources/entities/IntervalTest.java
@@ -0,0 +1,149 @@
+package org.navalplanner.business.test.resources.entities;
+
+import java.util.Date;
+
+import org.junit.Test;
+import org.navalplanner.business.resources.entities.Interval;
+import org.navalplanner.business.test.resources.daos.CriterionSatisfactionDAOTest;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.navalplanner.business.test.resources.daos.CriterionSatisfactionDAOTest.year;
+
+public class IntervalTest {
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testStartDateMustBeBeforeThanEndDate() throws Exception {
+ Interval.range(CriterionSatisfactionDAOTest.year(2000),
+ CriterionSatisfactionDAOTest.year(1999));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testStartDateMustBeNotNull() throws Exception {
+ Interval.range(null, CriterionSatisfactionDAOTest.year(1999));
+ }
+
+ @Test
+ public void intervalCanBeOpenEnded() throws Exception {
+ Interval.range(CriterionSatisfactionDAOTest.year(1990), null);
+ }
+
+ @Test
+ public void testContainsPointInTime() {
+ Interval openEnded = Interval.from(CriterionSatisfactionDAOTest
+ .year(1990));
+ Interval range = Interval.range(
+ CriterionSatisfactionDAOTest.year(1990),
+ CriterionSatisfactionDAOTest.year(2000));
+ Interval startPoint = Interval.point(year(1990));
+ Interval endPoint = Interval.point(year(2000));
+ assertTrue(openEnded.contains(CriterionSatisfactionDAOTest.year(5000)));
+ assertFalse(range.contains(year(5000)));
+ assertTrue(range.contains(year(1990)));
+ assertFalse(range.contains(year(2000)));
+ assertTrue(range.contains(year(1991)));
+ assertFalse(range.contains(year(1989)));
+ assertFalse(range.includes(startPoint));
+ assertFalse(range.includes(endPoint));
+ }
+
+ @Test
+ public void testPointsOnlyContainsThemselves() throws Exception {
+ Interval point = Interval
+ .point(CriterionSatisfactionDAOTest.year(1990));
+ assertTrue(point.contains(CriterionSatisfactionDAOTest.year(1990)));
+ assertFalse(point.contains(CriterionSatisfactionDAOTest.year(2010)));
+ }
+
+ @Test
+ public void testIntervalsAreStartInclusiveAndEndExclusive()
+ throws Exception {
+ Interval range = Interval.range(year(1990), year(2000));
+ assertTrue(range.contains(year(1990)));
+ assertFalse(range.contains(year(2000)));
+ assertFalse(range.contains(new Date(year(1990).getTime() - 1)));
+ assertFalse(range.contains(new Date(year(1990).getTime() - 1)));
+ assertFalse(range.contains(new Date(year(2000).getTime() + 1)));
+ }
+
+ @Test
+ public void testIncludes() throws Exception {
+ Interval bigRange = Interval.range(year(1990), year(2000));
+ Interval included = Interval.range(year(1990), year(1998));
+ Interval point = Interval.point(year(1996));
+ assertTrue(bigRange.includes(included));
+ assertTrue(bigRange.includes(point));
+ assertTrue(included.includes(point));
+ }
+
+ @Test
+ public void testStartPointDoesntOverlapsWithRange() throws Exception {
+ Interval range = Interval.range(year(1990), year(2005));
+ Interval openEndedRange = Interval.from(year(1990));
+ Interval point = Interval.point(year(1990));
+ Interval internalPoint = Interval.point(year(1991));
+
+ assertFalse(point.overlapsWith(range));
+ assertFalse(point.overlapsWith(openEndedRange));
+ assertFalse(range.overlapsWith(point));
+ assertFalse(openEndedRange.overlapsWith(point));
+
+ assertTrue(internalPoint.overlapsWith(range));
+ assertTrue(internalPoint.overlapsWith(openEndedRange));
+ assertTrue(range.overlapsWith(internalPoint));
+ assertTrue(openEndedRange.overlapsWith(internalPoint));
+ }
+
+ @Test
+ public void testOverlapsWith() {
+ Interval firstRange = Interval.range(year(1990), year(2005));
+ Interval igalia = Interval.from(year(2001));
+ Interval distantPoint = Interval.point(year(2030));
+ Interval pointInFirstRange = Interval.point(year(2000));
+ Interval outRange = Interval.range(year(2020), year(2030));
+ assertTrue(firstRange.overlapsWith(igalia));
+ assertTrue(firstRange.overlapsWith(Interval.range(year(1980),
+ year(1991))));
+ assertTrue(igalia.overlapsWith(firstRange));
+ assertTrue(outRange.overlapsWith(igalia));
+ assertFalse(outRange.overlapsWith(firstRange));
+ assertTrue(distantPoint.overlapsWith(igalia));
+ assertFalse(distantPoint.overlapsWith(firstRange));
+ assertTrue(igalia.overlapsWith(distantPoint));
+ assertTrue(distantPoint.overlapsWith(igalia));
+ assertFalse(firstRange.overlapsWith(distantPoint));
+ assertTrue(firstRange.overlapsWith(pointInFirstRange));
+ }
+
+ @Test
+ public void testIntervalFinishingAtTheStartOfOtherDontOverlap()
+ throws Exception {
+ Interval range = Interval.range(year(2000), year(2005));
+ Interval from = Interval.from(year(2000));
+ Interval before = Interval.range(year(1995), year(2000));
+ assertFalse(range.overlapsWith(before));
+ assertFalse(before.overlapsWith(range));
+
+ assertFalse(from.overlapsWith(before));
+ assertFalse(before.overlapsWith(from));
+ }
+
+ @Test
+ public void testStartPointDoesntOverlapsWithRanges() {
+ Interval range = Interval.range(year(2010), year(2030));
+ Interval point = Interval.point(year(2010));
+ Interval otherRange = Interval.from(year(2010));
+ assertFalse(point.overlapsWith(range));
+ assertFalse(range.overlapsWith(point));
+ assertFalse(point.overlapsWith(otherRange));
+ assertFalse(otherRange.overlapsWith(point));
+ }
+
+ @Test
+ public void testCreatingPointWithRange() throws Exception {
+ Interval point = Interval.point(year(1990));
+ Interval range = Interval.range(year(1990), year(1990));
+ assertEquals(point, range);
+ }
+}
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 4351ebac3..d562b126e 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
@@ -1,7 +1,10 @@
package org.navalplanner.business.test.resources.entities;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Date;
import java.util.HashSet;
+import java.util.List;
import org.junit.Test;
import org.navalplanner.business.resources.entities.Criterion;
@@ -10,6 +13,7 @@ import org.navalplanner.business.resources.entities.CriterionTypeBase;
import org.navalplanner.business.resources.entities.CriterionWithItsType;
import org.navalplanner.business.resources.entities.ICriterion;
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.navalplanner.business.test.resources.daos.CriterionDAOTest;
@@ -21,6 +25,7 @@ import static org.junit.Assert.assertFalse;
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;
/**
* Tests for {@link Resource}.
@@ -36,10 +41,10 @@ public class ResourceTest {
CriterionTypeBase otherType = createTypeThatMatches(false, other);
Worker worker = new Worker("firstName", "surName", "2333232", 10);
assertThat(worker.getSatisfactionsFor(criterion).size(), equalTo(0));
- worker.activate(new CriterionWithItsType(type, criterion));
+ worker.addSatisfaction(new CriterionWithItsType(type, criterion));
assertTrue(criterion.isSatisfiedBy(worker));
assertThat(worker.getSatisfactionsFor(criterion).size(), equalTo(1));
- worker.activate(new CriterionWithItsType(otherType, other));
+ worker.addSatisfaction(new CriterionWithItsType(otherType, other));
assertTrue(other.isSatisfiedBy(worker));
assertThat(worker.getSatisfactionsFor(other).size(), equalTo(1));
assertThat(worker.getSatisfactionsFor(criterion).size(), equalTo(1));
@@ -48,17 +53,16 @@ public class ResourceTest {
@Test(expected = IllegalArgumentException.class)
public void getSatisfactionsForWrongIntervalThrowsException() {
Worker worker = new Worker("firstName", "surName", "2333232", 10);
- worker.getActiveSatisfactionsForIn(CriterionDAOTest
- .createValidCriterion(), CriterionSatisfactionDAOTest
- .year(2000), CriterionSatisfactionDAOTest.year(1999));
+ worker.query().from(CriterionDAOTest.createValidCriterion())
+ .enforcedInAll(Interval.range(year(2000), year(1999)))
+ .result();
}
@Test(expected = IllegalArgumentException.class)
public void getSatisfactionsForWrongIntervalForCriterionTypeThrowsException() {
Worker worker = new Worker("firstName", "surName", "2333232", 10);
- worker.getActiveSatisfactionsForIn(createTypeThatMatches(),
- CriterionSatisfactionDAOTest.year(2000),
- CriterionSatisfactionDAOTest.year(1999));
+ worker.query().from(createTypeThatMatches()).enforcedInAll(
+ Interval.range(year(2000), year(1999))).current().result();
}
@Test
@@ -71,14 +75,14 @@ public class ResourceTest {
CriterionWithItsType otherCriterionWithItsType = new CriterionWithItsType(
createTypeThatMatches(otherCriterion), otherCriterion);
Worker worker = new Worker("firstName", "surName", "2333232", 10);
- worker.activate(criterionWithItsType, CriterionSatisfactionDAOTest
- .year(2000));
- worker.activate(otherCriterionWithItsType, CriterionSatisfactionDAOTest
- .year(2000));
- worker.activate(criterionWithItsType, CriterionSatisfactionDAOTest
- .year(4000));
+ worker.addSatisfaction(criterionWithItsType, Interval
+ .from(CriterionSatisfactionDAOTest.year(2000)));
+ worker.addSatisfaction(otherCriterionWithItsType, Interval
+ .from(CriterionSatisfactionDAOTest.year(2000)));
+ worker.addSatisfaction(criterionWithItsType, Interval
+ .from(CriterionSatisfactionDAOTest.year(4000)));
assertEquals(2, worker.getSatisfactionsFor(criterionType).size());
- assertEquals(1, worker.getActiveSatisfactionsFor(criterionType).size());
+ assertEquals(1, worker.getCurrentSatisfactionsFor(criterionType).size());
}
@Test
@@ -92,16 +96,16 @@ public class ResourceTest {
CriterionWithItsType otherCriterionWithItsType = new CriterionWithItsType(
type, otherCriterion);
Worker worker = new Worker("firstName", "surName", "2333232", 10);
- assertThat(worker.getActiveCriterionsFor(type).size(), equalTo(0));
- worker.activate(criterionWithItsType, CriterionSatisfactionDAOTest
- .year(2000));
- assertThat(worker.getActiveCriterionsFor(type).size(), equalTo(1));
- worker.activate(criterionWithItsType, CriterionSatisfactionDAOTest
- .year(2002));
- assertThat(worker.getActiveCriterionsFor(type).size(), equalTo(1));
- worker.activate(otherCriterionWithItsType, CriterionSatisfactionDAOTest
- .year(2000));
- assertThat(worker.getActiveCriterionsFor(type).size(), equalTo(2));
+ assertThat(worker.getCurrentCriterionsFor(type).size(), equalTo(0));
+ worker.addSatisfaction(criterionWithItsType, Interval
+ .from(CriterionSatisfactionDAOTest.year(2000)));
+ assertThat(worker.getCurrentCriterionsFor(type).size(), equalTo(1));
+ worker.addSatisfaction(criterionWithItsType, Interval
+ .from(CriterionSatisfactionDAOTest.year(2002)));
+ assertThat(worker.getCurrentCriterionsFor(type).size(), equalTo(1));
+ worker.addSatisfaction(otherCriterionWithItsType, Interval
+ .from(CriterionSatisfactionDAOTest.year(2000)));
+ assertThat(worker.getCurrentCriterionsFor(type).size(), equalTo(2));
}
public static CriterionTypeBase createTypeThatMatches(
@@ -152,23 +156,23 @@ public class ResourceTest {
createTypeThatMatches(otherCriterion), otherCriterion);
Worker worker = new Worker("firstName", "surName", "2333232", 10);
- worker.activate(criterionWithItsType, CriterionSatisfactionDAOTest
- .year(2000));
- worker.activate(criterionWithItsType, CriterionSatisfactionDAOTest
- .year(2003));
- worker.activate(otherCriterionWithItsType, CriterionSatisfactionDAOTest
- .year(2000));
+ worker.addSatisfaction(criterionWithItsType, Interval
+ .from(CriterionSatisfactionDAOTest.year(2000)));
+ worker.addSatisfaction(criterionWithItsType, Interval
+ .from(CriterionSatisfactionDAOTest.year(2003)));
+ worker.addSatisfaction(otherCriterionWithItsType, Interval
+ .from(CriterionSatisfactionDAOTest.year(2000)));
assertEquals(2, worker.getSatisfactionsFor(criterionType).size());
- assertEquals(1, worker.getActiveSatisfactionsForIn(criterionType,
- CriterionSatisfactionDAOTest.year(2001),
- CriterionSatisfactionDAOTest.year(2005)).size());
- assertEquals(2, worker.getActiveSatisfactionsForIn(criterionType,
- CriterionSatisfactionDAOTest.year(2004),
- CriterionSatisfactionDAOTest.year(2005)).size());
- assertEquals(0, worker.getActiveSatisfactionsForIn(criterionType,
- CriterionSatisfactionDAOTest.year(1999),
- CriterionSatisfactionDAOTest.year(2005)).size());
+ assertEquals(1, 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()
+ .size());
+ assertEquals(0, worker.query().from(criterionType).enforcedInAll(
+ Interval.range(year(1999), year(2005))).current().result()
+ .size());
}
@Test(expected = IllegalArgumentException.class)
@@ -180,114 +184,184 @@ public class ResourceTest {
}
@Test
- public void testActivateAndDeactivateCriterion() {
+ public void testAddAndRemoveSatisfactions() {
Criterion criterion = CriterionDAOTest.createValidCriterion();
Criterion otherCriterion = CriterionDAOTest.createValidCriterion();
Worker worker = new Worker("firstName", "surName", "2333232", 10);
ICriterionType criterionType = createTypeThatMatches(false,
criterion, otherCriterion);
- assertThat(worker.getActiveSatisfactionsFor(criterion).size(),
+ assertThat(worker.getCurrentSatisfactionsFor(criterion).size(),
equalTo(0));
assertFalse(criterion.isSatisfiedBy(worker));
- assertTrue(worker.canBeActivated(new CriterionWithItsType(
- criterionType, criterion)));
- worker.activate(new CriterionWithItsType(criterionType, criterion));
+ Interval fromNow = Interval.from(new Date());
+ assertTrue(worker.canAddSatisfaction(new CriterionWithItsType(
+ criterionType, criterion), fromNow));
+ worker.addSatisfaction(new CriterionWithItsType(criterionType,
+ criterion), fromNow);
assertTrue(criterion.isSatisfiedBy(worker));
- assertThat(worker.getActiveSatisfactionsFor(criterion).size(),
+ assertThat(worker.getCurrentSatisfactionsFor(criterion).size(),
equalTo(1));
- assertFalse(worker.canBeActivated(new CriterionWithItsType(
- criterionType, otherCriterion)));
+ assertFalse(worker.canAddSatisfaction(new CriterionWithItsType(
+ criterionType, otherCriterion), fromNow));
try {
- worker.activate(new CriterionWithItsType(criterionType,
+ worker.addSatisfaction(new CriterionWithItsType(criterionType,
otherCriterion));
fail("must send exception since it already is activated for a criterion of the same type and the type doesn't allow repeated criterions per resource");
} catch (IllegalStateException e) {
// ok
}
- assertTrue(worker.canBeActivated(new CriterionWithItsType(
- criterionType, criterion)));
- assertThat(worker.getActiveSatisfactionsFor(criterion).size(),
- equalTo(1));
- worker.deactivate(new CriterionWithItsType(criterionType, criterion));
- assertTrue("the satisfactions are deactivated", worker
- .getActiveSatisfactionsFor(criterion).isEmpty());
+ assertThat(worker.query().from(criterionType).enforcedInAll(fromNow)
+ .result().size(), equalTo(1));
+ List finished = worker.finishEnforcedAt(
+ new CriterionWithItsType(criterionType, criterion), fromNow
+ .getStart());
+ assertThat(finished.size(), equalTo(1));
+ assertTrue("all satisfactions are finished", worker.query().from(
+ criterionType).enforcedInAll(fromNow).result().isEmpty());
+ assertTrue(worker.canAddSatisfaction(new CriterionWithItsType(
+ criterionType, criterion), fromNow));
}
@Test
- public void testActivateInDate() throws Exception {
+ public void testAddAtDate() throws Exception {
Criterion criterion = CriterionDAOTest.createValidCriterion();
Criterion otherCriterion = CriterionDAOTest.createValidCriterion();
Worker worker = new Worker("firstName", "surName", "2333232", 10);
ICriterionType criterionType = createTypeThatMatches(false,
criterion, otherCriterion);
- worker.activate(new CriterionWithItsType(criterionType, criterion),
- CriterionSatisfactionDAOTest.year(4000));
- worker.activate(new CriterionWithItsType(criterionType, criterion),
- CriterionSatisfactionDAOTest.year(5000),
- CriterionSatisfactionDAOTest.year(6000));
+ worker.addSatisfaction(new CriterionWithItsType(criterionType,
+ criterion), Interval.range(year(5000), year(6000)));
+ worker.addSatisfaction(new CriterionWithItsType(criterionType,
+ criterion), Interval.from(year(4000)));
- assertThat(worker.getActiveSatisfactionsForIn(criterion,
- CriterionSatisfactionDAOTest.year(4001),
- CriterionSatisfactionDAOTest.year(4999)).size(), equalTo(1));
- assertThat(worker.getActiveSatisfactionsForIn(criterion,
- CriterionSatisfactionDAOTest.year(5001),
- CriterionSatisfactionDAOTest.year(5500)).size(), equalTo(1));
+ assertThat(worker.query().from(criterion).enforcedInAll(
+ Interval.range(year(4001), year(4999))).result().size(),
+ equalTo(1));
+ assertThat(worker.query().from(criterion).enforcedInAll(
+ Interval.range(year(4001), year(5000))).result().size(),
+ equalTo(0));
+ assertThat(worker.query().from(criterion).enforcedInAll(
+ Interval.range(year(5000), year(5001))).result().size(),
+ equalTo(1));
+ assertThat(worker.query().from(criterion).enforcedInAll(
+ Interval.range(year(5001), year(5500))).result().size(),
+ equalTo(1));
- worker.deactivate(new CriterionWithItsType(criterionType, criterion));
+ worker.finish(new CriterionWithItsType(criterionType, criterion));
- assertThat(worker.getActiveSatisfactionsForIn(criterion,
- CriterionSatisfactionDAOTest.year(4001),
- CriterionSatisfactionDAOTest.year(4999)).size(), equalTo(1));
- assertThat(worker.getActiveSatisfactionsForIn(criterion,
- CriterionSatisfactionDAOTest.year(5001),
- CriterionSatisfactionDAOTest.year(5500)).size(), equalTo(1));
+ assertThat(worker.query().from(criterion).enforcedInAll(
+ Interval.range(year(4001), year(4999))).result().size(),
+ equalTo(1));
+ assertThat(worker.query().from(criterion).enforcedInAll(
+ Interval.range(year(5001), year(5500))).result().size(),
+ equalTo(1));
- assertFalse(worker.canBeActivated(new CriterionWithItsType(
- criterionType, otherCriterion), CriterionSatisfactionDAOTest
- .year(4001)));
+ assertFalse(worker.canAddSatisfaction(new CriterionWithItsType(
+ criterionType, otherCriterion), Interval
+ .from(CriterionSatisfactionDAOTest.year(4001))));
}
@Test
// when type doesnt allow multiple active criterions per resource
- public void activateOnlyUntilNextCriterionIsActive() {
+ public void addOnlyUntilNextCriterionIsActive() {
Criterion criterion = CriterionDAOTest.createValidCriterion();
Criterion otherCriterion = CriterionDAOTest.createValidCriterion();
Worker worker = new Worker("firstName", "surName", "2333232", 10);
ICriterionType criterionType = createTypeThatMatches(false,
criterion, otherCriterion);
- worker.activate(new CriterionWithItsType(criterionType, criterion),
- CriterionSatisfactionDAOTest.year(4000));
- worker.activate(
- new CriterionWithItsType(criterionType, otherCriterion),
- CriterionSatisfactionDAOTest.year(3500));
+ worker.addSatisfaction(new CriterionWithItsType(criterionType,
+ criterion), Interval.from(year(4000)));
+ worker.addSatisfaction(new CriterionWithItsType(criterionType,
+ otherCriterion), Interval.from(year(3500)));
assertThat(worker.getSatisfactionsFor(otherCriterion).size(),
equalTo(1));
CriterionSatisfaction satisfaction = worker.getSatisfactionsFor(
otherCriterion).iterator().next();
- assertThat(satisfaction.getEndDate(),
- equalTo(CriterionSatisfactionDAOTest.year(4000)));
+ assertThat(satisfaction.getEndDate(), equalTo(year(4000)));
}
@Test(expected = IllegalStateException.class)
// when type doesnt allow multiple active criterions per resource
- public void deactivatePrevious() {
+ public void testCantAddOverlappingTotally() {
Criterion criterion = CriterionDAOTest.createValidCriterion();
Criterion otherCriterion = CriterionDAOTest.createValidCriterion();
Worker worker = new Worker("firstName", "surName", "2333232", 10);
ICriterionType criterionType = createTypeThatMatches(false,
criterion, otherCriterion);
- worker.activate(
- new CriterionWithItsType(criterionType, otherCriterion),
- CriterionSatisfactionDAOTest.year(3500));
- assertFalse(worker.canBeActivated(new CriterionWithItsType(
- criterionType, criterion), CriterionSatisfactionDAOTest
- .year(4000)));
- worker.activate(new CriterionWithItsType(criterionType, criterion),
- CriterionSatisfactionDAOTest.year(4000));
+ worker.addSatisfaction(new CriterionWithItsType(criterionType,
+ otherCriterion), Interval.from(year(3500)));
+ assertFalse(worker.canAddSatisfaction(new CriterionWithItsType(
+ criterionType, criterion), Interval.range(year(4000),
+ year(5000))));
+ worker.addSatisfaction(new CriterionWithItsType(criterionType,
+ criterion), Interval.range(year(4000), year(5000)));
}
@Test(expected = IllegalStateException.class)
- public void shouldntActivate() {
+ public void testCantAddIfOverlapsPartially() {
+ Criterion criterion = CriterionDAOTest.createValidCriterion();
+ Criterion otherCriterion = CriterionDAOTest.createValidCriterion();
+ Worker worker = new Worker("firstName", "surName", "2333232", 10);
+ ICriterionType criterionType = createTypeThatMatches(false,
+ criterion, otherCriterion);
+ worker.addSatisfaction(new CriterionWithItsType(criterionType,
+ otherCriterion), Interval.range(year(3500), year(4500)));
+ assertFalse(worker.canAddSatisfaction(new CriterionWithItsType(
+ criterionType, criterion), Interval.range(year(3600),
+ year(3800))));
+ worker.addSatisfaction(new CriterionWithItsType(criterionType,
+ criterion), Interval.range(year(3600), year(3800)));
+ }
+
+ @Test
+ public void testCantAddWrongCriterionSatisfaction() {
+ Criterion criterion = CriterionDAOTest.createValidCriterion();
+ Criterion otherCriterion = CriterionDAOTest.createValidCriterion();
+ Worker worker = new Worker("firstName", "surName", "2333232", 10);
+ Worker other = new Worker("other", "surName", "2333232", 10);
+ ICriterionType criterionType = createTypeThatMatches(false,
+ criterion);
+ List wrongSatisfactions = new ArrayList();
+ CriterionSatisfaction satisfaction = createValid(criterion, worker);
+ satisfaction.setResource(other);
+ wrongSatisfactions.add(satisfaction);
+ satisfaction = createValid(criterion, worker);
+ satisfaction.setResource(null);
+ wrongSatisfactions.add(satisfaction);
+ satisfaction = createValid(criterion, worker);
+ satisfaction.setCriterion(otherCriterion);
+ wrongSatisfactions.add(satisfaction);
+ for (CriterionSatisfaction wrong : wrongSatisfactions) {
+ try {
+ worker.addSatisfaction(criterionType, wrong);
+ fail("must send exception");
+ } catch (IllegalArgumentException e) {
+ // ok
+ }
+ }
+ }
+
+ public void testAddCriterionSatisfaction() throws Exception {
+ Criterion criterion = CriterionDAOTest.createValidCriterion();
+ Worker worker = new Worker("firstName", "surName", "2333232", 10);
+ ICriterionType criterionType = createTypeThatMatches(false,
+ criterion);
+ CriterionSatisfaction satisfaction = createValid(criterion, worker);
+ worker.addSatisfaction(criterionType, satisfaction);
+ assertThat(worker.getAllSatisfactions().size(), equalTo(1));
+ }
+
+ private CriterionSatisfaction createValid(Criterion criterion, Worker worker) {
+ CriterionSatisfaction satisfaction = new CriterionSatisfaction();
+ satisfaction.setResource(worker);
+ satisfaction.setStartDate(year(2000));
+ satisfaction.setCriterion(criterion);
+ satisfaction.setEndDate(year(2004));
+ return satisfaction;
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void shouldntAdd() {
Criterion criterion = CriterionDAOTest.createValidCriterion();
Worker worker = new Worker("firstName", "surName", "2333232", 10);
ICriterionType> type = new CriterionTypeBase("prueba", false, false,
@@ -316,8 +390,9 @@ public class ResourceTest {
};
CriterionWithItsType criterionWithItsType = new CriterionWithItsType(
type, criterion);
- assertFalse(worker.canBeActivated(criterionWithItsType));
- worker.activate(criterionWithItsType);
+ assertFalse(worker.canAddSatisfaction(criterionWithItsType, Interval
+ .from(new Date())));
+ worker.addSatisfaction(criterionWithItsType);
}
}
diff --git a/navalplanner-business/src/test/java/org/navalplanner/business/test/resources/services/CriterionServiceTest.java b/navalplanner-business/src/test/java/org/navalplanner/business/test/resources/services/CriterionServiceTest.java
index bee04a9b6..dc2f18222 100644
--- a/navalplanner-business/src/test/java/org/navalplanner/business/test/resources/services/CriterionServiceTest.java
+++ b/navalplanner-business/src/test/java/org/navalplanner/business/test/resources/services/CriterionServiceTest.java
@@ -15,6 +15,7 @@ import org.navalplanner.business.resources.entities.CriterionWithItsType;
import org.navalplanner.business.resources.entities.ICriterion;
import org.navalplanner.business.resources.entities.ICriterionOnData;
import org.navalplanner.business.resources.entities.ICriterionType;
+import org.navalplanner.business.resources.entities.Interval;
import org.navalplanner.business.resources.entities.PredefinedCriterionTypes;
import org.navalplanner.business.resources.entities.Resource;
import org.navalplanner.business.resources.entities.Worker;
@@ -126,7 +127,7 @@ public class CriterionServiceTest {
Criterion criterion = CriterionDAOTest.createValidCriterion();
ICriterionType> type = createTypeThatMatches(criterion);
Worker worker = new Worker("firstName", "surName", "2333232", 10);
- worker.activate(new CriterionWithItsType(type, criterion));
+ worker.addSatisfaction(new CriterionWithItsType(type, criterion));
assertTrue(criterion.isSatisfiedBy(worker));
resourceService.saveResource(worker);
assertTrue(criterion.isSatisfiedBy(worker));
@@ -141,7 +142,7 @@ public class CriterionServiceTest {
criterionService.save(criterion);
ICriterionType> type = createTypeThatMatches(criterion);
Worker worker = new Worker("firstName", "surName", "2333232", 10);
- worker.activate(new CriterionWithItsType(type, criterion));
+ worker.addSatisfaction(new CriterionWithItsType(type, criterion));
assertTrue(criterion.isSatisfiedBy(worker));
resourceService.saveResource(worker);
assertTrue(criterion.isSatisfiedBy(worker));
@@ -155,7 +156,7 @@ public class CriterionServiceTest {
ICriterionType> type = createTypeThatMatches(criterion);
criterionService.save(criterion);
Worker worker = new Worker("firstName", "surName", "2333232", 10);
- worker.activate(new CriterionWithItsType(type, criterion));
+ worker.addSatisfaction(new CriterionWithItsType(type, criterion));
resourceService.saveResource(worker);
assertThat(criterionService.getResourcesSatisfying(criterion).size(),
equalTo(1));
@@ -170,7 +171,7 @@ public class CriterionServiceTest {
ICriterionType> type = createTypeThatMatches(criterion);
Worker worker = new Worker("firstName", "surName", "2333232", 10);
resourceService.saveResource(worker);
- worker.activate(new CriterionWithItsType(type, criterion));
+ worker.addSatisfaction(new CriterionWithItsType(type, criterion));
assertEquals(1, criterionService.getResourcesSatisfying(criterion)
.size());
}
@@ -191,7 +192,7 @@ public class CriterionServiceTest {
ICriterionType type = createTypeThatMatches(criterion);
Worker worker = new Worker("firstName", "surName", "2333232", 10);
resourceService.saveResource(worker);
- worker.activate(new CriterionWithItsType(type, criterion));
+ worker.addSatisfaction(new CriterionWithItsType(type, criterion));
assertThat(criterionService.getResourcesSatisfying(Resource.class,
criterion).size(), is(1));
@@ -208,8 +209,7 @@ public class CriterionServiceTest {
criterionService.save(criterion);
Worker worker = new Worker("firstName", "surName", "2333232", 10);
resourceService.saveResource(worker);
- worker.activate(new CriterionWithItsType(type, criterion),
- CriterionSatisfactionDAOTest.year(2000));
+ worker.addSatisfaction(new CriterionWithItsType(type, criterion), Interval.from(CriterionSatisfactionDAOTest.year(2000)));
ICriterionOnData criterionOnData = criterionService.empower(criterion);
assertTrue(criterionOnData.isSatisfiedBy(worker));
assertEquals(1, criterionOnData.getResourcesSatisfying().size());
@@ -232,7 +232,7 @@ public class CriterionServiceTest {
Criterion criterion = CriterionDAOTest.createValidCriterion();
criterionService.save(criterion);
ICriterionType> type = createTypeThatMatches(criterion);
- worker1.activate(new CriterionWithItsType(type, criterion));
+ worker1.addSatisfaction(new CriterionWithItsType(type, criterion));
resourceService.saveResource(worker1);
Resource workerReloaded = criterionService
.onTransaction(new OnTransaction() {
@@ -266,8 +266,7 @@ public class CriterionServiceTest {
criterionService.save(criterion);
Worker worker = new Worker("firstName", "surName", "2333232", 10);
resourceService.saveResource(worker);
- worker.activate(new CriterionWithItsType(type, criterion),
- CriterionSatisfactionDAOTest.year(2000));
+ worker.addSatisfaction(new CriterionWithItsType(type, criterion), Interval.from(CriterionSatisfactionDAOTest.year(2000)));
ICriterionOnData criterionOnData = criterionService.empower(criterion);
criterionOnData.getResourcesSatisfying();
criterionOnData.getResourcesSatisfying(CriterionSatisfactionDAOTest
@@ -292,8 +291,8 @@ public class CriterionServiceTest {
type, criterion);
Worker worker = new Worker("firstName", "surName", "2333232", 10);
resourceService.saveResource(worker);
- worker.activate(criterionWithItsType, CriterionSatisfactionDAOTest
- .year(2000));
+ worker.addSatisfaction(criterionWithItsType, Interval.from(CriterionSatisfactionDAOTest
+ .year(2000)));
assertEquals(1, criterionService.getResourcesSatisfying(criterion,
CriterionSatisfactionDAOTest.year(2001),
@@ -302,8 +301,7 @@ public class CriterionServiceTest {
CriterionSatisfactionDAOTest.year(1999),
CriterionSatisfactionDAOTest.year(2005)).size());
- worker.activate(new CriterionWithItsType(type, criterion),
- CriterionSatisfactionDAOTest.year(1998));
+ worker.addSatisfaction(new CriterionWithItsType(type, criterion), Interval.from(CriterionSatisfactionDAOTest.year(1998)));
assertEquals(1, criterionService.getResourcesSatisfying(criterion,
CriterionSatisfactionDAOTest.year(1999),
@@ -319,10 +317,10 @@ public class CriterionServiceTest {
criterionService.save(criterion);
Worker worker = new Worker("firstName", "surName", "2333232", 10);
resourceService.saveResource(worker);
- worker.activate(criterionWithItsType, CriterionSatisfactionDAOTest
- .year(2000));
- worker.activate(criterionWithItsType, CriterionSatisfactionDAOTest
- .year(1998));
+ worker.addSatisfaction(criterionWithItsType, Interval.from(CriterionSatisfactionDAOTest
+ .year(2000)));
+ worker.addSatisfaction(criterionWithItsType, Interval.from(CriterionSatisfactionDAOTest
+ .year(1998)));
ICriterionType> criterionType = ResourceTest
.createTypeThatMatches(criterion);
@@ -337,8 +335,8 @@ public class CriterionServiceTest {
CriterionSatisfactionDAOTest.year(1997),
CriterionSatisfactionDAOTest.year(2005)).size());
- worker.activate(criterionWithItsType, CriterionSatisfactionDAOTest
- .year(1997));
+ worker.addSatisfaction(criterionWithItsType, Interval.from(CriterionSatisfactionDAOTest
+ .year(1997)));
assertEquals(2, criterionService.getSatisfactionsFor(criterionType,
CriterionSatisfactionDAOTest.year(1999),
CriterionSatisfactionDAOTest.year(2005)).size());
@@ -363,18 +361,18 @@ public class CriterionServiceTest {
}
public static ICriterionType createTypeThatMatches(
- final boolean allowMultipleActiveCriterionsPerResource,
+ final boolean allowSimultaneousCriterionsPerResource,
final Criterion criterion) {
return new ICriterionType() {
@Override
- public boolean allowHierarchy() {
- return false;
+ public boolean allowSimultaneousCriterionsPerResource() {
+ return allowSimultaneousCriterionsPerResource;
}
@Override
- public boolean allowMultipleActiveCriterionsPerResource() {
- return allowMultipleActiveCriterionsPerResource;
+ public boolean allowHierarchy() {
+ return false;
}
@Override
diff --git a/navalplanner-business/src/test/java/org/navalplanner/business/test/resources/services/ResourceServiceTest.java b/navalplanner-business/src/test/java/org/navalplanner/business/test/resources/services/ResourceServiceTest.java
index 1e9e387b1..d221968b3 100644
--- a/navalplanner-business/src/test/java/org/navalplanner/business/test/resources/services/ResourceServiceTest.java
+++ b/navalplanner-business/src/test/java/org/navalplanner/business/test/resources/services/ResourceServiceTest.java
@@ -138,7 +138,7 @@ public class ResourceServiceTest {
criterionService.save(criterion);
ICriterionType type = CriterionServiceTest
.createTypeThatMatches(criterion);
- worker1.activate(new CriterionWithItsType(type, criterion));
+ worker1.addSatisfaction(new CriterionWithItsType(type, criterion));
resourceService.saveResource(worker1);
assertThat(worker1.getVersion(), not(equalTo(versionValueAfterSave)));
}
diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/criterion/CriterionsModel.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/criterion/CriterionsModel.java
index dc755b2c6..43fab7e9b 100644
--- a/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/criterion/CriterionsModel.java
+++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/criterion/CriterionsModel.java
@@ -126,7 +126,7 @@ public class CriterionsModel implements ICriterionsModel {
@Override
public boolean isChangeAssignmentsDisabled() {
return criterionType == null
- || !criterionType.allowMultipleActiveCriterionsPerResource();
+ || !criterionType.allowSimultaneousCriterionsPerResource();
}
@Override
@@ -135,7 +135,7 @@ public class CriterionsModel implements ICriterionsModel {
for (Resource resource : resources) {
Resource reloaded = find(resource.getId());
reloaded
- .activate(new CriterionWithItsType(criterionType, criterion));
+ .addSatisfaction(new CriterionWithItsType(criterionType, criterion));
resourceService.saveResource(reloaded);
}
}
@@ -145,7 +145,7 @@ public class CriterionsModel implements ICriterionsModel {
public void deactivateAll(Collection extends Resource> resources) {
for (Resource resource : resources) {
Resource reloaded = find(resource.getId());
- reloaded.deactivate(new CriterionWithItsType(criterionType,
+ reloaded.finish(new CriterionWithItsType(criterionType,
criterion));
resourceService.saveResource(reloaded);
}
diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/worker/WorkRelationshipsController.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/worker/WorkRelationshipsController.java
index a1b7f8f40..94bf88f2e 100644
--- a/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/worker/WorkRelationshipsController.java
+++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/resources/worker/WorkRelationshipsController.java
@@ -1,26 +1,22 @@
package org.navalplanner.web.resources.worker;
-import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
-import java.util.logging.Level;
-import java.util.logging.Logger;
import org.navalplanner.business.common.exceptions.InstanceNotFoundException;
import org.navalplanner.business.resources.entities.Criterion;
import org.navalplanner.business.resources.entities.CriterionSatisfaction;
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.Worker;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.util.GenericForwardComposer;
-import org.zkoss.zul.Datebox;
import org.zkoss.zul.Listbox;
/**
@@ -33,7 +29,10 @@ public class WorkRelationshipsController extends GenericForwardComposer {
private WorkerCRUDController workerCRUDController;
-/* private CriterionSatisfaction newRelationship = new CriterionSatisfaction(); */
+ /*
+ * private CriterionSatisfaction newRelationship = new
+ * CriterionSatisfaction();
+ */
private CriterionSatisfaction editRelationship = new CriterionSatisfaction();
@@ -41,21 +40,26 @@ public class WorkRelationshipsController extends GenericForwardComposer {
private Listbox selectedWorkCriterion;
-/* private Datebox newWorkRelationshipStartDate;
-
- private Datebox newWorkRelationshipEndDate; */
+ /*
+ * private Datebox newWorkRelationshipStartDate;
+ *
+ * private Datebox newWorkRelationshipEndDate;
+ */
private HashMap fromCriterionToType;
+ private boolean editing;
+
public WorkRelationshipsController(IWorkerModel workerModel,
WorkerCRUDController workerCRUDController) {
this.workerModel = workerModel;
this.workerCRUDController = workerCRUDController;
this.workCriterions = new ArrayList();
- Map, Collection> map =
- workerModel.getLaboralRelatedCriterions();
+ Map, Collection> map = workerModel
+ .getLaboralRelatedCriterions();
this.fromCriterionToType = new HashMap();
- for (Entry, Collection> entry : map.entrySet()) {
+ for (Entry, Collection> entry : map
+ .entrySet()) {
this.workCriterions.addAll(entry.getValue());
for (Criterion criterion : entry.getValue()) {
this.fromCriterionToType.put(criterion,
@@ -68,66 +72,53 @@ public class WorkRelationshipsController extends GenericForwardComposer {
if (this.workerCRUDController.getWorker() == null) {
return new HashSet();
} else {
- return workerModel.getLaboralRelatedCriterionSatisfactions(
- this.workerCRUDController.getWorker());
+ return workerModel
+ .getLaboralRelatedCriterionSatisfactions(this.workerCRUDController
+ .getWorker());
}
}
public void deleteCriterionSatisfaction(CriterionSatisfaction satisfaction)
throws InstanceNotFoundException {
- workerCRUDController.getWorker().removeCriterionSatisfaction(satisfaction);
+ workerCRUDController.getWorker().removeCriterionSatisfaction(
+ satisfaction);
this.workerCRUDController.goToEditForm();
}
- public void setEditCriterionSatisfaction(CriterionSatisfaction crit) {
- // the component should be preselected.
- this.editRelationship = crit;
+ public void prepareForCreate() {
+ this.editRelationship = new CriterionSatisfaction();
+ editing = false;
+ }
+
+ public void prepareForEdit(CriterionSatisfaction criterionSatisfaction) {
+ this.editRelationship = criterionSatisfaction;
+ editing = true;
}
public void saveCriterionSatisfaction() throws InstanceNotFoundException {
// Add new criterion
- Criterion selectedCriterion = (Criterion) selectedWorkCriterion.getSelectedItem().getValue();
- CriterionWithItsType criterionWithItsType = fromCriterionToType.get(selectedCriterion);
- System.out.println( "SAVE!!: " + selectedCriterion.getName() );
-
- if (editRelationship.getStartDate() == null) {
- this.workerCRUDController.getWorker().activate(
- criterionWithItsType,
- editRelationship.getStartDate());
- } else {
- this.workerCRUDController.getWorker().activate(
- criterionWithItsType,
- editRelationship.getStartDate(),
- editRelationship.getEndDate());
+ Criterion selectedCriterion = (Criterion) selectedWorkCriterion
+ .getSelectedItem().getValue();
+ CriterionWithItsType criterionWithItsType = fromCriterionToType
+ .get(selectedCriterion);
+ System.out.println("SAVE!!: " + selectedCriterion.getName());
+ if (this.workerCRUDController.getWorker().contains(editRelationship)) {
+ this.workerCRUDController.getWorker().removeCriterionSatisfaction(
+ editRelationship);
}
+ this.workerCRUDController.getWorker().addSatisfaction(
+ criterionWithItsType,
+ Interval.range(editRelationship.getStartDate(),
+ editRelationship.getEndDate()));
// Delete the former one
- workerCRUDController.getWorker().
- removeCriterionSatisfaction(this.editRelationship);
+ workerCRUDController.getWorker().removeCriterionSatisfaction(
+ this.editRelationship);
this.workerCRUDController.goToEditForm();
}
- public void addCriterionSatisfaction() {
- Criterion selectedCriterion = (Criterion) selectedWorkCriterion.getSelectedItem().getValue();
- CriterionWithItsType criterionWithItsType = fromCriterionToType.get(selectedCriterion);
- // never accessed: Unnecesary as edition does this.
- System.out.println( "SELECTED: " + criterionWithItsType.toString() );
-
- if (editRelationship.getStartDate() == null) {
- this.workerCRUDController.getWorker().activate(
- criterionWithItsType,
- editRelationship.getStartDate());
- } else {
- this.workerCRUDController.getWorker().activate(
- criterionWithItsType,
- editRelationship.getStartDate(),
- editRelationship.getEndDate());
- }
- this.workerCRUDController.goToEditForm();
- }
-
@Override
public void doAfterCompose(Component comp) throws Exception {
super.doAfterCompose(comp);
@@ -142,4 +133,8 @@ public class WorkRelationshipsController extends GenericForwardComposer {
return this.workCriterions;
}
+ public boolean isEditing() {
+ return editing;
+ }
+
}
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 bc230877a..cafd97c5c 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
@@ -1,17 +1,11 @@
package org.navalplanner.web.resources.worker;
-import java.util.Date;
import java.util.List;
import org.hibernate.validator.InvalidValue;
import org.navalplanner.business.common.exceptions.ValidationException;
-import org.navalplanner.business.resources.entities.Criterion;
import org.navalplanner.business.resources.entities.CriterionSatisfaction;
-import org.navalplanner.business.resources.entities.CriterionTypeBase;
-import org.navalplanner.business.resources.entities.CriterionWithItsType;
-import org.navalplanner.business.resources.entities.PredefinedCriterionTypes;
import org.navalplanner.business.resources.entities.Worker;
-import org.navalplanner.business.resources.entities.WorkingRelationship;
import org.navalplanner.business.resources.services.CriterionService;
import org.navalplanner.web.common.IMessagesForUser;
import org.navalplanner.web.common.Level;
@@ -53,7 +47,7 @@ public class WorkerCRUDController extends GenericForwardComposer implements
private Component messagesContainer;
- private WorkRelationshipsController workRelationship;
+ private WorkRelationshipsController addWorkRelationship;
private LocalizationsController localizationsForEditionController;
@@ -61,13 +55,16 @@ public class WorkerCRUDController extends GenericForwardComposer implements
private CriterionService criterionService;
+ private WorkRelationshipsController editWorkRelationship;
+
public WorkerCRUDController() {
}
public WorkerCRUDController(Window createWindow, Window listWindow,
Window editWindow, Window workRelationshipsWindow,
- Window addWorkRelationshipWindow, Window editWorkRelationshipWindow,
- IWorkerModel workerModel, IMessagesForUser messages) {
+ Window addWorkRelationshipWindow,
+ Window editWorkRelationshipWindow, IWorkerModel workerModel,
+ IMessagesForUser messages) {
this.createWindow = createWindow;
this.listWindow = listWindow;
this.editWindow = editWindow;
@@ -131,24 +128,9 @@ public class WorkerCRUDController extends GenericForwardComposer implements
}
public void goToAddWorkRelationshipForm() {
- Criterion selectedCriterion = criterionService.load(
- WorkingRelationship.HIRED.criterion());
- CriterionWithItsType criteriontype = new CriterionWithItsType(
- PredefinedCriterionTypes.WORK_RELATIONSHIP, selectedCriterion);
- this.workerModel.getWorker().activate(criteriontype,new Date());
- /* CriterionSatisfaction newSatisfaction =
- new CriterionSatisfaction(
- new Date(),
- selectedCriterion,
- this.workerModel.getWorker()); */
- CriterionSatisfaction newSatisfaction =
- this.workerModel.getWorker().
- getActiveSatisfactionsFor(selectedCriterion).iterator().next();
- this.workRelationship.setEditCriterionSatisfaction(newSatisfaction);
+ this.addWorkRelationship.prepareForCreate();
getVisibility().showOnly(addWorkRelationshipWindow);
Util.reloadBindings(addWorkRelationshipWindow);
-// getVisibility().showOnly(editWorkRelationshipWindow);
-// Util.reloadBindings(editWorkRelationshipWindow);
}
public void goToCreateForm() {
@@ -158,7 +140,7 @@ public class WorkerCRUDController extends GenericForwardComposer implements
}
public void goToEditWorkRelationshipForm(CriterionSatisfaction satisfaction) {
- this.workRelationship.setEditCriterionSatisfaction(satisfaction);
+ this.editWorkRelationship.prepareForEdit(satisfaction);
getVisibility().showOnly(editWorkRelationshipWindow);
Util.reloadBindings(editWorkRelationshipWindow);
}
@@ -175,15 +157,27 @@ public class WorkerCRUDController extends GenericForwardComposer implements
if (messagesContainer == null)
throw new RuntimeException("messagesContainer is needed");
messages = new MessagesForUser(messagesContainer);
- this.workRelationship =
- new WorkRelationshipsController(this.workerModel,this);
- this.workRelationship.doAfterCompose(
- comp.getFellow("addWorkRelationshipWindow"));
- URLHandler handler = URLHandlerRegistry
+ this.addWorkRelationship = new WorkRelationshipsController(
+ this.workerModel, this);
+ setupWorkRelationshipController(this.addWorkRelationship,
+ this.addWorkRelationshipWindow);
+ setupWorkRelationshipController(
+ this.editWorkRelationship = new WorkRelationshipsController(
+ this.workerModel, this), editWorkRelationshipWindow);
+
+ URLHandler handler = URLHandlerRegistry
.getRedirectorFor(IWorkerCRUDControllerEntryPoints.class);
handler.applyIfMatches(this);
}
+ private void setupWorkRelationshipController(
+ WorkRelationshipsController workRelationshipController,
+ Window workRelationshipWindow) throws Exception {
+ workRelationshipController.doAfterCompose(workRelationshipWindow);
+ workRelationshipWindow.setVariable("workRelationship",
+ workRelationshipController, true);
+ }
+
private LocalizationsController createLocalizationsController(
Component comp, String localizationsContainerName) throws Exception {
LocalizationsController localizationsController = new LocalizationsController(
@@ -198,13 +192,13 @@ public class WorkerCRUDController extends GenericForwardComposer implements
if (visibility == null) {
visibility = new OnlyOneVisible(listWindow, editWindow,
createWindow, workRelationshipsWindow,
- addWorkRelationshipWindow, editWorkRelationshipWindow );
+ addWorkRelationshipWindow, editWorkRelationshipWindow);
}
return visibility;
}
public GenericForwardComposer getWorkRelationship() {
- return this.workRelationship;
+ return this.addWorkRelationship;
}
}
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 01dce1624..15b2565a3 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
@@ -19,6 +19,7 @@ import org.navalplanner.business.resources.entities.Criterion;
import org.navalplanner.business.resources.entities.CriterionSatisfaction;
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.PredefinedCriterionTypes;
import org.navalplanner.business.resources.entities.Resource;
import org.navalplanner.business.resources.entities.Worker;
@@ -165,7 +166,7 @@ public class WorkerModel implements IWorkerModel {
ICriterionType> type) {
Validate
.isTrue(
- type.allowMultipleActiveCriterionsPerResource(),
+ type.allowSimultaneousCriterionsPerResource(),
"must allow multiple active criterions for this type to use this assignment strategy");
this.criterionService = criterionService;
this.resource = resource;
@@ -197,13 +198,13 @@ public class WorkerModel implements IWorkerModel {
private HashSet calculateInitialActive() {
return new HashSet(resource
- .getActiveSatisfactionsFor(type));
+ .getCurrentSatisfactionsFor(type));
}
private List calculateInitialCriterionsNotAssigned() {
Map allCriterions = byId(criterionService
.getCriterionsFor(type));
- for (Long activeId : asIds(resource.getActiveCriterionsFor(type))) {
+ for (Long activeId : asIds(resource.getCurrentCriterionsFor(type))) {
allCriterions.remove(activeId);
}
return new ArrayList(allCriterions.values());
@@ -250,12 +251,11 @@ public class WorkerModel implements IWorkerModel {
@Override
public void applyChanges() {
for (CriterionSatisfaction criterionSatisfaction : added) {
- resource.activate(new CriterionWithItsType(type,
- criterionSatisfaction.getCriterion()),
- criterionSatisfaction.getStartDate());
+ resource.addSatisfaction(new CriterionWithItsType(type,
+ criterionSatisfaction.getCriterion()), Interval.from(criterionSatisfaction.getStartDate()));
}
for (Criterion criterion : unassigned.keySet()) {
- resource.deactivate(new CriterionWithItsType(type, criterion));
+ resource.finish(new CriterionWithItsType(type, criterion));
}
}
}
diff --git a/navalplanner-webapp/src/main/webapp/resources/worker/_editWorkRelationship.zul b/navalplanner-webapp/src/main/webapp/resources/worker/_editWorkRelationship.zul
index 71bfa62d4..276405568 100644
--- a/navalplanner-webapp/src/main/webapp/resources/worker/_editWorkRelationship.zul
+++ b/navalplanner-webapp/src/main/webapp/resources/worker/_editWorkRelationship.zul
@@ -1,5 +1,4 @@
-
+
@@ -9,11 +8,11 @@
+ value="@{workRelationship.editRelationship.startDate}" />
+ value="@{workRelationship.editRelationship.endDate}" />
+ model="@{workRelationship.workCriterions}" disabled="@{! workRelationship.editing}">
@@ -21,7 +20,7 @@
-