se.inera.axel.shs.broker.agreement.mongo.MongoAgreementService.java Source code

Java tutorial

Introduction

Here is the source code for se.inera.axel.shs.broker.agreement.mongo.MongoAgreementService.java

Source

/**
 * Copyright (C) 2013 Inera AB (http://www.inera.se)
 *
 * This file is part of Inera Axel (http://code.google.com/p/inera-axel).
 *
 * Inera Axel is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Inera Axel 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
 */
package se.inera.axel.shs.broker.agreement.mongo;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import se.inera.axel.shs.broker.agreement.AgreementService;
import se.inera.axel.shs.broker.agreement.mongo.model.MongoShsAgreement;
import se.inera.axel.shs.broker.directory.Agreement;
import se.inera.axel.shs.broker.directory.DirectoryService;
import se.inera.axel.shs.exception.IllegalAgreementException;
import se.inera.axel.shs.exception.IllegalSenderException;
import se.inera.axel.shs.exception.MissingAgreementException;
import se.inera.axel.shs.exception.ShsException;
import se.inera.axel.shs.exception.UnknownReceiverException;
import se.inera.axel.shs.xml.UrnProduct;
import se.inera.axel.shs.xml.agreement.*;
import se.inera.axel.shs.xml.label.*;
import se.inera.axel.shs.xml.label.Product;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service("agreementService")
public class MongoAgreementService implements AgreementService {

    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(MongoAgreementService.class);

    @Resource
    private MongoShsAgreementRepository mongoShsAgreementRepository;

    @Autowired
    private AgreementAssembler assembler;

    @Autowired
    private DirectoryService directoryService;

    @Override
    public ShsAgreement findOne(String agreementId) {
        ShsAgreement agreement = null;
        MongoShsAgreement mongoShsAgreement = mongoShsAgreementRepository.findOne(agreementId);

        if (mongoShsAgreement != null) {
            agreement = assembler.assembleShsAgreement(mongoShsAgreement);
        }

        return agreement;
    }

    @Override
    public List<ShsAgreement> findAgreements(ShsLabel label) {

        Product product = label.getProduct();
        String productId = product.getValue();

        From from = label.getFrom();

        if (from == null || StringUtils.isEmpty(from.getValue())) {
            return new ArrayList<ShsAgreement>();
        }

        String fromOrgNumber = from.getValue();
        String toOrgNumber = label.getTo() != null ? label.getTo().getOrgNumber() : null;

        List<MongoShsAgreement> agreements = null;
        if (toOrgNumber == null || toOrgNumber.isEmpty()) {
            agreements = mongoShsAgreementRepository.findByProductTypeIdAndFrom(productId, fromOrgNumber);
        } else {
            agreements = mongoShsAgreementRepository.findByProductTypeIdAndFromAndTo(productId, fromOrgNumber,
                    toOrgNumber);
        }

        if (agreements.size() > 0) {
            return assembler.assembleShsAgreementList(agreements);
        }

        log.debug("Looking for public agreements");
        List<Agreement> publicAgreements = directoryService.findAgreements(toOrgNumber, productId);
        List<ShsAgreement> shsAgreements = new ArrayList<ShsAgreement>(publicAgreements.size());
        if (log.isDebugEnabled()) {
            log.debug("Found {} public agreements", publicAgreements.size());
        }

        for (Agreement agreement : publicAgreements) {
            // TODO catch exception and ignore?
            ShsAgreement shsAgreement = assembler.assembleShsAgreement(agreement);

            shsAgreements.add(shsAgreement);
        }

        return shsAgreements;
    }

    private List<ShsAgreement> getAgreements(String actor1, String actor2, String product) {
        List<MongoShsAgreement> agreements = mongoShsAgreementRepository.findByProductTypeIdAndFromAndTo(product,
                actor1, actor2);
        return assembler.assembleShsAgreementList(agreements);
    }

