Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package ai.timefold.solver.core.api.score.stream;

import java.util.SequencedCollection;
import java.util.function.BiFunction;
import java.util.function.BiPredicate;
import java.util.function.Function;
Expand Down Expand Up @@ -256,6 +257,93 @@ public final class Joiners {
.and(Joiners.greaterThan(leftEndMapping, rightStartMapping));
}

/**
* Joins every A and B where a value of property on B is contained in the collection of properties on A.
* <p>
* For example:
* <ul>
* <li>{@code ["A", "B"]} containing {@code "A"} is {@code true}</li>
* <li>{@code ["A"]} containing {@code "A"} is {@code true}</li>
* <li>{@code ["X", "Y"]} containing {@code "A"} is {@code false}</li>
* <li>{@code []} containing {@code "A"} is {@code false}</li>
* <li>{@code ["A", "B"]} containing {@code null} is {@code false}</li>
* <li>{@code []} containing {@code null} is {@code false}</li>
* </ul>
*
* @param leftMapping mapping function to apply to A
* @param rightMapping mapping function to apply to B
* @param <A> the type of object on the left
* @param <B> the type of object on the right
* @param <Property_> the type of the property to compare
*/
public static <A, B, Property_> @NonNull BiJoiner<A, B> containing(
@NonNull Function<A, SequencedCollection<Property_>> leftMapping,
@NonNull Function<B, Property_> rightMapping) {
return new DefaultBiJoiner<>(leftMapping, JoinerType.CONTAINING, rightMapping);
}

/**
* Joins every A and B where a value of property on A is contained in the collection of properties on B.
* <p>
* For example:
* <ul>
* <li>{@code "A"} contained in {@code ["A", "B"]} is {@code true}</li>
* <li>{@code "A"} contained in {@code ["A"]} is {@code true}</li>
* <li>{@code "A"} contained in {@code ["X", "Y"]} is {@code false}</li>
* <li>{@code "A"} contained in {@code []} is {@code false}</li>
* <li>{@code null} contained in {@code ["A", "B"]} is {@code false}</li>
* <li>{@code null} contained in {@code []} is {@code false}</li>
* </ul>
*
* @param leftMapping mapping function to apply to A
* @param rightMapping mapping function to apply to B
* @param <A> the type of object on the left
* @param <B> the type of object on the right
* @param <Property_> the type of the property to compare
*/
public static <A, B, Property_> @NonNull BiJoiner<A, B> containedIn(@NonNull Function<A, Property_> leftMapping,
@NonNull Function<B, SequencedCollection<Property_>> rightMapping) {
return new DefaultBiJoiner<>(leftMapping, JoinerType.CONTAINED_IN, rightMapping);
}

/**
* As defined by {@link #containingAnyOf(Function, Function)} with both arguments using the same mapping.
*
* @param mapping mapping function to apply to both A and B
* @param <A> the type of both objects
* @param <Property_> the type of the property to compare
*/
public static <A, Property_> @NonNull BiJoiner<A, A> containingAnyOf(
@NonNull Function<A, SequencedCollection<Property_>> mapping) {
return containingAnyOf(mapping, mapping);
}

/**
* Joins every A and B where a collection of properties on A overlaps with a collection of properties on B.
* <p>
* For example:
* <ul>
* <li>{@code ["A", "B"]} intersecting {@code ["A", "B"]} is {@code true}</li>
* <li>{@code ["A", "B"]} intersecting {@code ["A"]} is {@code true}</li>
* <li>{@code ["A"]} intersecting {@code ["A", "B"]} is {@code true}</li>
* <li>{@code ["A", "B"]} intersecting {@code ["X", "Y"]} is {@code false}</li>
* <li>{@code ["A", "B"]} intersecting {@code []} is {@code false}</li>
* <li>{@code []} intersecting {@code ["A", "B"]} is {@code false}</li>
* <li>{@code []} intersecting {@code []} is {@code false}</li>
* </ul>
*
* @param leftMapping mapping function to apply to A
* @param rightMapping mapping function to apply to B
* @param <A> the type of object on the left
* @param <B> the type of object on the right
* @param <Property_> the type of the property to compare
*/
public static <A, B, Property_> @NonNull BiJoiner<A, B> containingAnyOf(
@NonNull Function<A, SequencedCollection<Property_>> leftMapping,
@NonNull Function<B, SequencedCollection<Property_>> rightMapping) {
return new DefaultBiJoiner<>(leftMapping, JoinerType.CONTAINING_ANY_OF, rightMapping);
}

