persolijn

an efficient router for busses
Log | Files | Refs

TargetIterable.java (8612B)


      1 package osm.planner;
      2 
      3 import java.util.List;
      4 import java.util.AbstractSet;
      5 import java.util.Collection;
      6 import java.util.HashMap;
      7 import java.util.Iterator;
      8 import java.util.Map;
      9 import java.util.Objects;
     10 import java.util.function.Function;
     11 import java.util.function.Supplier;
     12 
     13 /**
     14  * An iterable representing a set of target entries, each associated with a
     15  * visitation state.
     16  *
     17  * @param <P> The type of target points.
     18  * @param <T> The type of elements in the iterable.
     19  */
     20 public class TargetIterable<P, T> implements Iterable<TargetIterable.TargetSet<P, T>> {
     21 
     22     /**
     23      * Enumeration representing the visitation states of target points in the
     24      * {@link TargetIterable}.
     25      */
     26     public static enum Visited {
     27         /**
     28          * Represents a target point that has finished processing.
     29          */
     30         FINISHED(false, null),
     31 
     32         /**
     33          * Represents a target point that is currently being processed.
     34          */
     35         BUSY(true, FINISHED),
     36 
     37         /**
     38          * Represents a target point that is pending processing.
     39          */
     40         PENDING(true, BUSY);
     41 
     42         private final boolean include;
     43         private final Visited next;
     44 
     45         /**
     46          * Constructs a Visited enum with the specified inclusion flag and the next
     47          * visitation state.
     48          *
     49          * @param include The flag indicating whether the target point should be
     50          *                included in processing.
     51          * @param next    The next visitation state after this one.
     52          */
     53         private Visited(boolean include, Visited next) {
     54             this.include = include;
     55             this.next = next;
     56         }
     57 
     58         /**
     59          * Gets the next visitation state after this one.
     60          *
     61          * @return The next visitation state.
     62          */
     63         public Visited getNext() {
     64             return next;
     65         }
     66 
     67         /**
     68          * Checks if the target point should be included in processing.
     69          *
     70          * @return {@code true} if the target point should be included, {@code false}
     71          *         otherwise.
     72          */
     73         public boolean doInclude() {
     74             return include;
     75         }
     76     }
     77 
     78     /**
     79      * Represents a set of target entries associated with their visitation states.
     80      *
     81      * @param <P> The type of target points.
     82      * @param <T> The type of elements in the set.
     83      */
     84     public static class TargetSet<P, T> extends AbstractSet<T> {
     85 
     86         /**
     87          * The iterable to which this set belongs.
     88          */
     89         public final TargetIterable<P, T> iterable;
     90 
     91         /**
     92          * A map associating each target point with its visitation state.
     93          */
     94         public final Map<P, Visited> targetMap;
     95 
     96         /**
     97          * The list of target elements in this set.
     98          */
     99         public final List<T> targets;
    100 
    101         /**
    102          * Constructs a TargetSet with the specified iterable, target map, and target
    103          * elements.
    104          *
    105          * @param iterable  The iterable to which this set belongs.
    106          * @param targetMap A map associating each target point with its visitation
    107          *                  state.
    108          * @param targets   The list of target elements in this set.
    109          */
    110         private TargetSet(TargetIterable<P, T> iterable, Map<P, Visited> targetMap, List<T> targets) {
    111             this.iterable = iterable;
    112             this.targetMap = targetMap;
    113             this.targets = targets;
    114         }
    115 
    116         /**
    117          * Returns a string representation of this TargetSet.
    118          *
    119          * @return A string representation of this TargetSet.
    120          */
    121         @Override
    122         public String toString() {
    123             return String.format("TargetSet(%s)", targets);
    124         }
    125 
    126         /**
    127          * Returns the number of elements in this set.
    128          *
    129          * @return The number of elements in this set.
    130          */
    131         @Override
    132         public int size() {
    133             return targets.size();
    134         }
    135 
    136         /**
    137          * Returns an iterator over the elements in this set.
    138          *
    139          * @return An iterator over the elements in this set.
    140          */
    141         @Override
    142         public Iterator<T> iterator() {
    143             return targets.iterator();
    144         }
    145 
    146         /**
    147          * Creates a new iterable to continue processing with additional targets.
    148          *
    149          * @param supplier A supplier providing the next element.
    150          * @return An iterable with additional targets.
    151          */
    152         public Iterable<TargetSet<P, T>> doContinue(Supplier<T> supplier) {
    153             return new TargetIterable<>(iterable.garage, iterable.targetList, targetMap,
    154                     supplier, iterable.startPoint, iterable.targetPoint);
    155         }
    156     }
    157 
    158     private final T garage;
    159     private final Collection<P> targetList;
    160     private final Supplier<T> supplier;
    161     private final Function<P, T> startPoint;
    162     private final Function<P, T> targetPoint;
    163     private final Map<P, Visited> originalMap;
    164 
    165     /**
    166      * Constructs a TargetIterable.
    167      *
    168      * @param garage      The garage element.
    169      * @param targetList  The list of target points.
    170      * @param targetMap   A map associating each target point with its visitation
    171      *                    state.
    172      * @param supplier    A supplier providing the next element.
    173      * @param startPoint  A function providing the starting point for a target.
    174      * @param targetPoint A function providing the target point for a target.
    175      */
    176     public TargetIterable(T garage, Collection<P> targetList, Map<P, Visited> targetMap,
    177             Supplier<T> supplier, Function<P, T> startPoint, Function<P, T> targetPoint) {
    178         this.garage = garage;
    179         this.targetList = targetList;
    180         this.supplier = supplier;
    181         this.startPoint = startPoint;
    182         this.targetPoint = targetPoint;
    183         this.originalMap = targetMap;
    184     }
    185 
    186     /**
    187      * Constructs a TargetIterable with an empty target map.
    188      *
    189      * @param garage      The garage element.
    190      * @param targetList  The list of target points.
    191      * @param supplier    A supplier providing the next element.
    192      * @param startPoint  A function providing the starting point for a target.
    193      * @param targetPoint A function providing the target point for a target.
    194      */
    195     public TargetIterable(T garage, Collection<P> targetList,
    196             Supplier<T> supplier, Function<P, T> startPoint, Function<P, T> targetPoint) {
    197         this.garage = garage;
    198         this.targetList = targetList;
    199         this.supplier = supplier;
    200         this.startPoint = startPoint;
    201         this.targetPoint = targetPoint;
    202         this.originalMap = Map.of();
    203     }
    204 
    205     @Override
    206     public Iterator<TargetSet<P, T>> iterator() {
    207         return new Iterator<TargetIterable.TargetSet<P, T>>() {
    208             final Map<P, Visited> targetMap = new HashMap<>(TargetIterable.this.originalMap);
    209 
    210             private Visited checkVisited(P p, T current) {
    211                 Visited visited = targetMap.getOrDefault(p, Visited.PENDING);
    212 
    213                 if (startPoint.apply(p).equals(current) && visited == Visited.PENDING)
    214                     visited = visited.getNext();
    215 
    216                 if (targetPoint.apply(p).equals(current) && visited == Visited.BUSY)
    217                     visited = visited.getNext();
    218 
    219                 return visited;
    220             }
    221 
    222             @Override
    223             public boolean hasNext() {
    224                 T current = supplier.get();
    225 
    226                 return current != garage || targetList.stream()
    227                         .map(p -> checkVisited(p, current))
    228                         .anyMatch(Visited::doInclude);
    229             }
    230 
    231             @Override
    232             public TargetSet<P, T> next() {
    233                 T current = supplier.get();
    234 
    235                 List<T> targetNodes = targetList.stream()
    236                         .map(p -> Map.entry(p, checkVisited(p, current)))
    237                         .peek(e -> targetMap.put(e.getKey(), e.getValue()))
    238 
    239                         .map(e -> switch (e.getValue()) {
    240                             case PENDING -> startPoint.apply(e.getKey());
    241                             case BUSY -> targetPoint.apply(e.getKey());
    242                             case FINISHED -> null;
    243                         })
    244                         .filter(Objects::nonNull)
    245                         .toList();
    246 
    247                 if (targetNodes.isEmpty() && current != garage)
    248                     return new TargetSet<>(TargetIterable.this, targetMap, List.of(garage));
    249 
    250                 return new TargetSet<>(TargetIterable.this, targetMap, targetNodes);
    251             }
    252         };
    253     }
    254 }