aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/SemanticsWorker.java
blob: 512c2778eee6802463fe14d335571a1371caa0a1 (plain) (blame)
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
103
104
105
106
107
108
109
110
111
112
113
/*
 * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/>
 *
 * SPDX-License-Identifier: EPL-2.0
 */
package tools.refinery.language.web.semantics;

import com.google.inject.Inject;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.xtext.service.OperationCanceledManager;
import org.eclipse.xtext.util.CancelIndicator;
import org.eclipse.xtext.validation.CheckType;
import org.eclipse.xtext.validation.FeatureBasedDiagnostic;
import org.eclipse.xtext.validation.IDiagnosticConverter;
import org.eclipse.xtext.validation.Issue;
import org.eclipse.xtext.web.server.validation.ValidationResult;
import tools.refinery.language.model.problem.Problem;
import tools.refinery.language.semantics.metadata.MetadataCreator;
import tools.refinery.language.semantics.model.ModelInitializer;
import tools.refinery.language.semantics.model.TracedException;
import tools.refinery.store.dse.propagation.PropagationAdapter;
import tools.refinery.store.model.ModelStore;
import tools.refinery.store.query.viatra.ViatraModelQueryAdapter;
import tools.refinery.store.reasoning.ReasoningAdapter;
import tools.refinery.store.reasoning.ReasoningStoreAdapter;
import tools.refinery.store.reasoning.literal.Concreteness;
import tools.refinery.store.reasoning.translator.TranslationException;
import tools.refinery.store.util.CancellationToken;

import java.util.ArrayList;
import java.util.concurrent.Callable;

class SemanticsWorker implements Callable<SemanticsResult> {
	private static final String DIAGNOSTIC_ID = "tools.refinery.language.semantics.SemanticError";

	@Inject
	private PartialInterpretation2Json partialInterpretation2Json;

	@Inject
	private OperationCanceledManager operationCanceledManager;

	@Inject
	private IDiagnosticConverter diagnosticConverter;

	@Inject
	private ModelInitializer initializer;

	@Inject
	private MetadataCreator metadataCreator;

	private Problem problem;

	private CancellationToken cancellationToken;

	public void setProblem(Problem problem, CancelIndicator parentIndicator) {
		this.problem = problem;
		cancellationToken = () -> {
			if (Thread.interrupted() || parentIndicator.isCanceled()) {
				operationCanceledManager.throwOperationCanceledException();
			}
		};
	}

	@Override
	public SemanticsResult call() {
		var builder = ModelStore.builder()
				.cancellationToken(cancellationToken)
				.with(ViatraModelQueryAdapter.builder())
				.with(PropagationAdapter.builder())
				.with(ReasoningAdapter.builder()
						.requiredInterpretations(Concreteness.PARTIAL));
		cancellationToken.checkCancelled();
		try {
			var modelSeed = initializer.createModel(problem, builder);
			cancellationToken.checkCancelled();
			metadataCreator.setInitializer(initializer);
			cancellationToken.checkCancelled();
			var nodesMetadata = metadataCreator.getNodesMetadata();
			cancellationToken.checkCancelled();
			var relationsMetadata = metadataCreator.getRelationsMetadata();
			cancellationToken.checkCancelled();
			var store = builder.build();
			cancellationToken.checkCancelled();
			var model = store.getAdapter(ReasoningStoreAdapter.class).createInitialModel(modelSeed);
			cancellationToken.checkCancelled();
			var partialInterpretation = partialInterpretation2Json.getPartialInterpretation(initializer, model,
					Concreteness.PARTIAL, cancellationToken);

			return new SemanticsSuccessResult(nodesMetadata, relationsMetadata, partialInterpretation);
		} catch (TracedException e) {
			return getTracedErrorResult(e.getSourceElement(), e.getMessage());
		} catch (TranslationException e) {
			var sourceElement = initializer.getInverseTrace(e.getPartialSymbol());
			return getTracedErrorResult(sourceElement, e.getMessage());
		}
	}

	private SemanticsResult getTracedErrorResult(EObject sourceElement, String message) {
		if (sourceElement == null || !problem.eResource().equals(sourceElement.eResource())) {
			return new SemanticsInternalErrorResult(message);
		}
		var diagnostic = new FeatureBasedDiagnostic(Diagnostic.ERROR, message, sourceElement, null, 0,
				CheckType.EXPENSIVE, DIAGNOSTIC_ID);
		var xtextIssues = new ArrayList<Issue>();
		diagnosticConverter.convertValidatorDiagnostic(diagnostic, xtextIssues::add);
		var issues = xtextIssues.stream()
				.map(issue -> new ValidationResult.Issue(issue.getMessage(), "error", issue.getLineNumber(),
						issue.getColumn(), issue.getOffset(), issue.getLength()))
				.toList();
		return new SemanticsIssuesResult(issues);
	}
}