// ************************************************************************
// TriJoiner
// ************************************************************************
Expand Down Expand Up @@ -366,6 +454,53 @@ public final class Joiners {
.and(Joiners.greaterThan(leftEndMapping, rightStartMapping));
}

/**
* As defined by {@link #containing(Function, Function)}.
*
* @param <A> the type of the first object on the left
* @param <B> the type of the second object on the left
* @param <C> the type of the object on the right
* @param <Property_> the type of the collection elements
* @param leftMapping mapping function to apply to (A,B)
* @param rightMapping mapping function to apply to C
*/
public static <A, B, C, Property_> @NonNull TriJoiner<A, B, C> containing(
@NonNull BiFunction<A, B, SequencedCollection<Property_>> leftMapping,
@NonNull Function<C, Property_> rightMapping) {
return new DefaultTriJoiner<>(leftMapping, JoinerType.CONTAINING, rightMapping);
}

/**
* As defined by {@link #containedIn(Function, Function)}.
*
* @param <A> the type of the first object on the left
* @param <B> the type of the second object on the left
* @param <C> the type of the object on the right
* @param <Property_> the type of the collection elements
* @param leftMapping mapping function to apply to (A,B)
* @param rightMapping mapping function to apply to C
*/
public static <A, B, C, Property_> @NonNull TriJoiner<A, B, C> containedIn(@NonNull BiFunction<A, B, Property_> leftMapping,
@NonNull Function<C, SequencedCollection<Property_>> rightMapping) {
return new DefaultTriJoiner<>(leftMapping, JoinerType.CONTAINED_IN, rightMapping);
}

/**
* As defined by {@link #containingAnyOf(Function, Function)}.
*
* @param <A> the type of the first object on the left
* @param <B> the type of the second object on the left
* @param <C> the type of the object on the right
* @param <Property_> the type of the collection elements
* @param leftMapping mapping function to apply to (A,B)
* @param rightMapping mapping function to apply to C
*/
public static <A, B, C, Property_> @NonNull TriJoiner<A, B, C> containingAnyOf(
@NonNull BiFunction<A, B, SequencedCollection<Property_>> leftMapping,
@NonNull Function<C, SequencedCollection<Property_>> rightMapping) {
return new DefaultTriJoiner<>(leftMapping, JoinerType.CONTAINING_ANY_OF, rightMapping);
}

// ************************************************************************
// QuadJoiner
// ************************************************************************
Expand Down Expand Up @@ -483,6 +618,57 @@ public final class Joiners {
.and(Joiners.greaterThan(leftEndMapping, rightStartMapping));
}

/**
* As defined by {@link #containing(Function, Function)}.
*
* @param <A> the type of the first object on the left
* @param <B> the type of the second object on the left
* @param <C> the type of the third object on the left
* @param <D> the type of the object on the right
* @param <Property_> the type of the collection elements
* @param leftMapping mapping function to apply to (A,B,C)
* @param rightMapping mapping function to apply to D
*/
public static <A, B, C, D, Property_> @NonNull QuadJoiner<A, B, C, D> containing(
@NonNull TriFunction<A, B, C, SequencedCollection<Property_>> leftMapping,
@NonNull Function<D, Property_> rightMapping) {
return new DefaultQuadJoiner<>(leftMapping, JoinerType.CONTAINING, rightMapping);
}

/**
* As defined by {@link #containedIn(Function, Function)}.
*
* @param <A> the type of the first object on the left
* @param <B> the type of the second object on the left
* @param <C> the type of the third object on the left
* @param <D> the type of the object on the right
* @param <Property_> the type of the collection elements
* @param leftMapping mapping function to apply to (A,B,C)
* @param rightMapping mapping function to apply to D
*/
public static <A, B, C, D, Property_> @NonNull QuadJoiner<A, B, C, D> containedIn(
@NonNull TriFunction<A, B, C, Property_> leftMapping,
@NonNull Function<D, SequencedCollection<Property_>> rightMapping) {
return new DefaultQuadJoiner<>(leftMapping, JoinerType.CONTAINED_IN, rightMapping);
}

