aboutsummaryrefslogtreecommitdiffstats
path: root/Application/hu.bme.mit.inf.dslreasoner.application/src/hu/bme/mit/inf/dslreasoner/application/execution/QueryLoader.xtend
blob: 277a1d5f41f4978033c435f20dc5b392b5dea1af (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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
package hu.bme.mit.inf.dslreasoner.application.execution

import hu.bme.mit.inf.dslreasoner.application.applicationConfiguration.AllPatternEntry
import hu.bme.mit.inf.dslreasoner.application.applicationConfiguration.ConfigurationScript
import hu.bme.mit.inf.dslreasoner.application.applicationConfiguration.PatternElement
import hu.bme.mit.inf.dslreasoner.application.applicationConfiguration.PatternEntry
import hu.bme.mit.inf.dslreasoner.application.applicationConfiguration.PatternSpecification
import hu.bme.mit.inf.dslreasoner.application.applicationConfiguration.ViatraImport
import hu.bme.mit.inf.dslreasoner.viatra2logic.ViatraQuerySetDescriptor
import java.util.HashMap
import java.util.LinkedHashSet
import java.util.List
import java.util.Set
import org.eclipse.emf.ecore.EClass
import org.eclipse.emf.ecore.EPackage
import org.eclipse.viatra.query.patternlanguage.emf.specification.SpecificationBuilder
import org.eclipse.viatra.query.patternlanguage.emf.vql.Pattern
import org.eclipse.viatra.query.patternlanguage.emf.vql.PatternCompositionConstraint
import org.eclipse.viatra.query.patternlanguage.emf.vql.PatternModel
import org.eclipse.viatra.query.runtime.api.IQuerySpecification
import org.eclipse.xtext.EcoreUtil2

import static extension hu.bme.mit.inf.dslreasoner.util.CollectionsUtil.*
import org.eclipse.viatra.query.patternlanguage.emf.vql.PatternCall
import org.eclipse.viatra.query.runtime.api.IPatternMatch
import org.eclipse.viatra.query.runtime.api.ViatraQueryMatcher
import java.util.LinkedHashMap
import java.util.LinkedList

class QueryLoader {
	//val parser = new VQLParser
	val builder = new SpecificationBuilder
	
	def loadQueries(PatternSpecification specification) {
		val patterns = new LinkedHashSet
		
		for(entry: specification.entries) {
			patterns += getPatterns(entry)
		}
		
		//val errors = patterns.map[eResource].toSet.map[errors]
		//errors.forEach[println(it)]
		
		val allConcernedPatterns = patterns.allReferredPatterns
		val pattern2Specification = allConcernedPatterns.translatePatterns()
		
		val List<IQuerySpecification<?>> patternsToTranslate =
			pattern2Specification.values.toList
		val Set<IQuerySpecification<?>> validationPatterns =
			patterns.filter[it.annotations.exists[it.name.equals("Constraint")]]
			.map[lookup(pattern2Specification)]
			.toSet
		val derivedFeatures = calculateDerivedFeatures(patterns.referredEcoreModels,patterns.map[it.lookup(pattern2Specification)])
//		patternsToTranslate.forEach[println(it.fullyQualifiedName)]
//		if (true) throw new Exception
		return new ViatraQuerySetDescriptor(
			patternsToTranslate,
			validationPatterns,
			derivedFeatures
		) -> allConcernedPatterns
	}
	
	def dispatch List<Pattern> getPatterns(AllPatternEntry entry) {
		val excluded = entry.exclusuion.map[getPatterns]
		val referredPatternModels = allPatternsWithSamePackage(entry,entry.package as PatternModel).toSet
		val patterns = referredPatternModels.map[patterns].flatten
		return patterns.filter[!excluded.contains(it)].toList
	}
	
	def dispatch List<Pattern> getPatterns(PatternElement entry) {
		return #[entry.pattern]
	}
	
	def private allPatternsWithSamePackage(PatternEntry entry, PatternModel model) {
		val packageURI = model.packageName
		val document = EcoreUtil2.getContainerOfType(entry,ConfigurationScript)
		val viatraImportsWithSamePackage = document.imports
			.filter(ViatraImport)
			.map[it.importedViatra]
			.filterNull
			.filter[packageName.equals(packageURI)]
		return viatraImportsWithSamePackage
	}
	
	/**
	 * Adds all referred patterns to a given set of patterns.
	 */
	def private Set<Pattern> allReferredPatterns(Set<Pattern> patterns) {
		val res = new LinkedHashSet
		res+=patterns
		
		var boolean changed
		do{
			changed = false
			val newElements =  res.map[directlyReferredPatterns].flatten.filter[!res.contains(it)]
			if(!newElements.empty) {
				changed = true
				res.addAll(newElements)
			}
		} while(changed)
		
		return res
	}
	
	def private directlyReferredPatterns(Pattern pattern) {
		return pattern
			.bodies
			.map[constraints]
			.flatten
			.filter(PatternCompositionConstraint)
			.map[(call as PatternCall).patternRef].toSet
	}
	
	def private referredEcoreModels(Set<Pattern> patterns) {
		patterns.map[eContainer as PatternModel].map[it.importPackages.packageImport.map[it.EPackage].filterNull].flatten.toSet
	}
	
	def private translatePatterns(Set<Pattern> xtextPattern) {
		val res = new LinkedHashMap<Pattern,IQuerySpecification<?>>
		val patterns = new LinkedList<IQuerySpecification<?>>
		for(pattern : xtextPattern) {
			val querySpecification = builder.getOrCreateSpecification(pattern,patterns,true)
			res.put(pattern,querySpecification)
			patterns += querySpecification
		}
		
		return res
	}
	
	def private calculateDerivedFeatures(Set<EPackage> packages, Iterable<IQuerySpecification<?>> patterns) {
		val features = packages.map[EClassifiers].flatten.filter(EClass).map[it.EStructuralFeatures].flatten
		val res = new HashMap
		for(feature : features) {
/*
			val QBFAnnotation = feature.EAnnotations.filter[it.source.equals("org.eclipse.viatra.query.querybasedfeature")].head
			if(QBFAnnotation !== null) {
				val targetFQN =	QBFAnnotation.details.get("patternFQN")
				val referredPattern = patterns.filter[
					val fqn = it.fullyQualifiedName
					fqn.equals(targetFQN)
				].head
				if(referredPattern!== null) {
					res.put(referredPattern, feature)
				}
			}
*/
			if (feature.derived){
				//TODO we can check if feature is not from the ECORE MM
				//TODO we can check that the found pattern has a "@QueryBasedFeature" annotation
				val referredPattern = patterns.filter[
					val fqnSplit = it.fullyQualifiedName.split("\\.")
					val patName = fqnSplit.get(fqnSplit.length - 1)
					patName.equals(feature.name)
				].head
				if(referredPattern!== null) {
					res.put(referredPattern, feature)
				}
			}
		}
//		if (!res.empty) {
//			println("Derived Features")
//			res.entrySet.forEach[println(it)]
//		}
		return res
	}
}