no.abmu.user.service.UserServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for no.abmu.user.service.UserServiceImpl.java

Source

/*$Id: UserServiceImpl.java 15657 2010-10-12 06:20:13Z jens $*/
/*
 ****************************************************************************
 *                                                                          *
 *                   (c) Copyright 2005 ABM-utvikling                        *
 *                                                                          *
 *                         Created on 12-Jan-2005                           *
 *                                                                          *
 * This program is free software; you can redistribute it and/or modify it  *
 * under the terms of the GNU General Public License as published by the    *
 * Free Software Foundation; either version 2 of the License, or (at your   *
 * option) any later version.                                               *
 *                                                                          *
 * 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. http://www.gnu.org/licenses/gpl.html    *
 *                                                                          *
 ****************************************************************************
 */

package no.abmu.user.service;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

import net.sf.acegisecurity.providers.dao.UserCache;
import no.abmu.common.acegisecurity.SecurityContext;
import no.abmu.common.browsing.OrganisationUnitForBrowsing;
import no.abmu.common.jasperreports.SchemaList;
import no.abmu.common.persistence.FinderSpecification;
import no.abmu.common.reporting.OrgUnitReport;
import no.abmu.common.reporting.OrgUnitReportCountyAndNameComparator;
import no.abmu.common.reporting.PostalAddressReport;
import no.abmu.organisationregister.domain.OrganisationTypeNameConst;
import no.abmu.organisationregister.domain.OrganisationUnit;
import no.abmu.organisationregister.finders.organisationunit.OrgUnitBrowseFinderSpecification;
import no.abmu.organisationregister.finders.organisationunit.OrgUnitFinderSpecificationBean;
import no.abmu.organisationregister.finders.organisationunit.OrgUnitQueryFinderSpecification;
import no.abmu.organisationregister.finders.organisationunit.PostalAddressFinderSpecification;
import no.abmu.organisationregister.service.OrganisationUnitService;
import no.abmu.user.domain.ContactInfo;
import no.abmu.user.domain.GroupOrgUnitMapping;
import no.abmu.user.domain.Principal;
import no.abmu.user.domain.Role;
import no.abmu.user.domain.RoleRelation;
import no.abmu.user.domain.User;
import no.abmu.user.domain.UserGroup;
import no.abmu.user.domain.UserRoleNameConst;
import no.abmu.user.finders.role.RoleFinderSpecification;
import no.abmu.user.finders.rolerelation.RoleRelationFinderSpecification;
import no.abmu.user.finders.user.UserFinderSpecification;
import no.abmu.user.finders.usergroup.UserGroupFinderSpecification;
import no.abmu.user.util.RoleRelationUtil;
import no.abmu.user.util.UserUtil;
import no.abmu.util.date.DateUtil;
import no.abmu.util.test.Assert;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StopWatch;

/**
 * UserServiceImpl.
 * 
 * @author Erik Romson, erik@zenior.no
 * @author $Author: jens $
 * @version $Rev: 15657 $
 * @date $Date: 2010-10-12 08:20:13 +0200 (Tue, 12 Oct 2010) $
 * copyright ABM-utvikling
 * @since 2005.01.12
 * @spring.bean id="userServiceImpl"
 * @spring.property ref="userDaoImpl"
 * name="securityDao"
 * @spring.property ref="reportingDeadlineService"
 * name="reportingDeadlineService"
 */
@Transactional(propagation = Propagation.REQUIRED, value = "securityTransactionManager")
public class UserServiceImpl extends BaseServiceImpl implements UserService {

    private static final Log logger = (Log) LogFactory.getLog(UserServiceImpl.class);

    private ReportingDeadlineService reportingDeadlineService;
    private OrganisationUnitService organisationUnitService;
    private SecurityContext securityContext;
    private UserCache userCache;

    public void setReportingDeadlineService(ReportingDeadlineService reportingDeadlineService) {
        this.reportingDeadlineService = reportingDeadlineService;
    }

    public void setOrganisationUnitService(OrganisationUnitService organisationUnitService) {
        this.organisationUnitService = organisationUnitService;
    }

    public void setSecurityContext(SecurityContext securityContext) {
        this.securityContext = securityContext;
    }

    public SecurityContext getSecurityContext() {
        return securityContext;
    }

    public UserCache getUserCache() {
        return userCache;
    }

    public void setUserCache(UserCache userCache) {
        this.userCache = userCache;
    }

    public Collection find(FinderSpecification finderSpecification) {
        return userDao.find(finderSpecification);
    }

    public Object findSingle(FinderSpecification finderSpecification) {
        return userDao.findSingle(finderSpecification);
    }

    public String getUserName(User user) {
        userDao.reattach(user);
        String userName = user.getName();
        return userName;
    }

    /**
     * Creates the specified user. The user will be added to the first found UserGroup
     * of the specified organisationUnit. A new UserGroup will be created if the
     * organisationUnit does not have a UserGroup.
     *
     * @param user
     * @param organisationUnit
     * @return
     */
    public User createUser(User user, OrganisationUnit organisationUnit) {
        UserGroup userGroup;
        List<UserGroup> userGroups;
        GroupOrgUnitMapping groupOrgUnitMapping = null;

        /* Validate the input */
        Collection users = find(new UserFinderSpecification(user.getName()));
        if (users.size() > 0) {
            logger.error("Can't create user, username '" + user.getName() + "' already in use.");
            return null;
        }

        userGroups = userDao.getUserGroupsByOrganisationId(organisationUnit.getId());

        if (userGroups == null || userGroups.isEmpty()) {
            userGroup = new UserGroup("group" + organisationUnit.getId());
            groupOrgUnitMapping = new GroupOrgUnitMapping(userGroup, organisationUnit.getId());

        } else {
            userGroup = (UserGroup) userGroups.get(0);
        }

        store(user);

        if (userGroup != null) {
            userGroup.addPrincipalChildren(user);
            store(userGroup);
        }

        if (groupOrgUnitMapping != null) {
            store(groupOrgUnitMapping);
        }

        return user;
    }