/**
* As defined by {@link #containingAnyOf(Function, Function)}.
*
* @param <A> the type of the first object on the left
* @param <B> the type of the second object on the left
* @param <C> the type of the third object on the left
* @param <D> the type of the object on the right
* @param <Property_> the type of the collection elements
* @param leftMapping mapping function to apply to (A,B,C)
* @param rightMapping mapping function to apply to D
*/
public static <A, B, C, D, Property_> @NonNull QuadJoiner<A, B, C, D> containingAnyOf(
@NonNull TriFunction<A, B, C, SequencedCollection<Property_>> leftMapping,
@NonNull Function<D, SequencedCollection<Property_>> rightMapping) {
return new DefaultQuadJoiner<>(leftMapping, JoinerType.CONTAINING_ANY_OF, rightMapping);
}

// ************************************************************************
// PentaJoiner
// ************************************************************************
Expand Down Expand Up @@ -608,7 +794,60 @@ public final class Joiners {
.and(Joiners.greaterThan(leftEndMapping, rightStartMapping));
}

private Joiners() {
/**
* As defined by {@link #containing(Function, Function)}.
*
* @param <A> the type of the first object on the left
* @param <B> the type of the second object on the left
* @param <C> the type of the third object on the left
* @param <D> the type of the fourth object on the left
* @param <E> the type of the object on the right
* @param <Property_> the type of the collection elements
* @param leftMapping mapping function to apply to (A,B,C,D)
* @param rightMapping mapping function to apply to E
*/
public static <A, B, C, D, E, Property_> @NonNull PentaJoiner<A, B, C, D, E> containing(
@NonNull QuadFunction<A, B, C, D, SequencedCollection<Property_>> leftMapping,
@NonNull Function<E, Property_> rightMapping) {
return new DefaultPentaJoiner<>(leftMapping, JoinerType.CONTAINING, rightMapping);
}

/**
* As defined by {@link #containedIn(Function, Function)}.
*
* @param <A> the type of the first object on the left
* @param <B> the type of the second object on the left
* @param <C> the type of the third object on the left
* @param <D> the type of the fourth object on the left
* @param <E> the type of the object on the right
* @param <Property_> the type of the collection elements
* @param leftMapping mapping function to apply to (A,B,C,D)
* @param rightMapping mapping function to apply to E
*/
public static <A, B, C, D, E, Property_> @NonNull PentaJoiner<A, B, C, D, E> containedIn(
@NonNull QuadFunction<A, B, C, D, Property_> leftMapping,
@NonNull Function<E, SequencedCollection<Property_>> rightMapping) {
return new DefaultPentaJoiner<>(leftMapping, JoinerType.CONTAINED_IN, rightMapping);
}

/**
* As defined by {@link #containingAnyOf(Function, Function)}.
*
* @param <A> the type of the first object on the left
* @param <B> the type of the second object on the left
* @param <C> the type of the third object on the left
* @param <D> the type of the fourth object on the left
* @param <E> the type of the object on the right
* @param <Property_> the type of the collection elements
* @param leftMapping mapping function to apply to (A,B,C,D)
* @param rightMapping mapping function to apply to E
*/
public static <A, B, C, D, E, Property_> @NonNull PentaJoiner<A, B, C, D, E> containingAnyOf(
@NonNull QuadFunction<A, B, C, D, SequencedCollection<Property_>> leftMapping,
@NonNull Function<E, SequencedCollection<Property_>> rightMapping) {
return new DefaultPentaJoiner<>(leftMapping, JoinerType.CONTAINING_ANY_OF, rightMapping);
}

private Joiners() {
}
}
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
package ai.timefold.solver.core.impl.bavet.common.index;

import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.SequencedCollection;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
import java.util.random.RandomGenerator;

import ai.timefold.solver.core.impl.score.stream.UnfinishedJoiners;
import ai.timefold.solver.core.api.score.stream.Joiners;
import ai.timefold.solver.core.impl.util.ListEntry;

import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;

/**
* As defined by {@link UnfinishedJoiners#containedIn(Function, Function)}
* As defined by {@link Joiners#containedIn(Function, Function)}
*/
@NullMarked
final class ContainedInIndexer<T, Key_, KeyCollection_ extends Collection<Key_>> implements Indexer<T> {
final class ContainedInIndexer<T, Key_, KeyCollection_ extends SequencedCollection<Key_>> implements Indexer<T> {

private final KeyUnpacker<Key_> modifyKeyUnpacker;
private final KeyUnpacker<KeyCollection_> queryKeyUnpacker;
Expand Down
Loading
Loading