package com.kickstarter.libs.utils;
import android.os.Parcelable;
import android.support.annotation.NonNull;
import java.util.ArrayList;
import java.util.List;
import auto.parcel.AutoParcel;
import rx.functions.Func2;
public final class DiffUtils {
private DiffUtils() {}
@AutoParcel
public abstract static class Diff implements Parcelable {
public abstract @NonNull List<Integer> insertions();
public abstract @NonNull List<Integer> deletions();
public abstract @NonNull List<Integer> updates();
@AutoParcel.Builder
public abstract static class Builder {
public abstract Builder insertions(List<Integer> __);
public abstract Builder deletions(List<Integer> __);
public abstract Builder updates(List<Integer> __);
public abstract Diff build();
}
public static Builder builder() {
return new AutoParcel_DiffUtils_Diff.Builder()
.insertions(new ArrayList<>())
.deletions(new ArrayList<>())
.updates(new ArrayList<>());
}
public abstract Builder toBuilder();
}
public static @NonNull <T> Diff diff(final @NonNull List<T> oldItems, final @NonNull List<T> newItems) {
return DiffUtils.diff(oldItems, newItems, Object::equals);
}
public static @NonNull <T> Diff diff(final @NonNull List<T> oldItems, final @NonNull List<T> newItems,
final @NonNull Func2<T, T, Boolean> matches) {
final List<Integer> insertions = new ArrayList<>();
final List<Integer> deletions = new ArrayList<>();
final List<Integer> updates = new ArrayList<>();
final List<T> missingItems = ListUtils.difference(oldItems, newItems, matches);
for (final T item : missingItems) {
deletions.add(oldItems.indexOf(item));
}
final List<T> addedItems = ListUtils.difference(newItems, oldItems, matches);
for (final T item : addedItems) {
insertions.add(newItems.indexOf(item));
}
final List<T> maybeUpdatedItems = ListUtils.intersection(oldItems, newItems, matches);
for (final T maybeUpdatedItem : maybeUpdatedItems) {
final T oldItem = ListUtils.find(oldItems, maybeUpdatedItem, matches);
final T newItem = ListUtils.find(newItems, maybeUpdatedItem, matches);
if (!oldItem.equals(newItem)) {
updates.add(ListUtils.indexOf(oldItems, oldItem));
}
}
return Diff.builder()
.insertions(insertions)
.deletions(deletions)
.updates(updates)
.build();
}
}