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 }