Package org.gradle.foundation.common

Source Code of org.gradle.foundation.common.ListReorderer

/*
* Copyright 2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.gradle.foundation.common;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Collections;
import java.util.Comparator;

/**
* Utility class that allows lists to be reordered.
*
* @author Chris Hampton
*/
public class ListReorderer {
    /**
     * Moves the object down one position in the group list.
     *
     * @param sourceList The list whose elements we want to reorder.
     * @param object The object to move.
     */
    public static boolean moveBefore(List sourceList, Object object) {
        // Get the old index of the object
        int previousIndex = sourceList.indexOf(object);
        // If the index of the object is 0 it can't go any lower. If it's
        // -1 it's not even in the list. In these cases we do nothing.
        if (previousIndex < 1) {
            return false;
        }
        // Remove the object from it's old position in the list, this shifts all
        // elements above it down by 1
        sourceList.remove(object);
        // Add the object back at 1 less than it's original index, the old
        // element at this position is shifted to right in the lise
        sourceList.add(previousIndex - 1, object);
        // If we get here we assume we moved it.
        return true;
    }

    /**
     * Moves a list of elements in this list while keeping their relative positions. When the first element reaches the
     * beginning it goes no further and the other elements in the list will continue to be shifted on subsequent calls
     * as long as they don't overwrite previously moved elements. This means that elements with other elements between
     * them will continue move with the same distance between them but will 'bunch up' toward the beginning of the
     * list.
     *
     * NOTE: The order of the list of moved elements is important. They have to be added in order from lowest index to
     * highest.
     *
     * @param sourceList The list whose elements we want to reorder.
     * @param objectsToMove List of elements to move.
     */
    public static void moveBefore(List sourceList, List objectsToMove) {
        sortMoveListByRelativeOrder(sourceList, objectsToMove);
        // Create a new list to put elements in we try to move
        List triedToMove = new ArrayList();
        // Now iterate through the elements to move and attempt to move them
        Iterator iterator = objectsToMove.iterator();
        while (iterator.hasNext()) {
            // Get the next object to move
            Object objectToMove = iterator.next();
            // Get the index of the object to move
            int currentPosition = sourceList.indexOf(objectToMove);
            // Only move the element if it's not already at the front of the list
            if (currentPosition > 0) {
                // Get the element at the position we want to move to and make sure it's not
                // an element in the list that we'vd already moved
                Object occupyingObject = sourceList.get(currentPosition - 1);
                if (currentPosition < sourceList.size() && !triedToMove.contains(occupyingObject)) {
                    moveBefore(sourceList, objectToMove);
                }
            }
            // If we get here we have at least tried to move the object,
            // so stick it in the tried list
            triedToMove.add(objectToMove);
        }
    }

    /**
     * Moves a list of objects to a new index location.
     *
     * @param sourceList The list where the move will occur.
     * @param moveList The objects to move.
     * @param index The object's new location in the list.
     */
    public static void moveTo(List sourceList, List moveList, int index) {
        // First make sure the move is valid
        if (index < 0 || index >= sourceList.size()) {
            return;
        }
        // Store the object at the index to move to
        Object moveBeforeObject = sourceList.get(index);

        //This fixes a bug. This happens if the user selects things and moves them to an index where something is already selected. I select 1, 2, and 4 and I say move to 2. 2 is already selected. This makes no sense, but its happened in the field.
        if (moveList.contains(moveBeforeObject)) //just remove the item from the move list.
        {
            List newMoveList = new ArrayList(
                    moveList);   //we don't want to actually affect the move list. Callers use it for visually selecting items after the move. So we'll make a duplicate and just recursively call ourselves again.
            newMoveList.remove(moveBeforeObject);
            moveTo(sourceList, newMoveList, index + 1);   //skip over the one we took out
            return;
        }

        // Remove the object from it's old position
        sourceList.removeAll(moveList);
        // Get the new index value after shifts
        index = sourceList.indexOf(moveBeforeObject);

        //make sure the index is within bounds.
        if (index < 0) {
            index = 0;
        }
        if (index > sourceList.size() - 1) {
            index = sourceList.size() - 1;
        }

        // Add the element to the new location
        sourceList.addAll(index, moveList);
    }

    /**
     * Moves an object to the front of the list.
     *
     * @param sourceList The list the object is in.
     * @param object The object to move.
     * @return True if the object was in the list and it was moved.
     */
    public static boolean moveToFront(List sourceList, Object object) {
        boolean moved = false;
        // If we can remove it, then it was in the list
        if (sourceList.remove(object)) {
            sourceList.add(0, object); // This is a void method, so it doesn't set our flag
            moved = true;
        }

        return moved;
    }

    /**
     * Moves a list of objects to the front of the list.
     *
     * @param sourceList The list the object is in.
     * @param objectsToMove The object to move.
     */
    public static void moveToFront(List sourceList, List objectsToMove) {
        sortMoveListByRelativeOrder(sourceList, objectsToMove);
        for (int i = objectsToMove.size() - 1; i >= 0; i--) {
            Object object = objectsToMove.get(i);
            if (sourceList.remove(object)) {
                sourceList.add(0, object);
            }
        }
    }

    /**
     * Moves the object up one index position in the list.
     *
     * @param sourceList The list whose elements we want to reorder.
     * @param object The object to move.
     */
    public static boolean moveAfter(List sourceList, Object object) {
        // Get the old index of the object
        int previousIndex = sourceList.indexOf(object);
        // If the index of the object is 0 it can't go any higher. If it's
        // -1 it's not even in the list. In these cases we do nothing.
        if (previousIndex >= sourceList.size() - 1 || previousIndex == -1) {
            return false;
        }
        // Remove the object from it's old position in the list, this shifts all
        // elements above it down by 1
        sourceList.remove(object);
        // Add the object back at 2 higher than it's original index, if we only
        // add one than we just place it back where it was since everything shifted
        // down when we removed it
        sourceList.add(previousIndex + 1, object);
        // If we get here we assume we moved it.
        return true;
    }