    public void createNewUserForOrganisationUnit(OrganisationUnit organisationUnit) {
        Assert.checkRequiredArgument("organisationUnit", organisationUnit);

        // Getting existence userGroup
        List<UserGroup> userGroups = userDao.getUserGroupsByOrganisationId(organisationUnit.getId());
        if (userGroups == null || userGroups.isEmpty()) {
            // No user group exist exit
            logger.warn("Abort registration of new user, no user group exist for orgUnit: " + organisationUnit);
            return;
        }
        UserGroup userGroup = userGroups.get(0);

        //a null name will set the user name to the same as the user id
        User user = new User(null, UserUtil.generatePassword());

        ContactInfo contactInfo = new ContactInfo();
        Object obj = organisationUnit.getName() != null ? organisationUnit.getName().getDefault() : "unknown";
        String str = obj == null ? "noname" : obj.toString();
        contactInfo.setLastName(str);
        user.setContactInfo(contactInfo);

        /* Tag this user, to enable sql to turn off of the enabled flag later on */
        user.setTemporaryUser(true);
        store(user);
        userGroup.addPrincipalChildren(user);
        store(userGroup);
    }

    /**
     * Creates a user and a user group for the specified organisation.
     * 
     * @param organisationUnit
     * @param roles
     * @param temporaryUser flag indicating that the user should be marked as temporary.
     * @return
     */
    private User createUserFromOrganisationUnit(OrganisationUnit organisationUnit, Set<RoleRelation> roles,
            boolean temporaryUser) {

        UserGroup userGroup = new UserGroup("group" + organisationUnit.getId());
        //a null name will set the user name to the same as the user id
        User user = new User(null, UserUtil.generatePassword());

        ContactInfo contactInfo = new ContactInfo();
        Object obj = organisationUnit.getName() != null ? organisationUnit.getName().getDefault() : "unknown";
        String str = obj == null ? "noname" : obj.toString();
        contactInfo.setLastName(str);
        user.setContactInfo(contactInfo);

        /* Tag this user, to enable sql to turn off of the enabled flag later on */
        user.setTemporaryUser(true);

        if (roles != null) {
            user.addRoles(roles);
        }
        store(user);
        userGroup.addPrincipalChildren(user);
        store(userGroup);

        GroupOrgUnitMapping mapping = new GroupOrgUnitMapping(userGroup, organisationUnit.getId());
        store(mapping);
        return user;
    }

    public Collection<Role> getAllRoles() {

        RoleFinderSpecification finderSpecification = new RoleFinderSpecification();
        Collection<Role> roles = find(finderSpecification);
        return roles;
    }

    public UserGroup getEditableMarkedUserGroup(Long organisationUnitId) {

        UserGroupFinderSpecification finderSpecification = new UserGroupFinderSpecification();
        finderSpecification.setOrganisationUnitId(organisationUnitId);
        Collection<UserGroup> userGroups = find(finderSpecification);

        if (userGroups.size() == 0) {
            String errorMessage = "[getEditableMarkedUserGroup] OrganisationUnit with Id= '" + organisationUnitId
                    + "' has no user.";
            logger.error(errorMessage);
            throw new IllegalArgumentException(errorMessage);
        }

        if (userGroups.size() > 1) {
            String errorMessage = "[getEditableMarkedUserGroup] OrganisationUnit with Id= '" + organisationUnitId
                    + "' has '" + userGroups.size() + " userGroups.";
            logger.error(errorMessage);
            throw new IllegalStateException(errorMessage);
        }

        UserGroup userGroup = userGroups.iterator().next();
        List<Principal> principals = userGroup.getPrincipalChildren();
        for (Principal principal : principals) {
            RoleRelationUtil.decideAndSetEditableRoleRelation(securityContext, principal);
        }

        return userGroup;
    }

    /**
     * Returns the Role having the specified name.
     * Of the role does not exist, the Role will be created.
     * If more than on role that role name exists the first 
     * matching role will be returned.
     *
     * @param roleName
     * @return
     */
    private Role findOrAddRoleByName(String roleName) {
        Role role;

        Collection<Role> roles = find(new RoleFinderSpecification(roleName));

        if (roles.size() == 0) {
            role = new Role(roleName);
            userDao.saveOrUpdate(role);
        } else if (roles.size() > 1) {
            // Should this be an error and throwing an exceptions ???
            logger.warn("There are more than one role with roleName '" + roleName + "'");
            role = roles.iterator().next();
        } else {
            role = roles.iterator().next();
        }
        return role;
    }

