aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/viatra-runtime-matchers/src/main/java/tools/refinery/viatra/runtime/matchers/scopes/tables/DefaultIndexTable.java
diff options
context:
space:
mode:
Diffstat (limited to 'subprojects/viatra-runtime-matchers/src/main/java/tools/refinery/viatra/runtime/matchers/scopes/tables/DefaultIndexTable.java')
-rw-r--r--subprojects/viatra-runtime-matchers/src/main/java/tools/refinery/viatra/runtime/matchers/scopes/tables/DefaultIndexTable.java143
1 files changed, 143 insertions, 0 deletions
diff --git a/subprojects/viatra-runtime-matchers/src/main/java/tools/refinery/viatra/runtime/matchers/scopes/tables/DefaultIndexTable.java b/subprojects/viatra-runtime-matchers/src/main/java/tools/refinery/viatra/runtime/matchers/scopes/tables/DefaultIndexTable.java
new file mode 100644
index 00000000..39475d11
--- /dev/null
+++ b/subprojects/viatra-runtime-matchers/src/main/java/tools/refinery/viatra/runtime/matchers/scopes/tables/DefaultIndexTable.java
@@ -0,0 +1,143 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2018, Gabor Bergmann, IncQuery Labs Ltd.
3 * This program and the accompanying materials are made available under the
4 * terms of the Eclipse Public License v. 2.0 which is available at
5 * http://www.eclipse.org/legal/epl-v20.html.
6 *
7 * SPDX-License-Identifier: EPL-2.0
8 *******************************************************************************/
9package tools.refinery.viatra.runtime.matchers.scopes.tables;
10
11import java.util.Map;
12import java.util.Optional;
13import java.util.stream.Stream;
14
15import tools.refinery.viatra.runtime.matchers.context.IInputKey;
16import tools.refinery.viatra.runtime.matchers.memories.MaskedTupleMemory;
17import tools.refinery.viatra.runtime.matchers.tuple.ITuple;
18import tools.refinery.viatra.runtime.matchers.tuple.Tuple;
19import tools.refinery.viatra.runtime.matchers.tuple.TupleMask;
20import tools.refinery.viatra.runtime.matchers.util.Accuracy;
21import tools.refinery.viatra.runtime.matchers.util.CollectionsFactory;
22import tools.refinery.viatra.runtime.matchers.util.CollectionsFactory.MemoryType;
23import tools.refinery.viatra.runtime.matchers.util.Direction;
24import tools.refinery.viatra.runtime.matchers.util.IMemory;
25
26/**
27 * Demo default implementation.
28 * <p>
29 * <strong>EXPERIMENTAL</strong>. This class or interface has been added as
30 * part of a work in progress. There is no guarantee that this API will
31 * work or that it will remain the same.
32 *
33 * @since 2.0
34 * @author Gabor Bergmann
35 */
36public class DefaultIndexTable extends AbstractIndexTable implements ITableWriterGeneric {
37
38 protected IMemory<Tuple> rows = CollectionsFactory.createMultiset(); // TODO use SetMemory if unique
39 protected Map<TupleMask, MaskedTupleMemory<?>> indexMemories = CollectionsFactory.createMap();
40 private boolean unique;
41
42 /**
43 * @param unique
44 * client promises to only insert a given tuple with multiplicity one
45 */
46 public DefaultIndexTable(IInputKey inputKey, ITableContext tableContext, boolean unique) {
47 super(inputKey, tableContext);
48 this.unique = unique;
49 }
50
51 @Override
52 public void write(Direction direction, Tuple row) {
53 if (direction == Direction.INSERT) {
54 boolean changed = rows.addOne(row);
55 if (unique && !changed) {
56 String msg = String.format(
57 "Error: trying to add duplicate row %s to the unique table %s. This indicates some errors in underlying model representation.",
58 row, getInputKey().getPrettyPrintableName());
59 logError(msg);
60 }
61 if (changed) {
62 for (MaskedTupleMemory<?> indexMemory : indexMemories.values()) {
63 indexMemory.add(row);
64 }
65 if (emitNotifications) {
66 deliverChangeNotifications(row, true);
67 }
68 }
69 } else { // DELETE
70 boolean changed = rows.removeOne(row);
71 if (unique && !changed) {
72 String msg = String.format(
73 "Error: trying to remove duplicate value %s from the unique table %s. This indicates some errors in underlying model representation.",
74 row, getInputKey().getPrettyPrintableName());
75 logError(msg);
76 }
77 if (changed) {
78 for (MaskedTupleMemory<?> indexMemory : indexMemories.values()) {
79 indexMemory.remove(row);
80 }
81 if (emitNotifications) {
82 deliverChangeNotifications(row, false);
83 }
84 }
85 }
86 }
87
88 @Override
89 public boolean containsTuple(ITuple seed) {
90 return rows.distinctValues().contains(seed);
91 }
92
93 private MaskedTupleMemory<?> getIndexMemory(TupleMask seedMask) {
94 return indexMemories.computeIfAbsent(seedMask, mask -> {
95 MaskedTupleMemory<?> memory = MaskedTupleMemory.create(seedMask, MemoryType.SETS, DefaultIndexTable.this);
96 for (Tuple tuple : rows.distinctValues()) {
97 memory.add(tuple);
98 }
99 return memory;
100 });
101 }
102
103 @Override
104 public int countTuples(TupleMask seedMask, ITuple seed) {
105 switch (seedMask.getSize()) {
106 case 0: // unseeded
107 return rows.size();
108 default:
109 return getIndexMemory(seedMask).getOrEmpty(seed).size();
110 }
111 }
112
113 @Override
114 public Optional<Long> estimateProjectionSize(TupleMask groupMask, Accuracy requiredAccuracy) {
115 // always exact count
116 if (groupMask.getSize() == 0) {
117 return rows.size() == 0 ? Optional.of(0L) : Optional.of(1L);
118 } else if (groupMask.getSize() == this.emptyTuple.getSize()) {
119 return Optional.of((long) rows.size());
120 } else {
121 return Optional.of((long)getIndexMemory(groupMask).getKeysetSize());
122 }
123 }
124
125 @Override
126 public Iterable<Tuple> enumerateTuples(TupleMask seedMask, ITuple seed) {
127 return getIndexMemory(seedMask).getOrEmpty(seed);
128 }
129
130 @Override
131 public Stream<? extends Tuple> streamTuples(TupleMask seedMask, ITuple seed) {
132 return getIndexMemory(seedMask).getOrEmpty(seed).stream();
133 }
134
135 @Override
136 public Stream<? extends Object> streamValues(TupleMask seedMask, ITuple seed) {
137 // we assume there is a single omitted index in the mask
138 int queriedColumn = seedMask.getFirstOmittedIndex().getAsInt();
139 return getIndexMemory(seedMask).getOrEmpty(seed).stream()
140 .map(row2 -> row2.get(queriedColumn));
141 }
142
143}