    @Override
    public void validateAgreement(ShsLabel label) throws ShsException {
        log.trace("validating agreement for message with label {}", label);

        if (label == null) {
            throw new IllegalArgumentException("label must be provided");
        }

        if (label.getSequenceType() == SequenceType.ADM) {
            return;
        }

        if (label.getFrom() == null || StringUtils.isBlank(label.getFrom().getValue())) {
            throw new IllegalSenderException("From-address missing in message");
        }

        if (label.getTo() == null || StringUtils.isBlank(label.getTo().getValue())) {
            throw new UnknownReceiverException("To-address missing in message");
        }

        String recipientOrgNumber = label.getTo().getOrgNumber();

        log.debug("validating agreement for orgNumber {}", recipientOrgNumber);

        if (hasValidExplicitAgreement(label, recipientOrgNumber))
            return;

        if (hasValidLocalAgreement(label, recipientOrgNumber))
            return;

        // Look for a valid public agreement
        if (hasValidPublicAgreement(label, recipientOrgNumber))
            return;

        MissingAgreementException missingAgreementException = new MissingAgreementException(
                "No valid agreement found for the message");

        missingAgreementException.setCorrId(label.getCorrId());
        if (label.getContent() != null)
            missingAgreementException.setContentId(label.getContent().getContentId());

        throw missingAgreementException;
    }

    private boolean hasValidLocalAgreement(ShsLabel label, String recipientOrgNumber) {
        String senderOrgNumber = getSenderOrgNumber(label);

        String product = label.getProduct().getValue();

        if (log.isDebugEnabled())
            log.debug("searching for agreement involving actor {}, actor {} and product {}",
                    new String[] { senderOrgNumber, recipientOrgNumber, product });

        List<ShsAgreement> agreements = getAgreements(senderOrgNumber, recipientOrgNumber, product);

        for (ShsAgreement a : agreements) {
            try {
                validate(label, recipientOrgNumber, a);
            } catch (Exception e) {
                log.warn("validation failed for one agreement, continuing..", e);
                continue;
            }

            // Valid agreement found
            return true;
        }

        return false;
    }

    private String getSenderOrgNumber(ShsLabel label) {
        return label.getFrom() == null ? null : label.getFrom().getOrgNumber();
    }

    private boolean hasValidExplicitAgreement(ShsLabel label, String recipientOrgNumber) {
        if (label.getShsAgreement() != null) {
            ShsAgreement agreement = findOne(label.getShsAgreement());
            if (agreement == null) {
                throw new MissingAgreementException("given agreement can not be found in repository");
            }
            validate(label, recipientOrgNumber, agreement);
            return true;
        }

        return false;
    }

    private boolean hasValidPublicAgreement(ShsLabel label, String orgNumber) {
        List<Agreement> publicAgreements = directoryService.findAgreements(orgNumber,
                label.getProduct().getValue());

        for (Agreement publicAgreement : publicAgreements) {
            String publicTransferType = publicAgreement.getTransferType().toUpperCase();
            if ("ANY".equals(publicTransferType) || StringUtils.isBlank(publicTransferType) // null or empty is considered == any TODO validate with specification
                    || TransferType.valueOf(publicTransferType).equals(label.getTransferType())) {
                // Valid public agreement found
                return true;
            }
        }

        return false;
    }

    private void validate(ShsLabel label, String orgNumber, ShsAgreement agreement) {

        // check if products match
        checkThatProductMatchAgreement(label, agreement);

        checkThatActorsMatchAgreement(label, orgNumber, agreement);

        isValidNow(agreement);

    }

