DistanceMatrixImpl implements DistanceMatrix { @Override public DistanceMatrixRow addLocation(Location newLocation) { Map<Long, Distance> distancesToOthers = new ConcurrentHashMap<>(); distancesToOthers.put(newLocation.id(), Distance.ZERO); matrix.entrySet().stream().parallel().forEach(distanceRow -> { Location other = distanceRow.getKey(); Map<Long, Distance> distancesFromOther = distanceRow.getValue(); distancesFromOther.put(newLocation.id(), calculateOrRestoreDistance(other, newLocation)); distancesToOthers.put(other.id(), calculateOrRestoreDistance(newLocation, other)); }); matrix.put(newLocation, distancesToOthers); return locationId -> { if (!distancesToOthers.containsKey(locationId)) { throw new IllegalArgumentException( "Distance from " + newLocation + " to " + locationId + " hasn't been recorded.\n" + "We only know distances to " + distancesToOthers.keySet()); } return distancesToOthers.get(locationId); }; } @Autowired  DistanceMatrixImpl(DistanceCalculator distanceCalculator, DistanceRepository distanceRepository); @Override DistanceMatrixRow addLocation(Location newLocation); @Override void removeLocation(Location location); @Override void clear(); int dimension();  }
@Test void should_call_router_and_persist_distances_when_repo_is_empty() { Location l1 = location(100, -1); Location l2 = location(111, 20); long dist12 = 12; long dist21 = 21; when(distanceRepository.getDistance(any(), any())).thenReturn(-1L); when(distanceCalculator.travelTimeMillis(l1.coordinates(), l2.coordinates())).thenReturn(dist12); when(distanceCalculator.travelTimeMillis(l2.coordinates(), l1.coordinates())).thenReturn(dist21); distanceMatrix.addLocation(l1); verifyNoInteractions(distanceCalculator); verifyNoInteractions(distanceRepository); distanceMatrix.addLocation(l2); verify(distanceRepository).getDistance(l2, l1); verify(distanceRepository).getDistance(l1, l2); verify(distanceRepository).saveDistance(l2, l1, dist21); verify(distanceRepository).saveDistance(l1, l2, dist12); }
@Test void should_not_call_router_when_repo_is_full() { Location l1 = location(1, 0); Location l2 = location(2, 0); when(distanceRepository.getDistance(l1, l2)).thenReturn(0L); when(distanceRepository.getDistance(l2, l1)).thenReturn(1L); distanceMatrix.addLocation(l1); verifyNoInteractions(distanceCalculator); verifyNoInteractions(distanceRepository); distanceMatrix.addLocation(l2); verify(distanceRepository).getDistance(l2, l1); verify(distanceRepository).getDistance(l1, l2); verify(distanceRepository, never()).saveDistance(any(Location.class), any(Location.class), anyLong()); verifyNoInteractions(distanceCalculator); }