gov.ca.cwds.cals.service.ComplaintsService.java Source code

Java tutorial

Introduction

Here is the source code for gov.ca.cwds.cals.service.ComplaintsService.java

Source

package gov.ca.cwds.cals.service;

import static gov.ca.cwds.cals.Constants.UnitOfWork.CMS;
import static gov.ca.cwds.cals.Constants.UnitOfWork.FAS;
import static gov.ca.cwds.cals.Constants.UnitOfWork.FAS_FFA;
import static gov.ca.cwds.cals.Constants.UnitOfWork.FAS_RFH_LIVE;
import static javax.ws.rs.core.Response.Status.NOT_FOUND;

import com.google.inject.Inject;
import gov.ca.cwds.cals.Constants;
import gov.ca.cwds.cals.persistence.dao.fas.FasChildResComplaintDao;
import gov.ca.cwds.cals.persistence.dao.fas.FasFfaComplaintDao;
import gov.ca.cwds.cals.persistence.dao.fas.FasRfhLiveComplaintDao;
import gov.ca.cwds.cals.persistence.model.cwscms.CountyLicenseCaseComplaintInfo;
import gov.ca.cwds.cals.service.comparator.ComplaintComparator;
import gov.ca.cwds.cals.service.dao.CountyLicenseCaseComplaintInfoDao;
import gov.ca.cwds.cals.service.dto.AllegationDto;
import gov.ca.cwds.cals.service.dto.ComplaintDto;
import gov.ca.cwds.cals.service.mapper.ComplaintMapper;
import gov.ca.cwds.cals.util.PlacementHomeUtil;
import gov.ca.cwds.cms.data.access.dao.PlacementHomeDao;
import gov.ca.cwds.data.legacy.cms.entity.PlacementHome;
import gov.ca.cwds.rest.exception.ExpectedException;
import gov.ca.cwds.rest.services.ServiceException;
import io.dropwizard.hibernate.UnitOfWork;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Service to cover facility complaints functionality.
 *
 * @author CWDS CALS API Team
 */
public class ComplaintsService {

    private static final Logger LOGGER = LoggerFactory.getLogger(ComplaintsService.class);

    @Inject
    private FasChildResComplaintDao fasComplaintDao;

    @Inject
    private FasFfaComplaintDao fasFfaComplaintDao;

    @Inject
    private FasRfhLiveComplaintDao fasRfhLiveComplaintDao;

    @Inject
    private PlacementHomeDao placementHomeDao;

    @Inject
    private ComplaintMapper complaintMapper;

    @Inject
    private CountyLicenseCaseComplaintInfoDao countyLicenseCaseComplaintInfoDao;

    /**
     * Get complaints by facility id.
     */
    public Set<ComplaintDto> getComplaintsByFacilityId(final String facilityNumber) {
        final String licenseNumber = calculateFacilityLicenseNumber(facilityNumber);
        if (licenseNumber == null) {
            return Collections.emptySet();
        }
        List<ComplaintDto> facilityComplaints = aggregateComplaintsFromDifferentSources(licenseNumber);
        if (CollectionUtils.isEmpty(facilityComplaints)) {
            return Collections.emptySet();
        }
        Set<ComplaintDto> sortedSet = new TreeSet<>(ComplaintComparator.getCompositeComparator());
        sortedSet.addAll(facilityComplaints);
        return sortedSet;
    }

    /**
     * Get complaint by facility id and complaint id.
     */
    public ComplaintDto getComplaintByFacilityIdAndComplaintId(String facilityId, String complaintId) {
        final String licenseNumber = calculateFacilityLicenseNumber(facilityId);
        if (licenseNumber == null) {
            return null;
        }
        return Optional
                .ofNullable(fasComplaintDao.findComplaintByFacilityIdAndComplaintId(licenseNumber, complaintId))
                .map(complaintMapper::entityToDto).orElseThrow(() -> new ExpectedException(
                        Constants.ExpectedExceptionMessages.COMPLAINT_NOT_FOUND_BY_ID, NOT_FOUND));
    }

    private String calculateFacilityLicenseNumber(String facilityId) {
        if (isCwsCmsFacility(facilityId)) {
            return getLicenseNumberByFacilityId(facilityId);
        }
        return PlacementHomeUtil.normalizeLicenseNumber(facilityId);
    }

    private boolean isCwsCmsFacility(String facilityId) {
        return !NumberUtils.isDigits(facilityId);
    }

