/** * Revenue Settlement and Sharing System GE * Copyright (C) 2011-2014, Javier Lucio - lucio@tid.es * Telefonica Investigacion y Desarrollo, S.A. * * Copyright (C) 2015, CoNWeT Lab., Universidad Politécnica de Madrid * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package es.upm.fiware.rss.service; import es.upm.fiware.rss.dao.CurrencyDao; import es.upm.fiware.rss.dao.DbeAppProviderDao; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Date; import java.util.HashSet; import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import es.upm.fiware.rss.dao.DbeTransactionDao; import es.upm.fiware.rss.dao.ReportProviderDao; import es.upm.fiware.rss.dao.SharingReportDao; import es.upm.fiware.rss.exception.RSSException; import es.upm.fiware.rss.exception.UNICAExceptionType; import es.upm.fiware.rss.model.Aggregator; import es.upm.fiware.rss.model.BmCurrency; import es.upm.fiware.rss.model.DbeAppProvider; import es.upm.fiware.rss.model.DbeTransaction; import es.upm.fiware.rss.model.RSSModel; import es.upm.fiware.rss.model.RSSProvider; import es.upm.fiware.rss.model.RSSReport; import es.upm.fiware.rss.model.ReportProvider; import es.upm.fiware.rss.model.ReportProviderId; import es.upm.fiware.rss.model.SharingReport; import es.upm.fiware.rss.model.StakeholderModel; import es.upm.fiware.rss.settlement.ProductSettlementTask; import es.upm.fiware.rss.settlement.SettlementTaskFactory; import es.upm.fiware.rss.settlement.ThreadPoolManager; @Service @Transactional(rollbackFor = Exception.class) public class SettlementManager { /*** * Logging system. */ private final Logger logger = LoggerFactory.getLogger(SettlementManager.class); /** * */ @Autowired private DbeTransactionDao transactionDao; @Autowired private DbeAppProviderDao appProviderDao; @Autowired private SharingReportDao sharingReportDao; @Autowired private ReportProviderDao reportProviderDao; @Autowired private CurrencyDao currencyDao; @Autowired private SettlementTaskFactory taskFactory; @Autowired private AggregatorManager aggregatorManager; @Autowired private ProviderManager providerManager; @Autowired private RSSModelsManager modelsManager; @Autowired private ThreadPoolManager poolManager; private List<Aggregator> getAggregators(String aggregatorId) throws RSSException{ // Get given aggregators if needed List<Aggregator> aggregators; if (aggregatorId == null || aggregatorId.isEmpty()) { aggregators = this.aggregatorManager.getAPIAggregators(); } else { aggregators = new ArrayList<>(); aggregators.add(this.aggregatorManager.getAggregator(aggregatorId)); } return aggregators; } private List<RSSProvider> getProviders(String aggregatorId, String providerId) throws RSSException { List<RSSProvider> providers; if (providerId != null && !providerId.isEmpty()) { providers = new ArrayList<>(); providers.add(this.providerManager.getProvider(aggregatorId, providerId)); } else { providers = this.providerManager.getAPIProviders(aggregatorId); } return providers; } private List<RSSModel> getModels(String aggregatorId, String providerId, String productClass) throws RSSException { return this.modelsManager.getRssModels(aggregatorId, providerId, productClass); } /** * Launch settlement process. * * @param aggregatorId * @param providerId * @param productClass * @throws RSSException */ public void runSettlement(String aggregatorId, String providerId, String productClass) throws RSSException { // Validate fields if (aggregatorId != null && !aggregatorId.isEmpty()) { if (providerId != null && !providerId.isEmpty()) { // Check that the given provider belongs to the aggregator this.modelsManager.checkValidAppProvider(aggregatorId, providerId); // Check that the provider has a RS model // for the specified product class if (productClass != null && !productClass.isEmpty() && !this.modelsManager.existModel(aggregatorId, providerId, productClass)) { String[] args = {productClass}; throw new RSSException(UNICAExceptionType.NON_EXISTENT_RESOURCE_ID, args); } } } // Launch settlement for the given transactions for (Aggregator ag: this.getAggregators(aggregatorId)) { List<RSSProvider> providers = this.getProviders(ag.getAggregatorId(), providerId); for(RSSProvider pv: providers) { List<RSSModel> models = this.getModels(ag.getAggregatorId(), pv.getProviderId(), productClass); for (RSSModel m: models) { // Get related transactions List<DbeTransaction> txs = this.transactionDao. getTransactions(ag.getAggregatorId(), pv.getProviderId(), m.getProductClass()); // Set transactions as processing if (txs != null && !txs.isEmpty()) { this.setTxState(txs, "processing", true); // Create processing task ProductSettlementTask settlementTask = this.taskFactory.getSettlementTask(m, txs); poolManager.getExecutorService().submit(settlementTask); } } } } } /** * * @param transactions * @param state * @param toFlush */ public void setTxState(List<DbeTransaction> transactions, String state, boolean toFlush) { for (DbeTransaction tx: transactions) { tx.setState(state); this.transactionDao.update(tx); } // Flush state to the database if (toFlush) { this.transactionDao.flush(); } } public void generateReport(RSSModel sharingRes, String curr) throws IOException { this.logger.info("Generating report: " + sharingRes.getAggregatorId() + " " + sharingRes.getOwnerProviderId() + " " + sharingRes.getProductClass()); // Fill basic report information SharingReport report = new SharingReport(); report.setAlgorithmType(sharingRes.getAlgorithmType()); report.setProductClass(sharingRes.getProductClass()); report.setDate(new Date()); report.setAggregatorValue(sharingRes.getAggregatorValue()); report.setOwnerValue(sharingRes.getOwnerValue()); // Get provider object report.setOwner(this.appProviderDao.getProvider( sharingRes.getAggregatorId(), sharingRes.getOwnerProviderId())); // Set currency BmCurrency currency = this.currencyDao.getByIso4217StringCode(curr); report.setCurrency(currency); // Include stakeholders info if (sharingRes.getStakeholders() != null) { Set<ReportProvider> stakeholders = new HashSet<>(); for (StakeholderModel stakeholderModel: sharingRes.getStakeholders()) { DbeAppProvider stakeholder = this.appProviderDao. getProvider(sharingRes.getAggregatorId(), stakeholderModel.getStakeholderId()); // Build stakeholder id ReportProviderId stModelId = new ReportProviderId(); stModelId.setStakeholder(stakeholder); stModelId.setReport(report); // Build stakeholder ReportProvider stModel = new ReportProvider(); stModel.setId(stModelId); stModel.setModelValue(stakeholderModel.getModelValue()); // Add stakeholder to the set stakeholders.add(stModel); } report.setStakeholders(stakeholders); } Set<SharingReport> reports = report.getOwner().getReports(); if (null == reports) { reports = new HashSet<>(); } reports.add(report); // Save new report this.sharingReportDao.create(report); // Save stakeholders info for(ReportProvider st: report.getStakeholders()) { this.reportProviderDao.create(st); } } /** * Get the generated sharing reports filtered by some parameters. * * @param aggregator, aggregator of the returned sharing reports * @param provider, porvider of the returned sharing reports * @param productClass, Product class of the returned sharing reports * @return */ public List<RSSReport> getSharingReports( String aggregator, String provider, String productClass) { logger.debug("Into getSettlementFiles method."); // Get reports List<SharingReport> dbReports = this.sharingReportDao. getSharingReportsByParameters(aggregator, provider, productClass); List<RSSReport> reports = new ArrayList<>(); // Build API format if (dbReports != null) { for (SharingReport rp: dbReports) { RSSReport rep = new RSSReport(); rep.setAggregatorId(rp.getOwner().getId().getAggregator().getTxEmail()); rep.setAggregatorValue(rp.getAggregatorValue()); rep.setAlgorithmType(rp.getAlgorithmType()); rep.setCurrency(rp.getCurrency().getTxIso4217Code()); rep.setOwnerProviderId(rp.getOwner().getId().getTxAppProviderId()); rep.setOwnerValue(rp.getOwnerValue()); rep.setProductClass(rp.getProductClass()); rep.setTimestamp(rp.getDate()); // Set stakeholders Set<ReportProvider> stakeholders = rp.getStakeholders(); List<StakeholderModel> st = new ArrayList<>(); for (ReportProvider rPro: stakeholders) { StakeholderModel stakeholder = new StakeholderModel(); stakeholder.setStakeholderId(rPro.getStakeholder().getId().getTxAppProviderId()); stakeholder.setModelValue(rPro.getModelValue()); st.add(stakeholder); } rep.setStakeholders(st); reports.add(rep); } } return reports; } }