aboutsummaryrefslogtreecommitdiffstats
path: root/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/simple/SimpleStateCoder.java
diff options
context:
space:
mode:
Diffstat (limited to 'Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/simple/SimpleStateCoder.java')
-rw-r--r--Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/simple/SimpleStateCoder.java250
1 files changed, 250 insertions, 0 deletions
diff --git a/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/simple/SimpleStateCoder.java b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/simple/SimpleStateCoder.java
new file mode 100644
index 00000000..0f0759ae
--- /dev/null
+++ b/Solvers/VIATRA-Solver/org.eclipse.viatra.dse/src/org/eclipse/viatra/dse/statecoding/simple/SimpleStateCoder.java
@@ -0,0 +1,250 @@
1/*******************************************************************************
2 * Copyright (c) 2010-2015, Andras Szabolcs Nagy and Daniel Varro
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 org.eclipse.viatra.dse.statecoding.simple;
10
11import java.util.Arrays;
12import java.util.Collection;
13import java.util.HashMap;
14import java.util.HashSet;
15import java.util.List;
16import java.util.Map;
17import java.util.Set;
18
19import org.eclipse.emf.common.notify.Notifier;
20import org.eclipse.emf.ecore.EAttribute;
21import org.eclipse.emf.ecore.EClass;
22import org.eclipse.emf.ecore.EObject;
23import org.eclipse.emf.ecore.EReference;
24import org.eclipse.emf.ecore.EStructuralFeature;
25import org.eclipse.emf.ecore.EStructuralFeature.Setting;
26import org.eclipse.viatra.dse.api.DSEException;
27import org.eclipse.viatra.dse.statecode.IStateCoder;
28import org.eclipse.viatra.dse.util.EMFHelper.MetaModelElements;
29import org.eclipse.viatra.dse.util.ValueComparableEObjectStringMap;
30import org.eclipse.viatra.query.runtime.api.IPatternMatch;
31import org.eclipse.viatra.query.runtime.api.ViatraQueryEngine;
32import org.eclipse.viatra.query.runtime.base.api.FeatureListener;
33import org.eclipse.viatra.query.runtime.base.api.IndexingLevel;
34import org.eclipse.viatra.query.runtime.base.api.InstanceListener;
35import org.eclipse.viatra.query.runtime.base.api.NavigationHelper;
36import org.eclipse.viatra.query.runtime.emf.EMFBaseIndexWrapper;
37import org.eclipse.viatra.query.runtime.emf.EMFScope;
38import org.eclipse.viatra.query.runtime.exception.ViatraQueryException;
39
40/**
41 *
42 * @author Andras Szabolcs Nagy
43 *
44 */
45public class SimpleStateCoder implements IStateCoder {
46
47 private Set<EClass> classes;
48 private Set<EStructuralFeature> features;
49 private NavigationHelper navigationHelper;
50
51 private Map<EClass, Map<EObject, String>> objectCodes;
52 private int maxDepth;
53
54 private Set<EObject> changedOrNewEObjects = new HashSet<EObject>();
55 private Set<EObject> deletedClasses = new HashSet<EObject>();
56
57 public SimpleStateCoder(MetaModelElements metaModelElements) {
58 this.maxDepth = 1;
59
60 classes = metaModelElements.classes;
61 features = new HashSet<EStructuralFeature>(metaModelElements.attributes);
62 features.addAll(metaModelElements.references);
63 }
64
65 @Override
66 public void init(Notifier notifier) {
67 try {
68 EMFScope scope = new EMFScope(notifier);
69 ViatraQueryEngine queryEngine = ViatraQueryEngine.on(scope);
70 EMFBaseIndexWrapper baseIndex = (EMFBaseIndexWrapper) queryEngine.getBaseIndex();
71 navigationHelper = baseIndex.getNavigationHelper();
72 navigationHelper.registerObservedTypes(classes, null, features, IndexingLevel.FULL);
73 } catch (ViatraQueryException e) {
74 throw new DSEException(e);
75 }
76
77 objectCodes = new HashMap<EClass, Map<EObject, String>>();
78 for (EClass eClass : classes) {
79 Map<EObject, String> codes = new ValueComparableEObjectStringMap();
80
81 objectCodes.put(eClass, codes);
82
83 for (EObject eObject : navigationHelper.getDirectInstances(eClass)) {
84 codes.put(eObject, createObjectCodeWithDepth(eObject, maxDepth));
85 }
86 }
87
88 navigationHelper.addFeatureListener(features, new FeatureListener() {
89
90 @Override
91 public void featureInserted(EObject host, EStructuralFeature feature, Object value) {
92 changedOrNewEObjects.add(host);
93 }
94
95 @Override
96 public void featureDeleted(EObject host, EStructuralFeature feature, Object value) {
97 changedOrNewEObjects.add(host);
98 if (value instanceof EObject) {
99 changedOrNewEObjects.add((EObject) value);
100 }
101 }
102 });
103
104 navigationHelper.addInstanceListener(classes, new InstanceListener() {
105
106 @Override
107 public void instanceInserted(EClass clazz, EObject instance) {
108 changedOrNewEObjects.add(instance);
109 }
110
111 @Override
112 public void instanceDeleted(EClass clazz, EObject instance) {
113 deletedClasses.add(instance);
114 }
115 });
116 }
117
118 private String createObjectCodeWithDepth(EObject eObject, int depth) {
119
120 StringBuilder sb = new StringBuilder();
121
122 Collection<EAttribute> attributes = eObject.eClass().getEAllAttributes();
123 for (EAttribute eAttribute : attributes) {
124 Object value = eObject.eGet(eAttribute);
125 sb.append(value);
126 sb.append(',');
127 }
128 if (!attributes.isEmpty()) {
129 sb.deleteCharAt(sb.length() - 1);
130 }
131 if (depth > 0) {
132 sb.append('-');
133 Collection<EReference> eReferences = eObject.eClass().getEAllReferences();
134 for (EReference eReference : eReferences) {
135 Object value = eObject.eGet(eReference);
136 if (value == null) {
137 sb.append("null,");
138 } else if (value instanceof EObject) {
139 sb.append(createObjectCodeWithDepth((EObject) value, depth - 1));
140 sb.append(',');
141 } else {
142 List<EObject> referencedEObjects = (List<EObject>) value;
143 if (!referencedEObjects.isEmpty()) {
144
145 String[] codes = new String[referencedEObjects.size()];
146 int index = 0;
147 for (EObject referencedEObject : referencedEObjects) {
148 codes[index++] = createObjectCodeWithDepth(referencedEObject, depth - 1);
149 }
150 Arrays.sort(codes);
151 sb.append('(');
152 for (String code : codes) {
153 sb.append(code);
154 }
155 sb.append("),");
156 }
157 }
158 }
159 sb.deleteCharAt(sb.length() - 1);
160 }
161 return sb.toString();
162 }
163
164 @Override
165 public Object createStateCode() {
166
167 refreshObjectCodes();
168
169 StringBuilder sb = new StringBuilder();
170
171 for (EClass eClass : classes) {
172
173 Set<EObject> instances = navigationHelper.getDirectInstances(eClass);
174
175 if (!instances.isEmpty()) {
176
177 sb.append(eClass.getName());
178 sb.append(':');
179
180 String[] codesToSort = new String[instances.size()];
181 int index = 0;
182 Map<EObject, String> codes = objectCodes.get(eClass);
183 for (EObject eObject : instances) {
184 codesToSort[index++] = codes.get(eObject);
185 }
186 Arrays.sort(codesToSort);
187 for (String string : codesToSort) {
188 sb.append(string);
189 sb.append(';');
190 }
191 sb.deleteCharAt(sb.length() - 1);
192 sb.append('|');
193 }
194 }
195 if (sb.length() != 0) {
196 sb.deleteCharAt(sb.length() - 1);
197 }
198 return sb.toString();
199 }
200
201 private void refreshObjectCodes() {
202 for (EObject eObject : deletedClasses) {
203 EClass eClass = eObject.eClass();
204 objectCodes.get(eClass).remove(eObject);
205 }
206 deletedClasses.clear();
207
208 Set<EObject> objectsToRecode = new HashSet<EObject>();
209 for (EObject eObject : changedOrNewEObjects) {
210 objectsToRecode.add(eObject);
211 for (Setting setting : navigationHelper.getInverseReferences(eObject)) {
212 objectsToRecode.add(setting.getEObject());
213 }
214 }
215
216 for (EObject eObject : objectsToRecode) {
217 EClass eClass = eObject.eClass();
218 objectCodes.get(eClass).put(eObject, createObjectCodeWithDepth(eObject, maxDepth));
219 }
220 changedOrNewEObjects.clear();
221 }
222
223 @Override
224 public Object createActivationCode(IPatternMatch match) {
225
226 StringBuilder sb = new StringBuilder();
227 String[] tokens = match.specification().getFullyQualifiedName().split("\\.");
228 sb.append(tokens[tokens.length - 1]);
229 sb.append(':');
230 Object param;
231 for (int i = 0; (param = match.get(i)) != null; i++) {
232 EObject eObject = (EObject) param;
233
234 Collection<EAttribute> attributes = eObject.eClass().getEAllAttributes();
235 for (EAttribute eAttribute : attributes) {
236 Object value = eObject.eGet(eAttribute);
237 sb.append(value);
238 sb.append(',');
239 }
240 if (!attributes.isEmpty()) {
241 sb.deleteCharAt(sb.length() - 1);
242 }
243
244 sb.append('|');
245 }
246 sb.deleteCharAt(sb.length() - 1);
247 return sb.toString().intern();
248 }
249
250}