    private Set<Role> getUserAndRegistratorRolesForOrganisationType(String organisationTypeName) {
        if (logger.isDebugEnabled()) {
            logger.debug("Executing Set<Role> getUserAndRegistratorRolesForOrganisationType, "
                    + "with organisationTypeName='" + organisationTypeName + "'");
        }
        Assert.checkRequiredArgument("organisationTypeName", organisationTypeName);

        HashSet<Role> roles = new HashSet<Role>();

        /* All users should have this */
        roles.add(findOrAddRoleByName(UserRoleNameConst.ROLE_ABMSTATISTIKK_USER));

        if (organisationTypeName == OrganisationTypeNameConst.ARCHIVE) {
            roles.add(findOrAddRoleByName(UserRoleNameConst.ROLE_ARCHIVE_USER));
            roles.add(findOrAddRoleByName(UserRoleNameConst.ROLE_ARCHIVE_REGISTRATOR));
            return roles;
        }
        if (organisationTypeName == OrganisationTypeNameConst.FYLKES_LIBRARY) {
            roles.add(findOrAddRoleByName(UserRoleNameConst.ROLE_FOLKEBIB_FYLKESBIB_REGISTRATOR));
            roles.add(findOrAddRoleByName(UserRoleNameConst.ROLE_FOLKEBIB_FOLKEBIB_REGISTRATOR));
            roles.add(findOrAddRoleByName(UserRoleNameConst.ROLE_FOLKEBIB_GRUNNSKOLE_REGISTRATOR));
            roles.add(findOrAddRoleByName(UserRoleNameConst.ROLE_FOLKEBIB_VIDEREGAENDE_SKOLE_REGISTRATOR));
            roles.add(findOrAddRoleByName(UserRoleNameConst.ROLE_FOLKEBIB_MOBIL_REGISTRATOR));
            roles.add(findOrAddRoleByName(UserRoleNameConst.ROLE_FOLKEBIB_KOMMUNE_REGISTRATOR));
            roles.add(findOrAddRoleByName(UserRoleNameConst.ROLE_FOLKEBIB_FYLKESKOMMUNE_REGISTRATOR));
            return roles;
        }

        if (organisationTypeName == OrganisationTypeNameConst.KOMMUNE) {
            roles.add(findOrAddRoleByName(UserRoleNameConst.ROLE_FOLKEBIB_KOMMUNE_REGISTRATOR));
            roles.add(findOrAddRoleByName(UserRoleNameConst.ROLE_FOLKEBIB_GRUNNSKOLE_REGISTRATOR));
            return roles;
        }

        if (organisationTypeName == OrganisationTypeNameConst.FYLKE) {
            roles.add(findOrAddRoleByName(UserRoleNameConst.ROLE_FOLKEBIB_FYLKESKOMMUNE_REGISTRATOR));
            roles.add(findOrAddRoleByName(UserRoleNameConst.ROLE_FOLKEBIB_VIDEREGAENDE_SKOLE_REGISTRATOR));
            return roles;
        }

        if (organisationTypeName == OrganisationTypeNameConst.PUBLIC_LIBRARY
                || organisationTypeName == OrganisationTypeNameConst.FOLKEBIBLIOTEK_SVALBARD) {
            roles.add(findOrAddRoleByName(UserRoleNameConst.ROLE_FOLKEBIB_FOLKEBIB_REGISTRATOR));
            //            roles.add(findOrAddRoleByName(UserRoleNameConst.ROLE_FOLKEBIB_MOBIL_REGISTRATOR));
            return roles;
        }

        if (organisationTypeName == OrganisationTypeNameConst.FAG_LIBRARY
                || organisationTypeName == OrganisationTypeNameConst.NATIONAL_LIBRARY
                || organisationTypeName == OrganisationTypeNameConst.UNIVERITY_OF_OSLO
                || organisationTypeName == OrganisationTypeNameConst.UNIVERITY_OF_BERGEN
                || organisationTypeName == OrganisationTypeNameConst.UNIVERITY_OF_TRONDHEIM
                || organisationTypeName == OrganisationTypeNameConst.UNIVERITY_OF_TROMSOE
                || organisationTypeName == OrganisationTypeNameConst.SPECIALISED_UNIVERISTY_LIBRARY
                || organisationTypeName == OrganisationTypeNameConst.PUBLIC_COLLEGE_LIBRARY
                || organisationTypeName == OrganisationTypeNameConst.PRIVATE_COLLEGE_LIBRARY
                || organisationTypeName == OrganisationTypeNameConst.PUBLIC_SPECIAL_LIBRARY
                || organisationTypeName == OrganisationTypeNameConst.PRIVATE_SPECIAL_LIBRARY
                || organisationTypeName == OrganisationTypeNameConst.FAG_BIBLIOTEK_LEVEL_1
                || organisationTypeName == OrganisationTypeNameConst.FAG_BIBLIOTEK_LEVEL_2
                || organisationTypeName == OrganisationTypeNameConst.FAG_BIBLIOTEK_LEVEL_3) {
            roles.add(findOrAddRoleByName(UserRoleNameConst.ROLE_FAGBIB_REGISTRATOR));
            return roles;
        }

        if (organisationTypeName == OrganisationTypeNameConst.REPORTINGMUSEUM) {
            roles.add(findOrAddRoleByName(UserRoleNameConst.ROLE_REPORTING_MUSEUM_REGISTRATOR));
            roles.add(findOrAddRoleByName(UserRoleNameConst.ROLE_KKD_FINANCE_APPLICATION_REGISTRATOR));
            return roles;
        }

        if (organisationTypeName == OrganisationTypeNameConst.MUSEUM) {
            roles.add(findOrAddRoleByName(UserRoleNameConst.ROLE_MUSEUM_REGISTRATOR));
            return roles;
        }

        if (organisationTypeName == OrganisationTypeNameConst.HIGH_SCHOOL_LIBRARY) {
            roles.add(findOrAddRoleByName(UserRoleNameConst.ROLE_FOLKEBIB_VIDEREGAENDE_SKOLE_REGISTRATOR));
            return roles;
        }
        if (organisationTypeName == OrganisationTypeNameConst.HOSPITAL_LIBRARY) {
            roles.add(findOrAddRoleByName(UserRoleNameConst.ROLE_FOLKEBIB_PASIENT_REGISTRATOR));
            return roles;
        }

        if (organisationTypeName == OrganisationTypeNameConst.PRISON_LIBRARY) {
            roles.add(findOrAddRoleByName(UserRoleNameConst.ROLE_FOLKEBIB_FENGSEL_REGISTRATOR));
            return roles;
        }
        if (organisationTypeName == OrganisationTypeNameConst.MOBILE_LIBRARY) {
            roles.add(findOrAddRoleByName(UserRoleNameConst.ROLE_FOLKEBIB_MOBIL_REGISTRATOR));
            return roles;
        }

        if (organisationTypeName == OrganisationTypeNameConst.PRIMARY_SCHOOL_LIBRARY
                || organisationTypeName == OrganisationTypeNameConst.GRUNNSKOLEBIBLIOTEK_SVALBARD) {
            roles.add(findOrAddRoleByName(UserRoleNameConst.ROLE_FOLKEBIB_GRUNNSKOLE_REGISTRATOR));
            return roles;
        }

        if (organisationTypeName == OrganisationTypeNameConst.KKD_GENERAL_ARTS) {
            roles.add(findOrAddRoleByName(UserRoleNameConst.ROLE_KKD_GENERAL_ARTS_USER));
            roles.add(findOrAddRoleByName(UserRoleNameConst.ROLE_KKD_GENERAL_ARTS_REGISTRATOR));
            roles.add(findOrAddRoleByName(UserRoleNameConst.ROLE_KKD_FINANCE_APPLICATION_REGISTRATOR));
            return roles;
        }
        if (organisationTypeName == OrganisationTypeNameConst.KKD_VISUAL_ARTS) {
            roles.add(findOrAddRoleByName(UserRoleNameConst.ROLE_KKD_VISUAL_ARTS_USER));
            roles.add(findOrAddRoleByName(UserRoleNameConst.ROLE_KKD_VISUAL_ARTS_REGISTRATOR));
            roles.add(findOrAddRoleByName(UserRoleNameConst.ROLE_KKD_FINANCE_APPLICATION_REGISTRATOR));
            return roles;
        }
        if (organisationTypeName == OrganisationTypeNameConst.KKD_DRAMATIC_ART) {
            roles.add(findOrAddRoleByName(UserRoleNameConst.ROLE_KKD_DRAMATIC_ART_USER));
            roles.add(findOrAddRoleByName(UserRoleNameConst.ROLE_KKD_DRAMATIC_ART_REGISTRATOR));
            roles.add(findOrAddRoleByName(UserRoleNameConst.ROLE_KKD_FINANCE_APPLICATION_REGISTRATOR));
            return roles;
        }
        if (organisationTypeName == OrganisationTypeNameConst.KKD_DRAMATIC_ART_70) {
            roles.add(findOrAddRoleByName(UserRoleNameConst.ROLE_KKD_DRAMATIC_ART_70_USER));
            roles.add(findOrAddRoleByName(UserRoleNameConst.ROLE_KKD_DRAMATIC_ART_70_REGISTRATOR));
            roles.add(findOrAddRoleByName(UserRoleNameConst.ROLE_KKD_FINANCE_APPLICATION_REGISTRATOR));
            return roles;
        }
        if (organisationTypeName == OrganisationTypeNameConst.KKD_KNUTEPUNKT) {
            roles.add(findOrAddRoleByName(UserRoleNameConst.ROLE_KKD_KNUTEPUNKT_USER));
            roles.add(findOrAddRoleByName(UserRoleNameConst.ROLE_KKD_KNUTEPUNKT_REGISTRATOR));
            roles.add(findOrAddRoleByName(UserRoleNameConst.ROLE_KKD_FINANCE_APPLICATION_REGISTRATOR));
            return roles;
        }
        if (organisationTypeName == OrganisationTypeNameConst.KKD_MUSIC) {
            roles.add(findOrAddRoleByName(UserRoleNameConst.ROLE_KKD_MUSIC_USER));
            roles.add(findOrAddRoleByName(UserRoleNameConst.ROLE_KKD_MUSIC_REGISTRATOR));
            roles.add(findOrAddRoleByName(UserRoleNameConst.ROLE_KKD_FINANCE_APPLICATION_REGISTRATOR));
            return roles;
        }
        if (organisationTypeName == OrganisationTypeNameConst.KKD_MUSIC_70) {
            roles.add(findOrAddRoleByName(UserRoleNameConst.ROLE_KKD_MUSIC_70_USER));
            roles.add(findOrAddRoleByName(UserRoleNameConst.ROLE_KKD_MUSIC_70_REGISTRATOR));
            roles.add(findOrAddRoleByName(UserRoleNameConst.ROLE_KKD_FINANCE_APPLICATION_REGISTRATOR));
            return roles;
        }

        logger.error("Illegal organisationUnitTypeName '" + organisationTypeName + "'");
        throw new IllegalArgumentException("Illegal organisationUnitTypeName '" + organisationTypeName + "'");
    }

