Java tutorial
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; } }