nl.strohalm.cyclos.services.tokens.TokenServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for nl.strohalm.cyclos.services.tokens.TokenServiceImpl.java

Source

/*
 *
 *    This file is part of Cyclos.
 *
 *    Cyclos 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.
 *
 *    Cyclos 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.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with Cyclos; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 *
 *
 */

package nl.strohalm.cyclos.services.tokens;

import nl.strohalm.cyclos.dao.tokens.TokenDAO;
import nl.strohalm.cyclos.entities.Relationship;
import nl.strohalm.cyclos.entities.access.Channel;
import nl.strohalm.cyclos.entities.access.PrincipalType;
import nl.strohalm.cyclos.entities.access.User;
import nl.strohalm.cyclos.entities.accounts.AccountOwner;
import nl.strohalm.cyclos.entities.accounts.SystemAccountOwner;
import nl.strohalm.cyclos.entities.accounts.transactions.Transfer;
import nl.strohalm.cyclos.entities.accounts.transactions.TransferType;
import nl.strohalm.cyclos.entities.members.Member;
import nl.strohalm.cyclos.entities.tokens.Status;
import nl.strohalm.cyclos.entities.tokens.Token;
import nl.strohalm.cyclos.services.elements.ElementService;
import nl.strohalm.cyclos.services.settings.SettingsService;
import nl.strohalm.cyclos.services.tokens.exceptions.BadStatusForRedeem;
import nl.strohalm.cyclos.services.tokens.exceptions.InvalidPinException;
import nl.strohalm.cyclos.services.tokens.exceptions.RefundNonExpiredToken;
import nl.strohalm.cyclos.services.tokens.exceptions.WrongTokenStateForPinReset;
import nl.strohalm.cyclos.services.transactions.PaymentService;
import nl.strohalm.cyclos.services.transactions.TransactionContext;
import nl.strohalm.cyclos.services.transactions.TransferDTO;
import nl.strohalm.cyclos.services.transfertypes.TransferTypeService;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateUtils;

import java.util.Calendar;
import java.util.List;

public class TokenServiceImpl implements TokenService {

    private TokenDAO tokenDao;

    private PaymentService paymentService;
    private ElementService elementService;
    private TransferTypeService transferTypeService;
    private SettingsService settingsService;

    @Override
    public String generateToken(GenerateTokenDTO generateTokenDTO) {
        String tokenId = generateTokenID();
        boolean ifSendNotification = true;
        if (generateTokenDTO.getSenderMobilePhone() == null) {
            //FIXME what if username != mobile
            //sender is not set for user transaction and set if initiated by agent
            ifSendNotification = false; //notification send only to agent
            generateTokenDTO.setSenderMobilePhone(generateTokenDTO.getFrom());
        }
        Transfer transfer = transferToSuspenseAccount(generateTokenDTO, generateTokenDTO.getRecipientMobilePhone());
        Token token = createToken(generateTokenDTO, transfer, tokenId, ifSendNotification);
        generatePin(tokenId);
        return token.getTransferFrom().getTransactionNumber();
    }

    private Token createToken(GenerateTokenDTO generateTokenDTO, Transfer transfer, String tokenId,
            boolean ifSendNotification) {
        Token token = new Token();
        token.setTokenId(tokenId);
        token.setTransferFrom(transfer);
        token.setAmount(generateTokenDTO.getAmount());
        token.setStatus(Status.ISSUED);
        token.setSenderMobilePhone(generateTokenDTO.getSenderMobilePhone());
        token.setRecipientMobilePhone(generateTokenDTO.getRecipientMobilePhone());
        token.setIfSendNotification(ifSendNotification);
        return tokenDao.insert(token);
    }

    private Transfer transferToSuspenseAccount(GenerateTokenDTO generateTokenDTO, String recipient) {
        TransferDTO doPaymentDTO = new TransferDTO();

        doPaymentDTO.setAmount(generateTokenDTO.getAmount());
        doPaymentDTO.setChannel("");
        Member from = loadUser(generateTokenDTO.getFrom());
        doPaymentDTO.setFromOwner(from);

        Long tokenTypeId = generateTokenDTO.getTransferTypeId();
        TransferType tt = transferTypeService.load(tokenTypeId);
        doPaymentDTO.setTransferType(tt);

        doPaymentDTO.setToOwner(SystemAccountOwner.instance());
        doPaymentDTO.setContext(TransactionContext.AUTOMATIC);
        doPaymentDTO.setDescription("Creation of token for recipient " + recipient);
        doPaymentDTO.setChannel(Channel.POSWEB);

        return (Transfer) paymentService.insertWithoutNotification(doPaymentDTO);
    }

    private Member loadUser(String userName) {
        return elementService.loadByPrincipal(new PrincipalType(Channel.Principal.USER), userName);
    }

    @Override
    public void redeemToken(Member broker, String tokenId, String pin, Long transferTypeId) {
        Token token = tokenDao.loadByTokenId(tokenId);
        validatePin(token, pin);
        Transfer transfer = redeemToken(token, transferTypeId, broker, Status.ISSUED, Status.REMITTED);
        token.setTransferTo(transfer);
        token.setStatus(Status.REMITTED);
        tokenDao.update(token);
    }