    /**
     * Moves the objects in the list up one index position in this list while maintaining their relative position. When
     * an element reaches the end of the list it can go no farther, but the other elements continue to move each call
     * without overwriting previously moved elements. This causes moved elements to 'bunch up' at the end of the list.
     *
     * NOTE: The order of the list of moved elements is important. They have to be added in order from lowest index to
     * highest.
     *
     * @param sourceList The list whose elements we want to reorder.
     * @param objectsToMove List of elements to move.
     */
    public static void moveAfter(List sourceList, List objectsToMove) {
        sortMoveListByRelativeOrder(sourceList, objectsToMove);
        List triedToMove = new ArrayList();
        // Since we are moving elements to a greater index in the list,
        // we iterate through the list backwards to move the highest indexed
        // element first
        for (int i = objectsToMove.size() - 1; i >= 0; i--) {
            Object objectToMove = objectsToMove.get(i);
            // Get the index of the object to move
            int currentPosition = sourceList.indexOf(objectToMove);
            // Make sure the element we want to move isn't already at the end of
            // the list
            if (currentPosition < sourceList.size() - 1) {
                // Now get the index of the elment occupying the spot we want
                // to move to and only move the current objectToMove if it
                // does not overwite a previously moved element
                Object occupyingObject = sourceList.get(currentPosition + 1);
                if (!triedToMove.contains(occupyingObject)) {
                    moveAfter(sourceList, objectToMove);
                }
            }
            // If we get here we have at least tried to move the object,
            // so stick it in the tried list
            triedToMove.add(objectToMove);
        }
    }

    /**
     * Moves an object to the back of the list.
     *
     * @param sourceList The list the object is in.
     * @param object The object to move.
     * @return True if the object was in the list and it was moved.
     */
    public static boolean moveToBack(List sourceList, Object object) {
        boolean moved = false;

        // If we can remove it, then it was in the list
        if (sourceList.remove(object)) {
            moved = sourceList.add(object);
        }

        return moved;
    }

    /**
     * Moves a list of objects to the front of the list.
     *
     * @param sourceList The list the object is in.
     * @param objectsToMove The object to move.
     */
    public static void moveToBack(List sourceList, List objectsToMove) {
        sortMoveListByRelativeOrder(sourceList, objectsToMove);
        for (int i = 0; i < objectsToMove.size(); i++) {
            Object object = objectsToMove.get(i);
            if (sourceList.remove(object)) {
                sourceList.add(object);
            }
        }
    }

    /**
     * Sorts a child list by position in a parent list to preserve relative ordering of the elements.
     *
     * @param parentList .
     * @param childList .
     */
    public static void sortMoveListByRelativeOrder(final List parentList, List childList) {
        Collections.sort(childList, new Comparator() {
            public int compare(Object o, Object o1) {
                int index = parentList.indexOf(o);
                int index1 = parentList.indexOf(o1);
                return (index < index1) ? -1 : (index > index1) ? 1 : 0;
            }
        });
    }

    /**
     * Returns true if all the elements of the check list are at the end of the source list.
     *
     * @param sourceList .
     * @param checkList .
     * @return .
     */
    public static boolean allElementsInFront(List sourceList, List checkList) {
        // Quick check, if the source list doesn't contain all elements of the checklist,
        // abort and return false
        if (!sourceList.containsAll(checkList)) {
            return false;
        }
        // Get the last index of the source list
        int sourceIndex = checkList.size();
        // Iterate thru the check list. Find the index of the element
        // in the source list; and check it's index against the index
        // we should be on to match the source.
        for (int index = 0; index < checkList.size(); index++) {
            Object element = checkList.get(index);
            int checkIndex = sourceList.indexOf(element);
            if (checkIndex >= sourceIndex) {
                return false;
            }
        }

        return true;
    }

    public static boolean allElementsInBack(List sourceList, List checkList) {
        // Quick check, if the source list doesn't contain all elements of the checklist,
        // abort and return false
        if (!sourceList.containsAll(checkList)) {
            return false;
        }
        // Get the last index of the source list
        int sourceIndex = sourceList.size() - checkList.size();
        // Iterate thru the check list. Find the index of the element
        // in the source list; and check it's index against the index
        // we should be on to match the source.
        for (int index = checkList.size() - 1; index >= 0; index--) {
            Object element = checkList.get(index);
            int checkIndex = sourceList.indexOf(element);
            if (checkIndex < sourceIndex) {
                return false;
            }
        }

        return true;
    }

    /**
     * This is mainly used for after doing a move. It gives you the current index of all the moved elements. This is
     * useful for UIs that need to reselect the new items.
     *
     * @param sourceList the source list
     * @param objectsToMove the elements to move
     * @return an integer array of the items to select.
     */
    public static int[] getIndices(List sourceList, List objectsToMove) {
        int[] newIndices = new int[objectsToMove.size()];

        for (int index = 0; index < objectsToMove.size(); index++) {
            Object elementToMove = objectsToMove.get(index);
            int sourceIndexOfElement = sourceList.indexOf(elementToMove);

            newIndices[index] = sourceIndexOfElement;
        }

        return newIndices;
    }
}
TOP

Related Classes of org.gradle.foundation.common.ListReorderer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.