// Path: collection-matchers/src/main/java/ru/yandex/qatools/matchers/collection/HasSameItemsAsCollectionMatcher.java
// @Factory
// public static <T> Matcher<Collection<? extends T>> hasSameItemsAsCollection(Collection<? extends T> correctList) {
//     return new HasSameItemsAsCollectionMatcher<>(correctList);
// }
// 
// Path: collection-matchers/src/main/java/ru/yandex/qatools/matchers/collection/MismatchHelper.java
// @SuppressWarnings("unchecked")
// public static void appendMismatch(Description mismatchDescription, String comment, Collection collectionToPrint) {
//     if (collectionToPrint.size() > 0) {
//         mismatchDescription.appendText("\n(").appendText(comment)
//                 .appendText(") [")
//                 .appendValue(collectionToPrint.size())
//                 .appendText("]:\n")
//                 .appendValueList("-> ", "\n-> ", "", collectionToPrint);
//     }
// }
// 
// Path: collection-matchers/src/main/java/ru/yandex/qatools/matchers/collection/WrapperConverter.java
// public static <T> WrapperConverter<T> wrap(List<? extends T> list, WrapperFactory<T> factory) {
//     return new WrapperConverter<T>(list, factory);
// }


import ch.lambdaj.collection.LambdaList;
import org.hamcrest.*;
import java.util.Collection;
import java.util.List;
import static ch.lambdaj.collection.LambdaCollections.with;
import static org.hamcrest.Matchers.*;
import static ru.yandex.qatools.matchers.collection.HasSameItemsAsCollectionMatcher.hasSameItemsAsCollection;
import static ru.yandex.qatools.matchers.collection.MismatchHelper.appendMismatch;
import static ru.yandex.qatools.matchers.collection.WrapperConverter.wrap;
        this.wrapperFactory = wrapperFactory;
        return this;
    }

    public HasSameItemsAsListMatcher<T> sameSorted() {
        sortcheck = true;
        return this;
    }


    @Override
    protected boolean matchesSafely(List<? extends T> actual, Description mismatchDescription) {
        LambdaList<Wrapper<T>> wrappedActual = with(actual).convert(wrap(actual, wrapperFactory));
        LambdaList<Wrapper<T>> wrappedExpected = with(expected).convert(wrap(expected, wrapperFactory));

        LambdaList<Wrapper<T>> inActualButNotInExpected = wrappedActual.clone().remove(isIn(wrappedExpected));
        LambdaList<Wrapper<T>> inExpectedButNotInActual = wrappedExpected.clone().remove(isIn(wrappedActual));

        appendMismatch(mismatchDescription, "In Actual but not in Expected", inActualButNotInExpected);
        appendMismatch(mismatchDescription, "In Expected but not in Actual", inExpectedButNotInActual);

        Matcher<Collection<? extends Wrapper<T>>> collectionMatcher = hasSameItemsAsCollection(
                wrappedExpected.remove(not(isIn(wrappedActual)))
        );
        collectionMatcher.describeMismatch(wrappedActual.remove(not(isIn(wrappedExpected))), mismatchDescription);

        int notsorted = 0;
        if (sortcheck) {
            LambdaList<Wrapper<T>> notCorrectlySorted = wrappedExpected.clone()
                    .remove(sortedEqual(wrappedActual));
// Path: collection-matchers/src/main/java/ru/yandex/qatools/matchers/collection/HasSameItemsAsCollectionMatcher.java
// @Factory
// public static <T> Matcher<Collection<? extends T>> hasSameItemsAsCollection(Collection<? extends T> correctList) {
//     return new HasSameItemsAsCollectionMatcher<>(correctList);
// }
// 
// Path: collection-matchers/src/main/java/ru/yandex/qatools/matchers/collection/MismatchHelper.java
// @SuppressWarnings("unchecked")
// public static void appendMismatch(Description mismatchDescription, String comment, Collection collectionToPrint) {
//     if (collectionToPrint.size() > 0) {
//         mismatchDescription.appendText("\n(").appendText(comment)
//                 .appendText(") [")
//                 .appendValue(collectionToPrint.size())
//                 .appendText("]:\n")
//                 .appendValueList("-> ", "\n-> ", "", collectionToPrint);
//     }
// }
// 
// Path: collection-matchers/src/main/java/ru/yandex/qatools/matchers/collection/WrapperConverter.java
// public static <T> WrapperConverter<T> wrap(List<? extends T> list, WrapperFactory<T> factory) {
//     return new WrapperConverter<T>(list, factory);
// }


// Path: collection-matchers/src/main/java/ru/yandex/qatools/matchers/collection/HasSameItemsAsListMatcher.java
import ch.lambdaj.collection.LambdaList;
import org.hamcrest.*;
import java.util.Collection;
import java.util.List;
import static ch.lambdaj.collection.LambdaCollections.with;
import static org.hamcrest.Matchers.*;
import static ru.yandex.qatools.matchers.collection.HasSameItemsAsCollectionMatcher.hasSameItemsAsCollection;
import static ru.yandex.qatools.matchers.collection.MismatchHelper.appendMismatch;
import static ru.yandex.qatools.matchers.collection.WrapperConverter.wrap;

        this.wrapperFactory = wrapperFactory;
        return this;
    }

    public HasSameItemsAsListMatcher<T> sameSorted() {
        sortcheck = true;
        return this;
    }


    @Override
    protected boolean matchesSafely(List<? extends T> actual, Description mismatchDescription) {
        LambdaList<Wrapper<T>> wrappedActual = with(actual).convert(wrap(actual, wrapperFactory));
        LambdaList<Wrapper<T>> wrappedExpected = with(expected).convert(wrap(expected, wrapperFactory));

        LambdaList<Wrapper<T>> inActualButNotInExpected = wrappedActual.clone().remove(isIn(wrappedExpected));
        LambdaList<Wrapper<T>> inExpectedButNotInActual = wrappedExpected.clone().remove(isIn(wrappedActual));

        appendMismatch(mismatchDescription, "In Actual but not in Expected", inActualButNotInExpected);
        appendMismatch(mismatchDescription, "In Expected but not in Actual", inExpectedButNotInActual);

        Matcher<Collection<? extends Wrapper<T>>> collectionMatcher = hasSameItemsAsCollection(
                wrappedExpected.remove(not(isIn(wrappedActual)))
        );
        collectionMatcher.describeMismatch(wrappedActual.remove(not(isIn(wrappedExpected))), mismatchDescription);

        int notsorted = 0;
        if (sortcheck) {
            LambdaList<Wrapper<T>> notCorrectlySorted = wrappedExpected.clone()
                    .remove(sortedEqual(wrappedActual));
            appendMismatch(mismatchDescription, "Not sorted correctly",