    private void validatePin(Token token, String pin) {
        if (!token.getPin().equals(pin)) {
            throw new InvalidPinException();
        }
    }

    @Override
    public void senderRedeemToken(Member member, SenderRedeemTokenData senderRedeemTokenData) {
        Token token = loadTokenByTransactionId(senderRedeemTokenData.getTransactionId());
        validatePin(token, senderRedeemTokenData.getPin());
        Long tokenTypeId = senderRedeemTokenData.getTransferTypeId();
        token.setTransferTo(redeemToken(token, tokenTypeId, member, Status.ISSUED, Status.SENDER_REMITTED));
        token.setStatus(Status.SENDER_REMITTED);
        tokenDao.update(token);
    }

    @Override
    public void resetPinToken(ResetPinTokenData resetPinTokenData) {
        Token token = loadTokenByTransactionId(resetPinTokenData.getTransactionId());
        if (token.getStatus() != Status.ISSUED) {
            throw new WrongTokenStateForPinReset();
        }
        token.setPin(randomNumber(4));
        tokenDao.update(token);
    }

    private Transfer redeemToken(Token token, Long transferTypeId, AccountOwner to, Status neededOldStatus,
            Status newStatus) {
        if (token.getStatus() != neededOldStatus) {
            throw new BadStatusForRedeem();
        }
        token.setStatus(newStatus);
        tokenDao.update(token);

        TransferDTO doPaymentDTO = new TransferDTO();
        doPaymentDTO.setAmount(token.getAmount());
        doPaymentDTO.setFromOwner(SystemAccountOwner.instance());

        doPaymentDTO.setTransferType(transferTypeService.load(transferTypeId));

        doPaymentDTO.setToOwner(to);
        doPaymentDTO.setDescription("Redemption of token " + token.getTokenId());
        doPaymentDTO.setContext(TransactionContext.AUTOMATIC);
        return (Transfer) paymentService.insertWithoutNotification(doPaymentDTO);
    }

    private void generatePin(String tokenId) {
        Token token = tokenDao.loadByTokenId(tokenId);
        if (token.getStatus() != Status.ISSUED) {
            throw new BadStatusForRedeem();
        }
        if (token.getPin() == null) {
            String pin = createPin();
            token.setPin(pin);
            tokenDao.update(token);
        }
    }

    @Override
    public Token loadTokenById(String tokenId, Relationship... rel) {
        return tokenDao.loadByTokenId(tokenId, rel);
    }

    @Override
    public void refundToken(Member member, SenderRedeemTokenData senderRedeemTokenData) {
        Token token = loadTokenByTransactionId(senderRedeemTokenData.getTransactionId());
        validatePin(token, senderRedeemTokenData.getPin());
        if (token.getStatus() != Status.EXPIRED) {
            throw new RefundNonExpiredToken();
        }
        redeemToken(token, senderRedeemTokenData.getTransferTypeId(), member, Status.EXPIRED, Status.REFUNDED);
        token.setStatus(Status.REFUNDED);
        tokenDao.update(token);
    }

    @Override
    public void processExpiredTokens(Calendar time) {
        Calendar timeToExpire = Calendar.getInstance();
        int tokenExpirationInDays = -1 * settingsService.getLocalSettings().getTokenExpirationInDays();
        timeToExpire.setTime(
                DateUtils.addDays(time.getTime(), tokenExpirationInDays == 0 ? -30 : tokenExpirationInDays));
        for (Token token : tokenDao.getTokensToExpire(timeToExpire)) {
            token.setStatus(Status.EXPIRED);
            Long ttId = settingsService.getLocalSettings().getExpireTokenTransferType();
            token.setTransferTo(
                    redeemToken(token, ttId, SystemAccountOwner.instance(), Status.ISSUED, Status.EXPIRED));
            tokenDao.update(token);
        }

    }

    String generateTokenID() {
        return randomNumber(12);
    }

    public String padTransactionId(String transactionId) {
        return "0000000".substring(transactionId.length()) + transactionId;
    }

    @Override
    public Token loadTokenByTransactionId(String tokenId) {
        String paddedTransactionId = padTransactionId(tokenId);
        return tokenDao.loadByTransactionId(paddedTransactionId);
    }

    private String randomNumber(int length) {
        return StringUtils.rightPad("" + (long) (Math.random() * Math.pow(10, length + 1)), length + 1, "0")
                .substring(1, length + 1);
    }

    private String createPin() {
        return randomNumber(4);
    }

    public void setPaymentService(PaymentService paymentService) {
        this.paymentService = paymentService;
    }

    public void setElementService(ElementService elementService) {
        this.elementService = elementService;
    }

    public void setTokenDao(TokenDAO tokenDao) {
        this.tokenDao = tokenDao;
    }

    public void setTransferTypeService(TransferTypeService transferTypeService) {
        this.transferTypeService = transferTypeService;
    }

    public void setSettingsService(SettingsService settingsService) {
        this.settingsService = settingsService;
    }

    @Override
    public List<Token> getUserTokens(User user) {
        return tokenDao.getUserTokens(user.getUsername());
    }
}