de.iteratec.iteraplan.businesslogic.service.UserServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for de.iteratec.iteraplan.businesslogic.service.UserServiceImpl.java

Source

/*
 * iteraplan is an IT Governance web application developed by iteratec, GmbH
 * Copyright (C) 2004 - 2014 iteratec, GmbH
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License version 3 as published by
 * the Free Software Foundation with the addition of the following permission
 * added to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED
 * WORK IN WHICH THE COPYRIGHT IS OWNED BY ITERATEC, ITERATEC DISCLAIMS THE
 * WARRANTY OF NON INFRINGEMENT  OF THIRD PARTY RIGHTS.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, see http://www.gnu.org/licenses or write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02110-1301 USA.
 *
 * You can contact iteratec GmbH headquarters at Inselkammerstr. 4
 * 82008 Munich - Unterhaching, Germany, or at email address info@iteratec.de.
 *
 * The interactive user interfaces in modified source and object code versions
 * of this program must display Appropriate Legal Notices, as required under
 * Section 5 of the GNU Affero General Public License version 3.
 *
 * In accordance with Section 7(b) of the GNU Affero General Public License
 * version 3, these Appropriate Legal Notices must retain the display of the
 * "iteraplan" logo. If the display of the logo is not reasonably
 * feasible for technical reasons, the Appropriate Legal Notices must display
 * the words "Powered by iteraplan".
 */
package de.iteratec.iteraplan.businesslogic.service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.springframework.stereotype.Repository;
import org.springframework.stereotype.Service;

import de.iteratec.hibernate.criterion.IteraplanLikeExpression;
import de.iteratec.iteraplan.common.GeneralHelper;
import de.iteratec.iteraplan.common.UserContext;
import de.iteratec.iteraplan.common.error.IteraplanBusinessException;
import de.iteratec.iteraplan.common.error.IteraplanErrorMessages;
import de.iteratec.iteraplan.model.BuildingBlock;
import de.iteratec.iteraplan.model.BuildingBlockType;
import de.iteratec.iteraplan.model.attribute.AttributeType;
import de.iteratec.iteraplan.model.sorting.BuildingBlockComparator;
import de.iteratec.iteraplan.model.sorting.UserEntityIntComparator;
import de.iteratec.iteraplan.model.user.TypeOfFunctionalPermission;
import de.iteratec.iteraplan.model.user.User;
import de.iteratec.iteraplan.model.user.UserEntity;
import de.iteratec.iteraplan.model.user.UserGroup;
import de.iteratec.iteraplan.persistence.dao.AttributeTypeDAO;
import de.iteratec.iteraplan.persistence.dao.BuildingBlockTypeDAO;
import de.iteratec.iteraplan.persistence.dao.DAOTemplate;
import de.iteratec.iteraplan.persistence.dao.GeneralBuildingBlockDAO;
import de.iteratec.iteraplan.persistence.dao.UserDAO;
import de.iteratec.iteraplan.persistence.util.SqlHqlStringUtils;

/**
 * A {@link UserService} implementation for retrieving, creating and deleting the {@link User} entities.
 */
@Service("userService")
@Repository
public class UserServiceImpl extends AbstractEntityService<User, Integer> implements UserService {

    private AttributeTypeDAO attributeTypeDAO;
    private UserDAO userDAO;
    private GeneralBuildingBlockDAO generalBuildingBlockDAO;
    private BuildingBlockTypeDAO buildingBlockTypeDAO;
    private UserEntityService userEntityService;

