package org.pegadi.server.service.impl;
import no.dusken.common.model.Department;
import no.dusken.common.model.Person;
import no.dusken.common.model.Role;
import no.dusken.common.service.DepartmentService;
import no.dusken.common.service.PersonService;
import no.dusken.common.service.RoleService;
import org.apache.commons.lang.NotImplementedException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcDaoSupport;
import org.springframework.jdbc.core.simple.SimpleJdbcInsert;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
@Service("personService")
public class PersonServiceImpl extends NamedParameterJdbcDaoSupport implements PersonService<Person> {
@Autowired
private DepartmentService<Department> departmentService;
@Autowired
private RoleService roleService;
private RowMapper<Person> rowmapper = getRowMapper();
private DataSourceTransactionManager transactionManager;
@Override
public Person getByUsername(String username) {
try {
return getNamedParameterJdbcTemplate().queryForObject("SELECT * FROM person where username = :username",
Collections.singletonMap("username", username), rowmapper);
} catch (DataAccessException e) {
return null;
}
}
@Override
public List<Person> getByActive(boolean isActive) {
throw new NotImplementedException();
}
@Override
public Person getByExternalID(Long aLong) {
throw new NotImplementedException();
}
@Override
public List<Person> findAll() {
return getJdbcTemplate().query("SELECT * FROM person", rowmapper);
}
@Override
public Iterable<Person> findAll(Iterable<Long> longs) {
throw new NotImplementedException();
}
@Override
public long count() {
throw new NotImplementedException();
}
@Override
public void delete(Long aLong) {
throw new NotImplementedException();
}
@Override
public void delete(Person entity) {
throw new NotImplementedException();
}
@Override
public void delete(Iterable<? extends Person> entities) {
throw new NotImplementedException();
}
@Override
public void deleteAll() {
throw new NotImplementedException();
}
@Override
public List<Person> findAll(Sort sort) {
throw new NotImplementedException();
}
@Override
public Page<Person> findAll(Pageable pageable) {
throw new NotImplementedException();
}
@Override
public <S extends Person> S save(final S entity) {
transactionManager = new DataSourceTransactionManager(getDataSource());
TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
Person person = transactionTemplate.execute(new TransactionCallback<Person>() {
@Override
public Person doInTransaction(TransactionStatus status) {
final Number id;
if (entity.isNew()) {
SimpleJdbcInsert jdbcInsert = new SimpleJdbcInsert(getJdbcTemplate()).withTableName("person").usingGeneratedKeyColumns("id");
HashMap<String, Object> parameters = getPersonParameters();
id = jdbcInsert.executeAndReturnKey(parameters);
insertRoles(id);
} else {
id = entity.getId();
HashMap<String, Object> personParameters = getPersonParameters();
personParameters.put("id", id);
getNamedParameterJdbcTemplate().update("UPDATE person SET firstname=:firstname, surname=:surname, emailaddress=:emailaddress, department_id=:department_id,active=:active WHERE ID = :id", personParameters);
getNamedParameterJdbcTemplate().update("DELETE FROM person_role WHERE person_id = :id", Collections.singletonMap("id", id));
for(final Role role: entity.getRoles()){
try {
getNamedParameterJdbcTemplate().update("INSERT INTO person_role(role_id, person_id) VALUES (:roleid, :personid)",
new HashMap<String, Object>(){{
put("roleid", role.getId());
put("personid", id);
}});
} catch (DuplicateKeyException e) {
//Role entry already exists
}
}
}
Person p = new Person(id.longValue(), entity.getFirstname(), entity.getSurname(), entity.getUsername(), entity.getEmailAddress());
p.setActive(entity.getActive());
p.setBirthdate(entity.getBirthdate());
p.setDepartment(entity.getDepartment());
p.setRoles(entity.getRoles());
p.setTimeCreated(entity.getTimeCreated());
return p;
}
private void insertRoles(Number personId) {
SimpleJdbcInsert person_role = new SimpleJdbcInsert(getJdbcTemplate()).withTableName("person_role");
for (Role role : entity.getRoles()) {
HashMap<String, Object> roleParameters = getRoleParameters(personId, role);
person_role.execute(roleParameters);
}
}
private HashMap<String, Object> getRoleParameters(Number personId, Role role) {
HashMap<String, Object> roleParameters = new HashMap<String, Object>();
roleParameters.put("role_id", role.getId());
roleParameters.put("person_id", personId);
return roleParameters;
}
private HashMap<String, Object> getPersonParameters() {
HashMap<String, Object> parameters = new HashMap<String, Object>();
parameters.put("firstname", entity.getFirstname());
parameters.put("surname", entity.getSurname());
parameters.put("username", entity.getUsername());
parameters.put("emailaddress", entity.getEmailAddress());
parameters.put("birthdate", entity.getBirthdate());
if (entity.getDepartment() != null) {
parameters.put("department_id", entity.getDepartment().getId());
} else {
parameters.put("department_id", null);
}
parameters.put("active", entity.getActive());
parameters.put("timecreated", entity.getTimeCreated());
return parameters;
}
});
return (S) person;
}
@Override
public <S extends Person> List<S> save(Iterable<S> entities) {
throw new NotImplementedException();
}
@Override
public Person findOne(Long id) {
return getNamedParameterJdbcTemplate().queryForObject("SELECT * FROM PERSON WHERE ID=:id", Collections.singletonMap("id", id), rowmapper);
}
@Override
public boolean exists(Long aLong) {
throw new NotImplementedException();
}
@Override
public void flush() {
throw new NotImplementedException();
}
@Override
public Person saveAndFlush(Person entity) {
throw new NotImplementedException();
}
@Override
public void deleteInBatch(Iterable<Person> entities) {
throw new NotImplementedException();
}
@Override
public void deleteAllInBatch() {
throw new NotImplementedException();
}
@Override
public Person findOne(Specification spec) {
throw new NotImplementedException();
}
@Override
public List<Person> findAll(Specification spec) {
throw new NotImplementedException();
}
@Override
public Page<Person> findAll(Specification spec, Pageable pageable) {
throw new NotImplementedException();
}
@Override
public List<Person> findAll(Specification spec, Sort sort) {
throw new NotImplementedException();
}
@Override
public long count(Specification spec) {
throw new NotImplementedException();
}
private RowMapper<Person> getRowMapper() {
return new org.springframework.jdbc.core.simple.ParameterizedRowMapper<Person>() {
public Person mapRow(ResultSet rs, int rowNr) throws SQLException {
Person person = new Person(rs.getLong("id"),
rs.getString("firstname"),
rs.getString("surname"),
rs.getString("username"),
rs.getString("emailaddress"));
person.setActive(rs.getBoolean("active"));
person.setDepartment(departmentService.findOne(rs.getLong("department_id")));
person.setRoles(roleService.findRolesForPerson(person));
return person;
}
};
}
}