ResourceAggregator { public List<? extends Resource> intersection( List<? extends Resource> resourcesA, List<? extends Resource> resourcesB) { checkSupporting(resourcesA); checkSupporting(resourcesB); final Set<String> keysA = resourcesA.stream().map(Resource::getType).collect(toSet()); final Set<String> keysB = resourcesB.stream().map(Resource::getType).collect(toSet()); final Set<String> commonKeys = ImmutableSet.copyOf(Sets.intersection(keysA, keysB)); return Stream.concat(resourcesA.stream(), resourcesB.stream()) .filter(res -> commonKeys.contains(res.getType())) .collect(Collectors.toList()); } @Inject  ResourceAggregator(Set<ResourceType> resourcesTypes); Map<String, Resource> aggregateByType(List<? extends Resource> resources); List<? extends Resource> deduct(
      List<? extends Resource> sourceResources, List<? extends Resource> resourcesToDeduct); List<? extends Resource> excess(
      List<? extends Resource> sourceResources, List<? extends Resource> resourcesToCompare); Resource aggregate(Resource resourceA, Resource resourceB); Resource deduct(Resource totalResource, Resource deduction); List<? extends Resource> intersection(
      List<? extends Resource> resourcesA, List<? extends Resource> resourcesB); List<? extends Resource> min(Collection<? extends Resource> resources);  }
@Test public void shouldReturnIntersectionOfTwoResourcesLists() throws Exception { final ResourceImpl aResource = new ResourceImpl(A_RESOURCE_TYPE, 123, "unit"); final ResourceImpl bResource = new ResourceImpl(B_RESOURCE_TYPE, 123, "unit"); final ResourceImpl anotherBResource = new ResourceImpl(B_RESOURCE_TYPE, 321, "unit"); final ResourceImpl cResource = new ResourceImpl(C_RESOURCE_TYPE, 321, "unit"); List<? extends Resource> intersection = resourceAggregator.intersection( asList(aResource, bResource), asList(anotherBResource, cResource)); assertEquals(intersection.size(), 2); assertTrue(intersection.contains(bResource)); assertTrue(intersection.contains(anotherBResource)); }
@Test(expectedExceptions = IllegalArgumentException.class) public void shouldThrowIllegalArgumentExceptionWhenFirstListContainsResourceWithUnsupportedTypeOnIntersection() throws Exception { final ResourceImpl dResource = mock(ResourceImpl.class); when(dResource.getType()).thenReturn("resourceD"); resourceAggregator.intersection(singletonList(dResource), emptyList()); }
@Test(expectedExceptions = IllegalArgumentException.class) public void shouldThrowIllegalArgumentExceptionWhenSecondListContainsResourceWithUnsupportedTypeOnIntersection() throws Exception { final ResourceImpl dResource = mock(ResourceImpl.class); when(dResource.getType()).thenReturn("resourceD"); resourceAggregator.intersection(emptyList(), singletonList(dResource)); }