diff options
author | 2024-03-07 22:10:42 +0100 | |
---|---|---|
committer | 2024-04-07 14:55:46 +0200 | |
commit | 16a9b534adec2c53b50f92a43c1623918b1c59c0 (patch) | |
tree | 690b299a2ca31e302ddad219a7aa94bcf86d5d0b /subprojects/store/src/main/java/tools | |
parent | fix(frontend): * operator highlighting (diff) | |
download | refinery-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')
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 | */ | ||
6 | package tools.refinery.store.representation; | ||
7 | |||
8 | import java.util.Objects; | ||
9 | import java.util.Optional; | ||
10 | |||
11 | public 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 | */ | ||
6 | package tools.refinery.store.representation; | ||
7 | |||
8 | public 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 | */ | ||
6 | package tools.refinery.store.representation; | ||
7 | |||
8 | public 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 | */ | ||
6 | package tools.refinery.store.representation; | ||
7 | |||
8 | import java.util.Optional; | ||
9 | |||
10 | // Singleton pattern, because there is only one domain for truth values. | ||
11 | @SuppressWarnings("squid:S6548") | ||
12 | public 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 | */ | ||
6 | package tools.refinery.store.representation.cardinality; | ||
7 | |||
8 | import tools.refinery.store.representation.AbstractDomain; | ||
9 | |||
10 | import java.util.Optional; | ||
11 | |||
12 | // Singleton pattern, because there is only one domain for truth values. | ||
13 | @SuppressWarnings("squid:S6548") | ||
14 | public 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 | */ | ||
6 | package tools.refinery.store.representation.cardinality; | ||
7 | |||
8 | public 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 | */ | ||
6 | package tools.refinery.store.representation.cardinality; | ||
7 | |||
8 | public 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 | */ | ||
6 | package tools.refinery.store.representation.cardinality; | ||
7 | |||
8 | // Singleton implementation, because there is only a single empty interval. | ||
9 | @SuppressWarnings("squid:S6548") | ||
10 | public 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 | */ | ||
6 | package tools.refinery.store.representation.cardinality; | ||
7 | |||
8 | import org.jetbrains.annotations.NotNull; | ||
9 | import org.jetbrains.annotations.Nullable; | ||
10 | |||
11 | import java.util.function.IntBinaryOperator; | ||
12 | |||
13 | public 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 | */ | ||
6 | package tools.refinery.store.representation.cardinality; | ||
7 | |||
8 | import java.util.Objects; | ||
9 | import java.util.function.BinaryOperator; | ||
10 | import java.util.function.IntBinaryOperator; | ||
11 | |||
12 | public 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 | */ | ||
6 | package tools.refinery.store.representation.cardinality; | ||
7 | |||
8 | import org.jetbrains.annotations.NotNull; | ||
9 | |||
10 | // Singleton implementation, because there is only a single countable infinity. | ||
11 | @SuppressWarnings("squid:S6548") | ||
12 | public 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 | */ | ||
6 | package tools.refinery.store.representation.cardinality; | ||
7 | |||
8 | public 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 | */ | ||
6 | package tools.refinery.store.representation.cardinality; | ||
7 | |||
8 | import org.jetbrains.annotations.Nullable; | ||
9 | |||
10 | public 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 | */ | ||
6 | package tools.refinery.store.util; | ||
7 | |||
8 | import java.util.*; | ||
9 | import java.util.function.Function; | ||
10 | import java.util.stream.Collectors; | ||
11 | |||
12 | public 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 | } | ||