| /* |
| ******************************************************************************* |
| * Copyright (c) 2019 Contributors to the Eclipse Foundation |
| * |
| * See the NOTICE file(s) distributed with this work for additional |
| * information regarding copyright ownership. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0. |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| ******************************************************************************* |
| */ |
| package org.eclipse.openk.gridfailureinformation.service; |
| |
| import lombok.extern.log4j.Log4j2; |
| import org.eclipse.openk.gridfailureinformation.bpmn.base.ProcessException; |
| import org.eclipse.openk.gridfailureinformation.bpmn.impl.GfiGrid; |
| import org.eclipse.openk.gridfailureinformation.bpmn.impl.GfiProcessState; |
| import org.eclipse.openk.gridfailureinformation.bpmn.impl.GfiProcessSubject; |
| import org.eclipse.openk.gridfailureinformation.bpmn.impl.tasks.ProcessHelper; |
| import org.eclipse.openk.gridfailureinformation.constants.Constants; |
| import org.eclipse.openk.gridfailureinformation.enums.OperationType; |
| import org.eclipse.openk.gridfailureinformation.exceptions.BadRequestException; |
| import org.eclipse.openk.gridfailureinformation.exceptions.InternalServerErrorException; |
| import org.eclipse.openk.gridfailureinformation.exceptions.NotFoundException; |
| import org.eclipse.openk.gridfailureinformation.exceptions.OperationDeniedException; |
| import org.eclipse.openk.gridfailureinformation.mapper.FailureInformationMapper; |
| import org.eclipse.openk.gridfailureinformation.mapper.FailureInformationPublicationChannelMapper; |
| import org.eclipse.openk.gridfailureinformation.mapper.tools.AddressSplitterMerger; |
| import org.eclipse.openk.gridfailureinformation.model.HtblFailureInformation; |
| import org.eclipse.openk.gridfailureinformation.model.RefBranch; |
| import org.eclipse.openk.gridfailureinformation.model.RefExpectedReason; |
| import org.eclipse.openk.gridfailureinformation.model.RefStatus; |
| import org.eclipse.openk.gridfailureinformation.model.TblAddress; |
| import org.eclipse.openk.gridfailureinformation.model.TblFailureInformation; |
| import org.eclipse.openk.gridfailureinformation.model.TblFailureInformationPublicationChannel; |
| import org.eclipse.openk.gridfailureinformation.model.TblFailureInformationReminderMailSent; |
| import org.eclipse.openk.gridfailureinformation.model.TblFailureInformationStation; |
| import org.eclipse.openk.gridfailureinformation.model.TblStation; |
| import org.eclipse.openk.gridfailureinformation.repository.AddressRepository; |
| import org.eclipse.openk.gridfailureinformation.repository.BranchRepository; |
| import org.eclipse.openk.gridfailureinformation.repository.DistributionGroupRepository; |
| import org.eclipse.openk.gridfailureinformation.repository.ExpectedReasonRepository; |
| import org.eclipse.openk.gridfailureinformation.repository.FailureClassificationRepository; |
| import org.eclipse.openk.gridfailureinformation.repository.FailureInformationDistributionGroupRepository; |
| import org.eclipse.openk.gridfailureinformation.repository.FailureInformationPublicationChannelRepository; |
| import org.eclipse.openk.gridfailureinformation.repository.FailureInformationReminderMailSentRepository; |
| import org.eclipse.openk.gridfailureinformation.repository.FailureInformationRepository; |
| import org.eclipse.openk.gridfailureinformation.repository.FailureInformationStationRepository; |
| import org.eclipse.openk.gridfailureinformation.repository.HistFailureInformationRepository; |
| import org.eclipse.openk.gridfailureinformation.repository.RadiusRepository; |
| import org.eclipse.openk.gridfailureinformation.repository.StationRepository; |
| import org.eclipse.openk.gridfailureinformation.repository.StatusRepository; |
| import org.eclipse.openk.gridfailureinformation.util.ExternalStatusCalculator; |
| import org.eclipse.openk.gridfailureinformation.util.GrahamScan; |
| import org.eclipse.openk.gridfailureinformation.viewmodel.FailureInformationDto; |
| import org.eclipse.openk.gridfailureinformation.viewmodel.FailureInformationLastModDto; |
| import org.eclipse.openk.gridfailureinformation.viewmodel.FailureInformationPublicationChannelDto; |
| import org.springframework.beans.factory.annotation.Autowired; |
| import org.springframework.beans.factory.annotation.Value; |
| import org.springframework.data.domain.Page; |
| import org.springframework.data.domain.Pageable; |
| import org.springframework.stereotype.Service; |
| import org.springframework.transaction.annotation.Transactional; |
| |
| import java.awt.*; |
| import java.math.BigDecimal; |
| import java.math.RoundingMode; |
| import java.time.LocalDateTime; |
| import java.time.ZoneId; |
| import java.util.ArrayList; |
| import java.util.Comparator; |
| import java.util.Date; |
| import java.util.HashSet; |
| import java.util.LinkedList; |
| import java.util.List; |
| import java.util.Optional; |
| import java.util.Set; |
| import java.util.UUID; |
| import java.util.stream.Collectors; |
| |
| import static org.eclipse.openk.gridfailureinformation.constants.Constants.FREETEXT_ADDRESS_TYPE; |
| |
| @Log4j2 |
| @Service |
| public class FailureInformationService { |
| |
| @Value("${spring.settings.daysInPastToShowClosedInfos}") |
| private int daysInPastToShowClosedInfos; |
| |
| @Autowired |
| private FailureInformationRepository failureInformationRepository; |
| |
| @Autowired |
| private HistFailureInformationRepository histFailureInformationRepository; |
| |
| @Autowired |
| private FailureInformationMapper failureInformationMapper; |
| |
| @Autowired |
| private FailureInformationPublicationChannelMapper failureInformationPublicationChannelMapper; |
| |
| @Autowired |
| private BranchRepository branchRepository; |
| |
| @Autowired |
| private FailureClassificationRepository failureClassificationRepository; |
| |
| @Autowired |
| private RadiusRepository radiusRepository; |
| |
| @Autowired |
| private ExpectedReasonRepository expectedReasonRepository; |
| |
| @Autowired |
| private StatusRepository statusRepository; |
| |
| @Autowired |
| private StationRepository stationRepository; |
| |
| @Autowired |
| private AddressRepository addressRepository; |
| |
| @Autowired |
| private DistributionGroupRepository distributionGroupRepository; |
| |
| @Autowired |
| private FailureInformationDistributionGroupRepository failureInformationDistributionGroupRepository; |
| |
| @Autowired |
| private FailureInformationPublicationChannelRepository failureInformationPublicationChannelRepository; |
| |
| @Autowired |
| private FailureInformationStationRepository failureInformationStationRepository; |
| |
| @Autowired |
| FailureInformationReminderMailSentRepository failureInformationReminderMailSentRepository; |
| |
| @Autowired |
| HistFailureInformationStationService histFailureInformationStationService; |
| |
| @Autowired |
| private GfiGrid grid; |
| |
| @Autowired |
| private ProcessHelper processHelper; |
| |
| public FailureInformationDto findFailureInformation( UUID uuid ) { |
| |
| TblFailureInformation existingTblFailureInfo = failureInformationRepository.findByUuid( uuid ) |
| .orElseThrow(NotFoundException::new); |
| |
| return enrichFailureInfo(failureInformationMapper.toFailureInformationDto(existingTblFailureInfo)); |
| } |
| |
| public Page<FailureInformationDto> findFailureInformations(Pageable pageable) { |
| Page<FailureInformationDto> retPage = findFailureInformationsForDisplay(pageable) |
| .map(failureInformationMapper::toFailureInformationDto); |
| |
| retPage.getContent().forEach(this::enrichFailureInfo); |
| return retPage; |
| } |
| |
| public Page<TblFailureInformation> findFailureInformationsForDisplay(Pageable pageable) { |
| LocalDateTime now = LocalDateTime.now(); |
| LocalDateTime ldt = LocalDateTime.of(now.getYear(), now.getMonth(), now.getDayOfMonth(), 0, 0, 0); |
| ldt = ldt.minusDays(daysInPastToShowClosedInfos); |
| Date nowMinusFourWeeks = Date.from(ldt.atZone(ZoneId.of("UTC")).toInstant()); |
| return failureInformationRepository.findByTblFailureInformationForDisplay( |
| GfiProcessState.COMPLETED.getStatusValue(), |
| GfiProcessState.CANCELED.getStatusValue(), |
| nowMinusFourWeeks, pageable); |
| } |
| |
| public List<FailureInformationDto> findFailureInformationsByCondensedUuid(UUID uuid) { |
| |
| List<FailureInformationDto> listFailureInformationDtos = new LinkedList<>(); |
| List<TblFailureInformation> listFailureInformations = failureInformationRepository.findByFailureInformationCondensedUuid(uuid); |
| |
| for(TblFailureInformation tblInfo: listFailureInformations){ |
| FailureInformationDto infoDto = failureInformationMapper.toFailureInformationDto(tblInfo); |
| enrichFailureInfo(infoDto); |
| listFailureInformationDtos.add(infoDto); |
| } |
| |
| return listFailureInformationDtos; |
| } |
| |
| public FailureInformationDto findByObjectReferenceExternalSystem( String extRef ) { |
| Optional<TblFailureInformation> tblFailureInformation |
| = failureInformationRepository.findByObjectReferenceExternalSystem( extRef ); |
| if( tblFailureInformation.isPresent() ) { |
| return failureInformationMapper.toFailureInformationDto(tblFailureInformation.get()); |
| } |
| else { |
| return null; |
| } |
| } |
| |
| @Transactional |
| public FailureInformationDto insertFailureInfo(FailureInformationDto failureInfoDto, GfiProcessState initialState) { |
| failureInfoDto.setUuid(null); // force null here |
| |
| return storeFailureInfo(failureInfoDto, initialState); |
| } |
| |
| @Transactional |
| public FailureInformationDto updateFailureInfo(FailureInformationDto failureInfoDto) { |
| return processGrid(failureInfoDto, null); |
| } |
| |
| @Transactional |
| public FailureInformationDto updateAndPublish( FailureInformationDto failureInformationDto) { |
| if( getRefStatus(failureInformationDto).getId() != GfiProcessState.QUALIFIED.getStatusValue()) { |
| throw new BadRequestException("Publishing is only possible with state 'qualified'"); |
| } |
| TblFailureInformation tblFailureInfo = failureInformationRepository.findByUuid(failureInformationDto.getUuid()).orElseThrow(()-> new NotFoundException("")); |
| List<TblFailureInformationPublicationChannel> channelList = failureInformationPublicationChannelRepository.findByTblFailureInformation(tblFailureInfo); |
| if( channelList.isEmpty()) { |
| throw new BadRequestException("Publishing is only possible with at least one selected channel"); |
| } |
| return processGrid(failureInformationDto, GfiProcessState.CHECKED_FOR_PUBLISH_); |
| } |
| |
| |
| public FailureInformationDto storeFailureInfo(FailureInformationDto dto, GfiProcessState initialState) { |
| TblFailureInformation tblFailureInformationToSave = failureInformationMapper.toTblFailureInformation(dto); |
| if(dto.getUuid() == null ) { |
| tblFailureInformationToSave.setUuid(UUID.randomUUID()); |
| tblFailureInformationToSave.setVersionNumber(1L); |
| setFromGridFailureInformationDto(tblFailureInformationToSave, dto); |
| |
| RefStatus refStatus = statusRepository.findById(initialState.getStatusValue()) |
| .orElseThrow(() -> new NotFoundException("ref.status.not.found")); |
| |
| tblFailureInformationToSave.setRefStatusIntern(refStatus); |
| tblFailureInformationToSave.setCondensedCount(0); |
| tblFailureInformationToSave.setCondensed(false); |
| } else { |
| TblFailureInformation tblFailureInformation = failureInformationRepository.findByUuid(dto.getUuid()) |
| .orElseThrow(() -> new NotFoundException(Constants.FAILURE_INFO_UUID_NOT_EXISTING)); |
| |
| tblFailureInformationToSave = failureInformationMapper.toTblFailureInformation(dto); |
| tblFailureInformationToSave.setId(tblFailureInformation.getId()); |
| |
| setFromGridFailureInformationDto(tblFailureInformationToSave, dto); |
| setVersionNumber(tblFailureInformationToSave); |
| } |
| |
| TblFailureInformation tblFailureInformationSaved = failureInformationRepository.save(tblFailureInformationToSave); |
| FailureInformationDto failureInformationDto = failureInformationMapper.toFailureInformationDto(tblFailureInformationSaved); |
| |
| storeStations(tblFailureInformationSaved, dto.getStationIds()); |
| FailureInformationDto enrichedFailureInformationDto = enrichFailureInfo(failureInformationDto); |
| |
| // insert stations in history table |
| histFailureInformationStationService.insertHistFailureInfoStationsForGfi(tblFailureInformationSaved); |
| |
| return enrichedFailureInformationDto; |
| } |
| |
| private void storeStations( TblFailureInformation tblToStore, List<UUID> stationIds ) { |
| List<TblStation> stationList = resolveStationIds(stationIds); |
| Set<TblStation> stationSet = new HashSet<>(stationList); |
| if(stationList.size() > stationSet.size()){ |
| throw new OperationDeniedException(OperationType.INSERT, "double.assignment.of.stations"); |
| } |
| List<TblFailureInformationStation> tblFailureStations |
| = failureInformationStationRepository.findByFkTblFailureInformation(tblToStore.getId()); |
| failureInformationStationRepository.deleteAll(tblFailureStations); |
| |
| stationList.forEach(x-> { |
| TblFailureInformationStation newRecord = new TblFailureInformationStation(); |
| newRecord.setStationStationId(x.getStationId()); |
| newRecord.setFkTblFailureInformation(tblToStore.getId()); |
| failureInformationStationRepository.save(newRecord); |
| }); |
| |
| } |
| |
| private FailureInformationDto processGrid(FailureInformationDto failureInfoDto, GfiProcessState forcedState) { |
| GfiProcessSubject subject = GfiProcessSubject.of(failureInfoDto, processHelper ); |
| |
| if( forcedState != null ) { |
| subject.setStateInDb(forcedState); // use forced state |
| } |
| else { |
| // use state from db |
| RefStatus refStatus = getRefStatus(failureInfoDto); |
| subject.setStateInDb(GfiProcessState.fromValue(refStatus.getId())); |
| } |
| try { |
| grid.recover( subject ).start(subject::getStateInDb); |
| } catch (ProcessException e) { |
| log.error( e.getMessage() + " -> \r\n" + e.getStackTrace()); |
| throw new InternalServerErrorException(e.getMessage()); |
| } |
| |
| return subject.getFailureInformationDto(); |
| } |
| |
| @Transactional |
| public RefStatus getRefStatus(FailureInformationDto failureInfoDto) { |
| FailureInformationDto failureInfoDtoDB = findFailureInformation(failureInfoDto.getUuid()); |
| return statusRepository.findByUuid(failureInfoDtoDB.getStatusInternId()) |
| .orElseThrow( () -> new InternalServerErrorException("status.not.found.or.null")); |
| } |
| |
| private void setFromGridFailureInformationDto( TblFailureInformation destTblFailureInformation, FailureInformationDto sourceDto ) { |
| |
| resolveBranch(destTblFailureInformation, sourceDto); |
| resolveFailureClassification(destTblFailureInformation, sourceDto); |
| resolveStatii(destTblFailureInformation, sourceDto); |
| resolveRadius(destTblFailureInformation, sourceDto); |
| resolveExpectedReason(destTblFailureInformation, sourceDto); |
| resolveCondensed(destTblFailureInformation, sourceDto); |
| |
| destTblFailureInformation.setStations(resolveStationIds(sourceDto.getStationIds())); |
| } |
| |
| |
| private List<TblStation> resolveStationIds(List<UUID> stationUuids) { |
| if( stationUuids != null ) { |
| List<TblStation> stationList = new ArrayList<>(); |
| |
| for (UUID stationUuid: stationUuids) { |
| stationList.add(stationRepository.findByUuid(stationUuid).orElseThrow(() -> new NotFoundException("station.uuid.not.existing"))); |
| } |
| return stationList; |
| |
| } |
| return new LinkedList<>(); |
| } |
| |
| private void resolveCondensed(TblFailureInformation destTblFailureInformation, FailureInformationDto sourceDto) { |
| if( sourceDto.getFailureInformationCondensedId() != null ) { |
| destTblFailureInformation.setTblFailureInformationCondensed( failureInformationRepository |
| .findByUuid(sourceDto.getFailureInformationCondensedId()) |
| .orElseThrow(() -> new NotFoundException(Constants.FAILURE_INFO_UUID_NOT_EXISTING))); |
| } |
| else { |
| destTblFailureInformation.setTblFailureInformationCondensed(null); |
| } |
| } |
| |
| private void resolveExpectedReason(TblFailureInformation destTblFailureInformation, FailureInformationDto sourceDto) { |
| if( sourceDto.getExpectedReasonId() != null ) { |
| destTblFailureInformation.setRefExpectedReason( expectedReasonRepository |
| .findByUuid(sourceDto.getExpectedReasonId()) |
| .orElseThrow(() -> new NotFoundException("expected.reason.uuid.not.existing"))); |
| } |
| else { |
| destTblFailureInformation.setRefExpectedReason(null); |
| } |
| } |
| |
| private void resolveRadius(TblFailureInformation destTblFailureInformation, FailureInformationDto sourceDto) { |
| if( sourceDto.getRadiusId() != null ) { |
| destTblFailureInformation.setRefRadius( radiusRepository |
| .findByUuid(sourceDto.getRadiusId()) |
| .orElseThrow(() -> new NotFoundException("radius.uuid.not.existing"))); |
| } |
| else { |
| destTblFailureInformation.setRefRadius(null); |
| } |
| } |
| |
| private void resolveStatii(TblFailureInformation destTblFailureInformation, FailureInformationDto sourceDto) { |
| if( sourceDto.getStatusInternId() != null ) { |
| destTblFailureInformation.setRefStatusIntern( statusRepository |
| .findByUuid(sourceDto.getStatusInternId()) |
| .orElseThrow(() -> new NotFoundException("status.uuid.not.existing"))); |
| } |
| else { |
| destTblFailureInformation.setRefStatusIntern(null); |
| } |
| } |
| |
| private void resolveFailureClassification(TblFailureInformation destTblFailureInformation, FailureInformationDto sourceDto) { |
| if( sourceDto.getFailureClassificationId() != null ) { |
| destTblFailureInformation.setRefFailureClassification( failureClassificationRepository |
| .findByUuid(sourceDto.getFailureClassificationId()) |
| .orElseThrow(() -> new NotFoundException("failure.classification.uuid.not.existing"))); |
| } |
| else { |
| destTblFailureInformation.setRefFailureClassification(null); |
| } |
| } |
| |
| private void resolveBranch(TblFailureInformation destTblFailureInformation, FailureInformationDto sourceDto) { |
| if( sourceDto.getBranchId() != null ) { |
| destTblFailureInformation.setRefBranch( branchRepository |
| .findByUuid(sourceDto.getBranchId()) |
| .orElseThrow(() -> new NotFoundException("branch.uuid.not.existing"))); |
| } |
| else { |
| destTblFailureInformation.setRefBranch(null); |
| } |
| } |
| |
| private void setVersionNumber(TblFailureInformation tblFailureInformation){ |
| List<HtblFailureInformation> hfailureList = histFailureInformationRepository.findByUuid(tblFailureInformation.getUuid()); |
| Long lastVersion = hfailureList.stream().map(HtblFailureInformation::getVersionNumber).max(Comparator.naturalOrder()).orElse(0L) ; |
| tblFailureInformation.setVersionNumber(lastVersion+1); |
| } |
| |
| |
| public FailureInformationDto enrichFailureInfo(FailureInformationDto failureInformationDto) { |
| // wenn Mittelspannung dann füge Adress-Polygonpunkte für Kartenanzeige hinzu |
| if(failureInformationDto.getVoltageLevel() != null && failureInformationDto.getVoltageLevel().equals("MS")) { |
| addPolygonAddressPoints(failureInformationDto); |
| } |
| |
| ExternalStatusCalculator.addExternalStatus( statusRepository, failureInformationDto); |
| |
| enrichStations(failureInformationDto); |
| |
| return failureInformationDto; |
| } |
| |
| |
| @Transactional |
| public FailureInformationDto updateSubordinatedFailureInfos(UUID condensedUuid, List<UUID> subordinatedUuidList){ |
| return condenseFailureInfos(subordinatedUuidList, Optional.of(condensedUuid)); |
| } |
| |
| private void storeSubordinated(TblFailureInformation child, TblFailureInformation parent) { |
| child.setCondensed(false); |
| child.setTblFailureInformationCondensed(parent); |
| setVersionNumber(child); |
| failureInformationRepository.save(child); |
| } |
| |
| protected boolean containsAlienSubordinatedFailureInfos(Optional<UUID> condensedUuid, List<UUID> subordinatedUuidList){ |
| |
| List<TblFailureInformation> futureSubordinateFailureInfoList = failureInformationRepository |
| .findByUuidIn(subordinatedUuidList); |
| |
| List<TblFailureInformation> filteredList = futureSubordinateFailureInfoList.stream() |
| .filter(x -> x.getTblFailureInformationCondensed() != null) |
| .collect(Collectors.toList()); |
| |
| if( condensedUuid.isPresent()) { |
| filteredList = filteredList.stream() |
| .filter(x -> !x.getTblFailureInformationCondensed().getUuid().equals( condensedUuid.get()) ) |
| .collect(Collectors.toList()); |
| } |
| return !filteredList.isEmpty(); |
| } |
| |
| private void enrichStations( FailureInformationDto dto) { |
| List<UUID> stationList = failureInformationStationRepository.findUuidByFkTblFailureInformation(dto.getUuid()); |
| dto.setStationIds(stationList); |
| } |
| |
| @Transactional |
| public FailureInformationDto condenseFailureInfos(List<UUID> listUuids, Optional<UUID> condensedUuid){ |
| // pruefen, ob in der uebergebenen Liste unterzuordnender FailureInfos Teile einer anderen Verdichtung sind |
| if (containsAlienSubordinatedFailureInfos(condensedUuid, listUuids)) { |
| throw new BadRequestException("failure.info.already.subordinated"); |
| } |
| |
| if(listUuids.isEmpty()){ |
| throw new BadRequestException("empty.array.for.subordinated.failure.infos"); |
| } |
| |
| List<TblFailureInformation> listNewSubordinatedFailureInfos= failureInformationRepository.findByUuidIn(listUuids); |
| List<TblFailureInformation> oldListOfSubordinatedFailureInfos = (condensedUuid.isPresent() ? |
| failureInformationRepository.findByFailureInformationCondensedUuid(condensedUuid.get()) : new ArrayList<>()); |
| |
| if(!checkSameBranch(listNewSubordinatedFailureInfos)) { |
| throw new OperationDeniedException(OperationType.CONDENSE, "failure.infos.have.different.branches"); |
| } |
| |
| TblFailureInformation condensedFailureInformation = getOrCreateCondensedFailureInfo(condensedUuid); |
| |
| condensedFailureInformation.setRefBranch(listNewSubordinatedFailureInfos.get(0).getRefBranch()); |
| |
| setCondensedFieldsFromMany(condensedFailureInformation, listNewSubordinatedFailureInfos); |
| condensedFailureInformation.setCondensed(true); |
| condensedFailureInformation.setCondensedCount(listNewSubordinatedFailureInfos.size()); |
| TblFailureInformation condensedFailureInformationSaved = failureInformationRepository.save(condensedFailureInformation); |
| |
| storeCondensedStations(listNewSubordinatedFailureInfos, condensedFailureInformationSaved); |
| |
| //kennzeichne die neu hingefügt FailureInfos und speichere |
| listNewSubordinatedFailureInfos.stream() |
| .filter( x -> listUuids.contains(x.getUuid())) |
| .forEach( x -> storeSubordinated(x, condensedFailureInformationSaved)); |
| |
| // die alten nicht mehr zugeordneten FailureInfos freigeben |
| oldListOfSubordinatedFailureInfos.stream() |
| .filter( x -> !listUuids.contains(x.getUuid())) |
| .forEach( x -> storeSubordinated(x, null)); |
| |
| return enrichFailureInfo( failureInformationMapper.toFailureInformationDto(condensedFailureInformationSaved)); |
| |
| } |
| |
| private void setCondensedFieldsFromMany(TblFailureInformation condensedFailureInformation, List<TblFailureInformation> listSubordinatedFailureInfos) { |
| setVoltageLevel(listSubordinatedFailureInfos, condensedFailureInformation); |
| setEarliestStartdate(listSubordinatedFailureInfos, condensedFailureInformation); |
| setLatestEnddate(listSubordinatedFailureInfos, condensedFailureInformation); |
| setExpectedReason(listSubordinatedFailureInfos, condensedFailureInformation); |
| setAddress(listSubordinatedFailureInfos, condensedFailureInformation); |
| setRadius(listSubordinatedFailureInfos, condensedFailureInformation); |
| |
| |
| RefStatus refStatusNew = statusRepository |
| .findById(GfiProcessState.NEW.getStatusValue()) |
| .orElseThrow(() -> new NotFoundException("status.not.existing")); |
| |
| condensedFailureInformation.setRefStatusIntern(refStatusNew); |
| } |
| |
| private TblFailureInformation getOrCreateCondensedFailureInfo(Optional<UUID> condensedUuid) { |
| TblFailureInformation condensedFailureInformation; |
| if(condensedUuid.isPresent()){ |
| // update einer bestehenden Verdichtung |
| condensedFailureInformation = failureInformationRepository |
| .findByUuid(condensedUuid.get()) |
| .orElseThrow(() -> new NotFoundException(Constants.FAILURE_INFO_UUID_NOT_EXISTING)); |
| this.setVersionNumber(condensedFailureInformation); |
| } |
| else { |
| // neue Verdichtung |
| condensedFailureInformation = new TblFailureInformation(); |
| condensedFailureInformation.setUuid(UUID.randomUUID()); |
| condensedFailureInformation.setVersionNumber(1L); |
| } |
| return condensedFailureInformation; |
| } |
| |
| private void storeCondensedStations(List<TblFailureInformation> listFailureInfos, TblFailureInformation condensedFailureInformation) { |
| // get unique set of station (strings) from all subordinated failureinfos |
| Set<String> stationsSuperSet = new HashSet<>(); |
| listFailureInfos.forEach( x -> |
| stationsSuperSet.addAll( |
| failureInformationStationRepository.findByFkTblFailureInformation(x.getId()) |
| .stream() |
| .map( TblFailureInformationStation::getStationStationId ) |
| .collect(Collectors.toList()) |
| ) |
| ); |
| final List<TblFailureInformationStation> byFkTblFailureInformation = failureInformationStationRepository.findByFkTblFailureInformation(condensedFailureInformation.getId()); |
| Set<String> stationsOfOldExistingCondensedFi = |
| byFkTblFailureInformation.stream() |
| .map( TblFailureInformationStation::getStationStationId ) |
| .collect(Collectors.toSet()); |
| |
| // store the set for the newly created failure info |
| stationsSuperSet |
| .stream() |
| .filter( x -> !stationsOfOldExistingCondensedFi.contains(x)) |
| .forEach( x -> { |
| TblFailureInformationStation fis = new TblFailureInformationStation(); |
| fis.setFkTblFailureInformation(condensedFailureInformation.getId()); |
| fis.setStationStationId(x); |
| failureInformationStationRepository.save(fis); |
| }); |
| // remove obsolete stations |
| byFkTblFailureInformation.stream() |
| .filter( x -> !stationsSuperSet.contains(x.getStationStationId())) |
| .forEach( x -> failureInformationStationRepository.delete(x)); |
| |
| } |
| |
| private void setRadius(List<TblFailureInformation> listFailureInfos, TblFailureInformation condensedFailureInformation){ |
| |
| condensedFailureInformation.setRefRadius( |
| |
| listFailureInfos.stream() |
| .filter(fi -> fi.getRefRadius() != null) |
| .map(TblFailureInformation::getRefRadius) |
| .max( (x,y) -> Long.compare(x.getRadius(), y.getRadius())) |
| .orElse( null )); |
| |
| } |
| |
| private void setAddress(List<TblFailureInformation> listFailureInfos, TblFailureInformation condensedFailureInformation){ |
| |
| Optional<TblFailureInformation> firstCompleteFailureInformation = listFailureInfos |
| .stream() |
| .filter(f -> (f.getPostcode() != null && f.getStreet() != null && f.getHousenumber() != null) || (f.getAddressType() != null && f.getAddressType().equals(FREETEXT_ADDRESS_TYPE))) |
| .findFirst(); |
| |
| if (!firstCompleteFailureInformation.isPresent()) { |
| setCondensedFailureInformationAddress(condensedFailureInformation, null); |
| } else { |
| String address = concatAddress(firstCompleteFailureInformation.get()); |
| |
| List<TblFailureInformation> filteredList = listFailureInfos |
| .stream() |
| .filter(f -> (f.getPostcode() != null && f.getStreet() != null && f.getHousenumber() != null) || (f.getAddressType() != null && f.getAddressType().equals(FREETEXT_ADDRESS_TYPE))) |
| .filter(f -> concatAddress(f).equals(address)) |
| .collect(Collectors.toList()); |
| |
| if (listFailureInfos.size() == filteredList.size()) { |
| setCondensedFailureInformationAddress(condensedFailureInformation, firstCompleteFailureInformation.get()); |
| } |
| else{ |
| setCondensedFailureInformationAddress(condensedFailureInformation, null); |
| } |
| } |
| } |
| |
| private void setCondensedFailureInformationAddress(TblFailureInformation condensedFailureInformation, TblFailureInformation failureInformation) { |
| condensedFailureInformation.setPostcode(failureInformation != null ? failureInformation.getPostcode() : null); |
| condensedFailureInformation.setStreet(failureInformation != null ? failureInformation.getStreet() : null); |
| condensedFailureInformation.setHousenumber(failureInformation != null ? failureInformation.getHousenumber() : null); |
| condensedFailureInformation.setCity(failureInformation != null ? failureInformation.getCity() : null); |
| condensedFailureInformation.setDistrict(failureInformation != null ? failureInformation.getDistrict() : null); |
| condensedFailureInformation.setLongitude(failureInformation != null ? failureInformation.getLongitude() : null); |
| condensedFailureInformation.setLatitude(failureInformation != null ? failureInformation.getLatitude() : null); |
| condensedFailureInformation.setAddressType(failureInformation != null ? failureInformation.getAddressType() : null); |
| } |
| |
| private String concatAddress(TblFailureInformation failureInformation) { |
| if (failureInformation == null) return null; |
| return failureInformation.getPostcode() + failureInformation.getStreet() + failureInformation.getHousenumber(); |
| } |
| |
| private void setExpectedReason(List<TblFailureInformation> listFailureInfos, TblFailureInformation condensedFailureInformation){ |
| RefExpectedReason firstExpReason = listFailureInfos.get(0).getRefExpectedReason(); |
| UUID firstExpectedReason = firstExpReason != null ? firstExpReason.getUuid() : null; |
| |
| List<TblFailureInformation> filteredList = listFailureInfos |
| .stream() |
| .filter(f-> f.getRefExpectedReason() != null && f.getRefExpectedReason().getUuid()!=null) |
| .filter(f -> f.getRefExpectedReason().getUuid().equals(firstExpectedReason)) |
| .collect(Collectors.toList()); |
| |
| if (listFailureInfos.size() == filteredList.size()) { |
| condensedFailureInformation.setRefExpectedReason(listFailureInfos.get(0).getRefExpectedReason()); |
| } |
| else{ |
| condensedFailureInformation.setRefExpectedReason(null); |
| } |
| } |
| |
| private void setLatestEnddate(List<TblFailureInformation> listFailureInfos, TblFailureInformation condensedFailureInformation){ |
| |
| Date latest = listFailureInfos |
| .stream() |
| .filter(f -> f.getFailureEndPlanned() != null) |
| .map(TblFailureInformation::getFailureEndPlanned).max(Comparator.naturalOrder()) |
| .orElse(null); |
| |
| condensedFailureInformation.setFailureEndPlanned(latest); |
| } |
| |
| private void setEarliestStartdate(List<TblFailureInformation> listFailureInfos, TblFailureInformation condensedFailureInfo){ |
| |
| Date earliest = listFailureInfos |
| .stream() |
| .filter(f -> f.getFailureBegin() != null) |
| .map(TblFailureInformation::getFailureBegin).min(Comparator.naturalOrder()) |
| .orElse(null); |
| |
| condensedFailureInfo.setFailureBegin(earliest); |
| } |
| |
| private boolean checkSameBranch(List<TblFailureInformation> listFailureInfos){ |
| |
| RefBranch firstBranch = listFailureInfos.get(0).getRefBranch(); |
| List<TblFailureInformation> filteredList = listFailureInfos.stream().filter(f -> f.getRefBranch().equals(firstBranch)).collect(Collectors.toList()); |
| |
| return listFailureInfos.size() == filteredList.size(); |
| } |
| |
| private void setVoltageLevel(List<TblFailureInformation> listFailureInfos, TblFailureInformation condensedFailureInfo){ |
| |
| String firstVoltageLevel = listFailureInfos.get(0).getVoltageLevel(); |
| |
| List<TblFailureInformation> filteredList = listFailureInfos |
| .stream() |
| .filter(f -> f.getVoltageLevel()!= null) |
| .filter(f -> f.getVoltageLevel().equals(firstVoltageLevel)) |
| .collect(Collectors.toList()); |
| |
| if (listFailureInfos.size() == filteredList.size()) { |
| condensedFailureInfo.setVoltageLevel(firstVoltageLevel); |
| } |
| else{ |
| condensedFailureInfo.setVoltageLevel(null); |
| } |
| } |
| |
| private void addPolygonAddressPoints(FailureInformationDto failureInformationDto){ |
| |
| // Stationen ermitteln |
| List<UUID> stationUuids = |
| failureInformationStationRepository.findUuidByFkTblFailureInformation(failureInformationDto.getUuid()); |
| |
| if(stationUuids.isEmpty()) { |
| log.debug("No station ids found for failureInfo: " + failureInformationDto.getUuid().toString()); |
| return; |
| } |
| |
| List<ArrayList<BigDecimal>> addressPolygonPoints = getPolygonCoordinatesForStationUuids(stationUuids); |
| |
| if(!addressPolygonPoints.isEmpty()) { |
| failureInformationDto.setAddressPolygonPoints(addressPolygonPoints); |
| } |
| } |
| |
| |
| public List<ArrayList<BigDecimal>> getPolygonCoordinatesForStationUuids (List<UUID> stationUuids) { |
| |
| List<TblAddress> allAdresses = new ArrayList<>(); |
| List<ArrayList<BigDecimal>> addressPolygonPoints = new LinkedList<>(); |
| |
| // Holen der Adressen, die fuer die Stoerungsinformation relevant sind |
| for (UUID stationUuid : stationUuids) { |
| TblStation tblStation = stationRepository |
| .findByUuid(stationUuid) |
| .orElse(null); |
| |
| if (tblStation == null) { |
| log.warn("station " + stationUuid.toString() + "not found "); |
| } else { |
| List<TblAddress> addressListForStation = addressRepository.findByStationId(tblStation.getStationId()); |
| if (addressListForStation.isEmpty()) { |
| log.debug("Station " + stationUuid.toString() + "has no addresses."); |
| |
| } else { |
| allAdresses.addAll(addressListForStation); |
| } |
| } |
| } |
| |
| List<Point> addressPoints = new LinkedList<>(); |
| // Hinzufügen der gefundenen Adressen zur Liste der Adresspunkte |
| // (Multiplikation mit 1000000 notwendig zur Erlangung von ganzzahligen Werten für die Übergabe an GrahamScan) |
| allAdresses |
| .forEach(x -> addressPoints.add |
| (new Point((x.getLatitude().setScale(6, RoundingMode.FLOOR).movePointRight(6)).intValue(), |
| (x.getLongitude().setScale(6, RoundingMode.FLOOR).movePointRight(6)).intValue()))); |
| |
| if (addressPoints.isEmpty()) { |
| log.debug("No addresses for the given stations available"); |
| return addressPolygonPoints; |
| } |
| |
| // GrahamScan über die Adresspunkte zum Erhalt der äußeren Punkte, die ein Polygon bilden |
| List<Point> polygonPoints = GrahamScan.getConvexHull(addressPoints); |
| |
| |
| // Verpacken der Polygonpunkte in eine Liste von Arrays (longitude/latitude) die ins DTO der Störungsmeldung geschrieben wird |
| // (Division durch 1000000 notwendig zur Wiedererlangung der ursprünglichen Werte) |
| for (Point point : polygonPoints) { |
| ArrayList<BigDecimal> twoValues = new ArrayList<>(); |
| twoValues.add(BigDecimal.valueOf(point.getX()).movePointLeft(6)); |
| twoValues.add(BigDecimal.valueOf(point.getY()).movePointLeft(6)); |
| addressPolygonPoints.add(twoValues); |
| } |
| |
| return addressPolygonPoints; |
| } |
| |
| public FailureInformationPublicationChannelDto insertPublicationChannelForFailureInfo(UUID failureInfoUuid, String publicationChannel){ |
| |
| TblFailureInformation existingTblFailureInformation = failureInformationRepository |
| .findByUuid(failureInfoUuid) |
| .orElseThrow(() -> new NotFoundException(Constants.FAILURE_INFO_UUID_NOT_EXISTING)); |
| |
| //check if channel is already existing |
| if(failureInformationPublicationChannelRepository.countByTblFailureInformationAndPublicationChannel(existingTblFailureInformation, publicationChannel)>0){ |
| throw new BadRequestException("channel.already.existing"); |
| } |
| |
| //create new channel |
| TblFailureInformationPublicationChannel tfiPublicationChannelToSave = new TblFailureInformationPublicationChannel(); |
| tfiPublicationChannelToSave.setTblFailureInformation(existingTblFailureInformation); |
| tfiPublicationChannelToSave.setPublicationChannel(publicationChannel); |
| tfiPublicationChannelToSave.setPublished(false); |
| |
| TblFailureInformationPublicationChannel savedTfiPublicationChannel = failureInformationPublicationChannelRepository.save(tfiPublicationChannelToSave); |
| |
| return failureInformationPublicationChannelMapper.toFailureInformationPublicationChannelDto(savedTfiPublicationChannel); |
| } |
| |
| public void deletePublicationChannelForFailureInfo(UUID failureInfoUuid, String publicationChannel){ |
| |
| TblFailureInformation existingTblFailureInformation = failureInformationRepository |
| .findByUuid(failureInfoUuid) |
| .orElseThrow(() -> new NotFoundException(Constants.FAILURE_INFO_UUID_NOT_EXISTING)); |
| |
| TblFailureInformationPublicationChannel existingTblFailureInformationPublicationChannel = failureInformationPublicationChannelRepository |
| .findByTblFailureInformationAndPublicationChannel(existingTblFailureInformation, publicationChannel) |
| .orElseThrow(() -> new NotFoundException("channel.not.existing")); |
| |
| failureInformationPublicationChannelRepository.delete(existingTblFailureInformationPublicationChannel); |
| |
| } |
| |
| |
| public List<FailureInformationPublicationChannelDto> getPublicationChannelsForFailureInfo(UUID failureInfoUuid){ |
| |
| TblFailureInformation existingTblFailureInformation = failureInformationRepository |
| .findByUuid(failureInfoUuid) |
| .orElseThrow(() -> new NotFoundException(Constants.FAILURE_INFO_UUID_NOT_EXISTING)); |
| |
| List<TblFailureInformationPublicationChannel> publicationChannels = failureInformationPublicationChannelRepository |
| .findByTblFailureInformation(existingTblFailureInformation); |
| |
| return publicationChannels |
| .stream() |
| .map(x -> failureInformationPublicationChannelMapper.toFailureInformationPublicationChannelDto(x)) |
| .collect(Collectors.toList()); |
| |
| } |
| |
| @Transactional |
| public void deleteFailureInfo(UUID failureInfoUuid){ |
| |
| TblFailureInformation existingTblFailureInformation = failureInformationRepository |
| .findByUuid(failureInfoUuid) |
| .orElseThrow(() -> new NotFoundException("failure.info.uuid.not.existing")); |
| |
| if(isStatusNewPlannedCreated(existingTblFailureInformation)){ |
| |
| failureInformationPublicationChannelRepository.findByTblFailureInformation(existingTblFailureInformation) |
| .forEach(failureInformationPublicationChannelRepository::delete); |
| |
| Optional<TblFailureInformationReminderMailSent> reminder = failureInformationReminderMailSentRepository.findByTblFailureInformation(existingTblFailureInformation); |
| if(reminder.isPresent()) { |
| failureInformationReminderMailSentRepository.deleteByTblFailureInformation(existingTblFailureInformation); |
| } |
| |
| failureInformationStationRepository.findByFkTblFailureInformation(existingTblFailureInformation.getId()) |
| .forEach(failureInformationStationRepository::delete); |
| |
| failureInformationDistributionGroupRepository.findByFkTblFailureInformation(existingTblFailureInformation.getId()) |
| .forEach(failureInformationDistributionGroupRepository::delete); |
| |
| failureInformationRepository.findByFailureInformationCondensedUuid(existingTblFailureInformation.getUuid()) |
| .forEach( this::undoCondensedOnParentDelete ); |
| failureInformationRepository.delete(existingTblFailureInformation); |
| } |
| else{ |
| throw new BadRequestException("delete.not.allowed"); |
| } |
| } |
| |
| public FailureInformationLastModDto getFailureInformationLastModTimeStamp() { |
| FailureInformationLastModDto lastModDto = new FailureInformationLastModDto(); |
| List<TblFailureInformation> visibleList = findFailureInformationsForDisplay(Pageable.unpaged()).toList(); |
| |
| // get the newest Elem out of the list of visible elements |
| TblFailureInformation newestElem = visibleList.stream().max( (x,y) -> x.getModDate().compareTo(y.getModDate())) |
| .orElseThrow( () -> new NotFoundException("no.failures.available")); |
| lastModDto.setLastModification(newestElem.getModDate()); |
| lastModDto.setUuid(newestElem.getUuid()); |
| |
| return lastModDto; |
| } |
| |
| |
| private void undoCondensedOnParentDelete(TblFailureInformation x) { |
| x.setTblFailureInformationCondensed(null); |
| setVersionNumber(x); |
| failureInformationRepository.save(x); |
| } |
| |
| private boolean isStatusNewPlannedCreated(TblFailureInformation tblFailureInformation){ |
| RefStatus refStatus = tblFailureInformation.getRefStatusIntern(); |
| return (refStatus.getStatus().equals("neu") || refStatus.getStatus().equals("geplant") || refStatus.getStatus().equals("angelegt")); |
| } |
| |
| |
| |
| } |