diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/common/exceptions/ValidationException.java b/navalplanner-business/src/main/java/org/navalplanner/business/common/exceptions/ValidationException.java
index ba470e723..b5e1b1671 100644
--- a/navalplanner-business/src/main/java/org/navalplanner/business/common/exceptions/ValidationException.java
+++ b/navalplanner-business/src/main/java/org/navalplanner/business/common/exceptions/ValidationException.java
@@ -28,6 +28,7 @@ import org.navalplanner.business.common.BaseEntity;
/**
* Encapsulates some validation failure
* @author Óscar González Fernández
+ * @author Diego Pino García
*/
public class ValidationException extends RuntimeException {
@@ -63,6 +64,12 @@ public class ValidationException extends RuntimeException {
return bean.toString();
}
+ public static ValidationException invalidValue(String message, Object value) {
+ InvalidValue invalidValue = new InvalidValue(message, null, "", value,
+ null);
+ return new ValidationException(invalidValue);
+ }
+
private InvalidValue[] invalidValues;
public InvalidValue[] getInvalidValues() {
diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/costcategories/entities/CostCategory.java b/navalplanner-business/src/main/java/org/navalplanner/business/costcategories/entities/CostCategory.java
index 3089e1c52..8f18bab12 100644
--- a/navalplanner-business/src/main/java/org/navalplanner/business/costcategories/entities/CostCategory.java
+++ b/navalplanner-business/src/main/java/org/navalplanner/business/costcategories/entities/CostCategory.java
@@ -45,6 +45,7 @@ import org.navalplanner.business.costcategories.daos.ICostCategoryDAO;
/**
* @author Jacobo Aragunde Perez
+ * @author Diego Pino García
*/
public class CostCategory extends IntegrationEntity {
@@ -91,6 +92,58 @@ public class CostCategory extends IntegrationEntity {
return (CostCategory) create(new CostCategory(name));
}
+ public static void validateHourCostsOverlap(Set hoursCosts)
+ throws ValidationException {
+ List listHourCosts = new ArrayList(hoursCosts);
+ for (int i = 0; i < listHourCosts.size(); i++) {
+ LocalDate initDate = listHourCosts.get(i).getInitDate();
+ LocalDate endDate = listHourCosts.get(i).getEndDate();
+ for (int j = i + 1; j < listHourCosts.size(); j++) {
+ HourCost listElement = listHourCosts.get(j);
+ if (listElement.getType() == null
+ || listHourCosts.get(i).getType() == null) {
+ // this is not exactly an overlapping but a
+ // problem with missing compulsory fields
+ throw ValidationException.invalidValue(
+ _("Hours cost type cannot be empty or null"),
+ listElement);
+ }
+ if (listElement.getType().getId()
+ .equals(listHourCosts.get(i).getType().getId())) {
+ if (initDate == null || listElement.getInitDate() == null) {
+ // this is not exactly an overlapping but a
+ // problem with missing compulsory fields
+ throw ValidationException.invalidValue(
+ _("Init date cannot be empty or null"),
+ listElement);
+ }
+ if (endDate == null && listElement.getEndDate() == null) {
+ throw ValidationException.invalidValue(
+ _("End date cannot be empty or null"),
+ listElement);
+ } else if ((endDate == null && listElement.getEndDate()
+ .compareTo(initDate) >= 0)
+ || (listElement.getEndDate() == null && listElement
+ .getInitDate().compareTo(endDate) <= 0)) {
+ throw ValidationException
+ .invalidValue(
+ _("Two hour costs with the same type overlap in time"),
+ listElement);
+ } else if ((endDate != null && listElement.getEndDate() != null)
+ && ((listElement.getEndDate().compareTo(initDate) >= 0 && listElement
+ .getEndDate().compareTo(endDate) <= 0) || (listElement
+ .getInitDate().compareTo(initDate) >= 0 && listElement
+ .getInitDate().compareTo(endDate) <= 0))) {
+ throw ValidationException
+ .invalidValue(
+ _("Two hour costs with the same type overlap in time"),
+ listElement);
+ }
+ }
+ }
+ }
+ }
+
protected CostCategory(String name) {
this.name = name;
}
@@ -173,42 +226,12 @@ public class CostCategory extends IntegrationEntity {
@AssertFalse(message="Two hour costs with the same type overlap in time")
public boolean checkHourCostsOverlap() {
- List listHourCosts = new ArrayList();
- listHourCosts.addAll(getHourCosts());
- for(int i=0; i=0) ||
- (listElement.getEndDate() == null && listElement.getInitDate().compareTo(endDate)<=0)) {
- return true;
- }
- else if((endDate != null && listElement.getEndDate() != null) &&
- ((listElement.getEndDate().compareTo(initDate)>=0 &&
- listElement.getEndDate().compareTo(endDate)<=0) ||
- (listElement.getInitDate().compareTo(initDate)>=0 &&
- listElement.getInitDate().compareTo(endDate)<=0))) {
- return true;
- }
- }
- }
+ try {
+ validateHourCostsOverlap(getHourCosts());
+ return false;
+ } catch (ValidationException e) {
+ return true;
}
- return false;
}
@Override
diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/costcategories/CostCategoryCRUDController.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/costcategories/CostCategoryCRUDController.java
index bc9040cd9..cbf0a051a 100644
--- a/navalplanner-webapp/src/main/java/org/navalplanner/web/costcategories/CostCategoryCRUDController.java
+++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/costcategories/CostCategoryCRUDController.java
@@ -31,6 +31,7 @@ import java.util.List;
import java.util.Set;
import org.apache.commons.logging.LogFactory;
+import org.hibernate.validator.InvalidValue;
import org.joda.time.LocalDate;
import org.navalplanner.business.common.exceptions.InstanceNotFoundException;
import org.navalplanner.business.common.exceptions.ValidationException;
@@ -45,7 +46,9 @@ import org.navalplanner.web.common.OnlyOneVisible;
import org.navalplanner.web.common.Util;
import org.navalplanner.web.common.components.Autocomplete;
import org.navalplanner.web.workreports.WorkReportCRUDController;
+import org.zkoss.ganttz.util.ComponentsFinder;
import org.zkoss.zk.ui.Component;
+import org.zkoss.zk.ui.WrongValueException;
import org.zkoss.zk.ui.event.CheckEvent;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
@@ -68,6 +71,7 @@ import org.zkoss.zul.api.Window;
* Controller for CRUD actions over a {@link CostCategory}
*
* @author Jacobo Aragunde Perez
+ * @author Diego Pino García
*/
@SuppressWarnings("serial")
public class CostCategoryCRUDController extends GenericForwardComposer
@@ -164,20 +168,36 @@ public class CostCategoryCRUDController extends GenericForwardComposer
}
public boolean save() {
- if(!ConstraintChecker.isValid(createWindow)) {
+ if (!ConstraintChecker.isValid(createWindow)) {
return false;
}
+
+ try {
+ costCategoryModel.validateHourCostsOverlap();
+ } catch (ValidationException e) {
+ showHoursCostsOverlapValidationException(e);
+ }
+
try {
costCategoryModel.confirmSave();
- messagesForUser.showMessage(Level.INFO,
- _("Cost category saved"));
+ messagesForUser.showMessage(Level.INFO, _("Cost category saved"));
return true;
} catch (ValidationException e) {
+ e.getInvalidValue().getValue();
messagesForUser.showInvalidValues(e);
}
return false;
}
+ private void showHoursCostsOverlapValidationException(ValidationException e) {
+ InvalidValue invalid = e.getInvalidValue();
+ Row comp = ComponentsFinder.findRowByValue(listHourCosts,
+ invalid.getValue());
+ if (comp != null) {
+ throw new WrongValueException(comp, invalid.getMessage());
+ }
+ }
+
public CostCategory getCostCategory() {
return costCategoryModel.getCostCategory();
}
diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/costcategories/CostCategoryModel.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/costcategories/CostCategoryModel.java
index 657677a32..57150a9a7 100644
--- a/navalplanner-webapp/src/main/java/org/navalplanner/web/costcategories/CostCategoryModel.java
+++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/costcategories/CostCategoryModel.java
@@ -47,6 +47,7 @@ import org.springframework.transaction.annotation.Transactional;
* Model for UI operations related to {@link CostCategory}
*
* @author Jacobo Aragunde Perez
+ * @author Diego Pino García
*/
@Service
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
@@ -181,4 +182,9 @@ public class CostCategoryModel extends IntegrationEntityModel implements
public IntegrationEntity getCurrentEntity() {
return this.costCategory;
}
-}
+
+ @Override
+ public void validateHourCostsOverlap() throws ValidationException {
+ CostCategory.validateHourCostsOverlap(getCostCategory().getHourCosts());
+ }
+}
\ No newline at end of file
diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/costcategories/ICostCategoryModel.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/costcategories/ICostCategoryModel.java
index d35b60db5..cacef385d 100644
--- a/navalplanner-webapp/src/main/java/org/navalplanner/web/costcategories/ICostCategoryModel.java
+++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/costcategories/ICostCategoryModel.java
@@ -34,6 +34,7 @@ import org.navalplanner.web.common.IIntegrationEntityModel;
* Model for UI operations related to {@link CostCategory}
*
* @author Jacobo Aragunde Perez
+ * @author Diego Pino García
*/
public interface ICostCategoryModel extends IIntegrationEntityModel {
@@ -62,4 +63,7 @@ public interface ICostCategoryModel extends IIntegrationEntityModel {
throws InstanceNotFoundException;
boolean canRemoveCostCategory(CostCategory category);
-}
+
+ void validateHourCostsOverlap() throws ValidationException;
+
+}
\ No newline at end of file