    private Set<RoleRelation> createRoleRelationsForOrganisationType(String organisationTypeName) {
        if (logger.isDebugEnabled()) {
            logger.debug("Executing: Set<RoleRelation> createRoleRelationsForOrganisationType");
        }
        Assert.checkRequiredArgument("organisationTypeName", organisationTypeName);

        Set<RoleRelation> roleRelations = new HashSet<RoleRelation>();

        Set<Role> roles = getUserAndRegistratorRolesForOrganisationType(organisationTypeName);
        for (Role role : roles) {
            RoleRelation roleRelation = createRoleRelationForRole(role, organisationTypeName);
            roleRelations.add(roleRelation);
        }
        return roleRelations;
    }

    private RoleRelation createRoleRelationForRoleName(String roleName, String organisationTypeName) {
        Assert.checkRequiredArgument("roleName", roleName);

        // Get role from DB for specified roleName.
        RoleFinderSpecification finderSpecification = new RoleFinderSpecification(roleName);
        Collection<Role> roles = find(finderSpecification);

        if (roles.size() == 0) {
            String errorMessage = "[createRoleRelationForRoleName] No role with name ='" + roleName + "'.";
            logger.error(errorMessage);
            throw new IllegalArgumentException(errorMessage);
        }

        if (roles.size() > 1) {
            String errorMessage = "[createRoleRelationForRoleName] More than one role with name ='" + roleName
                    + "'.";
            logger.error(errorMessage);
            throw new IllegalStateException(errorMessage);
        }
        Role role = roles.iterator().next();
        return createRoleRelationForRole(role, organisationTypeName);
    }

    private RoleRelation createRoleRelationForRole(Role role, String organisationTypeName) {
        Assert.checkRequiredArgument("role", role);
        Assert.checkRequiredArgument("organisationTypeName", organisationTypeName);

        Date deadline = null;
        Date opningDate = null;

        String roleName = role.getName();
        if (roleName.contains("_REGISTRATOR")) {
            String deadlineAsText = reportingDeadlineService.getActualDeadline(organisationTypeName, roleName);
            String opningDateAsText = reportingDeadlineService.getOpningDate(organisationTypeName, roleName);
            deadline = DateUtil.parseISODate(deadlineAsText);
            opningDate = DateUtil.parseISODate(opningDateAsText);
        }
        return new RoleRelation(role, opningDate, deadline);
    }

    public boolean hasPrincipalRole(Principal principal, String roleName) {
        Assert.checkRequiredArgument("principal", principal);
        Assert.checkRequiredArgument("roleName", roleName);

        List<RoleRelation> roleRelations = principal.getRoles();
        for (RoleRelation roleRelation : roleRelations) {
            if (roleName.equals(roleRelation.getRole().getName())) {
                return true;
            }
        }

        return false;
    }

