org.alfresco.repo.virtual.page.PageCollatorTest.java Source code

Java tutorial

Introduction

Here is the source code for org.alfresco.repo.virtual.page.PageCollatorTest.java

Source

/*
 * #%L
 * Alfresco Repository
 * %%
 * Copyright (C) 2005 - 2016 Alfresco Software Limited
 * %%
 * This file is part of the Alfresco software. 
 * If the software was purchased under a paid Alfresco license, the terms of 
 * the paid license agreement will prevail.  Otherwise, the software is 
 * provided under the following open source license terms:
 * 
 * Alfresco is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Alfresco is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
 * #L%
 */

package org.alfresco.repo.virtual.page;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

import junit.framework.TestCase;

import org.alfresco.query.ListBackedPagingResults;
import org.alfresco.query.PagingRequest;
import org.alfresco.query.PagingResults;
import org.alfresco.repo.virtual.page.PageCollator.PagingResultsSource;
import org.alfresco.util.Pair;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Test;
import org.springframework.util.comparator.ComparableComparator;

public class PageCollatorTest extends TestCase {
    private static Log logger = LogFactory.getLog(PageCollatorTest.class);

    @Override
    protected void setUp() throws Exception {
        super.setUp();
    }

    private int[] createMergedPage(int skip, int count, List<Integer> s1, Integer[] s2) {
        return createMergedPage(skip, count, s1, ArrayUtils.toPrimitive(s2));
    }

    private int[] createMergedPage(int skip, int count, List<Integer> s1, int[] s2) {
        int[] s1Primitive = (s1 == null || s1.isEmpty()) ? new int[] {}
                : ArrayUtils.toPrimitive((Integer[]) s1.toArray());

        return createMergedPage(skip, count, s1Primitive, s2);
    }

    /**
     * Creates an page-array by concatenating the given arrays than skipping and
     * trimming the resulted array.
     * 
     * @param skip
     * @param count
     * @param s1
     * @param s2
     * @return a page-array obtained by merging <code>s1</code> and
     *         <code>s2</code>, sorting the result than copying
     *         <code>count</code> elements from the concatenation starting with
     *         the element at index <code>skip</code> into the returned array of
     *         size <code>count</code>. If <code>skip</code> value is out of
     *         bounds an empty array is returned.
     */
    private int[] createMergedPage(int skip, int count, int[] s1, int[] s2) {
        final int[] m = Arrays.copyOf(s1, s1.length + s2.length);
        System.arraycopy(s2, 0, m, s1.length, s2.length);
        Arrays.sort(m);

        final int zeroCount = (count == 0 ? m.length : count);

        final int len = Math.min(m.length - skip, zeroCount);
        if (len > 0) {
            int[] p = new int[len];

            System.arraycopy(m, skip, p, 0, len);

            return p;
        } else {
            return new int[] {};
        }
    }

    private void assertEqualPages(int[] expected, int[] actual) {
        assertEqualPages(Arrays.toString(expected) + " vs " + Arrays.toString(actual), expected, actual);
    }

    private void assertEqualPages(String message, int[] expected, int[] actual) {
        assertTrue(message, Arrays.equals(expected, actual));
    }

    private void assertEqualPages(String message, int[] expected, List<Integer> page) {
        assertEqualPages(message, expected, ArrayUtils.toPrimitive((Integer[]) page.toArray(new Integer[] {})));
    }

