class DataMigrationRepository {

    public CloseableIterator<List<Unit>> selectUnitBulkInTopDownHierarchyLevel() {

        MongoCursor<Unit> unitMongoCursor = selectUnitsInTopDownHierarchyLevel();

        PeekingIterator<Unit> unitPeekingIterator = new PeekingIterator<>(unitMongoCursor);

        return new CloseableIterator<List<Unit>>() {

            int lastLevel;

            @Override
            public void close() {
                unitMongoCursor.close();
            }

            @Override
            public boolean hasNext() {
                return unitPeekingIterator.hasNext();
            }

            @Override
            public List<Unit> next() {

                if (!hasNext()) {
                    throw new NoSuchElementException();
                }

                List<String> bulkUnitIds = new ArrayList<>();

                // Bulk processing
                while (unitMongoCursor.hasNext()) {

                    Unit unit = unitPeekingIterator.peek();

                    int unitLevel = unit.getInteger(DataMigrationRepository.NB_UNIT_UPS);

                    boolean shouldSplitUnitLevel = !bulkUnitIds.isEmpty() && unitLevel > lastLevel;
                    if (shouldSplitUnitLevel) {
                        lastLevel = unitLevel;
                        break;
                    }

                    unit = unitPeekingIterator.next();
                    bulkUnitIds.add(unit.getId());

                    boolean shouldSplitByBulkSize = bulkUnitIds.size() == bulkSize;
                    if (shouldSplitByBulkSize) {
                        break;
                    }
                }

                return getUnitsByIds(bulkUnitIds);
            }
        };
    }

    public  DataMigrationRepository();
    @VisibleForTesting  DataMigrationRepository(int bulkSize);

}