    public User createUserForCulturalRucksack(OrganisationUnit organisationUnit) {

        HashSet<RoleRelation> roles = new HashSet<RoleRelation>();

        //a null name will set the user name to the same as the user id
        User user = new User(null, UserUtil.generatePassword());
        ContactInfo contactInfo = new ContactInfo();
        user.setContactInfo(contactInfo);

        /* All users should have this */
        roles.add(new RoleRelation(findOrAddRoleByName(UserRoleNameConst.ROLE_ABMSTATISTIKK_USER), null, null));

        roles.add(new RoleRelation(findOrAddRoleByName(UserRoleNameConst.ROLE_CULTURALRUCKSACK_USER), null, null));

        Date deadline = DateUtil.parseISODate("2007-10-21");
        roles.add(new RoleRelation(findOrAddRoleByName(UserRoleNameConst.ROLE_CULTURALRUCKSACK_USER), null,
                deadline));
        user.addRoles(roles);

        createUser(user, organisationUnit);

        return user;
    }

    public void addRegistratorRoleToCulturalRucksackUser() {

        String organisationTypeName = OrganisationTypeNameConst.FYLKE;
        OrgUnitFinderSpecificationBean finderBean = new OrgUnitFinderSpecificationBean();
        finderBean.setOrganisationTypeName(organisationTypeName);
        finderBean.setActiveDate(new Date());
        String registratorRoleName = UserRoleNameConst.ROLE_CULTURALRUCKSACK_REGISTRATOR;

        Date deadline = getActualDeadlineDate(organisationTypeName, registratorRoleName);
        Date opningDate = getOpningDate(organisationTypeName, registratorRoleName);

        OrgUnitQueryFinderSpecification finderSpecification = new OrgUnitQueryFinderSpecification(finderBean);
        Collection<OrganisationUnit> orgUnits = organisationUnitService.find(finderSpecification);

        List<RoleRelation> roleRelationStoreList = new ArrayList<RoleRelation>();
        for (OrganisationUnit organisationUnit : orgUnits) {

            RoleRelationFinderSpecification roleRelationFinderSpecification = new RoleRelationFinderSpecification(
                    organisationUnit.getId(), registratorRoleName);

            Collection<RoleRelation> roleRelations = userDao.find(roleRelationFinderSpecification);
            logger.info("For organisationId='" + organisationUnit.getId() + "' and userRoleName='"
                    + UserRoleNameConst.ROLE_CULTURALRUCKSACK_REGISTRATOR + "' has " + roleRelations.size()
                    + " # roleRelations, organisationUnitName ==> " + organisationUnit.getDefaultName());

            for (RoleRelation roleRelation : roleRelations) {
                if (roleRelation.getRole().getName().equals(registratorRoleName)) {

                    roleRelation.setStartDate(opningDate);
                    roleRelation.setEndDate(deadline);
                    roleRelationStoreList.add(roleRelation);
                }
            }

            if (roleRelations.size() == 0) {
                UserFinderSpecification userFinderSpecification = new UserFinderSpecification(
                        organisationUnit.getId(), UserRoleNameConst.ROLE_CULTURALRUCKSACK_USER);
                logger.info("Now try to create new roleRealiation for user " + organisationUnit.getId());

                Collection<User> users = userDao.find(userFinderSpecification);
                if (users.size() == 0) {
                    logger.info("No user exist for organisationUnit with id='" + organisationUnit.getId()
                            + "' we do not create new users here.");
                } else if (users.size() == 1) {
                    logger.info("One user we create and add new roleRelation to user");
                    // First find or create role
                    Role role = findOrAddRoleByName(registratorRoleName);
                    RoleRelation roleRelation = new RoleRelation(role, opningDate, deadline);
                    User user = users.iterator().next();
                    user.addRole(roleRelation);
                    userDao.saveOrUpdate(user);
                } else {
                    logger.info("More than one user, we don't do anything.");
                }
            }
        }

        userDao.saveOrUpdate(roleRelationStoreList.toArray());

        removeUserForOrganisationUnitsFromUserCache(orgUnits);
    }

    public boolean createUsersForOrganisationType(String organisationTypeName) {
        Assert.checkRequiredArgument("organisationTypeName", organisationTypeName);

        StopWatch stopWatch = new StopWatch("reportDataForOrganisationUnits");
        stopWatch.start("Sok i DB");

        boolean resultOKForAllOrganisationUnits = true;
        OrgUnitQueryFinderSpecification finderSpecification = new OrgUnitQueryFinderSpecification(
                organisationTypeName);
        Collection<OrganisationUnit> orgUnits = organisationUnitService.find(finderSpecification);
        stopWatch.stop();
        int numOfOrgUnits = orgUnits.size();
        logger.info("Searching orgunit tok " + stopWatch.getTotalTimeMillis()
                + " milliseconds and number of OrgUnits input " + numOfOrgUnits + " elements ");

        Set<RoleRelation> roleRelations = createRoleRelationsForOrganisationType(organisationTypeName);
        for (RoleRelation rr : roleRelations) {

            logger.debug("RoleRelation: " + rr.toString());
        }

        for (OrganisationUnit organisationUnit : orgUnits) {
            Long orgUnitId = organisationUnit.getId();
            UserFinderSpecification finder = new UserFinderSpecification(orgUnitId);
            Collection users = find(finder);
            if (users.size() > 0) {
                resultOKForAllOrganisationUnits = false;
                logger.warn("Skipping for organisationUnit id='" + orgUnitId + "' name='"
                        + organisationUnit.getName().getReference() + "' who allready has one or more user(s).");
            } else {
                createUserFromOrganisationUnit(organisationUnit, roleRelations, true);
            }
        }

        return resultOKForAllOrganisationUnits;
    }

    public ContactInfo getContactInfoForOrgUnitAndRole(Long orgUnitid, String roleName) {

        Assert.checkRequiredArgument("orgUnitid", orgUnitid);
        Assert.checkRequiredArgument("roleName", roleName);

        logger.info("orgUnitId=[" + orgUnitid + "] roleName=[" + roleName + "]");
        Collection<User> users = find(new UserFinderSpecification(orgUnitid, roleName));
        if (users.size() == 0) {
            logger.error("No user for organisationunitId [" + orgUnitid + "] with role [" + roleName + "]");
            return null;
        } else if (users.size() > 1) {
            logger.error(
                    "More than one user for organisationunitId [" + orgUnitid + "] with role [" + roleName + "]");
            return null;
        } else {
            Iterator<User> userIterator = users.iterator();
            User user = userIterator.next();
            return user.getContactInfo();
        }

    }

