package com.github.sommeri.less4j.utils;
import java.util.ArrayList;
import java.util.List;
public class ListsComparator {
public <T> boolean equals(List<T> first, List<T> second, ListMemberComparator<T> comparator) {
if (first.size() != second.size()) {
return false;
}
return equals(first, second, first.size(), comparator);
}
public <T> boolean equals(List<T> first, List<T> second, int count, ListMemberComparator<T> comparator) {
for (int i = 0; i < first.size() && i < count; i++) {
if (!comparator.equals(first.get(i), second.get(i))) {
return false;
}
}
return true;
}
public <T> boolean prefix(List<T> lookFor, List<T> inList, ListMemberComparator<T> comparator) {
if (lookFor.isEmpty())
return true;
if (lookFor.size() > inList.size())
return false;
int beforeLast = lookFor.size() - 1;
if (!equals(lookFor, inList, beforeLast, comparator))
return false;
return comparator.prefix(lookFor.get(beforeLast), inList.get(beforeLast));
}
public <T> MatchMarker<T> prefixMatches(List<T> lookFor, List<T> inList, ListMemberComparator<T> comparator) {
if (lookFor.isEmpty() || lookFor.size() > inList.size())
return null;
List<T> relevantInList = ArraysUtils.sameLengthPrefix(inList, lookFor);
List<T> relevantInListWithoutLast = ArraysUtils.sublistWithoutLast(relevantInList);
List<T> lookForWithoutLast = ArraysUtils.sublistWithoutLast(lookFor);
if (!equals(lookForWithoutLast, relevantInListWithoutLast, comparator))
return null;
boolean isPrefix = comparator.prefix(ArraysUtils.last(lookFor), ArraysUtils.last(relevantInList));
if (isPrefix)
return new MatchMarker<T>(ArraysUtils.first(relevantInList), ArraysUtils.last(relevantInList), false);
return null;
}
public <T> T prefixEnd(List<T> lookFor, List<T> inList, ListMemberComparator<T> comparator) {
if (lookFor.isEmpty())
return inList.isEmpty() ? null : inList.get(0);
if (lookFor.size() > inList.size())
return null;
List<T> relevantInList = ArraysUtils.sameLengthPrefix(inList, lookFor);
List<T> relevantInListWithoutLast = ArraysUtils.sublistWithoutLast(relevantInList);
List<T> lookForWithoutLast = ArraysUtils.sublistWithoutLast(lookFor);
if (!equals(lookForWithoutLast, relevantInListWithoutLast, comparator))
return null;
if (comparator.prefix(ArraysUtils.last(lookFor), ArraysUtils.last(relevantInList)))
return ArraysUtils.last(relevantInList);
return null;
}
public <T> boolean suffix(List<T> lookFor, List<T> inList, ListMemberComparator<T> comparator) {
return null != suffixMatches(lookFor, inList, comparator);
}
public <T> MatchMarker<T> suffixMatches(List<T> lookFor, List<T> inList, ListMemberComparator<T> comparator) {
if (lookFor.isEmpty() || lookFor.size() > inList.size())
return null;
List<T> relevantInList = ArraysUtils.sameLengthSuffix(inList, lookFor);
List<T> relevantInListWithoutFirst = ArraysUtils.sublistWithoutFirst(relevantInList);
List<T> lookForWithoutFirst = ArraysUtils.sublistWithoutFirst(lookFor);
if (!equals(lookForWithoutFirst, relevantInListWithoutFirst, comparator))
return null;
boolean isSuffix = comparator.suffix(ArraysUtils.first(lookFor), ArraysUtils.first(relevantInList));
if (isSuffix)
return new MatchMarker<T>(ArraysUtils.first(relevantInList), ArraysUtils.last(relevantInList), false);
return null;
}
public <T> boolean contains(List<T> lookFor, List<T> inList, ListMemberComparator<T> comparator) {
return !findMatches(lookFor, inList, comparator).isEmpty();
}
public <T> List<MatchMarker<T>> findMatches(List<T> lookFor, List<T> inList, ListMemberComparator<T> comparator) {
return collectMatches(lookFor, inList, comparator, new ArrayList<MatchMarker<T>>());
}
public <T> List<MatchMarker<T>> collectMatches(List<T> lookFor, List<T> inList, ListMemberComparator<T> comparator, List<MatchMarker<T>> result) {
if (lookFor.isEmpty() || lookFor.size() > inList.size())
return result;
if (lookFor.size() == 1) {
return collectMatches(ArraysUtils.first(lookFor), inList, comparator, result);
}
T firstLookFor = ArraysUtils.first(lookFor);
T firstInList = ArraysUtils.first(inList);
List<T> remainderLookFor = ArraysUtils.sublistWithoutFirst(lookFor);
List<T> remainderInList = ArraysUtils.sublistWithoutFirst(inList);
boolean firstIsSuffix = comparator.suffix(firstLookFor, firstInList);
T prefixEnd = prefixEnd(remainderLookFor, remainderInList, comparator);
boolean remainderIsPrefix = prefixEnd != null;
if (firstIsSuffix && remainderIsPrefix) {
result.add(new MatchMarker<T>(firstInList, prefixEnd, false));
}
collectMatches(lookFor, remainderInList, comparator, result);
return result;
}
private <T> List<MatchMarker<T>> collectMatches(T lookFor, List<T> inParts, ListMemberComparator<T> comparator, List<MatchMarker<T>> result) {
for (T inPart : inParts) {
if (comparator.contains(lookFor, inPart))
result.add(new MatchMarker<T>(inPart, inPart, false));
}
return result;
}
public static interface ListMemberComparator<T> {
public boolean equals(T first, T second);
public boolean prefix(T lookFor, T inside);
public boolean suffix(T lookFor, T inside);
public boolean contains(T lookFor, T inside);
}
public static interface ModifiedListBuilder<T> {
public boolean splitInside(T lookFor, T inPart, List<T> replaceBy);
public boolean cutSuffix(T lookFor, T inside, List<T> replaceBy);
public boolean cutPrefix(T lookFor, T inside, List<T> replaceBy);
}
public class MatchMarker<T> {
private T first;
private T last;
private boolean isEquals;
public MatchMarker(T first, T last, boolean isEquals) {
this.first = first;
this.last = last;
this.isEquals = isEquals;
}
public T getFirst() {
return first;
}
public void setFirst(T first) {
this.first = first;
}
public T getLast() {
return last;
}
public void setLast(T last) {
this.last = last;
}
public boolean isEquals() {
return isEquals;
}
public void setEquals(boolean isEquals) {
this.isEquals = isEquals;
}
public boolean firstIsLast() {
return first == last;
}
public boolean isIn(List<T> list) {
return list.contains(getFirst()) && list.contains(getLast());
}
}
}