    @Test
    public void testCreateMergedPage() throws Exception {
        // { 0, 1, 2, 3, 4, 7, 8, 9, 10 }
        final int[] s1 = new int[] { 0, 1, 3, 7, 8 };
        final int[] s2 = new int[] { 2, 4, 9, 10 };

        assertEqualPages(new int[] { 2, 3, 4 }, createMergedPage(2, 3, s1, s2));

        assertEqualPages(new int[] { 9, 10 }, createMergedPage(7, 2, s1, s2));

        assertEqualPages(new int[] { 0, 1, 2, 3, 4 }, createMergedPage(0, 5, s1, s2));

        assertEqualPages(new int[] { 0, 1, 2, 3, 4 }, createMergedPage(0, 5, s1, s2));

        assertEqualPages(new int[] { 4, 7, 8, 9 }, createMergedPage(4, 4, s1, s2));

        assertEqualPages(new int[] {}, createMergedPage(10, 4, s1, s2));

        assertEqualPages(new int[] {}, createMergedPage(9, 1, s1, s2));

        assertEqualPages(new int[] {}, createMergedPage(9, 1, s1, s2));

        assertEqualPages(new int[] {}, createMergedPage(11, 3, s1, s2));

        final int[] s3 = new int[] { 2, 3 };
        final int[] s4 = new int[] { 7, 10, 13, 11 };

        assertEqualPages(new int[] { 13 }, createMergedPage(5, 2, s3, s4));

        final int[] s5 = new int[] { 1, 2, 3 };
        final int[] s6 = new int[] { 5 };

        assertEqualPages(new int[] { 5 }, createMergedPage(3, 1, s5, s6));

        assertEqualPages(new int[] { 1, 2, 3, 5 }, createMergedPage(0, 0, s5, s6));
    }

    /**
     * A page source that uses a generic array for the entire possible page
     * range.
     * 
     * @author Bogdan Horje
     * @param <R>
     */
    class ArrayPageSource<R> implements PagingResultsSource<R> {
        private R[] array;

        private boolean boundsError;

        public ArrayPageSource(R[] array) {
            this(array, true);
        }

        public ArrayPageSource(R[] array, boolean boundsError) {
            super();
            this.array = array;
            this.boundsError = boundsError;
        }

        @Override
        public PagingResults<R> retrieve(PagingRequest pr) throws PageCollationException {
            final int skip = pr.getSkipCount();
            final int pageSize = pr.getMaxItems();
            if (skip < 0 || pageSize < 0) {
                throw new PageCollationException("Invalid page!");
            }

            if (boundsError && (skip >= array.length)) {
                throw new InvalidPageBounds("Out of bounds " + skip + ">=" + array.length);
            }

            return new ListBackedPagingResults<R>(Arrays.asList(array), pr);
        }

    }

    public void assertCollate(List<Integer> results, Integer[] source, int skip, int pageSize) throws Exception {
        assertCollate(results, source, skip, pageSize, false);
    }

    public void assertCollate(List<Integer> results, Integer[] source, int skip, int pageSize, boolean boundsError)
            throws Exception {
        Arrays.sort(source);
        Collections.sort(results);
        int[] expected = createMergedPage(skip, pageSize, results, source);
        PagingResults<Integer> actualResults = new PageCollator<Integer>().collate(results,
                new ArrayPageSource(source), new PagingRequest(skip, pageSize),
                new ComparableComparator<Integer>());
        List<Integer> actualPage = actualResults.getPage();

        final String message = "[" + results + " + " + Arrays.toString(source) + " ] -> "
                + Arrays.toString(expected) + " != " + actualPage;
        assertEqualPages(message, expected, actualPage);
        assertEquals("Invalid moreItems info!",
                (pageSize != 0) && (skip + pageSize < results.size() + source.length),
                actualResults.hasMoreItems());
        assertTrue(message, (pageSize == 0) || actualPage.size() <= pageSize);
        final int expectedTotal = source.length + results.size();
        if (boundsError && !new Pair<Integer, Integer>(null, null).equals(actualResults.getTotalResultCount())) {
            assertEquals("Invalid total info", new Pair<Integer, Integer>(expectedTotal, expectedTotal),
                    actualResults.getTotalResultCount());
        }
        logger.info(actualPage);
    }

    @Test
    public void testCollate() throws Exception {
        final List<Integer> s1 = Arrays.asList(2, 4, 9, 10);
        final Integer[] s2 = new Integer[] { 0, 1, 3, 5, 7, 8 };

        assertCollate(s1, s2, 0, 3);
        assertCollate(s1, s2, 2, 3);

        final List<Integer> s3 = Arrays.asList(2, 4, 9, 10, 12, 15, 17, 18);
        final Integer[] s4 = new Integer[] { 0, 1, 3, 8, 16, 19 };

        assertCollate(s3, s4, 0, 3);
        assertCollate(s3, s4, 2, 3);
        assertCollate(s3, s4, 6, 3);
        assertCollate(s3, s4, 7, 3);

        final List<Integer> s5 = Arrays.asList(2, 3, 6, 8);
        final Integer[] s6 = new Integer[] { 7, 10, 13, 11, 17, 19 };

        assertCollate(s5, s6, 0, 1);
        assertCollate(s5, s6, 1, 2);

    }