    public void storeContactInfo(ContactInfo contactInfo) {
        userDao.saveOrUpdate(contactInfo);
    }

    public void addressFromUserToJasperReport(SchemaList jasperReportDataSource, String roleName) {
        logger.info(" addressFromUserToJasperReport: START");

        for (Iterator<Map<String, Object>> iterator = jasperReportDataSource.iterator(); iterator.hasNext();) {
            Map<String, Object> report = iterator.next();
            Assert.assertTrue("Key organisationUnitId has to be in report map",
                    report.containsKey("organisationUnitId"));

            Long organisationUnitId = (Long) report.get("organisationUnitId");

            Assert.assertNotNull("Long: organisationUnitId can not be null", organisationUnitId);
            logger.info(" Orgunit number: " + organisationUnitId + "  and rolename: " + roleName);

            Collection<User> users = find(new UserFinderSpecification(organisationUnitId, roleName));

            for (User user : users) {
                report.put("postalAddress", user.getContactInfo().getAddress());
                report.put("postalAddressLine2", "");
                report.put("postalCode", user.getContactInfo().getZipCode());
                report.put("postalPlace", user.getContactInfo().getCity());
                report.put("contactPerson", user.getContactInfo().getLastName());
                report.put("contactPersonTelephone01", "");
                report.put("contactPersonEmail01", user.getContactInfo().getEmailAddress());
                logger.info(" Orgunit number: " + organisationUnitId + "  has userName: " + user.getName() + " "
                        + user.getContactInfo().toString());

            }
        }
        logger.info(" addressFromUserToJasperReport: END");

    }

    public void setNewDeadlineForOrgTypeAndRole(String organisationTypeName, String userRoleName) {
        setNewDeadlineForOrgTypeAndRole(organisationTypeName, userRoleName, false);
    }

    public void setNewDeadlineForOrgTypeAndRole(String organisationTypeName, String userRoleName,
            boolean createMissingRole) {

        Assert.checkRequiredArgument("organisationTypeName", organisationTypeName);
        Assert.checkRequiredArgument("userRoleName", userRoleName);
        Assert.checkRequiredArgument("createMissingRole", createMissingRole);

        String deadlineAsText = reportingDeadlineService.getActualDeadline(organisationTypeName, userRoleName);
        String opningDateAsText = reportingDeadlineService.getOpningDate(organisationTypeName, userRoleName);
        Date deadline = DateUtil.parseISODate(deadlineAsText);
        Date opningDate = DateUtil.parseISODate(opningDateAsText);

        logger.info("[setNewDeadline] Deadline " + deadline);

        StopWatch stopWatch = new StopWatch("reportDataForOrganisationUnits");
        stopWatch.start("Sok i DB");

        OrgUnitFinderSpecificationBean finderBean = new OrgUnitFinderSpecificationBean();
        finderBean.setOrganisationTypeName(organisationTypeName);
        finderBean.setActiveDate(new Date());

        OrgUnitQueryFinderSpecification finderSpecification = new OrgUnitQueryFinderSpecification(finderBean);
        Collection<OrganisationUnit> orgUnits = organisationUnitService.find(finderSpecification);
        stopWatch.stop();
        int numOfOrgUnits = orgUnits.size();
        logger.info("Searching orgunit tok " + stopWatch.getTotalTimeMillis()
                + " milliseconds and number of OrgUnits input " + numOfOrgUnits + " elements ");

        logger.info("Start prosessing of setting new deadlines for organisationType:" + organisationTypeName
                + " with " + numOfOrgUnits + " organisationUnits");
        StopWatch roleRelationstopWatch = new StopWatch("reportDataForOrganisationUnits");
        roleRelationstopWatch.start("Sok i DB");

        int i = 0;
        List<RoleRelation> roleRelationStoreList = new ArrayList<RoleRelation>();
        for (OrganisationUnit organisationUnit : orgUnits) {
            RoleRelationFinderSpecification roleRelationFinderSpecification = new RoleRelationFinderSpecification(
                    organisationUnit.getId(), userRoleName);

            Collection<RoleRelation> roleRelations = userDao.find(roleRelationFinderSpecification);
            logger.info("For organisationId='" + organisationUnit.getId() + "' and userRoleName='" + userRoleName
                    + "' has " + roleRelations.size() + " # roleRelations, organisationUnitName ==> "
                    + organisationUnit.getDefaultName());

            for (RoleRelation roleRelation : roleRelations) {
                if (roleRelation.getRole().getName().equals(userRoleName)) {

                    roleRelation.setStartDate(opningDate);
                    roleRelation.setEndDate(deadline);
                    roleRelationStoreList.add(roleRelation);

                }
            }

            if ((roleRelations.size() == 0) && createMissingRole) {
                logger.info("Now try to create new roleRealiation for user " + organisationUnit.getId());
                UserFinderSpecification userFinderSpecification = new UserFinderSpecification(
                        organisationUnit.getId());

                Collection<User> users = userDao.find(userFinderSpecification);
                if (users.size() == 0) {
                    logger.info("No user exist for organisationUnit with id='" + organisationUnit.getId()
                            + "' we do not create new users here.");
                } else if (users.size() == 1) {
                    logger.info("One user we create and add new roleRelation to user");
                    // First find or create role
                    Role role = findOrAddRoleByName(userRoleName);
                    RoleRelation roleRelation = new RoleRelation(role, opningDate, deadline);
                    User user = users.iterator().next();
                    user.addRole(roleRelation);
                    userDao.saveOrUpdate(user);
                } else {
                    logger.info("More than one user, we don't do anything.");
                }
            }

            i++;
            if ((i % 100) == 0) {
                logger.info("Has processed setting deadline " + i + " of " + numOfOrgUnits
                        + " for organisationUnitType:" + organisationTypeName);
            }
        }

        int numberOfUpdates = roleRelationStoreList.size();
        userDao.saveOrUpdate(roleRelationStoreList.toArray());

        removeUserForOrganisationUnitsFromUserCache(orgUnits);
        roleRelationstopWatch.stop();
        logger.info("Finish setting deadline for organisation type :" + organisationTypeName + " with "
                + numOfOrgUnits + " elements and have updated " + numberOfUpdates + " roleRelations in "
                + roleRelationstopWatch.getTotalTimeMillis() + " ms");

    }