    private void checkThatActorsMatchAgreement(ShsLabel label, String receiverOrgNumber, ShsAgreement agreement) {
        String flow = getFlow(agreement);

        String expectedSender = null;
        String expectedReceiver = null;

        String senderOrgNumber = getSenderOrgNumber(label);
        String principalOrgNumber = getPrincipalOrgNumber(agreement);
        String customerOrgNumber = getCustomerOrgNumber(agreement);

        if ("any".equalsIgnoreCase(flow)) {
            checkAnyAgreementActors(receiverOrgNumber, senderOrgNumber, principalOrgNumber, customerOrgNumber);
        } else {
            if ("to-customer".equalsIgnoreCase(flow)) {
                expectedSender = principalOrgNumber;
                expectedReceiver = customerOrgNumber;
            } else if ("from-customer".equalsIgnoreCase(flow)) {
                expectedSender = customerOrgNumber;
                expectedReceiver = principalOrgNumber;
            }

            if (label.getSequenceType() == SequenceType.REPLY) {
                String temp = expectedSender;
                expectedSender = expectedReceiver;
                expectedReceiver = temp;
            }

            if (expectedSender != null && !expectedSender.equalsIgnoreCase(getSenderOrgNumber(label)))
                throw new IllegalAgreementException("Sender does not match agreement");

            if (expectedReceiver != null && !expectedReceiver.equalsIgnoreCase(receiverOrgNumber))
                throw new IllegalAgreementException("Receiver does not match agreement");
        }

    }

    private void checkAnyAgreementActors(String receiverOrgNumber, String senderOrgNumber,
            String principalOrgNumber, String customerOrgNumber) {
        if (senderOrgNumber.equalsIgnoreCase(principalOrgNumber)) {
            if (customerOrgNumber == null || receiverOrgNumber.equalsIgnoreCase(customerOrgNumber)) {
                return;
            }
        } else if (receiverOrgNumber.equalsIgnoreCase(principalOrgNumber)) {
            if (customerOrgNumber == null || senderOrgNumber.equalsIgnoreCase(customerOrgNumber)) {
                return;
            }
        }

        throw new IllegalAgreementException("Actors do not match the agreement");
    }

    private String getPrincipalOrgNumber(ShsAgreement agreement) {
        Shs shs = agreement.getShs();
        Principal principal = shs == null ? null : shs.getPrincipal();

        return principal == null ? null : principal.getValue();
    }

    private String getCustomerOrgNumber(ShsAgreement agreement) {
        Shs shs = agreement.getShs();
        Customer customer = shs == null ? null : shs.getCustomer();

        return customer == null ? null : customer.getValue();
    }

    private String getFlow(ShsAgreement agreement) {
        Shs shs = agreement.getShs();
        Direction direction = shs == null ? null : shs.getDirection();

        // TODO should any be default?
        return direction == null ? "any" : direction.getFlow();
    }

    private void checkThatProductMatchAgreement(ShsLabel label, ShsAgreement agreement) {
        String productId = label.getProduct().getValue();
        UrnProduct labelProduct = UrnProduct.valueOf(productId);

        List<se.inera.axel.shs.xml.agreement.Product> agreementProducts = agreement.getShs().getProduct();
        UrnProduct agreementProduct = null;

        for (se.inera.axel.shs.xml.agreement.Product p : agreementProducts) {
            agreementProduct = UrnProduct.valueOf(p.getValue());
            if (labelProduct.equals(agreementProduct)) {
                break;
            }
            agreementProduct = null;
        }

        if (agreementProduct == null) {
            throw new IllegalAgreementException("product in label does not match any product in agreement");
        }
    }

    private void isValidNow(ShsAgreement agreement) {
        General general = agreement.getGeneral();
        if (general == null)
            return;

        Valid valid = general.getValid();

        if (valid == null)
            return;

        ValidFrom validFrom = valid.getValidFrom();

        Date fromDate = validFrom == null ? null : validFrom.getDate();
        ValidTo validTo = agreement.getGeneral().getValid().getValidTo();
        Date toDate = validTo == null ? null : validTo.getDate();

        Date today = new Date();
        if ((fromDate != null && today.before(fromDate)) || (toDate != null && today.after(toDate))) {
            throw new IllegalAgreementException("the current time is outside validity period of agreement");
        }
    }

}