View Javadoc
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  }