    @Transactional(readOnly = true)
    public SchemaList letterDataAddressFromOrganisationregister(String orgTypeName, String userRoleName) {
        Assert.checkRequiredArgument("orgTypeName", orgTypeName);
        Assert.checkRequiredArgument("userRoleName", userRoleName);

        Boolean createMissingRoleRelations = false;

        return letterDataAddressFromOrganisationregister(orgTypeName, userRoleName, createMissingRoleRelations);
    }

    public SchemaList letterDataAddressFromOrganisationregister(String orgTypeName, String userRoleName,
            Boolean createMissingRoleRelations) {
        Assert.checkRequiredArgument("orgTypeName", orgTypeName);
        Assert.checkRequiredArgument("userRoleName", userRoleName);
        Assert.checkRequiredArgument("createMissingRoleRelations", createMissingRoleRelations);

        String messageToUser = "Executing: letterDataAddressFromOrganisationregister with orgTypeName ='"
                + orgTypeName + "' and userRoleName ='" + userRoleName + "'.";

        logger.info(messageToUser);
        // Getting due date
        String reportDueDate = reportingDeadlineService.getOfficialDeadline(orgTypeName, userRoleName);

        return letterAddressFromOrganisationregister(orgTypeName, reportDueDate, userRoleName,
                createMissingRoleRelations);
    }

    public SchemaList letterDataAddressFromUserDB(String orgTypeName, String userRoleName) {
        Assert.checkRequiredArgument("orgTypeName", orgTypeName);
        Assert.checkRequiredArgument("userRoleName", userRoleName);

        // Getting due date
        String reportDueDate = reportingDeadlineService.getOfficialDeadline(orgTypeName, userRoleName);

        // Getting id and name for organisationType
        StopWatch stopWatchPostalAddress = new StopWatch("postalAddress");
        stopWatchPostalAddress.start("postalAddress");
        OrgUnitBrowseFinderSpecification finderSpecification = new OrgUnitBrowseFinderSpecification(orgTypeName);

        Collection orgUnits = organisationUnitService.find(finderSpecification);
        stopWatchPostalAddress.stop();
        int numOfOrgUnits = orgUnits.size();
        logger.info("Getting institutions tok " + stopWatchPostalAddress.getTotalTimeMillis() + " milliseconds for "
                + orgUnits.size() + " elements " + " for organisationType " + orgTypeName);

        // Getting username and password
        StopWatch userNameAndPasswordStopWatch = new StopWatch("reportDataForOrganisationUnits");
        userNameAndPasswordStopWatch.start("Sok i DB");
        logger.info("Start getting username and passwords for organisationType:" + orgTypeName + " with "
                + numOfOrgUnits + " organisationUnits");

        SchemaList schemaList = new SchemaList();
        int n = 0;
        for (Iterator i = orgUnits.iterator(); i.hasNext(); n++) {
            OrganisationUnitForBrowsing orgUnit = (OrganisationUnitForBrowsing) i.next();
            Long organisationUnitId = orgUnit.getOrganisationUnitId();

            HashMap<String, Object> report = new HashMap<String, Object>();
            report.put("id", orgUnit.getOrganisationUnitId());
            report.put("name", orgUnit.getOrganisationUnitName());
            report.put("report_due_date", reportDueDate);

            Collection<User> users = find(new UserFinderSpecification(organisationUnitId, userRoleName));
            putUserNamePasswordAndAddressToJasperReport(report, users, organisationUnitId);
            schemaList.add(report);

            if ((n % 100) == 0) {
                logger.info("Has processed getting username and passwords " + n + " of " + numOfOrgUnits
                        + " for organisationUnitType:" + orgTypeName);
            }
        }

        userNameAndPasswordStopWatch.stop();
        logger.info("Finish getting username and password for organisation type :" + orgTypeName + " with "
                + numOfOrgUnits + " elements in " + userNameAndPasswordStopWatch.getTotalTimeMillis() + " ms");

        return schemaList;
    }

    // ////////////////////////////////////////////////////////////////////////
    //
    // Private methods.
    //
    // ////////////////////////////////////////////////////////////////////////

    private Date getOpningDate(String organisationTypeName, String userRoleName) {
        String opningDateAsText = reportingDeadlineService.getOpningDate(organisationTypeName, userRoleName);

        return DateUtil.parseISODate(opningDateAsText);
    }

    private Date getActualDeadlineDate(String organisationTypeName, String userRoleName) {
        String deadlineAsText = reportingDeadlineService.getActualDeadline(organisationTypeName, userRoleName);

        return DateUtil.parseISODate(deadlineAsText);
    }

    private void removeUserForOrganisationUnitsFromUserCache(Collection<OrganisationUnit> orgUnits) {
        for (OrganisationUnit organisationUnit : orgUnits) {
            UserFinderSpecification userFinderSpecification = new UserFinderSpecification(organisationUnit.getId());
            Collection<User> users = userDao.find(userFinderSpecification);
            for (User user : users) {
                userCache.removeUserFromCache(user.getName());
            }
        }
    }

