nl.surfnet.coin.teams.service.impl.ApiGrouperDaoImpl.java Source code

Java tutorial

Introduction

Here is the source code for nl.surfnet.coin.teams.service.impl.ApiGrouperDaoImpl.java

Source

/*
 * Copyright 2012 SURFnet bv, The Netherlands
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package nl.surfnet.coin.teams.service.impl;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import nl.surfnet.coin.api.client.domain.Group20;
import nl.surfnet.coin.api.client.domain.Group20Entry;
import nl.surfnet.coin.api.client.domain.GroupMembersEntry;
import nl.surfnet.coin.api.client.domain.Person;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Transformer;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowCallbackHandler;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.util.Assert;

public class ApiGrouperDaoImpl extends AbstractGrouperDaoImpl implements ApiGrouperDao {

    private static final Logger LOG = LoggerFactory.getLogger(ApiGrouperDaoImpl.class);

    private JdbcTemplate jdbcTemplate;
    /*
     * http://static.springsource.org/spring/docs/2.5.x/reference/jdbc.html#jdbc-in
     * -clause
     */
    private NamedParameterJdbcTemplate namedParameterJdbcTemplate;

    private static final Map<String, String> VALID_SORTS_FOR_TEAM_QUERY;

    static {
        VALID_SORTS_FOR_TEAM_QUERY = new HashMap<String, String>();
        VALID_SORTS_FOR_TEAM_QUERY.put("id", "name");
        VALID_SORTS_FOR_TEAM_QUERY.put("title", "display_name");
        VALID_SORTS_FOR_TEAM_QUERY.put("description", "description");
    }

    public Group20Entry findGroup20(String personId, String groupName) {
        Group20Entry group20Entry;
        Assert.notNull(personId, "The personId can not be null");
        Assert.notNull(groupName, "The groupName can not be null");
        try {
            LOG.debug("Query to grouper database for person '{}' in group '{}'", personId, groupName.toUpperCase());
            group20Entry = new Group20Entry(
                    Arrays.asList(jdbcTemplate.queryForObject(SQL_FIND_TEAM_BY_MEMBER_AND_BY_GROUPNAME,
                            new Object[] { personId, groupName.toUpperCase() }, new OpenSocial20GroupRowMapper())));
            addRolesToGroups(personId, group20Entry.getEntry());
        } catch (EmptyResultDataAccessException ignored) {
            group20Entry = new Group20Entry();
        }
        return group20Entry;
    }

    public Group20Entry findAllGroup20sByMember(String personId, Integer offset, Integer pageSize, String sortBy) {
        int rowCount = this.jdbcTemplate.queryForInt(SQL_FIND_ALL_TEAMS_BY_MEMBER_ROWCOUNT, personId);
        List<Group20> groups = new ArrayList<Group20>();
        pageSize = correctPageSize(pageSize);
        offset = correctOffset(offset);
        try {
            String sql = formatAllTeamsSQLWithSortByOption(sortBy);
            groups = jdbcTemplate.query(sql, new Object[] { personId, pageSize, offset },
                    new OpenSocial20GroupRowMapper());
            addRolesToGroups(personId, groups);
        } catch (EmptyResultDataAccessException e) {
        }
        return new Group20Entry(groups, pageSize, offset, sortBy, rowCount);

    }

    protected String formatAllTeamsSQLWithSortByOption(String sortBy) {
        String sql = SQL_FIND_ALL_TEAMS_BY_MEMBER_SORTED;
        if (!StringUtils.isBlank(sortBy)) {
            String sortByColumn = null;
            Set<Entry<String, String>> entrySet = VALID_SORTS_FOR_TEAM_QUERY.entrySet();
            for (Entry<String, String> entry : entrySet) {
                if (entry.getKey().equals(sortBy)) {
                    sortByColumn = entry.getValue();
                    break;
                }
            }
            Assert.isTrue(!StringUtils.isBlank(sortByColumn), "The only supported sortBy options are ("
                    + VALID_SORTS_FOR_TEAM_QUERY.keySet() + "). Not allowed is '" + sortBy + "'");
            sql = String.format(sql, sortByColumn);
        } else {
            sql = String.format(sql, "name");
        }
        return sql;
    }

    public static class OpenSocial20GroupRowMapper extends GrouperRowMapper<Group20> {
        @Override
        public Group20 createObj(String id, String name, String description) {
            return new Group20(id, name, description);
        }
    }

    private enum Role {
        Manager, Admin, Member, none
    }

    private void addRolesToGroups(String personId, List<Group20> groups) {
        try {
            RolesRowCallbackHandler handler = new RolesRowCallbackHandler();
            this.jdbcTemplate.query(SQL_ROLES_BY_TEAMS, new Object[] { personId }, handler);
            Map<String, Role> roles = handler.roles;
            for (Group20 group : groups) {
                Role role = roles.get(group.getId());
                role = (role == null ? Role.Member : role);

                group.setVoot_membership_role(role.name().toLowerCase());
            }
        } catch (EmptyResultDataAccessException e) {
            // this we can ignore
        }

    }

    private class RolesRowCallbackHandler implements RowCallbackHandler {
        protected Map<String, Role> roles;

        public RolesRowCallbackHandler() {
            super();
            this.roles = new HashMap<String, Role>();
        }

        @Override
        public void processRow(ResultSet rs) throws SQLException {
            String groupName = rs.getString("groupname");
            String permission = rs.getString("fieldname");
            /*
             * If the permission equals 'admins' then we have an Role.Admin, else we
             * have a role Role.Manager, but we must not overwrite a previous
             * Role.Admin
             */
            Role role = roles.get(groupName);
            if (!Role.Admin.equals(role)) {
                roles.put(groupName, permission.equals("admins") ? Role.Admin : Role.Manager);
            }
        }
    }

    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * nl.surfnet.coin.teams.service.impl.ApiGrouperDao#findAllMembers(java.lang
     * .String, int, int)
     */
    @Override
    public GroupMembersEntry findAllMembers(String groupId, Integer offset, Integer pageSize) {
        List<Person> persons = new ArrayList<Person>();
        pageSize = correctPageSize(pageSize);
        offset = correctOffset(offset);
        try {
            RowMapper<Person> mapper = new RowMapper<Person>() {
                @Override
                public Person mapRow(ResultSet rs, int rowNum) throws SQLException {
                    Person person = new Person();
                    person.setId(rs.getString(1));
                    return person;
                }
            };
            persons = jdbcTemplate.query(SQL_MEMBERS_BY_TEAM, new Object[] { groupId, pageSize, offset }, mapper);
            if (CollectionUtils.isNotEmpty(persons)) {
                addPersonRolesToGroup(persons, groupId);
            }
        } catch (EmptyResultDataAccessException e) {
            // ignore as we have a sensible default
        }
        return new GroupMembersEntry(persons);
    }

    @Override
    public Group20Entry findGroups20ByIds(String personId, String[] groupIds, Integer pageSize, Integer offset) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("groupId", Arrays.asList(groupIds));

        List<Group20> groups = new ArrayList<Group20>();
        pageSize = correctPageSize(pageSize);
        offset = correctOffset(offset);
        params.put("limit", pageSize);
        params.put("offset", offset);
        try {
            String sql = SQL_FIND_TEAMS_BY_GROUPIDS;
            groups = namedParameterJdbcTemplate.query(sql, params, new OpenSocial20GroupRowMapper());
            addRolesToGroups(personId, groups);
        } catch (EmptyResultDataAccessException e) {
        }
        // FIXME: rowCount != groups.size() maar aparte query voor rowcount (query bestaat al: SQL_FIND_TEAMS_BY_GROUPIDS_ROWCOUNT)
        return new Group20Entry(groups, pageSize, offset, null, groups.size());
    }

    @SuppressWarnings("unchecked")
    private void addPersonRolesToGroup(Collection<Person> persons, String groupId) {
        try {
            RolesMembersRowCallbackHandler handler = new RolesMembersRowCallbackHandler();
            Collection<String> personIds = CollectionUtils.collect(persons, new Transformer() {
                @Override
                public Object transform(Object input) {
                    return ((Person) input).getId();
                }
            });
            Map<String, Object> params = new HashMap<String, Object>();
            params.put("groupId", groupId);
            params.put("identifiers", personIds);
            namedParameterJdbcTemplate.query(SQL_ROLES_BY_TEAM_AND_MEMBERS, params, handler);
            for (Person person : persons) {
                Role role = handler.roles.get(person.getId());
                role = (role == null ? Role.Member : role);
                person.setVoot_membership_role(role.name().toLowerCase());
            }
        } catch (EmptyResultDataAccessException e) {
            // this we can ignore
        }
    }

    private class RolesMembersRowCallbackHandler extends RolesRowCallbackHandler {

        @Override
        public void processRow(ResultSet rs) throws SQLException {
            String personName = rs.getString("subject_id");
            String permission = rs.getString("fieldname");
            Role role = roles.get(personName);
            if (!Role.Admin.equals(role)) {
                roles.put(personName, permission.equals("admins") ? Role.Admin : Role.Manager);
            }
        }
    }

    /**
     * @param namedParameterJdbcTemplate
     *          the namedParameterJdbcTemplate to set
     */
    public void setNamedParameterJdbcTemplate(NamedParameterJdbcTemplate namedParameterJdbcTemplate) {
        this.namedParameterJdbcTemplate = namedParameterJdbcTemplate;
    }
}