    public void testCollateBoundary1() throws Exception {
        final List<Integer> s1 = Arrays.asList(2, 3);
        final Integer[] s2 = new Integer[] { 7, 10, 13, 11 };

        assertCollate(s1, s2, 6, 1, true);
    }

    public void testCollateBoundary2() throws Exception {
        final List<Integer> s1 = Arrays.asList(2, 3);
        final Integer[] s2 = new Integer[] { 7, 10, 13, 11 };

        assertCollate(s1, s2, 5, 2, true);
    }

    public void testCollateBoundary3() throws Exception {
        final List<Integer> s1 = Arrays.asList(1, 2, 3);
        final Integer[] s2 = new Integer[] { 5, 6, 7, 8 };

        assertCollate(s1, s2, 6, 1, true);
    }

    public void testCollateBoundary4() throws Exception {
        final List<Integer> s1 = Arrays.asList(1, 2, 3);
        final Integer[] s2 = new Integer[] { 5 };

        assertCollate(s1, s2, 3, 1, false);
    }

    public void testCollateBoundary5() throws Exception {
        final List<Integer> s1 = Arrays.asList(2, 3);
        final Integer[] s2 = new Integer[] { 7, 10, 13 };

        assertCollate(s1, s2, 10, 2, true);
    }

    public void testCollateBoundary6() throws Exception {
        final List<Integer> s1 = Arrays.asList(2, 3);
        final Integer[] s2 = new Integer[] { 7, 10, 13 };

        assertCollate(s1, s2, 0, 0, true);
    }

    public void testCollateBoundary7() throws Exception {
        final List<Integer> s1 = Arrays.asList(10);
        final Integer[] s2 = new Integer[] { 1, 2, 3 };

        assertCollate(s1, s2, 6, 1, true);
    }

    public void testCollateBoundary8() throws Exception {
        final List<Integer> s1 = Arrays.asList(1);
        final Integer[] s2 = new Integer[] { 5, 6, 7 };

        assertCollate(s1, s2, 5, 1, true);
    }

    public void testCollateBoundary9() throws Exception {
        final List<Integer> s1 = Arrays.asList(1);
        final Integer[] s2 = new Integer[] { 5 };

        assertCollate(s1, s2, 0, 2, true);
    }

    public void testCollateBoundary10() throws Exception {
        final List<Integer> s1 = Arrays.asList();
        final Integer[] s2 = new Integer[] { 5 };

        assertCollate(s1, s2, 0, 2, true);
    }

    public void testCollateBoundary11() throws Exception {
        final List<Integer> s1 = Arrays.asList(1);
        final Integer[] s2 = new Integer[] {};

        assertCollate(s1, s2, 0, 1, false);
    }

    public void testCollateBoundary12() throws Exception {
        final List<Integer> s1 = Arrays.asList();
        final Integer[] s2 = new Integer[] {};

        assertCollate(s1, s2, 0, 1, false);
    }

    public void testCollateBoundary13() throws Exception {
        final List<Integer> s1 = Arrays.asList(6, 7, 8, 9, 10, 11, 12, 13, 14);
        final Integer[] s2 = new Integer[] { 1 };

        assertCollate(s1, s2, 3, 5, false);
    }

    public void testCollateFalsePositive1() throws Exception {
        final List<Integer> s1 = Arrays.asList(2, 3);
        final Integer[] s2 = new Integer[] { 7, 10, 13 };

        try {
            new PageCollator<Integer>().collate(s1, new ArrayPageSource(s2), new PagingRequest(-1, 1),
                    new ComparableComparator<Integer>());
            fail("Invalid page data.");
        } catch (PageCollationException e) {
            logger.info(e.getMessage());
        }

        try {
            new PageCollator<Integer>().collate(s1, new ArrayPageSource(s2), new PagingRequest(1, -1),
                    new ComparableComparator<Integer>());
            fail("Invalid page data.");
        } catch (PageCollationException e) {
            logger.info(e.getMessage());
        }
    }
}