    /** {@inheritDoc}. */
    @Override
    public void deleteEntity(User userToDelete) {
        UserContext.getCurrentPerms().assureFunctionalPermission(TypeOfFunctionalPermission.USER);
        User currentUser = UserContext.getCurrentUserContext().getUser();

        Integer userId = userToDelete.getId();
        if (userId == null) {
            throw new IllegalArgumentException("An ID equal to null is not allowed for deletion.");
        }

        User user = userDAO.loadObjectById(userId);
        // The currently logged in user cannot be deleted.
        if ((currentUser != null) && currentUser.getLoginName().equals(user.getLoginName())) {
            throw new IteraplanBusinessException(IteraplanErrorMessages.CANNOT_DELETE_CURRENTLY_LOGGED_IN_USER);
        }

        // Check, if the user is referenced through an attribute of type responsibility.
        List<AttributeType> list = attributeTypeDAO.getResponsibilityAttributeTypesReferencingUserEntityID(userId);

        if (list.size() > 0) {
            StringBuilder attributes = new StringBuilder();
            for (Iterator<AttributeType> iter = list.iterator(); iter.hasNext();) {
                AttributeType at = iter.next();
                attributes.append(at.getName());
                if (iter.hasNext()) {
                    attributes.append(", ");
                }
            }

            throw new IteraplanBusinessException(IteraplanErrorMessages.USER_REFERENCED_BY_ATTRIBUTE,
                    user.getFirstName() + " " + user.getLastName(), attributes.toString());
        }

        // Remove references to owned building blocks. This is usually done in the corresponding DAO,
        // but the iteraplan architecture denies accessing services from the DAO layer.
        List<BuildingBlock> owned = userEntityService.loadOwnedBuildingBlocks(user, false);
        user.removeOwnedBuildingBlocks(owned);

        List<BuildingBlock> subscribedBbs = loadSubscribedBuildingBlocks(user);
        List<BuildingBlockType> subscribedBbts = loadSubscribedBuildingBlockTypes(user);
        user.removeSubscriptions(subscribedBbs, subscribedBbts);

        userDAO.delete(user);
    }

    /**
     * Loads and returns a {@code List} of {@link BuildingBlock}s for which the specified
     * {@link User} has a subscription. If the given user has not yet been persisted an
     * empty {@code List} is returned. The {@code List} is sorted
     * by the building block's internationalized type string and their identity string.
     * 
     * @param user
     *          The user for which owned building blocks shall be returned.
     * @return See method description.
     */
    private List<BuildingBlock> loadSubscribedBuildingBlocks(User user) {
        // Load the list of owned building block IDs for the complete hierarchy of user entities.
        List<Integer> identifiers = userDAO.loadSubscribedBuildingBlockIDs(user.getId());

        // Load the building blocks itself. Due to the current ORM strategy in iteraplan the objects
        // MUST be loaded separately by mapped class. If the base class was used, a database join too
        // big for MySQL would be generated.
        List<BuildingBlock> subscribed = generalBuildingBlockDAO.loadBuildingBlocks(identifiers);
        Collections.sort(subscribed, new BuildingBlockComparator());

        return subscribed;
    }

    /**
     * Loads and returns a {@code List} of {@link BuildingBlockType}s for which the specified
     * {@link User} has a subscription. If the given user has not yet been persisted an
     * empty {@code List} is returned. The {@code List} is sorted
     * by the building block type's internationalized type string and their identity string.
     * 
     * @param user
     *          The user for which owned building blocks shall be returned.
     * @return See method description.
     */
    private List<BuildingBlockType> loadSubscribedBuildingBlockTypes(User user) {
        // Load the list of owned building block IDs for the complete hierarchy of user entities.
        List<Integer> identifiers = userDAO.loadSubscribedBuildingBlockTypeIDs(user.getId());

        // Load the building blocks itself. Due to the current ORM strategy in iteraplan the objects
        // MUST be loaded separately by mapped class. If the base class was used, a database join too
        // big for MySQL would be generated.
        List<BuildingBlockType> subscribed = buildingBlockTypeDAO
                .loadElementListWithIds(new HashSet<Integer>(identifiers));

        return subscribed;
    }

    /** {@inheritDoc}. */
    public List<UserEntity> getAggregatedOwningUserEntities(List<UserEntity> owningUserEntities) {
        Set<UserEntity> aggregatedOwningUserEntitiesSet = new HashSet<UserEntity>();
        findAggregatedOwningUserEntities(new HashSet<UserEntity>(owningUserEntities),
                aggregatedOwningUserEntitiesSet);
        List<UserEntity> aggregatedOwningUserEntitiesList = new ArrayList<UserEntity>(
                aggregatedOwningUserEntitiesSet);
        Collections.sort(aggregatedOwningUserEntitiesList, new UserEntityIntComparator());

        return aggregatedOwningUserEntitiesList;
    }

