1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
|
/*
* SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
*
* SPDX-License-Identifier: EPL-2.0
*/
package tools.refinery.store.model.internal;
import org.eclipse.collections.api.factory.Maps;
import org.eclipse.collections.api.factory.primitive.IntObjectMaps;
import org.eclipse.collections.api.map.MutableMap;
import org.eclipse.collections.api.map.primitive.MutableIntObjectMap;
import tools.refinery.store.map.*;
import tools.refinery.store.tuple.Tuple;
import java.util.Set;
class BaseIndexer<T> {
private final MutableIntObjectMap<MutableMap<Tuple, T>>[] maps;
private final VersionedMap<Tuple, T> versionedMap;
public BaseIndexer(int arity, VersionedMap<Tuple, T> map) {
if (arity < 2) {
throw new IllegalArgumentException("Only arity >= 2 symbols need to be indexed");
}
// There is no way in Java to create a generic array in a checked way.
@SuppressWarnings({"unchecked", "squid:S1905"})
var uncheckedMaps = (MutableIntObjectMap<MutableMap<Tuple, T>>[]) new MutableIntObjectMap[arity];
maps = uncheckedMaps;
for (int i = 0; i < arity; i++) {
maps[i] = IntObjectMaps.mutable.empty();
}
this.versionedMap = map;
if (map != null) {
var cursor = map.getAll();
while (cursor.move()) {
put(cursor.getKey(), cursor.getValue());
}
}
}
public void put(Tuple key, T value) {
for (int i = 0; i < maps.length; i++) {
var map = maps[i];
int element = key.get(i);
var adjacentTuples = map.getIfAbsentPut(element, Maps.mutable::empty);
adjacentTuples.put(key, value);
}
}
public void remove(Tuple key) {
for (int i = 0; i < maps.length; i++) {
var map = maps[i];
int element = key.get(i);
var adjacentTuples = map.get(element);
if (adjacentTuples == null) {
continue;
}
adjacentTuples.remove(key);
if (adjacentTuples.isEmpty()) {
map.remove(element);
}
}
}
private MutableMap<Tuple, T> getAdjacentMap(int slot, int node) {
if (slot < 0 || slot >= maps.length) {
throw new IllegalArgumentException("Invalid index: " + slot);
}
var map = maps[slot];
return map.get(node);
}
public int getAdjacentSize(int slot, int node) {
var adjacentTuples = getAdjacentMap(slot, node);
if (adjacentTuples == null) {
return 0;
}
return adjacentTuples.size();
}
public Cursor<Tuple, T> getAdjacent(int slot, int node) {
var adjacentTuples = getAdjacentMap(slot, node);
if (adjacentTuples == null) {
return Cursors.empty();
}
return new IndexCursor<>(adjacentTuples, versionedMap);
}
private static class IndexCursor<T> extends IteratorBasedCursor<Tuple, T> {
private final Set<AnyVersionedMap> dependingMaps;
public IndexCursor(MutableMap<Tuple, T> map, VersionedMap<Tuple, T> versionedMap) {
super(map.entrySet().iterator());
dependingMaps = versionedMap == null ? Set.of() : Set.of(versionedMap);
}
@Override
public Set<AnyVersionedMap> getDependingMaps() {
return dependingMaps;
}
}
}
|