aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/store/src/main/java/tools
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kristof@marussy.com>2024-03-07 22:10:42 +0100
committerLibravatar Kristóf Marussy <kristof@marussy.com>2024-04-07 14:55:46 +0200
commit16a9b534adec2c53b50f92a43c1623918b1c59c0 (patch)
tree690b299a2ca31e302ddad219a7aa94bcf86d5d0b /subprojects/store/src/main/java/tools
parentfix(frontend): * operator highlighting (diff)
downloadrefinery-16a9b534adec2c53b50f92a43c1623918b1c59c0.tar.gz
refinery-16a9b534adec2c53b50f92a43c1623918b1c59c0.tar.zst
refinery-16a9b534adec2c53b50f92a43c1623918b1c59c0.zip
refactor: move terms and DNF into logic subproject
Diffstat (limited to 'subprojects/store/src/main/java/tools')
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/representation/AbstractDomain.java37
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/representation/AnyAbstractDomain.java12
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/representation/TruthValue.java76
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/representation/TruthValueDomain.java66
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/CardinalityDomain.java68
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/CardinalityInterval.java28
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/CardinalityIntervals.java51
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/EmptyCardinalityInterval.java71
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/FiniteUpperCardinality.java83
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/NonEmptyCardinalityInterval.java106
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/UnboundedUpperCardinality.java66
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/UpperCardinalities.java38
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/UpperCardinality.java32
-rw-r--r--subprojects/store/src/main/java/tools/refinery/store/util/CycleDetectingMapper.java61
14 files changed, 0 insertions, 795 deletions
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/AbstractDomain.java b/subprojects/store/src/main/java/tools/refinery/store/representation/AbstractDomain.java
deleted file mode 100644
index dfdb43bd..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/representation/AbstractDomain.java
+++ /dev/null
@@ -1,37 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.representation;
7
8import java.util.Objects;
9import java.util.Optional;
10
11public non-sealed interface AbstractDomain<A, C> extends AnyAbstractDomain {
12 @Override
13 Class<A> abstractType();
14
15 @Override
16 Class<C> concreteType();
17
18 A toAbstract(C concreteValue);
19
20 Optional<C> toConcrete(A abstractValue);
21
22 default boolean isConcrete(A abstractValue) {
23 return toConcrete(abstractValue).isPresent();
24 }
25
26 default boolean isRefinement(A originalValue, A refinedValue) {
27 return Objects.equals(commonRefinement(originalValue, refinedValue), refinedValue);
28 }
29
30 A commonRefinement(A leftValue, A rightValue);
31
32 A commonAncestor(A leftValue, A rightValue);
33
34 A unknown();
35
36 boolean isError(A abstractValue);
37}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/AnyAbstractDomain.java b/subprojects/store/src/main/java/tools/refinery/store/representation/AnyAbstractDomain.java
deleted file mode 100644
index c354fab7..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/representation/AnyAbstractDomain.java
+++ /dev/null
@@ -1,12 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.representation;
7
8public sealed interface AnyAbstractDomain permits AbstractDomain {
9 Class<?> abstractType();
10
11 Class<?> concreteType();
12}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/TruthValue.java b/subprojects/store/src/main/java/tools/refinery/store/representation/TruthValue.java
deleted file mode 100644
index f81ee9a4..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/representation/TruthValue.java
+++ /dev/null
@@ -1,76 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.representation;
7
8public enum TruthValue {
9 TRUE("true"),
10
11 FALSE("false"),
12
13 UNKNOWN("unknown"),
14
15 ERROR("error");
16
17 private final String name;
18
19 TruthValue(String name) {
20 this.name = name;
21 }
22
23 public String getName() {
24 return name;
25 }
26
27 public static TruthValue toTruthValue(boolean value) {
28 return value ? TRUE : FALSE;
29 }
30
31 public boolean isConsistent() {
32 return this != ERROR;
33 }
34
35 public boolean isComplete() {
36 return this != UNKNOWN;
37 }
38
39 public boolean isConcrete() {
40 return this == TRUE || this == FALSE;
41 }
42
43 public boolean must() {
44 return this == TRUE || this == ERROR;
45 }
46
47 public boolean may() {
48 return this == TRUE || this == UNKNOWN;
49 }
50
51 public TruthValue not() {
52 return switch (this) {
53 case TRUE -> FALSE;
54 case FALSE -> TRUE;
55 default -> this;
56 };
57 }
58
59 public TruthValue merge(TruthValue other) {
60 return switch (this) {
61 case TRUE -> other == UNKNOWN || other == TRUE ? TRUE : ERROR;
62 case FALSE -> other == UNKNOWN || other == FALSE ? FALSE : ERROR;
63 case UNKNOWN -> other;
64 case ERROR -> ERROR;
65 };
66 }
67
68 public TruthValue join(TruthValue other) {
69 return switch (this) {
70 case TRUE -> other == ERROR || other == TRUE ? TRUE : UNKNOWN;
71 case FALSE -> other == ERROR || other == FALSE ? FALSE : UNKNOWN;
72 case UNKNOWN -> UNKNOWN;
73 case ERROR -> other;
74 };
75 }
76}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/TruthValueDomain.java b/subprojects/store/src/main/java/tools/refinery/store/representation/TruthValueDomain.java
deleted file mode 100644
index 61696dca..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/representation/TruthValueDomain.java
+++ /dev/null
@@ -1,66 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.representation;
7
8import java.util.Optional;
9
10// Singleton pattern, because there is only one domain for truth values.
11@SuppressWarnings("squid:S6548")
12public final class TruthValueDomain implements AbstractDomain<TruthValue, Boolean> {
13 public static final TruthValueDomain INSTANCE = new TruthValueDomain();
14
15 private TruthValueDomain() {
16 }
17
18 @Override
19 public Class<TruthValue> abstractType() {
20 return TruthValue.class;
21 }
22
23 @Override
24 public Class<Boolean> concreteType() {
25 return Boolean.class;
26 }
27
28 @Override
29 public TruthValue toAbstract(Boolean concreteValue) {
30 return TruthValue.toTruthValue(concreteValue);
31 }
32
33 @Override
34 public Optional<Boolean> toConcrete(TruthValue abstractValue) {
35 return switch (abstractValue) {
36 case TRUE -> Optional.of(true);
37 case FALSE -> Optional.of(false);
38 default -> Optional.empty();
39 };
40 }
41
42 @Override
43 public boolean isConcrete(TruthValue abstractValue) {
44 return abstractValue.isConcrete();
45 }
46
47 @Override
48 public TruthValue commonRefinement(TruthValue leftValue, TruthValue rightValue) {
49 return leftValue.merge(rightValue);
50 }
51
52 @Override
53 public TruthValue commonAncestor(TruthValue leftValue, TruthValue rightValue) {
54 return leftValue.join(rightValue);
55 }
56
57 @Override
58 public TruthValue unknown() {
59 return TruthValue.UNKNOWN;
60 }
61
62 @Override
63 public boolean isError(TruthValue abstractValue) {
64 return !abstractValue.isConsistent();
65 }
66}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/CardinalityDomain.java b/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/CardinalityDomain.java
deleted file mode 100644
index 7ae2d935..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/CardinalityDomain.java
+++ /dev/null
@@ -1,68 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.representation.cardinality;
7
8import tools.refinery.store.representation.AbstractDomain;
9
10import java.util.Optional;
11
12// Singleton pattern, because there is only one domain for truth values.
13@SuppressWarnings("squid:S6548")
14public class CardinalityDomain implements AbstractDomain<CardinalityInterval, Integer> {
15 public static final CardinalityDomain INSTANCE = new CardinalityDomain();
16
17 private CardinalityDomain() {
18 }
19
20 @Override
21 public Class<CardinalityInterval> abstractType() {
22 return CardinalityInterval.class;
23 }
24
25 @Override
26 public Class<Integer> concreteType() {
27 return Integer.class;
28 }
29
30 @Override
31 public CardinalityInterval toAbstract(Integer concreteValue) {
32 return CardinalityIntervals.exactly(concreteValue);
33 }
34
35 @Override
36 public Optional<Integer> toConcrete(CardinalityInterval abstractValue) {
37 return isConcrete(abstractValue) ? Optional.of(abstractValue.lowerBound()) : Optional.empty();
38 }
39
40 @Override
41 public boolean isConcrete(CardinalityInterval abstractValue) {
42 if (!(abstractValue instanceof NonEmptyCardinalityInterval nonEmptyValue) ||
43 !((nonEmptyValue.upperBound()) instanceof FiniteUpperCardinality finiteUpperCardinality)) {
44 return false;
45 }
46 return nonEmptyValue.lowerBound() == finiteUpperCardinality.finiteUpperBound();
47 }
48
49 @Override
50 public CardinalityInterval commonRefinement(CardinalityInterval leftValue, CardinalityInterval rightValue) {
51 return leftValue.meet(rightValue);
52 }
53
54 @Override
55 public CardinalityInterval commonAncestor(CardinalityInterval leftValue, CardinalityInterval rightValue) {
56 return leftValue.join(rightValue);
57 }
58
59 @Override
60 public CardinalityInterval unknown() {
61 return CardinalityIntervals.SET;
62 }
63
64 @Override
65 public boolean isError(CardinalityInterval abstractValue) {
66 return abstractValue.isEmpty();
67 }
68}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/CardinalityInterval.java b/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/CardinalityInterval.java
deleted file mode 100644
index b20c685a..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/CardinalityInterval.java
+++ /dev/null
@@ -1,28 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.representation.cardinality;
7
8public sealed interface CardinalityInterval permits NonEmptyCardinalityInterval, EmptyCardinalityInterval {
9 int lowerBound();
10
11 UpperCardinality upperBound();
12
13 boolean isEmpty();
14
15 CardinalityInterval min(CardinalityInterval other);
16
17 CardinalityInterval max(CardinalityInterval other);
18
19 CardinalityInterval add(CardinalityInterval other);
20
21 CardinalityInterval take(int count);
22
23 CardinalityInterval multiply(CardinalityInterval other);
24
25 CardinalityInterval meet(CardinalityInterval other);
26
27 CardinalityInterval join(CardinalityInterval other);
28}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/CardinalityIntervals.java b/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/CardinalityIntervals.java
deleted file mode 100644
index 855fd248..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/CardinalityIntervals.java
+++ /dev/null
@@ -1,51 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.representation.cardinality;
7
8public final class CardinalityIntervals {
9 public static final CardinalityInterval NONE = exactly(0);
10
11 public static final CardinalityInterval ONE = exactly(1);
12
13 public static final CardinalityInterval LONE = atMost(1);
14
15 public static final CardinalityInterval SET = atLeast(0);
16
17 public static final CardinalityInterval SOME = atLeast(1);
18
19 public static final CardinalityInterval ERROR = EmptyCardinalityInterval.INSTANCE;
20
21 private CardinalityIntervals() {
22 throw new IllegalStateException("This is a static utility class and should not be instantiated directly");
23 }
24
25 public static CardinalityInterval between(int lowerBound, UpperCardinality upperBound) {
26 if (upperBound.compareToInt(lowerBound) < 0) {
27 return ERROR;
28 }
29 return new NonEmptyCardinalityInterval(lowerBound, upperBound);
30 }
31
32 public static CardinalityInterval between(int lowerBound, int upperBound) {
33 return between(lowerBound, UpperCardinalities.atMost(upperBound));
34 }
35
36 public static CardinalityInterval atMost(UpperCardinality upperBound) {
37 return new NonEmptyCardinalityInterval(0, upperBound);
38 }
39
40 public static CardinalityInterval atMost(int upperBound) {
41 return atMost(UpperCardinalities.atMost(upperBound));
42 }
43
44 public static CardinalityInterval atLeast(int lowerBound) {
45 return new NonEmptyCardinalityInterval(lowerBound, UpperCardinalities.UNBOUNDED);
46 }
47
48 public static CardinalityInterval exactly(int lowerBound) {
49 return new NonEmptyCardinalityInterval(lowerBound, UpperCardinalities.atMost(lowerBound));
50 }
51}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/EmptyCardinalityInterval.java b/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/EmptyCardinalityInterval.java
deleted file mode 100644
index 9e371e21..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/EmptyCardinalityInterval.java
+++ /dev/null
@@ -1,71 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.representation.cardinality;
7
8// Singleton implementation, because there is only a single empty interval.
9@SuppressWarnings("squid:S6548")
10public final class EmptyCardinalityInterval implements CardinalityInterval {
11 static final EmptyCardinalityInterval INSTANCE = new EmptyCardinalityInterval();
12
13 private EmptyCardinalityInterval() {
14 // Singleton constructor.
15 }
16
17 @Override
18 public int lowerBound() {
19 return 1;
20 }
21
22 @Override
23 public boolean isEmpty() {
24 return true;
25 }
26
27 @Override
28 public UpperCardinality upperBound() {
29 return UpperCardinalities.ZERO;
30 }
31
32 @Override
33 public CardinalityInterval min(CardinalityInterval other) {
34 return this;
35 }
36
37 @Override
38 public CardinalityInterval max(CardinalityInterval other) {
39 return this;
40 }
41
42 @Override
43 public CardinalityInterval add(CardinalityInterval other) {
44 return this;
45 }
46
47 @Override
48 public CardinalityInterval take(int count) {
49 return this;
50 }
51
52 @Override
53 public CardinalityInterval multiply(CardinalityInterval other) {
54 return this;
55 }
56
57 @Override
58 public CardinalityInterval meet(CardinalityInterval other) {
59 return this;
60 }
61
62 @Override
63 public CardinalityInterval join(CardinalityInterval other) {
64 return other;
65 }
66
67 @Override
68 public String toString() {
69 return "error";
70 }
71}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/FiniteUpperCardinality.java b/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/FiniteUpperCardinality.java
deleted file mode 100644
index b63a8637..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/FiniteUpperCardinality.java
+++ /dev/null
@@ -1,83 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.representation.cardinality;
7
8import org.jetbrains.annotations.NotNull;
9import org.jetbrains.annotations.Nullable;
10
11import java.util.function.IntBinaryOperator;
12
13public record FiniteUpperCardinality(int finiteUpperBound) implements UpperCardinality {
14 public FiniteUpperCardinality {
15 if (finiteUpperBound < 0) {
16 throw new IllegalArgumentException("finiteUpperBound must not be negative");
17 }
18 }
19
20 @Override
21 public UpperCardinality add(UpperCardinality other) {
22 return lift(other, Integer::sum);
23 }
24
25 @Override
26 @Nullable
27 public UpperCardinality take(int count) {
28 if (finiteUpperBound < count) {
29 return null;
30 }
31 return new FiniteUpperCardinality(finiteUpperBound - count);
32 }
33
34 @Override
35 public UpperCardinality multiply(UpperCardinality other) {
36 return lift(other, (a, b) -> a * b);
37 }
38
39 @Override
40 public int compareTo(@NotNull UpperCardinality upperCardinality) {
41 if (upperCardinality instanceof FiniteUpperCardinality finiteUpperCardinality) {
42 return compareToInt(finiteUpperCardinality.finiteUpperBound);
43 }
44 if (upperCardinality instanceof UnboundedUpperCardinality) {
45 return -1;
46 }
47 throw new IllegalArgumentException("Unknown UpperCardinality: " + upperCardinality);
48 }
49
50 @Override
51 public int compareToInt(int value) {
52 return Integer.compare(finiteUpperBound, value);
53 }
54
55 @Override
56 public String toString() {
57 return Integer.toString(finiteUpperBound);
58 }
59
60 private UpperCardinality lift(@NotNull UpperCardinality other, IntBinaryOperator operator) {
61 if (other instanceof FiniteUpperCardinality finiteUpperCardinality) {
62 return UpperCardinalities.atMost(operator.applyAsInt(finiteUpperBound,
63 finiteUpperCardinality.finiteUpperBound));
64 }
65 if (other instanceof UnboundedUpperCardinality) {
66 return UpperCardinalities.UNBOUNDED;
67 }
68 throw new IllegalArgumentException("Unknown UpperCardinality: " + other);
69 }
70
71 @Override
72 public boolean equals(Object o) {
73 if (this == o) return true;
74 if (o == null || getClass() != o.getClass()) return false;
75 FiniteUpperCardinality that = (FiniteUpperCardinality) o;
76 return finiteUpperBound == that.finiteUpperBound;
77 }
78
79 @Override
80 public int hashCode() {
81 return finiteUpperBound;
82 }
83}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/NonEmptyCardinalityInterval.java b/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/NonEmptyCardinalityInterval.java
deleted file mode 100644
index 6bd66df7..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/NonEmptyCardinalityInterval.java
+++ /dev/null
@@ -1,106 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.representation.cardinality;
7
8import java.util.Objects;
9import java.util.function.BinaryOperator;
10import java.util.function.IntBinaryOperator;
11
12public record NonEmptyCardinalityInterval(int lowerBound, UpperCardinality upperBound) implements CardinalityInterval {
13 public NonEmptyCardinalityInterval {
14 if (lowerBound < 0) {
15 throw new IllegalArgumentException("lowerBound must not be negative");
16 }
17 if (upperBound.compareToInt(lowerBound) < 0) {
18 throw new IllegalArgumentException("lowerBound must not be larger than upperBound");
19 }
20 }
21
22 @Override
23 public boolean isEmpty() {
24 return false;
25 }
26
27 @Override
28 public CardinalityInterval min(CardinalityInterval other) {
29 return lift(other, Math::min, UpperCardinality::min);
30 }
31
32 @Override
33 public CardinalityInterval max(CardinalityInterval other) {
34 return lift(other, Math::max, UpperCardinality::max);
35 }
36
37 @Override
38 public CardinalityInterval add(CardinalityInterval other) {
39 return lift(other, Integer::sum, UpperCardinality::add);
40 }
41
42 @Override
43 public CardinalityInterval multiply(CardinalityInterval other) {
44 return lift(other, (a, b) -> a * b, UpperCardinality::multiply);
45 }
46
47 @Override
48 public CardinalityInterval meet(CardinalityInterval other) {
49 return lift(other, Math::max, UpperCardinality::min);
50 }
51
52 @Override
53 public CardinalityInterval join(CardinalityInterval other) {
54 return lift(other, Math::min, UpperCardinality::max, this);
55 }
56
57 @Override
58 public CardinalityInterval take(int count) {
59 int newLowerBound = Math.max(lowerBound - count, 0);
60 var newUpperBound = upperBound.take(count);
61 if (newUpperBound == null) {
62 return CardinalityIntervals.ERROR;
63 }
64 return CardinalityIntervals.between(newLowerBound, newUpperBound);
65 }
66
67 private CardinalityInterval lift(CardinalityInterval other, IntBinaryOperator lowerOperator,
68 BinaryOperator<UpperCardinality> upperOperator,
69 CardinalityInterval whenEmpty) {
70 if (other instanceof NonEmptyCardinalityInterval nonEmptyOther) {
71 return CardinalityIntervals.between(lowerOperator.applyAsInt(lowerBound, nonEmptyOther.lowerBound),
72 upperOperator.apply(upperBound, nonEmptyOther.upperBound));
73 }
74 if (other instanceof EmptyCardinalityInterval) {
75 return whenEmpty;
76 }
77 throw new IllegalArgumentException("Unknown CardinalityInterval: " + other);
78 }
79
80 private CardinalityInterval lift(CardinalityInterval other, IntBinaryOperator lowerOperator,
81 BinaryOperator<UpperCardinality> upperOperator) {
82 return lift(other, lowerOperator, upperOperator, CardinalityIntervals.ERROR);
83 }
84
85 @Override
86 public String toString() {
87 if (upperBound instanceof FiniteUpperCardinality finiteUpperCardinality &&
88 finiteUpperCardinality.finiteUpperBound() == lowerBound) {
89 return "[%d]".formatted(lowerBound);
90 }
91 return "[%d..%s]".formatted(lowerBound, upperBound);
92 }
93
94 @Override
95 public boolean equals(Object o) {
96 if (this == o) return true;
97 if (o == null || getClass() != o.getClass()) return false;
98 NonEmptyCardinalityInterval that = (NonEmptyCardinalityInterval) o;
99 return lowerBound == that.lowerBound && Objects.equals(upperBound, that.upperBound);
100 }
101
102 @Override
103 public int hashCode() {
104 return lowerBound * 31 + upperBound.hashCode();
105 }
106}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/UnboundedUpperCardinality.java b/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/UnboundedUpperCardinality.java
deleted file mode 100644
index 03c701ae..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/UnboundedUpperCardinality.java
+++ /dev/null
@@ -1,66 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.representation.cardinality;
7
8import org.jetbrains.annotations.NotNull;
9
10// Singleton implementation, because there is only a single countable infinity.
11@SuppressWarnings("squid:S6548")
12public final class UnboundedUpperCardinality implements UpperCardinality {
13 static final UnboundedUpperCardinality INSTANCE = new UnboundedUpperCardinality();
14
15 private UnboundedUpperCardinality() {
16 // Singleton constructor.
17 }
18
19 @Override
20 public UpperCardinality add(UpperCardinality other) {
21 return this;
22 }
23
24 @Override
25 public UpperCardinality take(int count) {
26 return this;
27 }
28
29 @Override
30 public UpperCardinality multiply(UpperCardinality other) {
31 return this;
32 }
33
34 // This should always be greater than any finite cardinality.
35 @SuppressWarnings("ComparatorMethodParameterNotUsed")
36 @Override
37 public int compareTo(@NotNull UpperCardinality upperCardinality) {
38 if (upperCardinality instanceof FiniteUpperCardinality) {
39 return 1;
40 }
41 if (upperCardinality instanceof UnboundedUpperCardinality) {
42 return 0;
43 }
44 throw new IllegalArgumentException("Unknown UpperCardinality: " + upperCardinality);
45 }
46
47 @Override
48 public int compareToInt(int value) {
49 return 1;
50 }
51
52 @Override
53 public String toString() {
54 return "*";
55 }
56
57 @Override
58 public boolean equals(Object obj) {
59 return this == obj || (obj != null && getClass() == obj.getClass());
60 }
61
62 @Override
63 public int hashCode() {
64 return -1;
65 }
66}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/UpperCardinalities.java b/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/UpperCardinalities.java
deleted file mode 100644
index 17d1b292..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/UpperCardinalities.java
+++ /dev/null
@@ -1,38 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.representation.cardinality;
7
8public final class UpperCardinalities {
9 public static final UpperCardinality UNBOUNDED = UnboundedUpperCardinality.INSTANCE;
10
11 public static final UpperCardinality ZERO;
12
13 public static final UpperCardinality ONE;
14
15 private static final FiniteUpperCardinality[] cache = new FiniteUpperCardinality[256];
16
17 static {
18 for (int i = 0; i < cache.length; i++) {
19 cache[i] = new FiniteUpperCardinality(i);
20 }
21 ZERO = cache[0];
22 ONE = cache[1];
23 }
24
25 private UpperCardinalities() {
26 throw new IllegalStateException("This is a static utility class and should not be instantiated directly");
27 }
28
29 public static UpperCardinality atMost(int upperBound) {
30 if (upperBound < 0) {
31 return UNBOUNDED;
32 }
33 if (upperBound < cache.length) {
34 return cache[upperBound];
35 }
36 return new FiniteUpperCardinality(upperBound);
37 }
38}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/UpperCardinality.java b/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/UpperCardinality.java
deleted file mode 100644
index 3f0db028..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/UpperCardinality.java
+++ /dev/null
@@ -1,32 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.representation.cardinality;
7
8import org.jetbrains.annotations.Nullable;
9
10public sealed interface UpperCardinality extends Comparable<UpperCardinality> permits FiniteUpperCardinality,
11 UnboundedUpperCardinality {
12 default UpperCardinality min(UpperCardinality other) {
13 return this.compareTo(other) <= 0 ? this : other;
14 }
15
16 default UpperCardinality max(UpperCardinality other) {
17 return this.compareTo(other) >= 0 ? this : other;
18 }
19
20 UpperCardinality add(UpperCardinality other);
21
22 @Nullable
23 UpperCardinality take(int count);
24
25 UpperCardinality multiply(UpperCardinality other);
26
27 int compareToInt(int value);
28
29 static UpperCardinality of(int upperBound) {
30 return UpperCardinalities.atMost(upperBound);
31 }
32}
diff --git a/subprojects/store/src/main/java/tools/refinery/store/util/CycleDetectingMapper.java b/subprojects/store/src/main/java/tools/refinery/store/util/CycleDetectingMapper.java
deleted file mode 100644
index 2e302663..00000000
--- a/subprojects/store/src/main/java/tools/refinery/store/util/CycleDetectingMapper.java
+++ /dev/null
@@ -1,61 +0,0 @@
1/*
2 * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.store.util;
7
8import java.util.*;
9import java.util.function.Function;
10import java.util.stream.Collectors;
11
12public class CycleDetectingMapper<T, R> {
13 private static final String SEPARATOR = " -> ";
14
15 private final Function<T, String> getName;
16
17 private final Function<T, R> doMap;
18
19 private final Set<T> inProgress = new LinkedHashSet<>();
20
21 private final Map<T, R> results = new HashMap<>();
22
23 public CycleDetectingMapper(Function<T, R> doMap) {
24 this(Objects::toString, doMap);
25 }
26
27 public CycleDetectingMapper(Function<T, String> getName, Function<T, R> doMap) {
28 this.getName = getName;
29 this.doMap = doMap;
30 }
31
32 public R map(T input) {
33 if (inProgress.contains(input)) {
34 var path = inProgress.stream().map(getName).collect(Collectors.joining(SEPARATOR));
35 throw new IllegalArgumentException("Circular reference %s%s%s detected".formatted(path, SEPARATOR,
36 getName.apply(input)));
37 }
38 // We can't use computeIfAbsent here, because translating referenced queries calls this method in a reentrant
39 // way, which would cause a ConcurrentModificationException with computeIfAbsent.
40 @SuppressWarnings("squid:S3824")
41 var result = results.get(input);
42 if (result == null) {
43 inProgress.add(input);
44 try {
45 result = doMap.apply(input);
46 results.put(input, result);
47 } finally {
48 inProgress.remove(input);
49 }
50 }
51 return result;
52 }
53
54 public List<T> getInProgress() {
55 return List.copyOf(inProgress);
56 }
57
58 public R getAlreadyMapped(T input) {
59 return results.get(input);
60 }
61}