aboutsummaryrefslogtreecommitdiffstats
path: root/model-data/src
diff options
context:
space:
mode:
authorLibravatar OszkarSemerath <semerath@mit.bme.hu>2021-08-15 21:50:19 +0200
committerLibravatar OszkarSemerath <semerath@mit.bme.hu>2021-08-15 21:50:19 +0200
commit51c1a6ff28f26675b4a225d58f025c55911ff3a7 (patch)
tree09df2bca3f1c344acc85431676911bebb9b3f470 /model-data/src
parent:lipstick: (diff)
downloadrefinery-51c1a6ff28f26675b4a225d58f025c55911ff3a7.tar.gz
refinery-51c1a6ff28f26675b4a225d58f025c55911ff3a7.tar.zst
refinery-51c1a6ff28f26675b4a225d58f025c55911ff3a7.zip
Initial commit of query integration, adapting the work of Attila Ficsor
Co-authored-by: Ficsor Attila <ficsorattila96@gmail.com
Diffstat (limited to 'model-data/src')
-rw-r--r--model-data/src/main/java/org/eclipse/viatra/solver/data/query/RelationView.java90
-rw-r--r--model-data/src/main/java/org/eclipse/viatra/solver/data/query/RelationalScope.java31
-rw-r--r--model-data/src/main/java/org/eclipse/viatra/solver/data/query/internal/DummyBaseIndexer.java59
-rw-r--r--model-data/src/main/java/org/eclipse/viatra/solver/data/query/internal/RelationUpdateListener.java51
-rw-r--r--model-data/src/main/java/org/eclipse/viatra/solver/data/query/internal/RelationUpdateListenerEntry.java62
-rw-r--r--model-data/src/main/java/org/eclipse/viatra/solver/data/query/internal/RelationViewKey.java59
-rw-r--r--model-data/src/main/java/org/eclipse/viatra/solver/data/query/internal/RelationalEngineContext.java31
-rw-r--r--model-data/src/main/java/org/eclipse/viatra/solver/data/query/internal/RelationalQueryMetaContext.java56
-rw-r--r--model-data/src/main/java/org/eclipse/viatra/solver/data/query/internal/RelationalRuntimeContext.java183
-rw-r--r--model-data/src/main/java/org/eclipse/viatra/solver/data/query/relationView/FilteredRelationView.java35
-rw-r--r--model-data/src/main/java/org/eclipse/viatra/solver/data/query/relationView/FunctionalRelationView.java45
-rw-r--r--model-data/src/main/java/org/eclipse/viatra/solver/data/query/relationView/RelationView.java43
12 files changed, 655 insertions, 90 deletions
diff --git a/model-data/src/main/java/org/eclipse/viatra/solver/data/query/RelationView.java b/model-data/src/main/java/org/eclipse/viatra/solver/data/query/RelationView.java
deleted file mode 100644
index c52b9ff0..00000000
--- a/model-data/src/main/java/org/eclipse/viatra/solver/data/query/RelationView.java
+++ /dev/null
@@ -1,90 +0,0 @@
1package org.eclipse.viatra.solver.data.query;
2
3import java.util.function.BiFunction;
4import java.util.function.BiPredicate;
5
6import org.eclipse.viatra.solver.data.map.CursorAsIterator;
7import org.eclipse.viatra.solver.data.model.Model;
8import org.eclipse.viatra.solver.data.model.Tuple;
9import org.eclipse.viatra.solver.data.model.representation.RelationRepresentation;
10
11/**
12 * Represents a view of a {@link RelationRepresentation} that can be queried.
13 * @author Oszkar Semerath
14 *
15 * @param <D>
16 */
17public class RelationView<D>{
18 protected final Model model;
19 protected final RelationRepresentation<D> representation;
20 protected final BiPredicate<Tuple, D> filter;
21 protected final BiFunction<Tuple,D,Object[]> mapping;
22
23 protected RelationView(Model model, RelationRepresentation<D> representation, BiPredicate<Tuple,D> filter, BiFunction<Tuple,D,Object[]> mapping) {
24 this.model = model;
25 this.representation = representation;
26 this.filter = filter;
27 this.mapping = mapping;
28 checkRepresentation(model, representation);
29 }
30
31 protected RelationView(Model model, RelationRepresentation<D> representation, BiPredicate<Tuple,D> filter) {
32 this.model = model;
33 this.representation = representation;
34 this.filter = filter;
35 this.mapping = ((k,v)->toTuple1Array(k));
36 checkRepresentation(model, representation);
37 }
38 protected RelationView(Model model, RelationRepresentation<D> representation, BiFunction<Tuple,D,Object[]> mapping) {
39 this.model = model;
40 this.representation = representation;
41 this.filter = ((k,v)->true);
42 this.mapping = mapping;
43 checkRepresentation(model, representation);
44 }
45 protected RelationView(Model model, RelationRepresentation<D> representation) {
46 this.model = model;
47 this.representation = representation;
48 this.filter = ((k,v)->true);
49 this.mapping = (RelationView::toTuple1ArrayPlusValue);
50 checkRepresentation(model, representation);
51 }
52
53 private void checkRepresentation(Model model, RelationRepresentation<D> representation) {
54 if(!model.getDataRepresentations().contains(representation)) {
55 throw new IllegalArgumentException("Selected model does not contain representation " + representation + "!");
56 }
57 }
58
59 public Model getModel() {
60 return model;
61 }
62 public RelationRepresentation<D> getRepresentation() {
63 return representation;
64 }
65
66 public boolean get(Tuple t) {
67 D value = model.get(representation, t);
68 return value != representation.getDefaultValue() && filter.test(t,value);
69 }
70
71 public Iterable<Object[]> getAll() {
72 return (()->new CursorAsIterator<>(model.getAll(representation), mapping, filter));
73 }
74
75 public static Object[] toTuple1Array(Tuple t) {
76 Object[] result = new Object[t.getSize()];
77 for(int i = 0; i<t.getSize(); i++) {
78 result[i] = t.get(i);
79 }
80 return result;
81 }
82 public static <D> Object[] toTuple1ArrayPlusValue(Tuple t, D value) {
83 Object[] result = new Object[t.getSize()+1];
84 for(int i = 0; i<t.getSize(); i++) {
85 result[i] = t.get(i);
86 }
87 result[t.getSize()] = value;
88 return result;
89 }
90}
diff --git a/model-data/src/main/java/org/eclipse/viatra/solver/data/query/RelationalScope.java b/model-data/src/main/java/org/eclipse/viatra/solver/data/query/RelationalScope.java
new file mode 100644
index 00000000..66d55885
--- /dev/null
+++ b/model-data/src/main/java/org/eclipse/viatra/solver/data/query/RelationalScope.java
@@ -0,0 +1,31 @@
1package org.eclipse.viatra.solver.data.query;
2
3import java.util.Set;
4
5import org.apache.log4j.Logger;
6import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine;
7import org.eclipse.viatra.query.runtime.api.scope.IEngineContext;
8import org.eclipse.viatra.query.runtime.api.scope.IIndexingErrorListener;
9import org.eclipse.viatra.query.runtime.api.scope.QueryScope;
10import org.eclipse.viatra.solver.data.model.Tuple;
11import org.eclipse.viatra.solver.data.query.internal.RelationUpdateListener;
12import org.eclipse.viatra.solver.data.query.internal.RelationalEngineContext;
13import org.eclipse.viatra.solver.data.query.relationView.RelationView;
14
15public class RelationalScope extends QueryScope{
16 private final RelationUpdateListener updateListener;
17
18 public RelationalScope(Set<RelationView<?>> relationViews) {
19 updateListener = new RelationUpdateListener(relationViews);
20 }
21
22 public <D> void processUpdate(RelationView<D> relationView, Tuple key, D oldValue, D newValue) {
23 updateListener.processChange(relationView, key, oldValue, newValue);
24 }
25
26 @Override
27 protected IEngineContext createEngineContext(ViatraQueryEngine engine, IIndexingErrorListener errorListener,
28 Logger logger) {
29 return new RelationalEngineContext(this.updateListener);
30 }
31}
diff --git a/model-data/src/main/java/org/eclipse/viatra/solver/data/query/internal/DummyBaseIndexer.java b/model-data/src/main/java/org/eclipse/viatra/solver/data/query/internal/DummyBaseIndexer.java
new file mode 100644
index 00000000..042ec3dc
--- /dev/null
+++ b/model-data/src/main/java/org/eclipse/viatra/solver/data/query/internal/DummyBaseIndexer.java
@@ -0,0 +1,59 @@
1package org.eclipse.viatra.solver.data.query.internal;
2
3import java.lang.reflect.InvocationTargetException;
4import java.util.concurrent.Callable;
5
6import org.eclipse.viatra.query.runtime.api.scope.IBaseIndex;
7import org.eclipse.viatra.query.runtime.api.scope.IIndexingErrorListener;
8import org.eclipse.viatra.query.runtime.api.scope.IInstanceObserver;
9import org.eclipse.viatra.query.runtime.api.scope.ViatraBaseIndexChangeListener;
10
11/**
12 * copied from org.eclipse.viatra.query.runtime.tabular.TabularEngineContext;
13 */
14public class DummyBaseIndexer implements IBaseIndex{
15
16 @Override
17 public <V> V coalesceTraversals(Callable<V> callable) throws InvocationTargetException {
18 try {
19 return callable.call();
20 } catch (Exception e) {
21 throw new InvocationTargetException(e);
22 }
23 }
24
25 @Override
26 public void addBaseIndexChangeListener(ViatraBaseIndexChangeListener listener) {
27 // no notification support
28 }
29
30 @Override
31 public void removeBaseIndexChangeListener(ViatraBaseIndexChangeListener listener) {
32 // no notification support
33 }
34
35 @Override
36 public void resampleDerivedFeatures() {
37 throw new UnsupportedOperationException();
38 }
39
40 @Override
41 public boolean addIndexingErrorListener(IIndexingErrorListener listener) {
42 return true;
43 }
44
45 @Override
46 public boolean removeIndexingErrorListener(IIndexingErrorListener listener) {
47 return true;
48 }
49
50 @Override
51 public boolean addInstanceObserver(IInstanceObserver observer, Object observedObject) {
52 return true;
53 }
54
55 @Override
56 public boolean removeInstanceObserver(IInstanceObserver observer, Object observedObject) {
57 return true;
58 }
59}
diff --git a/model-data/src/main/java/org/eclipse/viatra/solver/data/query/internal/RelationUpdateListener.java b/model-data/src/main/java/org/eclipse/viatra/solver/data/query/internal/RelationUpdateListener.java
new file mode 100644
index 00000000..b7d3b866
--- /dev/null
+++ b/model-data/src/main/java/org/eclipse/viatra/solver/data/query/internal/RelationUpdateListener.java
@@ -0,0 +1,51 @@
1package org.eclipse.viatra.solver.data.query.internal;
2
3import java.util.HashMap;
4import java.util.HashSet;
5import java.util.Map;
6import java.util.Set;
7
8import org.eclipse.viatra.query.runtime.matchers.context.IQueryRuntimeContextListener;
9import org.eclipse.viatra.query.runtime.matchers.tuple.ITuple;
10import org.eclipse.viatra.solver.data.model.Tuple;
11import org.eclipse.viatra.solver.data.query.relationView.RelationView;
12
13public class RelationUpdateListener {
14 private final Map<RelationView<?>,Set<RelationUpdateListenerEntry<?>>> view2Listeners;
15
16 public RelationUpdateListener(Set<RelationView<?>> relationViews) {
17 view2Listeners = new HashMap<>();
18 for(RelationView<?> relationView : relationViews) {
19 view2Listeners.put(relationView, new HashSet<>());
20 }
21 }
22 public boolean containsRelationalView(RelationViewKey<?> relationalKey) {
23 RelationView<?> relationView = relationalKey.getWrappedKey();
24 return view2Listeners.containsKey(relationView);
25 }
26 public void addListener(RelationViewKey<?> relationalKey, ITuple seed, IQueryRuntimeContextListener listener) {
27 RelationView<?> relationView = relationalKey.getWrappedKey();
28 if(view2Listeners.containsKey(relationView)) {
29 RelationUpdateListenerEntry<?> entry = new RelationUpdateListenerEntry<>(relationalKey, seed, listener);
30 view2Listeners.get(relationView).add(entry);
31 } else throw new IllegalArgumentException();
32 }
33 public void removeListener(RelationViewKey<?> relationalKey, ITuple seed, IQueryRuntimeContextListener listener) {
34 RelationView<?> relationView = relationalKey.getWrappedKey();
35 if(view2Listeners.containsKey(relationView)) {
36 RelationUpdateListenerEntry<?> entry = new RelationUpdateListenerEntry<>(relationalKey, seed, listener);
37 view2Listeners.get(relationView).remove(entry);
38 } else throw new IllegalArgumentException();
39 }
40
41 public <D> void processChange(RelationView<D> relationView, Tuple tuple, D oldValue, D newValue) {
42 Set<RelationUpdateListenerEntry<?>> listeners = view2Listeners.get(relationView);
43 if(listeners != null) {
44 for(RelationUpdateListenerEntry<?> listener : listeners) {
45 @SuppressWarnings("unchecked")
46 RelationUpdateListenerEntry<D> typeCorrectListener = (RelationUpdateListenerEntry<D>) listener;
47 typeCorrectListener.processChange(tuple, oldValue, newValue);
48 }
49 } else throw new IllegalArgumentException("View was not indexed in constructor "+relationView);
50 }
51}
diff --git a/model-data/src/main/java/org/eclipse/viatra/solver/data/query/internal/RelationUpdateListenerEntry.java b/model-data/src/main/java/org/eclipse/viatra/solver/data/query/internal/RelationUpdateListenerEntry.java
new file mode 100644
index 00000000..def02aa5
--- /dev/null
+++ b/model-data/src/main/java/org/eclipse/viatra/solver/data/query/internal/RelationUpdateListenerEntry.java
@@ -0,0 +1,62 @@
1package org.eclipse.viatra.solver.data.query.internal;
2
3import java.util.Arrays;
4import java.util.Objects;
5
6import org.eclipse.viatra.query.runtime.matchers.context.IQueryRuntimeContextListener;
7import org.eclipse.viatra.query.runtime.matchers.tuple.ITuple;
8import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples;
9import org.eclipse.viatra.solver.data.model.Tuple;
10
11public class RelationUpdateListenerEntry<D> {
12 final RelationViewKey<D> key;
13 final ITuple filter;
14 final IQueryRuntimeContextListener listener;
15
16 public RelationUpdateListenerEntry(RelationViewKey<D> key, ITuple filter, IQueryRuntimeContextListener listener) {
17 super();
18 this.key = key;
19 this.filter = filter;
20 this.listener = listener;
21 }
22
23 public void processChange(Tuple tuple, D oldValue, D newValue) {
24 Object[] oldTuple = isMatching(key.getWrappedKey().transform(tuple, oldValue), filter);
25 Object[] newTuple = isMatching(key.getWrappedKey().transform(tuple, newValue), filter);
26
27 if(!Arrays.equals(oldTuple, newTuple)) {
28 if(oldTuple != null) {
29 listener.update(key, Tuples.flatTupleOf(oldTuple), false);
30 }
31 if(newTuple != null) {
32 listener.update(key, Tuples.flatTupleOf(newTuple), true);
33 }
34 }
35 }
36
37 private Object[] isMatching(Object[] tuple, ITuple filter) {
38 for(int i = 0; i<filter.getSize(); i++) {
39 final Object filterObject = filter.get(i);
40 if(filterObject != null && !filterObject.equals(tuple[i])) {
41 return null;
42 }
43 }
44 return tuple;
45 }
46
47 @Override
48 public int hashCode() {
49 return Objects.hash(filter, key, listener);
50 }
51
52 @Override
53 public boolean equals(Object obj) {
54 if (this == obj)
55 return true;
56 if (!(obj instanceof RelationUpdateListenerEntry))
57 return false;
58 RelationUpdateListenerEntry<?> other = (RelationUpdateListenerEntry<?>) obj;
59 return Objects.equals(filter, other.filter) && Objects.equals(key, other.key)
60 && Objects.equals(listener, other.listener);
61 }
62}
diff --git a/model-data/src/main/java/org/eclipse/viatra/solver/data/query/internal/RelationViewKey.java b/model-data/src/main/java/org/eclipse/viatra/solver/data/query/internal/RelationViewKey.java
new file mode 100644
index 00000000..f73ddd25
--- /dev/null
+++ b/model-data/src/main/java/org/eclipse/viatra/solver/data/query/internal/RelationViewKey.java
@@ -0,0 +1,59 @@
1package org.eclipse.viatra.solver.data.query.internal;
2
3import java.util.Objects;
4import java.util.UUID;
5
6import org.eclipse.viatra.query.runtime.matchers.context.common.BaseInputKeyWrapper;
7import org.eclipse.viatra.solver.data.query.relationView.RelationView;
8
9public class RelationViewKey<D> extends BaseInputKeyWrapper<RelationView<D>>{
10 private final String uniqueName;
11
12
13 public RelationViewKey(RelationView<D> wrappedKey) {
14 super(wrappedKey);
15 this.uniqueName = wrappedKey.getRepresentation().getName() + "-"+UUID.randomUUID();
16 }
17
18 @Override
19 public String getPrettyPrintableName() {
20 return wrappedKey.getRepresentation().getName();
21 }
22
23 @Override
24 public String getStringID() {
25 return uniqueName;
26 }
27
28 @Override
29 public int getArity() {
30 return wrappedKey.getRepresentation().getSymbol().getArity();
31 }
32
33 @Override
34 public boolean isEnumerable() {
35 return true;
36 }
37
38 @Override
39 public int hashCode() {
40 final int prime = 31;
41 int result = super.hashCode();
42 result = prime * result + Objects.hash(uniqueName);
43 return result;
44 }
45
46 @Override
47 public boolean equals(Object obj) {
48 if (this == obj)
49 return true;
50 if (!super.equals(obj))
51 return false;
52 if (!(obj instanceof RelationViewKey))
53 return false;
54 RelationViewKey<?> other = (RelationViewKey<?>) obj;
55 return Objects.equals(uniqueName, other.uniqueName);
56 }
57
58
59}
diff --git a/model-data/src/main/java/org/eclipse/viatra/solver/data/query/internal/RelationalEngineContext.java b/model-data/src/main/java/org/eclipse/viatra/solver/data/query/internal/RelationalEngineContext.java
new file mode 100644
index 00000000..c46da1bb
--- /dev/null
+++ b/model-data/src/main/java/org/eclipse/viatra/solver/data/query/internal/RelationalEngineContext.java
@@ -0,0 +1,31 @@
1package org.eclipse.viatra.solver.data.query.internal;
2
3import org.eclipse.viatra.query.runtime.api.scope.IBaseIndex;
4import org.eclipse.viatra.query.runtime.api.scope.IEngineContext;
5import org.eclipse.viatra.query.runtime.matchers.context.IQueryRuntimeContext;
6
7public class RelationalEngineContext implements IEngineContext{
8 private final IBaseIndex baseIndex = new DummyBaseIndexer();
9 private final RelationalRuntimeContext runtimeContext;
10
11
12 public RelationalEngineContext(RelationUpdateListener updateListener) {
13 runtimeContext = new RelationalRuntimeContext(updateListener);
14 }
15
16 @Override
17 public IBaseIndex getBaseIndex() {
18 return this.baseIndex;
19 }
20
21 @Override
22 public void dispose() {
23 //lifecycle not controlled by engine
24 }
25
26 @Override
27 public IQueryRuntimeContext getQueryRuntimeContext() {
28 return runtimeContext;
29 }
30
31}
diff --git a/model-data/src/main/java/org/eclipse/viatra/solver/data/query/internal/RelationalQueryMetaContext.java b/model-data/src/main/java/org/eclipse/viatra/solver/data/query/internal/RelationalQueryMetaContext.java
new file mode 100644
index 00000000..457ed6fd
--- /dev/null
+++ b/model-data/src/main/java/org/eclipse/viatra/solver/data/query/internal/RelationalQueryMetaContext.java
@@ -0,0 +1,56 @@
1package org.eclipse.viatra.solver.data.query.internal;
2
3import java.util.Collection;
4import java.util.Collections;
5import java.util.HashMap;
6import java.util.HashSet;
7import java.util.Map;
8import java.util.Set;
9
10import org.eclipse.viatra.query.runtime.matchers.context.AbstractQueryMetaContext;
11import org.eclipse.viatra.query.runtime.matchers.context.IInputKey;
12import org.eclipse.viatra.query.runtime.matchers.context.InputKeyImplication;
13
14/**
15 * The meta context information for String scopes.
16 */
17public final class RelationalQueryMetaContext extends AbstractQueryMetaContext {
18
19 @Override
20 public boolean isEnumerable(IInputKey key) {
21 ensureValidKey(key);
22 return key.isEnumerable();
23 }
24
25 @Override
26 public boolean isStateless(IInputKey key) {
27 ensureValidKey(key);
28 return key instanceof RelationViewKey<?>;
29 }
30
31 @Override
32 public Collection<InputKeyImplication> getImplications(IInputKey implyingKey) {
33 ensureValidKey(implyingKey);
34 return new HashSet<InputKeyImplication>();
35 }
36
37 @Override
38 public Map<Set<Integer>, Set<Integer>> getFunctionalDependencies(IInputKey key) {
39 ensureValidKey(key);
40 if (key instanceof RelationViewKey) {
41 return new HashMap<Set<Integer>, Set<Integer>>();
42 } else {
43 return Collections.emptyMap();
44 }
45 }
46
47 public void ensureValidKey(IInputKey key) {
48 if (! (key instanceof RelationViewKey<?>))
49 illegalInputKey(key);
50 }
51
52 public void illegalInputKey(IInputKey key) {
53 throw new IllegalArgumentException("The input key " + key + " is not a valid input key.");
54 }
55
56}
diff --git a/model-data/src/main/java/org/eclipse/viatra/solver/data/query/internal/RelationalRuntimeContext.java b/model-data/src/main/java/org/eclipse/viatra/solver/data/query/internal/RelationalRuntimeContext.java
new file mode 100644
index 00000000..8f6fb8dd
--- /dev/null
+++ b/model-data/src/main/java/org/eclipse/viatra/solver/data/query/internal/RelationalRuntimeContext.java
@@ -0,0 +1,183 @@
1package org.eclipse.viatra.solver.data.query.internal;
2
3import static org.eclipse.viatra.solver.data.util.CollectionsUtil.filter;
4import static org.eclipse.viatra.solver.data.util.CollectionsUtil.map;
5
6import java.lang.reflect.InvocationTargetException;
7import java.util.Iterator;
8import java.util.Optional;
9import java.util.concurrent.Callable;
10
11import org.eclipse.viatra.query.runtime.base.core.NavigationHelperImpl;
12import org.eclipse.viatra.query.runtime.matchers.context.IInputKey;
13import org.eclipse.viatra.query.runtime.matchers.context.IQueryMetaContext;
14import org.eclipse.viatra.query.runtime.matchers.context.IQueryRuntimeContext;
15import org.eclipse.viatra.query.runtime.matchers.context.IQueryRuntimeContextListener;
16import org.eclipse.viatra.query.runtime.matchers.context.IndexingService;
17import org.eclipse.viatra.query.runtime.matchers.tuple.ITuple;
18import org.eclipse.viatra.query.runtime.matchers.tuple.Tuple;
19import org.eclipse.viatra.query.runtime.matchers.tuple.TupleMask;
20import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples;
21import org.eclipse.viatra.query.runtime.matchers.util.Accuracy;
22
23public class RelationalRuntimeContext implements IQueryRuntimeContext {
24 private final RelationalQueryMetaContext metaContext = new RelationalQueryMetaContext();
25 private final RelationUpdateListener relationUpdateListener;
26
27 public RelationalRuntimeContext(RelationUpdateListener relationUpdateListener) {
28 this.relationUpdateListener = relationUpdateListener;
29 }
30
31 @Override
32 public IQueryMetaContext getMetaContext() {
33 return metaContext;
34 }
35
36 //
37 /**
38 * TODO: check {@link NavigationHelperImpl#coalesceTraversals(Callable)}
39 */
40 @Override
41 public <V> V coalesceTraversals(Callable<V> callable) throws InvocationTargetException {
42 try {
43 return callable.call();
44 } catch (Exception e) {
45 throw new InvocationTargetException(e);
46 }
47 }
48
49 @Override
50 public boolean isCoalescing() {
51 return true;
52 }
53
54 @Override
55 public boolean isIndexed(IInputKey key, IndexingService service) {
56 if(key instanceof RelationViewKey<?>) {
57 RelationViewKey<?> relationalKey = (RelationViewKey<?>) key;
58 return this.relationUpdateListener.containsRelationalView(relationalKey);
59 } else {
60 return false;
61 }
62 }
63
64 @Override
65 public void ensureIndexed(IInputKey key, IndexingService service) {
66 if(!isIndexed(key, service)) {
67 throw new IllegalStateException("Engine tries to index a new key " +key);
68 }
69 }
70
71 RelationViewKey<?> checkKey(IInputKey key) {
72 if(key instanceof RelationViewKey) {
73 RelationViewKey<?> relationViewKey = (RelationViewKey<?>) key;
74 if(relationUpdateListener.containsRelationalView(relationViewKey)) {
75 return relationViewKey;
76 } else {
77 throw new IllegalStateException("Query is asking for non-indexed key");
78 }
79 } else {
80 throw new IllegalStateException("Query is asking for non-relational key");
81 }
82 }
83
84 @Override
85 public int countTuples(IInputKey key, TupleMask seedMask, ITuple seed) {
86 RelationViewKey<?> relationalViewKey = checkKey(key);
87 Iterable<Object[]> allObjects = relationalViewKey.getWrappedKey().getAll();
88 Iterable<Object[]> filteredBySeed = filter(allObjects,objectArray -> isMatching(objectArray,seedMask,seed));
89 Iterator<Object[]> iterator = filteredBySeed.iterator();
90 int result = 0;
91 while(iterator.hasNext()) {
92 iterator.next();
93 result++;
94 }
95 return result;
96 }
97
98 @Override
99 public Optional<Long> estimateCardinality(IInputKey key, TupleMask groupMask, Accuracy requiredAccuracy) {
100 return Optional.empty();
101 }
102
103 @Override
104 public Iterable<Tuple> enumerateTuples(IInputKey key, TupleMask seedMask, ITuple seed) {
105 RelationViewKey<?> relationalViewKey = checkKey(key);
106 Iterable<Object[]> allObjects = relationalViewKey.getWrappedKey().getAll();
107 Iterable<Object[]> filteredBySeed = filter(allObjects,objectArray -> isMatching(objectArray,seedMask,seed));
108 return map(filteredBySeed,Tuples::flatTupleOf);
109 }
110
111 private boolean isMatching(Object[] tuple, TupleMask seedMask, ITuple seed) {
112 for(int i=0; i<seedMask.indices.length; i++) {
113 final Object seedElement = seed.get(i);
114 final Object tupleElement = tuple[seedMask.indices[i]];
115 if(!tupleElement.equals(seedElement)) {
116 return false;
117 }
118 }
119 return true;
120 }
121// private Object[] toObjectMask(RelationViewKey<?> relationalViewKey, TupleMask seedMask, ITuple seed) {
122// final int arity = relationalViewKey.getArity();
123// Object[] result = new Object[arity];
124// for(int i = 0; i<seedMask.indices.length; i++) {
125// result[seedMask.indices[i]] = seed.get(i);
126// }
127// return result;
128// }
129
130 @Override
131 public Iterable<? extends Object> enumerateValues(IInputKey key, TupleMask seedMask, ITuple seed) {
132 return enumerateTuples(key, seedMask, seed);
133 }
134
135 @Override
136 public boolean containsTuple(IInputKey key, ITuple seed) {
137 RelationViewKey<?> relationalViewKey = checkKey(key);
138 return relationalViewKey.getWrappedKey().get(seed.getElements());
139 }
140
141 @Override
142 public void addUpdateListener(IInputKey key, Tuple seed, IQueryRuntimeContextListener listener) {
143 RelationViewKey<?> relationalKey = checkKey(key);
144 this.relationUpdateListener.addListener(relationalKey, seed, listener);
145
146 }
147
148 @Override
149 public void removeUpdateListener(IInputKey key, Tuple seed, IQueryRuntimeContextListener listener) {
150 RelationViewKey<?> relationalKey = checkKey(key);
151 this.relationUpdateListener.removeListener(relationalKey, seed, listener);
152 }
153
154 @Override
155 public Object wrapElement(Object externalElement) {
156 return externalElement;
157 }
158
159 @Override
160 public Object unwrapElement(Object internalElement) {
161 return internalElement;
162 }
163
164 @Override
165 public Tuple wrapTuple(Tuple externalElements) {
166 return externalElements;
167 }
168
169 @Override
170 public Tuple unwrapTuple(Tuple internalElements) {
171 return internalElements;
172 }
173
174 @Override
175 public void ensureWildcardIndexing(IndexingService service) {
176 throw new UnsupportedOperationException();
177 }
178
179 @Override
180 public void executeAfterTraversal(Runnable runnable) throws InvocationTargetException {
181 runnable.run();
182 }
183}
diff --git a/model-data/src/main/java/org/eclipse/viatra/solver/data/query/relationView/FilteredRelationView.java b/model-data/src/main/java/org/eclipse/viatra/solver/data/query/relationView/FilteredRelationView.java
new file mode 100644
index 00000000..b5660041
--- /dev/null
+++ b/model-data/src/main/java/org/eclipse/viatra/solver/data/query/relationView/FilteredRelationView.java
@@ -0,0 +1,35 @@
1package org.eclipse.viatra.solver.data.query.relationView;
2
3import org.eclipse.viatra.solver.data.model.Model;
4import org.eclipse.viatra.solver.data.model.Tuple;
5import org.eclipse.viatra.solver.data.model.Tuple.Tuple1;
6import org.eclipse.viatra.solver.data.model.representation.RelationRepresentation;
7
8public abstract class FilteredRelationView<D> extends RelationView<D>{
9
10 protected FilteredRelationView(Model model, RelationRepresentation<D> representation) {
11 super(model, representation);
12 }
13 @Override
14 protected Object[] forwardMap(Tuple key, D value) {
15 return toTuple1Array(key);
16 }
17 @Override
18 public boolean get(Object[] tuple) {
19 int[] content = new int[tuple.length];
20 for(int i = 0; i<tuple.length; i++) {
21 content[i] =((Tuple1)tuple[i]).get(0);
22 }
23 Tuple key = Tuple.of(content);
24 D value = this.model.get(representation, key);
25 return filter(key, value);
26 }
27
28 public static Object[] toTuple1Array(Tuple t) {
29 Object[] result = new Object[t.getSize()];
30 for(int i = 0; i<t.getSize(); i++) {
31 result[i] = t.get(i);
32 }
33 return result;
34 }
35}
diff --git a/model-data/src/main/java/org/eclipse/viatra/solver/data/query/relationView/FunctionalRelationView.java b/model-data/src/main/java/org/eclipse/viatra/solver/data/query/relationView/FunctionalRelationView.java
new file mode 100644
index 00000000..2cd4b05e
--- /dev/null
+++ b/model-data/src/main/java/org/eclipse/viatra/solver/data/query/relationView/FunctionalRelationView.java
@@ -0,0 +1,45 @@
1package org.eclipse.viatra.solver.data.query.relationView;
2
3import org.eclipse.viatra.solver.data.model.Model;
4import org.eclipse.viatra.solver.data.model.Tuple;
5import org.eclipse.viatra.solver.data.model.Tuple.Tuple1;
6import org.eclipse.viatra.solver.data.model.representation.RelationRepresentation;
7
8public class FunctionalRelationView<D> extends RelationView<D> {
9
10 protected FunctionalRelationView(Model model, RelationRepresentation<D> representation) {
11 super(model, representation);
12 }
13
14 @Override
15 protected boolean filter(Tuple key, D value) {
16 return true;
17 }
18
19 @Override
20 protected Object[] forwardMap(Tuple key, D value) {
21 return toTuple1ArrayPlusValue(key, value);
22 }
23
24 @Override
25 public boolean get(Object[] tuple) {
26 int[] content = new int[tuple.length-1];
27 for(int i = 0; i<tuple.length-1; i++) {
28 content[i] =((Tuple1)tuple[i]).get(0);
29 }
30 Tuple key = Tuple.of(content);
31 @SuppressWarnings("unchecked")
32 D valueInTuple = (D) tuple[tuple.length-1];
33 D valueInMap = this.model.get(representation, key);
34 return valueInTuple.equals(valueInMap);
35 }
36
37 public static <D> Object[] toTuple1ArrayPlusValue(Tuple t, D value) {
38 Object[] result = new Object[t.getSize()+1];
39 for(int i = 0; i<t.getSize(); i++) {
40 result[i] = t.get(i);
41 }
42 result[t.getSize()] = value;
43 return result;
44 }
45}
diff --git a/model-data/src/main/java/org/eclipse/viatra/solver/data/query/relationView/RelationView.java b/model-data/src/main/java/org/eclipse/viatra/solver/data/query/relationView/RelationView.java
new file mode 100644
index 00000000..876f1dcc
--- /dev/null
+++ b/model-data/src/main/java/org/eclipse/viatra/solver/data/query/relationView/RelationView.java
@@ -0,0 +1,43 @@
1package org.eclipse.viatra.solver.data.query.relationView;
2
3import org.eclipse.viatra.solver.data.map.CursorAsIterator;
4import org.eclipse.viatra.solver.data.model.Model;
5import org.eclipse.viatra.solver.data.model.Tuple;
6import org.eclipse.viatra.solver.data.model.representation.RelationRepresentation;
7
8/**
9 * Represents a view of a {@link RelationRepresentation} that can be queried.
10 * @author Oszkar Semerath
11 *
12 * @param <D>
13 */
14public abstract class RelationView<D>{
15 protected final Model model;
16 protected final RelationRepresentation<D> representation;
17
18 protected RelationView(Model model, RelationRepresentation<D> representation) {
19 this.model = model;
20 this.representation = representation;
21 }
22
23 public Model getModel() {
24 return model;
25 }
26 public RelationRepresentation<D> getRepresentation() {
27 return representation;
28 }
29
30 protected abstract boolean filter(Tuple key, D value);
31 protected abstract Object[] forwardMap(Tuple key, D value);
32 public abstract boolean get(Object[] tuple);
33
34 public Object[] transform(Tuple tuple, D value) {
35 if(filter(tuple, value)) {
36 return forwardMap(tuple, value);
37 } else return null;
38 }
39
40 public Iterable<Object[]> getAll() {
41 return (()->new CursorAsIterator<>(model.getAll(representation), (k,v)->forwardMap(k,v), (k,v)->filter(k,v)));
42 }
43}