// Path: src/main/java/craterdog/collections/primitives/MergeSorter.java
// public class MergeSorter<E> extends Sorter<E> {
// 
//     @Override
//     public void sortCollection(SortableCollection<E> collection, Comparator<? super E> comparator) {
//         // see if any sorting is needed
//         if (collection != null && collection.getSize() > 1) {
// 
//             // make sure the comparator exists
//             if (comparator == null) comparator = new NaturalComparator<>();
// 
//             // convert the collection to an array
//             E[] array = collection.toArray();
// 
//             // sort the array
//             sortArray(array, comparator);
// 
//             // convert it back to a collection
//             collection.removeAll();
//             collection.addElements(array);
// 
//         }
//     }
// 
// 
//     private void sortArray(E[] array, Comparator<? super E> comparator) {
//         // check to see if the array is already sorted
//         int length = array.length;
//         if (length < 2) return;
// 
//         // split the array into two halves
//         int leftLength = length / 2;
//         E[] left = Arrays.copyOfRange(array, 0, leftLength);
//         E[] right = Arrays.copyOfRange(array, leftLength, length);
// 
//         // sort each half separately
//         sortArray(left, comparator);
//         sortArray(right, comparator);
// 
//         // merge the sorted halves back together
//         mergeArrays(left, right, array, comparator);
//     }
// 
// 
//     private void mergeArrays(E[] left, E[] right, E[] result, Comparator<? super E> comparator) {
//         int leftIndex = 0;
//         int rightIndex = 0;
//         int resultIndex = 0;
//         while (resultIndex < result.length) {
//             if (leftIndex < left.length && rightIndex < right.length) {
//                 // still have elements in both halves
//                 if (comparator.compare(left[leftIndex], right[rightIndex]) < 0) {
//                     // copy the next left element to the result
//                     result[resultIndex++] = left[leftIndex++];
//                 } else {
//                     // copy the next right element to the result
//                     result[resultIndex++] = right[rightIndex++];
//                 }
//             } else if (leftIndex < left.length) {
//                 // copy the rest of the left half to the result
//                 int leftRemaining = left.length - leftIndex;
//                 System.arraycopy(left, leftIndex, result, resultIndex, leftRemaining);
//                 leftIndex += leftRemaining;
//                 resultIndex += leftRemaining;
//             } else {
//                 // copy the rest of the right half to the result
//                 int rightRemaining = right.length - rightIndex;
//                 System.arraycopy(right, rightIndex, result, resultIndex, rightRemaining);
//                 rightIndex += rightRemaining;
//                 resultIndex += rightRemaining;
//             }
//         }
//     }
// 
// }
// 
// Path: src/main/java/craterdog/collections/primitives/RandomSorter.java
// public class RandomSorter<E> extends Sorter<E> {
// 
//     @Override
//     public void sortCollection(SortableCollection<E> collection, Comparator<? super E> comparator) {
//         // see if any sorting is really required
//         if (collection != null && collection.getSize() > 1) {
//             if (collection instanceof List) {
//                 // randomize it in place
//                 @SuppressWarnings("unchecked")
//                 List<E> indexedCollection = (List<E>) collection;
//                 int size = collection.getSize();
//                 randomizeCollection(indexedCollection, size);
//             } else {
//                 // convert the collection to an array
//                 E[] array = collection.toArray();
// 
//                 // randomize the array
//                 randomizeArray(array);
// 
//                 // convert it back to a collection
//                 collection.removeAll();
//                 collection.addElements(array);
//             }
//         }
//     }
// 
//     private void randomizeCollection(List<E> indexedCollection, int size) {
//         for (int index = size; index > 1; index--) {
//             int randomIndex = RandomUtils.pickRandomIndex(index) + 1;  // use ordinal based indexing
//             E swap = indexedCollection.getElement(index);
//             swap = indexedCollection.replaceElement(swap, randomIndex);
//             indexedCollection.replaceElement(swap, index);
//         }
//     }
// 
//     private void randomizeArray(E[] array) {
//         int size = array.length;
//         for (int index = size; index > 1; index--) {
//             int randomIndex = RandomUtils.pickRandomIndex(index);  // use zero based indexing
//             E swap = array[index - 1];
//             array[index - 1] = array[randomIndex];
//             array[randomIndex] = swap;
//         }
//     }
// 
// }