    private SchemaList letterAddressFromOrganisationregister(String orgTypeName, String reportDueDate,
            String userRoleName, Boolean createMissingRoleRelationOnExistingUser) {

        // Getting postal address data for organisationType
        Collection<PostalAddressReport> postalAddresses = getPostalAddresses(orgTypeName);
        int numOfPostalAddresses = postalAddresses.size();

        // Getting username and password
        StopWatch userNameAndPasswordStopWatch = new StopWatch("reportDataForOrganisationUnits");
        userNameAndPasswordStopWatch.start("Sok i DB");
        logger.info("Start getting username and passwords for organisationType:" + orgTypeName + " with "
                + numOfPostalAddresses + " organisationUnits");

        SchemaList schemaList = new SchemaList();
        int n = 0;
        for (PostalAddressReport postalAddressReport : postalAddresses) {
            n++;
            Map<String, Object> report = putPostalAddressUserNameAndPassword(postalAddressReport, userRoleName,
                    createMissingRoleRelationOnExistingUser, orgTypeName);
            report.put("report_due_date", reportDueDate);
            schemaList.add(report);

            if ((n % 100) == 0) {
                logger.info("Has processed getting username and passwords " + n + " of " + numOfPostalAddresses
                        + " for organisationUnitType:" + orgTypeName);
            }

        }

        userNameAndPasswordStopWatch.stop();
        logger.info("Finish getting username and password for organisation type :" + orgTypeName + " with "
                + numOfPostalAddresses + " elements in " + userNameAndPasswordStopWatch.getTotalTimeMillis()
                + " ms");

        return schemaList;

    }

    private void putUserNamePasswordAndAddressToJasperReport(Map<String, Object> report, Collection<User> users,
            Long organisationUnitId) {

        if (users.size() == 0) {
            logger.error("No user for organisationunitId [" + organisationUnitId + "]");
        } else if (users.size() > 1) {
            logger.error("More than one user for organisationunitId [" + organisationUnitId + "]");
        } else {
            Iterator<User> userIterator = users.iterator();
            User user = userIterator.next();
            report.put("username", user.getUsername());
            report.put("password", user.getPassword());
            report.put("postalAddress", user.getContactInfo().getAddress());
            report.put("postalAddressLine2", "");
            report.put("postalCode", user.getContactInfo().getZipCode());
            report.put("postalPlace", user.getContactInfo().getCity());
        }
    }

    private Collection<PostalAddressReport> getPostalAddresses(String orgTypeName) {

        // Getting postal address data for organisationType of today.
        StopWatch stopWatchPostalAddress = new StopWatch("postalAddress");
        stopWatchPostalAddress.start("postalAddress");

        Date toDay = new Date();
        logger.info("ToDay: " + toDay);
        OrgUnitFinderSpecificationBean finderBean = new OrgUnitFinderSpecificationBean();
        finderBean.setOrganisationTypeName(orgTypeName);
        finderBean.setActiveDate(toDay);

        PostalAddressFinderSpecification finderSpecification = new PostalAddressFinderSpecification(finderBean);
        Collection<PostalAddressReport> postalAddresses = organisationUnitService.find(finderSpecification);

        stopWatchPostalAddress.stop();
        logger.info(
                "Getting postal addresses tok " + stopWatchPostalAddress.getTotalTimeMillis() + " milliseconds for "
                        + postalAddresses.size() + " elements " + " for organisationType " + orgTypeName);

        Comparator<OrgUnitReport> comparator = new OrgUnitReportCountyAndNameComparator();
        SortedSet<PostalAddressReport> reports = new TreeSet<PostalAddressReport>(comparator);
        reports.addAll(postalAddresses);

        return reports;
    }

    private Map<String, Object> putPostalAddressUserNameAndPassword(PostalAddressReport postalAddress,
            String userRoleName, Boolean createMissingRoleRelationOnExistingUser, String organisationTypeName) {
        Assert.checkRequiredArgument("postalAddress", postalAddress);
        Assert.checkRequiredArgument("userRoleName", userRoleName);

        Map<String, Object> report = new HashMap<String, Object>();
        report.put("id", postalAddress.getOrganisationUnitId());
        report.put("name", postalAddress.getOrganisationUnitName());
        report.put("postalAddress", postalAddress.getPostalAddressLine1());
        report.put("postalAddressLine2", postalAddress.getPostalAddressLine2());
        report.put("postalCode", postalAddress.getPostalCode());
        report.put("postalPlace", postalAddress.getPostalPlace());
        report.put("countyNumber", postalAddress.getCountyNumber());
        report.put("municipalityNumber", postalAddress.getMunicipalityNumber());

        Long organisationUnitId = postalAddress.getOrganisationUnitId();
        UserFinderSpecification finderSpecification = new UserFinderSpecification(organisationUnitId, userRoleName);

        Collection<User> users = find(finderSpecification);

        if (users.size() == 1) {
            // Exact match everything is OK
            User user = users.iterator().next();
            report.put("username", user.getUsername());
            report.put("password", user.getPassword());
            return report;
        }

        if (users.size() > 1) {
            // Too many matches cast error
            String errorMessage = "[putPostalAddressUserNameAndPassword] More than on user with role = '"
                    + userRoleName + "' for organisationUnit with Id ='" + organisationUnitId + "'.";
            logger.error(errorMessage);
            throw new IllegalStateException(errorMessage);
        }

        if (!createMissingRoleRelationOnExistingUser) {
            // No matches and we are not allowed to create new roleRelation.
            String errorMessage = "[putPostalAddressUserNameAndPassword] No user with role = '" + userRoleName
                    + "' for organisationUnit with Id ='" + organisationUnitId
                    + "' and we are not allowed to create new roleRelation";
            logger.error(errorMessage);
            throw new IllegalStateException(errorMessage);
        }

        // Try to create new roleRelation first we need to find exactly one user for orgunitId
        finderSpecification = new UserFinderSpecification(organisationUnitId);
        users = find(finderSpecification);

        if (users.size() == 0) {
            String errorMessage = "[putPostalAddressUserNameAndPassword] No user for organisationUnit with Id ='"
                    + organisationUnitId + "'.";
            logger.error(errorMessage);
            throw new IllegalStateException(errorMessage);
        }

        if (users.size() > 1) {
            String errorMessage = "[putPostalAddressUserNameAndPassword] "
                    + "More that one user for organisationUnit with Id ='" + organisationUnitId + "'.";
            logger.error(errorMessage);
            throw new IllegalStateException(errorMessage);
        }

        RoleRelation roleRelation = createRoleRelationForRoleName(userRoleName, organisationTypeName);
        User user = users.iterator().next();
        logger.info("Create roleRelation with roleName='" + roleRelation.getRole().getName()
                + "' for user with id= '" + user.getName() + "'.");
        user.addRole(roleRelation);
        userDao.saveOrUpdate(user);

        report.put("username", user.getUsername());
        report.put("password", user.getPassword());
        return report;

    }
}