nu.yona.server.analysis.service.InactivityManagementService.java Source code

Java tutorial

Introduction

Here is the source code for nu.yona.server.analysis.service.InactivityManagementService.java

Source

/*******************************************************************************
 * Copyright (c) 2015, 2017 Stichting Yona Foundation This Source Code Form is subject to the terms of the Mozilla Public License,
 * v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *******************************************************************************/
package nu.yona.server.analysis.service;

import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Set;
import java.util.UUID;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import nu.yona.server.analysis.entities.DayActivity;
import nu.yona.server.analysis.entities.DayActivityRepository;
import nu.yona.server.analysis.entities.WeekActivity;
import nu.yona.server.analysis.entities.WeekActivityRepository;
import nu.yona.server.goals.entities.Goal;
import nu.yona.server.goals.service.GoalDto;
import nu.yona.server.goals.service.GoalService;
import nu.yona.server.subscriptions.entities.UserAnonymized;
import nu.yona.server.subscriptions.service.UserAnonymizedDto;
import nu.yona.server.subscriptions.service.UserAnonymizedService;
import nu.yona.server.util.LockPool;
import nu.yona.server.util.TimeUtil;
import nu.yona.server.util.TransactionHelper;

@Service
public class InactivityManagementService {
    @Autowired(required = false)
    private WeekActivityRepository weekActivityRepository;

    @Autowired(required = false)
    private DayActivityRepository dayActivityRepository;

    @Autowired
    private UserAnonymizedService userAnonymizedService;

    @Autowired
    private GoalService goalService;

    @Autowired
    private LockPool<UUID> userAnonymizedSynchronizer;

    @Autowired
    private TransactionHelper transactionHelper;

    // This is intentionally not marked with @Transactional, as the transaction is explicitly started within the lock
    public void createInactivityEntities(UUID userAnonymizedId, Set<IntervalInactivityDto> intervalInactivities) {
        try (LockPool<UUID>.Lock lock = userAnonymizedSynchronizer.lock(userAnonymizedId)) {
            transactionHelper.executeInNewTransaction(() -> {
                UserAnonymizedDto userAnonymized = userAnonymizedService.getUserAnonymized(userAnonymizedId);
                createWeekInactivityEntities(userAnonymizedId, intervalInactivities.stream()
                        .filter(ia -> ia.getTimeUnit() == ChronoUnit.WEEKS).collect(Collectors.toSet()));
                createDayInactivityEntities(userAnonymized, intervalInactivities.stream()
                        .filter(ia -> ia.getTimeUnit() == ChronoUnit.DAYS).collect(Collectors.toSet()));
            });
        }
    }

    private void createWeekInactivityEntities(UUID userAnonymizedId, Set<IntervalInactivityDto> weekInactivities) {
        weekInactivities.stream().forEach(wi -> createWeekInactivity(userAnonymizedId, wi));
    }

    private void createDayInactivityEntities(UserAnonymizedDto userAnonymized,
            Set<IntervalInactivityDto> dayInactivities) {
        dayInactivities.stream()
                .forEach(di -> createDayInactivity(userAnonymized.getId(),
                        createWeekInactivity(userAnonymized.getId(),
                                getGoal(userAnonymized, di.getGoalId()).getGoalId(),
                                TimeUtil.getStartOfWeek(userAnonymized.getTimeZone(), di.getStartTime())),
                        di));
    }

    private GoalDto getGoal(UserAnonymizedDto userAnonymized, UUID goalId) {
        return goalService.getGoalForUserAnonymizedId(userAnonymized.getId(), goalId);
    }

    private void createWeekInactivity(UUID userAnonymizedId, IntervalInactivityDto weekInactivity) {
        createWeekInactivity(userAnonymizedId, weekInactivity.getGoalId(), weekInactivity.getStartTime());
    }

    private WeekActivity createWeekInactivity(UUID userAnonymizedId, UUID goalId, ZonedDateTime weekStartTime) {
        return createInactivity(userAnonymizedId, goalId,
                () -> weekActivityRepository.findOne(userAnonymizedId, weekStartTime.toLocalDate(), goalId),
                (ua, g) -> WeekActivity.createInstance(ua, g, weekStartTime.getZone(), weekStartTime.toLocalDate()),
                wa -> wa.getGoal().addWeekActivity(wa));
    }

    private void createDayInactivity(UUID userAnonymizedId, WeekActivity weekActivity,
            IntervalInactivityDto dayInactivity) {
        createInactivity(userAnonymizedId, dayInactivity.getGoalId(),
                () -> dayActivityRepository.findOne(userAnonymizedId, dayInactivity.getStartTime().toLocalDate(),
                        dayInactivity.getGoalId()),
                (ua, g) -> DayActivity.createInstance(ua, g, dayInactivity.getStartTime().getZone(),
                        dayInactivity.getStartTime().toLocalDate()),
                da -> weekActivity.addDayActivity(da));
    }

    private <T> T createInactivity(UUID userAnonymizedId, UUID goalId, Supplier<T> existingActivityFinder,
            BiFunction<UserAnonymized, Goal, T> creator, Consumer<T> storer) {
        T existingActivity = existingActivityFinder.get();
        if (existingActivity != null) {
            return existingActivity;
        }
        UserAnonymized userAnonymized = userAnonymizedService.getUserAnonymizedEntity(userAnonymizedId);
        Goal goal = goalService.getGoalEntityForUserAnonymizedId(userAnonymizedId, goalId);
        T inactivityEntity = creator.apply(userAnonymized, goal);

        storer.accept(inactivityEntity);

        return inactivityEntity;
    }
}