import craterdog.collections.primitives.MergeSorter;
import craterdog.collections.primitives.RandomSorter;
import craterdog.core.Manipulator;
import craterdog.utils.NaturalComparator;
import java.util.Comparator;
import org.slf4j.ext.XLogger;
import org.slf4j.ext.XLoggerFactory;
/************************************************************************
 * Copyright (c) Crater Dog Technologies(TM).  All Rights Reserved.     *
 ************************************************************************
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.        *
 *                                                                      *
 * This code is free software; you can redistribute it and/or modify it *
 * under the terms of The MIT License (MIT), as published by the Open   *
 * Source Initiative. (See http://opensource.org/licenses/MIT)          *
 ************************************************************************/
package craterdog.collections.abstractions;



/**
 * This abstract class defines the invariant methods that all sortable collections must inherit.
 * A sortable collection allows the order of its elements to be determined externally.  By
 * default, the elements will be placed in the order in which they were added to the collection.
 * Additionally, the elements can be sorted in various ways depending on a specified sorting
 * algorithm and comparison function.
 *
 * @author Derk Norton
 * @param <E> The type of element managed by the collection.
 */
public abstract class SortableCollection<E> extends OpenCollection<E> {

    static private final XLogger logger = XLoggerFactory.getXLogger(SortableCollection.class);


