1 /* 2 * Copyright (C) 2025 Alberto Irurueta Carro (alberto@irurueta.com) 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.irurueta.hermes; 18 19 import java.util.List; 20 import java.util.stream.IntStream; 21 22 /** 23 * Class to detect changes between two lists of items. 24 * Notice that returned changes in this class indicate the positions of the items when each change is applied 25 * sequentially to the old list. 26 * 27 * @param <T> type of items. 28 */ 29 public class SequentialListItemChangeDetector<T> extends AbstractSequentialListItemChangeDetector<T> { 30 31 /** 32 * Comparator to determine whether two items are equal (e.g., by their id). 33 */ 34 private final ItemComparator<T> itemComparator; 35 36 /** 37 * Comparator to determine whether the content of two items is equal. 38 */ 39 private final ItemContentComparator<T> itemContentComparator; 40 41 /** 42 * Constructor. 43 * 44 * @param itemComparator comparator to determine whether two items are equal. 45 * @param itemContentComparator comparator to determine whether the content of two items is equal. 46 * @throws IllegalArgumentException if any of the parameters is null. 47 */ 48 public SequentialListItemChangeDetector(final ItemComparator<T> itemComparator, 49 final ItemContentComparator<T> itemContentComparator) { 50 51 if (itemComparator == null || itemContentComparator == null) { 52 throw new IllegalArgumentException(); 53 } 54 55 this.itemComparator = itemComparator; 56 this.itemContentComparator = itemContentComparator; 57 } 58 59 /** 60 * Determines whether the content of an item has changed. 61 * 62 * @param newItem new item. 63 * @param oldItem old item. 64 * @return true if the content of the item has changed, false otherwise. 65 */ 66 @Override 67 protected boolean hasContentChanged(final T newItem, final T oldItem) { 68 return !itemContentComparator.equalContent(newItem, oldItem); 69 } 70 71 /** 72 * Determines whether an item is not contained in a list. 73 * 74 * @param items list of items. 75 * @param item item to be checked. 76 * @return true if the item is not contained in the list, false otherwise. 77 */ 78 @Override 79 protected boolean notContains(final List<T> items, final T item) { 80 return items.stream().noneMatch(newItem -> itemComparator.equals(newItem, item)); 81 } 82 83 /** 84 * Determines the index of an item in a list. 85 * 86 * @param items list of items. 87 * @param item item to be checked. 88 * @return index of the item in the list, or -1 if the item is not contained in the list. 89 */ 90 @Override 91 protected int indexOf(final List<T> items, final T item) { 92 return IntStream.range(0, items.size()).filter(index -> { 93 final var otherItem = items.get(index); 94 return itemComparator.equals(item, otherItem); 95 }).findFirst().orElse(-1); 96 } 97 }