diff options
Diffstat (limited to 'subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/operations/generic/GenericTypeExtend.java')
-rw-r--r-- | subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/operations/generic/GenericTypeExtend.java | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/operations/generic/GenericTypeExtend.java b/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/operations/generic/GenericTypeExtend.java new file mode 100644 index 00000000..dfc3e9ad --- /dev/null +++ b/subprojects/viatra-runtime-localsearch/src/main/java/tools/refinery/viatra/runtime/localsearch/operations/generic/GenericTypeExtend.java | |||
@@ -0,0 +1,145 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2010-2017, Zoltan Ujhelyi, 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 | *******************************************************************************/ | ||
9 | package tools.refinery.viatra.runtime.localsearch.operations.generic; | ||
10 | |||
11 | import java.util.ArrayList; | ||
12 | import java.util.Collections; | ||
13 | import java.util.Iterator; | ||
14 | import java.util.List; | ||
15 | import java.util.Objects; | ||
16 | import java.util.Set; | ||
17 | import java.util.function.Function; | ||
18 | import java.util.stream.Collectors; | ||
19 | |||
20 | import tools.refinery.viatra.runtime.localsearch.MatchingFrame; | ||
21 | import tools.refinery.viatra.runtime.localsearch.matcher.ISearchContext; | ||
22 | import tools.refinery.viatra.runtime.localsearch.operations.ExtendOperationExecutor; | ||
23 | import tools.refinery.viatra.runtime.localsearch.operations.IIteratingSearchOperation; | ||
24 | import tools.refinery.viatra.runtime.localsearch.operations.ISearchOperation; | ||
25 | import tools.refinery.viatra.runtime.matchers.context.IInputKey; | ||
26 | import tools.refinery.viatra.runtime.matchers.tuple.Tuple; | ||
27 | import tools.refinery.viatra.runtime.matchers.tuple.TupleMask; | ||
28 | import tools.refinery.viatra.runtime.matchers.tuple.VolatileMaskedTuple; | ||
29 | import tools.refinery.viatra.runtime.matchers.util.Preconditions; | ||
30 | |||
31 | /** | ||
32 | * @author Zoltan Ujhelyi | ||
33 | * @since 1.7 | ||
34 | * @noextend This class is not intended to be subclassed by clients. | ||
35 | */ | ||
36 | public class GenericTypeExtend implements IIteratingSearchOperation { | ||
37 | |||
38 | private class Executor extends ExtendOperationExecutor<Tuple> { | ||
39 | private final VolatileMaskedTuple maskedTuple; | ||
40 | |||
41 | public Executor() { | ||
42 | this.maskedTuple = new VolatileMaskedTuple(callMask); | ||
43 | } | ||
44 | |||
45 | @Override | ||
46 | protected Iterator<? extends Tuple> getIterator(MatchingFrame frame, ISearchContext context) { | ||
47 | maskedTuple.updateTuple(frame); | ||
48 | return context.getRuntimeContext().enumerateTuples(type, indexerMask, maskedTuple).iterator(); | ||
49 | } | ||
50 | |||
51 | @Override | ||
52 | protected boolean fillInValue(Tuple newTuple, MatchingFrame frame, ISearchContext context) { | ||
53 | for (Integer position : unboundVariableIndices) { | ||
54 | frame.setValue(position, null); | ||
55 | } | ||
56 | for (int i = 0; i < positions.length; i++) { | ||
57 | Object newValue = newTuple.get(i); | ||
58 | Object oldValue = frame.getValue(positions[i]); | ||
59 | if (oldValue != null && !Objects.equals(oldValue, newValue)) { | ||
60 | // If positions tuple maps more than one values for the same element (e.g. loop), it means that | ||
61 | // these arguments are to unified by the caller. In this case if the callee assigns different values | ||
62 | // the frame shall be considered a failed match | ||
63 | return false; | ||
64 | } | ||
65 | frame.setValue(positions[i], newValue); | ||
66 | } | ||
67 | return true; | ||
68 | } | ||
69 | |||
70 | @Override | ||
71 | protected void cleanup(MatchingFrame frame, ISearchContext context) { | ||
72 | for (Integer position : unboundVariableIndices) { | ||
73 | frame.setValue(position, null); | ||
74 | } | ||
75 | } | ||
76 | |||
77 | @Override | ||
78 | public ISearchOperation getOperation() { | ||
79 | return GenericTypeExtend.this; | ||
80 | } | ||
81 | } | ||
82 | |||
83 | private final IInputKey type; | ||
84 | private final int[] positions; | ||
85 | private final List<Integer> positionList; | ||
86 | private final Set<Integer> unboundVariableIndices; | ||
87 | private final TupleMask indexerMask; | ||
88 | private final TupleMask callMask; | ||
89 | |||
90 | /** | ||
91 | * | ||
92 | * @param type | ||
93 | * the type to execute the extend operation on | ||
94 | * @param positions | ||
95 | * the parameter positions that represent the variables of the input key | ||
96 | * @param unboundVariableIndices | ||
97 | * the set of positions that are bound at the start of the operation | ||
98 | */ | ||
99 | public GenericTypeExtend(IInputKey type, int[] positions, TupleMask callMask, TupleMask indexerMask, Set<Integer> unboundVariableIndices) { | ||
100 | Preconditions.checkArgument(positions.length == type.getArity(), | ||
101 | "The type %s requires %d parameters, but %d positions are provided", type.getPrettyPrintableName(), | ||
102 | type.getArity(), positions.length); | ||
103 | List<Integer> modifiablePositionList = new ArrayList<>(); | ||
104 | for (int position : positions) { | ||
105 | modifiablePositionList.add(position); | ||
106 | } | ||
107 | this.positionList = Collections.unmodifiableList(modifiablePositionList); | ||
108 | this.positions = positions; | ||
109 | this.type = type; | ||
110 | |||
111 | this.unboundVariableIndices = unboundVariableIndices; | ||
112 | this.indexerMask = indexerMask; | ||
113 | this.callMask = callMask; | ||
114 | } | ||
115 | |||
116 | @Override | ||
117 | public IInputKey getIteratedInputKey() { | ||
118 | return type; | ||
119 | } | ||
120 | |||
121 | @Override | ||
122 | public ISearchOperationExecutor createExecutor() { | ||
123 | return new Executor(); | ||
124 | } | ||
125 | |||
126 | @Override | ||
127 | public List<Integer> getVariablePositions() { | ||
128 | return positionList; | ||
129 | } | ||
130 | |||
131 | @Override | ||
132 | public String toString() { | ||
133 | return toString(Object::toString); | ||
134 | } | ||
135 | |||
136 | @Override | ||
137 | public String toString(Function<Integer, String> variableMapping) { | ||
138 | return "extend " + type.getPrettyPrintableName() + "(" | ||
139 | + positionList.stream() | ||
140 | .map(input -> String.format("%s%s", unboundVariableIndices.contains(input) ? "-" : "+", variableMapping.apply(input))) | ||
141 | .collect(Collectors.joining(", ")) | ||
142 | + ")"; | ||
143 | } | ||
144 | |||
145 | } | ||