    /** {@inheritDoc}. */
    public List<UserEntity> getAllUserEntitiesFiltered(Set<Integer> userEntityIdsToExclude) {
        return userDAO.getAllUserEntitiesFiltered(null, userEntityIdsToExclude);
    }

    /** {@inheritDoc}. */
    public User getUserByLoginIfExists(String loginName) {
        return userDAO.getUserByLoginIfExists(loginName);
    }

    /** {@inheritDoc}. */
    public List<User> getUsersFiltered(Integer id, List<User> elementsToExclude) {
        Set<Integer> set = GeneralHelper.createIdSetFromIdEntities(elementsToExclude);
        List<User> list = userDAO.loadFilteredElementList("loginName", set);

        // add given user group
        if (id != null) {
            User user = userDAO.loadObjectById(id);
            if ((user != null) && !list.contains(user)) {
                list.add(user);
            }
        }

        Collections.sort(list);

        return list;
    }

    private void findAggregatedOwningUserEntities(Set<UserEntity> owningUserEntities,
            Set<UserEntity> aggregatedOwningUserEntitiesSet) {
        for (UserEntity ue : owningUserEntities) {
            aggregatedOwningUserEntitiesSet.add(ue);
            if (ue instanceof UserGroup) {
                UserGroup ug = (UserGroup) ue;
                findAggregatedOwningUserEntities(ug.getMembers(), aggregatedOwningUserEntitiesSet);
            }
        }
    }

    /** {@inheritDoc}. */
    @Override
    protected DAOTemplate<User, Integer> getDao() {
        return this.userDAO;
    }

    /** {@inheritDoc}. */
    public List<User> getUserBySearch(User user) {
        //FIXME push this down into DAO and additionally escape T-SQL control characters within like criteria 
        DetachedCriteria crit = DetachedCriteria.forClass(User.class);

        if (user != null) {
            if (!StringUtils.isEmpty(user.getFirstName())) {
                String sqlSearchTerm = SqlHqlStringUtils.processGuiFilterForSql(user.getFirstName());
                crit.add(new IteraplanLikeExpression("firstName", sqlSearchTerm, true));
            }

            if (!StringUtils.isEmpty(user.getLastName())) {
                String sqlSearchTerm = SqlHqlStringUtils.processGuiFilterForSql(user.getLastName());
                crit.add(new IteraplanLikeExpression("lastName", sqlSearchTerm, true));
            }
        }
        crit.addOrder(Order.asc("lastName"));
        // don't add order constraint to count criteria!

        return this.userDAO.findByCriteria(crit);
    }

    /** {@inheritDoc} */
    public User createUser(String loginName) {
        // name should not be null / empty
        if (StringUtils.isBlank(loginName)) {
            throw new IteraplanBusinessException(IteraplanErrorMessages.NAME_CANNOT_BE_EMPTY);
        }

        User user = new User();
        user.setLoginName(loginName);
        user.setFirstName(loginName);
        user.setLastName(loginName);
        user.validate();

        // check if an entity with the same name already exists
        if (doesObjectWithDifferentIdExist(null, loginName)) {
            throw new IteraplanBusinessException(IteraplanErrorMessages.DUPLICATE_ENTRY, loginName);
        }

        return saveOrUpdate(user);
    }

    public void setAttributeTypeDAO(AttributeTypeDAO attributeTypeDAO) {
        this.attributeTypeDAO = attributeTypeDAO;
    }

    public void setUserDAO(UserDAO userDAO) {
        this.userDAO = userDAO;
    }

    public void setGeneralBuildingBlockDAO(GeneralBuildingBlockDAO generalBuildingBlockDAO) {
        this.generalBuildingBlockDAO = generalBuildingBlockDAO;
    }

    public void setBuildingBlockTypeDAO(BuildingBlockTypeDAO buildingBlockTypeDAO) {
        this.buildingBlockTypeDAO = buildingBlockTypeDAO;
    }

    public void setUserEntityService(UserEntityService userEntityService) {
        this.userEntityService = userEntityService;
    }
}