com.khartec.waltz.service.data_flow.RatedDataFlowService.java Source code

Java tutorial

Introduction

Here is the source code for com.khartec.waltz.service.data_flow.RatedDataFlowService.java

Source

/*
 *  This file is part of Waltz.
 *
 *     Waltz 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 3 of the License, or
 *     (at your option) any later version.
 *
 *     Waltz 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 Waltz.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.khartec.waltz.service.data_flow;

import com.khartec.waltz.common.Checks;
import com.khartec.waltz.data.application.ApplicationDao;
import com.khartec.waltz.data.application.ApplicationIdSelectorFactory;
import com.khartec.waltz.data.data_flow.DataFlowDao;
import com.khartec.waltz.model.*;
import com.khartec.waltz.model.application.Application;
import com.khartec.waltz.model.authoritativesource.AuthoritativeSource;
import com.khartec.waltz.model.authoritativesource.Rating;
import com.khartec.waltz.model.dataflow.DataFlow;
import com.khartec.waltz.model.dataflow.ImmutableRatedDataFlow;
import com.khartec.waltz.model.dataflow.RatedDataFlow;
import com.khartec.waltz.service.authoritative_source.AuthoritativeSourceCalculator;
import org.jooq.Record1;
import org.jooq.Select;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.khartec.waltz.common.Checks.checkNotNull;
import static com.khartec.waltz.common.ListUtilities.filter;
import static com.khartec.waltz.common.MapUtilities.*;
import static com.khartec.waltz.model.utils.IdUtilities.toIds;

@Service
public class RatedDataFlowService {

    private final AuthoritativeSourceCalculator authoritativeSourceCalculator;
    private final ApplicationDao applicationDao;
    private final DataFlowDao dataFlowDao;
    private final ApplicationIdSelectorFactory applicationIdSelectorFactory;

    /** (dataflow, (type -> [authSource])) -> Rating */
    private static final BiFunction<DataFlow, Map<String, Map<Long, AuthoritativeSource>>, Rating> lookupRatingFn = (
            df, authSourceByTypeThenApp) -> {
        Map<Long, AuthoritativeSource> authSourcesByApp = authSourceByTypeThenApp.get(df.dataType());

        if (isEmpty(authSourcesByApp)) {
            return Rating.NO_OPINION;
        }

        long sourceAppId = df.source().id();

        AuthoritativeSource authoritativeSource = authSourcesByApp.get(sourceAppId);

        return authoritativeSource == null ? Rating.DISCOURAGED : authoritativeSource.rating();
    };

    @Autowired
    public RatedDataFlowService(AuthoritativeSourceCalculator authoritativeSourceCalculator,
            ApplicationDao applicationDao, DataFlowDao dataFlowDao,
            ApplicationIdSelectorFactory applicationIdSelectorFactory) {
        checkNotNull(applicationDao, "applicationDao must not be null");
        checkNotNull(authoritativeSourceCalculator, "authoritativeSourceCalculator must not be null");
        checkNotNull(dataFlowDao, "dataFlowDao must not be null");
        Checks.checkNotNull(applicationIdSelectorFactory, "applicationIdSelectorFactory cannot be null");

        this.authoritativeSourceCalculator = authoritativeSourceCalculator;
        this.applicationDao = applicationDao;
        this.dataFlowDao = dataFlowDao;
        this.applicationIdSelectorFactory = applicationIdSelectorFactory;
    }

    public List<RatedDataFlow> calculateRatedFlowsForOrgUnitTree(long orgUnitId) {

        Map<Long, Map<String, Map<Long, AuthoritativeSource>>> authSourcesByOrgThenTypeThenApp = authoritativeSourceCalculator
                .calculateAuthSourcesForOrgUnitTree(orgUnitId);

        Select<Record1<Long>> appIdSelector = createAppIdSelectorBasedOnOrgUnitId(orgUnitId);

        List<Application> apps = applicationDao.findByAppIdSelector(appIdSelector);

        List<DataFlow> relevantFlows = loadRelevantDataFlows(dataFlowDao, apps);

        Map<Long, Collection<DataFlow>> flowsByOrgUnitId = groupFlowsByTargetOrgUnitId(apps, relevantFlows);

        return flowsByOrgUnitId.entrySet().stream().map(entry -> {
            long owningOrgUnitId = entry.getKey();

            Map<String, Map<Long, AuthoritativeSource>> authSourcesByTypeThenApp = authSourcesByOrgThenTypeThenApp
                    .get(owningOrgUnitId);
            Collection<DataFlow> flows = entry.getValue();
            return prepareResult(flows, authSourcesByTypeThenApp);
        }).flatMap(l -> l.stream()).collect(Collectors.toList());
    }

    private Select<Record1<Long>> createAppIdSelectorBasedOnOrgUnitId(long orgUnitId) {
        IdSelectionOptions selectionOptions = ImmutableIdSelectionOptions.builder()
                .entityReference(ImmutableEntityReference.builder().kind(EntityKind.ORG_UNIT).id(orgUnitId).build())
                .scope(HierarchyQueryScope.CHILDREN).build();

        return applicationIdSelectorFactory.apply(selectionOptions);
    }

    private static List<RatedDataFlow> prepareResult(Collection<DataFlow> flows,
            Map<String, Map<Long, AuthoritativeSource>> authSourceByTypeThenApp) {
        return flows.stream().map(f -> {
            Rating rating = lookupRatingFn.apply(f, authSourceByTypeThenApp);
            return ImmutableRatedDataFlow.builder().dataFlow(f).rating(rating).build();
        }).collect(Collectors.toList());
    }

    private static Map<Long, Collection<DataFlow>> groupFlowsByTargetOrgUnitId(List<Application> apps,
            List<DataFlow> relevantFlows) {
        Function<DataFlow, Long> lookupOrgUnitIdFn = mkLookupTargetOrgUnitIdFn(apps);

        return groupBy(lookupOrgUnitIdFn, relevantFlows);
    }

    /**
     * [app] -> dataFlow -> ouId
     *
     * @return function which takes a data flow and returns the ouId of the target application
     */
    private static Function<DataFlow, Long> mkLookupTargetOrgUnitIdFn(List<Application> apps) {
        Map<Long, Application> appsById = indexBy(a -> a.id().get(), apps);

        return df -> {
            long appId = df.target().id();
            Application app = appsById.get(appId);
            if (app == null) {
                return null;
            } else {
                return app.organisationalUnitId();
            }
        };
    }

    /**
     * (dao, [ouId], [app]) -> [ dataFlow ]
     * <br>
     * @return a list of data flows where the target is a member of [app].
     */
    private static List<DataFlow> loadRelevantDataFlows(DataFlowDao dataFlowDao, List<Application> targetApps) {

        List<Long> appIds = toIds(targetApps);

        List<DataFlow> dataFlows = dataFlowDao.findByApplicationIds(appIds);

        return filter(df -> appIds.contains(df.target().id()), dataFlows);
    }

}