diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/users/daos/IProfileDAO.java b/navalplanner-business/src/main/java/org/navalplanner/business/users/daos/IProfileDAO.java index 6df31767b..d9891e377 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/users/daos/IProfileDAO.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/users/daos/IProfileDAO.java @@ -23,15 +23,19 @@ package org.navalplanner.business.users.daos; import org.navalplanner.business.common.daos.IGenericDAO; import org.navalplanner.business.common.exceptions.InstanceNotFoundException; +import org.navalplanner.business.common.exceptions.ValidationException; import org.navalplanner.business.users.entities.Profile; /** * DAO interface for the Profile entity. * * @author Jacobo Aragunde Perez + * @author Diego Pino García */ public interface IProfileDAO extends IGenericDAO{ + void checkIsReferencedByOtherEntities(Profile profile) throws ValidationException; + boolean existsByProfileName(String profileName); boolean existsByProfileNameAnotherTransaction(String profileName); diff --git a/navalplanner-business/src/main/java/org/navalplanner/business/users/daos/ProfileDAO.java b/navalplanner-business/src/main/java/org/navalplanner/business/users/daos/ProfileDAO.java index 3716ed921..c08e0709f 100644 --- a/navalplanner-business/src/main/java/org/navalplanner/business/users/daos/ProfileDAO.java +++ b/navalplanner-business/src/main/java/org/navalplanner/business/users/daos/ProfileDAO.java @@ -21,10 +21,14 @@ package org.navalplanner.business.users.daos; +import java.util.Collections; + import org.hibernate.Criteria; +import org.hibernate.Query; import org.hibernate.criterion.Restrictions; import org.navalplanner.business.common.daos.GenericDAOHibernate; import org.navalplanner.business.common.exceptions.InstanceNotFoundException; +import org.navalplanner.business.common.exceptions.ValidationException; import org.navalplanner.business.users.entities.Profile; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Propagation; @@ -34,6 +38,7 @@ import org.springframework.transaction.annotation.Transactional; * Hibernate DAO for the Profile entity. * * @author Jacobo Aragunde Perez + * @author Diego Pino García */ @Repository public class ProfileDAO extends GenericDAOHibernate implements @@ -80,4 +85,23 @@ public class ProfileDAO extends GenericDAOHibernate implements return findByProfileName(profileName); } + @Override + public void checkIsReferencedByOtherEntities(Profile profile) throws ValidationException { + checkHasUsers(profile); + } + + private void checkHasUsers(Profile profile) { + // Query against a collection of elements + // http://community.jboss.org/message/353859#353859 + Query query = getSession().createQuery( + "FROM User user JOIN user.profiles up WHERE up IN (:profiles)"); + query.setParameterList("profiles", Collections.singleton(profile)); + if (!query.list().isEmpty()) { + throw ValidationException + .invalidValue( + "Cannot delete profile. It is being used at this moment by some users.", + profile); + } + } + } diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/users/IProfileModel.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/users/IProfileModel.java index d156864e5..366f00ddc 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/users/IProfileModel.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/users/IProfileModel.java @@ -32,35 +32,25 @@ import org.navalplanner.business.users.entities.UserRole; * Model for UI operations related to {@link Profile} * * @author Jacobo Aragunde Perez + * @author Diego Pino García */ public interface IProfileModel { /** - * Makes some operations needed before edit a {@link Profile}. + * Adds a role to the current {@link Profile} * - * @param profile - * The object to be edited + * @param role {@link UserRole} element to be added */ - void initEdit(Profile profile); + void addRole(UserRole role); + + void checkIsReferencedByOtherEntities(Profile profile) throws ValidationException; /** - * Makes some operations needed before create a new {@link Profile}. + * Stores the removal of the passed {@link Profile} + * @param profile {@link Profile} element to be removed. + * @throws InstanceNotFoundException */ - void initCreate(); - - /** - * Get all {@link Profile} elements - * - * @return - */ - List getProfiles(); - - /** - * Gets the current {@link Profile}. - * - * @return A {@link Profile} - */ - Profile getProfile(); + void confirmRemove(Profile profile) throws InstanceNotFoundException; /** * Stores the current {@link Profile}. @@ -76,11 +66,37 @@ public interface IProfileModel { List getAllRoles(); /** - * Adds a role to the current {@link Profile} + * Gets the current {@link Profile}. * - * @param role {@link UserRole} element to be added + * @return A {@link Profile} */ - void addRole(UserRole role); + Profile getProfile(); + + /** + * Get all {@link Profile} elements + * + * @return + */ + List getProfiles(); + + /** + * Returns a list of the {@link UserRole} objects related with the current profile. + * @return a list of {@link UserRole} objects. + */ + List getRoles(); + + /** + * Makes some operations needed before create a new {@link Profile}. + */ + void initCreate(); + + /** + * Makes some operations needed before edit a {@link Profile}. + * + * @param profile + * The object to be edited + */ + void initEdit(Profile profile); /** * Removes a role from the current {@link Profile} @@ -97,17 +113,4 @@ public interface IProfileModel { * false otherwise. */ boolean roleBelongs(UserRole role); - - /** - * Stores the removal of the passed {@link Profile} - * @param profile {@link Profile} element to be removed. - * @throws InstanceNotFoundException - */ - void confirmRemove(Profile profile) throws InstanceNotFoundException; - - /** - * Returns a list of the {@link UserRole} objects related with the current profile. - * @return a list of {@link UserRole} objects. - */ - List getRoles(); } diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/users/ProfileCRUDController.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/users/ProfileCRUDController.java index 58731f069..b9128be80 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/users/ProfileCRUDController.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/users/ProfileCRUDController.java @@ -47,6 +47,7 @@ import org.zkoss.zul.api.Window; * Controller for CRUD actions over a {@link Profile} * * @author Jacobo Aragunde Perez + * @author Diego Pino García */ @SuppressWarnings("serial") public class ProfileCRUDController extends GenericForwardComposer implements @@ -176,22 +177,57 @@ public class ProfileCRUDController extends GenericForwardComposer implements } public void removeProfile(Profile profile) { - try { - int status = Messagebox.show(_("Confirm deleting this profile. Are you sure?"), _("Delete"), - Messagebox.OK | Messagebox.CANCEL, Messagebox.QUESTION); - if (Messagebox.OK == status) { - profileModel.confirmRemove(profile); + if (!isReferencedByOtherEntities(profile)) { + int result = showConfirmDeleteProfile(profile); + if (result == Messagebox.OK) { + try { + profileModel.confirmRemove(profile); + goToList(); + } catch (InstanceNotFoundException e) { + messagesForUser + .showMessage( + Level.ERROR, + _("Cannot delete profile: it does not exist anymore")); + LOG.error(_("Error removing element: ", profile.getId()), e); + } } - } catch (InterruptedException e) { - messagesForUser.showMessage( - Level.ERROR, e.getMessage()); - LOG.error(_("Error on showing removing element: ", profile.getId()), e); - } catch (InstanceNotFoundException e) { - messagesForUser.showMessage( - Level.ERROR, _("Cannot delete profile: it does not exist anymore")); - LOG.error(_("Error removing element: ", profile.getId()), e); } - goToList(); + } + + private boolean isReferencedByOtherEntities(Profile profile) { + try { + profileModel.checkIsReferencedByOtherEntities(profile); + return false; + } catch (ValidationException e) { + showCannotDeleteProfileDialog(e.getInvalidValue().getMessage(), + profile); + } + return true; + } + + private void showCannotDeleteProfileDialog(String message, Profile profile) { + try { + Messagebox.show(_(message), _("Warning"), Messagebox.OK, + Messagebox.EXCLAMATION); + } catch (InterruptedException e) { + LOG.error( + _("Error on showing warning message removing typeOfWorkHours: ", + profile.getId()), e); + } + } + + private int showConfirmDeleteProfile(Profile profile) { + try { + return Messagebox.show( + _("Confirm deleting this profile. Are you sure?"), + _("Delete"), Messagebox.OK | Messagebox.CANCEL, + Messagebox.QUESTION); + } catch (InterruptedException e) { + LOG.error( + _("Error on showing removing element: ", profile.getId()), + e); + } + return Messagebox.CANCEL; } private OnlyOneVisible getVisibility() { diff --git a/navalplanner-webapp/src/main/java/org/navalplanner/web/users/ProfileModel.java b/navalplanner-webapp/src/main/java/org/navalplanner/web/users/ProfileModel.java index 0b14170d1..3a36f22e1 100644 --- a/navalplanner-webapp/src/main/java/org/navalplanner/web/users/ProfileModel.java +++ b/navalplanner-webapp/src/main/java/org/navalplanner/web/users/ProfileModel.java @@ -40,6 +40,7 @@ import org.springframework.transaction.annotation.Transactional; * Model for UI operations related to {@link Profile} * * @author Jacobo Aragunde Perez + * @author Diego Pino García */ @Service @Scope(BeanDefinition.SCOPE_PROTOTYPE) @@ -137,4 +138,10 @@ public class ProfileModel implements IProfileModel { return list; } + @Override + @Transactional(readOnly = true) + public void checkIsReferencedByOtherEntities(Profile profile) throws ValidationException { + profileDAO.checkIsReferencedByOtherEntities(profile); + } + }