diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/resources/daos/ICriterionDAO.java b/navalplanner-business/src/main/java/org/navalplanner/business/resources/daos/ICriterionDAO.java
new file mode 100644
index 000000000..1f39a06a0
--- /dev/null
+++ b/navalplanner-business/src/main/java/org/navalplanner/business/resources/daos/ICriterionDAO.java
@@ -0,0 +1,12 @@
+package org.navalplanner.business.resources.daos;
+
+import org.navalplanner.business.common.daos.IGenericDao;
+import org.navalplanner.business.resources.entities.Criterion;
+
+/**
+ * Description goes here.
+ * @author Óscar González Fernández
+ */
+public interface ICriterionDAO extends IGenericDao {
+
+}
diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/resources/daos/ICriterionSatisfactionDAO.java b/navalplanner-business/src/main/java/org/navalplanner/business/resources/daos/ICriterionSatisfactionDAO.java
new file mode 100644
index 000000000..e4c297b0c
--- /dev/null
+++ b/navalplanner-business/src/main/java/org/navalplanner/business/resources/daos/ICriterionSatisfactionDAO.java
@@ -0,0 +1,13 @@
+package org.navalplanner.business.resources.daos;
+
+import org.navalplanner.business.common.daos.IGenericDao;
+import org.navalplanner.business.resources.entities.CriterionSatisfaction;
+
+/**
+ * DAO for {@link CriterionSatisfaction}
+ * @author Óscar González Fernández
+ */
+public interface ICriterionSatisfactionDAO extends
+ IGenericDao {
+
+}
diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/resources/daos/impl/CriterionDAO.java b/navalplanner-business/src/main/java/org/navalplanner/business/resources/daos/impl/CriterionDAO.java
new file mode 100644
index 000000000..62ef28c17
--- /dev/null
+++ b/navalplanner-business/src/main/java/org/navalplanner/business/resources/daos/impl/CriterionDAO.java
@@ -0,0 +1,14 @@
+package org.navalplanner.business.resources.daos.impl;
+
+import org.navalplanner.business.common.daos.impl.GenericDaoHibernate;
+import org.navalplanner.business.resources.daos.ICriterionDAO;
+import org.navalplanner.business.resources.entities.Criterion;
+
+/**
+ * Description goes here.
+ * @author Óscar González Fernández
+ */
+public class CriterionDAO extends GenericDaoHibernate
+ implements ICriterionDAO {
+
+}
diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/resources/daos/impl/CriterionSatisfactionDAO.java b/navalplanner-business/src/main/java/org/navalplanner/business/resources/daos/impl/CriterionSatisfactionDAO.java
new file mode 100644
index 000000000..5cdb152c9
--- /dev/null
+++ b/navalplanner-business/src/main/java/org/navalplanner/business/resources/daos/impl/CriterionSatisfactionDAO.java
@@ -0,0 +1,14 @@
+package org.navalplanner.business.resources.daos.impl;
+
+import org.navalplanner.business.common.daos.impl.GenericDaoHibernate;
+import org.navalplanner.business.resources.daos.ICriterionSatisfactionDAO;
+import org.navalplanner.business.resources.entities.CriterionSatisfaction;
+
+/**
+ * Implementation
+ * @author Óscar González Fernández
+ */
+public class CriterionSatisfactionDAO extends
+ GenericDaoHibernate implements
+ ICriterionSatisfactionDAO {
+}
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
new file mode 100644
index 000000000..55d3c2743
--- /dev/null
+++ b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/Criterion.java
@@ -0,0 +1,34 @@
+package org.navalplanner.business.resources.entities;
+
+import java.util.Date;
+
+/**
+ * A criterion stored in the database
+ * @author Óscar González Fernández
+ */
+public class Criterion implements ICriterion {
+
+ private Long id;
+
+ @SuppressWarnings("unused")
+ private long version;
+
+ private String type;
+
+ private boolean active;
+
+ public Long getId() {
+ return id;
+ }
+
+ @Override
+ public boolean isSatisfiedBy(Resource resource) {
+ return !resource.getActiveSatisfactionsFor(this).isEmpty();
+ }
+
+ public boolean isSatisfiedBy(Resource resource, Date start, Date end) {
+ return !resource.getActiveSatisfactionsForIn(this, start, end)
+ .isEmpty();
+ }
+
+}
diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/CriterionCompounder.java b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/CriterionCompounder.java
new file mode 100644
index 000000000..83e22b4a9
--- /dev/null
+++ b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/CriterionCompounder.java
@@ -0,0 +1,168 @@
+package org.navalplanner.business.resources.entities;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Compounds some {@link ICriterion} into one
+ * Created at May 12, 2009
+ * @author Óscar González Fernández
+ */
+public class CriterionCompounder {
+
+ public static CriterionCompounder build() {
+ return new CriterionCompounder();
+ }
+
+ public static CriterionCompounder atom(ICriterion criterion) {
+ return build().and(criterion);
+ }
+
+ public static ICriterion not(ICriterion criterion) {
+ return new Negated(criterion);
+ }
+
+ public static ICriterion not(CriterionCompounder compounder) {
+ return not(compounder.getResult());
+ }
+
+ private static class Negated implements ICriterion {
+ private final ICriterion criterion;
+
+ private Negated(ICriterion criterion) {
+ this.criterion = criterion;
+ }
+
+ @Override
+ public boolean isSatisfiedBy(Resource resource) {
+ return !criterion.isSatisfiedBy(resource);
+ }
+
+ @Override
+ public boolean isSatisfiedBy(Resource resource, Date start, Date end) {
+ return !criterion.isSatisfiedBy(resource, start, end);
+ }
+ }
+
+ private static class OrClause implements ICriterion {
+
+ private Collection extends ICriterion> criterions;
+
+ public OrClause(Collection extends ICriterion> atoms) {
+ this.criterions = atoms;
+ }
+
+ @Override
+ public boolean isSatisfiedBy(Resource resource) {
+ for (ICriterion criterion : criterions) {
+ if (criterion.isSatisfiedBy(resource)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean isSatisfiedBy(Resource resource, Date start, Date end) {
+ for (ICriterion criterion : criterions) {
+ if (criterion.isSatisfiedBy(resource, start, end)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ }
+
+ private static class AndClause implements ICriterion {
+ private List criterions;
+
+ AndClause() {
+ this.criterions = new LinkedList();
+ }
+
+ private AndClause(List atoms) {
+ this.criterions = atoms;
+ }
+
+ public AndClause and(ICriterion criterion) {
+ return new AndClause(join(criterions, criterion));
+ }
+
+ private static List join(List previous,
+ ICriterion criterion) {
+ LinkedList result = new LinkedList(previous);
+ result.add(criterion);
+ return result;
+ }
+
+ @Override
+ public boolean isSatisfiedBy(Resource resource) {
+ for (ICriterion criterion : criterions) {
+ if (!criterion.isSatisfiedBy(resource))
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public boolean isSatisfiedBy(Resource resource, Date start, Date end) {
+ for (ICriterion criterion : criterions) {
+ if (!criterion.isSatisfiedBy(resource, start, end))
+ return false;
+ }
+ return true;
+ }
+
+ }
+
+ private final List clauses;
+
+ private CriterionCompounder() {
+ this(new AndClause());
+ }
+
+ private CriterionCompounder(AndClause andClause) {
+ clauses = new ArrayList();
+ clauses.add(andClause);
+ }
+
+ private CriterionCompounder(List clauses) {
+ this.clauses = clauses;
+ }
+
+ private AndClause getLast() {
+ return clauses.get(clauses.size() - 1);
+ }
+
+ private List updateLast(AndClause clause) {
+ ArrayList arrayList = new ArrayList(clauses);
+ arrayList.set(arrayList.size() - 1, clause);
+ return arrayList;
+ }
+
+ public CriterionCompounder and(CriterionCompounder compounder) {
+ return and(compounder.getResult());
+ }
+
+ public CriterionCompounder and(ICriterion criterion) {
+ return new CriterionCompounder(updateLast(getLast().and(criterion)));
+ }
+
+ public CriterionCompounder or(CriterionCompounder compounder) {
+ return or(compounder.getResult());
+ }
+
+ public CriterionCompounder or(ICriterion criterion) {
+ ArrayList copied = new ArrayList(clauses);
+ copied.add(new AndClause());
+ return new CriterionCompounder(copied).and(criterion);
+ }
+
+ public ICriterion getResult() {
+ return new OrClause(clauses);
+ }
+
+}
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
new file mode 100644
index 000000000..3c6ed492b
--- /dev/null
+++ b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/CriterionSatisfaction.java
@@ -0,0 +1,82 @@
+package org.navalplanner.business.resources.entities;
+
+import java.util.Date;
+
+import org.apache.commons.lang.Validate;
+
+/**
+ * Declares a interval of time in which the criterion is satisfied
+ * @author Óscar González Fernández
+ */
+public class CriterionSatisfaction {
+
+ private Long id;
+
+ @SuppressWarnings("unused")
+ private long version;
+
+ /**
+ * Required by hibernate. Do not use directly
+ */
+ public CriterionSatisfaction() {
+
+ }
+
+ public CriterionSatisfaction(Date startDate, Criterion criterion,
+ Resource resource) {
+ Validate.notNull(startDate, "startDate must be not null");
+ Validate.notNull(criterion, "criterion must be not null");
+ Validate.notNull(resource, "resource must be not null");
+ this.startDate = startDate;
+ this.criterion = criterion;
+ this.resource = resource;
+ this.resource.add(this);
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ private Date startDate;
+
+ private Date finishDate;
+
+ private Criterion criterion;
+
+ private Resource resource;
+
+ public Date getStartDate() {
+ return new Date(startDate.getTime());
+ }
+
+ public Date getEndDate() {
+ return new Date(finishDate.getTime());
+ }
+
+ public Criterion getCriterion() {
+ return criterion;
+ }
+
+ public Resource getResource() {
+ return resource;
+ }
+
+ public boolean isActiveNow() {
+ return startDate.before(new Date()) && finishDate == null;
+ }
+
+ public boolean isActiveIn(Date start, Date end) {
+ return startDate.before(start)
+ && (finishDate == null || end.before(finishDate));
+ }
+
+ public void finish(Date finish) {
+ Validate.notNull(finish);
+ Validate.isTrue(startDate.before(finish));
+ finishDate = finish;
+ }
+
+ public boolean isFinished() {
+ return finishDate != null;
+ }
+}
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
new file mode 100644
index 000000000..4f56e8c2c
--- /dev/null
+++ b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/CriterionTypeBase.java
@@ -0,0 +1,29 @@
+package org.navalplanner.business.resources.entities;
+
+/**
+ * Base implementation of {@link ICriterionType}
+ * @author Óscar González Fernández
+ */
+public abstract class CriterionTypeBase implements ICriterionType {
+
+ private final boolean allowHierarchy;
+
+ private final boolean allowMultipleValuesPerResource;
+
+ protected CriterionTypeBase(boolean allowHierarchy,
+ boolean allowMultipleValuesPerResource) {
+ this.allowHierarchy = allowHierarchy;
+ this.allowMultipleValuesPerResource = allowMultipleValuesPerResource;
+ }
+
+ @Override
+ public boolean allowHierarchy() {
+ return allowHierarchy;
+ }
+
+ @Override
+ public boolean allowMultipleActiveCriterionsPerResource() {
+ return allowMultipleValuesPerResource;
+ }
+
+}
diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/ICriterion.java b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/ICriterion.java
new file mode 100644
index 000000000..c6d953557
--- /dev/null
+++ b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/ICriterion.java
@@ -0,0 +1,17 @@
+package org.navalplanner.business.resources.entities;
+
+import java.util.Date;
+
+/**
+ * Responsible of searching the resources satisfiying some condition or set of
+ * conditions.
+ * Created at May 12, 2009
+ * @author Óscar González Fernández
+ */
+public interface ICriterion {
+
+ boolean isSatisfiedBy(Resource resource);
+
+ boolean isSatisfiedBy(Resource resource, Date start, Date end);
+
+}
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
new file mode 100644
index 000000000..5e623817f
--- /dev/null
+++ b/navalplanner-business/src/main/java/org/navalplanner/business/resources/entities/ICriterionType.java
@@ -0,0 +1,17 @@
+package org.navalplanner.business.resources.entities;
+
+/**
+ * Parametrizes the behaviour of some criterions
+ * @author Óscar González Fernández
+ */
+public interface ICriterionType {
+
+ public boolean allowMultipleActiveCriterionsPerResource();
+
+ public boolean allowHierarchy();
+
+ public ICriterion createCriterion();
+
+ public boolean contains(ICriterion criterion);
+
+}
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 e9243f74f..9c6be64e0 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,5 +1,13 @@
package org.navalplanner.business.resources.entities;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.commons.lang.Validate;
import org.navalplanner.business.common.exceptions.InstanceNotFoundException;
import org.navalplanner.business.resources.daos.ResourcesDaoRegistry;
@@ -22,6 +30,8 @@ public abstract class Resource {
@SuppressWarnings("unused")
private long version;
+ private Set criterionSatisfactions = new HashSet();
+
public Long getId() {
return id;
}
@@ -43,4 +53,87 @@ public abstract class Resource {
}
}
+ public Set getAllSatisfactions() {
+ return Collections.unmodifiableSet(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;
+ }
+
+ public Collection getActiveSatisfactionsFor(
+ ICriterionType criterionType) {
+ Collection satisfactionsFor = getSatisfactionsFor(criterionType);
+ ArrayList result = new ArrayList();
+ for (CriterionSatisfaction criterionSatisfaction : satisfactionsFor) {
+ if (criterionSatisfaction.isActiveNow()) {
+ result.add(criterionSatisfaction);
+ }
+ }
+ return result;
+ }
+
+ public Collection getActiveSatisfactionsForIn(
+ ICriterionType criterionType, Date start, Date end) {
+ Validate.notNull(criterionType);
+ Validate.isTrue(start.before(end));
+ Collection satisfactionsFor = getSatisfactionsFor(criterionType);
+ ArrayList result = new ArrayList();
+ for (CriterionSatisfaction criterionSatisfaction : satisfactionsFor) {
+ if (criterionSatisfaction.isActiveIn(start, end)) {
+ result.add(criterionSatisfaction);
+ }
+ }
+ return result;
+ }
+
+ public Collection getActiveSatisfactionsFor(
+ ICriterion criterion) {
+ Set result = new HashSet();
+ for (CriterionSatisfaction criterionSatisfaction : getAllSatisfactionsFor(criterion)) {
+ if (criterionSatisfaction.isActiveNow()) {
+ result.add(criterionSatisfaction);
+ }
+ }
+ return result;
+ }
+
+ private Collection getAllSatisfactionsFor(
+ ICriterion criterion) {
+ Set result = new HashSet();
+ for (CriterionSatisfaction satisfaction : criterionSatisfactions) {
+ if (satisfaction.getCriterion().equals(criterion)) {
+ result.add(satisfaction);
+ }
+ }
+ return result;
+ }
+
+ public Collection getActiveSatisfactionsForIn(
+ ICriterion criterion, Date start, Date end) {
+ Validate.isTrue(start.before(end));
+ ArrayList result = new ArrayList();
+ Collection allSatisfactionsFor = getAllSatisfactionsFor(criterion);
+ for (CriterionSatisfaction criterionSatisfaction : allSatisfactionsFor) {
+ if (criterionSatisfaction.isActiveIn(start, end)) {
+ result.add(criterionSatisfaction);
+ }
+ }
+ return result;
+ }
+
+ void add(CriterionSatisfaction criterionSatisfaction) {
+ Validate.notNull(criterionSatisfaction,
+ "criterionSatisfaction must be not null");
+ criterionSatisfactions.add(criterionSatisfaction);
+ }
+
}
diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/resources/services/CriterionService.java b/navalplanner-business/src/main/java/org/navalplanner/business/resources/services/CriterionService.java
new file mode 100644
index 000000000..a0079b4d7
--- /dev/null
+++ b/navalplanner-business/src/main/java/org/navalplanner/business/resources/services/CriterionService.java
@@ -0,0 +1,45 @@
+package org.navalplanner.business.resources.services;
+
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+
+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.ICriterion;
+import org.navalplanner.business.resources.entities.ICriterionType;
+import org.navalplanner.business.resources.entities.Resource;
+
+/**
+ * Services for aggregate {@link Criterion}
+ * @author Óscar González Fernández
+ */
+public interface CriterionService {
+
+ boolean exists(Long id);
+
+ Criterion find(Long id) throws InstanceNotFoundException;
+
+ List list();
+
+ void remove(Criterion criterion) throws InstanceNotFoundException;
+
+ void remove(Long id) throws InstanceNotFoundException;
+
+ void save(Criterion entity);
+
+ void add(CriterionSatisfaction criterionSatisfaction);
+
+ Collection getResourcesSatisfying(ICriterion criterion);
+
+ Collection getResourcesSatisfying(ICriterion criterion,
+ Date begin, Date end);
+
+ Collection getSatisfactionsFor(
+ ICriterionType criterionType);
+
+ Collection getSatisfactionsFor(
+ ICriterionType criterionType, Date begin, Date end);
+
+}
diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/resources/services/ResourceService.java b/navalplanner-business/src/main/java/org/navalplanner/business/resources/services/ResourceService.java
index 1af8811a7..c060d53d1 100644
--- a/navalplanner-business/src/main/java/org/navalplanner/business/resources/services/ResourceService.java
+++ b/navalplanner-business/src/main/java/org/navalplanner/business/resources/services/ResourceService.java
@@ -1,8 +1,10 @@
package org.navalplanner.business.resources.services;
import java.util.List;
+import java.util.Set;
import org.navalplanner.business.common.exceptions.InstanceNotFoundException;
+import org.navalplanner.business.resources.entities.ICriterion;
import org.navalplanner.business.resources.entities.Resource;
import org.navalplanner.business.resources.entities.Worker;
@@ -34,4 +36,7 @@ public interface ResourceService {
public List getWorkers();
+ public List getResources();
+
+ public Set getSetOfResourcesSatisfying(ICriterion criterion);
}
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
new file mode 100644
index 000000000..23c7fc47a
--- /dev/null
+++ b/navalplanner-business/src/main/java/org/navalplanner/business/resources/services/impl/CriterionServiceImpl.java
@@ -0,0 +1,113 @@
+package org.navalplanner.business.resources.services.impl;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+
+import org.apache.commons.lang.Validate;
+import org.navalplanner.business.common.exceptions.InstanceNotFoundException;
+import org.navalplanner.business.resources.daos.impl.CriterionDAO;
+import org.navalplanner.business.resources.daos.impl.CriterionSatisfactionDAO;
+import org.navalplanner.business.resources.entities.Criterion;
+import org.navalplanner.business.resources.entities.CriterionSatisfaction;
+import org.navalplanner.business.resources.entities.ICriterion;
+import org.navalplanner.business.resources.entities.ICriterionType;
+import org.navalplanner.business.resources.entities.Resource;
+import org.navalplanner.business.resources.services.CriterionService;
+import org.navalplanner.business.resources.services.ResourceService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * Implementation of {@link CriterionService} using {@link CriterionDAO}
+ * @author Óscar González Fernández
+ */
+@Transactional
+public class CriterionServiceImpl implements CriterionService {
+
+ @Autowired
+ private CriterionDAO criterionDAO;
+
+ @Autowired
+ private CriterionSatisfactionDAO criterionSatisfactionDAO;
+
+ @Autowired
+ private ResourceService resourceService;
+
+ public boolean exists(Long id) {
+ return criterionDAO.exists(id);
+ }
+
+ public Criterion find(Long id) throws InstanceNotFoundException {
+ return criterionDAO.find(id);
+ }
+
+ public List list() {
+ return criterionDAO.list(Criterion.class);
+ }
+
+ public void remove(Criterion criterion) throws InstanceNotFoundException {
+ criterionDAO.remove(criterion.getId());
+ }
+
+ public void remove(Long id) throws InstanceNotFoundException {
+ criterionDAO.remove(id);
+ }
+
+ public void save(Criterion entity) {
+ criterionDAO.save(entity);
+ }
+
+ @Override
+ public void add(CriterionSatisfaction criterionSatisfaction) {
+ criterionSatisfactionDAO.save(criterionSatisfaction);
+ }
+
+ @Override
+ public Collection getResourcesSatisfying(ICriterion criterion) {
+ List resources = resourceService.getResources();
+ ArrayList result = new ArrayList();
+ for (Resource resource : resources) {
+ if (criterion.isSatisfiedBy(resource)) {
+ result.add(resource);
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public Collection getResourcesSatisfying(ICriterion criterion,
+ Date start, Date end) {
+ Validate.isTrue(start.before(end), "start must be before than end");
+ List resources = resourceService.getResources();
+ ArrayList result = new ArrayList();
+ for (Resource resource : resources) {
+ if (criterion.isSatisfiedBy(resource, start, end)) {
+ result.add(resource);
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public Collection getSatisfactionsFor(
+ ICriterionType criterionType) {
+ ArrayList result = new ArrayList();
+ for (Resource resource : resourceService.getResources()) {
+ result.addAll(resource.getActiveSatisfactionsFor(criterionType));
+ }
+ return result;
+ }
+
+ @Override
+ public Collection getSatisfactionsFor(
+ ICriterionType criterionType, Date start, Date end) {
+ ArrayList result = new ArrayList();
+ for (Resource resource : resourceService.getResources()) {
+ result.addAll(resource.getActiveSatisfactionsForIn(criterionType,
+ start, end));
+ }
+ return result;
+ }
+}
diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/resources/services/impl/ResourceServiceImpl.java b/navalplanner-business/src/main/java/org/navalplanner/business/resources/services/impl/ResourceServiceImpl.java
index 6cc399cbd..e25820040 100644
--- a/navalplanner-business/src/main/java/org/navalplanner/business/resources/services/impl/ResourceServiceImpl.java
+++ b/navalplanner-business/src/main/java/org/navalplanner/business/resources/services/impl/ResourceServiceImpl.java
@@ -1,9 +1,12 @@
package org.navalplanner.business.resources.services.impl;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import org.navalplanner.business.common.exceptions.InstanceNotFoundException;
import org.navalplanner.business.resources.daos.IResourceDao;
+import org.navalplanner.business.resources.entities.ICriterion;
import org.navalplanner.business.resources.entities.Resource;
import org.navalplanner.business.resources.entities.Worker;
import org.navalplanner.business.resources.services.ResourceService;
@@ -51,4 +54,21 @@ public class ResourceServiceImpl implements ResourceService {
public List getWorkers() {
return resourceDao.list(Worker.class);
}
+
+ @Override
+ public Set getSetOfResourcesSatisfying(ICriterion criterion) {
+ List resources = resourceDao.list(Resource.class);
+ HashSet result = new HashSet();
+ for (Resource resource : resources) {
+ if (criterion.isSatisfiedBy(resource)) {
+ result.add(resource);
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public List getResources() {
+ return resourceDao.list(Resource.class);
+ }
}
diff --git a/navalplanner-business/src/main/resources/navalplanner-business-spring-config.xml b/navalplanner-business/src/main/resources/navalplanner-business-spring-config.xml
index 72dd606ee..49e28f4bd 100644
--- a/navalplanner-business/src/main/resources/navalplanner-business-spring-config.xml
+++ b/navalplanner-business/src/main/resources/navalplanner-business-spring-config.xml
@@ -25,7 +25,6 @@
-
@@ -57,6 +56,11 @@
+
+
+
+
diff --git a/navalplanner-business/src/main/resources/org/navalplanner/business/resources/entities/Resources.hbm.xml b/navalplanner-business/src/main/resources/org/navalplanner/business/resources/entities/Resources.hbm.xml
index aa34c6ff9..36ad692de 100644
--- a/navalplanner-business/src/main/resources/org/navalplanner/business/resources/entities/Resources.hbm.xml
+++ b/navalplanner-business/src/main/resources/org/navalplanner/business/resources/entities/Resources.hbm.xml
@@ -1,34 +1,43 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/navalplanner-business/src/test/java/org/navalplanner/business/test/resources/daos/CriterionDAOTest.java b/navalplanner-business/src/test/java/org/navalplanner/business/test/resources/daos/CriterionDAOTest.java
new file mode 100644
index 000000000..ae7a3379a
--- /dev/null
+++ b/navalplanner-business/src/test/java/org/navalplanner/business/test/resources/daos/CriterionDAOTest.java
@@ -0,0 +1,77 @@
+package org.navalplanner.business.test.resources.daos;
+
+import java.util.List;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.navalplanner.business.common.exceptions.InstanceNotFoundException;
+import org.navalplanner.business.resources.daos.ICriterionDAO;
+import org.navalplanner.business.resources.entities.Criterion;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.transaction.annotation.Transactional;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertTrue;
+import static org.navalplanner.business.BusinessGlobalNames.BUSINESS_SPRING_CONFIG_FILE;
+import static org.navalplanner.business.test.BusinessGlobalNames.BUSINESS_SPRING_CONFIG_TEST_FILE;
+
+/**
+ * Test cases for CriterionDAO
+ * Created at May 13, 2009
+ * @author Óscar González Fernández
+ */
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = { BUSINESS_SPRING_CONFIG_FILE,
+ BUSINESS_SPRING_CONFIG_TEST_FILE })
+@Transactional
+public class CriterionDAOTest {
+
+ @Autowired
+ private ICriterionDAO criterionDAO;
+
+ @Test
+ public void testInSpringContainer() {
+ assertNotNull(criterionDAO);
+ }
+
+ @Test
+ public void testSaveCriterions() throws Exception {
+ Criterion criterion = createValidCriterion();
+ criterionDAO.save(criterion);
+ assertNotNull(criterion.getId());
+ assertTrue(criterionDAO.exists(criterion.getId()));
+ }
+
+ public static Criterion createValidCriterion() {
+ return new Criterion();
+ }
+
+ @Test(expected = InstanceNotFoundException.class)
+ public void testRemoveNotExistent() throws InstanceNotFoundException {
+ criterionDAO.remove(Long.MAX_VALUE);
+ }
+
+ @Test
+ public void testRemove() throws InstanceNotFoundException {
+ Criterion criterion = createValidCriterion();
+ criterionDAO.save(criterion);
+ assertTrue(criterionDAO.exists(criterion.getId()));
+ criterionDAO.remove(criterion.getId());
+ assertFalse(criterionDAO.exists(criterion.getId()));
+ }
+
+ @Test
+ public void testList() {
+ int previous = criterionDAO.list(Criterion.class).size();
+ Criterion criterion1 = createValidCriterion();
+ Criterion criterion2 = createValidCriterion();
+ criterionDAO.save(criterion1);
+ criterionDAO.save(criterion2);
+ List list = criterionDAO.list(Criterion.class);
+ assertEquals(previous + 2, list.size());
+ }
+}
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
new file mode 100644
index 000000000..e6cd638f7
--- /dev/null
+++ b/navalplanner-business/src/test/java/org/navalplanner/business/test/resources/daos/CriterionSatisfactionDAOTest.java
@@ -0,0 +1,100 @@
+package org.navalplanner.business.test.resources.daos;
+
+import java.util.Calendar;
+import java.util.Date;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.navalplanner.business.common.exceptions.InstanceNotFoundException;
+import org.navalplanner.business.resources.daos.ICriterionDAO;
+import org.navalplanner.business.resources.daos.ICriterionSatisfactionDAO;
+import org.navalplanner.business.resources.daos.impl.WorkerDaoHibernate;
+import org.navalplanner.business.resources.entities.Criterion;
+import org.navalplanner.business.resources.entities.CriterionSatisfaction;
+import org.navalplanner.business.resources.entities.Worker;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.dao.DataIntegrityViolationException;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.transaction.annotation.Transactional;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertTrue;
+import static org.navalplanner.business.BusinessGlobalNames.BUSINESS_SPRING_CONFIG_FILE;
+import static org.navalplanner.business.test.BusinessGlobalNames.BUSINESS_SPRING_CONFIG_TEST_FILE;
+
+/**
+ * Description goes here.
+ * @author Óscar González Fernández
+ */
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = { BUSINESS_SPRING_CONFIG_FILE,
+ BUSINESS_SPRING_CONFIG_TEST_FILE })
+@Transactional
+public class CriterionSatisfactionDAOTest {
+
+ @Autowired
+ private ICriterionSatisfactionDAO satisfactionDAO;
+
+ @Autowired
+ private ICriterionDAO criterionDAO;
+
+ @Autowired
+ private WorkerDaoHibernate workerDAO;
+
+ @Test
+ public void testSaveCriterions() throws Exception {
+ CriterionSatisfaction criterionSatisfaction = createValidCriterionSatisfaction(2007);
+ satisfactionDAO.save(criterionSatisfaction);
+ assertNotNull(criterionSatisfaction.getId());
+ assertTrue(satisfactionDAO.exists(criterionSatisfaction.getId()));
+ }
+
+ private CriterionSatisfaction createValidCriterionSatisfaction(int year) {
+ Criterion criterion = CriterionDAOTest.createValidCriterion();
+ criterionDAO.save(criterion);
+ Worker worker = new Worker("firstname", "surname", "nif", 4);
+ workerDAO.save(worker);
+ CriterionSatisfaction criterionSatisfaction = new CriterionSatisfaction(
+ year(year), criterion, worker);
+ return criterionSatisfaction;
+ }
+
+ @Test(expected = DataIntegrityViolationException.class)
+ public void testNotSaveWithTransientCriterionAndWorker() {
+ Criterion criterion = CriterionDAOTest.createValidCriterion();
+ Worker worker = new Worker("firstname", "surname", "nif", 4);
+ CriterionSatisfaction criterionSatisfaction = new CriterionSatisfaction(
+ year(2007), criterion, worker);
+ satisfactionDAO.save(criterionSatisfaction);
+ }
+
+ public static Date year(int year) {
+ Calendar calendar = Calendar.getInstance();
+ calendar.clear();
+ calendar.set(Calendar.YEAR, year);
+ return calendar.getTime();
+ }
+
+ @Test
+ public void testRemove() throws InstanceNotFoundException {
+ CriterionSatisfaction satisfaction = createValidCriterionSatisfaction(2008);
+ satisfactionDAO.save(satisfaction);
+ assertTrue(satisfactionDAO.exists(satisfaction.getId()));
+ satisfactionDAO.remove(satisfaction.getId());
+ assertFalse(criterionDAO.exists(satisfaction.getId()));
+ }
+
+ @Test
+ public void testList() {
+ int previous = satisfactionDAO.list(CriterionSatisfaction.class).size();
+ CriterionSatisfaction satisfaction1 = createValidCriterionSatisfaction(2007);
+ CriterionSatisfaction satisfaction2 = createValidCriterionSatisfaction(2008);
+ satisfactionDAO.save(satisfaction1);
+ satisfactionDAO.save(satisfaction2);
+ assertEquals(previous + 2, satisfactionDAO.list(
+ CriterionSatisfaction.class).size());
+ }
+}
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
new file mode 100644
index 000000000..b1cbb16cd
--- /dev/null
+++ b/navalplanner-business/src/test/java/org/navalplanner/business/test/resources/entities/CriterionSatisfactionTest.java
@@ -0,0 +1,45 @@
+package org.navalplanner.business.test.resources.entities;
+
+import java.util.Date;
+
+import org.junit.Test;
+import org.navalplanner.business.resources.entities.Criterion;
+import org.navalplanner.business.resources.entities.CriterionSatisfaction;
+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.junit.Assert.assertTrue;
+
+/**
+ * Tests for {@link CriterionSatisfaction}
+ * @author Óscar González Fernández
+ */
+public class CriterionSatisfactionTest {
+
+ @Test
+ public void testFinish() {
+ 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);
+ criterionSatisfaction.finish(end);
+ assertTrue(criterionSatisfaction.isFinished());
+ assertEquals(end, criterionSatisfaction.getEndDate());
+ criterionSatisfaction.getEndDate().setTime(end.getTime() + 2000);
+ assertEquals("endDate must be well encapsulated", end,
+ criterionSatisfaction.getEndDate());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testCantFinishBeforeStart() {
+ 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));
+ }
+
+}
diff --git a/navalplanner-business/src/test/java/org/navalplanner/business/test/resources/entities/CriterionTest.java b/navalplanner-business/src/test/java/org/navalplanner/business/test/resources/entities/CriterionTest.java
new file mode 100644
index 000000000..a9afd9f30
--- /dev/null
+++ b/navalplanner-business/src/test/java/org/navalplanner/business/test/resources/entities/CriterionTest.java
@@ -0,0 +1,139 @@
+package org.navalplanner.business.test.resources.entities;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashSet;
+
+import org.junit.Test;
+import org.navalplanner.business.resources.entities.CriterionCompounder;
+import org.navalplanner.business.resources.entities.ICriterion;
+import org.navalplanner.business.resources.entities.Resource;
+import org.navalplanner.business.resources.entities.Worker;
+
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+import static org.navalplanner.business.resources.entities.CriterionCompounder.atom;
+import static org.navalplanner.business.resources.entities.CriterionCompounder.build;
+import static org.navalplanner.business.resources.entities.CriterionCompounder.not;
+
+/**
+ * Tests for criterion.
+ * Created at May 12, 2009
+ * @author Óscar González Fernández
+ */
+public class CriterionTest {
+
+ @Test
+ public void testCompounding() throws Exception {
+ Worker worker1 = new Worker();
+ Worker worker2 = new Worker();
+
+ ICriterion criterionForWorker1 = justThisResourcesCriterion(worker1);
+ ICriterion criterionForWorker2 = justThisResourcesCriterion(worker2);
+ ICriterion criterionForWorkers1And2 = justThisResourcesCriterion(
+ worker1, worker2);
+
+ assertTrue(criterionForWorker1.isSatisfiedBy(worker1));
+ assertTrue(criterionForWorker2.isSatisfiedBy(worker2));
+ assertFalse(criterionForWorker2.isSatisfiedBy(worker1));
+ assertTrue(criterionForWorkers1And2.isSatisfiedBy(worker1));
+ assertTrue(criterionForWorkers1And2.isSatisfiedBy(worker2));
+
+ ICriterion compositedCriterion = CriterionCompounder.atom(criterionForWorker1)
+ .and(criterionForWorkers1And2).getResult();
+ ICriterion matchesNoneComposited = CriterionCompounder.build().and(
+ criterionForWorker1).and(criterionForWorker2).getResult();
+
+ assertFalse(matchesNoneComposited.isSatisfiedBy(worker2));
+ assertFalse(matchesNoneComposited.isSatisfiedBy(worker1));
+
+ assertTrue(compositedCriterion.isSatisfiedBy(worker1));
+ assertFalse(compositedCriterion.isSatisfiedBy(worker2));
+ }
+
+ @Test
+ public void testEmptyMatchesAll() throws Exception {
+ assertTrue(build().getResult().isSatisfiedBy(new Worker()));
+ }
+
+ @Test
+ public void testSimpleNegation() throws Exception {
+ Worker worker1 = new Worker();
+ Worker worker2 = new Worker();
+ Worker worker3 = new Worker();
+ ICriterion criterionForWorker1 = justThisResourcesCriterion(worker1);
+ ICriterion criterionForWorker2 = justThisResourcesCriterion(worker2);
+ ICriterion worker1Negated = not(criterionForWorker1);
+ ICriterion compound = build().and(criterionForWorker1).and(
+ not(criterionForWorker2)).getResult();
+ assertFalse(worker1Negated.isSatisfiedBy(worker1));
+ assertTrue(worker1Negated.isSatisfiedBy(worker2));
+ assertFalse(compound.isSatisfiedBy(worker2));
+ assertTrue(compound.isSatisfiedBy(worker1));
+ assertFalse(compound.isSatisfiedBy(worker3));
+ }
+
+ @Test
+ public void testNegateAnd() throws Exception {
+ Worker worker1 = new Worker();
+ Worker worker2 = new Worker();
+ Worker worker3 = new Worker();
+ ICriterion criterionForWorker1 = justThisResourcesCriterion(worker1);
+ ICriterion both = justThisResourcesCriterion(worker1, worker2);
+ ICriterion andNegated = not(atom(criterionForWorker1).and(both));
+ assertTrue(andNegated.isSatisfiedBy(worker2));
+ assertTrue(andNegated.isSatisfiedBy(worker3));
+ assertFalse(andNegated.isSatisfiedBy(worker1));
+ }
+
+ @Test
+ public void testOr() throws Exception {
+ Worker worker1 = new Worker();
+ Worker worker2 = new Worker();
+ Worker worker3 = new Worker();
+ ICriterion both = justThisResourcesCriterion(worker1, worker2);
+ assertFalse(both.isSatisfiedBy(worker3));
+
+ ICriterion all = atom(both).or(justThisResourcesCriterion(worker3))
+ .getResult();
+
+ assertTrue(all.isSatisfiedBy(worker1));
+ assertTrue(all.isSatisfiedBy(worker2));
+ assertTrue(all.isSatisfiedBy(worker3));
+ }
+
+ @Test
+ public void testOrHasLessPrecendenceThanAnd() throws Exception {
+ Worker worker1 = new Worker();
+ Worker worker2 = new Worker();
+ Worker worker3 = new Worker();
+ ICriterion criterionForWorker1 = justThisResourcesCriterion(worker1);
+ ICriterion both = justThisResourcesCriterion(worker1, worker2);
+
+ ICriterion or = atom(criterionForWorker1).and(both).or(
+ justThisResourcesCriterion(worker3)).getResult();
+
+ assertTrue(or.isSatisfiedBy(worker1));
+ assertFalse(or.isSatisfiedBy(worker2));
+ assertTrue("or has less priority", or.isSatisfiedBy(worker3));
+ }
+
+ public static ICriterion justThisResourcesCriterion(
+ final Resource... resources) {
+ final HashSet set = new HashSet(Arrays
+ .asList(resources));
+ return new ICriterion() {
+
+ @Override
+ public boolean isSatisfiedBy(Resource resource) {
+ return set.contains(resource);
+ }
+
+ @Override
+ public boolean isSatisfiedBy(Resource resource, Date start, Date end) {
+ return isSatisfiedBy(resource);
+ }
+ };
+ }
+
+}
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
new file mode 100644
index 000000000..ab5825117
--- /dev/null
+++ b/navalplanner-business/src/test/java/org/navalplanner/business/test/resources/entities/ResourceTest.java
@@ -0,0 +1,136 @@
+package org.navalplanner.business.test.resources.entities;
+
+import java.util.Arrays;
+import java.util.HashSet;
+
+import org.junit.Test;
+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.ICriterion;
+import org.navalplanner.business.resources.entities.ICriterionType;
+import org.navalplanner.business.resources.entities.Resource;
+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;
+
+/**
+ * Tests for {@link Resource}.
+ * @author Óscar González Fernández
+ */
+public class ResourceTest {
+
+ @Test
+ public void testRelationResourceWithCriterionSatisfaction()
+ throws Exception {
+ Criterion criterion = CriterionDAOTest.createValidCriterion();
+ Worker worker = new Worker("firstName", "surName", "2333232", 10);
+ new CriterionSatisfaction(CriterionSatisfactionDAOTest.year(2000),
+ criterion, worker);
+ assertEquals(1, worker.getAllSatisfactions().size());
+ }
+
+ @Test
+ public void testGetActiveSatisfactionsForCriterion() throws Exception {
+ Criterion criterion = CriterionDAOTest.createValidCriterion();
+ Worker worker = new Worker("firstName", "surName", "2333232", 10);
+ new CriterionSatisfaction(CriterionSatisfactionDAOTest.year(2000),
+ criterion, worker);
+ new CriterionSatisfaction(CriterionSatisfactionDAOTest.year(4000),
+ criterion, worker);
+ assertEquals(1, worker.getActiveSatisfactionsFor(criterion).size());
+ }
+
+ @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));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void getSatisfactionsForWrongIntervalForCriterionTypeThrowsException() {
+ Worker worker = new Worker("firstName", "surName", "2333232", 10);
+ worker.getActiveSatisfactionsForIn(createTypeThatMatches(),
+ CriterionSatisfactionDAOTest.year(2000),
+ CriterionSatisfactionDAOTest.year(1999));
+ }
+
+ @Test
+ public void tesGetSatisfactionsInIntervalForCriterion() throws Exception {
+ Criterion criterion = CriterionDAOTest.createValidCriterion();
+ Worker worker = new Worker("firstName", "surName", "2333232", 10);
+ new CriterionSatisfaction(CriterionSatisfactionDAOTest.year(2000),
+ criterion, worker);
+ new CriterionSatisfaction(CriterionSatisfactionDAOTest.year(1997),
+ criterion, worker);
+ assertEquals(1, worker.getActiveSatisfactionsForIn(criterion,
+ CriterionSatisfactionDAOTest.year(1999),
+ CriterionSatisfactionDAOTest.year(2010)).size());
+ }
+
+ @Test
+ public void testRetrieveActiveCriterionsForCriterionType() throws Exception {
+ final Criterion criterion = CriterionDAOTest.createValidCriterion();
+ Criterion otherCriterion = CriterionDAOTest.createValidCriterion();
+ Worker worker = new Worker("firstName", "surName", "2333232", 10);
+ new CriterionSatisfaction(CriterionSatisfactionDAOTest.year(2000),
+ criterion, worker);
+ new CriterionSatisfaction(CriterionSatisfactionDAOTest.year(2000),
+ otherCriterion, worker);
+ new CriterionSatisfaction(CriterionSatisfactionDAOTest.year(4000),
+ criterion, worker);
+ ICriterionType criterionType = createTypeThatMatches(criterion);
+ assertEquals(2, worker.getSatisfactionsFor(criterionType).size());
+ assertEquals(1, worker.getActiveSatisfactionsFor(criterionType).size());
+ }
+
+ public static CriterionTypeBase createTypeThatMatches(
+ final Criterion... criterions) {
+ final HashSet criterionsSet = new HashSet(Arrays
+ .asList(criterions));
+ return new CriterionTypeBase(true, true) {
+
+ @Override
+ public boolean contains(ICriterion c) {
+ return criterionsSet.contains(c);
+ }
+
+ @Override
+ public ICriterion createCriterion() {
+ return null;
+ }
+ };
+ }
+
+ @Test
+ public void testRetrieveSatisfactionsInIntervalForCriterionType()
+ throws Exception {
+ Criterion criterion = CriterionDAOTest.createValidCriterion();
+ Criterion otherCriterion = CriterionDAOTest.createValidCriterion();
+ Worker worker = new Worker("firstName", "surName", "2333232", 10);
+ new CriterionSatisfaction(CriterionSatisfactionDAOTest.year(2000),
+ criterion, worker);
+ new CriterionSatisfaction(CriterionSatisfactionDAOTest.year(2003),
+ criterion, worker);
+ new CriterionSatisfaction(CriterionSatisfactionDAOTest.year(2000),
+ otherCriterion, worker);
+
+ ICriterionType criterionType = createTypeThatMatches(criterion);
+
+ 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());
+ }
+
+}
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
new file mode 100644
index 000000000..c952bf762
--- /dev/null
+++ b/navalplanner-business/src/test/java/org/navalplanner/business/test/resources/services/CriterionServiceTest.java
@@ -0,0 +1,178 @@
+package org.navalplanner.business.test.resources.services;
+
+import org.hibernate.SessionFactory;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.navalplanner.business.resources.entities.Criterion;
+import org.navalplanner.business.resources.entities.CriterionSatisfaction;
+import org.navalplanner.business.resources.entities.ICriterionType;
+import org.navalplanner.business.resources.entities.Worker;
+import org.navalplanner.business.resources.services.CriterionService;
+import org.navalplanner.business.resources.services.ResourceService;
+import org.navalplanner.business.test.resources.daos.CriterionDAOTest;
+import org.navalplanner.business.test.resources.daos.CriterionSatisfactionDAOTest;
+import org.navalplanner.business.test.resources.entities.ResourceTest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.dao.DataIntegrityViolationException;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.transaction.annotation.Transactional;
+
+import static junit.framework.Assert.assertEquals;
+import static org.navalplanner.business.BusinessGlobalNames.BUSINESS_SPRING_CONFIG_FILE;
+import static org.navalplanner.business.test.BusinessGlobalNames.BUSINESS_SPRING_CONFIG_TEST_FILE;
+
+/**
+ * Test cases for {@link CriterionService}
+ * @author Óscar González Fernández
+ */
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = { BUSINESS_SPRING_CONFIG_FILE,
+ BUSINESS_SPRING_CONFIG_TEST_FILE })
+@Transactional
+public class CriterionServiceTest {
+
+ @Autowired
+ private CriterionService criterionService;
+
+ @Autowired
+ private ResourceService resourceService;
+
+ @Autowired
+ private SessionFactory sessionFactory;
+
+ @Test
+ public void testCreateCriterionSatisfactionButNotSave() {
+ Criterion criterion = CriterionDAOTest.createValidCriterion();
+ criterionService.save(criterion);
+ Worker worker = new Worker("firstName", "surName", "2333232", 10);
+ resourceService.saveResource(worker);
+ new CriterionSatisfaction(CriterionSatisfactionDAOTest.year(2000),
+ criterion, worker);
+ assertEquals(1, worker.getAllSatisfactions().size());
+ }
+
+ /*
+ * It sends a dataIntegrityViolationException when adding a
+ * criterionSatisfaction with a resource that doesn't exist yet
+ */
+ @Test(expected = DataIntegrityViolationException.class)
+ public void testCreateCriterionSatisfactionOnTransientCriterion()
+ throws Exception {
+ Criterion criterion = CriterionDAOTest.createValidCriterion();
+ Worker worker = new Worker("firstName", "surName", "2333232", 10);
+ resourceService.saveResource(worker);
+
+ criterionService.add(new CriterionSatisfaction(
+ CriterionSatisfactionDAOTest.year(2000), criterion, worker));
+ }
+
+ @Test(expected = DataIntegrityViolationException.class)
+ public void testCreateCriterionSatisfactionOnTransientResource()
+ throws Exception {
+ Criterion criterion = CriterionDAOTest.createValidCriterion();
+ criterionService.save(criterion);
+ Worker worker = new Worker("firstName", "surName", "2333232", 10);
+ CriterionSatisfaction criterionSatisfaction = new CriterionSatisfaction(
+ CriterionSatisfactionDAOTest.year(2000), criterion, worker);
+ criterionService.add(criterionSatisfaction);
+ }
+
+ @Test
+ public void testCreatingButNotPersistingSatisfaction() throws Exception {
+ Criterion criterion = CriterionDAOTest.createValidCriterion();
+ criterionService.save(criterion);
+ Worker worker = new Worker("firstName", "surName", "2333232", 10);
+ CriterionSatisfaction criterionSatisfaction = new CriterionSatisfaction(
+ CriterionSatisfactionDAOTest.year(2000), criterion, worker);
+ resourceService.saveResource(worker);
+ assertEquals(1, criterionService.getResourcesSatisfying(criterion)
+ .size());
+ sessionFactory.getCurrentSession().evict(worker);
+ assertEquals(
+ "once the worker has been evicted the satisfaction created is not taken into account",
+ 0, criterionService.getResourcesSatisfying(criterion).size());
+ }
+
+ @Test
+ public void testGetSetOfResourcesSatisfyingCriterion() throws Exception {
+ Criterion criterion = CriterionDAOTest.createValidCriterion();
+ criterionService.save(criterion);
+ Worker worker = new Worker("firstName", "surName", "2333232", 10);
+ resourceService.saveResource(worker);
+ CriterionSatisfaction criterionSatisfaction = new CriterionSatisfaction(
+ CriterionSatisfactionDAOTest.year(2000), criterion, worker);
+ criterionService.add(criterionSatisfaction);
+ assertEquals(1, criterionService.getResourcesSatisfying(criterion)
+ .size());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void mustBeCorrectInterval() {
+ Criterion criterion = CriterionDAOTest.createValidCriterion();
+ criterionService.save(criterion);
+ criterionService.getResourcesSatisfying(criterion,
+ CriterionSatisfactionDAOTest.year(2005),
+ CriterionSatisfactionDAOTest.year(2003));
+ }
+
+ @Test
+ public void testSearchInInterval() throws Exception {
+ Criterion criterion = CriterionDAOTest.createValidCriterion();
+ criterionService.save(criterion);
+ Worker worker = new Worker("firstName", "surName", "2333232", 10);
+ resourceService.saveResource(worker);
+ CriterionSatisfaction criterionSatisfaction = new CriterionSatisfaction(
+ CriterionSatisfactionDAOTest.year(2000), criterion, worker);
+
+ criterionService.add(criterionSatisfaction);
+
+ assertEquals(1, criterionService.getResourcesSatisfying(criterion,
+ CriterionSatisfactionDAOTest.year(2001),
+ CriterionSatisfactionDAOTest.year(2005)).size());
+ assertEquals(0, criterionService.getResourcesSatisfying(criterion,
+ CriterionSatisfactionDAOTest.year(1999),
+ CriterionSatisfactionDAOTest.year(2005)).size());
+
+ CriterionSatisfaction otherSatisfaction = new CriterionSatisfaction(
+ CriterionSatisfactionDAOTest.year(1998), criterion, worker);
+ criterionService.add(otherSatisfaction);
+
+ assertEquals(1, criterionService.getResourcesSatisfying(criterion,
+ CriterionSatisfactionDAOTest.year(1999),
+ CriterionSatisfactionDAOTest.year(2005)).size());
+ }
+
+ @Test
+ public void testSearchResourcesForCriterionType() throws Exception {
+ Criterion criterion = CriterionDAOTest.createValidCriterion();
+ criterionService.save(criterion);
+ Worker worker = new Worker("firstName", "surName", "2333232", 10);
+ resourceService.saveResource(worker);
+ criterionService.add(new CriterionSatisfaction(
+ CriterionSatisfactionDAOTest.year(2000), criterion, worker));
+ criterionService.add(new CriterionSatisfaction(
+ CriterionSatisfactionDAOTest.year(1998), criterion, worker));
+
+ ICriterionType criterionType = ResourceTest
+ .createTypeThatMatches(criterion);
+
+ assertEquals(2, criterionService.getSatisfactionsFor(criterionType,
+ CriterionSatisfactionDAOTest.year(2001),
+ CriterionSatisfactionDAOTest.year(2005)).size());
+ assertEquals(1, criterionService.getSatisfactionsFor(criterionType,
+ CriterionSatisfactionDAOTest.year(1999),
+ CriterionSatisfactionDAOTest.year(2005)).size());
+ assertEquals(0, criterionService.getSatisfactionsFor(criterionType,
+ CriterionSatisfactionDAOTest.year(1997),
+ CriterionSatisfactionDAOTest.year(2005)).size());
+
+ criterionService.add(new CriterionSatisfaction(
+ CriterionSatisfactionDAOTest.year(1997), criterion, worker));
+ assertEquals(2, criterionService.getSatisfactionsFor(criterionType,
+ CriterionSatisfactionDAOTest.year(1999),
+ CriterionSatisfactionDAOTest.year(2005)).size());
+
+ }
+
+}
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 4a069103e..7b781b9d5 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
@@ -8,9 +8,11 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.navalplanner.business.common.exceptions.InstanceNotFoundException;
import org.navalplanner.business.resources.daos.IResourceDao;
+import org.navalplanner.business.resources.entities.ICriterion;
import org.navalplanner.business.resources.entities.Resource;
import org.navalplanner.business.resources.entities.Worker;
import org.navalplanner.business.resources.services.ResourceService;
+import org.navalplanner.business.test.resources.entities.CriterionTest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.annotation.NotTransactional;
import org.springframework.test.context.ContextConfiguration;
@@ -105,4 +107,27 @@ public class ResourceServiceTest {
}
}
+ public void testResourcesSatisfying() {
+ Worker worker1 = new Worker("worker-1", "worker-2-surname",
+ "11111111A", 8);
+ Worker worker2 = new Worker("worker-2", "worker-3-surname",
+ "22222222B", 6);
+ resourceService.saveResource(worker1);
+ resourceService.saveResource(worker2);
+ ICriterion firstCriterion = CriterionTest
+ .justThisResourcesCriterion(worker1);
+ ICriterion secondCriterion = CriterionTest
+ .justThisResourcesCriterion(worker2);
+ ICriterion bothCriterion = CriterionTest.justThisResourcesCriterion(
+ worker1, worker2);
+ assertEquals(1, resourceService.getSetOfResourcesSatisfying(
+ firstCriterion).size());
+ assertEquals(worker1, resourceService.getSetOfResourcesSatisfying(
+ firstCriterion).iterator().next());
+ assertEquals(1, resourceService.getSetOfResourcesSatisfying(
+ secondCriterion).size());
+ assertEquals(2, resourceService.getSetOfResourcesSatisfying(
+ bothCriterion).size());
+ }
+
}
diff --git a/navalplanner-business/src/test/resources/navalplanner-business-spring-config-test.xml b/navalplanner-business/src/test/resources/navalplanner-business-spring-config-test.xml
index 05d325e3e..982dbcde8 100644
--- a/navalplanner-business/src/test/resources/navalplanner-business-spring-config-test.xml
+++ b/navalplanner-business/src/test/resources/navalplanner-business-spring-config-test.xml
@@ -1,36 +1,37 @@
-
+
-
-
-
+ p:driverClassName="${jdbcDriver.className}" p:url="${testDataSource.url}"
+ p:username="${testDataSource.user}" p:password="${testDataSource.password}" />
+
+
+
-
-
+
+
- org/navalplanner/business/resources/entities/Resources.hbm.xml
+
+ org/navalplanner/business/resources/entities/Resources.hbm.xml
+
-
+
-
+