    /**
     * This method shuffles the elements in the collection using a randomizing algorithm.
     */
    public void shuffleElements() {
        logger.entry();
// Path: src/main/java/craterdog/collections/primitives/MergeSorter.java
// public class MergeSorter<E> extends Sorter<E> {
// 
//     @Override
//     public void sortCollection(SortableCollection<E> collection, Comparator<? super E> comparator) {
//         // see if any sorting is needed
//         if (collection != null && collection.getSize() > 1) {
// 
//             // make sure the comparator exists
//             if (comparator == null) comparator = new NaturalComparator<>();
// 
//             // convert the collection to an array
//             E[] array = collection.toArray();
// 
//             // sort the array
//             sortArray(array, comparator);
// 
//             // convert it back to a collection
//             collection.removeAll();
//             collection.addElements(array);
// 
//         }
//     }
// 
// 
//     private void sortArray(E[] array, Comparator<? super E> comparator) {
//         // check to see if the array is already sorted
//         int length = array.length;
//         if (length < 2) return;
// 
//         // split the array into two halves
//         int leftLength = length / 2;
//         E[] left = Arrays.copyOfRange(array, 0, leftLength);
//         E[] right = Arrays.copyOfRange(array, leftLength, length);
// 
//         // sort each half separately
//         sortArray(left, comparator);
//         sortArray(right, comparator);
// 
//         // merge the sorted halves back together
//         mergeArrays(left, right, array, comparator);
//     }
// 
// 
//     private void mergeArrays(E[] left, E[] right, E[] result, Comparator<? super E> comparator) {
//         int leftIndex = 0;
//         int rightIndex = 0;
//         int resultIndex = 0;
//         while (resultIndex < result.length) {
//             if (leftIndex < left.length && rightIndex < right.length) {
//                 // still have elements in both halves
//                 if (comparator.compare(left[leftIndex], right[rightIndex]) < 0) {
//                     // copy the next left element to the result
//                     result[resultIndex++] = left[leftIndex++];
//                 } else {
//                     // copy the next right element to the result
//                     result[resultIndex++] = right[rightIndex++];
//                 }
//             } else if (leftIndex < left.length) {
//                 // copy the rest of the left half to the result
//                 int leftRemaining = left.length - leftIndex;
//                 System.arraycopy(left, leftIndex, result, resultIndex, leftRemaining);
//                 leftIndex += leftRemaining;
//                 resultIndex += leftRemaining;
//             } else {
//                 // copy the rest of the right half to the result
//                 int rightRemaining = right.length - rightIndex;
//                 System.arraycopy(right, rightIndex, result, resultIndex, rightRemaining);
//                 rightIndex += rightRemaining;
//                 resultIndex += rightRemaining;
//             }
//         }
//     }
// 
// }
// 
// Path: src/main/java/craterdog/collections/primitives/RandomSorter.java
// public class RandomSorter<E> extends Sorter<E> {
// 
//     @Override
//     public void sortCollection(SortableCollection<E> collection, Comparator<? super E> comparator) {
//         // see if any sorting is really required
//         if (collection != null && collection.getSize() > 1) {
//             if (collection instanceof List) {
//                 // randomize it in place
//                 @SuppressWarnings("unchecked")
//                 List<E> indexedCollection = (List<E>) collection;
//                 int size = collection.getSize();
//                 randomizeCollection(indexedCollection, size);
//             } else {
//                 // convert the collection to an array
//                 E[] array = collection.toArray();
// 
//                 // randomize the array
//                 randomizeArray(array);
// 
//                 // convert it back to a collection
//                 collection.removeAll();
//                 collection.addElements(array);
//             }
//         }
//     }
// 
//     private void randomizeCollection(List<E> indexedCollection, int size) {
//         for (int index = size; index > 1; index--) {
//             int randomIndex = RandomUtils.pickRandomIndex(index) + 1;  // use ordinal based indexing
//             E swap = indexedCollection.getElement(index);
//             swap = indexedCollection.replaceElement(swap, randomIndex);
//             indexedCollection.replaceElement(swap, index);
//         }
//     }
// 
//     private void randomizeArray(E[] array) {
//         int size = array.length;
//         for (int index = size; index > 1; index--) {
//             int randomIndex = RandomUtils.pickRandomIndex(index);  // use zero based indexing
//             E swap = array[index - 1];
//             array[index - 1] = array[randomIndex];
//             array[randomIndex] = swap;
//         }
//     }
// 
// }


// Path: src/main/java/craterdog/collections/abstractions/SortableCollection.java
import craterdog.collections.primitives.MergeSorter;
import craterdog.collections.primitives.RandomSorter;
import craterdog.core.Manipulator;
import craterdog.utils.NaturalComparator;
import java.util.Comparator;
import org.slf4j.ext.XLogger;
import org.slf4j.ext.XLoggerFactory;

/************************************************************************
 * Copyright (c) Crater Dog Technologies(TM).  All Rights Reserved.     *
 ************************************************************************
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.        *
 *                                                                      *
 * This code is free software; you can redistribute it and/or modify it *
 * under the terms of The MIT License (MIT), as published by the Open   *
 * Source Initiative. (See http://opensource.org/licenses/MIT)          *
 ************************************************************************/
package craterdog.collections.abstractions;



/**
 * This abstract class defines the invariant methods that all sortable collections must inherit.
 * A sortable collection allows the order of its elements to be determined externally.  By
 * default, the elements will be placed in the order in which they were added to the collection.
 * Additionally, the elements can be sorted in various ways depending on a specified sorting
 * algorithm and comparison function.
 *
 * @author Derk Norton
 * @param <E> The type of element managed by the collection.
 */
public abstract class SortableCollection<E> extends OpenCollection<E> {

    static private final XLogger logger = XLoggerFactory.getXLogger(SortableCollection.class);


    /**
     * This method shuffles the elements in the collection using a randomizing algorithm.
     */
    public void shuffleElements() {
        logger.entry();
        Sorter<E> sorter = new RandomSorter<>();