/*
* Copyright 2011-2014 Eric F. Savage, code@efsavage.com
*
* 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 com.ajah.user.data;
import java.util.List;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.stereotype.Repository;
import com.ajah.crypto.CryptoException;
import com.ajah.crypto.HmacSha1Password;
import com.ajah.crypto.Password;
import com.ajah.spring.jdbc.AbstractAjahDao;
import com.ajah.spring.jdbc.criteria.Criteria;
import com.ajah.spring.jdbc.criteria.Order;
import com.ajah.spring.jdbc.criteria.SubCriteria;
import com.ajah.spring.jdbc.err.DataOperationException;
import com.ajah.spring.jdbc.err.DataOperationExceptionUtils;
import com.ajah.user.User;
import com.ajah.user.UserId;
import com.ajah.user.UserImpl;
import com.ajah.user.UserNotFoundException;
import com.ajah.user.UserStatus;
import com.ajah.user.UserType;
import com.ajah.util.AjahUtils;
import com.ajah.util.StringUtils;
/**
* Data operations on the "user" table.
*
* @author Eric F. Savage <code@efsavage.com>
*
*/
@Repository
public class UserDaoImpl extends AbstractAjahDao<UserId, User, UserImpl> implements UserDao {
/**
* @see com.ajah.user.data.UserDao#count(com.ajah.user.UserType,
* com.ajah.user.UserStatus)
*/
@Override
public int count(final UserType type, final UserStatus status) throws DataOperationException {
final Criteria criteria = new Criteria();
if (type != null) {
criteria.eq("type", type);
}
if (status != null) {
criteria.eq("status", status);
}
return super.count(criteria);
}
@Override
public User findByUserIdAndPassword(final UserId userId, final String password) throws DataOperationException {
return super.find(new Criteria().eq(userId).eq("password", password));
}
@Override
public User findByUsername(final String username) throws DataOperationException {
return super.findByField("username", username);
}
@Override
public User findByUsernameAndPassword(final String username, final String password) throws DataOperationException {
return super.findByFields(new String[] { "username", "password" }, new String[] { username, password });
}
/**
* @see com.ajah.user.data.UserDao#getPassword(com.ajah.user.UserId)
*/
@Override
public Password getPassword(final UserId userId) throws CryptoException, DataOperationException {
try {
final String value = this.jdbcTemplate.queryForObject("SELECT password from user WHERE user_id=?", String.class, new Object[] { userId.toString() });
return new HmacSha1Password(value, true);
} catch (final EmptyResultDataAccessException e) {
return null;
} catch (final DataAccessException e) {
throw DataOperationExceptionUtils.translate(e, "user");
}
}
/**
* @see com.ajah.user.data.UserDao#getRandomUser(UserStatus)
*/
@Override
public User getRandomUser(final UserStatus status) throws DataOperationException {
return super.find(new Criteria().eq("status", status).randomOrder());
}
/**
* @see com.ajah.user.data.UserDao#getStatus(com.ajah.user.UserId)
*/
@Override
public UserStatus getStatus(final UserId userId) throws UserNotFoundException, DataOperationException {
try {
final String value = this.jdbcTemplate.queryForObject("SELECT status from user WHERE user_id=?", String.class, new Object[] { userId.toString() });
return UserStatus.get(value);
} catch (final DataAccessException e) {
throw DataOperationExceptionUtils.translate(e, "user");
}
}
/**
* @see com.ajah.user.data.UserDao#getUsername(com.ajah.user.UserId)
*/
@Override
public String getUsername(final UserId userId) throws DataOperationException {
try {
return this.jdbcTemplate.queryForObject("SELECT username from user WHERE user_id=?", String.class, new Object[] { userId.toString() });
} catch (final EmptyResultDataAccessException e) {
return null;
} catch (final DataAccessException e) {
throw DataOperationExceptionUtils.translate(e, "user");
}
}
/**
* This method is for saving a new user. It includes the password field
* since that field is the only field on the user table that is not mapped
* to a User property.
*
* @param user
* The user to save, required.
* @param password
* The password for the user, required.
* @throws DataOperationException
* If the query could not be executed.
*/
@Override
public int insert(final User user, final Password password) throws DataOperationException {
AjahUtils.requireParam(user, "user");
AjahUtils.requireParam(password, "password");
AjahUtils.requireParam(this.jdbcTemplate, "this.jdbcTemplate");
try {
return this.jdbcTemplate.update("INSERT INTO user (user_id, username, password, status, type) VALUES (?,?,?,?,?)",
new Object[] { user.getId().toString(), user.getUsername(), password.toString(), user.getStatus().getId() + "", user.getType().getId() + "" });
} catch (final DataAccessException e) {
throw DataOperationExceptionUtils.translate(e, "user");
}
}
@Override
public List<User> list(final String sortField, final Order order, final int page, final int count) throws DataOperationException {
return super.list(new Criteria().offset(page * count).rows(count).orderBy(sortField, order));
}
@Override
public List<User> list(final String username, final String firstName, final String lastName, final UserStatus status, final String sort, final Order order, final int page, final int count)
throws DataOperationException {
final Criteria criteria = new Criteria().rows(count).offset(page * count);
if (!StringUtils.isBlank(username)) {
final String pattern = username.replaceAll("\\*", "%");
criteria.and(new SubCriteria().orLike("username", pattern));
}
if ("username".equals(sort)) {
criteria.orderBy(sort, Order.DESC);
}
criteria.orderBy("status", Order.DESC);
criteria.orderBy("username", Order.ASC);
return super.list(criteria);
}
@Override
public int searchCount(final String username, final String firstName, final String lastName, final UserStatus status) throws DataOperationException {
final Criteria criteria = new Criteria();
if (!StringUtils.isBlank(username)) {
final String pattern = username.replaceAll("\\*", "%");
criteria.and(new SubCriteria().orLike("username", pattern));
}
return super.count(criteria);
}
/**
* UPDATEs the user table with a new password.
*
* @param userId
* ID of user to update, required.
* @param password
* Password to update to, required.
* @throws DataOperationException
* If the query could not be executed.
*/
@Override
@CacheEvict(value = "User", allEntries = true)
public int updatePassword(final UserId userId, final Password password) throws DataOperationException {
AjahUtils.requireParam(userId, "userId");
AjahUtils.requireParam(password, "password");
AjahUtils.requireParam(this.jdbcTemplate, "this.jdbcTemplate");
try {
return this.jdbcTemplate.update("UPDATE user SET password = ? WHERE user_id = ?", new Object[] { password.toString(), userId.toString() });
} catch (final DataAccessException e) {
throw DataOperationExceptionUtils.translate(e, "user");
}
}
/**
* @see com.ajah.user.data.UserDao#updateUsername(com.ajah.user.UserId,
* java.lang.String)
*/
@Override
public int updateUsername(final UserId userId, final String username) throws DataOperationException {
AjahUtils.requireParam(userId, "userId");
AjahUtils.requireParam(username, "username");
AjahUtils.requireParam(this.jdbcTemplate, "this.jdbcTemplate");
try {
return this.jdbcTemplate.update("UPDATE user SET username = ? WHERE user_id = ?", new Object[] { username, userId.toString() });
} catch (final DataAccessException e) {
throw DataOperationExceptionUtils.translate(e, "user");
}
}
}