    @SuppressWarnings("squid:S2142") //Logging and informing client instead of shutdown
    private List<ComplaintDto> aggregateComplaintsFromDifferentSources(String facilityNumber) {
        List<ComplaintDto> complaints = new ArrayList<>();

        ExecutorService executorService = Executors.newFixedThreadPool(3);
        try {
            List<Future<List<ComplaintDto>>> futures = executorService.invokeAll(prepareListOfTasks(facilityNumber),
                    1, TimeUnit.MINUTES);
            for (Future<List<ComplaintDto>> future : futures) {
                complaints.addAll(future.get());
            }
        } catch (InterruptedException e) {
            String message = "One of complaints execution threads has been interrupted";
            LOGGER.error(message, e);
            throw new ServiceException(message, e);
        } catch (ExecutionException e) {
            LOGGER.error(e.getMessage(), e);
            throw new ServiceException(e.getMessage(), e);
        }

        shutdownExecutionService(executorService);

        return complaints;
    }

    private List<Callable<List<ComplaintDto>>> prepareListOfTasks(String facilityNumber) {
        Callable<List<ComplaintDto>> fasTask = () -> getComplaintsFromFas(facilityNumber);
        Callable<List<ComplaintDto>> fasFfaTask = () -> getComplaintsFromFasFfa(facilityNumber);
        Callable<List<ComplaintDto>> fasRfhLiveTask = () -> getComplaintsFromRfhLive(facilityNumber);
        Callable<List<ComplaintDto>> countyLicenseCaseComplaintsTask = () -> getCountyLicenseCaseComplaints(
                facilityNumber);
        return Arrays.asList(fasTask, fasFfaTask, fasRfhLiveTask, countyLicenseCaseComplaintsTask);
    }

    @SuppressWarnings("squid:S2142") //Logging and informing client instead of shutdown
    private void shutdownExecutionService(ExecutorService executorService) {
        executorService.shutdown();
        try {
            if (!executorService.awaitTermination(1, TimeUnit.MINUTES)) {
                executorService.shutdownNow();
            }
        } catch (InterruptedException e) {
            String message = "Can't properly shutdown complaints execution pool";
            LOGGER.warn(message, e);
            throw new ServiceException(message, e);
        }
    }

    @UnitOfWork(FAS)
    @SuppressWarnings("squid:S1452")
    protected List<ComplaintDto> getComplaintsFromFas(String facilityNumber) {
        return complaintMapper
                .complaintsListToComplaintsDtoList(fasComplaintDao.findComplaintsByFacilityNumber(facilityNumber));
    }

    @UnitOfWork(FAS_FFA)
    @SuppressWarnings("squid:S1452")
    protected List<ComplaintDto> getComplaintsFromFasFfa(String facilityNumber) {
        return complaintMapper.complaintsListToComplaintsDtoList(
                fasFfaComplaintDao.findComplaintsByFacilityNumber(facilityNumber));
    }

    @UnitOfWork(FAS_RFH_LIVE)
    @SuppressWarnings("squid:S1452")
    protected List<ComplaintDto> getComplaintsFromRfhLive(String facilityNumber) {
        return complaintMapper.complaintsListToComplaintsDtoList(
                fasRfhLiveComplaintDao.findComplaintsByFacilityNumber(facilityNumber));
    }

    @UnitOfWork(CMS)
    protected String getLicenseNumberByFacilityId(String facilityId) {
        return Optional.ofNullable(placementHomeDao.find(facilityId)).map(PlacementHome::getLicenseNo).orElse(null);
    }

    @UnitOfWork(CMS)
    protected List<ComplaintDto> getCountyLicenseCaseComplaints(String facilityNumber) {
        Map<LocalDate, List<CountyLicenseCaseComplaintInfo>> complaintsAggregation = countyLicenseCaseComplaintInfoDao
                .loadCountyLicenseCaseComplaintsByLicenseNumber(facilityNumber).stream()
                .collect(Collectors.groupingBy(CountyLicenseCaseComplaintInfo::getComplaintDate));
        List<ComplaintDto> complaints = new ArrayList<>(complaintsAggregation.size());
        for (Map.Entry<LocalDate, List<CountyLicenseCaseComplaintInfo>> entry : complaintsAggregation.entrySet()) {
            ComplaintDto complaintDto = new ComplaintDto();
            complaintDto.setComplaintDate(LocalDateTime.of(entry.getKey(), LocalTime.NOON));
            List<AllegationDto> allegations = entry.getValue().stream()
                    .map(CountyLicenseCaseComplaintInfo::toAllegationDto).collect(Collectors.toList());
            complaintDto.setAllegations(allegations);
            complaints.add(complaintDto);
        }
        return complaints;
    }

}