class ApplicationFundingBreakdownViewModelPopulator {

    public ApplicationFundingBreakdownViewModel populate(long applicationId, UserResource user) {

        ApplicationResource application = applicationRestService.getApplicationById(applicationId).getSuccess();
        CompetitionResource competition = competitionRestService.getCompetitionById(application.getCompetition()).getSuccess();
        List<ProcessRoleResource> processRoles = userRestService.findProcessRole(applicationId).getSuccess();

        Map<Long, ApplicationFinanceResource> finances = applicationFinanceRestService.getFinanceTotals(applicationId).getSuccess()
                    .stream().collect(toMap(ApplicationFinanceResource::getOrganisation, Function.identity()));

        List<OrganisationResource> organisations = organisationRestService.getOrganisationsByApplicationId(applicationId).getSuccess();
        long leadOrganisationId = application.getLeadOrganisationId();
        List<FinanceRowType> types = competition.getFinanceRowTypes().stream().filter(FinanceRowType::isCost).collect(toList());

        List<BreakdownTableRow> rows = organisations.stream()
                .filter(organisation -> competition.isKtp() ? organisation.getId().equals(leadOrganisationId) : true)
                .map(organisation -> toFinanceTableRow(organisation, finances, leadOrganisationId, processRoles, user, application, competition))
                .collect(toList());

        if (!application.isSubmitted() && !competition.isKtp()) {
            rows.addAll(pendingOrganisations(applicationId, types));
        }

        return new ApplicationFundingBreakdownViewModel(applicationId,
                competition.getName(),
                rows,
                application.isCollaborativeProject(),
                competition.getFundingType() == FundingType.KTP,
                types,
                finances.values().stream().anyMatch(ApplicationFinanceResource::isVatRegistered));
    }

}