diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/costcategories/daos/CostCategoryDAO.java b/navalplanner-business/src/main/java/org/navalplanner/business/costcategories/daos/CostCategoryDAO.java index 8bccdfa18..746ea05f4 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/costcategories/daos/CostCategoryDAO.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/costcategories/daos/CostCategoryDAO.java @@ -27,6 +27,7 @@ import java.util.List; import org.apache.commons.lang.Validate; import org.hibernate.Criteria; +import org.hibernate.criterion.MatchMode; import org.hibernate.criterion.Restrictions; import org.joda.time.LocalDate; import org.navalplanner.business.common.daos.IntegrationEntityDAO; @@ -38,6 +39,7 @@ import org.navalplanner.business.resources.entities.Resource; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; /** @@ -113,4 +115,37 @@ public class CostCategoryDAO extends IntegrationEntityDAO return null; } + @Override + @Transactional(readOnly=true) + public CostCategory findByNameCaseInsensitive(String name) + throws InstanceNotFoundException { + Criteria c = getSession().createCriteria(CostCategory.class); + c.add(Restrictions.ilike("name", name, MatchMode.EXACT)); + CostCategory result = (CostCategory) c.uniqueResult(); + + if (result == null) { + throw new InstanceNotFoundException(name, + getEntityClass().getName()); + } + + return result; + } + + @Override + @Transactional(readOnly = true, propagation = Propagation.REQUIRES_NEW) + public boolean existsByNameInAnotherTransaction(String name) { + try { + findByNameCaseInsensitive(name); + } catch (InstanceNotFoundException e) { + return false; + } + return true; + } + + @Override + @Transactional(readOnly = true, propagation = Propagation.REQUIRES_NEW) + public CostCategory findUniqueByNameInAnotherTransaction(String name) + throws InstanceNotFoundException { + return findByNameCaseInsensitive(name); + } } diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/costcategories/daos/ICostCategoryDAO.java b/navalplanner-business/src/main/java/org/navalplanner/business/costcategories/daos/ICostCategoryDAO.java index 27df9c05b..7f5515a85 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/costcategories/daos/ICostCategoryDAO.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/costcategories/daos/ICostCategoryDAO.java @@ -35,7 +35,18 @@ public interface ICostCategoryDAO extends IIntegrationEntityDAO { List findActive(); - CostCategory findUniqueByName(String name) throws InstanceNotFoundException; + CostCategory findUniqueByNameInAnotherTransaction(String name) + throws InstanceNotFoundException; + + boolean existsByNameInAnotherTransaction(String name); + + CostCategory findByNameCaseInsensitive(String name) + throws InstanceNotFoundException; + + CostCategory findUniqueByCode(String code) + throws InstanceNotFoundException; + + CostCategory findUniqueByName(String name) + throws InstanceNotFoundException; - CostCategory findUniqueByCode(String code) throws InstanceNotFoundException; } 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 40c7f92ef..1ef5248d9 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 @@ -49,7 +49,6 @@ import org.navalplanner.business.costcategories.daos.ICostCategoryDAO; */ public class CostCategory extends IntegrationEntity implements IHumanIdentifiable { - @NotEmpty private String name; private boolean enabled = true; @@ -59,6 +58,8 @@ public class CostCategory extends IntegrationEntity implements IHumanIdentifiabl @Valid private Set hourCosts = new HashSet(); + private ICostCategoryDAO costCategoryDAO = Registry.getCostCategoryDAO(); + // Default constructor, needed by Hibernate protected CostCategory() { @@ -189,6 +190,7 @@ public class CostCategory extends IntegrationEntity implements IHumanIdentifiabl this.name = name; } + @NotEmpty(message = "name not specified") public String getName() { return name; } @@ -317,4 +319,25 @@ public class CostCategory extends IntegrationEntity implements IHumanIdentifiabl return name; } + @AssertTrue(message = "the cost category name has to be unique. It is already used") + public boolean checkConstraintUniqueName() { + if (StringUtils.isBlank(name)) { + return true; + } + if (isNewObject()) { + return !costCategoryDAO.existsByNameInAnotherTransaction(name); + } else { + return checkNotExistsOrIsTheSame(); + } + } + + private boolean checkNotExistsOrIsTheSame() { + try { + CostCategory costCategory = costCategoryDAO + .findUniqueByNameInAnotherTransaction(name); + return costCategory.getId().equals(getId()); + } catch (InstanceNotFoundException e) { + return true; + } + } } \ No newline at end of file