package de.rwth.idsg.bikeman.repository; import de.rwth.idsg.bikeman.domain.Authority; import de.rwth.idsg.bikeman.domain.BookedTariff; import de.rwth.idsg.bikeman.domain.BookedTariff_; import de.rwth.idsg.bikeman.domain.CardAccount; import de.rwth.idsg.bikeman.domain.CardAccount_; import de.rwth.idsg.bikeman.domain.MajorCustomer; import de.rwth.idsg.bikeman.domain.MajorCustomer_; import de.rwth.idsg.bikeman.domain.Tariff_; import de.rwth.idsg.bikeman.domain.User_; import de.rwth.idsg.bikeman.security.AuthoritiesConstants; import de.rwth.idsg.bikeman.web.rest.dto.modify.CreateEditMajorCustomerDTO; import de.rwth.idsg.bikeman.web.rest.dto.view.ViewCardAccountDTO; import de.rwth.idsg.bikeman.web.rest.dto.view.ViewMajorCustomerDTO; import de.rwth.idsg.bikeman.web.rest.exception.DatabaseException; import lombok.extern.slf4j.Slf4j; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Repository; import org.springframework.transaction.annotation.Transactional; import javax.inject.Inject; import javax.persistence.EntityExistsException; import javax.persistence.EntityManager; import javax.persistence.NoResultException; import javax.persistence.PersistenceContext; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Expression; import javax.persistence.criteria.Join; import javax.persistence.criteria.JoinType; import javax.persistence.criteria.Path; import javax.persistence.criteria.Root; import java.util.HashSet; import java.util.List; /** * Created by swam on 16/10/14. */ @Repository @Slf4j public class MajorCustomerRepositoryImpl implements MajorCustomerRepository { @Inject private PasswordEncoder passwordEncoder; private enum Operation {CREATE, UPDATE} private enum FindType {ALL, BY_ID, BY_LOGIN} @PersistenceContext private EntityManager em; @Override @Transactional(readOnly = true) public List<ViewMajorCustomerDTO> findAll() throws DatabaseException { try { CriteriaBuilder builder = em.getCriteriaBuilder(); return em.createQuery( getMajorCustomerQuery(builder, FindType.ALL, null, null) ).getResultList(); } catch (Exception e) { throw new DatabaseException("Failed during database operation.", e); } } @Override @Transactional(readOnly = true) public ViewMajorCustomerDTO findByLogin(String login) throws DatabaseException { CriteriaBuilder builder = em.getCriteriaBuilder(); CriteriaQuery<ViewMajorCustomerDTO> criteria = this.getMajorCustomerQuery(builder, FindType.BY_LOGIN, login, null); ViewMajorCustomerDTO majorCustomerDTO; try { majorCustomerDTO = em.createQuery(criteria).getSingleResult(); } catch (Exception e) { throw new DatabaseException("Failed to find majorcustomer with majorCustomer login: " + login, e); } CriteriaQuery<ViewCardAccountDTO> cardAccountCriteria = builder.createQuery(ViewCardAccountDTO.class); Root<CardAccount> cardAccount = cardAccountCriteria.from(CardAccount.class); Join<CardAccount, BookedTariff> bookedTariff = cardAccount.join(CardAccount_.currentTariff, JoinType.LEFT); cardAccountCriteria.select( builder.construct( ViewCardAccountDTO.class, cardAccount.get(CardAccount_.cardId), cardAccount.get(CardAccount_.cardPin), cardAccount.get(CardAccount_.inTransaction), cardAccount.get(CardAccount_.operationState), bookedTariff.get(BookedTariff_.tariff).get(Tariff_.name) ) ).where(builder.equal(cardAccount.get(CardAccount_.user).get(User_.login), login)); List<ViewCardAccountDTO> list; try { list = em.createQuery(cardAccountCriteria).getResultList(); } catch (Exception e) { throw new DatabaseException("Failed to get cards for major customer", e); } if (list == null || list.isEmpty()) { majorCustomerDTO.setCardAccountDTOs(new HashSet<>()); } else { majorCustomerDTO.setCardAccountDTOs(new HashSet<>(list)); } return majorCustomerDTO; } // @Override // @Transactional(readOnly = true) // public ViewMajorCustomerDTO findOne(long majorCustomerId) throws DatabaseException { // // CriteriaBuilder builder = em.getCriteriaBuilder(); // // CriteriaQuery<ViewMajorCustomerDTO> criteria = this.getMajorCustomerQuery(builder, FindType.BY_ID, null, majorCustomerId); // ViewMajorCustomerDTO majorCustomerDTO; // // try { // majorCustomerDTO = em.createQuery(criteria).getSingleResult(); // } catch (Exception e) { // throw new DatabaseException("Failed to find majorcustomer with majorCustomerId: " + majorCustomerId, e); // } // // CriteriaQuery<ViewCardAccountDTO> cardAccountCriteria = builder.createQuery(ViewCardAccountDTO.class); // Root<CardAccount> cardAccount = cardAccountCriteria.from(CardAccount.class); // Join<CardAccount, BookedTariff> bookedTariff = cardAccount.join(CardAccount_.currentTariff, JoinType.LEFT); // // cardAccountCriteria.select( // builder.construct( // ViewCardAccountDTO.class, // cardAccount.get(CardAccount_.cardId), // cardAccount.get(CardAccount_.cardPin), // cardAccount.get(CardAccount_.inTransaction), // cardAccount.get(CardAccount_.operationState), // bookedTariff.get(BookedTariff_.tariff).get(Tariff_.name) // ) // ).where(builder.equal(cardAccount.get(CardAccount_.user).get(User_.userId), majorCustomerId)); // // List<ViewCardAccountDTO> list; // // try { // list = em.createQuery(cardAccountCriteria).getResultList(); // } catch (Exception e) { // throw new DatabaseException("Failed to get cards for major customer", e); // } // // if (list == null || list.isEmpty()) { // majorCustomerDTO.setCardAccountDTOs(new HashSet<>()); // } else { // majorCustomerDTO.setCardAccountDTOs(new HashSet<>(list)); // } // // return majorCustomerDTO; // } @Override public MajorCustomer findByName(String name) throws DatabaseException { final String query = "select mc from MajorCustomer mc where mc.name = :name"; try { return em.createQuery(query, MajorCustomer.class) .setParameter("name", name) .getSingleResult(); } catch (NoResultException e) { throw new DatabaseException("Could not find majorCustomer for specified name.", e); } } @Override @Transactional(rollbackFor = Exception.class) public void create(CreateEditMajorCustomerDTO dto) throws DatabaseException { MajorCustomer majorCustomer = new MajorCustomer(); setFields(majorCustomer, dto, Operation.CREATE); try { em.persist(majorCustomer); log.debug("Created new majorcustomer {}", majorCustomer); } catch (EntityExistsException e) { throw new DatabaseException("This customer exists already.", e); } catch (Exception e) { throw new DatabaseException("Failed to create a new customer.", e); } } @Override @Transactional(rollbackFor = Exception.class) public void update(CreateEditMajorCustomerDTO dto) throws DatabaseException { final Long userId = dto.getUserId(); if (userId == null) { return; } MajorCustomer majorCustomer = getMajorCustomerEntity(userId); try { setFields(majorCustomer, dto, Operation.UPDATE); em.merge(majorCustomer); log.debug("Updated majorcustomer {}", majorCustomer); } catch (Exception e) { throw new DatabaseException("Failed to update majorcustomer with userId " + userId, e); } } @Override @Transactional(rollbackFor = Exception.class) public void delete(long userId) throws DatabaseException { MajorCustomer majorCustomer = getMajorCustomerEntity(userId); try { em.remove(majorCustomer); log.debug("Deleted majorcustomer {}", majorCustomer); } catch (Exception e) { throw new DatabaseException("Failed to delete majorcustomer with userId " + userId, e); } } /** * Returns a customer, or throws exception when no customer exists. */ @Transactional(readOnly = true) private MajorCustomer getMajorCustomerEntity(long userId) throws DatabaseException { MajorCustomer majorCustomer = em.find(MajorCustomer.class, userId); if (majorCustomer == null) { throw new DatabaseException("No majorcustomer with userId " + userId); } else { return majorCustomer; } } /** * This method sets the fields of the customer to the values in DTO. */ private void setFields(MajorCustomer majorCustomer, CreateEditMajorCustomerDTO dto, Operation operation) { // TODO: Should the login be changeable? Who sets the field? Clarify! majorCustomer.setLogin(dto.getLogin()); majorCustomer.setName(dto.getName()); if (dto.getPassword() != null) { majorCustomer.setPassword(passwordEncoder.encode(dto.getPassword())); } switch (operation) { case CREATE: HashSet<Authority> authorities = new HashSet<>(); authorities.add(new Authority(AuthoritiesConstants.MAJOR_CUSTOMER)); majorCustomer.setAuthorities(authorities); break; case UPDATE: break; } } /** * This method returns the query to get information of customers for various lookup cases */ private CriteriaQuery<ViewMajorCustomerDTO> getMajorCustomerQuery(CriteriaBuilder builder, FindType findType, String login, Long majorCustomerId) { CriteriaQuery<ViewMajorCustomerDTO> criteria = builder.createQuery(ViewMajorCustomerDTO.class); Root<MajorCustomer> majorCustomer = criteria.from(MajorCustomer.class); criteria.select( builder.construct( ViewMajorCustomerDTO.class, majorCustomer.get(MajorCustomer_.userId), majorCustomer.get(MajorCustomer_.login), majorCustomer.get(MajorCustomer_.name) ) ); switch (findType) { case ALL: break; case BY_LOGIN: Path<String> loginPath = majorCustomer.get(MajorCustomer_.login); Expression<String> loginLower = builder.lower(loginPath); criteria.where( builder.equal(loginLower, login.toLowerCase()) ); break; case BY_ID: criteria.where(builder.equal(majorCustomer.get(MajorCustomer_.userId), majorCustomerId)); break; } return criteria; } private CriteriaQuery<ViewMajorCustomerDTO> getQueryWithCardAccounts(CriteriaBuilder builder) { CriteriaQuery<ViewMajorCustomerDTO> criteria = builder.createQuery(ViewMajorCustomerDTO.class); Root<MajorCustomer> majorCustomer = criteria.from(MajorCustomer.class); criteria.select( builder.construct( ViewMajorCustomerDTO.class, majorCustomer.get(MajorCustomer_.userId), majorCustomer.get(MajorCustomer_.login), majorCustomer.get(MajorCustomer_.name) ) ); return criteria; } }