SortHandler implements OutputOperationHandler<Sort, Iterable<? extends Element>> { @Override public Iterable<? extends Element> doOperation(final Sort operation, final Context context, final Store store) throws OperationException { if (null == operation.getInput() || null == operation.getComparators() || operation.getComparators().isEmpty()) { return null; } if (null != operation.getResultLimit() && 1 == operation.getResultLimit()) { final Element max = MAX_HANDLER.doOperation(new Max.Builder() .comparators(operation.getComparators()) .input(operation.getInput()) .build(), context, store); if (null == max) { return Collections.emptyList(); } return Collections.singletonList(max); } try (final Stream<? extends Element> stream = Streams.toStream(operation.getInput()) .filter(Objects::nonNull)) { return stream.collect( GafferCollectors.toLimitedInMemorySortedIterable( operation.getCombinedComparator(), operation.getResultLimit(), operation.isDeduplicate() ) ); } finally { CloseableUtil.close(operation); } }  @Override Iterable<? extends Element> doOperation(final Sort operation, final Context context, final Store store);  }
@Test public void shouldSortBasedOnProperty() throws OperationException, JsonProcessingException { final Entity entity1 = new Entity.Builder().group(TestGroups.ENTITY).property("property", 1).build(); final Entity entity2 = new Entity.Builder().group(TestGroups.ENTITY).property("property", 2).build(); final Entity entity3a = new Entity.Builder().group(TestGroups.ENTITY).property("property", 3) .property("otherProp", "a").build(); final Entity entity3b = new Entity.Builder().group(TestGroups.ENTITY).property("property", 3) .property("otherProp", "b").build(); final Entity entity4 = new Entity.Builder().group(TestGroups.ENTITY).property("property", 4).build(); final List<Entity> input = Lists.newArrayList(entity1, entity4, entity3a, entity3b, entity2); final Sort sort = new Sort.Builder().input(input).comparators(new ElementPropertyComparator.Builder() .groups(TestGroups.ENTITY).property("property").build()).build(); final SortHandler handler = new SortHandler(); final Iterable<? extends Element> result = handler.doOperation(sort, null, null); final List<? extends Element> resultList = Lists.newArrayList(result); assertTrue(Arrays.asList(entity1, entity2, entity3a, entity3b, entity4).equals(resultList) || Arrays.asList(entity1, entity2, entity3b, entity3a, entity4).equals(resultList), "Expected: \n" + Arrays.asList(entity1, entity2, entity3a, entity3b, entity4) + "\n but got: \n" + resultList); }
@Test public void shouldSortBasedOnProperty_reversed() throws OperationException, JsonProcessingException { final Entity entity1 = new Entity.Builder().group(TestGroups.ENTITY).property("property", 1).build(); final Entity entity2 = new Entity.Builder().group(TestGroups.ENTITY).property("property", 2).build(); final Entity entity3 = new Entity.Builder().group(TestGroups.ENTITY).property("property", 3).build(); final Entity entity4 = new Entity.Builder().group(TestGroups.ENTITY).property("property", 4).build(); final List<Entity> input = Lists.newArrayList(entity1, entity2, entity3, entity4); final Sort sort = new Sort.Builder().input(input) .comparators(new ElementPropertyComparator.Builder().groups(TestGroups.ENTITY) .property("property").comparator(new PropertyComparatorImpl()) .reverse(true).build()) .build(); final SortHandler handler = new SortHandler(); final Iterable<? extends Element> result = handler.doOperation(sort, null, null); assertEquals(Arrays.asList(entity4, entity3, entity2, entity1), Lists.newArrayList(result)); }
@Test public void shouldSortBasedOn2Properties() throws OperationException, JsonProcessingException { final Entity entity1 = new Entity.Builder().group(TestGroups.ENTITY).property("property1", 1) .property("property2", 1).build(); final Entity entity2 = new Entity.Builder().group(TestGroups.ENTITY).property("property1", 1) .property("property2", 2).build(); final Entity entity3 = new Entity.Builder().group(TestGroups.ENTITY).property("property1", 2) .property("property2", 2).build(); final Entity entity4 = new Entity.Builder().group(TestGroups.ENTITY).property("property1", 2) .property("property2", 1).build(); final List<Entity> input = Lists.newArrayList(entity1, entity3, entity2, entity4); final Sort sort = new Sort.Builder().input(input) .comparators(new ElementPropertyComparator.Builder().groups(TestGroups.ENTITY) .property("property1").build(), new ElementPropertyComparator.Builder().groups(TestGroups.ENTITY) .property("property2").build()) .build(); final SortHandler handler = new SortHandler(); final Iterable<? extends Element> result = handler.doOperation(sort, null, null); assertEquals(Arrays.asList(entity1, entity2, entity4, entity3), Lists.newArrayList(result)); }
@Test public void shouldSortBasedOnPropertyIncludingNulls() throws OperationException, JsonProcessingException { final Entity entity1 = new Entity.Builder().group(TestGroups.ENTITY).property("property", 1).build(); final Entity entity2 = new Entity.Builder().group(TestGroups.ENTITY).property("property", 2).build(); final Entity entity3 = new Entity.Builder().group(TestGroups.ENTITY).property("property", 3).build(); final Entity entity4 = new Entity.Builder().group(TestGroups.ENTITY).build(); final Entity entity5 = new Entity.Builder().group(TestGroups.ENTITY).build(); final List<Entity> input = Lists.newArrayList(entity1, entity3, entity4, entity2, entity5); final Sort sort = new Sort.Builder().input(input) .comparators(new ElementPropertyComparator.Builder().property("property") .groups(TestGroups.ENTITY).comparator(new PropertyComparatorImpl()) .build()) .deduplicate(true).build(); final SortHandler handler = new SortHandler(); final Iterable<? extends Element> result = handler.doOperation(sort, null, null); assertEquals(Arrays.asList(entity1, entity2, entity3, entity4), Lists.newArrayList(result)); }
@Test public void shouldReturnNullsLast() throws OperationException, JsonProcessingException { final Entity entity1 = new Entity.Builder().group(TestGroups.ENTITY).property("property", 1).build(); final Entity entity2 = new Entity.Builder().group(TestGroups.ENTITY).property("property", 2).build(); final Entity entity3 = new Entity.Builder().group(TestGroups.ENTITY).property("property", 3).build(); final Entity entity4 = new Entity.Builder().group(TestGroups.ENTITY).build(); final Entity entity5 = new Entity.Builder().group(TestGroups.ENTITY).build(); final List<Entity> input = Lists.newArrayList(entity1, entity3, entity2, entity4, entity5); final Sort sort = new Sort.Builder().input(input) .comparators(new ElementPropertyComparator.Builder().property("property") .groups(TestGroups.ENTITY).comparator(new PropertyComparatorImpl()) .build()) .deduplicate(false).build(); final SortHandler handler = new SortHandler(); final Iterable<? extends Element> result = handler.doOperation(sort, null, null); assertEquals(5, Iterables.size(result)); assertNull(Iterables.getLast(result).getProperty("property")); assertNotNull(Iterables.getFirst(result, null).getProperty("property")); }
@Test public void shouldSortBasedOnElement() throws OperationException { final Entity entity1 = new Entity.Builder().group(TestGroups.ENTITY).property("property1", 1) .property("property2", 1).build(); final Entity entity2 = new Entity.Builder().group(TestGroups.ENTITY).property("property1", 2) .property("property2", 2).build(); final Entity entity3 = new Entity.Builder().group(TestGroups.ENTITY).property("property1", 3) .property("property2", 3).build(); final Entity entity4 = new Entity.Builder().group(TestGroups.ENTITY).property("property1", 4) .property("property2", 4).build(); final List<Entity> input = Lists.newArrayList(entity1, entity3, entity2, entity4); final Sort sort = new Sort.Builder().input(input).comparators(new ElementComparatorImpl()).build(); final SortHandler handler = new SortHandler(); final Iterable<? extends Element> result = handler.doOperation(sort, null, null); int prev = Integer.MIN_VALUE; for (final Element element : result) { final int curr = (int) element.getProperty("property1"); assertTrue(curr > prev); prev = curr; } }
@Test public void shouldNotThrowExceptionIfIterableIsEmpty() throws OperationException { final List<Entity> input = Lists.newArrayList(); final Sort sort = new Sort.Builder().input(input).comparators(new ElementPropertyComparator.Builder() .groups(TestGroups.ENTITY).property("property").build()).build(); final SortHandler handler = new SortHandler(); final Iterable<? extends Element> result = handler.doOperation(sort, null, null); assertTrue(Streams.toStream(result).collect(Collectors.toList()).isEmpty()); }
@Test public void shouldReturnNullIfOperationInputIsNull() throws OperationException { final Sort sort = new Sort.Builder().build(); final SortHandler handler = new SortHandler(); final Iterable<? extends Element> result = handler.doOperation(sort, null, null); assertNull(result); }
@Test public void shouldReturnOriginalListIfBothComparatorsAreNull() throws OperationException { final List<Entity> input = Lists.newArrayList(); final Sort sort = new Sort.Builder().input(input).build(); final SortHandler handler = new SortHandler(); final Iterable<? extends Element> result = handler.doOperation(sort, null, null); assertNull(result); }
@Test public void shouldSortLargeNumberOfElements() throws OperationException { final int streamSize = 10000; final int resultLimit = 5000; final Stream<Element> stream = new Random().ints(streamSize * 2) .distinct().limit(streamSize).mapToObj(i -> new Entity.Builder() .group(TestGroups.ENTITY).property("property", i).build()); final Sort sort = new Sort.Builder().input(() -> stream.iterator()) .comparators(new ElementPropertyComparator.Builder().groups(TestGroups.ENTITY) .property("property").reverse(false).build()) .resultLimit(resultLimit).deduplicate(true).build(); final SortHandler handler = new SortHandler(); final Iterable<? extends Element> result = handler.doOperation(sort, null, null); final ArrayList<? extends Element> elements = Lists.newArrayList(result); final ArrayList<? extends Element> sortedElements = Lists.newArrayList(result); sortedElements.sort(new ElementPropertyComparator.Builder().groups(TestGroups.ENTITY) .property("property").reverse(false).build()); assertEquals(elements, sortedElements); assertNotNull(result); assertEquals(resultLimit, Iterables.size(result)); }