diff options
author | 2023-06-18 18:04:43 +0200 | |
---|---|---|
committer | 2023-06-18 18:04:43 +0200 | |
commit | a0619c0fbf1fab2304ca683343803d1f37c2ef7c (patch) | |
tree | 6d6e342b019a1f3ad0baae710cf520a5dffe4b9e /subprojects | |
parent | Merge pull request #24 from kris7t/partial-interpretation (diff) | |
parent | chore(deps): bump dependencies (diff) | |
download | refinery-a0619c0fbf1fab2304ca683343803d1f37c2ef7c.tar.gz refinery-a0619c0fbf1fab2304ca683343803d1f37c2ef7c.tar.zst refinery-a0619c0fbf1fab2304ca683343803d1f37c2ef7c.zip |
Merge pull request #26 from kris7t/query-refactor
Query refactor
Diffstat (limited to 'subprojects')
630 files changed, 10643 insertions, 4969 deletions
diff --git a/subprojects/frontend/.eslintrc.cjs b/subprojects/frontend/.eslintrc.cjs index 8a7b474a..25b86a83 100644 --- a/subprojects/frontend/.eslintrc.cjs +++ b/subprojects/frontend/.eslintrc.cjs | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | const path = require('node:path'); | 7 | const path = require('node:path'); |
2 | 8 | ||
3 | // Allow the Codium ESLint plugin to find `tsconfig.json` from the repository root. | 9 | // Allow the Codium ESLint plugin to find `tsconfig.json` from the repository root. |
@@ -43,6 +49,15 @@ module.exports = { | |||
43 | // In typescript, some class methods implementing an inderface do not use `this`: | 49 | // In typescript, some class methods implementing an inderface do not use `this`: |
44 | // https://github.com/typescript-eslint/typescript-eslint/issues/1103 | 50 | // https://github.com/typescript-eslint/typescript-eslint/issues/1103 |
45 | 'class-methods-use-this': 'off', | 51 | 'class-methods-use-this': 'off', |
52 | // Disable rules with a high performance cost. | ||
53 | // See https://typescript-eslint.io/linting/troubleshooting/performance-troubleshooting/ | ||
54 | 'import/default': 'off', | ||
55 | 'import/extensions': 'off', | ||
56 | 'import/named': 'off', | ||
57 | 'import/namespace': 'off', | ||
58 | 'import/no-named-as-default': 'off', | ||
59 | 'import/no-named-as-default-member': 'off', | ||
60 | '@typescript-eslint/indent': 'off', | ||
46 | // Make sure every import can be resolved by `eslint-import-resolver-typescript`. | 61 | // Make sure every import can be resolved by `eslint-import-resolver-typescript`. |
47 | 'import/no-unresolved': 'error', | 62 | 'import/no-unresolved': 'error', |
48 | // Organize imports automatically. | 63 | // Organize imports automatically. |
@@ -90,6 +105,7 @@ module.exports = { | |||
90 | files: [ | 105 | files: [ |
91 | '.eslintrc.cjs', | 106 | '.eslintrc.cjs', |
92 | 'config/*.ts', | 107 | 'config/*.ts', |
108 | 'config/*.cjs', | ||
93 | 'prettier.config.cjs', | 109 | 'prettier.config.cjs', |
94 | 'vite.config.ts', | 110 | 'vite.config.ts', |
95 | ], | 111 | ], |
@@ -103,6 +119,8 @@ module.exports = { | |||
103 | 'error', | 119 | 'error', |
104 | { devDependencies: true }, | 120 | { devDependencies: true }, |
105 | ], | 121 | ], |
122 | // Allow writing to the console in ad-hoc scripts. | ||
123 | 'no-console': 'off', | ||
106 | // Access to the environment in configuration files. | 124 | // Access to the environment in configuration files. |
107 | 'no-process-env': 'off', | 125 | 'no-process-env': 'off', |
108 | }, | 126 | }, |
diff --git a/subprojects/frontend/assets-src/favicon.svg.license b/subprojects/frontend/assets-src/favicon.svg.license new file mode 100644 index 00000000..e5db6ccd --- /dev/null +++ b/subprojects/frontend/assets-src/favicon.svg.license | |||
@@ -0,0 +1,3 @@ | |||
1 | SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
2 | |||
3 | SPDX-License-Identifier: EPL-2.0 | ||
diff --git a/subprojects/frontend/assets-src/icon.svg.license b/subprojects/frontend/assets-src/icon.svg.license new file mode 100644 index 00000000..e5db6ccd --- /dev/null +++ b/subprojects/frontend/assets-src/icon.svg.license | |||
@@ -0,0 +1,3 @@ | |||
1 | SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
2 | |||
3 | SPDX-License-Identifier: EPL-2.0 | ||
diff --git a/subprojects/frontend/assets-src/mask-icon.svg.license b/subprojects/frontend/assets-src/mask-icon.svg.license new file mode 100644 index 00000000..e5db6ccd --- /dev/null +++ b/subprojects/frontend/assets-src/mask-icon.svg.license | |||
@@ -0,0 +1,3 @@ | |||
1 | SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
2 | |||
3 | SPDX-License-Identifier: EPL-2.0 | ||
diff --git a/subprojects/frontend/build.gradle b/subprojects/frontend/build.gradle deleted file mode 100644 index 4cc2c5d7..00000000 --- a/subprojects/frontend/build.gradle +++ /dev/null | |||
@@ -1,131 +0,0 @@ | |||
1 | plugins { | ||
2 | id 'refinery-frontend-workspace' | ||
3 | id 'refinery-sonarqube' | ||
4 | } | ||
5 | |||
6 | import org.siouan.frontendgradleplugin.infrastructure.gradle.RunYarn | ||
7 | |||
8 | def viteOutputDir = "${buildDir}/vite" | ||
9 | def productionResources = file("${viteOutputDir}/production") | ||
10 | |||
11 | frontend { | ||
12 | assembleScript = 'run build' | ||
13 | } | ||
14 | |||
15 | configurations { | ||
16 | productionAssets { | ||
17 | canBeConsumed = true | ||
18 | canBeResolved = false | ||
19 | } | ||
20 | } | ||
21 | |||
22 | def installFrontend = tasks.named('installFrontend') | ||
23 | |||
24 | def sourcesWithoutTypegen = fileTree('src') { | ||
25 | exclude '**/*.typegen.ts' | ||
26 | } | ||
27 | |||
28 | def assembleFrontend = tasks.named('assembleFrontend') | ||
29 | assembleFrontend.configure { | ||
30 | dependsOn generateXStateTypes | ||
31 | inputs.dir 'public' | ||
32 | inputs.files sourcesWithoutTypegen | ||
33 | inputs.file 'index.html' | ||
34 | inputs.files('package.json', 'tsconfig.json', 'tsconfig.base.json', 'vite.config.ts') | ||
35 | inputs.file rootProject.file('yarn.lock') | ||
36 | outputs.dir productionResources | ||
37 | } | ||
38 | |||
39 | artifacts { | ||
40 | productionAssets(productionResources) { | ||
41 | builtBy assembleFrontend | ||
42 | } | ||
43 | } | ||
44 | |||
45 | def generateXStateTypes = tasks.register('generateXStateTypes', RunYarn) { | ||
46 | dependsOn installFrontend | ||
47 | inputs.files sourcesWithoutTypegen | ||
48 | inputs.file 'package.json' | ||
49 | inputs.file rootProject.file('yarn.lock') | ||
50 | outputs.dir 'src' | ||
51 | script = 'run typegen' | ||
52 | description = 'Generate TypeScript typings for XState state machines.' | ||
53 | } | ||
54 | |||
55 | def typecheckFrontend = tasks.register('typecheckFrontend', RunYarn) { | ||
56 | dependsOn installFrontend | ||
57 | dependsOn generateXStateTypes | ||
58 | inputs.dir 'src' | ||
59 | inputs.dir 'types' | ||
60 | inputs.files('package.json', 'tsconfig.json', 'tsconfig.base.json', 'tsconfig.node.json') | ||
61 | inputs.file rootProject.file('yarn.lock') | ||
62 | outputs.dir "${buildDir}/typescript" | ||
63 | script = 'run typecheck' | ||
64 | group = 'verification' | ||
65 | description = 'Check for TypeScript type errors.' | ||
66 | } | ||
67 | |||
68 | def lintFrontend = tasks.register('lintFrontend', RunYarn) { | ||
69 | dependsOn installFrontend | ||
70 | dependsOn generateXStateTypes | ||
71 | dependsOn typecheckFrontend | ||
72 | inputs.dir 'src' | ||
73 | inputs.dir 'types' | ||
74 | inputs.files('.eslintrc.cjs', 'prettier.config.cjs') | ||
75 | inputs.files('package.json', 'tsconfig.json', 'tsconfig.base.json', 'tsconfig.node.json') | ||
76 | inputs.file rootProject.file('yarn.lock') | ||
77 | if (project.hasProperty('ci')) { | ||
78 | outputs.file "${buildDir}/eslint.json" | ||
79 | script = 'run lint:ci' | ||
80 | } else { | ||
81 | script = 'run lint' | ||
82 | } | ||
83 | group = 'verification' | ||
84 | description = 'Check for TypeScript lint errors and warnings.' | ||
85 | } | ||
86 | |||
87 | def prettier = tasks.register('fixFrontend', RunYarn) { | ||
88 | dependsOn installFrontend | ||
89 | dependsOn generateXStateTypes | ||
90 | dependsOn typecheckFrontend | ||
91 | inputs.dir 'src' | ||
92 | inputs.dir 'types' | ||
93 | inputs.files('.eslintrc.cjs', 'prettier.config.cjs') | ||
94 | inputs.files('package.json', 'tsconfig.json', 'tsconfig.base.json', 'tsconfig.node.json') | ||
95 | inputs.file rootProject.file('yarn.lock') | ||
96 | script = 'run lint:fix' | ||
97 | group = 'verification' | ||
98 | description = 'Fix TypeScript lint errors and warnings.' | ||
99 | } | ||
100 | |||
101 | tasks.named('check') { | ||
102 | dependsOn(typecheckFrontend) | ||
103 | dependsOn(lintFrontend) | ||
104 | } | ||
105 | |||
106 | tasks.register('serveFrontend', RunYarn) { | ||
107 | dependsOn installFrontend | ||
108 | dependsOn generateXStateTypes | ||
109 | inputs.dir 'public' | ||
110 | inputs.files sourcesWithoutTypegen | ||
111 | inputs.file 'index.html' | ||
112 | inputs.files('package.json', 'tsconfig.json', 'tsconfig.base.json', 'vite.config.ts') | ||
113 | inputs.file rootProject.file('yarn.lock') | ||
114 | outputs.dir "${viteOutputDir}/development" | ||
115 | script = 'run serve' | ||
116 | group = 'run' | ||
117 | description = 'Start a Vite dev server with hot module replacement.' | ||
118 | } | ||
119 | |||
120 | tasks.named('clean') { | ||
121 | delete 'dev-dist' | ||
122 | delete fileTree('src') { | ||
123 | include '**/*.typegen.ts' | ||
124 | } | ||
125 | } | ||
126 | |||
127 | sonarqube.properties { | ||
128 | properties['sonar.sources'] = 'src' | ||
129 | property 'sonar.nodejs.executable', "${frontend.nodeInstallDirectory.get()}/bin/node" | ||
130 | property 'sonar.eslint.reportPaths', "${buildDir}/eslint.json" | ||
131 | } | ||
diff --git a/subprojects/frontend/build.gradle.kts b/subprojects/frontend/build.gradle.kts new file mode 100644 index 00000000..d0839371 --- /dev/null +++ b/subprojects/frontend/build.gradle.kts | |||
@@ -0,0 +1,144 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
7 | import org.siouan.frontendgradleplugin.infrastructure.gradle.RunYarn | ||
8 | import tools.refinery.gradle.utils.SonarPropertiesUtils | ||
9 | |||
10 | plugins { | ||
11 | id("tools.refinery.gradle.frontend-workspace") | ||
12 | id("tools.refinery.gradle.sonarqube") | ||
13 | } | ||
14 | |||
15 | frontend { | ||
16 | assembleScript.set("run build") | ||
17 | } | ||
18 | |||
19 | val viteOutputDir = "$buildDir/vite" | ||
20 | |||
21 | val productionResources = file("$viteOutputDir/production") | ||
22 | |||
23 | val productionAssets: Configuration by configurations.creating { | ||
24 | isCanBeConsumed = true | ||
25 | isCanBeResolved = false | ||
26 | } | ||
27 | |||
28 | val sourcesWithoutTypes = fileTree("src") { | ||
29 | exclude("**/*.typegen.ts") | ||
30 | } | ||
31 | |||
32 | val sourcesWithTypes: FileCollection = fileTree("src") + fileTree("types") | ||
33 | |||
34 | val buildScripts: FileCollection = fileTree("config") + files( | ||
35 | ".eslintrc.cjs", | ||
36 | "prettier.config.cjs", | ||
37 | "vite.config.ts", | ||
38 | ) | ||
39 | |||
40 | val installationState = files( | ||
41 | rootProject.file("yarn.lock"), | ||
42 | rootProject.file("package.json"), | ||
43 | "package.json", | ||
44 | ) | ||
45 | |||
46 | val sharedConfigFiles: FileCollection = installationState + files( | ||
47 | "tsconfig.json", | ||
48 | "tsconfig.base.json", | ||
49 | "tsconfig.node.json", | ||
50 | "tsconfig.shared.json", | ||
51 | ) | ||
52 | |||
53 | val assembleConfigFiles = sharedConfigFiles + file("vite.config.ts") + fileTree("config") { | ||
54 | include("**/*.ts") | ||
55 | } | ||
56 | |||
57 | val assembleSources = sourcesWithTypes + fileTree("public") + file("index.html") | ||
58 | |||
59 | val assembleFiles = assembleSources + assembleConfigFiles | ||
60 | |||
61 | val lintingFiles: FileCollection = sourcesWithTypes + buildScripts + sharedConfigFiles | ||
62 | |||
63 | tasks { | ||
64 | val generateXStateTypes by registering(RunYarn::class) { | ||
65 | dependsOn(installFrontend) | ||
66 | inputs.files(sourcesWithoutTypes) | ||
67 | inputs.files(installationState) | ||
68 | outputs.dir("src") | ||
69 | script.set("run typegen") | ||
70 | description = "Generate TypeScript typings for XState state machines." | ||
71 | } | ||
72 | |||
73 | assembleFrontend { | ||
74 | dependsOn(generateXStateTypes) | ||
75 | inputs.files(assembleFiles) | ||
76 | outputs.dir(productionResources) | ||
77 | } | ||
78 | |||
79 | |||
80 | val typeCheckFrontend by registering(RunYarn::class) { | ||
81 | dependsOn(installFrontend) | ||
82 | dependsOn(generateXStateTypes) | ||
83 | inputs.files(lintingFiles) | ||
84 | outputs.dir("$buildDir/typescript") | ||
85 | script.set("run typecheck") | ||
86 | group = "verification" | ||
87 | description = "Check for TypeScript type errors." | ||
88 | } | ||
89 | |||
90 | val lintFrontend by registering(RunYarn::class) { | ||
91 | dependsOn(installFrontend) | ||
92 | dependsOn(generateXStateTypes) | ||
93 | dependsOn(typeCheckFrontend) | ||
94 | inputs.files(lintingFiles) | ||
95 | outputs.file("$buildDir/eslint.json") | ||
96 | script.set("run lint") | ||
97 | group = "verification" | ||
98 | description = "Check for TypeScript lint errors and warnings." | ||
99 | } | ||
100 | |||
101 | register<RunYarn>("fixFrontend") { | ||
102 | dependsOn(installFrontend) | ||
103 | dependsOn(generateXStateTypes) | ||
104 | dependsOn(typeCheckFrontend) | ||
105 | inputs.files(lintingFiles) | ||
106 | script.set("run lint:fix") | ||
107 | group = "verification" | ||
108 | description = "Fix TypeScript lint errors and warnings." | ||
109 | } | ||
110 | |||
111 | check { | ||
112 | dependsOn(typeCheckFrontend) | ||
113 | dependsOn(lintFrontend) | ||
114 | } | ||
115 | |||
116 | register<RunYarn>("serveFrontend") { | ||
117 | dependsOn(installFrontend) | ||
118 | dependsOn(generateXStateTypes) | ||
119 | inputs.files(assembleFiles) | ||
120 | outputs.dir("$viteOutputDir/development") | ||
121 | script.set("run serve") | ||
122 | group = "run" | ||
123 | description = "Start a Vite dev server with hot module replacement." | ||
124 | } | ||
125 | |||
126 | clean { | ||
127 | delete("dev-dist") | ||
128 | delete(fileTree("src") { | ||
129 | include("**/*.typegen.ts") | ||
130 | }) | ||
131 | } | ||
132 | } | ||
133 | |||
134 | artifacts { | ||
135 | add("productionAssets", productionResources) { | ||
136 | builtBy(tasks.assembleFrontend) | ||
137 | } | ||
138 | } | ||
139 | |||
140 | sonarqube.properties { | ||
141 | SonarPropertiesUtils.addToList(properties, "sonar.sources", "src") | ||
142 | property("sonar.nodejs.executable", "${frontend.nodeInstallDirectory.get()}/bin/node") | ||
143 | property("sonar.eslint.reportPaths", "$buildDir/eslint.json") | ||
144 | } | ||
diff --git a/subprojects/frontend/config/backendConfigVitePlugin.ts b/subprojects/frontend/config/backendConfigVitePlugin.ts index 7a6bc3db..3bffce3a 100644 --- a/subprojects/frontend/config/backendConfigVitePlugin.ts +++ b/subprojects/frontend/config/backendConfigVitePlugin.ts | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import type { PluginOption } from 'vite'; | 7 | import type { PluginOption } from 'vite'; |
2 | 8 | ||
3 | import type BackendConfig from '../src/xtext/BackendConfig'; | 9 | import type BackendConfig from '../src/xtext/BackendConfig'; |
diff --git a/subprojects/frontend/config/detectDevModeOptions.ts b/subprojects/frontend/config/detectDevModeOptions.ts index b3696241..665204dc 100644 --- a/subprojects/frontend/config/detectDevModeOptions.ts +++ b/subprojects/frontend/config/detectDevModeOptions.ts | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import type { PluginOption, ServerOptions } from 'vite'; | 7 | import type { PluginOption, ServerOptions } from 'vite'; |
2 | 8 | ||
3 | import backendConfigVitePlugin, { | 9 | import backendConfigVitePlugin, { |
diff --git a/subprojects/frontend/config/eslintReport.cjs b/subprojects/frontend/config/eslintReport.cjs new file mode 100644 index 00000000..7c4b7bd6 --- /dev/null +++ b/subprojects/frontend/config/eslintReport.cjs | |||
@@ -0,0 +1,58 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
7 | const { writeFile } = require('node:fs/promises'); | ||
8 | const path = require('node:path'); | ||
9 | const { Readable } = require('node:stream'); | ||
10 | const { pipeline } = require('node:stream/promises'); | ||
11 | |||
12 | const { ESLint } = require('eslint'); | ||
13 | |||
14 | const rootDir = path.join(__dirname, '..'); | ||
15 | |||
16 | /** | ||
17 | * Write ESLint report to console. | ||
18 | * | ||
19 | * @param cli {import('eslint').ESLint} The ESLint CLI. | ||
20 | * @param report {import('eslint').ESLint.LintResult[]} The ESLint report. | ||
21 | * @return {Promise<void>} A promise that resolves when the report is finished. | ||
22 | */ | ||
23 | async function reportToConsole(cli, report) { | ||
24 | const stylishFormatter = await cli.loadFormatter('stylish'); | ||
25 | const output = new Readable(); | ||
26 | output.push(await stylishFormatter.format(report)); | ||
27 | output.push(null); | ||
28 | return pipeline(output, process.stdout); | ||
29 | } | ||
30 | |||
31 | /** | ||
32 | * Write ESLint report to the <code>build</code> directory. | ||
33 | * | ||
34 | * @param cli {import('eslint').ESLint} The ESLint CLI. | ||
35 | * @param report {import('eslint').ESLint.LintResult[]} The ESLint report. | ||
36 | * @return {Promise<void>} A promise that resolves when the report is finished. | ||
37 | */ | ||
38 | async function reportToJson(cli, report) { | ||
39 | const jsonFormatter = await cli.loadFormatter('json'); | ||
40 | const json = await jsonFormatter.format(report); | ||
41 | const reportPath = path.join(rootDir, 'build', 'eslint.json'); | ||
42 | return writeFile(reportPath, json, 'utf-8'); | ||
43 | } | ||
44 | |||
45 | async function createReport() { | ||
46 | const cli = new ESLint({ | ||
47 | useEslintrc: true, | ||
48 | cwd: rootDir, | ||
49 | }); | ||
50 | const report = await cli.lintFiles('.'); | ||
51 | await Promise.all([reportToConsole(cli, report), reportToJson(cli, report)]); | ||
52 | |||
53 | if (report.some((entry) => entry.errorCount > 0)) { | ||
54 | process.exitCode = 1; | ||
55 | } | ||
56 | } | ||
57 | |||
58 | createReport().catch(console.error); | ||
diff --git a/subprojects/frontend/config/fetchPackageMetadata.ts b/subprojects/frontend/config/fetchPackageMetadata.ts index 50807b03..02e16d57 100644 --- a/subprojects/frontend/config/fetchPackageMetadata.ts +++ b/subprojects/frontend/config/fetchPackageMetadata.ts | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import { readFile } from 'node:fs/promises'; | 7 | import { readFile } from 'node:fs/promises'; |
2 | import path from 'node:path'; | 8 | import path from 'node:path'; |
3 | 9 | ||
diff --git a/subprojects/frontend/config/manifest.ts b/subprojects/frontend/config/manifest.ts index 3cec777c..1822dc7c 100644 --- a/subprojects/frontend/config/manifest.ts +++ b/subprojects/frontend/config/manifest.ts | |||
@@ -1,10 +1,16 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import type { ManifestOptions } from 'vite-plugin-pwa'; | 7 | import type { ManifestOptions } from 'vite-plugin-pwa'; |
2 | 8 | ||
3 | const manifest: Partial<ManifestOptions> = { | 9 | const manifest: Partial<ManifestOptions> = { |
4 | lang: 'en-US', | 10 | lang: 'en-US', |
5 | name: 'Refinery', | 11 | name: 'Refinery', |
6 | short_name: 'Refinery', | 12 | short_name: 'Refinery', |
7 | description: 'An efficient graph sovler for generating well-formed models', | 13 | description: 'An efficient graph solver for generating well-formed models', |
8 | theme_color: '#f5f5f5', | 14 | theme_color: '#f5f5f5', |
9 | display_override: ['window-controls-overlay'], | 15 | display_override: ['window-controls-overlay'], |
10 | display: 'standalone', | 16 | display: 'standalone', |
diff --git a/subprojects/frontend/config/minifyHTMLVitePlugin.ts b/subprojects/frontend/config/minifyHTMLVitePlugin.ts index 18336d4d..7c08c488 100644 --- a/subprojects/frontend/config/minifyHTMLVitePlugin.ts +++ b/subprojects/frontend/config/minifyHTMLVitePlugin.ts | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import { minify, type Options as TerserOptions } from 'html-minifier-terser'; | 7 | import { minify, type Options as TerserOptions } from 'html-minifier-terser'; |
2 | import type { PluginOption } from 'vite'; | 8 | import type { PluginOption } from 'vite'; |
3 | 9 | ||
diff --git a/subprojects/frontend/config/preloadFontsVitePlugin.ts b/subprojects/frontend/config/preloadFontsVitePlugin.ts index bc6f8eaf..5c04477a 100644 --- a/subprojects/frontend/config/preloadFontsVitePlugin.ts +++ b/subprojects/frontend/config/preloadFontsVitePlugin.ts | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import micromatch from 'micromatch'; | 7 | import micromatch from 'micromatch'; |
2 | import type { PluginOption } from 'vite'; | 8 | import type { PluginOption } from 'vite'; |
3 | 9 | ||
diff --git a/subprojects/frontend/index.html b/subprojects/frontend/index.html index 8b6814eb..1bf3472e 100644 --- a/subprojects/frontend/index.html +++ b/subprojects/frontend/index.html | |||
@@ -1,4 +1,9 @@ | |||
1 | <!DOCTYPE html> | 1 | <!DOCTYPE html> |
2 | <!-- | ||
3 | SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
4 | |||
5 | SPDX-License-Identifier: EPL-2.0 | ||
6 | --> | ||
2 | <html lang="en-US"> | 7 | <html lang="en-US"> |
3 | <head> | 8 | <head> |
4 | <meta charset="utf-8"> | 9 | <meta charset="utf-8"> |
@@ -13,9 +18,9 @@ | |||
13 | <meta name="theme-color" media="(prefers-color-scheme:light)" content="#f5f5f5"> | 18 | <meta name="theme-color" media="(prefers-color-scheme:light)" content="#f5f5f5"> |
14 | <meta name="theme-color" media="(prefers-color-scheme:dark)" content="#21252b"> | 19 | <meta name="theme-color" media="(prefers-color-scheme:dark)" content="#21252b"> |
15 | <style> | 20 | <style> |
16 | @import '@fontsource/inter/variable.css'; | 21 | @import '@fontsource-variable/inter/wght.css'; |
17 | @import '@fontsource/jetbrains-mono/variable.css'; | 22 | @import '@fontsource-variable/jetbrains-mono/wght.css'; |
18 | @import '@fontsource/jetbrains-mono/variable-italic.css'; | 23 | @import '@fontsource-variable/jetbrains-mono/wght-italic.css'; |
19 | </style> | 24 | </style> |
20 | </head> | 25 | </head> |
21 | <body> | 26 | <body> |
diff --git a/subprojects/frontend/package.json b/subprojects/frontend/package.json index a761e74c..ba8a0a58 100644 --- a/subprojects/frontend/package.json +++ b/subprojects/frontend/package.json | |||
@@ -1,4 +1,9 @@ | |||
1 | { | 1 | { |
2 | "//": [ | ||
3 | "SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/>", | ||
4 | "", | ||
5 | "SPDX-License-Identifier: EPL-2.0" | ||
6 | ], | ||
2 | "name": "@refinery/frontend", | 7 | "name": "@refinery/frontend", |
3 | "version": "0.0.0", | 8 | "version": "0.0.0", |
4 | "description": "Web frontend for Refinery", | 9 | "description": "Web frontend for Refinery", |
@@ -9,41 +14,40 @@ | |||
9 | "serve": "cross-env MODE=development vite serve", | 14 | "serve": "cross-env MODE=development vite serve", |
10 | "typegen": "xstate typegen \"src/**/*.ts?(x)\"", | 15 | "typegen": "xstate typegen \"src/**/*.ts?(x)\"", |
11 | "typecheck": "tsc -p tsconfig.shared.json && tsc -p tsconfig.node.json && tsc -p tsconfig.json", | 16 | "typecheck": "tsc -p tsconfig.shared.json && tsc -p tsconfig.node.json && tsc -p tsconfig.json", |
12 | "lint": "eslint .", | 17 | "lint": "node config/eslintReport.cjs", |
13 | "lint:ci": "eslint -f json -o build/eslint.json .", | ||
14 | "lint:fix": "yarn run lint --fix" | 18 | "lint:fix": "yarn run lint --fix" |
15 | }, | 19 | }, |
16 | "repository": { | 20 | "repository": { |
17 | "type": "git", | 21 | "type": "git", |
18 | "url": "git+https://github.com/graphs4value/refinery.git" | 22 | "url": "git+https://github.com/graphs4value/refinery.git" |
19 | }, | 23 | }, |
20 | "author": "Refinery authors", | 24 | "author": "The Refinery Authors <https://refinery.tools/>", |
21 | "license": "EPL-2.0", | 25 | "license": "EPL-2.0", |
22 | "bugs": { | 26 | "bugs": { |
23 | "url": "https://github.com/graphs4value/issues" | 27 | "url": "https://github.com/graphs4value/refinery/issues" |
24 | }, | 28 | }, |
25 | "homepage": "https://refinery.tools", | 29 | "homepage": "https://refinery.tools", |
26 | "dependencies": { | 30 | "dependencies": { |
27 | "@codemirror/autocomplete": "^6.4.2", | 31 | "@codemirror/autocomplete": "^6.8.0", |
28 | "@codemirror/commands": "^6.2.2", | 32 | "@codemirror/commands": "^6.2.4", |
29 | "@codemirror/language": "^6.6.0", | 33 | "@codemirror/language": "^6.8.0", |
30 | "@codemirror/lint": "^6.2.0", | 34 | "@codemirror/lint": "^6.2.2", |
31 | "@codemirror/search": "^6.3.0", | 35 | "@codemirror/search": "^6.5.0", |
32 | "@codemirror/state": "^6.2.0", | 36 | "@codemirror/state": "^6.2.1", |
33 | "@codemirror/view": "^6.9.3", | 37 | "@codemirror/view": "^6.13.2", |
34 | "@emotion/react": "^11.10.6", | 38 | "@emotion/react": "^11.11.1", |
35 | "@emotion/styled": "^11.10.6", | 39 | "@emotion/styled": "^11.11.0", |
36 | "@fontsource/inter": "^4.5.15", | 40 | "@fontsource-variable/inter": "^5.0.3", |
37 | "@fontsource/jetbrains-mono": "^4.5.12", | 41 | "@fontsource-variable/jetbrains-mono": "^5.0.3", |
38 | "@lezer/common": "^1.0.2", | 42 | "@lezer/common": "^1.0.3", |
39 | "@lezer/highlight": "^1.1.4", | 43 | "@lezer/highlight": "^1.1.6", |
40 | "@lezer/lr": "^1.3.3", | 44 | "@lezer/lr": "^1.3.6", |
41 | "@material-icons/svg": "^1.0.33", | 45 | "@material-icons/svg": "^1.0.33", |
42 | "@mui/icons-material": "5.11.11", | 46 | "@mui/icons-material": "5.11.16", |
43 | "@mui/material": "5.11.15", | 47 | "@mui/material": "5.13.5", |
44 | "@vitejs/plugin-react-swc": "^3.2.0", | 48 | "@vitejs/plugin-react-swc": "^3.3.2", |
45 | "ansi-styles": "^6.2.1", | 49 | "ansi-styles": "^6.2.1", |
46 | "csstype": "^3.1.1", | 50 | "csstype": "^3.1.2", |
47 | "escape-string-regexp": "^5.0.0", | 51 | "escape-string-regexp": "^5.0.0", |
48 | "lodash-es": "^4.17.21", | 52 | "lodash-es": "^4.17.21", |
49 | "loglevel": "^1.8.1", | 53 | "loglevel": "^1.8.1", |
@@ -55,42 +59,41 @@ | |||
55 | "notistack": "^3.0.1", | 59 | "notistack": "^3.0.1", |
56 | "react": "^18.2.0", | 60 | "react": "^18.2.0", |
57 | "react-dom": "^18.2.0", | 61 | "react-dom": "^18.2.0", |
58 | "xstate": "^4.37.1", | 62 | "xstate": "^4.37.2", |
59 | "zod": "^3.21.4" | 63 | "zod": "^3.21.4" |
60 | }, | 64 | }, |
61 | "devDependencies": { | 65 | "devDependencies": { |
62 | "@lezer/generator": "^1.2.2", | 66 | "@lezer/generator": "^1.3.0", |
63 | "@tsconfig/strictest": "^2.0.0", | 67 | "@types/eslint": "^8.40.2", |
64 | "@types/eslint": "^8.37.0", | ||
65 | "@types/html-minifier-terser": "^7.0.0", | 68 | "@types/html-minifier-terser": "^7.0.0", |
66 | "@types/lodash-es": "^4.17.7", | 69 | "@types/lodash-es": "^4.17.7", |
67 | "@types/micromatch": "^4.0.2", | 70 | "@types/micromatch": "^4.0.2", |
68 | "@types/ms": "^0.7.31", | 71 | "@types/ms": "^0.7.31", |
69 | "@types/node": "^18.15.11", | 72 | "@types/node": "^18.16.18", |
70 | "@types/prettier": "^2.7.2", | 73 | "@types/prettier": "^2.7.3", |
71 | "@types/react": "^18.0.31", | 74 | "@types/react": "^18.2.12", |
72 | "@types/react-dom": "^18.0.11", | 75 | "@types/react-dom": "^18.2.5", |
73 | "@typescript-eslint/eslint-plugin": "^5.57.0", | 76 | "@typescript-eslint/eslint-plugin": "^5.59.11", |
74 | "@typescript-eslint/parser": "^5.57.0", | 77 | "@typescript-eslint/parser": "^5.59.11", |
75 | "@xstate/cli": "^0.4.2", | 78 | "@xstate/cli": "^0.5.1", |
76 | "cross-env": "^7.0.3", | 79 | "cross-env": "^7.0.3", |
77 | "eslint": "^8.37.0", | 80 | "eslint": "^8.43.0", |
78 | "eslint-config-airbnb": "^19.0.4", | 81 | "eslint-config-airbnb": "^19.0.4", |
79 | "eslint-config-airbnb-typescript": "^17.0.0", | 82 | "eslint-config-airbnb-typescript": "^17.0.0", |
80 | "eslint-config-prettier": "^8.8.0", | 83 | "eslint-config-prettier": "^8.8.0", |
81 | "eslint-import-resolver-typescript": "^3.5.4", | 84 | "eslint-import-resolver-typescript": "^3.5.5", |
82 | "eslint-plugin-import": "^2.27.5", | 85 | "eslint-plugin-import": "^2.27.5", |
83 | "eslint-plugin-jsx-a11y": "^6.7.1", | 86 | "eslint-plugin-jsx-a11y": "^6.7.1", |
84 | "eslint-plugin-mobx": "^0.0.9", | 87 | "eslint-plugin-mobx": "^0.0.9", |
85 | "eslint-plugin-prettier": "^4.2.1", | 88 | "eslint-plugin-prettier": "^4.2.1", |
86 | "eslint-plugin-react": "^7.32.2", | 89 | "eslint-plugin-react": "^7.32.2", |
87 | "eslint-plugin-react-hooks": "^4.6.0", | 90 | "eslint-plugin-react-hooks": "^4.6.0", |
88 | "html-minifier-terser": "^7.1.0", | 91 | "html-minifier-terser": "^7.2.0", |
89 | "micromatch": "^4.0.5", | 92 | "micromatch": "^4.0.5", |
90 | "prettier": "^2.8.7", | 93 | "prettier": "^2.8.8", |
91 | "typescript": "5.0.3", | 94 | "typescript": "5.1.3", |
92 | "vite": "^4.2.1", | 95 | "vite": "^4.3.9", |
93 | "vite-plugin-pwa": "^0.14.7", | 96 | "vite-plugin-pwa": "^0.16.4", |
94 | "workbox-window": "^6.5.4" | 97 | "workbox-window": "^7.0.0" |
95 | } | 98 | } |
96 | } | 99 | } |
diff --git a/subprojects/frontend/prettier.config.cjs b/subprojects/frontend/prettier.config.cjs index 75f5c54d..6f9ff7ad 100644 --- a/subprojects/frontend/prettier.config.cjs +++ b/subprojects/frontend/prettier.config.cjs | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | /** @type {import('prettier').Config} */ | 7 | /** @type {import('prettier').Config} */ |
2 | module.exports = { | 8 | module.exports = { |
3 | singleQuote: true, | 9 | singleQuote: true, |
diff --git a/subprojects/frontend/public/apple-touch-icon.png.license b/subprojects/frontend/public/apple-touch-icon.png.license new file mode 100644 index 00000000..e5db6ccd --- /dev/null +++ b/subprojects/frontend/public/apple-touch-icon.png.license | |||
@@ -0,0 +1,3 @@ | |||
1 | SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
2 | |||
3 | SPDX-License-Identifier: EPL-2.0 | ||
diff --git a/subprojects/frontend/public/favicon-96x96.png.license b/subprojects/frontend/public/favicon-96x96.png.license new file mode 100644 index 00000000..e5db6ccd --- /dev/null +++ b/subprojects/frontend/public/favicon-96x96.png.license | |||
@@ -0,0 +1,3 @@ | |||
1 | SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
2 | |||
3 | SPDX-License-Identifier: EPL-2.0 | ||
diff --git a/subprojects/frontend/public/favicon.png.license b/subprojects/frontend/public/favicon.png.license new file mode 100644 index 00000000..e5db6ccd --- /dev/null +++ b/subprojects/frontend/public/favicon.png.license | |||
@@ -0,0 +1,3 @@ | |||
1 | SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
2 | |||
3 | SPDX-License-Identifier: EPL-2.0 | ||
diff --git a/subprojects/frontend/public/favicon.svg.license b/subprojects/frontend/public/favicon.svg.license new file mode 100644 index 00000000..e5db6ccd --- /dev/null +++ b/subprojects/frontend/public/favicon.svg.license | |||
@@ -0,0 +1,3 @@ | |||
1 | SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
2 | |||
3 | SPDX-License-Identifier: EPL-2.0 | ||
diff --git a/subprojects/frontend/public/icon-192x192.png.license b/subprojects/frontend/public/icon-192x192.png.license new file mode 100644 index 00000000..e5db6ccd --- /dev/null +++ b/subprojects/frontend/public/icon-192x192.png.license | |||
@@ -0,0 +1,3 @@ | |||
1 | SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
2 | |||
3 | SPDX-License-Identifier: EPL-2.0 | ||
diff --git a/subprojects/frontend/public/icon-512x512.png.license b/subprojects/frontend/public/icon-512x512.png.license new file mode 100644 index 00000000..e5db6ccd --- /dev/null +++ b/subprojects/frontend/public/icon-512x512.png.license | |||
@@ -0,0 +1,3 @@ | |||
1 | SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
2 | |||
3 | SPDX-License-Identifier: EPL-2.0 | ||
diff --git a/subprojects/frontend/public/icon-any.svg.license b/subprojects/frontend/public/icon-any.svg.license new file mode 100644 index 00000000..e5db6ccd --- /dev/null +++ b/subprojects/frontend/public/icon-any.svg.license | |||
@@ -0,0 +1,3 @@ | |||
1 | SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
2 | |||
3 | SPDX-License-Identifier: EPL-2.0 | ||
diff --git a/subprojects/frontend/public/mask-icon.svg.license b/subprojects/frontend/public/mask-icon.svg.license new file mode 100644 index 00000000..e5db6ccd --- /dev/null +++ b/subprojects/frontend/public/mask-icon.svg.license | |||
@@ -0,0 +1,3 @@ | |||
1 | SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
2 | |||
3 | SPDX-License-Identifier: EPL-2.0 | ||
diff --git a/subprojects/frontend/public/robots.txt b/subprojects/frontend/public/robots.txt index c2a49f4f..e7c73099 100644 --- a/subprojects/frontend/public/robots.txt +++ b/subprojects/frontend/public/robots.txt | |||
@@ -1,2 +1,6 @@ | |||
1 | # SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
2 | # | ||
3 | # SPDX-License-Identifier: CC0-1.0 | ||
4 | |||
1 | User-agent: * | 5 | User-agent: * |
2 | Allow: / | 6 | Allow: / |
diff --git a/subprojects/frontend/src/App.tsx b/subprojects/frontend/src/App.tsx index cd394345..7f242529 100644 --- a/subprojects/frontend/src/App.tsx +++ b/subprojects/frontend/src/App.tsx | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import Box from '@mui/material/Box'; | 7 | import Box from '@mui/material/Box'; |
2 | import CssBaseline from '@mui/material/CssBaseline'; | 8 | import CssBaseline from '@mui/material/CssBaseline'; |
3 | import { throttle } from 'lodash-es'; | 9 | import { throttle } from 'lodash-es'; |
diff --git a/subprojects/frontend/src/Loading.tsx b/subprojects/frontend/src/Loading.tsx index 489563e0..adee4f0e 100644 --- a/subprojects/frontend/src/Loading.tsx +++ b/subprojects/frontend/src/Loading.tsx | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import CircularProgress from '@mui/material/CircularProgress'; | 7 | import CircularProgress from '@mui/material/CircularProgress'; |
2 | import { styled } from '@mui/material/styles'; | 8 | import { styled } from '@mui/material/styles'; |
3 | 9 | ||
diff --git a/subprojects/frontend/src/PWAStore.ts b/subprojects/frontend/src/PWAStore.ts index e9f99e2a..a1b3ffd9 100644 --- a/subprojects/frontend/src/PWAStore.ts +++ b/subprojects/frontend/src/PWAStore.ts | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import { makeAutoObservable, observable } from 'mobx'; | 7 | import { makeAutoObservable, observable } from 'mobx'; |
2 | import ms from 'ms'; | 8 | import ms from 'ms'; |
3 | // eslint-disable-next-line import/no-unresolved -- Importing virtual module. | 9 | // eslint-disable-next-line import/no-unresolved -- Importing virtual module. |
diff --git a/subprojects/frontend/src/Refinery.tsx b/subprojects/frontend/src/Refinery.tsx index f0162349..b5ff94e1 100644 --- a/subprojects/frontend/src/Refinery.tsx +++ b/subprojects/frontend/src/Refinery.tsx | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import Grow from '@mui/material/Grow'; | 7 | import Grow from '@mui/material/Grow'; |
2 | import Stack from '@mui/material/Stack'; | 8 | import Stack from '@mui/material/Stack'; |
3 | import { SnackbarProvider } from 'notistack'; | 9 | import { SnackbarProvider } from 'notistack'; |
diff --git a/subprojects/frontend/src/RootStore.ts b/subprojects/frontend/src/RootStore.ts index 2e76d66d..b84c0ce0 100644 --- a/subprojects/frontend/src/RootStore.ts +++ b/subprojects/frontend/src/RootStore.ts | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import { getLogger } from 'loglevel'; | 7 | import { getLogger } from 'loglevel'; |
2 | import { makeAutoObservable, runInAction } from 'mobx'; | 8 | import { makeAutoObservable, runInAction } from 'mobx'; |
3 | 9 | ||
diff --git a/subprojects/frontend/src/RootStoreProvider.tsx b/subprojects/frontend/src/RootStoreProvider.tsx index 2c11a0f9..7cb89af1 100644 --- a/subprojects/frontend/src/RootStoreProvider.tsx +++ b/subprojects/frontend/src/RootStoreProvider.tsx | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import { type ReactNode, createContext, useContext } from 'react'; | 7 | import { type ReactNode, createContext, useContext } from 'react'; |
2 | 8 | ||
3 | import type RootStore from './RootStore'; | 9 | import type RootStore from './RootStore'; |
diff --git a/subprojects/frontend/src/ToggleDarkModeButton.tsx b/subprojects/frontend/src/ToggleDarkModeButton.tsx index 59714f20..7a835e61 100644 --- a/subprojects/frontend/src/ToggleDarkModeButton.tsx +++ b/subprojects/frontend/src/ToggleDarkModeButton.tsx | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import DarkModeIcon from '@mui/icons-material/DarkMode'; | 7 | import DarkModeIcon from '@mui/icons-material/DarkMode'; |
2 | import LightModeIcon from '@mui/icons-material/LightMode'; | 8 | import LightModeIcon from '@mui/icons-material/LightMode'; |
3 | import IconButton from '@mui/material/IconButton'; | 9 | import IconButton from '@mui/material/IconButton'; |
diff --git a/subprojects/frontend/src/TopBar.tsx b/subprojects/frontend/src/TopBar.tsx index 5a825512..f2542b14 100644 --- a/subprojects/frontend/src/TopBar.tsx +++ b/subprojects/frontend/src/TopBar.tsx | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import GitHubIcon from '@mui/icons-material/GitHub'; | 7 | import GitHubIcon from '@mui/icons-material/GitHub'; |
2 | import AppBar from '@mui/material/AppBar'; | 8 | import AppBar from '@mui/material/AppBar'; |
3 | import Button from '@mui/material/Button'; | 9 | import Button from '@mui/material/Button'; |
diff --git a/subprojects/frontend/src/UpdateNotification.tsx b/subprojects/frontend/src/UpdateNotification.tsx index 5c8c2d01..d86c0703 100644 --- a/subprojects/frontend/src/UpdateNotification.tsx +++ b/subprojects/frontend/src/UpdateNotification.tsx | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import Button from '@mui/material/Button'; | 7 | import Button from '@mui/material/Button'; |
2 | import { observer } from 'mobx-react-lite'; | 8 | import { observer } from 'mobx-react-lite'; |
3 | import { useEffect } from 'react'; | 9 | import { useEffect } from 'react'; |
diff --git a/subprojects/frontend/src/WindowControlsOverlayColor.tsx b/subprojects/frontend/src/WindowControlsOverlayColor.tsx index 14eda566..cfa468ea 100644 --- a/subprojects/frontend/src/WindowControlsOverlayColor.tsx +++ b/subprojects/frontend/src/WindowControlsOverlayColor.tsx | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import { useTheme } from '@mui/material/styles'; | 7 | import { useTheme } from '@mui/material/styles'; |
2 | import { useEffect } from 'react'; | 8 | import { useEffect } from 'react'; |
3 | 9 | ||
diff --git a/subprojects/frontend/src/editor/AnimatedButton.tsx b/subprojects/frontend/src/editor/AnimatedButton.tsx index f75d4617..dbbda618 100644 --- a/subprojects/frontend/src/editor/AnimatedButton.tsx +++ b/subprojects/frontend/src/editor/AnimatedButton.tsx | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import Box from '@mui/material/Box'; | 7 | import Box from '@mui/material/Box'; |
2 | import Button from '@mui/material/Button'; | 8 | import Button from '@mui/material/Button'; |
3 | import { styled, type SxProps, type Theme } from '@mui/material/styles'; | 9 | import { styled, type SxProps, type Theme } from '@mui/material/styles'; |
diff --git a/subprojects/frontend/src/editor/ConnectButton.tsx b/subprojects/frontend/src/editor/ConnectButton.tsx index e2d251f3..eed6fbc7 100644 --- a/subprojects/frontend/src/editor/ConnectButton.tsx +++ b/subprojects/frontend/src/editor/ConnectButton.tsx | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import CloudIcon from '@mui/icons-material/Cloud'; | 7 | import CloudIcon from '@mui/icons-material/Cloud'; |
2 | import CloudOffIcon from '@mui/icons-material/CloudOff'; | 8 | import CloudOffIcon from '@mui/icons-material/CloudOff'; |
3 | import SyncIcon from '@mui/icons-material/Sync'; | 9 | import SyncIcon from '@mui/icons-material/Sync'; |
diff --git a/subprojects/frontend/src/editor/ConnectionStatusNotification.tsx b/subprojects/frontend/src/editor/ConnectionStatusNotification.tsx index 9b27f45c..b7b962ab 100644 --- a/subprojects/frontend/src/editor/ConnectionStatusNotification.tsx +++ b/subprojects/frontend/src/editor/ConnectionStatusNotification.tsx | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import Button from '@mui/material/Button'; | 7 | import Button from '@mui/material/Button'; |
2 | import { observer } from 'mobx-react-lite'; | 8 | import { observer } from 'mobx-react-lite'; |
3 | import { useEffect } from 'react'; | 9 | import { useEffect } from 'react'; |
diff --git a/subprojects/frontend/src/editor/DiagnosticValue.ts b/subprojects/frontend/src/editor/DiagnosticValue.ts index b4e0b165..20478262 100644 --- a/subprojects/frontend/src/editor/DiagnosticValue.ts +++ b/subprojects/frontend/src/editor/DiagnosticValue.ts | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import type { Diagnostic } from '@codemirror/lint'; | 7 | import type { Diagnostic } from '@codemirror/lint'; |
2 | import { RangeValue } from '@codemirror/state'; | 8 | import { RangeValue } from '@codemirror/state'; |
3 | 9 | ||
diff --git a/subprojects/frontend/src/editor/EditorArea.tsx b/subprojects/frontend/src/editor/EditorArea.tsx index cfb988b2..905fa2ec 100644 --- a/subprojects/frontend/src/editor/EditorArea.tsx +++ b/subprojects/frontend/src/editor/EditorArea.tsx | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import Box from '@mui/material/Box'; | 7 | import Box from '@mui/material/Box'; |
2 | import { useTheme } from '@mui/material/styles'; | 8 | import { useTheme } from '@mui/material/styles'; |
3 | import { observer } from 'mobx-react-lite'; | 9 | import { observer } from 'mobx-react-lite'; |
diff --git a/subprojects/frontend/src/editor/EditorButtons.tsx b/subprojects/frontend/src/editor/EditorButtons.tsx index 53b06e23..9b187e5c 100644 --- a/subprojects/frontend/src/editor/EditorButtons.tsx +++ b/subprojects/frontend/src/editor/EditorButtons.tsx | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import type { Diagnostic } from '@codemirror/lint'; | 7 | import type { Diagnostic } from '@codemirror/lint'; |
2 | import CheckIcon from '@mui/icons-material/Check'; | 8 | import CheckIcon from '@mui/icons-material/Check'; |
3 | import ErrorIcon from '@mui/icons-material/Error'; | 9 | import ErrorIcon from '@mui/icons-material/Error'; |
diff --git a/subprojects/frontend/src/editor/EditorPane.tsx b/subprojects/frontend/src/editor/EditorPane.tsx index f7f8241a..87f408fe 100644 --- a/subprojects/frontend/src/editor/EditorPane.tsx +++ b/subprojects/frontend/src/editor/EditorPane.tsx | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import Box from '@mui/material/Box'; | 7 | import Box from '@mui/material/Box'; |
2 | import Skeleton from '@mui/material/Skeleton'; | 8 | import Skeleton from '@mui/material/Skeleton'; |
3 | import Stack from '@mui/material/Stack'; | 9 | import Stack from '@mui/material/Stack'; |
diff --git a/subprojects/frontend/src/editor/EditorStore.ts b/subprojects/frontend/src/editor/EditorStore.ts index 0a0d885d..b98f085e 100644 --- a/subprojects/frontend/src/editor/EditorStore.ts +++ b/subprojects/frontend/src/editor/EditorStore.ts | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import type { | 7 | import type { |
2 | CompletionContext, | 8 | CompletionContext, |
3 | CompletionResult, | 9 | CompletionResult, |
diff --git a/subprojects/frontend/src/editor/EditorTheme.ts b/subprojects/frontend/src/editor/EditorTheme.ts index 01b65a7e..e057ce18 100644 --- a/subprojects/frontend/src/editor/EditorTheme.ts +++ b/subprojects/frontend/src/editor/EditorTheme.ts | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import errorSVG from '@material-icons/svg/svg/error/baseline.svg?raw'; | 7 | import errorSVG from '@material-icons/svg/svg/error/baseline.svg?raw'; |
2 | import expandMoreSVG from '@material-icons/svg/svg/expand_more/baseline.svg?raw'; | 8 | import expandMoreSVG from '@material-icons/svg/svg/expand_more/baseline.svg?raw'; |
3 | import infoSVG from '@material-icons/svg/svg/info/baseline.svg?raw'; | 9 | import infoSVG from '@material-icons/svg/svg/info/baseline.svg?raw'; |
@@ -8,32 +14,6 @@ function svgURL(svg: string): string { | |||
8 | return `url('data:image/svg+xml;utf8,${svg}')`; | 14 | return `url('data:image/svg+xml;utf8,${svg}')`; |
9 | } | 15 | } |
10 | 16 | ||
11 | function radialShadowTheme( | ||
12 | origin: string, | ||
13 | scaleX: boolean, | ||
14 | scaleY: boolean, | ||
15 | ): CSSObject { | ||
16 | function radialGradient(opacity: number, scale: string): string { | ||
17 | return `radial-gradient( | ||
18 | farthest-side at ${origin}, | ||
19 | rgba(0, 0, 0, ${opacity}), | ||
20 | rgba(0, 0, 0, 0) | ||
21 | ) | ||
22 | ${origin} / | ||
23 | ${scaleX ? scale : '100%'} | ||
24 | ${scaleY ? scale : '100%'} | ||
25 | no-repeat`; | ||
26 | } | ||
27 | |||
28 | return { | ||
29 | background: ` | ||
30 | ${radialGradient(0.2, '40%')}, | ||
31 | ${radialGradient(0.14, '50%')}, | ||
32 | ${radialGradient(0.12, '100%')} | ||
33 | `, | ||
34 | }; | ||
35 | } | ||
36 | |||
37 | export default styled('div', { | 17 | export default styled('div', { |
38 | name: 'EditorTheme', | 18 | name: 'EditorTheme', |
39 | shouldForwardProp: (propName) => | 19 | shouldForwardProp: (propName) => |
@@ -52,98 +32,13 @@ export default styled('div', { | |||
52 | }, | 32 | }, |
53 | }; | 33 | }; |
54 | 34 | ||
55 | const scrollerThumbOpacity = theme.palette.mode === 'dark' ? 0.16 : 0.28; | ||
56 | |||
57 | const generalStyle: CSSObject = { | 35 | const generalStyle: CSSObject = { |
58 | background: theme.palette.background.default, | 36 | background: theme.palette.background.default, |
59 | '&, .cm-editor': { | 37 | '&, .cm-editor': { |
60 | height: '100%', | 38 | height: '100%', |
61 | }, | 39 | }, |
62 | '.cm-scroller-holder': { | ||
63 | display: 'flex', | ||
64 | position: 'relative', | ||
65 | flexDirection: 'column', | ||
66 | overflow: 'hidden', | ||
67 | flex: '1 1', | ||
68 | }, | ||
69 | '.cm-scroller-spacer': { | ||
70 | position: 'sticky', | ||
71 | flexShrink: 0, | ||
72 | zIndex: 300, | ||
73 | width: 1, | ||
74 | marginRight: -1, | ||
75 | pointerEvents: 'none', | ||
76 | }, | ||
77 | '.cm-scroller': { | 40 | '.cm-scroller': { |
78 | color: theme.palette.text.secondary, | 41 | color: theme.palette.text.secondary, |
79 | scrollbarWidth: 'none', | ||
80 | MsOverflowStyle: 'none', | ||
81 | '&::-webkit-scrollbar': { | ||
82 | width: 0, | ||
83 | height: 0, | ||
84 | background: 'transparent', | ||
85 | }, | ||
86 | }, | ||
87 | '.cm-scroller-track': { | ||
88 | position: 'absolute', | ||
89 | zIndex: 300, | ||
90 | touchAction: 'none', | ||
91 | }, | ||
92 | '.cm-scroller-thumb': { | ||
93 | position: 'absolute', | ||
94 | background: theme.palette.text.secondary, | ||
95 | opacity: scrollerThumbOpacity, | ||
96 | transition: theme.transitions.create('opacity', { | ||
97 | duration: theme.transitions.duration.shortest, | ||
98 | }), | ||
99 | touchAction: 'none', | ||
100 | WebkitTapHighlightColor: 'transparent', | ||
101 | '&:hover': { | ||
102 | opacity: 0.75, | ||
103 | '@media (hover: none)': { | ||
104 | opacity: scrollerThumbOpacity, | ||
105 | }, | ||
106 | }, | ||
107 | '&.active': { | ||
108 | opacity: 1, | ||
109 | pointerEvents: 'none', | ||
110 | userSelect: 'none', | ||
111 | }, | ||
112 | }, | ||
113 | '.cm-scroller-track-y, .cm-scroller-thumb-y': { | ||
114 | top: 0, | ||
115 | right: 0, | ||
116 | width: 12, | ||
117 | }, | ||
118 | '.cm-scroller-track-x, .cm-scroller-thumb-x': { | ||
119 | left: 0, | ||
120 | bottom: 0, | ||
121 | height: 12, | ||
122 | }, | ||
123 | '.cm-scroller-track-x': { | ||
124 | right: 12, | ||
125 | }, | ||
126 | '.cm-scroller-gutter-decoration': { | ||
127 | position: 'absolute', | ||
128 | top: 0, | ||
129 | bottom: 0, | ||
130 | left: 0, | ||
131 | width: 0, | ||
132 | transition: theme.transitions.create('width', { | ||
133 | duration: theme.transitions.duration.shortest, | ||
134 | }), | ||
135 | ...radialShadowTheme('0 50%', true, false), | ||
136 | }, | ||
137 | '.cm-scroller-top-decoration': { | ||
138 | position: 'absolute', | ||
139 | top: 0, | ||
140 | left: 0, | ||
141 | right: 0, | ||
142 | height: 0, | ||
143 | transition: theme.transitions.create('height', { | ||
144 | duration: theme.transitions.duration.shortest, | ||
145 | }), | ||
146 | ...radialShadowTheme('50% 0', false, true), | ||
147 | }, | 42 | }, |
148 | '.cm-gutters': { | 43 | '.cm-gutters': { |
149 | background: theme.palette.background.default, | 44 | background: theme.palette.background.default, |
@@ -162,7 +57,6 @@ export default styled('div', { | |||
162 | background: 'transparent', | 57 | background: 'transparent', |
163 | }, | 58 | }, |
164 | '.cm-cursor, .cm-cursor-primary': { | 59 | '.cm-cursor, .cm-cursor-primary': { |
165 | marginLeft: -1, | ||
166 | borderLeft: `2px solid ${theme.palette.info.main}`, | 60 | borderLeft: `2px solid ${theme.palette.info.main}`, |
167 | }, | 61 | }, |
168 | '.cm-selectionBackground': { | 62 | '.cm-selectionBackground': { |
@@ -175,7 +69,6 @@ export default styled('div', { | |||
175 | }, | 69 | }, |
176 | }, | 70 | }, |
177 | '.cm-line': { | 71 | '.cm-line': { |
178 | position: 'relative', // For indentation highlights | ||
179 | padding: '0 12px 0 0px', | 72 | padding: '0 12px 0 0px', |
180 | }, | 73 | }, |
181 | }; | 74 | }; |
@@ -265,13 +158,6 @@ export default styled('div', { | |||
265 | '.cm-searchMatch-selected': { | 158 | '.cm-searchMatch-selected': { |
266 | background: theme.palette.highlight.search.selected, | 159 | background: theme.palette.highlight.search.selected, |
267 | }, | 160 | }, |
268 | '.cm-indentation-marker': { | ||
269 | display: 'inline-block', | ||
270 | boxShadow: `1px 0 0 ${theme.palette.text.disabled} inset`, | ||
271 | '&.active': { | ||
272 | boxShadow: `1px 0 0 ${theme.palette.text.primary} inset`, | ||
273 | }, | ||
274 | }, | ||
275 | '.cm-scroller-selection': { | 161 | '.cm-scroller-selection': { |
276 | position: 'absolute', | 162 | position: 'absolute', |
277 | right: 0, | 163 | right: 0, |
@@ -452,11 +338,11 @@ export default styled('div', { | |||
452 | 338 | ||
453 | const foldStyle = { | 339 | const foldStyle = { |
454 | '.cm-foldGutter': { | 340 | '.cm-foldGutter': { |
455 | width: 17, | 341 | width: 16, |
456 | }, | 342 | }, |
457 | '.problem-editor-foldMarker': { | 343 | '.problem-editor-foldMarker': { |
458 | display: 'block', | 344 | display: 'block', |
459 | margin: '4px 1px 4px 0', | 345 | margin: '4px 0 4px 0', |
460 | padding: 0, | 346 | padding: 0, |
461 | maskImage: svgURL(expandMoreSVG), | 347 | maskImage: svgURL(expandMoreSVG), |
462 | maskSize: '16px 16px', | 348 | maskSize: '16px 16px', |
@@ -467,7 +353,7 @@ export default styled('div', { | |||
467 | cursor: 'pointer', | 353 | cursor: 'pointer', |
468 | WebkitTapHighlightColor: 'transparent', | 354 | WebkitTapHighlightColor: 'transparent', |
469 | [theme.breakpoints.down('sm')]: { | 355 | [theme.breakpoints.down('sm')]: { |
470 | margin: '2px 1px 2px 0', | 356 | margin: '2px 0 2px 0', |
471 | }, | 357 | }, |
472 | }, | 358 | }, |
473 | '.problem-editor-foldMarker-open': { | 359 | '.problem-editor-foldMarker-open': { |
diff --git a/subprojects/frontend/src/editor/GenerateButton.tsx b/subprojects/frontend/src/editor/GenerateButton.tsx index 2036fc28..3837ef8e 100644 --- a/subprojects/frontend/src/editor/GenerateButton.tsx +++ b/subprojects/frontend/src/editor/GenerateButton.tsx | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import DangerousOutlinedIcon from '@mui/icons-material/DangerousOutlined'; | 7 | import DangerousOutlinedIcon from '@mui/icons-material/DangerousOutlined'; |
2 | import PlayArrowIcon from '@mui/icons-material/PlayArrow'; | 8 | import PlayArrowIcon from '@mui/icons-material/PlayArrow'; |
3 | import Button from '@mui/material/Button'; | 9 | import Button from '@mui/material/Button'; |
diff --git a/subprojects/frontend/src/editor/LintPanelStore.ts b/subprojects/frontend/src/editor/LintPanelStore.ts index 502f9c59..f81587fa 100644 --- a/subprojects/frontend/src/editor/LintPanelStore.ts +++ b/subprojects/frontend/src/editor/LintPanelStore.ts | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import { closeLintPanel, openLintPanel } from '@codemirror/lint'; | 7 | import { closeLintPanel, openLintPanel } from '@codemirror/lint'; |
2 | 8 | ||
3 | import type EditorStore from './EditorStore'; | 9 | import type EditorStore from './EditorStore'; |
diff --git a/subprojects/frontend/src/editor/PanelStore.ts b/subprojects/frontend/src/editor/PanelStore.ts index 4f827280..25ef8b6c 100644 --- a/subprojects/frontend/src/editor/PanelStore.ts +++ b/subprojects/frontend/src/editor/PanelStore.ts | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import type { Command } from '@codemirror/view'; | 7 | import type { Command } from '@codemirror/view'; |
2 | import { action, makeObservable, observable } from 'mobx'; | 8 | import { action, makeObservable, observable } from 'mobx'; |
3 | 9 | ||
diff --git a/subprojects/frontend/src/editor/SearchPanel.ts b/subprojects/frontend/src/editor/SearchPanel.ts index c9df41b7..b63d5eed 100644 --- a/subprojects/frontend/src/editor/SearchPanel.ts +++ b/subprojects/frontend/src/editor/SearchPanel.ts | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import { | 7 | import { |
2 | type EditorView, | 8 | type EditorView, |
3 | type Panel, | 9 | type Panel, |
diff --git a/subprojects/frontend/src/editor/SearchPanelPortal.tsx b/subprojects/frontend/src/editor/SearchPanelPortal.tsx index 5cf1c90e..b4b07c74 100644 --- a/subprojects/frontend/src/editor/SearchPanelPortal.tsx +++ b/subprojects/frontend/src/editor/SearchPanelPortal.tsx | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import Portal from '@mui/material/Portal'; | 7 | import Portal from '@mui/material/Portal'; |
2 | import { observer } from 'mobx-react-lite'; | 8 | import { observer } from 'mobx-react-lite'; |
3 | 9 | ||
diff --git a/subprojects/frontend/src/editor/SearchPanelStore.ts b/subprojects/frontend/src/editor/SearchPanelStore.ts index 65d595a8..6a97baf1 100644 --- a/subprojects/frontend/src/editor/SearchPanelStore.ts +++ b/subprojects/frontend/src/editor/SearchPanelStore.ts | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import { | 7 | import { |
2 | closeSearchPanel, | 8 | closeSearchPanel, |
3 | findNext, | 9 | findNext, |
diff --git a/subprojects/frontend/src/editor/SearchToolbar.tsx b/subprojects/frontend/src/editor/SearchToolbar.tsx index 54f3dba7..4ae7e893 100644 --- a/subprojects/frontend/src/editor/SearchToolbar.tsx +++ b/subprojects/frontend/src/editor/SearchToolbar.tsx | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import CloseIcon from '@mui/icons-material/Close'; | 7 | import CloseIcon from '@mui/icons-material/Close'; |
2 | import FindReplaceIcon from '@mui/icons-material/FindReplace'; | 8 | import FindReplaceIcon from '@mui/icons-material/FindReplace'; |
3 | import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown'; | 9 | import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown'; |
diff --git a/subprojects/frontend/src/editor/createEditorState.ts b/subprojects/frontend/src/editor/createEditorState.ts index ce1efa4f..67b8fb9e 100644 --- a/subprojects/frontend/src/editor/createEditorState.ts +++ b/subprojects/frontend/src/editor/createEditorState.ts | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import { | 7 | import { |
2 | closeBrackets, | 8 | closeBrackets, |
3 | closeBracketsKeymap, | 9 | closeBracketsKeymap, |
@@ -38,8 +44,6 @@ import type EditorStore from './EditorStore'; | |||
38 | import SearchPanel from './SearchPanel'; | 44 | import SearchPanel from './SearchPanel'; |
39 | import exposeDiagnostics from './exposeDiagnostics'; | 45 | import exposeDiagnostics from './exposeDiagnostics'; |
40 | import findOccurrences from './findOccurrences'; | 46 | import findOccurrences from './findOccurrences'; |
41 | import indentationMarkerViewPlugin from './indentationMarkerViewPlugin'; | ||
42 | import scrollbarViewPlugin from './scrollbarViewPlugin'; | ||
43 | import semanticHighlighting from './semanticHighlighting'; | 47 | import semanticHighlighting from './semanticHighlighting'; |
44 | 48 | ||
45 | export default function createEditorState( | 49 | export default function createEditorState( |
@@ -64,7 +68,6 @@ export default function createEditorState( | |||
64 | highlightSpecialChars(), | 68 | highlightSpecialChars(), |
65 | history(), | 69 | history(), |
66 | indentOnInput(), | 70 | indentOnInput(), |
67 | indentationMarkerViewPlugin(), | ||
68 | rectangularSelection(), | 71 | rectangularSelection(), |
69 | search({ | 72 | search({ |
70 | createPanel(view) { | 73 | createPanel(view) { |
@@ -123,7 +126,6 @@ export default function createEditorState( | |||
123 | ...defaultKeymap, | 126 | ...defaultKeymap, |
124 | ]), | 127 | ]), |
125 | problemLanguageSupport(), | 128 | problemLanguageSupport(), |
126 | scrollbarViewPlugin(store), | ||
127 | ], | 129 | ], |
128 | }); | 130 | }); |
129 | } | 131 | } |
diff --git a/subprojects/frontend/src/editor/defineDecorationSetExtension.ts b/subprojects/frontend/src/editor/defineDecorationSetExtension.ts index d9c7bc7d..0887c92e 100644 --- a/subprojects/frontend/src/editor/defineDecorationSetExtension.ts +++ b/subprojects/frontend/src/editor/defineDecorationSetExtension.ts | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import { StateEffect, StateField, TransactionSpec } from '@codemirror/state'; | 7 | import { StateEffect, StateField, TransactionSpec } from '@codemirror/state'; |
2 | import { EditorView, Decoration, DecorationSet } from '@codemirror/view'; | 8 | import { EditorView, Decoration, DecorationSet } from '@codemirror/view'; |
3 | 9 | ||
diff --git a/subprojects/frontend/src/editor/exposeDiagnostics.ts b/subprojects/frontend/src/editor/exposeDiagnostics.ts index 82f24c93..c4dcbb87 100644 --- a/subprojects/frontend/src/editor/exposeDiagnostics.ts +++ b/subprojects/frontend/src/editor/exposeDiagnostics.ts | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import { setDiagnosticsEffect } from '@codemirror/lint'; | 7 | import { setDiagnosticsEffect } from '@codemirror/lint'; |
2 | import { | 8 | import { |
3 | StateField, | 9 | StateField, |
diff --git a/subprojects/frontend/src/editor/findOccurrences.ts b/subprojects/frontend/src/editor/findOccurrences.ts index 08c078c2..00dffc96 100644 --- a/subprojects/frontend/src/editor/findOccurrences.ts +++ b/subprojects/frontend/src/editor/findOccurrences.ts | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import { | 7 | import { |
2 | type Range, | 8 | type Range, |
3 | RangeSet, | 9 | RangeSet, |
diff --git a/subprojects/frontend/src/editor/indentationMarkerViewPlugin.ts b/subprojects/frontend/src/editor/indentationMarkerViewPlugin.ts deleted file mode 100644 index 730fa6e3..00000000 --- a/subprojects/frontend/src/editor/indentationMarkerViewPlugin.ts +++ /dev/null | |||
@@ -1,341 +0,0 @@ | |||
1 | /** | ||
2 | * @file CodeMirror plugin to highlight indentation | ||
3 | * | ||
4 | * This file is based on the | ||
5 | * [@replit/codemirror-indentation-markers](https://github.com/replit/codemirror-indentation-markers) | ||
6 | * package, which is available under the | ||
7 | * [MIT License](https://github.com/replit/codemirror-indentation-markers/blob/543cc508ca5cef5d8350af23973eb1425e31525c/LICENSE). | ||
8 | * | ||
9 | * The highlighting heuristics were adjusted to make them more suitable | ||
10 | * for logic programming. | ||
11 | * | ||
12 | * @see https://github.com/replit/codemirror-indentation-markers/blob/543cc508ca5cef5d8350af23973eb1425e31525c/src/index.ts | ||
13 | */ | ||
14 | |||
15 | import { getIndentUnit } from '@codemirror/language'; | ||
16 | import { Text, RangeSet, EditorState } from '@codemirror/state'; | ||
17 | import { | ||
18 | ViewPlugin, | ||
19 | Decoration, | ||
20 | EditorView, | ||
21 | WidgetType, | ||
22 | PluginValue, | ||
23 | } from '@codemirror/view'; | ||
24 | |||
25 | export const INDENTATION_MARKER_CLASS = 'cm-indentation-marker'; | ||
26 | |||
27 | export const INDENTATION_MARKER_ACTIVE_CLASS = 'active'; | ||
28 | |||
29 | const indentationMark = Decoration.mark({ | ||
30 | class: INDENTATION_MARKER_CLASS, | ||
31 | tagName: 'span', | ||
32 | }); | ||
33 | |||
34 | const activeIndentationMark = Decoration.mark({ | ||
35 | class: `${INDENTATION_MARKER_CLASS} ${INDENTATION_MARKER_ACTIVE_CLASS}`, | ||
36 | tagName: 'span', | ||
37 | }); | ||
38 | |||
39 | /** | ||
40 | * Widget used to simulate N indentation markers on empty lines. | ||
41 | */ | ||
42 | class IndentationWidget extends WidgetType { | ||
43 | constructor( | ||
44 | readonly numIndent: number, | ||
45 | readonly indentSize: number, | ||
46 | readonly activeIndent?: number, | ||
47 | ) { | ||
48 | super(); | ||
49 | } | ||
50 | |||
51 | override eq(other: IndentationWidget) { | ||
52 | return ( | ||
53 | this.numIndent === other.numIndent && | ||
54 | this.indentSize === other.indentSize && | ||
55 | this.activeIndent === other.activeIndent | ||
56 | ); | ||
57 | } | ||
58 | |||
59 | override toDOM(view: EditorView) { | ||
60 | const indentSize = getIndentUnit(view.state); | ||
61 | |||
62 | const wrapper = document.createElement('span'); | ||
63 | wrapper.style.top = '0'; | ||
64 | wrapper.style.left = '0'; | ||
65 | wrapper.style.position = 'absolute'; | ||
66 | wrapper.style.pointerEvents = 'none'; | ||
67 | |||
68 | for (let indent = 0; indent < this.numIndent; indent += 1) { | ||
69 | const element = document.createElement('span'); | ||
70 | element.className = INDENTATION_MARKER_CLASS; | ||
71 | element.classList.toggle( | ||
72 | INDENTATION_MARKER_ACTIVE_CLASS, | ||
73 | indent === this.activeIndent, | ||
74 | ); | ||
75 | element.innerHTML = ' '.repeat(indentSize); | ||
76 | wrapper.appendChild(element); | ||
77 | } | ||
78 | |||
79 | return wrapper; | ||
80 | } | ||
81 | } | ||
82 | |||
83 | /** | ||
84 | * Returns the number of indentation markers a non-empty line should have | ||
85 | * based on the text in the line and the size of the indent. | ||
86 | */ | ||
87 | function getNumIndentMarkersForNonEmptyLine( | ||
88 | text: string, | ||
89 | indentSize: number, | ||
90 | onIndentMarker?: (pos: number) => void, | ||
91 | ) { | ||
92 | let numIndents = 0; | ||
93 | let numConsecutiveSpaces = 0; | ||
94 | let prevChar: string | undefined; | ||
95 | |||
96 | for (let char = 0; char < text.length; char += 1) { | ||
97 | // Bail if we encounter a non-whitespace character | ||
98 | if (text[char] !== ' ' && text[char] !== '\t') { | ||
99 | // We still increment the indentation level if we would | ||
100 | // have added a marker here had this been a space or tab. | ||
101 | if (numConsecutiveSpaces % indentSize === 0 && char !== 0) { | ||
102 | numIndents += 1; | ||
103 | } | ||
104 | |||
105 | return numIndents; | ||
106 | } | ||
107 | |||
108 | // Every tab and N space has an indentation marker | ||
109 | const shouldAddIndent = | ||
110 | prevChar === '\t' || numConsecutiveSpaces % indentSize === 0; | ||
111 | |||
112 | if (shouldAddIndent) { | ||
113 | numIndents += 1; | ||
114 | |||
115 | if (onIndentMarker) { | ||
116 | onIndentMarker(char); | ||
117 | } | ||
118 | } | ||
119 | |||
120 | if (text[char] === ' ') { | ||
121 | numConsecutiveSpaces += 1; | ||
122 | } else { | ||
123 | numConsecutiveSpaces = 0; | ||
124 | } | ||
125 | |||
126 | prevChar = text[char]; | ||
127 | } | ||
128 | |||
129 | return numIndents; | ||
130 | } | ||
131 | |||
132 | /** | ||
133 | * Returns the number of indent markers an empty line should have | ||
134 | * based on the number of indent markers of the previous | ||
135 | * and next non-empty lines. | ||
136 | */ | ||
137 | function getNumIndentMarkersForEmptyLine(prev: number, next: number) { | ||
138 | const min = Math.min(prev, next); | ||
139 | const max = Math.max(prev, next); | ||
140 | |||
141 | // If only one side is non-zero, we omit markers, | ||
142 | // because in logic programming, a block often ends with an empty line. | ||
143 | if (min === 0 && max > 0) { | ||
144 | return 0; | ||
145 | } | ||
146 | |||
147 | // Else, default to the minimum of the two | ||
148 | return min; | ||
149 | } | ||
150 | |||
151 | /** | ||
152 | * Returns the next non-empty line and its indent level. | ||
153 | */ | ||
154 | function findNextNonEmptyLineAndIndentLevel( | ||
155 | doc: Text, | ||
156 | startLine: number, | ||
157 | indentSize: number, | ||
158 | ): [number, number] { | ||
159 | const numLines = doc.lines; | ||
160 | let lineNo = startLine; | ||
161 | |||
162 | while (lineNo <= numLines) { | ||
163 | const { text } = doc.line(lineNo); | ||
164 | |||
165 | if (text.trim().length === 0) { | ||
166 | lineNo += 1; | ||
167 | } else { | ||
168 | const indent = getNumIndentMarkersForNonEmptyLine(text, indentSize); | ||
169 | return [lineNo, indent]; | ||
170 | } | ||
171 | } | ||
172 | |||
173 | // Reached the end of the doc | ||
174 | return [numLines + 1, 0]; | ||
175 | } | ||
176 | |||
177 | interface IndentationMarkerDesc { | ||
178 | lineNumber: number; | ||
179 | from: number; | ||
180 | to: number; | ||
181 | create(activeIndentIndex?: number): Decoration; | ||
182 | } | ||
183 | |||
184 | /** | ||
185 | * Returns a range of lines with an active indent marker. | ||
186 | */ | ||
187 | function getLinesWithActiveIndentMarker( | ||
188 | state: EditorState, | ||
189 | indentMap: Map<number, number>, | ||
190 | ): { start: number; end: number; activeIndent: number } { | ||
191 | const currentLine = state.doc.lineAt(state.selection.main.head); | ||
192 | const currentIndent = indentMap.get(currentLine.number); | ||
193 | const currentLineNo = currentLine.number; | ||
194 | |||
195 | if (!currentIndent) { | ||
196 | return { start: -1, end: -1, activeIndent: NaN }; | ||
197 | } | ||
198 | |||
199 | let start: number; | ||
200 | let end: number; | ||
201 | |||
202 | for (start = currentLineNo; start >= 0; start -= 1) { | ||
203 | const indent = indentMap.get(start - 1); | ||
204 | if (!indent || indent < currentIndent) { | ||
205 | break; | ||
206 | } | ||
207 | } | ||
208 | |||
209 | for (end = currentLineNo; ; end += 1) { | ||
210 | const indent = indentMap.get(end + 1); | ||
211 | if (!indent || indent < currentIndent) { | ||
212 | break; | ||
213 | } | ||
214 | } | ||
215 | |||
216 | return { start, end, activeIndent: currentIndent }; | ||
217 | } | ||
218 | /** | ||
219 | * Adds indentation markers to all lines within view. | ||
220 | */ | ||
221 | function addIndentationMarkers(view: EditorView) { | ||
222 | const indentSize = getIndentUnit(view.state); | ||
223 | const indentSizeMap = new Map</* lineNumber */ number, number>(); | ||
224 | const decorations: Array<IndentationMarkerDesc> = []; | ||
225 | |||
226 | view.visibleRanges.forEach(({ from, to }) => { | ||
227 | let pos = from; | ||
228 | |||
229 | let prevIndentMarkers = 0; | ||
230 | let nextIndentMarkers = 0; | ||
231 | let nextNonEmptyLine = 0; | ||
232 | |||
233 | while (pos <= to) { | ||
234 | const line = view.state.doc.lineAt(pos); | ||
235 | const { text } = line; | ||
236 | |||
237 | // If a line is empty, we match the indentation according | ||
238 | // to a heuristic based on the indentations of the | ||
239 | // previous and next non-empty lines. | ||
240 | if (text.trim().length === 0) { | ||
241 | // To retrieve the next non-empty indentation level, | ||
242 | // we perform a lookahead and cache the result. | ||
243 | if (nextNonEmptyLine < line.number) { | ||
244 | const [nextLine, nextIndent] = findNextNonEmptyLineAndIndentLevel( | ||
245 | view.state.doc, | ||
246 | line.number + 1, | ||
247 | indentSize, | ||
248 | ); | ||
249 | |||
250 | nextNonEmptyLine = nextLine; | ||
251 | nextIndentMarkers = nextIndent; | ||
252 | } | ||
253 | |||
254 | const numIndentMarkers = getNumIndentMarkersForEmptyLine( | ||
255 | prevIndentMarkers, | ||
256 | nextIndentMarkers, | ||
257 | ); | ||
258 | |||
259 | // Add the indent widget and move on to next line | ||
260 | indentSizeMap.set(line.number, numIndentMarkers); | ||
261 | decorations.push({ | ||
262 | from: pos, | ||
263 | to: pos, | ||
264 | lineNumber: line.number, | ||
265 | create: (activeIndentIndex) => | ||
266 | Decoration.widget({ | ||
267 | widget: new IndentationWidget( | ||
268 | numIndentMarkers, | ||
269 | indentSize, | ||
270 | activeIndentIndex, | ||
271 | ), | ||
272 | }), | ||
273 | }); | ||
274 | } else { | ||
275 | const indices: Array<number> = []; | ||
276 | |||
277 | prevIndentMarkers = getNumIndentMarkersForNonEmptyLine( | ||
278 | text, | ||
279 | indentSize, | ||
280 | (char) => indices.push(char), | ||
281 | ); | ||
282 | |||
283 | indentSizeMap.set(line.number, indices.length); | ||
284 | decorations.push( | ||
285 | ...indices.map( | ||
286 | (char, i): IndentationMarkerDesc => ({ | ||
287 | from: line.from + char, | ||
288 | to: line.from + char + 1, | ||
289 | lineNumber: line.number, | ||
290 | create: (activeIndentIndex) => | ||
291 | activeIndentIndex === i | ||
292 | ? activeIndentationMark | ||
293 | : indentationMark, | ||
294 | }), | ||
295 | ), | ||
296 | ); | ||
297 | } | ||
298 | |||
299 | // Move on to the next line | ||
300 | pos = line.to + 1; | ||
301 | } | ||
302 | }); | ||
303 | |||
304 | const activeBlockRange = getLinesWithActiveIndentMarker( | ||
305 | view.state, | ||
306 | indentSizeMap, | ||
307 | ); | ||
308 | |||
309 | return RangeSet.of<Decoration>( | ||
310 | Array.from(decorations).map(({ lineNumber, from, to, create }) => { | ||
311 | const activeIndent = | ||
312 | lineNumber >= activeBlockRange.start && | ||
313 | lineNumber <= activeBlockRange.end | ||
314 | ? activeBlockRange.activeIndent - 1 | ||
315 | : undefined; | ||
316 | |||
317 | return { from, to, value: create(activeIndent) }; | ||
318 | }), | ||
319 | true, | ||
320 | ); | ||
321 | } | ||
322 | |||
323 | export default function indentationMarkerViewPlugin() { | ||
324 | return ViewPlugin.define<PluginValue & { decorations: RangeSet<Decoration> }>( | ||
325 | (view) => ({ | ||
326 | decorations: addIndentationMarkers(view), | ||
327 | update(update) { | ||
328 | if ( | ||
329 | update.docChanged || | ||
330 | update.viewportChanged || | ||
331 | update.selectionSet | ||
332 | ) { | ||
333 | this.decorations = addIndentationMarkers(update.view); | ||
334 | } | ||
335 | }, | ||
336 | }), | ||
337 | { | ||
338 | decorations: (v) => v.decorations, | ||
339 | }, | ||
340 | ); | ||
341 | } | ||
diff --git a/subprojects/frontend/src/editor/scrollbarViewPlugin.ts b/subprojects/frontend/src/editor/scrollbarViewPlugin.ts deleted file mode 100644 index f44034fd..00000000 --- a/subprojects/frontend/src/editor/scrollbarViewPlugin.ts +++ /dev/null | |||
@@ -1,357 +0,0 @@ | |||
1 | import { EditorSelection } from '@codemirror/state'; | ||
2 | import { | ||
3 | type EditorView, | ||
4 | type PluginValue, | ||
5 | ViewPlugin, | ||
6 | } from '@codemirror/view'; | ||
7 | import { reaction } from 'mobx'; | ||
8 | |||
9 | import type EditorStore from './EditorStore'; | ||
10 | import { getDiagnostics } from './exposeDiagnostics'; | ||
11 | import findOccurrences from './findOccurrences'; | ||
12 | |||
13 | export const HOLDER_CLASS = 'cm-scroller-holder'; | ||
14 | export const SPACER_CLASS = 'cm-scroller-spacer'; | ||
15 | export const TRACK_CLASS = 'cm-scroller-track'; | ||
16 | export const THUMB_CLASS = 'cm-scroller-thumb'; | ||
17 | export const THUMB_ACTIVE_CLASS = 'active'; | ||
18 | export const GUTTER_DECORATION_CLASS = 'cm-scroller-gutter-decoration'; | ||
19 | export const TOP_DECORATION_CLASS = 'cm-scroller-top-decoration'; | ||
20 | export const ANNOTATION_SELECTION_CLASS = 'cm-scroller-selection'; | ||
21 | export const ANNOTATION_DIAGNOSTIC_CLASS = 'cm-scroller-diagnostic'; | ||
22 | export const ANNOTATION_OCCURRENCE_CLASS = 'cm-scroller-occurrence'; | ||
23 | export const SHADOW_WIDTH = 10; | ||
24 | export const SCROLLBAR_WIDTH = 12; | ||
25 | export const ANNOTATION_WIDTH = SCROLLBAR_WIDTH / 2; | ||
26 | export const MIN_ANNOTATION_HEIGHT = 1; | ||
27 | |||
28 | function createScrollbar( | ||
29 | holder: HTMLElement, | ||
30 | direction: 'x' | 'y', | ||
31 | touchCallback: (offsetX: number, offsetY: number) => void, | ||
32 | moveCallback: (movementX: number, movementY: number) => void, | ||
33 | ): { track: HTMLElement; thumb: HTMLElement } { | ||
34 | const track = holder.ownerDocument.createElement('div'); | ||
35 | track.className = `${TRACK_CLASS} ${TRACK_CLASS}-${direction}`; | ||
36 | holder.appendChild(track); | ||
37 | |||
38 | const thumb = holder.ownerDocument.createElement('div'); | ||
39 | thumb.className = `${THUMB_CLASS} ${THUMB_CLASS}-${direction}`; | ||
40 | track.appendChild(thumb); | ||
41 | |||
42 | let pointerId: number | undefined; | ||
43 | track.addEventListener('pointerdown', (event) => { | ||
44 | if (pointerId !== undefined) { | ||
45 | event.preventDefault(); | ||
46 | return; | ||
47 | } | ||
48 | ({ pointerId } = event); | ||
49 | thumb.classList.add(THUMB_ACTIVE_CLASS); | ||
50 | if (event.target === thumb) { | ||
51 | // Prevent implicit pointer capture on mobile. | ||
52 | thumb.releasePointerCapture(pointerId); | ||
53 | } else { | ||
54 | touchCallback(event.offsetX, event.offsetY); | ||
55 | } | ||
56 | track.setPointerCapture(pointerId); | ||
57 | }); | ||
58 | |||
59 | track.addEventListener('pointermove', (event) => { | ||
60 | if (event.pointerId !== pointerId) { | ||
61 | return; | ||
62 | } | ||
63 | moveCallback(event.movementX, event.movementY); | ||
64 | event.preventDefault(); | ||
65 | }); | ||
66 | |||
67 | function scrollEnd(event: PointerEvent) { | ||
68 | if (event.pointerId !== pointerId) { | ||
69 | return; | ||
70 | } | ||
71 | pointerId = undefined; | ||
72 | thumb.classList.remove(THUMB_ACTIVE_CLASS); | ||
73 | } | ||
74 | |||
75 | track.addEventListener('pointerup', scrollEnd, { passive: true }); | ||
76 | track.addEventListener('pointercancel', scrollEnd, { passive: true }); | ||
77 | |||
78 | return { track, thumb }; | ||
79 | } | ||
80 | |||
81 | function rebuildAnnotations( | ||
82 | view: EditorView, | ||
83 | scrollHeight: number, | ||
84 | trackYHeight: number, | ||
85 | holder: HTMLElement, | ||
86 | annotations: HTMLDivElement[], | ||
87 | ) { | ||
88 | const { state } = view; | ||
89 | const overlayAnnotationsHeight = | ||
90 | (view.contentHeight / scrollHeight) * trackYHeight; | ||
91 | const lineHeight = overlayAnnotationsHeight / state.doc.lines; | ||
92 | |||
93 | let i = 0; | ||
94 | |||
95 | function getOrCreateAnnotation(from: number, to?: number): HTMLDivElement { | ||
96 | const startLine = state.doc.lineAt(from).number; | ||
97 | const endLine = to === undefined ? startLine : state.doc.lineAt(to).number; | ||
98 | const top = (startLine - 1) * lineHeight; | ||
99 | const height = Math.max( | ||
100 | MIN_ANNOTATION_HEIGHT, | ||
101 | Math.max(1, endLine - startLine) * lineHeight, | ||
102 | ); | ||
103 | |||
104 | let annotation: HTMLDivElement | undefined; | ||
105 | if (i < annotations.length) { | ||
106 | annotation = annotations[i]; | ||
107 | } | ||
108 | if (annotation === undefined) { | ||
109 | annotation = holder.ownerDocument.createElement('div'); | ||
110 | annotations.push(annotation); | ||
111 | holder.appendChild(annotation); | ||
112 | } | ||
113 | i += 1; | ||
114 | |||
115 | annotation.style.top = `${top}px`; | ||
116 | annotation.style.height = `${height}px`; | ||
117 | |||
118 | return annotation; | ||
119 | } | ||
120 | |||
121 | state.selection.ranges.forEach(({ head }) => { | ||
122 | const selectionAnnotation = getOrCreateAnnotation(head); | ||
123 | selectionAnnotation.className = ANNOTATION_SELECTION_CLASS; | ||
124 | selectionAnnotation.style.width = `${SCROLLBAR_WIDTH}px`; | ||
125 | }); | ||
126 | |||
127 | const diagnosticsIter = getDiagnostics(state).iter(); | ||
128 | while (diagnosticsIter.value !== null) { | ||
129 | const diagnosticAnnotation = getOrCreateAnnotation( | ||
130 | diagnosticsIter.from, | ||
131 | diagnosticsIter.to, | ||
132 | ); | ||
133 | diagnosticAnnotation.className = `${ANNOTATION_DIAGNOSTIC_CLASS} ${ANNOTATION_DIAGNOSTIC_CLASS}-${diagnosticsIter.value.severity}`; | ||
134 | diagnosticAnnotation.style.width = `${ANNOTATION_WIDTH}px`; | ||
135 | diagnosticsIter.next(); | ||
136 | } | ||
137 | |||
138 | const occurrences = view.state.field(findOccurrences); | ||
139 | const occurrencesIter = occurrences.iter(); | ||
140 | while (occurrencesIter.value !== null) { | ||
141 | const occurrenceAnnotation = getOrCreateAnnotation( | ||
142 | occurrencesIter.from, | ||
143 | occurrencesIter.to, | ||
144 | ); | ||
145 | occurrenceAnnotation.className = ANNOTATION_OCCURRENCE_CLASS; | ||
146 | occurrenceAnnotation.style.width = `${ANNOTATION_WIDTH}px`; | ||
147 | occurrenceAnnotation.style.right = `${ANNOTATION_WIDTH}px`; | ||
148 | occurrencesIter.next(); | ||
149 | } | ||
150 | |||
151 | annotations | ||
152 | .splice(i) | ||
153 | .forEach((staleAnnotation) => holder.removeChild(staleAnnotation)); | ||
154 | } | ||
155 | |||
156 | export default function scrollbarViewPlugin( | ||
157 | editorStore: EditorStore, | ||
158 | ): ViewPlugin<PluginValue> { | ||
159 | return ViewPlugin.define((view) => { | ||
160 | const { scrollDOM } = view; | ||
161 | const { ownerDocument, parentElement: parentDOM } = scrollDOM; | ||
162 | if (parentDOM === null) { | ||
163 | return {}; | ||
164 | } | ||
165 | |||
166 | const holder = ownerDocument.createElement('div'); | ||
167 | holder.className = HOLDER_CLASS; | ||
168 | parentDOM.replaceChild(holder, scrollDOM); | ||
169 | holder.appendChild(scrollDOM); | ||
170 | |||
171 | const spacer = ownerDocument.createElement('div'); | ||
172 | spacer.className = SPACER_CLASS; | ||
173 | scrollDOM.insertBefore(spacer, scrollDOM.firstChild); | ||
174 | |||
175 | let gutterWidth = 0; | ||
176 | |||
177 | scrollDOM.addEventListener('click', (event) => { | ||
178 | const scrollX = scrollDOM.scrollLeft + event.offsetX; | ||
179 | const scrollY = scrollDOM.scrollTop + event.offsetY; | ||
180 | if (scrollX > gutterWidth && scrollY > view.contentHeight) { | ||
181 | event.preventDefault(); | ||
182 | view.focus(); | ||
183 | editorStore.dispatch({ | ||
184 | scrollIntoView: true, | ||
185 | selection: EditorSelection.create([ | ||
186 | EditorSelection.cursor(view.state.doc.length), | ||
187 | ]), | ||
188 | }); | ||
189 | } | ||
190 | }); | ||
191 | |||
192 | let factorY = 1; | ||
193 | let factorX = 1; | ||
194 | |||
195 | const { track: trackY, thumb: thumbY } = createScrollbar( | ||
196 | holder, | ||
197 | 'y', | ||
198 | (_offsetX, offsetY) => { | ||
199 | const scaledOffset = offsetY / factorY; | ||
200 | const { height: scrollerHeight } = scrollDOM.getBoundingClientRect(); | ||
201 | const target = Math.max(0, scaledOffset - scrollerHeight / 2); | ||
202 | scrollDOM.scrollTo({ top: target }); | ||
203 | }, | ||
204 | (_movementX, movementY) => { | ||
205 | scrollDOM.scrollBy({ top: movementY / factorY }); | ||
206 | }, | ||
207 | ); | ||
208 | |||
209 | const { track: trackX, thumb: thumbX } = createScrollbar( | ||
210 | holder, | ||
211 | 'x', | ||
212 | (offsetX) => { | ||
213 | const scaledOffset = offsetX / factorX; | ||
214 | const { width: scrollerWidth } = scrollDOM.getBoundingClientRect(); | ||
215 | const target = Math.max(0, scaledOffset - scrollerWidth / 2); | ||
216 | scrollDOM.scrollTo({ left: target }); | ||
217 | }, | ||
218 | (movementX) => { | ||
219 | scrollDOM.scrollBy({ left: movementX / factorX }); | ||
220 | }, | ||
221 | ); | ||
222 | |||
223 | const gutterDecoration = ownerDocument.createElement('div'); | ||
224 | gutterDecoration.className = GUTTER_DECORATION_CLASS; | ||
225 | holder.appendChild(gutterDecoration); | ||
226 | |||
227 | const topDecoration = ownerDocument.createElement('div'); | ||
228 | topDecoration.className = TOP_DECORATION_CLASS; | ||
229 | holder.appendChild(topDecoration); | ||
230 | |||
231 | const disposePanelReaction = reaction( | ||
232 | () => editorStore.searchPanel.state, | ||
233 | (panelOpen) => { | ||
234 | topDecoration.style.display = panelOpen ? 'none' : 'block'; | ||
235 | }, | ||
236 | { fireImmediately: true }, | ||
237 | ); | ||
238 | |||
239 | let gutters: Element | undefined; | ||
240 | |||
241 | let firstRun = true; | ||
242 | let firstRunTimeout: number | undefined; | ||
243 | let requested = false; | ||
244 | let rebuildRequested = false; | ||
245 | |||
246 | const annotations: HTMLDivElement[] = []; | ||
247 | |||
248 | let observer: ResizeObserver | undefined; | ||
249 | |||
250 | function update() { | ||
251 | requested = false; | ||
252 | |||
253 | if (gutters === undefined) { | ||
254 | gutters = scrollDOM.querySelector('.cm-gutters') ?? undefined; | ||
255 | if (gutters !== undefined && observer !== undefined) { | ||
256 | observer.observe(gutters); | ||
257 | } | ||
258 | } | ||
259 | |||
260 | const { height: scrollerHeight, width: scrollerWidth } = | ||
261 | scrollDOM.getBoundingClientRect(); | ||
262 | const { scrollTop, scrollLeft, scrollWidth } = scrollDOM; | ||
263 | const scrollHeight = | ||
264 | view.contentHeight + scrollerHeight - view.defaultLineHeight; | ||
265 | if (firstRun) { | ||
266 | if (firstRunTimeout !== undefined) { | ||
267 | clearTimeout(firstRunTimeout); | ||
268 | } | ||
269 | firstRunTimeout = setTimeout(() => { | ||
270 | spacer.style.minHeight = `${scrollHeight}px`; | ||
271 | firstRun = false; | ||
272 | }, 0); | ||
273 | } else { | ||
274 | spacer.style.minHeight = `${scrollHeight}px`; | ||
275 | } | ||
276 | gutterWidth = gutters?.clientWidth ?? 0; | ||
277 | let trackYHeight = scrollerHeight; | ||
278 | |||
279 | // Prevent spurious horizontal scrollbar by rounding up to the nearest pixel. | ||
280 | if (scrollWidth > Math.ceil(scrollerWidth)) { | ||
281 | // Leave space for horizontal scrollbar. | ||
282 | trackYHeight -= SCROLLBAR_WIDTH; | ||
283 | // Alwalys leave space for annotation in the vertical scrollbar. | ||
284 | const trackXWidth = scrollerWidth - gutterWidth - SCROLLBAR_WIDTH; | ||
285 | const thumbWidth = trackXWidth * (scrollerWidth / scrollWidth); | ||
286 | factorX = (trackXWidth - thumbWidth) / (scrollWidth - scrollerWidth); | ||
287 | trackY.style.bottom = `${SCROLLBAR_WIDTH}px`; | ||
288 | trackX.style.display = 'block'; | ||
289 | trackX.style.left = `${gutterWidth}px`; | ||
290 | thumbX.style.width = `${thumbWidth}px`; | ||
291 | thumbX.style.left = `${scrollLeft * factorX}px`; | ||
292 | scrollDOM.style.overflowX = 'scroll'; | ||
293 | } else { | ||
294 | trackY.style.bottom = '0px'; | ||
295 | trackX.style.display = 'none'; | ||
296 | scrollDOM.style.overflowX = 'hidden'; | ||
297 | } | ||
298 | |||
299 | const thumbHeight = trackYHeight * (scrollerHeight / scrollHeight); | ||
300 | factorY = (trackYHeight - thumbHeight) / (scrollHeight - scrollerHeight); | ||
301 | thumbY.style.display = 'block'; | ||
302 | thumbY.style.height = `${thumbHeight}px`; | ||
303 | thumbY.style.top = `${scrollTop * factorY}px`; | ||
304 | |||
305 | gutterDecoration.style.left = `${gutterWidth}px`; | ||
306 | gutterDecoration.style.width = `${Math.max( | ||
307 | 0, | ||
308 | Math.min(scrollLeft, SHADOW_WIDTH), | ||
309 | )}px`; | ||
310 | |||
311 | topDecoration.style.height = `${Math.max( | ||
312 | 0, | ||
313 | Math.min(scrollTop, SHADOW_WIDTH), | ||
314 | )}px`; | ||
315 | |||
316 | if (rebuildRequested) { | ||
317 | rebuildAnnotations( | ||
318 | view, | ||
319 | scrollHeight, | ||
320 | trackYHeight, | ||
321 | holder, | ||
322 | annotations, | ||
323 | ); | ||
324 | rebuildRequested = false; | ||
325 | } | ||
326 | } | ||
327 | |||
328 | function requestUpdate() { | ||
329 | if (!requested) { | ||
330 | requested = true; | ||
331 | view.requestMeasure({ read: update }); | ||
332 | } | ||
333 | } | ||
334 | |||
335 | function requestRebuild() { | ||
336 | requestUpdate(); | ||
337 | rebuildRequested = true; | ||
338 | } | ||
339 | |||
340 | observer = new ResizeObserver(requestRebuild); | ||
341 | observer.observe(holder); | ||
342 | |||
343 | scrollDOM.addEventListener('scroll', requestUpdate); | ||
344 | |||
345 | requestRebuild(); | ||
346 | |||
347 | return { | ||
348 | update: requestRebuild, | ||
349 | destroy() { | ||
350 | disposePanelReaction(); | ||
351 | observer?.disconnect(); | ||
352 | scrollDOM.removeEventListener('scroll', requestUpdate); | ||
353 | parentDOM.replaceChild(holder, holder); | ||
354 | }, | ||
355 | }; | ||
356 | }); | ||
357 | } | ||
diff --git a/subprojects/frontend/src/editor/semanticHighlighting.ts b/subprojects/frontend/src/editor/semanticHighlighting.ts index 2c1bd67d..1f2e564c 100644 --- a/subprojects/frontend/src/editor/semanticHighlighting.ts +++ b/subprojects/frontend/src/editor/semanticHighlighting.ts | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import { RangeSet, type TransactionSpec } from '@codemirror/state'; | 7 | import { RangeSet, type TransactionSpec } from '@codemirror/state'; |
2 | import { Decoration } from '@codemirror/view'; | 8 | import { Decoration } from '@codemirror/view'; |
3 | 9 | ||
diff --git a/subprojects/frontend/src/index.tsx b/subprojects/frontend/src/index.tsx index 29b2b196..cb11e6c3 100644 --- a/subprojects/frontend/src/index.tsx +++ b/subprojects/frontend/src/index.tsx | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import { configure } from 'mobx'; | 7 | import { configure } from 'mobx'; |
2 | import { type Root, createRoot } from 'react-dom/client'; | 8 | import { type Root, createRoot } from 'react-dom/client'; |
3 | 9 | ||
diff --git a/subprojects/frontend/src/language/folding.ts b/subprojects/frontend/src/language/folding.ts index 4dabfa27..b4d4ca22 100644 --- a/subprojects/frontend/src/language/folding.ts +++ b/subprojects/frontend/src/language/folding.ts | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import type { EditorState } from '@codemirror/state'; | 7 | import type { EditorState } from '@codemirror/state'; |
2 | import type { SyntaxNode } from '@lezer/common'; | 8 | import type { SyntaxNode } from '@lezer/common'; |
3 | 9 | ||
diff --git a/subprojects/frontend/src/language/indentation.ts b/subprojects/frontend/src/language/indentation.ts index a0f7032d..8446d7fa 100644 --- a/subprojects/frontend/src/language/indentation.ts +++ b/subprojects/frontend/src/language/indentation.ts | |||
@@ -1,3 +1,10 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2018-2021 by Marijn Haverbeke <marijnh@gmail.com> and others | ||
3 | * Copyright (C) 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
4 | * | ||
5 | * SPDX-License-Identifier: MIT OR EPL-2.0 | ||
6 | */ | ||
7 | |||
1 | import type { TreeIndentContext } from '@codemirror/language'; | 8 | import type { TreeIndentContext } from '@codemirror/language'; |
2 | 9 | ||
3 | /** | 10 | /** |
diff --git a/subprojects/frontend/src/language/problem.grammar b/subprojects/frontend/src/language/problem.grammar index 704badab..a7b1fb0a 100644 --- a/subprojects/frontend/src/language/problem.grammar +++ b/subprojects/frontend/src/language/problem.grammar | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | @detectDelim | 7 | @detectDelim |
2 | 8 | ||
3 | @external prop implicitCompletion from './props' | 9 | @external prop implicitCompletion from './props' |
diff --git a/subprojects/frontend/src/language/problemLanguageSupport.ts b/subprojects/frontend/src/language/problemLanguageSupport.ts index c3ae7ed9..2121e05f 100644 --- a/subprojects/frontend/src/language/problemLanguageSupport.ts +++ b/subprojects/frontend/src/language/problemLanguageSupport.ts | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import { | 7 | import { |
2 | foldInside, | 8 | foldInside, |
3 | foldNodeProp, | 9 | foldNodeProp, |
diff --git a/subprojects/frontend/src/language/props.ts b/subprojects/frontend/src/language/props.ts index 65392e75..aa67145a 100644 --- a/subprojects/frontend/src/language/props.ts +++ b/subprojects/frontend/src/language/props.ts | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | /* eslint-disable import/prefer-default-export -- Lezer needs non-default exports */ | 7 | /* eslint-disable import/prefer-default-export -- Lezer needs non-default exports */ |
2 | 8 | ||
3 | import { NodeProp } from '@lezer/common'; | 9 | import { NodeProp } from '@lezer/common'; |
diff --git a/subprojects/frontend/src/theme/ThemeProvider.tsx b/subprojects/frontend/src/theme/ThemeProvider.tsx index ff97d524..78146f25 100644 --- a/subprojects/frontend/src/theme/ThemeProvider.tsx +++ b/subprojects/frontend/src/theme/ThemeProvider.tsx | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import { | 7 | import { |
2 | alpha, | 8 | alpha, |
3 | createTheme, | 9 | createTheme, |
@@ -69,7 +75,7 @@ function createResponsiveTheme( | |||
69 | ...options, | 75 | ...options, |
70 | typography: { | 76 | typography: { |
71 | fontFamily: | 77 | fontFamily: |
72 | '"InterVariable", "Inter", "Roboto", "Helvetica", "Arial", sans-serif', | 78 | '"Inter Variable", "Inter", "Roboto", "Helvetica", "Arial", sans-serif', |
73 | fontWeightMedium: 600, | 79 | fontWeightMedium: 600, |
74 | fontWeightEditorNormal: 400, | 80 | fontWeightEditorNormal: 400, |
75 | fontWeightEditorBold: 700, | 81 | fontWeightEditorBold: 700, |
@@ -79,7 +85,7 @@ function createResponsiveTheme( | |||
79 | }, | 85 | }, |
80 | editor: { | 86 | editor: { |
81 | fontFamily: | 87 | fontFamily: |
82 | '"JetBrains MonoVariable", "JetBrains Mono", "Cascadia Code", "Fira Code", monospace', | 88 | '"JetBrains Mono Variable", "JetBrains Mono", "Cascadia Code", "Fira Code", monospace', |
83 | fontFeatureSettings: '"liga", "calt"', | 89 | fontFeatureSettings: '"liga", "calt"', |
84 | // `rem` for JetBrains MonoVariable make the text too large in Safari. | 90 | // `rem` for JetBrains MonoVariable make the text too large in Safari. |
85 | fontSize: '16px', | 91 | fontSize: '16px', |
diff --git a/subprojects/frontend/src/theme/ThemeStore.ts b/subprojects/frontend/src/theme/ThemeStore.ts index e09d8d99..7c657449 100644 --- a/subprojects/frontend/src/theme/ThemeStore.ts +++ b/subprojects/frontend/src/theme/ThemeStore.ts | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import { makeAutoObservable } from 'mobx'; | 7 | import { makeAutoObservable } from 'mobx'; |
2 | 8 | ||
3 | export enum ThemePreference { | 9 | export enum ThemePreference { |
diff --git a/subprojects/frontend/src/utils/CancelledError.ts b/subprojects/frontend/src/utils/CancelledError.ts index ee23676f..96b67af7 100644 --- a/subprojects/frontend/src/utils/CancelledError.ts +++ b/subprojects/frontend/src/utils/CancelledError.ts | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | export default class CancelledError extends Error { | 7 | export default class CancelledError extends Error { |
2 | constructor(message = 'Operation cancelled') { | 8 | constructor(message = 'Operation cancelled') { |
3 | super(message); | 9 | super(message); |
diff --git a/subprojects/frontend/src/utils/PendingTask.ts b/subprojects/frontend/src/utils/PendingTask.ts index d0b24c1f..80d1a346 100644 --- a/subprojects/frontend/src/utils/PendingTask.ts +++ b/subprojects/frontend/src/utils/PendingTask.ts | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import TimeoutError from './TimeoutError'; | 7 | import TimeoutError from './TimeoutError'; |
2 | import getLogger from './getLogger'; | 8 | import getLogger from './getLogger'; |
3 | 9 | ||
diff --git a/subprojects/frontend/src/utils/PriorityMutex.ts b/subprojects/frontend/src/utils/PriorityMutex.ts index 78736141..c1215c76 100644 --- a/subprojects/frontend/src/utils/PriorityMutex.ts +++ b/subprojects/frontend/src/utils/PriorityMutex.ts | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import CancelledError from './CancelledError'; | 7 | import CancelledError from './CancelledError'; |
2 | import PendingTask from './PendingTask'; | 8 | import PendingTask from './PendingTask'; |
3 | import getLogger from './getLogger'; | 9 | import getLogger from './getLogger'; |
diff --git a/subprojects/frontend/src/utils/TimeoutError.ts b/subprojects/frontend/src/utils/TimeoutError.ts index eb800f40..21365502 100644 --- a/subprojects/frontend/src/utils/TimeoutError.ts +++ b/subprojects/frontend/src/utils/TimeoutError.ts | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | export default class TimeoutError extends Error { | 7 | export default class TimeoutError extends Error { |
2 | constructor() { | 8 | constructor() { |
3 | super('Operation timed out'); | 9 | super('Operation timed out'); |
diff --git a/subprojects/frontend/src/utils/getLogger.ts b/subprojects/frontend/src/utils/getLogger.ts index 301fd76d..09b0b17f 100644 --- a/subprojects/frontend/src/utils/getLogger.ts +++ b/subprojects/frontend/src/utils/getLogger.ts | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import styles, { type CSPair } from 'ansi-styles'; | 7 | import styles, { type CSPair } from 'ansi-styles'; |
2 | import log from 'loglevel'; | 8 | import log from 'loglevel'; |
3 | import prefix from 'loglevel-plugin-prefix'; | 9 | import prefix from 'loglevel-plugin-prefix'; |
diff --git a/subprojects/frontend/src/utils/useDelayedSnackbar.ts b/subprojects/frontend/src/utils/useDelayedSnackbar.ts index 03ad6caa..3d6df3e3 100644 --- a/subprojects/frontend/src/utils/useDelayedSnackbar.ts +++ b/subprojects/frontend/src/utils/useDelayedSnackbar.ts | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import { | 7 | import { |
2 | useSnackbar, | 8 | useSnackbar, |
3 | type SnackbarKey, | 9 | type SnackbarKey, |
diff --git a/subprojects/frontend/src/xtext/BackendConfig.ts b/subprojects/frontend/src/xtext/BackendConfig.ts index 41737c0b..4c7eac5f 100644 --- a/subprojects/frontend/src/xtext/BackendConfig.ts +++ b/subprojects/frontend/src/xtext/BackendConfig.ts | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | /* eslint-disable @typescript-eslint/no-redeclare -- Declare types with their companion objects */ | 7 | /* eslint-disable @typescript-eslint/no-redeclare -- Declare types with their companion objects */ |
2 | 8 | ||
3 | import { z } from 'zod'; | 9 | import { z } from 'zod'; |
diff --git a/subprojects/frontend/src/xtext/ContentAssistService.ts b/subprojects/frontend/src/xtext/ContentAssistService.ts index 78f61c06..fd30c4f9 100644 --- a/subprojects/frontend/src/xtext/ContentAssistService.ts +++ b/subprojects/frontend/src/xtext/ContentAssistService.ts | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import type { | 7 | import type { |
2 | Completion, | 8 | Completion, |
3 | CompletionContext, | 9 | CompletionContext, |
diff --git a/subprojects/frontend/src/xtext/HighlightingService.ts b/subprojects/frontend/src/xtext/HighlightingService.ts index a126ee40..447f1401 100644 --- a/subprojects/frontend/src/xtext/HighlightingService.ts +++ b/subprojects/frontend/src/xtext/HighlightingService.ts | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import type EditorStore from '../editor/EditorStore'; | 7 | import type EditorStore from '../editor/EditorStore'; |
2 | import type { IHighlightRange } from '../editor/semanticHighlighting'; | 8 | import type { IHighlightRange } from '../editor/semanticHighlighting'; |
3 | 9 | ||
diff --git a/subprojects/frontend/src/xtext/OccurrencesService.ts b/subprojects/frontend/src/xtext/OccurrencesService.ts index fc72ead2..c9c6c699 100644 --- a/subprojects/frontend/src/xtext/OccurrencesService.ts +++ b/subprojects/frontend/src/xtext/OccurrencesService.ts | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import type { Transaction } from '@codemirror/state'; | 7 | import type { Transaction } from '@codemirror/state'; |
2 | import { debounce } from 'lodash-es'; | 8 | import { debounce } from 'lodash-es'; |
3 | import ms from 'ms'; | 9 | import ms from 'ms'; |
diff --git a/subprojects/frontend/src/xtext/UpdateService.ts b/subprojects/frontend/src/xtext/UpdateService.ts index 63e28652..ee5ebde2 100644 --- a/subprojects/frontend/src/xtext/UpdateService.ts +++ b/subprojects/frontend/src/xtext/UpdateService.ts | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import type { ChangeDesc, Transaction } from '@codemirror/state'; | 7 | import type { ChangeDesc, Transaction } from '@codemirror/state'; |
2 | import { debounce } from 'lodash-es'; | 8 | import { debounce } from 'lodash-es'; |
3 | import { nanoid } from 'nanoid'; | 9 | import { nanoid } from 'nanoid'; |
diff --git a/subprojects/frontend/src/xtext/UpdateStateTracker.ts b/subprojects/frontend/src/xtext/UpdateStateTracker.ts index 5d4ce49e..4ce93ed6 100644 --- a/subprojects/frontend/src/xtext/UpdateStateTracker.ts +++ b/subprojects/frontend/src/xtext/UpdateStateTracker.ts | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import { | 7 | import { |
2 | type ChangeDesc, | 8 | type ChangeDesc, |
3 | ChangeSet, | 9 | ChangeSet, |
diff --git a/subprojects/frontend/src/xtext/ValidationService.ts b/subprojects/frontend/src/xtext/ValidationService.ts index 72414590..64fb63eb 100644 --- a/subprojects/frontend/src/xtext/ValidationService.ts +++ b/subprojects/frontend/src/xtext/ValidationService.ts | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import type { Diagnostic } from '@codemirror/lint'; | 7 | import type { Diagnostic } from '@codemirror/lint'; |
2 | 8 | ||
3 | import type EditorStore from '../editor/EditorStore'; | 9 | import type EditorStore from '../editor/EditorStore'; |
diff --git a/subprojects/frontend/src/xtext/XtextClient.ts b/subprojects/frontend/src/xtext/XtextClient.ts index 14fb2430..e8181af0 100644 --- a/subprojects/frontend/src/xtext/XtextClient.ts +++ b/subprojects/frontend/src/xtext/XtextClient.ts | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import type { | 7 | import type { |
2 | CompletionContext, | 8 | CompletionContext, |
3 | CompletionResult, | 9 | CompletionResult, |
diff --git a/subprojects/frontend/src/xtext/XtextWebSocketClient.ts b/subprojects/frontend/src/xtext/XtextWebSocketClient.ts index 6b734546..6bb7eec8 100644 --- a/subprojects/frontend/src/xtext/XtextWebSocketClient.ts +++ b/subprojects/frontend/src/xtext/XtextWebSocketClient.ts | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import { createAtom, makeAutoObservable, observable } from 'mobx'; | 7 | import { createAtom, makeAutoObservable, observable } from 'mobx'; |
2 | import ms from 'ms'; | 8 | import ms from 'ms'; |
3 | import { nanoid } from 'nanoid'; | 9 | import { nanoid } from 'nanoid'; |
diff --git a/subprojects/frontend/src/xtext/fetchBackendConfig.ts b/subprojects/frontend/src/xtext/fetchBackendConfig.ts index 15e976d8..71ff2e63 100644 --- a/subprojects/frontend/src/xtext/fetchBackendConfig.ts +++ b/subprojects/frontend/src/xtext/fetchBackendConfig.ts | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import BackendConfig, { ENDPOINT } from './BackendConfig'; | 7 | import BackendConfig, { ENDPOINT } from './BackendConfig'; |
2 | 8 | ||
3 | export default async function fetchBackendConfig(): Promise<BackendConfig> { | 9 | export default async function fetchBackendConfig(): Promise<BackendConfig> { |
diff --git a/subprojects/frontend/src/xtext/webSocketMachine.ts b/subprojects/frontend/src/xtext/webSocketMachine.ts index fc53fef3..2fb1f52f 100644 --- a/subprojects/frontend/src/xtext/webSocketMachine.ts +++ b/subprojects/frontend/src/xtext/webSocketMachine.ts | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import ms from 'ms'; | 7 | import ms from 'ms'; |
2 | import { actions, assign, createMachine } from 'xstate'; | 8 | import { actions, assign, createMachine } from 'xstate'; |
3 | 9 | ||
diff --git a/subprojects/frontend/src/xtext/xtextMessages.ts b/subprojects/frontend/src/xtext/xtextMessages.ts index ec7a2a31..bbbff064 100644 --- a/subprojects/frontend/src/xtext/xtextMessages.ts +++ b/subprojects/frontend/src/xtext/xtextMessages.ts | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | /* eslint-disable @typescript-eslint/no-redeclare -- Declare types with their companion objects */ | 7 | /* eslint-disable @typescript-eslint/no-redeclare -- Declare types with their companion objects */ |
2 | 8 | ||
3 | import { z } from 'zod'; | 9 | import { z } from 'zod'; |
diff --git a/subprojects/frontend/src/xtext/xtextServiceResults.ts b/subprojects/frontend/src/xtext/xtextServiceResults.ts index e93c6714..d3b467ad 100644 --- a/subprojects/frontend/src/xtext/xtextServiceResults.ts +++ b/subprojects/frontend/src/xtext/xtextServiceResults.ts | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | /* eslint-disable @typescript-eslint/no-redeclare -- Declare types with their companion objects */ | 7 | /* eslint-disable @typescript-eslint/no-redeclare -- Declare types with their companion objects */ |
2 | 8 | ||
3 | import { z } from 'zod'; | 9 | import { z } from 'zod'; |
diff --git a/subprojects/frontend/tsconfig.base.json b/subprojects/frontend/tsconfig.base.json index b960e93c..5ef50b5e 100644 --- a/subprojects/frontend/tsconfig.base.json +++ b/subprojects/frontend/tsconfig.base.json | |||
@@ -1,10 +1,41 @@ | |||
1 | /* | ||
2 | * Copyright (c) Microsoft Corporation. | ||
3 | * Copyright (c) 2023 The Refinery Authors <https://refinery.tools/> | ||
4 | * | ||
5 | * SPDX-License-Identifier: MIT OR EPL-2.0 | ||
6 | * | ||
7 | * This file is based on | ||
8 | * https://github.com/tsconfig/bases/blob/7db25a41bc5a9c0f66d91f6f3aa28438afcb2f18/bases/strictest.json | ||
9 | * but we moved it inside the project for better tooling support. | ||
10 | */ | ||
1 | { | 11 | { |
2 | "extends": "@tsconfig/strictest", | ||
3 | "compilerOptions": { | 12 | "compilerOptions": { |
4 | "useDefineForClassFields": true, | 13 | "strict": true, |
5 | "verbatimModuleSyntax": false, | 14 | "allowUnusedLabels": false, |
15 | "allowUnreachableCode": false, | ||
16 | "exactOptionalPropertyTypes": true, | ||
17 | "noFallthroughCasesInSwitch": true, | ||
18 | "noImplicitOverride": true, | ||
19 | "noImplicitReturns": true, | ||
20 | "noPropertyAccessFromIndexSignature": true, | ||
21 | "noUncheckedIndexedAccess": true, | ||
22 | "noUnusedLocals": true, | ||
23 | "noUnusedParameters": true, | ||
24 | // "verbatimModuleSyntax" is incompatible with `import` syntax in modules | ||
25 | // with CommonJS import resolution, so we use "isolatedModules" only. | ||
26 | // "verbatimModuleSyntax": false, | ||
6 | "isolatedModules": true, | 27 | "isolatedModules": true, |
28 | "checkJs": true, | ||
29 | "esModuleInterop": true, | ||
30 | "skipLibCheck": true, | ||
31 | "forceConsistentCasingInFileNames": true, | ||
32 | "useDefineForClassFields": true, | ||
33 | // Project-specific configuration below. | ||
7 | "module": "es2022", | 34 | "module": "es2022", |
8 | "moduleResolution": "node" | 35 | "moduleResolution": "node", |
36 | "incremental": true, | ||
37 | "declaration": true, | ||
38 | "emitDeclarationOnly": true, | ||
39 | "outDir": "build/typescript" | ||
9 | } | 40 | } |
10 | } | 41 | } |
diff --git a/subprojects/frontend/tsconfig.json b/subprojects/frontend/tsconfig.json index 35abd789..06f6d8fe 100644 --- a/subprojects/frontend/tsconfig.json +++ b/subprojects/frontend/tsconfig.json | |||
@@ -1,8 +1,12 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | { | 6 | { |
2 | "extends": "./tsconfig.base.json", | 7 | "extends": "./tsconfig.base.json", |
3 | "compilerOptions": { | 8 | "compilerOptions": { |
4 | "jsx": "react-jsx", | 9 | "jsx": "react-jsx", |
5 | "noEmit": true, | ||
6 | "lib": ["DOM", "DOM.Iterable", "ES2022"], | 10 | "lib": ["DOM", "DOM.Iterable", "ES2022"], |
7 | "types": ["vite/client", "vite-plugin-pwa/client"] | 11 | "types": ["vite/client", "vite-plugin-pwa/client"] |
8 | }, | 12 | }, |
diff --git a/subprojects/frontend/tsconfig.node.json b/subprojects/frontend/tsconfig.node.json index f4908bcb..47feaf97 100644 --- a/subprojects/frontend/tsconfig.node.json +++ b/subprojects/frontend/tsconfig.node.json | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | { | 6 | { |
2 | "extends": "./tsconfig.base.json", | 7 | "extends": "./tsconfig.base.json", |
3 | "compilerOptions": { | 8 | "compilerOptions": { |
@@ -10,6 +15,7 @@ | |||
10 | "include": [ | 15 | "include": [ |
11 | ".eslintrc.cjs", | 16 | ".eslintrc.cjs", |
12 | "config/*.ts", | 17 | "config/*.ts", |
18 | "config/*.cjs", | ||
13 | "prettier.config.cjs", | 19 | "prettier.config.cjs", |
14 | "types/node", | 20 | "types/node", |
15 | "vite.config.ts" | 21 | "vite.config.ts" |
diff --git a/subprojects/frontend/tsconfig.shared.json b/subprojects/frontend/tsconfig.shared.json index b7e1de55..154fe122 100644 --- a/subprojects/frontend/tsconfig.shared.json +++ b/subprojects/frontend/tsconfig.shared.json | |||
@@ -1,13 +1,16 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | { | 6 | { |
2 | "extends": "./tsconfig.base.json", | 7 | "extends": "./tsconfig.base.json", |
3 | "compilerOptions": { | 8 | "compilerOptions": { |
4 | "composite": true, | 9 | "composite": true, |
5 | "lib": ["ES2022"], | 10 | "lib": ["ES2022"], |
6 | "types": [], | 11 | "types": [], |
7 | "emitDeclarationOnly": true, | ||
8 | "outDir": "build/typescript" | ||
9 | }, | 12 | }, |
10 | "include": [ | 13 | "include": [ |
11 | "src/xtext/BackendConfig.ts", | 14 | "src/xtext/BackendConfig.ts" |
12 | ] | 15 | ] |
13 | } | 16 | } |
diff --git a/subprojects/frontend/types/ImportMeta.d.ts b/subprojects/frontend/types/ImportMeta.d.ts index c32b48f5..f5a32ef1 100644 --- a/subprojects/frontend/types/ImportMeta.d.ts +++ b/subprojects/frontend/types/ImportMeta.d.ts | |||
@@ -1,3 +1,10 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2019-present, Yuxi (Evan) You and Vite contributors | ||
3 | * Copyright (c) 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
4 | * | ||
5 | * SPDX-License-Identifier: MIT OR EPL-2.0 | ||
6 | */ | ||
7 | |||
1 | interface ImportMeta { | 8 | interface ImportMeta { |
2 | env: { | 9 | env: { |
3 | BASE_URL: string; | 10 | BASE_URL: string; |
diff --git a/subprojects/frontend/types/grammar.d.ts b/subprojects/frontend/types/grammar.d.ts index 1480085b..e7a7eebf 100644 --- a/subprojects/frontend/types/grammar.d.ts +++ b/subprojects/frontend/types/grammar.d.ts | |||
@@ -1,3 +1,10 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2018 by Marijn Haverbeke <marijn@haverbeke.berlin> and others | ||
3 | * Copyright (C) 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
4 | * | ||
5 | * SPDX-License-Identifier: MIT OR EPL-2.0 | ||
6 | */ | ||
7 | |||
1 | declare module '*.grammar' { | 8 | declare module '*.grammar' { |
2 | import type { LRParser } from '@lezer/lr'; | 9 | import type { LRParser } from '@lezer/lr'; |
3 | 10 | ||
diff --git a/subprojects/frontend/types/node/@lezer-generator-rollup.d.ts b/subprojects/frontend/types/node/@lezer-generator-rollup.d.ts index 9c1ff03e..4ef9f4e3 100644 --- a/subprojects/frontend/types/node/@lezer-generator-rollup.d.ts +++ b/subprojects/frontend/types/node/@lezer-generator-rollup.d.ts | |||
@@ -1,3 +1,10 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2018 by Marijn Haverbeke <marijn@haverbeke.berlin> and others | ||
3 | * Copyright (C) 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
4 | * | ||
5 | * SPDX-License-Identifier: MIT OR EPL-2.0 | ||
6 | */ | ||
7 | |||
1 | // We have to explicitly redeclare the type of the `./rollup` ESM export of `@lezer/generator`, | 8 | // We have to explicitly redeclare the type of the `./rollup` ESM export of `@lezer/generator`, |
2 | // because TypeScript can't find it on its own even with `"moduleResolution": "Node16"`. | 9 | // because TypeScript can't find it on its own even with `"moduleResolution": "Node16"`. |
3 | declare module '@lezer/generator/rollup' { | 10 | declare module '@lezer/generator/rollup' { |
diff --git a/subprojects/frontend/types/windowControlsOverlay.d.ts b/subprojects/frontend/types/windowControlsOverlay.d.ts index d8f3182f..2513d620 100644 --- a/subprojects/frontend/types/windowControlsOverlay.d.ts +++ b/subprojects/frontend/types/windowControlsOverlay.d.ts | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | interface WindowControlsOverlayGeometryChangeEvent extends Event { | 7 | interface WindowControlsOverlayGeometryChangeEvent extends Event { |
2 | titlebarAreaRect: DOMRect; | 8 | titlebarAreaRect: DOMRect; |
3 | 9 | ||
diff --git a/subprojects/frontend/vite.config.ts b/subprojects/frontend/vite.config.ts index cd9993cc..9e08ccc4 100644 --- a/subprojects/frontend/vite.config.ts +++ b/subprojects/frontend/vite.config.ts | |||
@@ -1,3 +1,9 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
1 | import path from 'node:path'; | 7 | import path from 'node:path'; |
2 | import { fileURLToPath } from 'node:url'; | 8 | import { fileURLToPath } from 'node:url'; |
3 | 9 | ||
diff --git a/subprojects/language-ide/build.gradle b/subprojects/language-ide/build.gradle deleted file mode 100644 index 3786762b..00000000 --- a/subprojects/language-ide/build.gradle +++ /dev/null | |||
@@ -1,18 +0,0 @@ | |||
1 | plugins { | ||
2 | id 'refinery-java-library' | ||
3 | id 'refinery-xtext-conventions' | ||
4 | } | ||
5 | |||
6 | dependencies { | ||
7 | api project(':refinery-language') | ||
8 | api libs.xtext.ide | ||
9 | api libs.xtext.xbase.ide | ||
10 | } | ||
11 | |||
12 | def generateXtextLanguage = project(':refinery-language').tasks.named('generateXtextLanguage') | ||
13 | |||
14 | for (taskName in ['compileJava', 'processResources']) { | ||
15 | tasks.named(taskName) { | ||
16 | dependsOn generateXtextLanguage | ||
17 | } | ||
18 | } | ||
diff --git a/subprojects/language-ide/build.gradle.kts b/subprojects/language-ide/build.gradle.kts new file mode 100644 index 00000000..1259cd67 --- /dev/null +++ b/subprojects/language-ide/build.gradle.kts | |||
@@ -0,0 +1,18 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
7 | plugins { | ||
8 | id("tools.refinery.gradle.java-library") | ||
9 | id("tools.refinery.gradle.xtext-generated") | ||
10 | } | ||
11 | |||
12 | dependencies { | ||
13 | api(project(":refinery-language")) | ||
14 | api(libs.xtext.ide) | ||
15 | api(libs.xtext.xbase.ide) | ||
16 | xtextGenerated(project(":refinery-language", "generatedIdeSources")) | ||
17 | } | ||
18 | |||
diff --git a/subprojects/language-ide/src/main/java/tools/refinery/language/ide/ProblemIdeModule.java b/subprojects/language-ide/src/main/java/tools/refinery/language/ide/ProblemIdeModule.java index fb620065..122fe874 100644 --- a/subprojects/language-ide/src/main/java/tools/refinery/language/ide/ProblemIdeModule.java +++ b/subprojects/language-ide/src/main/java/tools/refinery/language/ide/ProblemIdeModule.java | |||
@@ -1,4 +1,10 @@ | |||
1 | /* | 1 | /* |
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
7 | /* | ||
2 | * generated by Xtext 2.25.0 | 8 | * generated by Xtext 2.25.0 |
3 | */ | 9 | */ |
4 | package tools.refinery.language.ide; | 10 | package tools.refinery.language.ide; |
diff --git a/subprojects/language-ide/src/main/java/tools/refinery/language/ide/ProblemIdeSetup.java b/subprojects/language-ide/src/main/java/tools/refinery/language/ide/ProblemIdeSetup.java index 5b88d41f..9d77e022 100644 --- a/subprojects/language-ide/src/main/java/tools/refinery/language/ide/ProblemIdeSetup.java +++ b/subprojects/language-ide/src/main/java/tools/refinery/language/ide/ProblemIdeSetup.java | |||
@@ -1,4 +1,10 @@ | |||
1 | /* | 1 | /* |
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
7 | /* | ||
2 | * generated by Xtext 2.25.0 | 8 | * generated by Xtext 2.25.0 |
3 | */ | 9 | */ |
4 | package tools.refinery.language.ide; | 10 | package tools.refinery.language.ide; |
diff --git a/subprojects/language-ide/src/main/java/tools/refinery/language/ide/contentassist/FuzzyMatcher.java b/subprojects/language-ide/src/main/java/tools/refinery/language/ide/contentassist/FuzzyMatcher.java index fe722ca1..4511223b 100644 --- a/subprojects/language-ide/src/main/java/tools/refinery/language/ide/contentassist/FuzzyMatcher.java +++ b/subprojects/language-ide/src/main/java/tools/refinery/language/ide/contentassist/FuzzyMatcher.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.ide.contentassist; | 6 | package tools.refinery.language.ide.contentassist; |
2 | 7 | ||
3 | import org.eclipse.xtext.ide.editor.contentassist.IPrefixMatcher; | 8 | import org.eclipse.xtext.ide.editor.contentassist.IPrefixMatcher; |
diff --git a/subprojects/language-ide/src/main/java/tools/refinery/language/ide/contentassist/ProblemCrossrefProposalProvider.java b/subprojects/language-ide/src/main/java/tools/refinery/language/ide/contentassist/ProblemCrossrefProposalProvider.java index 8f04ed00..e194ee31 100644 --- a/subprojects/language-ide/src/main/java/tools/refinery/language/ide/contentassist/ProblemCrossrefProposalProvider.java +++ b/subprojects/language-ide/src/main/java/tools/refinery/language/ide/contentassist/ProblemCrossrefProposalProvider.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.ide.contentassist; | 6 | package tools.refinery.language.ide.contentassist; |
2 | 7 | ||
3 | import java.util.Objects; | 8 | import java.util.Objects; |
diff --git a/subprojects/language-ide/src/main/java/tools/refinery/language/ide/contentassist/TokenSourceInjectingPartialProblemContentAssistParser.java b/subprojects/language-ide/src/main/java/tools/refinery/language/ide/contentassist/TokenSourceInjectingPartialProblemContentAssistParser.java index 3ece6f67..146bd8da 100644 --- a/subprojects/language-ide/src/main/java/tools/refinery/language/ide/contentassist/TokenSourceInjectingPartialProblemContentAssistParser.java +++ b/subprojects/language-ide/src/main/java/tools/refinery/language/ide/contentassist/TokenSourceInjectingPartialProblemContentAssistParser.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.ide.contentassist; | 6 | package tools.refinery.language.ide.contentassist; |
2 | 7 | ||
3 | import com.google.inject.Inject; | 8 | import com.google.inject.Inject; |
diff --git a/subprojects/language-ide/src/main/java/tools/refinery/language/ide/contentassist/TokenSourceInjectingProblemParser.java b/subprojects/language-ide/src/main/java/tools/refinery/language/ide/contentassist/TokenSourceInjectingProblemParser.java index 80dfee5c..f906d881 100644 --- a/subprojects/language-ide/src/main/java/tools/refinery/language/ide/contentassist/TokenSourceInjectingProblemParser.java +++ b/subprojects/language-ide/src/main/java/tools/refinery/language/ide/contentassist/TokenSourceInjectingProblemParser.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.ide.contentassist; | 6 | package tools.refinery.language.ide.contentassist; |
2 | 7 | ||
3 | import com.google.inject.Inject; | 8 | import com.google.inject.Inject; |
diff --git a/subprojects/language-ide/src/main/java/tools/refinery/language/ide/contentassist/antlr/ProblemTokenSource.java b/subprojects/language-ide/src/main/java/tools/refinery/language/ide/contentassist/antlr/ProblemTokenSource.java index c6c7f41f..fdc17c4f 100644 --- a/subprojects/language-ide/src/main/java/tools/refinery/language/ide/contentassist/antlr/ProblemTokenSource.java +++ b/subprojects/language-ide/src/main/java/tools/refinery/language/ide/contentassist/antlr/ProblemTokenSource.java | |||
@@ -1,4 +1,10 @@ | |||
1 | /* | 1 | /* |
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
7 | /* | ||
2 | * generated by Xtext 2.29.0.M2 | 8 | * generated by Xtext 2.29.0.M2 |
3 | */ | 9 | */ |
4 | package tools.refinery.language.ide.contentassist.antlr; | 10 | package tools.refinery.language.ide.contentassist.antlr; |
diff --git a/subprojects/language-ide/src/main/java/tools/refinery/language/ide/syntaxcoloring/ProblemSemanticHighlightingCalculator.java b/subprojects/language-ide/src/main/java/tools/refinery/language/ide/syntaxcoloring/ProblemSemanticHighlightingCalculator.java index 7703e4e3..e8f97d51 100644 --- a/subprojects/language-ide/src/main/java/tools/refinery/language/ide/syntaxcoloring/ProblemSemanticHighlightingCalculator.java +++ b/subprojects/language-ide/src/main/java/tools/refinery/language/ide/syntaxcoloring/ProblemSemanticHighlightingCalculator.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.ide.syntaxcoloring; | 6 | package tools.refinery.language.ide.syntaxcoloring; |
2 | 7 | ||
3 | import com.google.common.collect.ImmutableList; | 8 | import com.google.common.collect.ImmutableList; |
diff --git a/subprojects/language-model/META-INF/MANIFEST.MF.license b/subprojects/language-model/META-INF/MANIFEST.MF.license new file mode 100644 index 00000000..e5db6ccd --- /dev/null +++ b/subprojects/language-model/META-INF/MANIFEST.MF.license | |||
@@ -0,0 +1,3 @@ | |||
1 | SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
2 | |||
3 | SPDX-License-Identifier: EPL-2.0 | ||
diff --git a/subprojects/language-model/build.gradle b/subprojects/language-model/build.gradle deleted file mode 100644 index 275db188..00000000 --- a/subprojects/language-model/build.gradle +++ /dev/null | |||
@@ -1,55 +0,0 @@ | |||
1 | plugins { | ||
2 | id 'refinery-java-library' | ||
3 | id 'refinery-mwe2' | ||
4 | id 'refinery-sonarqube' | ||
5 | } | ||
6 | |||
7 | dependencies { | ||
8 | api libs.ecore | ||
9 | api libs.ecore.xmi | ||
10 | mwe2 libs.ecore.codegen | ||
11 | mwe2 libs.mwe.utils | ||
12 | mwe2 libs.mwe2.lib | ||
13 | mwe2 libs.xtext.core | ||
14 | mwe2 libs.xtext.xbase | ||
15 | } | ||
16 | |||
17 | sourceSets { | ||
18 | main { | ||
19 | java.srcDirs += ['src/main/emf-gen'] | ||
20 | } | ||
21 | } | ||
22 | |||
23 | def generateEPackage = tasks.register('generateEPackage', JavaExec) { | ||
24 | mainClass = 'org.eclipse.emf.mwe2.launch.runtime.Mwe2Launcher' | ||
25 | classpath = configurations.mwe2 | ||
26 | inputs.file 'src/main/java/tools/refinery/language/model/GenerateProblemModel.mwe2' | ||
27 | inputs.file 'src/main/resources/model/problem.ecore' | ||
28 | inputs.file 'src/main/resources/model/problem.genmodel' | ||
29 | outputs.dir 'src/main/emf-gen' | ||
30 | args += 'src/main/java/tools/refinery/language/model/GenerateProblemModel.mwe2' | ||
31 | args += '-p' | ||
32 | args += "rootPath=/${projectDir}" | ||
33 | } | ||
34 | |||
35 | for (taskName in ['compileJava', 'processResources', 'generateEclipseSourceFolders']) { | ||
36 | tasks.named(taskName) { | ||
37 | dependsOn generateEPackage | ||
38 | } | ||
39 | } | ||
40 | |||
41 | tasks.named('clean') { | ||
42 | delete 'src/main/emf-gen' | ||
43 | } | ||
44 | |||
45 | sonarqube.properties { | ||
46 | properties['sonar.exclusions'] += [ | ||
47 | 'src/main/emf-gen/**', | ||
48 | ] | ||
49 | } | ||
50 | |||
51 | eclipse.project.natures += [ | ||
52 | 'org.eclipse.sirius.nature.modelingproject', | ||
53 | 'org.eclipse.pde.PluginNature', | ||
54 | 'org.eclipse.xtext.ui.shared.xtextNature' | ||
55 | ] | ||
diff --git a/subprojects/language-model/build.gradle.kts b/subprojects/language-model/build.gradle.kts new file mode 100644 index 00000000..59ff9046 --- /dev/null +++ b/subprojects/language-model/build.gradle.kts | |||
@@ -0,0 +1,65 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
7 | import tools.refinery.gradle.utils.SonarPropertiesUtils | ||
8 | |||
9 | plugins { | ||
10 | id("tools.refinery.gradle.java-library") | ||
11 | id("tools.refinery.gradle.mwe2") | ||
12 | id("tools.refinery.gradle.sonarqube") | ||
13 | } | ||
14 | |||
15 | dependencies { | ||
16 | api(libs.ecore) | ||
17 | api(libs.ecore.xmi) | ||
18 | mwe2(libs.ecore.codegen) | ||
19 | mwe2(libs.mwe.utils) | ||
20 | mwe2(libs.mwe2.lib) | ||
21 | mwe2(libs.xtext.core) | ||
22 | mwe2(libs.xtext.xbase) | ||
23 | } | ||
24 | |||
25 | sourceSets { | ||
26 | main { | ||
27 | java.srcDir("src/main/emf-gen") | ||
28 | } | ||
29 | } | ||
30 | |||
31 | tasks { | ||
32 | val generateEPackage by registering(JavaExec::class) { | ||
33 | mainClass.set("org.eclipse.emf.mwe2.launch.runtime.Mwe2Launcher") | ||
34 | classpath(configurations.mwe2) | ||
35 | inputs.file("src/main/java/tools/refinery/language/model/GenerateProblemModel.mwe2") | ||
36 | inputs.file("src/main/resources/model/problem.ecore") | ||
37 | inputs.file("src/main/resources/model/problem.genmodel") | ||
38 | outputs.file("build.properties") | ||
39 | outputs.file("META-INF/MANIFEST.MF") | ||
40 | outputs.file("plugin.xml") | ||
41 | outputs.file("plugin.properties") | ||
42 | outputs.dir("src/main/emf-gen") | ||
43 | args("src/main/java/tools/refinery/language/model/GenerateProblemModel.mwe2", "-p", "rootPath=/$projectDir") | ||
44 | } | ||
45 | |||
46 | for (taskName in listOf("compileJava", "processResources", "generateEclipseSourceFolders")) { | ||
47 | named(taskName) { | ||
48 | dependsOn(generateEPackage) | ||
49 | } | ||
50 | } | ||
51 | |||
52 | clean { | ||
53 | delete("src/main/emf-gen") | ||
54 | } | ||
55 | } | ||
56 | |||
57 | sonarqube.properties { | ||
58 | SonarPropertiesUtils.addToList(properties, "sonar.exclusions", "src/main/emf-gen/**") | ||
59 | } | ||
60 | |||
61 | eclipse.project.natures.plusAssign(listOf( | ||
62 | "org.eclipse.sirius.nature.modelingproject", | ||
63 | "org.eclipse.pde.PluginNature", | ||
64 | "org.eclipse.xtext.ui.shared.xtextNature", | ||
65 | )) | ||
diff --git a/subprojects/language-model/build.properties b/subprojects/language-model/build.properties index 65dfc7c4..9b9859ff 100644 --- a/subprojects/language-model/build.properties +++ b/subprojects/language-model/build.properties | |||
@@ -1,4 +1,6 @@ | |||
1 | # SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
1 | # | 2 | # |
3 | # SPDX-License-Identifier: EPL-2.0 | ||
2 | 4 | ||
3 | bin.includes = .,\ | 5 | bin.includes = .,\ |
4 | src/main/resources/model/,\ | 6 | src/main/resources/model/,\ |
diff --git a/subprojects/language-model/plugin.properties b/subprojects/language-model/plugin.properties index c4fb7e23..c410feb7 100644 --- a/subprojects/language-model/plugin.properties +++ b/subprojects/language-model/plugin.properties | |||
@@ -1,4 +1,6 @@ | |||
1 | # SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
1 | # | 2 | # |
3 | # SPDX-License-Identifier: EPL-2.0 | ||
2 | 4 | ||
3 | pluginName = tools.refinery.language.model | 5 | pluginName = tools.refinery.language.model |
4 | providerName = refinery.tools | 6 | providerName = refinery.tools |
diff --git a/subprojects/language-model/plugin.xml b/subprojects/language-model/plugin.xml index 4ca005a8..ef1e21f4 100644 --- a/subprojects/language-model/plugin.xml +++ b/subprojects/language-model/plugin.xml | |||
@@ -2,6 +2,9 @@ | |||
2 | <?eclipse version="3.0"?> | 2 | <?eclipse version="3.0"?> |
3 | 3 | ||
4 | <!-- | 4 | <!-- |
5 | SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
6 | |||
7 | SPDX-License-Identifier: EPL-2.0 | ||
5 | --> | 8 | --> |
6 | 9 | ||
7 | <plugin> | 10 | <plugin> |
diff --git a/subprojects/language-model/problem.aird.license b/subprojects/language-model/problem.aird.license new file mode 100644 index 00000000..e5db6ccd --- /dev/null +++ b/subprojects/language-model/problem.aird.license | |||
@@ -0,0 +1,3 @@ | |||
1 | SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
2 | |||
3 | SPDX-License-Identifier: EPL-2.0 | ||
diff --git a/subprojects/language-model/src/main/java/tools/refinery/language/model/GenerateProblemModel.mwe2 b/subprojects/language-model/src/main/java/tools/refinery/language/model/GenerateProblemModel.mwe2 index 15198d69..074b6b71 100644 --- a/subprojects/language-model/src/main/java/tools/refinery/language/model/GenerateProblemModel.mwe2 +++ b/subprojects/language-model/src/main/java/tools/refinery/language/model/GenerateProblemModel.mwe2 | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | module tools.refinery.language.model.GenerateProblemModel | 6 | module tools.refinery.language.model.GenerateProblemModel |
2 | 7 | ||
3 | Workflow { | 8 | Workflow { |
diff --git a/subprojects/language-model/src/main/resources/model/problem.ecore.license b/subprojects/language-model/src/main/resources/model/problem.ecore.license new file mode 100644 index 00000000..e5db6ccd --- /dev/null +++ b/subprojects/language-model/src/main/resources/model/problem.ecore.license | |||
@@ -0,0 +1,3 @@ | |||
1 | SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
2 | |||
3 | SPDX-License-Identifier: EPL-2.0 | ||
diff --git a/subprojects/language-model/src/main/resources/model/problem.genmodel.license b/subprojects/language-model/src/main/resources/model/problem.genmodel.license new file mode 100644 index 00000000..e5db6ccd --- /dev/null +++ b/subprojects/language-model/src/main/resources/model/problem.genmodel.license | |||
@@ -0,0 +1,3 @@ | |||
1 | SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
2 | |||
3 | SPDX-License-Identifier: EPL-2.0 | ||
diff --git a/subprojects/language-semantics/build.gradle b/subprojects/language-semantics/build.gradle deleted file mode 100644 index 4f43ad24..00000000 --- a/subprojects/language-semantics/build.gradle +++ /dev/null | |||
@@ -1,11 +0,0 @@ | |||
1 | plugins { | ||
2 | id 'refinery-java-library' | ||
3 | } | ||
4 | |||
5 | dependencies { | ||
6 | implementation libs.eclipseCollections | ||
7 | implementation libs.eclipseCollections.api | ||
8 | api project(':refinery-language') | ||
9 | api project(':refinery-store') | ||
10 | testImplementation testFixtures(project(':refinery-language')) | ||
11 | } | ||
diff --git a/subprojects/language-semantics/build.gradle.kts b/subprojects/language-semantics/build.gradle.kts new file mode 100644 index 00000000..38cd9e0d --- /dev/null +++ b/subprojects/language-semantics/build.gradle.kts | |||
@@ -0,0 +1,17 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
7 | plugins { | ||
8 | id("tools.refinery.gradle.java-library") | ||
9 | } | ||
10 | |||
11 | dependencies { | ||
12 | implementation(libs.eclipseCollections) | ||
13 | implementation(libs.eclipseCollections.api) | ||
14 | api(project(":refinery-language")) | ||
15 | api(project(":refinery-store")) | ||
16 | testImplementation(testFixtures(project(":refinery-language"))) | ||
17 | } | ||
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/ModelInitializer.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/ModelInitializer.java index a6712a89..06b8ad77 100644 --- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/ModelInitializer.java +++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/ModelInitializer.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.semantics.model; | 6 | package tools.refinery.language.semantics.model; |
2 | 7 | ||
3 | import com.google.inject.Inject; | 8 | import com.google.inject.Inject; |
@@ -39,8 +44,8 @@ public class ModelInitializer { | |||
39 | var isEqualsRelation = relation == builtinSymbols.equals(); | 44 | var isEqualsRelation = relation == builtinSymbols.equals(); |
40 | var decisionTree = mergeAssertions(relationInfo, isEqualsRelation); | 45 | var decisionTree = mergeAssertions(relationInfo, isEqualsRelation); |
41 | var defaultValue = isEqualsRelation ? TruthValue.FALSE : TruthValue.UNKNOWN; | 46 | var defaultValue = isEqualsRelation ? TruthValue.FALSE : TruthValue.UNKNOWN; |
42 | relationTrace.put(relation, new Symbol<>(relationInfo.name(), relationInfo.arity(), TruthValue.class, defaultValue | 47 | relationTrace.put(relation, Symbol.of( |
43 | )); | 48 | relationInfo.name(), relationInfo.arity(), TruthValue.class, defaultValue)); |
44 | } | 49 | } |
45 | } | 50 | } |
46 | 51 | ||
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTree.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTree.java index 55edee6d..c1afecf9 100644 --- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTree.java +++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTree.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.semantics.model.internal; | 6 | package tools.refinery.language.semantics.model.internal; |
2 | 7 | ||
3 | import org.eclipse.collections.api.factory.primitive.IntObjectMaps; | 8 | import org.eclipse.collections.api.factory.primitive.IntObjectMaps; |
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTreeCursor.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTreeCursor.java index fdf8e452..9a1e15a3 100644 --- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTreeCursor.java +++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTreeCursor.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.semantics.model.internal; | 6 | package tools.refinery.language.semantics.model.internal; |
2 | 7 | ||
3 | import tools.refinery.store.map.Cursor; | 8 | import tools.refinery.store.map.Cursor; |
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTreeNode.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTreeNode.java index b81ea3fe..3c54e3c5 100644 --- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTreeNode.java +++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTreeNode.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.semantics.model.internal; | 6 | package tools.refinery.language.semantics.model.internal; |
2 | 7 | ||
3 | import org.eclipse.collections.api.LazyIntIterable; | 8 | import org.eclipse.collections.api.LazyIntIterable; |
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTreeValue.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTreeValue.java index 495a53dd..915ae2bf 100644 --- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTreeValue.java +++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/DecisionTreeValue.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.semantics.model.internal; | 6 | package tools.refinery.language.semantics.model.internal; |
2 | 7 | ||
3 | import tools.refinery.store.representation.TruthValue; | 8 | import tools.refinery.store.representation.TruthValue; |
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/IntermediateNode.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/IntermediateNode.java index c4200509..e6f01d48 100644 --- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/IntermediateNode.java +++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/IntermediateNode.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.semantics.model.internal; | 6 | package tools.refinery.language.semantics.model.internal; |
2 | 7 | ||
3 | import org.eclipse.collections.api.LazyIntIterable; | 8 | import org.eclipse.collections.api.LazyIntIterable; |
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/TerminalNode.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/TerminalNode.java index 4af836ff..ce49aa62 100644 --- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/TerminalNode.java +++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/model/internal/TerminalNode.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.semantics.model.internal; | 6 | package tools.refinery.language.semantics.model.internal; |
2 | 7 | ||
3 | import org.eclipse.collections.api.LazyIntIterable; | 8 | import org.eclipse.collections.api.LazyIntIterable; |
diff --git a/subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/model/tests/DecisionTreeTests.java b/subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/model/tests/DecisionTreeTests.java index 4630bf53..b3fcbabb 100644 --- a/subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/model/tests/DecisionTreeTests.java +++ b/subprojects/language-semantics/src/test/java/tools/refinery/language/semantics/model/tests/DecisionTreeTests.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.semantics.model.tests; | 6 | package tools.refinery.language.semantics.model.tests; |
2 | 7 | ||
3 | import org.junit.jupiter.api.Test; | 8 | import org.junit.jupiter.api.Test; |
diff --git a/subprojects/language-web/build.gradle b/subprojects/language-web/build.gradle deleted file mode 100644 index 8d277a5b..00000000 --- a/subprojects/language-web/build.gradle +++ /dev/null | |||
@@ -1,87 +0,0 @@ | |||
1 | plugins { | ||
2 | id 'refinery-java-application' | ||
3 | id 'refinery-xtext-conventions' | ||
4 | } | ||
5 | |||
6 | configurations { | ||
7 | webapp { | ||
8 | canBeConsumed = false | ||
9 | canBeResolved = true | ||
10 | } | ||
11 | |||
12 | all { | ||
13 | // Use log4j-over-slf4j instead of log4j 1.x | ||
14 | exclude group: 'log4j', module: 'log4j' | ||
15 | } | ||
16 | } | ||
17 | |||
18 | dependencies { | ||
19 | implementation project(':refinery-language') | ||
20 | implementation project(':refinery-language-ide') | ||
21 | implementation libs.jetty.server | ||
22 | implementation libs.jetty.servlet | ||
23 | implementation libs.jetty.websocket.server | ||
24 | implementation libs.slf4j.api | ||
25 | implementation libs.slf4j.simple | ||
26 | implementation libs.slf4j.log4j | ||
27 | implementation libs.xtext.web | ||
28 | webapp project(path: ':refinery-frontend', configuration: 'productionAssets') | ||
29 | testImplementation testFixtures(project(':refinery-language')) | ||
30 | testImplementation libs.jetty.websocket.client | ||
31 | } | ||
32 | |||
33 | def generateXtextLanguage = project(':refinery-language').tasks.named('generateXtextLanguage') | ||
34 | |||
35 | for (taskName in ['compileJava', 'processResources']) { | ||
36 | tasks.named(taskName) { | ||
37 | dependsOn generateXtextLanguage | ||
38 | } | ||
39 | } | ||
40 | |||
41 | mainClassName = 'tools.refinery.language.web.ServerLauncher' | ||
42 | |||
43 | // Enable JDK 19 preview features for virtual thread support. | ||
44 | application { | ||
45 | applicationDefaultJvmArgs += '--enable-preview' | ||
46 | } | ||
47 | tasks.withType(JavaCompile) { | ||
48 | options.release = 19 | ||
49 | options.compilerArgs += '--enable-preview' | ||
50 | } | ||
51 | tasks.withType(Test) { | ||
52 | jvmArgs += '--enable-preview' | ||
53 | } | ||
54 | |||
55 | tasks.named('jar') { | ||
56 | dependsOn project.configurations.webapp | ||
57 | from(project.configurations.webapp) { | ||
58 | into 'webapp' | ||
59 | } | ||
60 | } | ||
61 | |||
62 | tasks.named('shadowJar') { | ||
63 | dependsOn project.configurations.webapp | ||
64 | from(project.sourceSets.main.output) | ||
65 | configurations = [project.configurations.runtimeClasspath] | ||
66 | exclude('META-INF/INDEX.LIST', 'META-INF/*.SF', 'META-INF/*.DSA', 'META-INF/*.RSA','schema/*', | ||
67 | '.options', '.api_description', '*.profile', 'about.*', 'about_*.html', 'about_files/*', | ||
68 | 'plugin.xml', 'systembundle.properties', 'profile.list', 'META-INF/resources/xtext/**') | ||
69 | append('plugin.properties') | ||
70 | from(project.configurations.webapp) { | ||
71 | into 'webapp' | ||
72 | } | ||
73 | } | ||
74 | |||
75 | tasks.register('serveBackend', JavaExec) { | ||
76 | dependsOn project.configurations.webapp | ||
77 | dependsOn sourceSets.main.runtimeClasspath | ||
78 | classpath = sourceSets.main.runtimeClasspath | ||
79 | mainClass = mainClassName | ||
80 | // Enable JDK 19 preview features for virtual thread support. | ||
81 | jvmArgs += '--enable-preview' | ||
82 | standardInput = System.in | ||
83 | def baseResource = project.configurations.webapp.incoming.artifacts.artifactFiles.first() | ||
84 | environment BASE_RESOURCE: baseResource | ||
85 | group = 'run' | ||
86 | description = 'Start a Jetty web server serving the Xtex API and assets.' | ||
87 | } | ||
diff --git a/subprojects/language-web/build.gradle.kts b/subprojects/language-web/build.gradle.kts new file mode 100644 index 00000000..562a1bd9 --- /dev/null +++ b/subprojects/language-web/build.gradle.kts | |||
@@ -0,0 +1,68 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
7 | plugins { | ||
8 | id("tools.refinery.gradle.java-application") | ||
9 | id("tools.refinery.gradle.xtext-generated") | ||
10 | } | ||
11 | |||
12 | val webapp: Configuration by configurations.creating { | ||
13 | isCanBeConsumed = false | ||
14 | isCanBeResolved = true | ||
15 | } | ||
16 | |||
17 | dependencies { | ||
18 | implementation(project(":refinery-language")) | ||
19 | implementation(project(":refinery-language-ide")) | ||
20 | implementation(libs.jetty.server) | ||
21 | implementation(libs.jetty.servlet) | ||
22 | implementation(libs.jetty.websocket.api) | ||
23 | implementation(libs.jetty.websocket.server) | ||
24 | implementation(libs.slf4j.api) | ||
25 | implementation(libs.xtext.web) | ||
26 | xtextGenerated(project(":refinery-language", "generatedWebSources")) | ||
27 | webapp(project(":refinery-frontend", "productionAssets")) | ||
28 | testImplementation(testFixtures(project(":refinery-language"))) | ||
29 | testImplementation(libs.jetty.websocket.client) | ||
30 | } | ||
31 | |||
32 | application { | ||
33 | mainClass.set("tools.refinery.language.web.ServerLauncher") | ||
34 | } | ||
35 | |||
36 | tasks { | ||
37 | jar { | ||
38 | dependsOn(webapp) | ||
39 | from(webapp) { | ||
40 | into("webapp") | ||
41 | } | ||
42 | } | ||
43 | |||
44 | shadowJar { | ||
45 | dependsOn(webapp) | ||
46 | from(project.sourceSets.main.map { it.output }) | ||
47 | exclude("META-INF/INDEX.LIST", "META-INF/*.SF", "META-INF/*.DSA", "META-INF/*.RSA", "schema/*", | ||
48 | ".options", ".api_description", "*.profile", "about.*", "about_*.html", "about_files/*", | ||
49 | "plugin.xml", "systembundle.properties", "profile.list", "META-INF/resources/xtext/**") | ||
50 | append("plugin.properties") | ||
51 | from(webapp) { | ||
52 | into("webapp") | ||
53 | } | ||
54 | } | ||
55 | |||
56 | register<JavaExec>("serveBackend") { | ||
57 | dependsOn(webapp) | ||
58 | val mainRuntimeClasspath = sourceSets.main.map { it.runtimeClasspath } | ||
59 | dependsOn(mainRuntimeClasspath) | ||
60 | classpath(mainRuntimeClasspath) | ||
61 | mainClass.set(application.mainClass) | ||
62 | standardInput = System.`in` | ||
63 | val baseResource = webapp.incoming.artifacts.artifactFiles.first() | ||
64 | environment("BASE_RESOURCE", baseResource) | ||
65 | group = "run" | ||
66 | description = "Start a Jetty web server serving the Xtex API and assets." | ||
67 | } | ||
68 | } | ||
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/CacheControlFilter.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/CacheControlFilter.java index fd2af1b2..53f78c3c 100644 --- a/subprojects/language-web/src/main/java/tools/refinery/language/web/CacheControlFilter.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/CacheControlFilter.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.web; | 6 | package tools.refinery.language.web; |
2 | 7 | ||
3 | import jakarta.servlet.*; | 8 | import jakarta.servlet.*; |
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/ProblemWebModule.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/ProblemWebModule.java index 706413a9..b0197c01 100644 --- a/subprojects/language-web/src/main/java/tools/refinery/language/web/ProblemWebModule.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/ProblemWebModule.java | |||
@@ -1,15 +1,19 @@ | |||
1 | /* | 1 | /* |
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
7 | /* | ||
2 | * generated by Xtext 2.25.0 | 8 | * generated by Xtext 2.25.0 |
3 | */ | 9 | */ |
4 | package tools.refinery.language.web; | 10 | package tools.refinery.language.web; |
5 | 11 | ||
6 | import org.eclipse.xtext.ide.ExecutorServiceProvider; | ||
7 | import org.eclipse.xtext.web.server.XtextServiceDispatcher; | 12 | import org.eclipse.xtext.web.server.XtextServiceDispatcher; |
8 | import org.eclipse.xtext.web.server.model.IWebDocumentProvider; | 13 | import org.eclipse.xtext.web.server.model.IWebDocumentProvider; |
9 | import org.eclipse.xtext.web.server.model.XtextWebDocumentAccess; | 14 | import org.eclipse.xtext.web.server.model.XtextWebDocumentAccess; |
10 | import org.eclipse.xtext.web.server.occurrences.OccurrencesService; | 15 | import org.eclipse.xtext.web.server.occurrences.OccurrencesService; |
11 | import tools.refinery.language.web.occurrences.ProblemOccurrencesService; | 16 | import tools.refinery.language.web.occurrences.ProblemOccurrencesService; |
12 | import tools.refinery.language.web.xtext.VirtualThreadExecutorServiceProvider; | ||
13 | import tools.refinery.language.web.xtext.server.push.PushServiceDispatcher; | 17 | import tools.refinery.language.web.xtext.server.push.PushServiceDispatcher; |
14 | import tools.refinery.language.web.xtext.server.push.PushWebDocumentAccess; | 18 | import tools.refinery.language.web.xtext.server.push.PushWebDocumentAccess; |
15 | import tools.refinery.language.web.xtext.server.push.PushWebDocumentProvider; | 19 | import tools.refinery.language.web.xtext.server.push.PushWebDocumentProvider; |
@@ -33,8 +37,4 @@ public class ProblemWebModule extends AbstractProblemWebModule { | |||
33 | public Class<? extends OccurrencesService> bindOccurrencesService() { | 37 | public Class<? extends OccurrencesService> bindOccurrencesService() { |
34 | return ProblemOccurrencesService.class; | 38 | return ProblemOccurrencesService.class; |
35 | } | 39 | } |
36 | |||
37 | public Class<? extends ExecutorServiceProvider> bindExecutorServiceProvider() { | ||
38 | return VirtualThreadExecutorServiceProvider.class; | ||
39 | } | ||
40 | } | 40 | } |
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/ProblemWebSetup.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/ProblemWebSetup.java index 4738bc80..53a394d8 100644 --- a/subprojects/language-web/src/main/java/tools/refinery/language/web/ProblemWebSetup.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/ProblemWebSetup.java | |||
@@ -1,4 +1,10 @@ | |||
1 | /* | 1 | /* |
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
7 | /* | ||
2 | * generated by Xtext 2.25.0 | 8 | * generated by Xtext 2.25.0 |
3 | */ | 9 | */ |
4 | package tools.refinery.language.web; | 10 | package tools.refinery.language.web; |
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/ProblemWebSocketServlet.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/ProblemWebSocketServlet.java index df67b521..7b48cde8 100644 --- a/subprojects/language-web/src/main/java/tools/refinery/language/web/ProblemWebSocketServlet.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/ProblemWebSocketServlet.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.web; | 6 | package tools.refinery.language.web; |
2 | 7 | ||
3 | import org.eclipse.xtext.util.DisposableRegistry; | 8 | import org.eclipse.xtext.util.DisposableRegistry; |
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/SecurityHeadersFilter.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/SecurityHeadersFilter.java index c41db799..7b094fde 100644 --- a/subprojects/language-web/src/main/java/tools/refinery/language/web/SecurityHeadersFilter.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/SecurityHeadersFilter.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.web; | 6 | package tools.refinery.language.web; |
2 | 7 | ||
3 | import jakarta.servlet.*; | 8 | import jakarta.servlet.*; |
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/ServerLauncher.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/ServerLauncher.java index f49f46ee..ad19e77d 100644 --- a/subprojects/language-web/src/main/java/tools/refinery/language/web/ServerLauncher.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/ServerLauncher.java | |||
@@ -1,4 +1,10 @@ | |||
1 | /* | 1 | /* |
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
7 | /* | ||
2 | * generated by Xtext 2.25.0 | 8 | * generated by Xtext 2.25.0 |
3 | */ | 9 | */ |
4 | package tools.refinery.language.web; | 10 | package tools.refinery.language.web; |
@@ -13,6 +19,7 @@ import org.eclipse.jetty.ee10.websocket.server.config.JettyWebSocketServletConta | |||
13 | import org.eclipse.jetty.server.Server; | 19 | import org.eclipse.jetty.server.Server; |
14 | import org.eclipse.jetty.util.resource.Resource; | 20 | import org.eclipse.jetty.util.resource.Resource; |
15 | import org.eclipse.jetty.util.resource.ResourceFactory; | 21 | import org.eclipse.jetty.util.resource.ResourceFactory; |
22 | import org.eclipse.jetty.util.thread.QueuedThreadPool; | ||
16 | import org.slf4j.Logger; | 23 | import org.slf4j.Logger; |
17 | import org.slf4j.LoggerFactory; | 24 | import org.slf4j.LoggerFactory; |
18 | import tools.refinery.language.web.config.BackendConfigServlet; | 25 | import tools.refinery.language.web.config.BackendConfigServlet; |
@@ -43,7 +50,8 @@ public class ServerLauncher { | |||
43 | private final Server server; | 50 | private final Server server; |
44 | 51 | ||
45 | public ServerLauncher(InetSocketAddress bindAddress, String[] allowedOrigins, String webSocketUrl) { | 52 | public ServerLauncher(InetSocketAddress bindAddress, String[] allowedOrigins, String webSocketUrl) { |
46 | server = VirtualThreadUtils.newServerWithVirtualThreadsThreadPool("jetty", bindAddress); | 53 | server = new Server(bindAddress); |
54 | ((QueuedThreadPool) server.getThreadPool()).setName("jetty"); | ||
47 | var handler = new ServletContextHandler(); | 55 | var handler = new ServletContextHandler(); |
48 | addSessionHandler(handler); | 56 | addSessionHandler(handler); |
49 | addProblemServlet(handler, allowedOrigins); | 57 | addProblemServlet(handler, allowedOrigins); |
@@ -105,7 +113,7 @@ public class ServerLauncher { | |||
105 | var indexUrlInJar = ServerLauncher.class.getResource("/webapp/index.html"); | 113 | var indexUrlInJar = ServerLauncher.class.getResource("/webapp/index.html"); |
106 | if (indexUrlInJar != null) { | 114 | if (indexUrlInJar != null) { |
107 | // If the app is packaged in the jar, serve it. | 115 | // If the app is packaged in the jar, serve it. |
108 | URI webRootUri = null; | 116 | URI webRootUri; |
109 | try { | 117 | try { |
110 | webRootUri = URI.create(indexUrlInJar.toURI().toASCIIString().replaceFirst("/index.html$", "/")); | 118 | webRootUri = URI.create(indexUrlInJar.toURI().toASCIIString().replaceFirst("/index.html$", "/")); |
111 | } catch (URISyntaxException e) { | 119 | } catch (URISyntaxException e) { |
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/VirtualThreadUtils.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/VirtualThreadUtils.java deleted file mode 100644 index a055e755..00000000 --- a/subprojects/language-web/src/main/java/tools/refinery/language/web/VirtualThreadUtils.java +++ /dev/null | |||
@@ -1,52 +0,0 @@ | |||
1 | package tools.refinery.language.web; | ||
2 | |||
3 | import org.eclipse.jetty.server.Server; | ||
4 | import org.eclipse.jetty.server.ServerConnector; | ||
5 | import org.eclipse.jetty.util.thread.QueuedThreadPool; | ||
6 | import org.eclipse.jetty.util.thread.ThreadPool; | ||
7 | |||
8 | import java.net.InetSocketAddress; | ||
9 | import java.time.Duration; | ||
10 | import java.util.concurrent.ExecutorService; | ||
11 | import java.util.concurrent.Executors; | ||
12 | |||
13 | public final class VirtualThreadUtils { | ||
14 | private VirtualThreadUtils() { | ||
15 | throw new IllegalStateException("This is a static utility class and should not be instantiated directly"); | ||
16 | } | ||
17 | |||
18 | public static ExecutorService newNamedVirtualThreadsExecutor(String name) { | ||
19 | // Based on | ||
20 | // https://github.com/eclipse/jetty.project/blob/83154b4ffe4767ef44981598d6c26e6a5d32e57c/jetty-server/src/main/config/etc/jetty-threadpool-virtual-preview.xml | ||
21 | return Executors.newThreadPerTaskExecutor(Thread.ofVirtual() | ||
22 | .allowSetThreadLocals(true) | ||
23 | .inheritInheritableThreadLocals(false) | ||
24 | .name(name + "-virtual-", 0) | ||
25 | .factory()); | ||
26 | } | ||
27 | |||
28 | public static ThreadPool newThreadPoolWithVirtualThreadsExecutor(String name) { | ||
29 | // Based on | ||
30 | // https://github.com/eclipse/jetty.project/blob/83154b4ffe4767ef44981598d6c26e6a5d32e57c/jetty-server/src/main/config/etc/jetty-threadpool-virtual-preview.xml | ||
31 | int timeout = (int) Duration.ofMinutes(1).toMillis(); | ||
32 | var threadPool = new QueuedThreadPool(200, 10, timeout, -1, null, null); | ||
33 | threadPool.setName(name); | ||
34 | threadPool.setDetailedDump(false); | ||
35 | threadPool.setVirtualThreadsExecutor(newNamedVirtualThreadsExecutor(name)); | ||
36 | return threadPool; | ||
37 | } | ||
38 | |||
39 | public static Server newServerWithVirtualThreadsThreadPool(String name, InetSocketAddress listenAddress) { | ||
40 | var server = new Server(newThreadPoolWithVirtualThreadsExecutor(name)); | ||
41 | var connector = new ServerConnector(server); | ||
42 | try { | ||
43 | connector.setHost(listenAddress.getHostName()); | ||
44 | connector.setPort(listenAddress.getPort()); | ||
45 | server.addConnector(connector); | ||
46 | } catch (Exception e) { | ||
47 | connector.close(); | ||
48 | throw e; | ||
49 | } | ||
50 | return server; | ||
51 | } | ||
52 | } | ||
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/config/BackendConfig.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/config/BackendConfig.java index 2e864998..807b789c 100644 --- a/subprojects/language-web/src/main/java/tools/refinery/language/web/config/BackendConfig.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/config/BackendConfig.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.web.config; | 6 | package tools.refinery.language.web.config; |
2 | 7 | ||
3 | import com.google.gson.annotations.SerializedName; | 8 | import com.google.gson.annotations.SerializedName; |
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/config/BackendConfigServlet.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/config/BackendConfigServlet.java index f314a9fa..a2f04e34 100644 --- a/subprojects/language-web/src/main/java/tools/refinery/language/web/config/BackendConfigServlet.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/config/BackendConfigServlet.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.web.config; | 6 | package tools.refinery.language.web.config; |
2 | 7 | ||
3 | import com.google.gson.Gson; | 8 | import com.google.gson.Gson; |
@@ -29,7 +34,7 @@ public class BackendConfigServlet extends HttpServlet { | |||
29 | } | 34 | } |
30 | 35 | ||
31 | @Override | 36 | @Override |
32 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { | 37 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { |
33 | resp.setStatus(HttpStatus.OK_200); | 38 | resp.setStatus(HttpStatus.OK_200); |
34 | resp.setContentType("application/json"); | 39 | resp.setContentType("application/json"); |
35 | var writer = resp.getWriter(); | 40 | var writer = resp.getWriter(); |
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/occurrences/ProblemOccurrencesService.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/occurrences/ProblemOccurrencesService.java index d32bbb54..34117384 100644 --- a/subprojects/language-web/src/main/java/tools/refinery/language/web/occurrences/ProblemOccurrencesService.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/occurrences/ProblemOccurrencesService.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.web.occurrences; | 6 | package tools.refinery.language.web.occurrences; |
2 | 7 | ||
3 | import org.eclipse.emf.ecore.EObject; | 8 | import org.eclipse.emf.ecore.EObject; |
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/VirtualThreadExecutorServiceProvider.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/VirtualThreadExecutorServiceProvider.java deleted file mode 100644 index abbcbd53..00000000 --- a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/VirtualThreadExecutorServiceProvider.java +++ /dev/null | |||
@@ -1,16 +0,0 @@ | |||
1 | package tools.refinery.language.web.xtext; | ||
2 | |||
3 | import org.eclipse.xtext.ide.ExecutorServiceProvider; | ||
4 | import tools.refinery.language.web.VirtualThreadUtils; | ||
5 | |||
6 | import java.util.concurrent.ExecutorService; | ||
7 | |||
8 | public class VirtualThreadExecutorServiceProvider extends ExecutorServiceProvider { | ||
9 | private static final String THREAD_POOL_NAME = "xtextWeb"; | ||
10 | |||
11 | @Override | ||
12 | protected ExecutorService createInstance(String key) { | ||
13 | var name = key == null ? THREAD_POOL_NAME : THREAD_POOL_NAME + "-" + key; | ||
14 | return VirtualThreadUtils.newNamedVirtualThreadsExecutor(name); | ||
15 | } | ||
16 | } | ||
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/PongResult.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/PongResult.java index fe510f51..27b2e04e 100644 --- a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/PongResult.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/PongResult.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.web.xtext.server; | 6 | package tools.refinery.language.web.xtext.server; |
2 | 7 | ||
3 | import java.util.Objects; | 8 | import java.util.Objects; |
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/ResponseHandler.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/ResponseHandler.java index 2a85afe3..3069c2dd 100644 --- a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/ResponseHandler.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/ResponseHandler.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.web.xtext.server; | 6 | package tools.refinery.language.web.xtext.server; |
2 | 7 | ||
3 | import tools.refinery.language.web.xtext.server.message.XtextWebResponse; | 8 | import tools.refinery.language.web.xtext.server.message.XtextWebResponse; |
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/ResponseHandlerException.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/ResponseHandlerException.java index b686d33a..366ef0a7 100644 --- a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/ResponseHandlerException.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/ResponseHandlerException.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.web.xtext.server; | 6 | package tools.refinery.language.web.xtext.server; |
2 | 7 | ||
3 | import java.io.Serial; | 8 | import java.io.Serial; |
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/SubscribingServiceContext.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/SubscribingServiceContext.java index 78e00a9e..04212b84 100644 --- a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/SubscribingServiceContext.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/SubscribingServiceContext.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.web.xtext.server; | 6 | package tools.refinery.language.web.xtext.server; |
2 | 7 | ||
3 | import java.util.Set; | 8 | import java.util.Set; |
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/TransactionExecutor.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/TransactionExecutor.java index 7bb11d2e..0135d8f5 100644 --- a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/TransactionExecutor.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/TransactionExecutor.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.web.xtext.server; | 6 | package tools.refinery.language.web.xtext.server; |
2 | 7 | ||
3 | import com.google.common.base.Strings; | 8 | import com.google.common.base.Strings; |
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/message/XtextWebErrorKind.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/message/XtextWebErrorKind.java index f74bae74..6f4f265c 100644 --- a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/message/XtextWebErrorKind.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/message/XtextWebErrorKind.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.web.xtext.server.message; | 6 | package tools.refinery.language.web.xtext.server.message; |
2 | 7 | ||
3 | import com.google.gson.annotations.SerializedName; | 8 | import com.google.gson.annotations.SerializedName; |
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/message/XtextWebErrorResponse.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/message/XtextWebErrorResponse.java index 01d78c31..af38ad70 100644 --- a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/message/XtextWebErrorResponse.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/message/XtextWebErrorResponse.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.web.xtext.server.message; | 6 | package tools.refinery.language.web.xtext.server.message; |
2 | 7 | ||
3 | import java.util.Objects; | 8 | import java.util.Objects; |
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/message/XtextWebOkResponse.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/message/XtextWebOkResponse.java index 8af27247..73527ee5 100644 --- a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/message/XtextWebOkResponse.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/message/XtextWebOkResponse.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.web.xtext.server.message; | 6 | package tools.refinery.language.web.xtext.server.message; |
2 | 7 | ||
3 | import java.util.Objects; | 8 | import java.util.Objects; |
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/message/XtextWebPushMessage.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/message/XtextWebPushMessage.java index c9432e1c..e9ff87c4 100644 --- a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/message/XtextWebPushMessage.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/message/XtextWebPushMessage.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.web.xtext.server.message; | 6 | package tools.refinery.language.web.xtext.server.message; |
2 | 7 | ||
3 | import java.util.Objects; | 8 | import java.util.Objects; |
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/message/XtextWebRequest.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/message/XtextWebRequest.java index 959749f8..ff788e94 100644 --- a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/message/XtextWebRequest.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/message/XtextWebRequest.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.web.xtext.server.message; | 6 | package tools.refinery.language.web.xtext.server.message; |
2 | 7 | ||
3 | import java.util.Map; | 8 | import java.util.Map; |
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/message/XtextWebResponse.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/message/XtextWebResponse.java index 3bd13047..61444c99 100644 --- a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/message/XtextWebResponse.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/message/XtextWebResponse.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.web.xtext.server.message; | 6 | package tools.refinery.language.web.xtext.server.message; |
2 | 7 | ||
3 | public sealed interface XtextWebResponse permits XtextWebOkResponse,XtextWebErrorResponse,XtextWebPushMessage { | 8 | public sealed interface XtextWebResponse permits XtextWebOkResponse,XtextWebErrorResponse,XtextWebPushMessage { |
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/push/PrecomputationListener.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/push/PrecomputationListener.java index 79a284db..110c8f52 100644 --- a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/push/PrecomputationListener.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/push/PrecomputationListener.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.web.xtext.server.push; | 6 | package tools.refinery.language.web.xtext.server.push; |
2 | 7 | ||
3 | import org.eclipse.xtext.web.server.IServiceResult; | 8 | import org.eclipse.xtext.web.server.IServiceResult; |
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/push/PushServiceDispatcher.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/push/PushServiceDispatcher.java index c7b8108d..4c9135c8 100644 --- a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/push/PushServiceDispatcher.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/push/PushServiceDispatcher.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.web.xtext.server.push; | 6 | package tools.refinery.language.web.xtext.server.push; |
2 | 7 | ||
3 | import org.eclipse.xtext.web.server.IServiceContext; | 8 | import org.eclipse.xtext.web.server.IServiceContext; |
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/push/PushWebDocument.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/push/PushWebDocument.java index 906b9e30..56fd12c9 100644 --- a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/push/PushWebDocument.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/push/PushWebDocument.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.web.xtext.server.push; | 6 | package tools.refinery.language.web.xtext.server.push; |
2 | 7 | ||
3 | import java.util.ArrayList; | 8 | import java.util.ArrayList; |
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/push/PushWebDocumentAccess.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/push/PushWebDocumentAccess.java index b3666a86..d9e548cd 100644 --- a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/push/PushWebDocumentAccess.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/push/PushWebDocumentAccess.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.web.xtext.server.push; | 6 | package tools.refinery.language.web.xtext.server.push; |
2 | 7 | ||
3 | import org.eclipse.xtext.service.OperationCanceledManager; | 8 | import org.eclipse.xtext.service.OperationCanceledManager; |
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/push/PushWebDocumentProvider.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/push/PushWebDocumentProvider.java index b6f04748..b6f4fb43 100644 --- a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/push/PushWebDocumentProvider.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/server/push/PushWebDocumentProvider.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.web.xtext.server.push; | 6 | package tools.refinery.language.web.xtext.server.push; |
2 | 7 | ||
3 | import org.eclipse.xtext.web.server.IServiceContext; | 8 | import org.eclipse.xtext.web.server.IServiceContext; |
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/servlet/SimpleServiceContext.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/servlet/SimpleServiceContext.java index 43e37160..fee1141d 100644 --- a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/servlet/SimpleServiceContext.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/servlet/SimpleServiceContext.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.web.xtext.servlet; | 6 | package tools.refinery.language.web.xtext.servlet; |
2 | 7 | ||
3 | import java.util.Map; | 8 | import java.util.Map; |
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/servlet/SimpleSession.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/servlet/SimpleSession.java index 09c055a2..bc60c282 100644 --- a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/servlet/SimpleSession.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/servlet/SimpleSession.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.web.xtext.servlet; | 6 | package tools.refinery.language.web.xtext.servlet; |
2 | 7 | ||
3 | import java.util.HashMap; | 8 | import java.util.HashMap; |
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/servlet/XtextStatusCode.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/servlet/XtextStatusCode.java index 0cd229e8..caa98e84 100644 --- a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/servlet/XtextStatusCode.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/servlet/XtextStatusCode.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.web.xtext.servlet; | 6 | package tools.refinery.language.web.xtext.servlet; |
2 | 7 | ||
3 | public final class XtextStatusCode { | 8 | public final class XtextStatusCode { |
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/servlet/XtextWebSocket.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/servlet/XtextWebSocket.java index 1d9e0463..043d318c 100644 --- a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/servlet/XtextWebSocket.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/servlet/XtextWebSocket.java | |||
@@ -1,12 +1,17 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.web.xtext.servlet; | 6 | package tools.refinery.language.web.xtext.servlet; |
2 | 7 | ||
3 | import com.google.gson.Gson; | 8 | import com.google.gson.Gson; |
4 | import com.google.gson.JsonIOException; | 9 | import com.google.gson.JsonIOException; |
5 | import com.google.gson.JsonParseException; | 10 | import com.google.gson.JsonParseException; |
6 | import org.eclipse.jetty.ee10.websocket.api.Session; | 11 | import org.eclipse.jetty.websocket.api.Callback; |
7 | import org.eclipse.jetty.ee10.websocket.api.StatusCode; | 12 | import org.eclipse.jetty.websocket.api.Session; |
8 | import org.eclipse.jetty.ee10.websocket.api.WriteCallback; | 13 | import org.eclipse.jetty.websocket.api.StatusCode; |
9 | import org.eclipse.jetty.ee10.websocket.api.annotations.*; | 14 | import org.eclipse.jetty.websocket.api.annotations.*; |
10 | import org.eclipse.xtext.resource.IResourceServiceProvider; | 15 | import org.eclipse.xtext.resource.IResourceServiceProvider; |
11 | import org.eclipse.xtext.web.server.ISession; | 16 | import org.eclipse.xtext.web.server.ISession; |
12 | import org.slf4j.Logger; | 17 | import org.slf4j.Logger; |
@@ -20,7 +25,7 @@ import tools.refinery.language.web.xtext.server.message.XtextWebResponse; | |||
20 | import java.io.Reader; | 25 | import java.io.Reader; |
21 | 26 | ||
22 | @WebSocket | 27 | @WebSocket |
23 | public class XtextWebSocket implements WriteCallback, ResponseHandler { | 28 | public class XtextWebSocket implements ResponseHandler { |
24 | private static final Logger LOG = LoggerFactory.getLogger(XtextWebSocket.class); | 29 | private static final Logger LOG = LoggerFactory.getLogger(XtextWebSocket.class); |
25 | 30 | ||
26 | private final Gson gson = new Gson(); | 31 | private final Gson gson = new Gson(); |
@@ -38,13 +43,13 @@ public class XtextWebSocket implements WriteCallback, ResponseHandler { | |||
38 | this(new TransactionExecutor(session, resourceServiceProviderRegistry)); | 43 | this(new TransactionExecutor(session, resourceServiceProviderRegistry)); |
39 | } | 44 | } |
40 | 45 | ||
41 | @OnWebSocketConnect | 46 | @OnWebSocketOpen |
42 | public void onConnect(Session webSocketSession) { | 47 | public void onOpen(Session webSocketSession) { |
43 | if (this.webSocketSession != null) { | 48 | if (this.webSocketSession != null) { |
44 | LOG.error("Websocket session onConnect when already connected"); | 49 | LOG.error("Websocket session onConnect when already connected"); |
45 | return; | 50 | return; |
46 | } | 51 | } |
47 | LOG.debug("New websocket connection from {}", webSocketSession.getRemoteAddress()); | 52 | LOG.debug("New websocket connection from {}", webSocketSession.getRemoteSocketAddress()); |
48 | this.webSocketSession = webSocketSession; | 53 | this.webSocketSession = webSocketSession; |
49 | } | 54 | } |
50 | 55 | ||
@@ -55,10 +60,10 @@ public class XtextWebSocket implements WriteCallback, ResponseHandler { | |||
55 | return; | 60 | return; |
56 | } | 61 | } |
57 | if (statusCode == StatusCode.NORMAL || statusCode == StatusCode.SHUTDOWN) { | 62 | if (statusCode == StatusCode.NORMAL || statusCode == StatusCode.SHUTDOWN) { |
58 | LOG.debug("{} closed connection normally: {}", webSocketSession.getRemoteAddress(), reason); | 63 | LOG.debug("{} closed connection normally: {}", webSocketSession.getRemoteSocketAddress(), reason); |
59 | } else { | 64 | } else { |
60 | LOG.warn("{} closed connection with status code {}: {}", webSocketSession.getRemoteAddress(), statusCode, | 65 | LOG.warn("{} closed connection with status code {}: {}", webSocketSession.getRemoteSocketAddress(), |
61 | reason); | 66 | statusCode, reason); |
62 | } | 67 | } |
63 | webSocketSession = null; | 68 | webSocketSession = null; |
64 | } | 69 | } |
@@ -68,7 +73,7 @@ public class XtextWebSocket implements WriteCallback, ResponseHandler { | |||
68 | if (webSocketSession == null) { | 73 | if (webSocketSession == null) { |
69 | return; | 74 | return; |
70 | } | 75 | } |
71 | LOG.error("Internal websocket error in connection from" + webSocketSession.getRemoteAddress(), error); | 76 | LOG.error("Internal websocket error in connection from" + webSocketSession.getRemoteSocketAddress(), error); |
72 | } | 77 | } |
73 | 78 | ||
74 | @OnWebSocketMessage | 79 | @OnWebSocketMessage |
@@ -81,14 +86,14 @@ public class XtextWebSocket implements WriteCallback, ResponseHandler { | |||
81 | try { | 86 | try { |
82 | request = gson.fromJson(reader, XtextWebRequest.class); | 87 | request = gson.fromJson(reader, XtextWebRequest.class); |
83 | } catch (JsonIOException e) { | 88 | } catch (JsonIOException e) { |
84 | LOG.error("Cannot read from websocket from" + webSocketSession.getRemoteAddress(), e); | 89 | LOG.error("Cannot read from websocket from" + webSocketSession.getRemoteSocketAddress(), e); |
85 | if (webSocketSession.isOpen()) { | 90 | if (webSocketSession.isOpen()) { |
86 | webSocketSession.close(StatusCode.SERVER_ERROR, "Cannot read payload"); | 91 | webSocketSession.close(StatusCode.SERVER_ERROR, "Cannot read payload", Callback.NOOP); |
87 | } | 92 | } |
88 | return; | 93 | return; |
89 | } catch (JsonParseException e) { | 94 | } catch (JsonParseException e) { |
90 | LOG.warn("Malformed websocket request from" + webSocketSession.getRemoteAddress(), e); | 95 | LOG.warn("Malformed websocket request from" + webSocketSession.getRemoteSocketAddress(), e); |
91 | webSocketSession.close(XtextStatusCode.INVALID_JSON, "Invalid JSON payload"); | 96 | webSocketSession.close(XtextStatusCode.INVALID_JSON, "Invalid JSON payload", Callback.NOOP); |
92 | return; | 97 | return; |
93 | } | 98 | } |
94 | try { | 99 | try { |
@@ -96,7 +101,7 @@ public class XtextWebSocket implements WriteCallback, ResponseHandler { | |||
96 | } catch (ResponseHandlerException e) { | 101 | } catch (ResponseHandlerException e) { |
97 | LOG.warn("Cannot write websocket response", e); | 102 | LOG.warn("Cannot write websocket response", e); |
98 | if (webSocketSession.isOpen()) { | 103 | if (webSocketSession.isOpen()) { |
99 | webSocketSession.close(StatusCode.SERVER_ERROR, "Cannot write response"); | 104 | webSocketSession.close(StatusCode.SERVER_ERROR, "Cannot write response", Callback.NOOP); |
100 | } | 105 | } |
101 | } | 106 | } |
102 | } | 107 | } |
@@ -107,15 +112,14 @@ public class XtextWebSocket implements WriteCallback, ResponseHandler { | |||
107 | throw new ResponseHandlerException("Trying to send message when websocket is disconnected"); | 112 | throw new ResponseHandlerException("Trying to send message when websocket is disconnected"); |
108 | } | 113 | } |
109 | var responseString = gson.toJson(response); | 114 | var responseString = gson.toJson(response); |
110 | webSocketSession.getRemote().sendPartialString(responseString, true, this); | 115 | webSocketSession.sendText(responseString, Callback.from(() -> {}, this::writeFailed)); |
111 | } | 116 | } |
112 | 117 | ||
113 | @Override | ||
114 | public void writeFailed(Throwable x) { | 118 | public void writeFailed(Throwable x) { |
115 | if (webSocketSession == null) { | 119 | if (webSocketSession == null) { |
116 | LOG.error("Cannot complete async write to disconnected websocket", x); | 120 | LOG.error("Cannot complete async write to disconnected websocket", x); |
117 | return; | 121 | return; |
118 | } | 122 | } |
119 | LOG.warn("Cannot complete async write to websocket " + webSocketSession.getRemoteAddress(), x); | 123 | LOG.warn("Cannot complete async write to websocket " + webSocketSession.getRemoteSocketAddress(), x); |
120 | } | 124 | } |
121 | } | 125 | } |
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/servlet/XtextWebSocketServlet.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/servlet/XtextWebSocketServlet.java index 9a32b937..5e4fb0ce 100644 --- a/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/servlet/XtextWebSocketServlet.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/xtext/servlet/XtextWebSocketServlet.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.web.xtext.servlet; | 6 | package tools.refinery.language.web.xtext.servlet; |
2 | 7 | ||
3 | import jakarta.servlet.ServletConfig; | 8 | import jakarta.servlet.ServletConfig; |
diff --git a/subprojects/language-web/src/test/java/tools/refinery/language/web/ProblemWebSocketServletIntegrationTest.java b/subprojects/language-web/src/test/java/tools/refinery/language/web/ProblemWebSocketServletIntegrationTest.java index ecbefc4f..927eeab1 100644 --- a/subprojects/language-web/src/test/java/tools/refinery/language/web/ProblemWebSocketServletIntegrationTest.java +++ b/subprojects/language-web/src/test/java/tools/refinery/language/web/ProblemWebSocketServletIntegrationTest.java | |||
@@ -1,20 +1,30 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.web; | 6 | package tools.refinery.language.web; |
2 | 7 | ||
3 | import org.eclipse.jetty.ee10.servlet.ServletContextHandler; | 8 | import org.eclipse.jetty.ee10.servlet.ServletContextHandler; |
4 | import org.eclipse.jetty.ee10.servlet.ServletHolder; | 9 | import org.eclipse.jetty.ee10.servlet.ServletHolder; |
5 | import org.eclipse.jetty.ee10.websocket.api.Session; | ||
6 | import org.eclipse.jetty.ee10.websocket.api.StatusCode; | ||
7 | import org.eclipse.jetty.ee10.websocket.api.annotations.WebSocket; | ||
8 | import org.eclipse.jetty.ee10.websocket.api.exceptions.UpgradeException; | ||
9 | import org.eclipse.jetty.ee10.websocket.client.ClientUpgradeRequest; | ||
10 | import org.eclipse.jetty.ee10.websocket.client.WebSocketClient; | ||
11 | import org.eclipse.jetty.ee10.websocket.server.config.JettyWebSocketServletContainerInitializer; | 10 | import org.eclipse.jetty.ee10.websocket.server.config.JettyWebSocketServletContainerInitializer; |
12 | import org.eclipse.jetty.http.HttpHeader; | 11 | import org.eclipse.jetty.http.HttpHeader; |
13 | import org.eclipse.jetty.http.HttpStatus; | 12 | import org.eclipse.jetty.http.HttpStatus; |
14 | import org.eclipse.jetty.server.Server; | 13 | import org.eclipse.jetty.server.Server; |
14 | import org.eclipse.jetty.util.thread.QueuedThreadPool; | ||
15 | import org.eclipse.jetty.websocket.api.Callback; | ||
16 | import org.eclipse.jetty.websocket.api.Session; | ||
17 | import org.eclipse.jetty.websocket.api.StatusCode; | ||
18 | import org.eclipse.jetty.websocket.api.annotations.WebSocket; | ||
19 | import org.eclipse.jetty.websocket.api.exceptions.UpgradeException; | ||
20 | import org.eclipse.jetty.websocket.client.ClientUpgradeRequest; | ||
21 | import org.eclipse.jetty.websocket.client.WebSocketClient; | ||
15 | import org.eclipse.xtext.testing.GlobalRegistries; | 22 | import org.eclipse.xtext.testing.GlobalRegistries; |
16 | import org.eclipse.xtext.testing.GlobalRegistries.GlobalStateMemento; | 23 | import org.eclipse.xtext.testing.GlobalRegistries.GlobalStateMemento; |
17 | import org.junit.jupiter.api.*; | 24 | import org.junit.jupiter.api.AfterEach; |
25 | import org.junit.jupiter.api.BeforeEach; | ||
26 | import org.junit.jupiter.api.Test; | ||
27 | import org.junit.jupiter.api.TestInfo; | ||
18 | import org.junit.jupiter.params.ParameterizedTest; | 28 | import org.junit.jupiter.params.ParameterizedTest; |
19 | import org.junit.jupiter.params.provider.ValueSource; | 29 | import org.junit.jupiter.params.provider.ValueSource; |
20 | import tools.refinery.language.web.tests.WebSocketIntegrationTestClient; | 30 | import tools.refinery.language.web.tests.WebSocketIntegrationTestClient; |
@@ -86,23 +96,34 @@ class ProblemWebSocketServletIntegrationTest { | |||
86 | assertThat(responses, hasSize(5)); | 96 | assertThat(responses, hasSize(5)); |
87 | assertThat(responses.get(0), equalTo("{\"id\":\"foo\",\"response\":{\"stateId\":\"-80000000\"}}")); | 97 | assertThat(responses.get(0), equalTo("{\"id\":\"foo\",\"response\":{\"stateId\":\"-80000000\"}}")); |
88 | assertThat(responses.get(1), startsWith( | 98 | assertThat(responses.get(1), startsWith( |
89 | "{\"resource\":\"test.problem\",\"stateId\":\"-80000000\",\"service\":\"highlight\",\"push\":{\"regions\":[")); | 99 | "{\"resource\":\"test.problem\",\"stateId\":\"-80000000\",\"service\":\"highlight\"," + |
100 | "\"push\":{\"regions\":[")); | ||
90 | assertThat(responses.get(2), equalTo( | 101 | assertThat(responses.get(2), equalTo( |
91 | "{\"resource\":\"test.problem\",\"stateId\":\"-80000000\",\"service\":\"validate\",\"push\":{\"issues\":[]}}")); | 102 | "{\"resource\":\"test.problem\",\"stateId\":\"-80000000\",\"service\":\"validate\"," + |
103 | "\"push\":{\"issues\":[]}}")); | ||
92 | assertThat(responses.get(3), equalTo("{\"id\":\"bar\",\"response\":{\"stateId\":\"-7fffffff\"}}")); | 104 | assertThat(responses.get(3), equalTo("{\"id\":\"bar\",\"response\":{\"stateId\":\"-7fffffff\"}}")); |
93 | assertThat(responses.get(4), startsWith( | 105 | assertThat(responses.get(4), startsWith( |
94 | "{\"resource\":\"test.problem\",\"stateId\":\"-7fffffff\",\"service\":\"highlight\",\"push\":{\"regions\":[")); | 106 | "{\"resource\":\"test.problem\",\"stateId\":\"-7fffffff\",\"service\":\"highlight\"," + |
107 | "\"push\":{\"regions\":[")); | ||
95 | } | 108 | } |
96 | 109 | ||
97 | @WebSocket | 110 | @WebSocket |
98 | public static class UpdateTestClient extends WebSocketIntegrationTestClient { | 111 | public static class UpdateTestClient extends WebSocketIntegrationTestClient { |
99 | @Override | 112 | @Override |
100 | protected void arrange(Session session, int responsesReceived) throws IOException { | 113 | protected void arrange(Session session, int responsesReceived) { |
101 | switch (responsesReceived) { | 114 | switch (responsesReceived) { |
102 | case 0 -> session.getRemote().sendString( | 115 | case 0 -> session.sendText( |
103 | "{\"id\":\"foo\",\"request\":{\"resource\":\"test.problem\",\"serviceType\":\"update\",\"fullText\":\"class Person.\n\"}}"); | 116 | "{\"id\":\"foo\",\"request\":{\"resource\":\"test.problem\",\"serviceType\":\"update\"," + |
104 | case 3 -> session.getRemote().sendString( | 117 | "\"fullText\":\"class Person.\n\"}}", |
105 | "{\"id\":\"bar\",\"request\":{\"resource\":\"test.problem\",\"serviceType\":\"update\",\"requiredStateId\":\"-80000000\",\"deltaText\":\"indiv q.\nnode(q).\n\",\"deltaOffset\":\"0\",\"deltaReplaceLength\":\"0\"}}"); | 118 | Callback.NOOP |
119 | ); | ||
120 | case 3 -> //noinspection TextBlockMigration | ||
121 | session.sendText( | ||
122 | "{\"id\":\"bar\",\"request\":{\"resource\":\"test.problem\",\"serviceType\":\"update\"," + | ||
123 | "\"requiredStateId\":\"-80000000\",\"deltaText\":\"indiv q.\nnode(q).\n\"," + | ||
124 | "\"deltaOffset\":\"0\",\"deltaReplaceLength\":\"0\"}}", | ||
125 | Callback.NOOP | ||
126 | ); | ||
106 | case 5 -> session.close(); | 127 | case 5 -> session.close(); |
107 | } | 128 | } |
108 | } | 129 | } |
@@ -152,13 +173,13 @@ class ProblemWebSocketServletIntegrationTest { | |||
152 | @WebSocket | 173 | @WebSocket |
153 | public static class InvalidJsonTestClient extends WebSocketIntegrationTestClient { | 174 | public static class InvalidJsonTestClient extends WebSocketIntegrationTestClient { |
154 | @Override | 175 | @Override |
155 | protected void arrange(Session session, int responsesReceived) throws IOException { | 176 | protected void arrange(Session session, int responsesReceived) { |
156 | session.getRemote().sendString("<invalid json>"); | 177 | session.sendText("<invalid json>", Callback.NOOP); |
157 | } | 178 | } |
158 | } | 179 | } |
159 | 180 | ||
160 | @ParameterizedTest(name = "validOriginTest(\"{0}\")") | 181 | @ParameterizedTest(name = "validOriginTest(\"{0}\")") |
161 | @ValueSource(strings = { "https://refinery.example", "https://refinery.example:443", "HTTPS://REFINERY.EXAMPLE" }) | 182 | @ValueSource(strings = {"https://refinery.example", "https://refinery.example:443", "HTTPS://REFINERY.EXAMPLE"}) |
162 | void validOriginTest(String origin) { | 183 | void validOriginTest(String origin) { |
163 | startServer("https://refinery.example,https://refinery.example:443"); | 184 | startServer("https://refinery.example,https://refinery.example:443"); |
164 | var clientSocket = new CloseImmediatelyTestClient(); | 185 | var clientSocket = new CloseImmediatelyTestClient(); |
@@ -188,7 +209,8 @@ class ProblemWebSocketServletIntegrationTest { | |||
188 | private void startServer(String allowedOrigins) { | 209 | private void startServer(String allowedOrigins) { |
189 | var testName = getClass().getSimpleName() + "-" + testInfo.getDisplayName(); | 210 | var testName = getClass().getSimpleName() + "-" + testInfo.getDisplayName(); |
190 | var listenAddress = new InetSocketAddress(HOSTNAME, serverPort); | 211 | var listenAddress = new InetSocketAddress(HOSTNAME, serverPort); |
191 | server = VirtualThreadUtils.newServerWithVirtualThreadsThreadPool(testName, listenAddress); | 212 | server = new Server(listenAddress); |
213 | ((QueuedThreadPool) server.getThreadPool()).setName(testName); | ||
192 | var handler = new ServletContextHandler(); | 214 | var handler = new ServletContextHandler(); |
193 | var holder = new ServletHolder(ProblemWebSocketServlet.class); | 215 | var holder = new ServletHolder(ProblemWebSocketServlet.class); |
194 | if (allowedOrigins != null) { | 216 | if (allowedOrigins != null) { |
diff --git a/subprojects/language-web/src/test/java/tools/refinery/language/web/tests/AwaitTerminationExecutorServiceProvider.java b/subprojects/language-web/src/test/java/tools/refinery/language/web/tests/AwaitTerminationExecutorServiceProvider.java index c634e8fc..52acee6d 100644 --- a/subprojects/language-web/src/test/java/tools/refinery/language/web/tests/AwaitTerminationExecutorServiceProvider.java +++ b/subprojects/language-web/src/test/java/tools/refinery/language/web/tests/AwaitTerminationExecutorServiceProvider.java | |||
@@ -1,14 +1,19 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.web.tests; | 6 | package tools.refinery.language.web.tests; |
2 | 7 | ||
3 | import com.google.inject.Singleton; | 8 | import com.google.inject.Singleton; |
4 | import tools.refinery.language.web.xtext.VirtualThreadExecutorServiceProvider; | 9 | import org.eclipse.xtext.ide.ExecutorServiceProvider; |
5 | 10 | ||
6 | import java.util.ArrayList; | 11 | import java.util.ArrayList; |
7 | import java.util.List; | 12 | import java.util.List; |
8 | import java.util.concurrent.ExecutorService; | 13 | import java.util.concurrent.ExecutorService; |
9 | 14 | ||
10 | @Singleton | 15 | @Singleton |
11 | public class AwaitTerminationExecutorServiceProvider extends VirtualThreadExecutorServiceProvider { | 16 | public class AwaitTerminationExecutorServiceProvider extends ExecutorServiceProvider { |
12 | private final List<RestartableCachedThreadPool> servicesToShutDown = new ArrayList<>(); | 17 | private final List<RestartableCachedThreadPool> servicesToShutDown = new ArrayList<>(); |
13 | 18 | ||
14 | @Override | 19 | @Override |
diff --git a/subprojects/language-web/src/test/java/tools/refinery/language/web/tests/ProblemWebInjectorProvider.java b/subprojects/language-web/src/test/java/tools/refinery/language/web/tests/ProblemWebInjectorProvider.java index 43c12faa..4a5eed95 100644 --- a/subprojects/language-web/src/test/java/tools/refinery/language/web/tests/ProblemWebInjectorProvider.java +++ b/subprojects/language-web/src/test/java/tools/refinery/language/web/tests/ProblemWebInjectorProvider.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.web.tests; | 6 | package tools.refinery.language.web.tests; |
2 | 7 | ||
3 | import org.eclipse.xtext.ide.ExecutorServiceProvider; | 8 | import org.eclipse.xtext.ide.ExecutorServiceProvider; |
diff --git a/subprojects/language-web/src/test/java/tools/refinery/language/web/tests/RestartableCachedThreadPool.java b/subprojects/language-web/src/test/java/tools/refinery/language/web/tests/RestartableCachedThreadPool.java index cf805eda..09079aa8 100644 --- a/subprojects/language-web/src/test/java/tools/refinery/language/web/tests/RestartableCachedThreadPool.java +++ b/subprojects/language-web/src/test/java/tools/refinery/language/web/tests/RestartableCachedThreadPool.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.web.tests; | 6 | package tools.refinery.language.web.tests; |
2 | 7 | ||
3 | import com.google.inject.Provider; | 8 | import com.google.inject.Provider; |
diff --git a/subprojects/language-web/src/test/java/tools/refinery/language/web/tests/WebSocketIntegrationTestClient.java b/subprojects/language-web/src/test/java/tools/refinery/language/web/tests/WebSocketIntegrationTestClient.java index f19c10ca..6ccf1760 100644 --- a/subprojects/language-web/src/test/java/tools/refinery/language/web/tests/WebSocketIntegrationTestClient.java +++ b/subprojects/language-web/src/test/java/tools/refinery/language/web/tests/WebSocketIntegrationTestClient.java | |||
@@ -1,12 +1,16 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.web.tests; | 6 | package tools.refinery.language.web.tests; |
2 | 7 | ||
3 | import org.eclipse.jetty.ee10.websocket.api.Session; | 8 | import org.eclipse.jetty.websocket.api.Session; |
4 | import org.eclipse.jetty.ee10.websocket.api.annotations.OnWebSocketClose; | 9 | import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose; |
5 | import org.eclipse.jetty.ee10.websocket.api.annotations.OnWebSocketConnect; | 10 | import org.eclipse.jetty.websocket.api.annotations.OnWebSocketError; |
6 | import org.eclipse.jetty.ee10.websocket.api.annotations.OnWebSocketError; | 11 | import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage; |
7 | import org.eclipse.jetty.ee10.websocket.api.annotations.OnWebSocketMessage; | 12 | import org.eclipse.jetty.websocket.api.annotations.OnWebSocketOpen; |
8 | 13 | ||
9 | import java.io.IOException; | ||
10 | import java.time.Duration; | 14 | import java.time.Duration; |
11 | import java.util.ArrayList; | 15 | import java.util.ArrayList; |
12 | import java.util.List; | 16 | import java.util.List; |
@@ -14,7 +18,7 @@ import java.util.List; | |||
14 | import static org.junit.jupiter.api.Assertions.fail; | 18 | import static org.junit.jupiter.api.Assertions.fail; |
15 | 19 | ||
16 | public abstract class WebSocketIntegrationTestClient { | 20 | public abstract class WebSocketIntegrationTestClient { |
17 | private static final long TIMEOUT_MILLIS = Duration.ofSeconds(1).toMillis(); | 21 | private static final long TIMEOUT_MILLIS = Duration.ofSeconds(10).toMillis(); |
18 | 22 | ||
19 | private boolean finished = false; | 23 | private boolean finished = false; |
20 | 24 | ||
@@ -34,8 +38,8 @@ public abstract class WebSocketIntegrationTestClient { | |||
34 | return responses; | 38 | return responses; |
35 | } | 39 | } |
36 | 40 | ||
37 | @OnWebSocketConnect | 41 | @OnWebSocketOpen |
38 | public void onConnect(Session session) { | 42 | public void onOpen(Session session) { |
39 | arrangeAndCatchErrors(session); | 43 | arrangeAndCatchErrors(session); |
40 | } | 44 | } |
41 | 45 | ||
@@ -47,7 +51,7 @@ public abstract class WebSocketIntegrationTestClient { | |||
47 | } | 51 | } |
48 | } | 52 | } |
49 | 53 | ||
50 | protected abstract void arrange(Session session, int responsesReceived) throws IOException; | 54 | protected abstract void arrange(Session session, int responsesReceived); |
51 | 55 | ||
52 | @OnWebSocketClose | 56 | @OnWebSocketClose |
53 | public void onClose(int statusCode, String reason) { | 57 | public void onClose(int statusCode, String reason) { |
diff --git a/subprojects/language-web/src/test/java/tools/refinery/language/web/xtext/servlet/TransactionExecutorTest.java b/subprojects/language-web/src/test/java/tools/refinery/language/web/xtext/servlet/TransactionExecutorTest.java index 17f1ff5c..841bacd3 100644 --- a/subprojects/language-web/src/test/java/tools/refinery/language/web/xtext/servlet/TransactionExecutorTest.java +++ b/subprojects/language-web/src/test/java/tools/refinery/language/web/xtext/servlet/TransactionExecutorTest.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.web.xtext.servlet; | 6 | package tools.refinery.language.web.xtext.servlet; |
2 | 7 | ||
3 | import com.google.inject.Inject; | 8 | import com.google.inject.Inject; |
diff --git a/subprojects/language/build.gradle b/subprojects/language/build.gradle deleted file mode 100644 index 654558e3..00000000 --- a/subprojects/language/build.gradle +++ /dev/null | |||
@@ -1,73 +0,0 @@ | |||
1 | plugins { | ||
2 | id 'refinery-java-library' | ||
3 | id 'refinery-java-test-fixtures' | ||
4 | id 'refinery-mwe2' | ||
5 | id 'refinery-sonarqube' | ||
6 | id 'refinery-xtext-conventions' | ||
7 | } | ||
8 | |||
9 | dependencies { | ||
10 | api platform(libs.xtext.bom) | ||
11 | api libs.ecore | ||
12 | api libs.xtext.core | ||
13 | api libs.xtext.xbase | ||
14 | api project(':refinery-language-model') | ||
15 | testFixturesApi libs.xtext.testing | ||
16 | mwe2 libs.xtext.generator | ||
17 | mwe2 libs.xtext.generator.antlr | ||
18 | } | ||
19 | |||
20 | sourceSets { | ||
21 | testFixtures { | ||
22 | java.srcDirs += ['src/testFixtures/xtext-gen'] | ||
23 | resources.srcDirs += ['src/testFixtures/xtext-gen'] | ||
24 | } | ||
25 | } | ||
26 | |||
27 | tasks.named('jar') { | ||
28 | from(sourceSets.main.allSource) { | ||
29 | include '**/*.xtext' | ||
30 | } | ||
31 | } | ||
32 | |||
33 | def generateXtextLanguage = tasks.register('generateXtextLanguage', JavaExec) { | ||
34 | mainClass = 'org.eclipse.emf.mwe2.launch.runtime.Mwe2Launcher' | ||
35 | classpath = configurations.mwe2 | ||
36 | inputs.file 'src/main/java/tools/refinery/language/GenerateProblem.mwe2' | ||
37 | inputs.file 'src/main/java/tools/refinery/language/Problem.xtext' | ||
38 | outputs.dir 'src/main/xtext-gen' | ||
39 | outputs.dir 'src/testFixtures/xtext-gen' | ||
40 | outputs.dir '../language-ide/src/main/xtext-gen' | ||
41 | outputs.dir '../language-web/src/main/xtext-gen' | ||
42 | args += 'src/main/java/tools/refinery/language/GenerateProblem.mwe2' | ||
43 | args += '-p' | ||
44 | args += "rootPath=/${projectDir}/.." | ||
45 | } | ||
46 | |||
47 | for (taskName in [ | ||
48 | 'compileJava', | ||
49 | 'processResources', | ||
50 | 'processTestFixturesResources', | ||
51 | 'generateEclipseSourceFolders' | ||
52 | ]) { | ||
53 | tasks.named(taskName) { | ||
54 | dependsOn generateXtextLanguage | ||
55 | } | ||
56 | } | ||
57 | |||
58 | tasks.named('clean') { | ||
59 | delete 'src/main/xtext-gen' | ||
60 | delete 'src/testFixtures/xtext-gen' | ||
61 | delete '../language-ide/src/main/xtext-gen' | ||
62 | delete '../language-web/src/main/xtext-gen' | ||
63 | } | ||
64 | |||
65 | sonarqube.properties { | ||
66 | properties['sonar.exclusions'] += [ | ||
67 | 'src/testFixtures/xtext-gen/**', | ||
68 | ] | ||
69 | } | ||
70 | |||
71 | eclipse.project.natures += [ | ||
72 | 'org.eclipse.xtext.ui.shared.xtextNature' | ||
73 | ] | ||
diff --git a/subprojects/language/build.gradle.kts b/subprojects/language/build.gradle.kts new file mode 100644 index 00000000..bac1e586 --- /dev/null +++ b/subprojects/language/build.gradle.kts | |||
@@ -0,0 +1,101 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
7 | import tools.refinery.gradle.utils.SonarPropertiesUtils | ||
8 | |||
9 | plugins { | ||
10 | id("tools.refinery.gradle.java-library") | ||
11 | id("tools.refinery.gradle.java-test-fixtures") | ||
12 | id("tools.refinery.gradle.mwe2") | ||
13 | id("tools.refinery.gradle.sonarqube") | ||
14 | id("tools.refinery.gradle.xtext-generated") | ||
15 | } | ||
16 | |||
17 | val generatedIdeSources: Configuration by configurations.creating { | ||
18 | isCanBeConsumed = true | ||
19 | isCanBeResolved = false | ||
20 | } | ||
21 | |||
22 | val generatedWebSources: Configuration by configurations.creating { | ||
23 | isCanBeConsumed = true | ||
24 | isCanBeResolved = false | ||
25 | } | ||
26 | |||
27 | dependencies { | ||
28 | api(platform(libs.xtext.bom)) | ||
29 | api(libs.ecore) | ||
30 | api(libs.xtext.core) | ||
31 | api(libs.xtext.xbase) | ||
32 | api(project(":refinery-language-model")) | ||
33 | testFixturesApi(libs.xtext.testing) | ||
34 | mwe2(libs.xtext.generator) | ||
35 | mwe2(libs.xtext.generator.antlr) | ||
36 | } | ||
37 | |||
38 | sourceSets { | ||
39 | testFixtures { | ||
40 | java.srcDir("src/testFixtures/xtext-gen") | ||
41 | resources.srcDir("src/testFixtures/xtext-gen") | ||
42 | } | ||
43 | } | ||
44 | |||
45 | val generateXtextLanguage by tasks.registering(JavaExec::class) { | ||
46 | mainClass.set("org.eclipse.emf.mwe2.launch.runtime.Mwe2Launcher") | ||
47 | classpath(configurations.mwe2) | ||
48 | inputs.file("src/main/java/tools/refinery/language/GenerateProblem.mwe2") | ||
49 | inputs.file("src/main/java/tools/refinery/language/Problem.xtext") | ||
50 | inputs.file("../language-model/src/main/resources/model/problem.ecore") | ||
51 | inputs.file("../language-model/src/main/resources/model/problem.genmodel") | ||
52 | outputs.dir("src/main/xtext-gen") | ||
53 | outputs.dir("src/testFixtures/xtext-gen") | ||
54 | outputs.dir("$buildDir/generated/sources/xtext/ide") | ||
55 | outputs.dir("$buildDir/generated/sources/xtext/web") | ||
56 | args("src/main/java/tools/refinery/language/GenerateProblem.mwe2", "-p", "rootPath=/$projectDir/..") | ||
57 | } | ||
58 | |||
59 | tasks { | ||
60 | jar { | ||
61 | from(sourceSets.main.map { it.allSource }) { | ||
62 | include("**/*.xtext") | ||
63 | } | ||
64 | } | ||
65 | |||
66 | syncXtextGeneratedSources { | ||
67 | // We generate Xtext runtime sources directly to {@code src/main/xtext-gen}, so there is no need to copy them | ||
68 | // from an artifact. We expose the {@code generatedIdeSources} and {@code generatedWebSources} artifacts to | ||
69 | // sibling IDE and web projects which can use this task to consume them and copy the appropriate sources to | ||
70 | // their own {@code src/main/xtext-gen} directory. | ||
71 | enabled = false | ||
72 | } | ||
73 | |||
74 | for (taskName in listOf("compileJava", "processResources", "compileTestFixturesJava", | ||
75 | "processTestFixturesResources", "generateEclipseSourceFolders")) { | ||
76 | named(taskName) { | ||
77 | dependsOn(generateXtextLanguage) | ||
78 | } | ||
79 | } | ||
80 | |||
81 | clean { | ||
82 | delete("src/main/xtext-gen") | ||
83 | delete("src/testFixtures/xtext-gen") | ||
84 | } | ||
85 | } | ||
86 | |||
87 | artifacts { | ||
88 | add(generatedIdeSources.name, file("$buildDir/generated/sources/xtext/ide")) { | ||
89 | builtBy(generateXtextLanguage) | ||
90 | } | ||
91 | |||
92 | add(generatedWebSources.name, file("$buildDir/generated/sources/xtext/web")) { | ||
93 | builtBy(generateXtextLanguage) | ||
94 | } | ||
95 | } | ||
96 | |||
97 | sonarqube.properties { | ||
98 | SonarPropertiesUtils.addToList(properties, "sonar.exclusions", "src/textFixtures/xtext-gen/**") | ||
99 | } | ||
100 | |||
101 | eclipse.project.natures.plusAssign("org.eclipse.xtext.ui.shared.xtextNature") | ||
diff --git a/subprojects/language/src/main/java/tools/refinery/language/GenerateProblem.mwe2 b/subprojects/language/src/main/java/tools/refinery/language/GenerateProblem.mwe2 index 21ff456e..59eba8f7 100644 --- a/subprojects/language/src/main/java/tools/refinery/language/GenerateProblem.mwe2 +++ b/subprojects/language/src/main/java/tools/refinery/language/GenerateProblem.mwe2 | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | module tools.refinery.language.GenerateProblem | 6 | module tools.refinery.language.GenerateProblem |
2 | 7 | ||
3 | import org.eclipse.xtext.xtext.generator.* | 8 | import org.eclipse.xtext.xtext.generator.* |
@@ -11,16 +16,28 @@ Workflow { | |||
11 | project = StandardProjectConfig { | 16 | project = StandardProjectConfig { |
12 | baseName = 'language' | 17 | baseName = 'language' |
13 | rootPath = rootPath | 18 | rootPath = rootPath |
19 | runtime = { | ||
20 | // Do not generate new files into src/main/java | ||
21 | src = null | ||
22 | } | ||
14 | runtimeTest = { | 23 | runtimeTest = { |
15 | enabled = true | 24 | enabled = true |
16 | srcGen = 'src/testFixtures/xtext-gen' | 25 | // Only generate the xtext-gen files and leave the rest of the project alone |
26 | root = null | ||
27 | srcGen = '${rootPath}/language/src/testFixtures/xtext-gen' | ||
17 | } | 28 | } |
18 | genericIde = { | 29 | genericIde = { |
19 | name = 'language-ide' | 30 | name = 'language-ide' |
31 | // Only generate the xtext-gen files and leave the rest of the project alone | ||
32 | root = null | ||
33 | srcGen = "${rootPath}/language/build/generated/sources/xtext/ide" | ||
20 | } | 34 | } |
21 | web = { | 35 | web = { |
22 | enabled = true | 36 | enabled = true |
23 | name = 'language-web' | 37 | name = 'language-web' |
38 | // Only generate the xtext-gen files and leave the rest of the project alone | ||
39 | root = null | ||
40 | srcGen = "${rootPath}/language/build/generated/sources/xtext/web" | ||
24 | } | 41 | } |
25 | mavenLayout = true | 42 | mavenLayout = true |
26 | } | 43 | } |
@@ -55,7 +72,7 @@ Workflow { | |||
55 | } | 72 | } |
56 | webSupport = { | 73 | webSupport = { |
57 | // We only generate the {@code AbstractProblemWebModule}, | 74 | // We only generate the {@code AbstractProblemWebModule}, |
58 | // because we write our own integration code for CodeMirror 6. | 75 | // because we write our own integration code for CodeMirror 6. |
59 | framework = 'codemirror' | 76 | framework = 'codemirror' |
60 | generateHtmlExample = false | 77 | generateHtmlExample = false |
61 | generateJettyLauncher = false | 78 | generateJettyLauncher = false |
diff --git a/subprojects/language/src/main/java/tools/refinery/language/Problem.xtext b/subprojects/language/src/main/java/tools/refinery/language/Problem.xtext index 187ebf1f..9e330347 100644 --- a/subprojects/language/src/main/java/tools/refinery/language/Problem.xtext +++ b/subprojects/language/src/main/java/tools/refinery/language/Problem.xtext | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | grammar tools.refinery.language.Problem with org.eclipse.xtext.common.Terminals | 6 | grammar tools.refinery.language.Problem with org.eclipse.xtext.common.Terminals |
2 | 7 | ||
3 | import "http://www.eclipse.org/emf/2002/Ecore" as ecore | 8 | import "http://www.eclipse.org/emf/2002/Ecore" as ecore |
diff --git a/subprojects/language/src/main/java/tools/refinery/language/ProblemRuntimeModule.java b/subprojects/language/src/main/java/tools/refinery/language/ProblemRuntimeModule.java index 5efcdc81..2636a8ee 100644 --- a/subprojects/language/src/main/java/tools/refinery/language/ProblemRuntimeModule.java +++ b/subprojects/language/src/main/java/tools/refinery/language/ProblemRuntimeModule.java | |||
@@ -1,4 +1,10 @@ | |||
1 | /* | 1 | /* |
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
7 | /* | ||
2 | * generated by Xtext 2.25.0 | 8 | * generated by Xtext 2.25.0 |
3 | */ | 9 | */ |
4 | package tools.refinery.language; | 10 | package tools.refinery.language; |
diff --git a/subprojects/language/src/main/java/tools/refinery/language/ProblemStandaloneSetup.java b/subprojects/language/src/main/java/tools/refinery/language/ProblemStandaloneSetup.java index 41c96114..639d6778 100644 --- a/subprojects/language/src/main/java/tools/refinery/language/ProblemStandaloneSetup.java +++ b/subprojects/language/src/main/java/tools/refinery/language/ProblemStandaloneSetup.java | |||
@@ -1,4 +1,10 @@ | |||
1 | /* | 1 | /* |
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
7 | /* | ||
2 | * generated by Xtext 2.25.0 | 8 | * generated by Xtext 2.25.0 |
3 | */ | 9 | */ |
4 | package tools.refinery.language; | 10 | package tools.refinery.language; |
diff --git a/subprojects/language/src/main/java/tools/refinery/language/conversion/ProblemValueConverterService.java b/subprojects/language/src/main/java/tools/refinery/language/conversion/ProblemValueConverterService.java index 508688ed..afbc367e 100644 --- a/subprojects/language/src/main/java/tools/refinery/language/conversion/ProblemValueConverterService.java +++ b/subprojects/language/src/main/java/tools/refinery/language/conversion/ProblemValueConverterService.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.conversion; | 6 | package tools.refinery.language.conversion; |
2 | 7 | ||
3 | import org.eclipse.xtext.common.services.DefaultTerminalConverters; | 8 | import org.eclipse.xtext.common.services.DefaultTerminalConverters; |
diff --git a/subprojects/language/src/main/java/tools/refinery/language/conversion/UpperBoundValueConverter.java b/subprojects/language/src/main/java/tools/refinery/language/conversion/UpperBoundValueConverter.java index be0d15ad..4886757d 100644 --- a/subprojects/language/src/main/java/tools/refinery/language/conversion/UpperBoundValueConverter.java +++ b/subprojects/language/src/main/java/tools/refinery/language/conversion/UpperBoundValueConverter.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.conversion; | 6 | package tools.refinery.language.conversion; |
2 | 7 | ||
3 | import org.eclipse.xtext.conversion.ValueConverterException; | 8 | import org.eclipse.xtext.conversion.ValueConverterException; |
diff --git a/subprojects/language/src/main/java/tools/refinery/language/formatting2/ProblemFormatter.java b/subprojects/language/src/main/java/tools/refinery/language/formatting2/ProblemFormatter.java index 797535ea..55a5ac20 100644 --- a/subprojects/language/src/main/java/tools/refinery/language/formatting2/ProblemFormatter.java +++ b/subprojects/language/src/main/java/tools/refinery/language/formatting2/ProblemFormatter.java | |||
@@ -1,4 +1,10 @@ | |||
1 | /* | 1 | /* |
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
7 | /* | ||
2 | * generated by Xtext 2.26.0.M2 | 8 | * generated by Xtext 2.26.0.M2 |
3 | */ | 9 | */ |
4 | package tools.refinery.language.formatting2; | 10 | package tools.refinery.language.formatting2; |
diff --git a/subprojects/language/src/main/java/tools/refinery/language/naming/NamingUtil.java b/subprojects/language/src/main/java/tools/refinery/language/naming/NamingUtil.java index e959be74..1647d4e7 100644 --- a/subprojects/language/src/main/java/tools/refinery/language/naming/NamingUtil.java +++ b/subprojects/language/src/main/java/tools/refinery/language/naming/NamingUtil.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.naming; | 6 | package tools.refinery.language.naming; |
2 | 7 | ||
3 | import java.util.regex.Pattern; | 8 | import java.util.regex.Pattern; |
diff --git a/subprojects/language/src/main/java/tools/refinery/language/naming/ProblemQualifiedNameConverter.java b/subprojects/language/src/main/java/tools/refinery/language/naming/ProblemQualifiedNameConverter.java index 5453906f..74b4e208 100644 --- a/subprojects/language/src/main/java/tools/refinery/language/naming/ProblemQualifiedNameConverter.java +++ b/subprojects/language/src/main/java/tools/refinery/language/naming/ProblemQualifiedNameConverter.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.naming; | 6 | package tools.refinery.language.naming; |
2 | 7 | ||
3 | import org.eclipse.xtext.naming.IQualifiedNameConverter; | 8 | import org.eclipse.xtext.naming.IQualifiedNameConverter; |
diff --git a/subprojects/language/src/main/java/tools/refinery/language/parser/antlr/IdentifierTokenProvider.java b/subprojects/language/src/main/java/tools/refinery/language/parser/antlr/IdentifierTokenProvider.java index ab133a90..306a86fc 100644 --- a/subprojects/language/src/main/java/tools/refinery/language/parser/antlr/IdentifierTokenProvider.java +++ b/subprojects/language/src/main/java/tools/refinery/language/parser/antlr/IdentifierTokenProvider.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.parser.antlr; | 6 | package tools.refinery.language.parser.antlr; |
2 | 7 | ||
3 | import com.google.inject.Inject; | 8 | import com.google.inject.Inject; |
diff --git a/subprojects/language/src/main/java/tools/refinery/language/parser/antlr/ProblemTokenSource.java b/subprojects/language/src/main/java/tools/refinery/language/parser/antlr/ProblemTokenSource.java index 0b4e7185..5b91a6cc 100644 --- a/subprojects/language/src/main/java/tools/refinery/language/parser/antlr/ProblemTokenSource.java +++ b/subprojects/language/src/main/java/tools/refinery/language/parser/antlr/ProblemTokenSource.java | |||
@@ -1,4 +1,10 @@ | |||
1 | /* | 1 | /* |
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
7 | /* | ||
2 | * generated by Xtext 2.29.0.M2 | 8 | * generated by Xtext 2.29.0.M2 |
3 | */ | 9 | */ |
4 | package tools.refinery.language.parser.antlr; | 10 | package tools.refinery.language.parser.antlr; |
diff --git a/subprojects/language/src/main/java/tools/refinery/language/parser/antlr/TokenSourceInjectingProblemParser.java b/subprojects/language/src/main/java/tools/refinery/language/parser/antlr/TokenSourceInjectingProblemParser.java index 0cdd38d8..fe4c0bc7 100644 --- a/subprojects/language/src/main/java/tools/refinery/language/parser/antlr/TokenSourceInjectingProblemParser.java +++ b/subprojects/language/src/main/java/tools/refinery/language/parser/antlr/TokenSourceInjectingProblemParser.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.parser.antlr; | 6 | package tools.refinery.language.parser.antlr; |
2 | 7 | ||
3 | import com.google.inject.Inject; | 8 | import com.google.inject.Inject; |
diff --git a/subprojects/language/src/main/java/tools/refinery/language/resource/DerivedVariableComputer.java b/subprojects/language/src/main/java/tools/refinery/language/resource/DerivedVariableComputer.java index 6176b0c4..07c5da41 100644 --- a/subprojects/language/src/main/java/tools/refinery/language/resource/DerivedVariableComputer.java +++ b/subprojects/language/src/main/java/tools/refinery/language/resource/DerivedVariableComputer.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.resource; | 6 | package tools.refinery.language.resource; |
2 | 7 | ||
3 | import com.google.inject.Inject; | 8 | import com.google.inject.Inject; |
diff --git a/subprojects/language/src/main/java/tools/refinery/language/resource/ImplicitVariableScope.java b/subprojects/language/src/main/java/tools/refinery/language/resource/ImplicitVariableScope.java index b0ac2ab6..e97c8287 100644 --- a/subprojects/language/src/main/java/tools/refinery/language/resource/ImplicitVariableScope.java +++ b/subprojects/language/src/main/java/tools/refinery/language/resource/ImplicitVariableScope.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.resource; | 6 | package tools.refinery.language.resource; |
2 | 7 | ||
3 | import org.eclipse.emf.ecore.EObject; | 8 | import org.eclipse.emf.ecore.EObject; |
diff --git a/subprojects/language/src/main/java/tools/refinery/language/resource/NodeNameCollector.java b/subprojects/language/src/main/java/tools/refinery/language/resource/NodeNameCollector.java index 419be0d3..e5deca4d 100644 --- a/subprojects/language/src/main/java/tools/refinery/language/resource/NodeNameCollector.java +++ b/subprojects/language/src/main/java/tools/refinery/language/resource/NodeNameCollector.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.resource; | 6 | package tools.refinery.language.resource; |
2 | 7 | ||
3 | import com.google.common.collect.ImmutableSet; | 8 | import com.google.common.collect.ImmutableSet; |
diff --git a/subprojects/language/src/main/java/tools/refinery/language/resource/ProblemDerivedStateComputer.java b/subprojects/language/src/main/java/tools/refinery/language/resource/ProblemDerivedStateComputer.java index 8d3a552a..b145ef27 100644 --- a/subprojects/language/src/main/java/tools/refinery/language/resource/ProblemDerivedStateComputer.java +++ b/subprojects/language/src/main/java/tools/refinery/language/resource/ProblemDerivedStateComputer.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.resource; | 6 | package tools.refinery.language.resource; |
2 | 7 | ||
3 | import com.google.inject.Inject; | 8 | import com.google.inject.Inject; |
diff --git a/subprojects/language/src/main/java/tools/refinery/language/resource/ProblemLocationInFileProvider.java b/subprojects/language/src/main/java/tools/refinery/language/resource/ProblemLocationInFileProvider.java index df822987..1fe2df89 100644 --- a/subprojects/language/src/main/java/tools/refinery/language/resource/ProblemLocationInFileProvider.java +++ b/subprojects/language/src/main/java/tools/refinery/language/resource/ProblemLocationInFileProvider.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.resource; | 6 | package tools.refinery.language.resource; |
2 | 7 | ||
3 | import org.eclipse.emf.ecore.EObject; | 8 | import org.eclipse.emf.ecore.EObject; |
diff --git a/subprojects/language/src/main/java/tools/refinery/language/resource/ProblemResourceDescriptionStrategy.java b/subprojects/language/src/main/java/tools/refinery/language/resource/ProblemResourceDescriptionStrategy.java index 1a0b73a8..630be379 100644 --- a/subprojects/language/src/main/java/tools/refinery/language/resource/ProblemResourceDescriptionStrategy.java +++ b/subprojects/language/src/main/java/tools/refinery/language/resource/ProblemResourceDescriptionStrategy.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.resource; | 6 | package tools.refinery.language.resource; |
2 | 7 | ||
3 | import org.eclipse.emf.ecore.EObject; | 8 | import org.eclipse.emf.ecore.EObject; |
diff --git a/subprojects/language/src/main/java/tools/refinery/language/resource/ReferenceCounter.java b/subprojects/language/src/main/java/tools/refinery/language/resource/ReferenceCounter.java index ca20325e..f1be55ee 100644 --- a/subprojects/language/src/main/java/tools/refinery/language/resource/ReferenceCounter.java +++ b/subprojects/language/src/main/java/tools/refinery/language/resource/ReferenceCounter.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.resource; | 6 | package tools.refinery.language.resource; |
2 | 7 | ||
3 | import java.util.HashMap; | 8 | import java.util.HashMap; |
diff --git a/subprojects/language/src/main/java/tools/refinery/language/scoping/ProblemGlobalScopeProvider.java b/subprojects/language/src/main/java/tools/refinery/language/scoping/ProblemGlobalScopeProvider.java index b749154c..4d2dd772 100644 --- a/subprojects/language/src/main/java/tools/refinery/language/scoping/ProblemGlobalScopeProvider.java +++ b/subprojects/language/src/main/java/tools/refinery/language/scoping/ProblemGlobalScopeProvider.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.scoping; | 6 | package tools.refinery.language.scoping; |
2 | 7 | ||
3 | import java.util.LinkedHashSet; | 8 | import java.util.LinkedHashSet; |
diff --git a/subprojects/language/src/main/java/tools/refinery/language/scoping/ProblemLocalScopeProvider.java b/subprojects/language/src/main/java/tools/refinery/language/scoping/ProblemLocalScopeProvider.java index 61883f0e..229960a0 100644 --- a/subprojects/language/src/main/java/tools/refinery/language/scoping/ProblemLocalScopeProvider.java +++ b/subprojects/language/src/main/java/tools/refinery/language/scoping/ProblemLocalScopeProvider.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.scoping; | 6 | package tools.refinery.language.scoping; |
2 | 7 | ||
3 | import java.util.List; | 8 | import java.util.List; |
diff --git a/subprojects/language/src/main/java/tools/refinery/language/scoping/ProblemScopeProvider.java b/subprojects/language/src/main/java/tools/refinery/language/scoping/ProblemScopeProvider.java index 3ab07496..cf099aba 100644 --- a/subprojects/language/src/main/java/tools/refinery/language/scoping/ProblemScopeProvider.java +++ b/subprojects/language/src/main/java/tools/refinery/language/scoping/ProblemScopeProvider.java | |||
@@ -1,4 +1,10 @@ | |||
1 | /* | 1 | /* |
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
7 | /* | ||
2 | * generated by Xtext 2.25.0 | 8 | * generated by Xtext 2.25.0 |
3 | */ | 9 | */ |
4 | package tools.refinery.language.scoping; | 10 | package tools.refinery.language.scoping; |
diff --git a/subprojects/language/src/main/java/tools/refinery/language/serializer/PreferShortAssertionsProblemSemanticSequencer.java b/subprojects/language/src/main/java/tools/refinery/language/serializer/PreferShortAssertionsProblemSemanticSequencer.java index 27ce1521..b9cafbc2 100644 --- a/subprojects/language/src/main/java/tools/refinery/language/serializer/PreferShortAssertionsProblemSemanticSequencer.java +++ b/subprojects/language/src/main/java/tools/refinery/language/serializer/PreferShortAssertionsProblemSemanticSequencer.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.serializer; | 6 | package tools.refinery.language.serializer; |
2 | 7 | ||
3 | import com.google.inject.Inject; | 8 | import com.google.inject.Inject; |
diff --git a/subprojects/language/src/main/java/tools/refinery/language/utils/BuiltinSymbols.java b/subprojects/language/src/main/java/tools/refinery/language/utils/BuiltinSymbols.java index d3777cd3..c8c7fd4a 100644 --- a/subprojects/language/src/main/java/tools/refinery/language/utils/BuiltinSymbols.java +++ b/subprojects/language/src/main/java/tools/refinery/language/utils/BuiltinSymbols.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.utils; | 6 | package tools.refinery.language.utils; |
2 | 7 | ||
3 | import tools.refinery.language.model.problem.*; | 8 | import tools.refinery.language.model.problem.*; |
diff --git a/subprojects/language/src/main/java/tools/refinery/language/utils/CollectedSymbols.java b/subprojects/language/src/main/java/tools/refinery/language/utils/CollectedSymbols.java index b5682f32..e4e4d07a 100644 --- a/subprojects/language/src/main/java/tools/refinery/language/utils/CollectedSymbols.java +++ b/subprojects/language/src/main/java/tools/refinery/language/utils/CollectedSymbols.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.utils; | 6 | package tools.refinery.language.utils; |
2 | 7 | ||
3 | import java.util.Map; | 8 | import java.util.Map; |
diff --git a/subprojects/language/src/main/java/tools/refinery/language/utils/ContainmentRole.java b/subprojects/language/src/main/java/tools/refinery/language/utils/ContainmentRole.java index 708e10a9..a43c7dfe 100644 --- a/subprojects/language/src/main/java/tools/refinery/language/utils/ContainmentRole.java +++ b/subprojects/language/src/main/java/tools/refinery/language/utils/ContainmentRole.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.utils; | 6 | package tools.refinery.language.utils; |
2 | 7 | ||
3 | import tools.refinery.language.model.problem.PredicateKind; | 8 | import tools.refinery.language.model.problem.PredicateKind; |
diff --git a/subprojects/language/src/main/java/tools/refinery/language/utils/NodeInfo.java b/subprojects/language/src/main/java/tools/refinery/language/utils/NodeInfo.java index c8f47653..0fa7a454 100644 --- a/subprojects/language/src/main/java/tools/refinery/language/utils/NodeInfo.java +++ b/subprojects/language/src/main/java/tools/refinery/language/utils/NodeInfo.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.utils; | 6 | package tools.refinery.language.utils; |
2 | 7 | ||
3 | public record NodeInfo(String name, boolean individual) { | 8 | public record NodeInfo(String name, boolean individual) { |
diff --git a/subprojects/language/src/main/java/tools/refinery/language/utils/ProblemDesugarer.java b/subprojects/language/src/main/java/tools/refinery/language/utils/ProblemDesugarer.java index b8200919..738a0896 100644 --- a/subprojects/language/src/main/java/tools/refinery/language/utils/ProblemDesugarer.java +++ b/subprojects/language/src/main/java/tools/refinery/language/utils/ProblemDesugarer.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.utils; | 6 | package tools.refinery.language.utils; |
2 | 7 | ||
3 | import com.google.inject.Inject; | 8 | import com.google.inject.Inject; |
diff --git a/subprojects/language/src/main/java/tools/refinery/language/utils/ProblemUtil.java b/subprojects/language/src/main/java/tools/refinery/language/utils/ProblemUtil.java index 1e5164d3..9486dc2a 100644 --- a/subprojects/language/src/main/java/tools/refinery/language/utils/ProblemUtil.java +++ b/subprojects/language/src/main/java/tools/refinery/language/utils/ProblemUtil.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.utils; | 6 | package tools.refinery.language.utils; |
2 | 7 | ||
3 | import org.eclipse.emf.common.util.URI; | 8 | import org.eclipse.emf.common.util.URI; |
diff --git a/subprojects/language/src/main/java/tools/refinery/language/utils/RelationInfo.java b/subprojects/language/src/main/java/tools/refinery/language/utils/RelationInfo.java index 2253d257..1c46fe72 100644 --- a/subprojects/language/src/main/java/tools/refinery/language/utils/RelationInfo.java +++ b/subprojects/language/src/main/java/tools/refinery/language/utils/RelationInfo.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.utils; | 6 | package tools.refinery.language.utils; |
2 | 7 | ||
3 | import tools.refinery.language.model.problem.*; | 8 | import tools.refinery.language.model.problem.*; |
diff --git a/subprojects/language/src/main/java/tools/refinery/language/utils/SymbolCollector.java b/subprojects/language/src/main/java/tools/refinery/language/utils/SymbolCollector.java index 65167ed6..a4ea1113 100644 --- a/subprojects/language/src/main/java/tools/refinery/language/utils/SymbolCollector.java +++ b/subprojects/language/src/main/java/tools/refinery/language/utils/SymbolCollector.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.utils; | 6 | package tools.refinery.language.utils; |
2 | 7 | ||
3 | import com.google.inject.Inject; | 8 | import com.google.inject.Inject; |
diff --git a/subprojects/language/src/main/java/tools/refinery/language/validation/ProblemValidator.java b/subprojects/language/src/main/java/tools/refinery/language/validation/ProblemValidator.java index 659d882c..88d50c5b 100644 --- a/subprojects/language/src/main/java/tools/refinery/language/validation/ProblemValidator.java +++ b/subprojects/language/src/main/java/tools/refinery/language/validation/ProblemValidator.java | |||
@@ -1,4 +1,10 @@ | |||
1 | /* | 1 | /* |
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
7 | /* | ||
2 | * generated by Xtext 2.25.0 | 8 | * generated by Xtext 2.25.0 |
3 | */ | 9 | */ |
4 | package tools.refinery.language.validation; | 10 | package tools.refinery.language.validation; |
diff --git a/subprojects/language/src/main/resources/tools/refinery/language/builtin.problem b/subprojects/language/src/main/resources/tools/refinery/language/builtin.problem index 06b6da1d..9c1d7669 100644 --- a/subprojects/language/src/main/resources/tools/refinery/language/builtin.problem +++ b/subprojects/language/src/main/resources/tools/refinery/language/builtin.problem | |||
@@ -1,3 +1,6 @@ | |||
1 | % SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
2 | % | ||
3 | % SPDX-License-Identifier: EPL-2.0 | ||
1 | problem builtin. | 4 | problem builtin. |
2 | 5 | ||
3 | abstract class node { | 6 | abstract class node { |
diff --git a/subprojects/language/src/test/java/tools/refinery/language/tests/ProblemParsingTest.java b/subprojects/language/src/test/java/tools/refinery/language/tests/ProblemParsingTest.java index 58daa365..c7952369 100644 --- a/subprojects/language/src/test/java/tools/refinery/language/tests/ProblemParsingTest.java +++ b/subprojects/language/src/test/java/tools/refinery/language/tests/ProblemParsingTest.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.tests; | 6 | package tools.refinery.language.tests; |
2 | 7 | ||
3 | import com.google.inject.Inject; | 8 | import com.google.inject.Inject; |
diff --git a/subprojects/language/src/test/java/tools/refinery/language/tests/formatting2/ProblemFormatterTest.java b/subprojects/language/src/test/java/tools/refinery/language/tests/formatting2/ProblemFormatterTest.java index 6e0802ca..f688d970 100644 --- a/subprojects/language/src/test/java/tools/refinery/language/tests/formatting2/ProblemFormatterTest.java +++ b/subprojects/language/src/test/java/tools/refinery/language/tests/formatting2/ProblemFormatterTest.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.tests.formatting2; | 6 | package tools.refinery.language.tests.formatting2; |
2 | 7 | ||
3 | import com.google.inject.Inject; | 8 | import com.google.inject.Inject; |
diff --git a/subprojects/language/src/test/java/tools/refinery/language/tests/parser/antlr/IdentifierTokenProviderTest.java b/subprojects/language/src/test/java/tools/refinery/language/tests/parser/antlr/IdentifierTokenProviderTest.java index abff8d9c..37d38dd9 100644 --- a/subprojects/language/src/test/java/tools/refinery/language/tests/parser/antlr/IdentifierTokenProviderTest.java +++ b/subprojects/language/src/test/java/tools/refinery/language/tests/parser/antlr/IdentifierTokenProviderTest.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.tests.parser.antlr; | 6 | package tools.refinery.language.tests.parser.antlr; |
2 | 7 | ||
3 | import com.google.inject.Inject; | 8 | import com.google.inject.Inject; |
diff --git a/subprojects/language/src/test/java/tools/refinery/language/tests/parser/antlr/ProblemTokenSourceTest.java b/subprojects/language/src/test/java/tools/refinery/language/tests/parser/antlr/ProblemTokenSourceTest.java index cb42d5d0..644744a0 100644 --- a/subprojects/language/src/test/java/tools/refinery/language/tests/parser/antlr/ProblemTokenSourceTest.java +++ b/subprojects/language/src/test/java/tools/refinery/language/tests/parser/antlr/ProblemTokenSourceTest.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.tests.parser.antlr; | 6 | package tools.refinery.language.tests.parser.antlr; |
2 | 7 | ||
3 | import com.google.inject.Inject; | 8 | import com.google.inject.Inject; |
diff --git a/subprojects/language/src/test/java/tools/refinery/language/tests/parser/antlr/TransitiveClosureParserTest.java b/subprojects/language/src/test/java/tools/refinery/language/tests/parser/antlr/TransitiveClosureParserTest.java index 65ceb45f..1180d131 100644 --- a/subprojects/language/src/test/java/tools/refinery/language/tests/parser/antlr/TransitiveClosureParserTest.java +++ b/subprojects/language/src/test/java/tools/refinery/language/tests/parser/antlr/TransitiveClosureParserTest.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.tests.parser.antlr; | 6 | package tools.refinery.language.tests.parser.antlr; |
2 | 7 | ||
3 | import com.google.inject.Inject; | 8 | import com.google.inject.Inject; |
diff --git a/subprojects/language/src/test/java/tools/refinery/language/tests/rules/RuleParsingTest.java b/subprojects/language/src/test/java/tools/refinery/language/tests/rules/RuleParsingTest.java index 72e5e18a..68514bfa 100644 --- a/subprojects/language/src/test/java/tools/refinery/language/tests/rules/RuleParsingTest.java +++ b/subprojects/language/src/test/java/tools/refinery/language/tests/rules/RuleParsingTest.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.tests.rules; | 6 | package tools.refinery.language.tests.rules; |
2 | 7 | ||
3 | import com.google.inject.Inject; | 8 | import com.google.inject.Inject; |
diff --git a/subprojects/language/src/test/java/tools/refinery/language/tests/scoping/NodeScopingTest.java b/subprojects/language/src/test/java/tools/refinery/language/tests/scoping/NodeScopingTest.java index fa462691..734bfcd1 100644 --- a/subprojects/language/src/test/java/tools/refinery/language/tests/scoping/NodeScopingTest.java +++ b/subprojects/language/src/test/java/tools/refinery/language/tests/scoping/NodeScopingTest.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.tests.scoping; | 6 | package tools.refinery.language.tests.scoping; |
2 | 7 | ||
3 | import com.google.inject.Inject; | 8 | import com.google.inject.Inject; |
diff --git a/subprojects/language/src/test/java/tools/refinery/language/tests/serializer/ProblemSerializerTest.java b/subprojects/language/src/test/java/tools/refinery/language/tests/serializer/ProblemSerializerTest.java index 4a18704a..3f3a081f 100644 --- a/subprojects/language/src/test/java/tools/refinery/language/tests/serializer/ProblemSerializerTest.java +++ b/subprojects/language/src/test/java/tools/refinery/language/tests/serializer/ProblemSerializerTest.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.tests.serializer; | 6 | package tools.refinery.language.tests.serializer; |
2 | 7 | ||
3 | import com.google.inject.Inject; | 8 | import com.google.inject.Inject; |
diff --git a/subprojects/language/src/test/java/tools/refinery/language/tests/utils/SymbolCollectorTest.java b/subprojects/language/src/test/java/tools/refinery/language/tests/utils/SymbolCollectorTest.java index af6de37f..d200eeff 100644 --- a/subprojects/language/src/test/java/tools/refinery/language/tests/utils/SymbolCollectorTest.java +++ b/subprojects/language/src/test/java/tools/refinery/language/tests/utils/SymbolCollectorTest.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.tests.utils; | 6 | package tools.refinery.language.tests.utils; |
2 | 7 | ||
3 | import com.google.inject.Inject; | 8 | import com.google.inject.Inject; |
diff --git a/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/ProblemNavigationUtil.java b/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/ProblemNavigationUtil.java index 5761935b..d92011a9 100644 --- a/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/ProblemNavigationUtil.java +++ b/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/ProblemNavigationUtil.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.model.tests.utils; | 6 | package tools.refinery.language.model.tests.utils; |
2 | 7 | ||
3 | import java.util.List; | 8 | import java.util.List; |
diff --git a/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/ProblemParseHelper.java b/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/ProblemParseHelper.java index 5e044a94..6f6a87f7 100644 --- a/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/ProblemParseHelper.java +++ b/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/ProblemParseHelper.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.model.tests.utils; | 6 | package tools.refinery.language.model.tests.utils; |
2 | 7 | ||
3 | import org.eclipse.xtext.testing.util.ParseHelper; | 8 | import org.eclipse.xtext.testing.util.ParseHelper; |
diff --git a/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedAction.java b/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedAction.java index d176727b..3a49a0b9 100644 --- a/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedAction.java +++ b/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedAction.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.model.tests.utils; | 6 | package tools.refinery.language.model.tests.utils; |
2 | 7 | ||
3 | import tools.refinery.language.model.problem.Action; | 8 | import tools.refinery.language.model.problem.Action; |
diff --git a/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedArgument.java b/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedArgument.java index 9e4c59f5..ed749fed 100644 --- a/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedArgument.java +++ b/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedArgument.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.model.tests.utils; | 6 | package tools.refinery.language.model.tests.utils; |
2 | 7 | ||
3 | import tools.refinery.language.model.problem.*; | 8 | import tools.refinery.language.model.problem.*; |
diff --git a/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedAssertion.java b/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedAssertion.java index 2c38639d..b2ef6e48 100644 --- a/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedAssertion.java +++ b/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedAssertion.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.model.tests.utils; | 6 | package tools.refinery.language.model.tests.utils; |
2 | 7 | ||
3 | import tools.refinery.language.model.problem.Assertion; | 8 | import tools.refinery.language.model.problem.Assertion; |
diff --git a/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedAssertionArgument.java b/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedAssertionArgument.java index 840c1f74..b36f2506 100644 --- a/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedAssertionArgument.java +++ b/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedAssertionArgument.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.model.tests.utils; | 6 | package tools.refinery.language.model.tests.utils; |
2 | 7 | ||
3 | import tools.refinery.language.model.problem.AssertionArgument; | 8 | import tools.refinery.language.model.problem.AssertionArgument; |
diff --git a/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedAtom.java b/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedAtom.java index 498991f8..c02f447b 100644 --- a/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedAtom.java +++ b/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedAtom.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.model.tests.utils; | 6 | package tools.refinery.language.model.tests.utils; |
2 | 7 | ||
3 | import tools.refinery.language.model.problem.Atom; | 8 | import tools.refinery.language.model.problem.Atom; |
diff --git a/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedClassDeclaration.java b/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedClassDeclaration.java index 41b2ea62..a228137c 100644 --- a/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedClassDeclaration.java +++ b/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedClassDeclaration.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.model.tests.utils; | 6 | package tools.refinery.language.model.tests.utils; |
2 | 7 | ||
3 | import tools.refinery.language.model.problem.ClassDeclaration; | 8 | import tools.refinery.language.model.problem.ClassDeclaration; |
diff --git a/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedConjunction.java b/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedConjunction.java index 88ff71ab..b126b1ce 100644 --- a/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedConjunction.java +++ b/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedConjunction.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.model.tests.utils; | 6 | package tools.refinery.language.model.tests.utils; |
2 | 7 | ||
3 | import tools.refinery.language.model.problem.Conjunction; | 8 | import tools.refinery.language.model.problem.Conjunction; |
diff --git a/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedConsequent.java b/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedConsequent.java index 46faa7da..8d6a92f8 100644 --- a/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedConsequent.java +++ b/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedConsequent.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.model.tests.utils; | 6 | package tools.refinery.language.model.tests.utils; |
2 | 7 | ||
3 | import tools.refinery.language.model.problem.Consequent; | 8 | import tools.refinery.language.model.problem.Consequent; |
diff --git a/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedEnumDeclaration.java b/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedEnumDeclaration.java index 74dcf01b..229a8c0a 100644 --- a/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedEnumDeclaration.java +++ b/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedEnumDeclaration.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.model.tests.utils; | 6 | package tools.refinery.language.model.tests.utils; |
2 | 7 | ||
3 | import tools.refinery.language.model.problem.EnumDeclaration; | 8 | import tools.refinery.language.model.problem.EnumDeclaration; |
diff --git a/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedLiteral.java b/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedLiteral.java index 4aa71b99..160e5dd8 100644 --- a/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedLiteral.java +++ b/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedLiteral.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.model.tests.utils; | 6 | package tools.refinery.language.model.tests.utils; |
2 | 7 | ||
3 | import tools.refinery.language.model.problem.Atom; | 8 | import tools.refinery.language.model.problem.Atom; |
diff --git a/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedParametricDefinition.java b/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedParametricDefinition.java index c2f18a60..d44b79ed 100644 --- a/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedParametricDefinition.java +++ b/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedParametricDefinition.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.model.tests.utils; | 6 | package tools.refinery.language.model.tests.utils; |
2 | 7 | ||
3 | import tools.refinery.language.model.problem.Parameter; | 8 | import tools.refinery.language.model.problem.Parameter; |
diff --git a/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedPredicateDefinition.java b/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedPredicateDefinition.java index 7b95ecc1..2cf5fd89 100644 --- a/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedPredicateDefinition.java +++ b/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedPredicateDefinition.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.model.tests.utils; | 6 | package tools.refinery.language.model.tests.utils; |
2 | 7 | ||
3 | import tools.refinery.language.model.problem.PredicateDefinition; | 8 | import tools.refinery.language.model.problem.PredicateDefinition; |
diff --git a/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedProblem.java b/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedProblem.java index 78ca95c7..e5aa0043 100644 --- a/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedProblem.java +++ b/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedProblem.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.model.tests.utils; | 6 | package tools.refinery.language.model.tests.utils; |
2 | 7 | ||
3 | import org.eclipse.emf.ecore.resource.Resource.Diagnostic; | 8 | import org.eclipse.emf.ecore.resource.Resource.Diagnostic; |
diff --git a/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedRuleDefinition.java b/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedRuleDefinition.java index a4cf2eaf..326d8ec3 100644 --- a/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedRuleDefinition.java +++ b/subprojects/language/src/testFixtures/java/tools/refinery/language/model/tests/utils/WrappedRuleDefinition.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.language.model.tests.utils; | 6 | package tools.refinery.language.model.tests.utils; |
2 | 7 | ||
3 | import tools.refinery.language.model.problem.RuleDefinition; | 8 | import tools.refinery.language.model.problem.RuleDefinition; |
diff --git a/subprojects/store-query-viatra/NOTICE.md b/subprojects/store-query-viatra/NOTICE.md new file mode 100644 index 00000000..7c21726a --- /dev/null +++ b/subprojects/store-query-viatra/NOTICE.md | |||
@@ -0,0 +1,87 @@ | |||
1 | <!-- | ||
2 | Copyright (c) 2018-2019, Zoltan Ujhelyi, IncQuery Labs Ltd. | ||
3 | Copyright (c) 2023 The Refinery Authors <https://refinery.tools/> | ||
4 | |||
5 | SPDX-License-Identifier: EPL-2.0 | ||
6 | --> | ||
7 | |||
8 | This module contains source code from the [Eclipse VIATRA project](https://projects.eclipse.org/projects/modeling.viatra), which is available under the terms of the [Eclipse Public License v 2.0](http://www.eclipse.org/legal/epl-v20.html). | ||
9 | |||
10 | We reproduce the [accompanying notices](https://github.com/viatra/org.eclipse.viatra/blob/d422bcc626a99c4640c0d13931f393ccea0d2326/NOTICE.md) in full below: | ||
11 | |||
12 | # Notices for Eclipse VIATRA | ||
13 | |||
14 | This content is produced and maintained by the Eclipse VIATRA project. | ||
15 | |||
16 | * Project home: https://projects.eclipse.org/projects/modeling.viatra | ||
17 | |||
18 | ## Trademarks | ||
19 | |||
20 | Eclipse VIATRA, and VIATRA are trademarks of the Eclipse Foundation. | ||
21 | |||
22 | ## Copyright | ||
23 | |||
24 | All content is the property of the respective authors or their employers. For | ||
25 | more information regarding authorship of content, please consult the listed | ||
26 | source code repository logs. | ||
27 | |||
28 | ## Declared Project Licenses | ||
29 | |||
30 | This program and the accompanying materials are made available under the terms | ||
31 | of the Eclipse Public License v. 2.0 which is available at | ||
32 | http://www.eclipse.org/legal/epl-v20.html. | ||
33 | |||
34 | SPDX-License-Identifier: EPL-2.0 | ||
35 | |||
36 | ## Source Code | ||
37 | |||
38 | The project maintains the following source code repositories: | ||
39 | |||
40 | * http://git.eclipse.org/c/viatra/org.eclipse.viatra.git | ||
41 | * http://git.eclipse.org/c/viatra/org.eclipse.viatra.modelobfuscator.git | ||
42 | * http://git.eclipse.org/c/viatra/org.eclipse.viatra.examples.git | ||
43 | * http://git.eclipse.org/c/viatra/org.eclipse.viatra2.vpm.git | ||
44 | |||
45 | ## Third-party Content | ||
46 | |||
47 | This project leverages the following third party content. | ||
48 | |||
49 | ANTLR Runtime only: (3.2) | ||
50 | |||
51 | * License: New BSD license | ||
52 | |||
53 | Apache Commons Language Library (2.1) | ||
54 | |||
55 | * License: Apache License, 2.0 | ||
56 | |||
57 | Google Guice / Inject Core API (3.0.0) | ||
58 | |||
59 | * License: Apache License, 2.0 | ||
60 | |||
61 | Google Guice / Inject Core API (3.0.0) | ||
62 | |||
63 | * License: Apache License 2.0 | ||
64 | |||
65 | Guava (10.0.1) | ||
66 | |||
67 | * License: Apache License, 2.0 | ||
68 | |||
69 | Guice (2.0) | ||
70 | |||
71 | * License: Apache License, 2.0 | ||
72 | |||
73 | guice-multibindings (3.0.0) | ||
74 | |||
75 | * License: Apache License, 2.0 | ||
76 | |||
77 | log4j (1.2.15) | ||
78 | |||
79 | * License: Apache License 2.0 | ||
80 | |||
81 | LPG Java Runtime (lpgjavaruntime.jar) (1.1) | ||
82 | |||
83 | * License: Eclipse Public License | ||
84 | |||
85 | mockito (1.9.5) | ||
86 | |||
87 | * License: Apache License, 2.0, New BSD license, MIT license | ||
diff --git a/subprojects/store-query-viatra/build.gradle b/subprojects/store-query-viatra/build.gradle deleted file mode 100644 index 13a7544f..00000000 --- a/subprojects/store-query-viatra/build.gradle +++ /dev/null | |||
@@ -1,16 +0,0 @@ | |||
1 | plugins { | ||
2 | id 'refinery-java-library' | ||
3 | } | ||
4 | |||
5 | configurations.testRuntimeClasspath { | ||
6 | // VIATRA requires log4j 1.x, but we use log4j-over-slf4j instead | ||
7 | exclude group: 'log4j', module: 'log4j' | ||
8 | } | ||
9 | |||
10 | dependencies { | ||
11 | implementation libs.ecore | ||
12 | api libs.viatra | ||
13 | api project(':refinery-store-query') | ||
14 | testImplementation libs.slf4j.simple | ||
15 | testImplementation libs.slf4j.log4j | ||
16 | } | ||
diff --git a/subprojects/store-query-viatra/build.gradle.kts b/subprojects/store-query-viatra/build.gradle.kts new file mode 100644 index 00000000..e3a22145 --- /dev/null +++ b/subprojects/store-query-viatra/build.gradle.kts | |||
@@ -0,0 +1,15 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
7 | plugins { | ||
8 | id("tools.refinery.gradle.java-library") | ||
9 | } | ||
10 | |||
11 | dependencies { | ||
12 | implementation(libs.ecore) | ||
13 | api(libs.viatra) | ||
14 | api(project(":refinery-store-query")) | ||
15 | } | ||
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraModelQuery.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraModelQuery.java deleted file mode 100644 index 677e3c7d..00000000 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraModelQuery.java +++ /dev/null | |||
@@ -1,21 +0,0 @@ | |||
1 | package tools.refinery.store.query.viatra; | ||
2 | |||
3 | import tools.refinery.store.adapter.ModelAdapterBuilderFactory; | ||
4 | import tools.refinery.store.model.ModelStoreBuilder; | ||
5 | import tools.refinery.store.query.ModelQuery; | ||
6 | import tools.refinery.store.query.viatra.internal.ViatraModelQueryBuilderImpl; | ||
7 | |||
8 | public final class ViatraModelQuery extends ModelAdapterBuilderFactory<ViatraModelQueryAdapter, | ||
9 | ViatraModelQueryStoreAdapter, ViatraModelQueryBuilder> { | ||
10 | public static final ViatraModelQuery ADAPTER = new ViatraModelQuery(); | ||
11 | |||
12 | private ViatraModelQuery() { | ||
13 | super(ViatraModelQueryAdapter.class, ViatraModelQueryStoreAdapter.class, ViatraModelQueryBuilder.class); | ||
14 | extendsAdapter(ModelQuery.ADAPTER); | ||
15 | } | ||
16 | |||
17 | @Override | ||
18 | public ViatraModelQueryBuilder createBuilder(ModelStoreBuilder storeBuilder) { | ||
19 | return new ViatraModelQueryBuilderImpl(storeBuilder); | ||
20 | } | ||
21 | } | ||
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraModelQueryAdapter.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraModelQueryAdapter.java index 7e21476b..12c93f62 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraModelQueryAdapter.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraModelQueryAdapter.java | |||
@@ -1,8 +1,18 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.viatra; | 6 | package tools.refinery.store.query.viatra; |
2 | 7 | ||
3 | import tools.refinery.store.query.ModelQueryAdapter; | 8 | import tools.refinery.store.query.ModelQueryAdapter; |
9 | import tools.refinery.store.query.viatra.internal.ViatraModelQueryBuilderImpl; | ||
4 | 10 | ||
5 | public interface ViatraModelQueryAdapter extends ModelQueryAdapter { | 11 | public interface ViatraModelQueryAdapter extends ModelQueryAdapter { |
6 | @Override | 12 | @Override |
7 | ViatraModelQueryStoreAdapter getStoreAdapter(); | 13 | ViatraModelQueryStoreAdapter getStoreAdapter(); |
14 | |||
15 | static ViatraModelQueryBuilder builder() { | ||
16 | return new ViatraModelQueryBuilderImpl(); | ||
17 | } | ||
8 | } | 18 | } |
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraModelQueryBuilder.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraModelQueryBuilder.java index 7ae86f9f..931a07aa 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraModelQueryBuilder.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraModelQueryBuilder.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.viatra; | 6 | package tools.refinery.store.query.viatra; |
2 | 7 | ||
3 | import org.eclipse.viatra.query.runtime.api.ViatraQueryEngineOptions; | 8 | import org.eclipse.viatra.query.runtime.api.ViatraQueryEngineOptions; |
@@ -45,5 +50,5 @@ public interface ViatraModelQueryBuilder extends ModelQueryBuilder { | |||
45 | ViatraModelQueryBuilder hint(Dnf dnf, QueryEvaluationHint queryEvaluationHint); | 50 | ViatraModelQueryBuilder hint(Dnf dnf, QueryEvaluationHint queryEvaluationHint); |
46 | 51 | ||
47 | @Override | 52 | @Override |
48 | ViatraModelQueryStoreAdapter createStoreAdapter(ModelStore store); | 53 | ViatraModelQueryStoreAdapter build(ModelStore store); |
49 | } | 54 | } |
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraModelQueryStoreAdapter.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraModelQueryStoreAdapter.java index 1ee02f12..da6d7bd5 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraModelQueryStoreAdapter.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/ViatraModelQueryStoreAdapter.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.viatra; | 6 | package tools.refinery.store.query.viatra; |
2 | 7 | ||
3 | import org.eclipse.viatra.query.runtime.api.ViatraQueryEngineOptions; | 8 | import org.eclipse.viatra.query.runtime.api.ViatraQueryEngineOptions; |
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/RelationalScope.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/RelationalScope.java index 8328e759..d1a65a89 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/RelationalScope.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/RelationalScope.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.viatra.internal; | 6 | package tools.refinery.store.query.viatra.internal; |
2 | 7 | ||
3 | import org.apache.log4j.Logger; | 8 | import org.apache.log4j.Logger; |
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryAdapterImpl.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryAdapterImpl.java index 8be30fee..7103a561 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryAdapterImpl.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryAdapterImpl.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.viatra.internal; | 6 | package tools.refinery.store.query.viatra.internal; |
2 | 7 | ||
3 | import org.eclipse.viatra.query.runtime.api.AdvancedViatraQueryEngine; | 8 | import org.eclipse.viatra.query.runtime.api.AdvancedViatraQueryEngine; |
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryBuilderImpl.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryBuilderImpl.java index bfabf26e..ce2467b4 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryBuilderImpl.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryBuilderImpl.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.viatra.internal; | 6 | package tools.refinery.store.query.viatra.internal; |
2 | 7 | ||
3 | import org.eclipse.viatra.query.runtime.api.IQuerySpecification; | 8 | import org.eclipse.viatra.query.runtime.api.IQuerySpecification; |
@@ -20,7 +25,8 @@ import tools.refinery.store.query.viatra.internal.pquery.Dnf2PQuery; | |||
20 | import java.util.*; | 25 | import java.util.*; |
21 | import java.util.function.Function; | 26 | import java.util.function.Function; |
22 | 27 | ||
23 | public class ViatraModelQueryBuilderImpl extends AbstractModelAdapterBuilder implements ViatraModelQueryBuilder { | 28 | public class ViatraModelQueryBuilderImpl extends AbstractModelAdapterBuilder<ViatraModelQueryStoreAdapterImpl> |
29 | implements ViatraModelQueryBuilder { | ||
24 | private ViatraQueryEngineOptions.Builder engineOptionsBuilder; | 30 | private ViatraQueryEngineOptions.Builder engineOptionsBuilder; |
25 | private QueryEvaluationHint defaultHint = new QueryEvaluationHint(Map.of( | 31 | private QueryEvaluationHint defaultHint = new QueryEvaluationHint(Map.of( |
26 | // Use a cost function that ignores the initial (empty) model but allows higher arity input keys. | 32 | // Use a cost function that ignores the initial (empty) model but allows higher arity input keys. |
@@ -30,8 +36,7 @@ public class ViatraModelQueryBuilderImpl extends AbstractModelAdapterBuilder imp | |||
30 | private final Set<AnyQuery> vacuousQueries = new LinkedHashSet<>(); | 36 | private final Set<AnyQuery> vacuousQueries = new LinkedHashSet<>(); |
31 | private final Map<AnyQuery, IQuerySpecification<RawPatternMatcher>> querySpecifications = new LinkedHashMap<>(); | 37 | private final Map<AnyQuery, IQuerySpecification<RawPatternMatcher>> querySpecifications = new LinkedHashMap<>(); |
32 | 38 | ||
33 | public ViatraModelQueryBuilderImpl(ModelStoreBuilder storeBuilder) { | 39 | public ViatraModelQueryBuilderImpl() { |
34 | super(storeBuilder); | ||
35 | engineOptionsBuilder = new ViatraQueryEngineOptions.Builder() | 40 | engineOptionsBuilder = new ViatraQueryEngineOptions.Builder() |
36 | .withDefaultBackend(ReteBackendFactory.INSTANCE) | 41 | .withDefaultBackend(ReteBackendFactory.INSTANCE) |
37 | .withDefaultCachingBackend(ReteBackendFactory.INSTANCE) | 42 | .withDefaultCachingBackend(ReteBackendFactory.INSTANCE) |
@@ -40,36 +45,42 @@ public class ViatraModelQueryBuilderImpl extends AbstractModelAdapterBuilder imp | |||
40 | 45 | ||
41 | @Override | 46 | @Override |
42 | public ViatraModelQueryBuilder engineOptions(ViatraQueryEngineOptions engineOptions) { | 47 | public ViatraModelQueryBuilder engineOptions(ViatraQueryEngineOptions engineOptions) { |
48 | checkNotConfigured(); | ||
43 | engineOptionsBuilder = new ViatraQueryEngineOptions.Builder(engineOptions); | 49 | engineOptionsBuilder = new ViatraQueryEngineOptions.Builder(engineOptions); |
44 | return this; | 50 | return this; |
45 | } | 51 | } |
46 | 52 | ||
47 | @Override | 53 | @Override |
48 | public ViatraModelQueryBuilder defaultHint(QueryEvaluationHint queryEvaluationHint) { | 54 | public ViatraModelQueryBuilder defaultHint(QueryEvaluationHint queryEvaluationHint) { |
55 | checkNotConfigured(); | ||
49 | defaultHint = defaultHint.overrideBy(queryEvaluationHint); | 56 | defaultHint = defaultHint.overrideBy(queryEvaluationHint); |
50 | return this; | 57 | return this; |
51 | } | 58 | } |
52 | 59 | ||
53 | @Override | 60 | @Override |
54 | public ViatraModelQueryBuilder backend(IQueryBackendFactory queryBackendFactory) { | 61 | public ViatraModelQueryBuilder backend(IQueryBackendFactory queryBackendFactory) { |
62 | checkNotConfigured(); | ||
55 | engineOptionsBuilder.withDefaultBackend(queryBackendFactory); | 63 | engineOptionsBuilder.withDefaultBackend(queryBackendFactory); |
56 | return this; | 64 | return this; |
57 | } | 65 | } |
58 | 66 | ||
59 | @Override | 67 | @Override |
60 | public ViatraModelQueryBuilder cachingBackend(IQueryBackendFactory queryBackendFactory) { | 68 | public ViatraModelQueryBuilder cachingBackend(IQueryBackendFactory queryBackendFactory) { |
69 | checkNotConfigured(); | ||
61 | engineOptionsBuilder.withDefaultCachingBackend(queryBackendFactory); | 70 | engineOptionsBuilder.withDefaultCachingBackend(queryBackendFactory); |
62 | return this; | 71 | return this; |
63 | } | 72 | } |
64 | 73 | ||
65 | @Override | 74 | @Override |
66 | public ViatraModelQueryBuilder searchBackend(IQueryBackendFactory queryBackendFactory) { | 75 | public ViatraModelQueryBuilder searchBackend(IQueryBackendFactory queryBackendFactory) { |
76 | checkNotConfigured(); | ||
67 | engineOptionsBuilder.withDefaultSearchBackend(queryBackendFactory); | 77 | engineOptionsBuilder.withDefaultSearchBackend(queryBackendFactory); |
68 | return this; | 78 | return this; |
69 | } | 79 | } |
70 | 80 | ||
71 | @Override | 81 | @Override |
72 | public ViatraModelQueryBuilder query(AnyQuery query) { | 82 | public ViatraModelQueryBuilder query(AnyQuery query) { |
83 | checkNotConfigured(); | ||
73 | if (querySpecifications.containsKey(query) || vacuousQueries.contains(query)) { | 84 | if (querySpecifications.containsKey(query) || vacuousQueries.contains(query)) { |
74 | // Ignore duplicate queries. | 85 | // Ignore duplicate queries. |
75 | return this; | 86 | return this; |
@@ -98,21 +109,27 @@ public class ViatraModelQueryBuilderImpl extends AbstractModelAdapterBuilder imp | |||
98 | 109 | ||
99 | @Override | 110 | @Override |
100 | public ViatraModelQueryBuilder computeHint(Function<Dnf, QueryEvaluationHint> computeHint) { | 111 | public ViatraModelQueryBuilder computeHint(Function<Dnf, QueryEvaluationHint> computeHint) { |
112 | checkNotConfigured(); | ||
101 | dnf2PQuery.setComputeHint(computeHint); | 113 | dnf2PQuery.setComputeHint(computeHint); |
102 | return this; | 114 | return this; |
103 | } | 115 | } |
104 | 116 | ||
105 | @Override | 117 | @Override |
106 | public ViatraModelQueryBuilder hint(Dnf dnf, QueryEvaluationHint queryEvaluationHint) { | 118 | public ViatraModelQueryBuilder hint(Dnf dnf, QueryEvaluationHint queryEvaluationHint) { |
119 | checkNotConfigured(); | ||
107 | dnf2PQuery.hint(dnf, queryEvaluationHint); | 120 | dnf2PQuery.hint(dnf, queryEvaluationHint); |
108 | return this; | 121 | return this; |
109 | } | 122 | } |
110 | 123 | ||
111 | @Override | 124 | @Override |
112 | public ViatraModelQueryStoreAdapterImpl createStoreAdapter(ModelStore store) { | 125 | public void doConfigure(ModelStoreBuilder storeBuilder) { |
113 | validateSymbols(store); | ||
114 | dnf2PQuery.assertNoUnusedHints(); | 126 | dnf2PQuery.assertNoUnusedHints(); |
115 | return new ViatraModelQueryStoreAdapterImpl(store, buildEngineOptions(), dnf2PQuery.getRelationViews(), | 127 | } |
128 | |||
129 | @Override | ||
130 | public ViatraModelQueryStoreAdapterImpl doBuild(ModelStore store) { | ||
131 | validateSymbols(store); | ||
132 | return new ViatraModelQueryStoreAdapterImpl(store, buildEngineOptions(), dnf2PQuery.getSymbolViews(), | ||
116 | Collections.unmodifiableMap(querySpecifications), Collections.unmodifiableSet(vacuousQueries)); | 133 | Collections.unmodifiableMap(querySpecifications), Collections.unmodifiableSet(vacuousQueries)); |
117 | } | 134 | } |
118 | 135 | ||
@@ -135,11 +152,11 @@ public class ViatraModelQueryBuilderImpl extends AbstractModelAdapterBuilder imp | |||
135 | 152 | ||
136 | private void validateSymbols(ModelStore store) { | 153 | private void validateSymbols(ModelStore store) { |
137 | var symbols = store.getSymbols(); | 154 | var symbols = store.getSymbols(); |
138 | for (var relationView : dnf2PQuery.getRelationViews().keySet()) { | 155 | for (var symbolView : dnf2PQuery.getSymbolViews().keySet()) { |
139 | var symbol = relationView.getSymbol(); | 156 | var symbol = symbolView.getSymbol(); |
140 | if (!symbols.contains(symbol)) { | 157 | if (!symbols.contains(symbol)) { |
141 | throw new IllegalArgumentException("Cannot query relation view %s: symbol %s is not in the model" | 158 | throw new IllegalArgumentException("Cannot query view %s: symbol %s is not in the model" |
142 | .formatted(relationView, symbol)); | 159 | .formatted(symbolView, symbol)); |
143 | } | 160 | } |
144 | } | 161 | } |
145 | } | 162 | } |
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryStoreAdapterImpl.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryStoreAdapterImpl.java index 04c48c43..11a3c7fd 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryStoreAdapterImpl.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/ViatraModelQueryStoreAdapterImpl.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.viatra.internal; | 6 | package tools.refinery.store.query.viatra.internal; |
2 | 7 | ||
3 | import org.eclipse.viatra.query.runtime.api.IQuerySpecification; | 8 | import org.eclipse.viatra.query.runtime.api.IQuerySpecification; |
@@ -8,20 +13,20 @@ import tools.refinery.store.model.ModelStore; | |||
8 | import tools.refinery.store.query.dnf.AnyQuery; | 13 | import tools.refinery.store.query.dnf.AnyQuery; |
9 | import tools.refinery.store.query.viatra.ViatraModelQueryStoreAdapter; | 14 | import tools.refinery.store.query.viatra.ViatraModelQueryStoreAdapter; |
10 | import tools.refinery.store.query.viatra.internal.matcher.RawPatternMatcher; | 15 | import tools.refinery.store.query.viatra.internal.matcher.RawPatternMatcher; |
11 | import tools.refinery.store.query.view.AnyRelationView; | 16 | import tools.refinery.store.query.view.AnySymbolView; |
12 | 17 | ||
13 | import java.util.*; | 18 | import java.util.*; |
14 | 19 | ||
15 | public class ViatraModelQueryStoreAdapterImpl implements ViatraModelQueryStoreAdapter { | 20 | public class ViatraModelQueryStoreAdapterImpl implements ViatraModelQueryStoreAdapter { |
16 | private final ModelStore store; | 21 | private final ModelStore store; |
17 | private final ViatraQueryEngineOptions engineOptions; | 22 | private final ViatraQueryEngineOptions engineOptions; |
18 | private final Map<AnyRelationView, IInputKey> inputKeys; | 23 | private final Map<AnySymbolView, IInputKey> inputKeys; |
19 | private final Map<AnyQuery, IQuerySpecification<RawPatternMatcher>> querySpecifications; | 24 | private final Map<AnyQuery, IQuerySpecification<RawPatternMatcher>> querySpecifications; |
20 | private final Set<AnyQuery> vacuousQueries; | 25 | private final Set<AnyQuery> vacuousQueries; |
21 | private final Set<AnyQuery> allQueries; | 26 | private final Set<AnyQuery> allQueries; |
22 | 27 | ||
23 | ViatraModelQueryStoreAdapterImpl(ModelStore store, ViatraQueryEngineOptions engineOptions, | 28 | ViatraModelQueryStoreAdapterImpl(ModelStore store, ViatraQueryEngineOptions engineOptions, |
24 | Map<AnyRelationView, IInputKey> inputKeys, | 29 | Map<AnySymbolView, IInputKey> inputKeys, |
25 | Map<AnyQuery, IQuerySpecification<RawPatternMatcher>> querySpecifications, | 30 | Map<AnyQuery, IQuerySpecification<RawPatternMatcher>> querySpecifications, |
26 | Set<AnyQuery> vacuousQueries) { | 31 | Set<AnyQuery> vacuousQueries) { |
27 | this.store = store; | 32 | this.store = store; |
@@ -40,11 +45,11 @@ public class ViatraModelQueryStoreAdapterImpl implements ViatraModelQueryStoreAd | |||
40 | return store; | 45 | return store; |
41 | } | 46 | } |
42 | 47 | ||
43 | public Collection<AnyRelationView> getRelationViews() { | 48 | public Collection<AnySymbolView> getSymbolViews() { |
44 | return inputKeys.keySet(); | 49 | return inputKeys.keySet(); |
45 | } | 50 | } |
46 | 51 | ||
47 | public Map<AnyRelationView, IInputKey> getInputKeys() { | 52 | public Map<AnySymbolView, IInputKey> getInputKeys() { |
48 | return inputKeys; | 53 | return inputKeys; |
49 | } | 54 | } |
50 | 55 | ||
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/cardinality/UpperCardinalitySumAggregationOperator.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/cardinality/UpperCardinalitySumAggregationOperator.java deleted file mode 100644 index e0bca9e0..00000000 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/cardinality/UpperCardinalitySumAggregationOperator.java +++ /dev/null | |||
@@ -1,97 +0,0 @@ | |||
1 | package tools.refinery.store.query.viatra.internal.cardinality; | ||
2 | |||
3 | import org.eclipse.viatra.query.runtime.matchers.psystem.aggregations.BoundAggregator; | ||
4 | import org.eclipse.viatra.query.runtime.matchers.psystem.aggregations.IMultisetAggregationOperator; | ||
5 | import tools.refinery.store.representation.cardinality.FiniteUpperCardinality; | ||
6 | import tools.refinery.store.representation.cardinality.UnboundedUpperCardinality; | ||
7 | import tools.refinery.store.representation.cardinality.UpperCardinalities; | ||
8 | import tools.refinery.store.representation.cardinality.UpperCardinality; | ||
9 | |||
10 | import java.util.stream.Stream; | ||
11 | |||
12 | public class UpperCardinalitySumAggregationOperator implements IMultisetAggregationOperator<UpperCardinality, | ||
13 | UpperCardinalitySumAggregationOperator.Accumulator, UpperCardinality> { | ||
14 | public static final UpperCardinalitySumAggregationOperator INSTANCE = new UpperCardinalitySumAggregationOperator(); | ||
15 | |||
16 | public static final BoundAggregator BOUND_AGGREGATOR = new BoundAggregator(INSTANCE, UpperCardinality.class, | ||
17 | UpperCardinality.class); | ||
18 | |||
19 | private UpperCardinalitySumAggregationOperator() { | ||
20 | // Singleton constructor. | ||
21 | } | ||
22 | |||
23 | @Override | ||
24 | public String getName() { | ||
25 | return "sum<UpperCardinality>"; | ||
26 | } | ||
27 | |||
28 | @Override | ||
29 | public String getShortDescription() { | ||
30 | return "%s computes the sum of finite or unbounded upper cardinalities".formatted(getName()); | ||
31 | } | ||
32 | |||
33 | @Override | ||
34 | public Accumulator createNeutral() { | ||
35 | return new Accumulator(); | ||
36 | } | ||
37 | |||
38 | @Override | ||
39 | public boolean isNeutral(Accumulator result) { | ||
40 | return result.sumFiniteUpperBounds == 0 && result.countUnbounded == 0; | ||
41 | } | ||
42 | |||
43 | @Override | ||
44 | public Accumulator update(Accumulator oldResult, UpperCardinality updateValue, boolean isInsertion) { | ||
45 | if (updateValue instanceof FiniteUpperCardinality finiteUpperCardinality) { | ||
46 | int finiteUpperBound = finiteUpperCardinality.finiteUpperBound(); | ||
47 | if (isInsertion) { | ||
48 | oldResult.sumFiniteUpperBounds += finiteUpperBound; | ||
49 | } else { | ||
50 | oldResult.sumFiniteUpperBounds -= finiteUpperBound; | ||
51 | } | ||
52 | } else if (updateValue instanceof UnboundedUpperCardinality) { | ||
53 | if (isInsertion) { | ||
54 | oldResult.countUnbounded += 1; | ||
55 | } else { | ||
56 | oldResult.countUnbounded -= 1; | ||
57 | } | ||
58 | } else { | ||
59 | throw new IllegalArgumentException("Unknown UpperCardinality: " + updateValue); | ||
60 | } | ||
61 | return oldResult; | ||
62 | } | ||
63 | |||
64 | @Override | ||
65 | public UpperCardinality getAggregate(Accumulator result) { | ||
66 | return result.countUnbounded > 0 ? UpperCardinalities.UNBOUNDED : | ||
67 | UpperCardinalities.valueOf(result.sumFiniteUpperBounds); | ||
68 | } | ||
69 | |||
70 | @Override | ||
71 | public UpperCardinality aggregateStream(Stream<UpperCardinality> stream) { | ||
72 | var result = stream.collect(this::createNeutral, (accumulator, value) -> update(accumulator, value, true), | ||
73 | (left, right) -> new Accumulator(left.sumFiniteUpperBounds + right.sumFiniteUpperBounds, | ||
74 | left.countUnbounded + right.countUnbounded)); | ||
75 | return getAggregate(result); | ||
76 | } | ||
77 | |||
78 | @Override | ||
79 | public Accumulator clone(Accumulator original) { | ||
80 | return new Accumulator(original.sumFiniteUpperBounds, original.countUnbounded); | ||
81 | } | ||
82 | |||
83 | public static class Accumulator { | ||
84 | private int sumFiniteUpperBounds; | ||
85 | |||
86 | private int countUnbounded; | ||
87 | |||
88 | private Accumulator(int sumFiniteUpperBounds, int countUnbounded) { | ||
89 | this.sumFiniteUpperBounds = sumFiniteUpperBounds; | ||
90 | this.countUnbounded = countUnbounded; | ||
91 | } | ||
92 | |||
93 | private Accumulator() { | ||
94 | this(0, 0); | ||
95 | } | ||
96 | } | ||
97 | } | ||
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/DummyBaseIndexer.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/DummyBaseIndexer.java index 2a24b67c..8cb199d2 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/DummyBaseIndexer.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/DummyBaseIndexer.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.viatra.internal.context; | 6 | package tools.refinery.store.query.viatra.internal.context; |
2 | 7 | ||
3 | import org.eclipse.viatra.query.runtime.api.scope.IBaseIndex; | 8 | import org.eclipse.viatra.query.runtime.api.scope.IBaseIndex; |
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalEngineContext.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalEngineContext.java index 28bc69d0..7220f8ca 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalEngineContext.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalEngineContext.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.viatra.internal.context; | 6 | package tools.refinery.store.query.viatra.internal.context; |
2 | 7 | ||
3 | import org.eclipse.viatra.query.runtime.api.scope.IBaseIndex; | 8 | import org.eclipse.viatra.query.runtime.api.scope.IBaseIndex; |
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalQueryMetaContext.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalQueryMetaContext.java index d2c6beb4..211eacb4 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalQueryMetaContext.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalQueryMetaContext.java | |||
@@ -1,12 +1,16 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.viatra.internal.context; | 6 | package tools.refinery.store.query.viatra.internal.context; |
2 | 7 | ||
3 | import org.eclipse.viatra.query.runtime.matchers.context.AbstractQueryMetaContext; | 8 | import org.eclipse.viatra.query.runtime.matchers.context.AbstractQueryMetaContext; |
4 | import org.eclipse.viatra.query.runtime.matchers.context.IInputKey; | 9 | import org.eclipse.viatra.query.runtime.matchers.context.IInputKey; |
5 | import org.eclipse.viatra.query.runtime.matchers.context.InputKeyImplication; | 10 | import org.eclipse.viatra.query.runtime.matchers.context.InputKeyImplication; |
6 | import org.eclipse.viatra.query.runtime.matchers.context.common.JavaTransitiveInstancesKey; | 11 | import org.eclipse.viatra.query.runtime.matchers.context.common.JavaTransitiveInstancesKey; |
7 | import tools.refinery.store.query.term.DataSort; | 12 | import tools.refinery.store.query.viatra.internal.pquery.SymbolViewWrapper; |
8 | import tools.refinery.store.query.viatra.internal.pquery.RelationViewWrapper; | 13 | import tools.refinery.store.query.view.AnySymbolView; |
9 | import tools.refinery.store.query.view.AnyRelationView; | ||
10 | 14 | ||
11 | import java.util.*; | 15 | import java.util.*; |
12 | 16 | ||
@@ -14,9 +18,9 @@ import java.util.*; | |||
14 | * The meta context information for String scopes. | 18 | * The meta context information for String scopes. |
15 | */ | 19 | */ |
16 | public class RelationalQueryMetaContext extends AbstractQueryMetaContext { | 20 | public class RelationalQueryMetaContext extends AbstractQueryMetaContext { |
17 | private final Map<AnyRelationView, IInputKey> inputKeys; | 21 | private final Map<AnySymbolView, IInputKey> inputKeys; |
18 | 22 | ||
19 | RelationalQueryMetaContext(Map<AnyRelationView, IInputKey> inputKeys) { | 23 | RelationalQueryMetaContext(Map<AnySymbolView, IInputKey> inputKeys) { |
20 | this.inputKeys = inputKeys; | 24 | this.inputKeys = inputKeys; |
21 | } | 25 | } |
22 | 26 | ||
@@ -42,29 +46,29 @@ public class RelationalQueryMetaContext extends AbstractQueryMetaContext { | |||
42 | if (implyingKey instanceof JavaTransitiveInstancesKey) { | 46 | if (implyingKey instanceof JavaTransitiveInstancesKey) { |
43 | return List.of(); | 47 | return List.of(); |
44 | } | 48 | } |
45 | var relationView = checkKey(implyingKey); | 49 | var symbolView = checkKey(implyingKey); |
46 | var relationViewImplications = relationView.getImpliedRelationViews(); | 50 | var relationViewImplications = symbolView.getImpliedRelationViews(); |
47 | var inputKeyImplications = new HashSet<InputKeyImplication>(relationViewImplications.size()); | 51 | var inputKeyImplications = new HashSet<InputKeyImplication>(relationViewImplications.size()); |
48 | for (var relationViewImplication : relationViewImplications) { | 52 | for (var relationViewImplication : relationViewImplications) { |
49 | if (!relationView.equals(relationViewImplication.implyingRelationView())) { | 53 | if (!symbolView.equals(relationViewImplication.implyingView())) { |
50 | throw new IllegalArgumentException("Relation view %s returned unrelated implication %s".formatted( | 54 | throw new IllegalArgumentException("Relation view %s returned unrelated implication %s".formatted( |
51 | relationView, relationViewImplication)); | 55 | symbolView, relationViewImplication)); |
52 | } | 56 | } |
53 | var impliedInputKey = inputKeys.get(relationViewImplication.impliedRelationView()); | 57 | var impliedInputKey = inputKeys.get(relationViewImplication.impliedView()); |
54 | // Ignore implications not relevant for any queries included in the model. | 58 | // Ignore implications not relevant for any queries included in the model. |
55 | if (impliedInputKey != null) { | 59 | if (impliedInputKey != null) { |
56 | inputKeyImplications.add(new InputKeyImplication(implyingKey, impliedInputKey, | 60 | inputKeyImplications.add(new InputKeyImplication(implyingKey, impliedInputKey, |
57 | relationViewImplication.impliedIndices())); | 61 | relationViewImplication.impliedIndices())); |
58 | } | 62 | } |
59 | } | 63 | } |
60 | var sorts = relationView.getSorts(); | 64 | var parameters = symbolView.getParameters(); |
61 | int arity = relationView.arity(); | 65 | int arity = symbolView.arity(); |
62 | for (int i = 0; i < arity; i++) { | 66 | for (int i = 0; i < arity; i++) { |
63 | var sort = sorts.get(i); | 67 | var parameter = parameters.get(i); |
64 | if (sort instanceof DataSort<?> dataSort) { | 68 | var parameterType = parameter.tryGetType(); |
65 | var javaTransitiveInstancesKey = new JavaTransitiveInstancesKey(dataSort.type()); | 69 | if (parameterType.isPresent()) { |
66 | var javaImplication = new InputKeyImplication(implyingKey, javaTransitiveInstancesKey, | 70 | var javaTransitiveInstancesKey = new JavaTransitiveInstancesKey(parameterType.get()); |
67 | List.of(i)); | 71 | var javaImplication = new InputKeyImplication(implyingKey, javaTransitiveInstancesKey, List.of(i)); |
68 | inputKeyImplications.add(javaImplication); | 72 | inputKeyImplications.add(javaImplication); |
69 | } | 73 | } |
70 | } | 74 | } |
@@ -94,20 +98,20 @@ public class RelationalQueryMetaContext extends AbstractQueryMetaContext { | |||
94 | return flattened; | 98 | return flattened; |
95 | } | 99 | } |
96 | 100 | ||
97 | private static void checkValidIndices(AnyRelationView relationView, Collection<Integer> indices) { | 101 | private static void checkValidIndices(AnySymbolView relationView, Collection<Integer> indices) { |
98 | indices.stream().filter(relationView::invalidIndex).findAny().ifPresent(i -> { | 102 | indices.stream().filter(relationView::invalidIndex).findAny().ifPresent(i -> { |
99 | throw new IllegalArgumentException("Index %d is invalid for %s".formatted(i, relationView)); | 103 | throw new IllegalArgumentException("Index %d is invalid for %s".formatted(i, relationView)); |
100 | }); | 104 | }); |
101 | } | 105 | } |
102 | 106 | ||
103 | public AnyRelationView checkKey(IInputKey key) { | 107 | public AnySymbolView checkKey(IInputKey key) { |
104 | if (!(key instanceof RelationViewWrapper wrapper)) { | 108 | if (!(key instanceof SymbolViewWrapper wrapper)) { |
105 | throw new IllegalArgumentException("The input key %s is not a valid input key".formatted(key)); | 109 | throw new IllegalArgumentException("The input key %s is not a valid input key".formatted(key)); |
106 | } | 110 | } |
107 | var relationView = wrapper.getWrappedKey(); | 111 | var symbolView = wrapper.getWrappedKey(); |
108 | if (!inputKeys.containsKey(relationView)) { | 112 | if (!inputKeys.containsKey(symbolView)) { |
109 | throw new IllegalArgumentException("The input key %s is not present in the model".formatted(key)); | 113 | throw new IllegalArgumentException("The input key %s is not present in the model".formatted(key)); |
110 | } | 114 | } |
111 | return relationView; | 115 | return symbolView; |
112 | } | 116 | } |
113 | } | 117 | } |
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalRuntimeContext.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalRuntimeContext.java index 854817b1..0f2daca8 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalRuntimeContext.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/context/RelationalRuntimeContext.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.viatra.internal.context; | 6 | package tools.refinery.store.query.viatra.internal.context; |
2 | 7 | ||
3 | import org.eclipse.viatra.query.runtime.matchers.context.*; | 8 | import org.eclipse.viatra.query.runtime.matchers.context.*; |
@@ -8,9 +13,9 @@ import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples; | |||
8 | import org.eclipse.viatra.query.runtime.matchers.util.Accuracy; | 13 | import org.eclipse.viatra.query.runtime.matchers.util.Accuracy; |
9 | import tools.refinery.store.model.Model; | 14 | import tools.refinery.store.model.Model; |
10 | import tools.refinery.store.query.viatra.internal.ViatraModelQueryAdapterImpl; | 15 | import tools.refinery.store.query.viatra.internal.ViatraModelQueryAdapterImpl; |
11 | import tools.refinery.store.query.viatra.internal.pquery.RelationViewWrapper; | 16 | import tools.refinery.store.query.viatra.internal.pquery.SymbolViewWrapper; |
12 | import tools.refinery.store.query.viatra.internal.update.ModelUpdateListener; | 17 | import tools.refinery.store.query.viatra.internal.update.ModelUpdateListener; |
13 | import tools.refinery.store.query.view.AnyRelationView; | 18 | import tools.refinery.store.query.view.AnySymbolView; |
14 | 19 | ||
15 | import java.lang.reflect.InvocationTargetException; | 20 | import java.lang.reflect.InvocationTargetException; |
16 | import java.util.Iterator; | 21 | import java.util.Iterator; |
@@ -54,9 +59,9 @@ public class RelationalRuntimeContext implements IQueryRuntimeContext { | |||
54 | 59 | ||
55 | @Override | 60 | @Override |
56 | public boolean isIndexed(IInputKey key, IndexingService service) { | 61 | public boolean isIndexed(IInputKey key, IndexingService service) { |
57 | if (key instanceof RelationViewWrapper wrapper) { | 62 | if (key instanceof SymbolViewWrapper wrapper) { |
58 | var relationalKey = wrapper.getWrappedKey(); | 63 | var symbolViewKey = wrapper.getWrappedKey(); |
59 | return this.modelUpdateListener.containsRelationView(relationalKey); | 64 | return this.modelUpdateListener.containsSymbolView(symbolViewKey); |
60 | } else { | 65 | } else { |
61 | return false; | 66 | return false; |
62 | } | 67 | } |
@@ -69,13 +74,13 @@ public class RelationalRuntimeContext implements IQueryRuntimeContext { | |||
69 | } | 74 | } |
70 | } | 75 | } |
71 | 76 | ||
72 | AnyRelationView checkKey(IInputKey key) { | 77 | AnySymbolView checkKey(IInputKey key) { |
73 | if (key instanceof RelationViewWrapper wrappedKey) { | 78 | if (key instanceof SymbolViewWrapper wrappedKey) { |
74 | var relationViewKey = wrappedKey.getWrappedKey(); | 79 | var symbolViewKey = wrappedKey.getWrappedKey(); |
75 | if (modelUpdateListener.containsRelationView(relationViewKey)) { | 80 | if (modelUpdateListener.containsSymbolView(symbolViewKey)) { |
76 | return relationViewKey; | 81 | return symbolViewKey; |
77 | } else { | 82 | } else { |
78 | throw new IllegalStateException("Query is asking for non-indexed key %s".formatted(relationViewKey)); | 83 | throw new IllegalStateException("Query is asking for non-indexed key %s".formatted(symbolViewKey)); |
79 | } | 84 | } |
80 | } else { | 85 | } else { |
81 | throw new IllegalStateException("Query is asking for non-relational key"); | 86 | throw new IllegalStateException("Query is asking for non-relational key"); |
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/ExtendOperationExecutor.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/ExtendOperationExecutor.java index 2d3dd5a7..37177cbf 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/ExtendOperationExecutor.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/ExtendOperationExecutor.java | |||
@@ -1,5 +1,6 @@ | |||
1 | /******************************************************************************* | 1 | /******************************************************************************* |
2 | * Copyright (c) 2010-2013, Zoltan Ujhelyi, Akos Horvath, Istvan Rath and Daniel Varro | 2 | * Copyright (c) 2010-2013, Zoltan Ujhelyi, Akos Horvath, Istvan Rath and Daniel Varro |
3 | * Copyright (c) 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * This program and the accompanying materials are made available under the | 4 | * 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 | * terms of the Eclipse Public License v. 2.0 which is available at |
5 | * http://www.eclipse.org/legal/epl-v20.html. | 6 | * http://www.eclipse.org/legal/epl-v20.html. |
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/ExtendPositivePatternCall.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/ExtendPositivePatternCall.java index aaaece80..9d48c785 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/ExtendPositivePatternCall.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/ExtendPositivePatternCall.java | |||
@@ -1,5 +1,6 @@ | |||
1 | /******************************************************************************* | 1 | /******************************************************************************* |
2 | * Copyright (c) 2010-2016, Grill Balázs, IncQueryLabs | 2 | * Copyright (c) 2010-2016, Grill Balázs, IncQueryLabs |
3 | * Copyright (c) 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * This program and the accompanying materials are made available under the | 4 | * 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 | * terms of the Eclipse Public License v. 2.0 which is available at |
5 | * http://www.eclipse.org/legal/epl-v20.html. | 6 | * http://www.eclipse.org/legal/epl-v20.html. |
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/FlatCostFunction.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/FlatCostFunction.java index 84cab142..cc906f22 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/FlatCostFunction.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/FlatCostFunction.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.viatra.internal.localsearch; | 6 | package tools.refinery.store.query.viatra.internal.localsearch; |
2 | 7 | ||
3 | import org.eclipse.viatra.query.runtime.localsearch.planner.cost.IConstraintEvaluationContext; | 8 | import org.eclipse.viatra.query.runtime.localsearch.planner.cost.IConstraintEvaluationContext; |
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/GenericTypeExtend.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/GenericTypeExtend.java index 64653658..96ac4a72 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/GenericTypeExtend.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/GenericTypeExtend.java | |||
@@ -1,5 +1,6 @@ | |||
1 | /******************************************************************************* | 1 | /******************************************************************************* |
2 | * Copyright (c) 2010-2017, Zoltan Ujhelyi, IncQuery Labs Ltd. | 2 | * Copyright (c) 2010-2017, Zoltan Ujhelyi, IncQuery Labs Ltd. |
3 | * Copyright (c) 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * This program and the accompanying materials are made available under the | 4 | * 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 | * terms of the Eclipse Public License v. 2.0 which is available at |
5 | * http://www.eclipse.org/legal/epl-v20.html. | 6 | * http://www.eclipse.org/legal/epl-v20.html. |
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/RelationalLocalSearchBackendFactory.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/RelationalLocalSearchBackendFactory.java index 156eb313..0c77f587 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/RelationalLocalSearchBackendFactory.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/RelationalLocalSearchBackendFactory.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.viatra.internal.localsearch; | 6 | package tools.refinery.store.query.viatra.internal.localsearch; |
2 | 7 | ||
3 | import org.eclipse.viatra.query.runtime.localsearch.matcher.integration.AbstractLocalSearchResultProvider; | 8 | import org.eclipse.viatra.query.runtime.localsearch.matcher.integration.AbstractLocalSearchResultProvider; |
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/RelationalLocalSearchResultProvider.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/RelationalLocalSearchResultProvider.java index be2a38ca..da37be14 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/RelationalLocalSearchResultProvider.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/RelationalLocalSearchResultProvider.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.viatra.internal.localsearch; | 6 | package tools.refinery.store.query.viatra.internal.localsearch; |
2 | 7 | ||
3 | import org.eclipse.viatra.query.runtime.localsearch.matcher.integration.AbstractLocalSearchResultProvider; | 8 | import org.eclipse.viatra.query.runtime.localsearch.matcher.integration.AbstractLocalSearchResultProvider; |
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/RelationalOperationCompiler.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/RelationalOperationCompiler.java index b6832b39..f76ef486 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/RelationalOperationCompiler.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/localsearch/RelationalOperationCompiler.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.viatra.internal.localsearch; | 6 | package tools.refinery.store.query.viatra.internal.localsearch; |
2 | 7 | ||
3 | import org.eclipse.viatra.query.runtime.localsearch.operations.generic.GenericTypeExtendSingleValue; | 8 | import org.eclipse.viatra.query.runtime.localsearch.operations.generic.GenericTypeExtendSingleValue; |
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/FunctionalCursor.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/FunctionalCursor.java index 4daa14a1..47efb2aa 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/FunctionalCursor.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/FunctionalCursor.java | |||
@@ -1,17 +1,21 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.viatra.internal.matcher; | 6 | package tools.refinery.store.query.viatra.internal.matcher; |
2 | 7 | ||
3 | import org.eclipse.viatra.query.runtime.matchers.tuple.Tuple; | ||
4 | import org.eclipse.viatra.query.runtime.rete.index.IterableIndexer; | 8 | import org.eclipse.viatra.query.runtime.rete.index.IterableIndexer; |
5 | import tools.refinery.store.map.Cursor; | 9 | import tools.refinery.store.map.Cursor; |
6 | import tools.refinery.store.tuple.TupleLike; | 10 | import tools.refinery.store.tuple.Tuple; |
7 | 11 | ||
8 | import java.util.Iterator; | 12 | import java.util.Iterator; |
9 | 13 | ||
10 | class FunctionalCursor<T> implements Cursor<TupleLike, T> { | 14 | class FunctionalCursor<T> implements Cursor<Tuple, T> { |
11 | private final IterableIndexer indexer; | 15 | private final IterableIndexer indexer; |
12 | private final Iterator<Tuple> iterator; | 16 | private final Iterator<org.eclipse.viatra.query.runtime.matchers.tuple.Tuple> iterator; |
13 | private boolean terminated; | 17 | private boolean terminated; |
14 | private TupleLike key; | 18 | private Tuple key; |
15 | private T value; | 19 | private T value; |
16 | 20 | ||
17 | public FunctionalCursor(IterableIndexer indexer) { | 21 | public FunctionalCursor(IterableIndexer indexer) { |
@@ -20,7 +24,7 @@ class FunctionalCursor<T> implements Cursor<TupleLike, T> { | |||
20 | } | 24 | } |
21 | 25 | ||
22 | @Override | 26 | @Override |
23 | public TupleLike getKey() { | 27 | public Tuple getKey() { |
24 | return key; | 28 | return key; |
25 | } | 29 | } |
26 | 30 | ||
@@ -38,7 +42,7 @@ class FunctionalCursor<T> implements Cursor<TupleLike, T> { | |||
38 | public boolean move() { | 42 | public boolean move() { |
39 | if (!terminated && iterator.hasNext()) { | 43 | if (!terminated && iterator.hasNext()) { |
40 | var match = iterator.next(); | 44 | var match = iterator.next(); |
41 | key = new ViatraTupleLike(match); | 45 | key = MatcherUtils.toRefineryTuple(match); |
42 | value = MatcherUtils.getSingleValue(indexer.get(match)); | 46 | value = MatcherUtils.getSingleValue(indexer.get(match)); |
43 | return true; | 47 | return true; |
44 | } | 48 | } |
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/FunctionalViatraMatcher.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/FunctionalViatraMatcher.java index 6aa45af2..f018288b 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/FunctionalViatraMatcher.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/FunctionalViatraMatcher.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.viatra.internal.matcher; | 6 | package tools.refinery.store.query.viatra.internal.matcher; |
2 | 7 | ||
3 | import org.eclipse.viatra.query.runtime.matchers.backend.IQueryResultProvider; | 8 | import org.eclipse.viatra.query.runtime.matchers.backend.IQueryResultProvider; |
@@ -11,7 +16,7 @@ import tools.refinery.store.query.ResultSet; | |||
11 | import tools.refinery.store.query.dnf.FunctionalQuery; | 16 | import tools.refinery.store.query.dnf.FunctionalQuery; |
12 | import tools.refinery.store.query.dnf.Query; | 17 | import tools.refinery.store.query.dnf.Query; |
13 | import tools.refinery.store.query.viatra.internal.ViatraModelQueryAdapterImpl; | 18 | import tools.refinery.store.query.viatra.internal.ViatraModelQueryAdapterImpl; |
14 | import tools.refinery.store.tuple.TupleLike; | 19 | import tools.refinery.store.tuple.Tuple; |
15 | 20 | ||
16 | /** | 21 | /** |
17 | * Directly access the tuples inside a VIATRA pattern matcher.<p> | 22 | * Directly access the tuples inside a VIATRA pattern matcher.<p> |
@@ -63,7 +68,7 @@ public class FunctionalViatraMatcher<T> implements ResultSet<T> { | |||
63 | } | 68 | } |
64 | 69 | ||
65 | @Override | 70 | @Override |
66 | public T get(TupleLike parameters) { | 71 | public T get(Tuple parameters) { |
67 | var tuple = MatcherUtils.toViatraTuple(parameters); | 72 | var tuple = MatcherUtils.toViatraTuple(parameters); |
68 | if (omitOutputIndexer == null) { | 73 | if (omitOutputIndexer == null) { |
69 | return MatcherUtils.getSingleValue(backend.getAllMatches(omitOutputMask, tuple).iterator()); | 74 | return MatcherUtils.getSingleValue(backend.getAllMatches(omitOutputMask, tuple).iterator()); |
@@ -73,7 +78,7 @@ public class FunctionalViatraMatcher<T> implements ResultSet<T> { | |||
73 | } | 78 | } |
74 | 79 | ||
75 | @Override | 80 | @Override |
76 | public Cursor<TupleLike, T> getAll() { | 81 | public Cursor<Tuple, T> getAll() { |
77 | if (omitOutputIndexer == null) { | 82 | if (omitOutputIndexer == null) { |
78 | var allMatches = backend.getAllMatches(emptyMask, Tuples.staticArityFlatTupleOf()); | 83 | var allMatches = backend.getAllMatches(emptyMask, Tuples.staticArityFlatTupleOf()); |
79 | return new UnsafeFunctionalCursor<>(allMatches.iterator()); | 84 | return new UnsafeFunctionalCursor<>(allMatches.iterator()); |
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/IndexerUtils.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/IndexerUtils.java index 55eb8c44..15f00b2d 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/IndexerUtils.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/IndexerUtils.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.viatra.internal.matcher; | 6 | package tools.refinery.store.query.viatra.internal.matcher; |
2 | 7 | ||
3 | import org.eclipse.viatra.query.runtime.matchers.tuple.TupleMask; | 8 | import org.eclipse.viatra.query.runtime.matchers.tuple.TupleMask; |
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/MatcherUtils.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/MatcherUtils.java index 5d4be95d..1c784492 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/MatcherUtils.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/MatcherUtils.java | |||
@@ -1,10 +1,14 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.viatra.internal.matcher; | 6 | package tools.refinery.store.query.viatra.internal.matcher; |
2 | 7 | ||
3 | import org.eclipse.viatra.query.runtime.matchers.tuple.ITuple; | 8 | import org.eclipse.viatra.query.runtime.matchers.tuple.ITuple; |
4 | import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples; | 9 | import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples; |
5 | import org.jetbrains.annotations.Nullable; | 10 | import org.jetbrains.annotations.Nullable; |
6 | import tools.refinery.store.tuple.Tuple; | 11 | import tools.refinery.store.tuple.*; |
7 | import tools.refinery.store.tuple.TupleLike; | ||
8 | 12 | ||
9 | import java.util.Iterator; | 13 | import java.util.Iterator; |
10 | 14 | ||
@@ -13,25 +17,80 @@ final class MatcherUtils { | |||
13 | throw new IllegalStateException("This is a static utility class and should not be instantiated directly"); | 17 | throw new IllegalStateException("This is a static utility class and should not be instantiated directly"); |
14 | } | 18 | } |
15 | 19 | ||
16 | public static org.eclipse.viatra.query.runtime.matchers.tuple.Tuple toViatraTuple(TupleLike tuple) { | 20 | public static org.eclipse.viatra.query.runtime.matchers.tuple.Tuple toViatraTuple(Tuple refineryTuple) { |
17 | if (tuple instanceof ViatraTupleLike viatraTupleLike) { | 21 | if (refineryTuple instanceof Tuple0) { |
18 | return viatraTupleLike.wrappedTuple().toImmutable(); | 22 | return Tuples.staticArityFlatTupleOf(); |
23 | } else if (refineryTuple instanceof Tuple1) { | ||
24 | return Tuples.staticArityFlatTupleOf(refineryTuple); | ||
25 | } else if (refineryTuple instanceof Tuple2 tuple2) { | ||
26 | return Tuples.staticArityFlatTupleOf(Tuple.of(tuple2.value0()), Tuple.of(tuple2.value1())); | ||
27 | } else if (refineryTuple instanceof Tuple3 tuple3) { | ||
28 | return Tuples.staticArityFlatTupleOf(Tuple.of(tuple3.value0()), Tuple.of(tuple3.value1()), | ||
29 | Tuple.of(tuple3.value2())); | ||
30 | } else if (refineryTuple instanceof Tuple4 tuple4) { | ||
31 | return Tuples.staticArityFlatTupleOf(Tuple.of(tuple4.value0()), Tuple.of(tuple4.value1()), | ||
32 | Tuple.of(tuple4.value2()), Tuple.of(tuple4.value3())); | ||
33 | } else { | ||
34 | int arity = refineryTuple.getSize(); | ||
35 | var values = new Object[arity]; | ||
36 | for (int i = 0; i < arity; i++) { | ||
37 | values[i] = Tuple.of(refineryTuple.get(i)); | ||
38 | } | ||
39 | return Tuples.flatTupleOf(values); | ||
19 | } | 40 | } |
20 | int size = tuple.getSize(); | 41 | } |
21 | var array = new Object[size]; | 42 | |
22 | for (int i = 0; i < size; i++) { | 43 | public static Tuple toRefineryTuple(ITuple viatraTuple) { |
23 | var value = tuple.get(i); | 44 | int arity = viatraTuple.getSize(); |
24 | array[i] = Tuple.of(value); | 45 | if (arity == 1) { |
46 | return getWrapper(viatraTuple, 0); | ||
25 | } | 47 | } |
26 | return Tuples.flatTupleOf(array); | 48 | return prefixToRefineryTuple(viatraTuple, viatraTuple.getSize()); |
49 | } | ||
50 | |||
51 | public static Tuple keyToRefineryTuple(ITuple viatraTuple) { | ||
52 | return prefixToRefineryTuple(viatraTuple, viatraTuple.getSize() - 1); | ||
27 | } | 53 | } |
28 | 54 | ||
55 | private static Tuple prefixToRefineryTuple(ITuple viatraTuple, int targetArity) { | ||
56 | if (targetArity < 0) { | ||
57 | throw new IllegalArgumentException("Requested negative prefix %d of %s" | ||
58 | .formatted(targetArity, viatraTuple)); | ||
59 | } | ||
60 | return switch (targetArity) { | ||
61 | case 0 -> Tuple.of(); | ||
62 | case 1 -> Tuple.of(unwrap(viatraTuple, 0)); | ||
63 | case 2 -> Tuple.of(unwrap(viatraTuple, 0), unwrap(viatraTuple, 1)); | ||
64 | case 3 -> Tuple.of(unwrap(viatraTuple, 0), unwrap(viatraTuple, 1), unwrap(viatraTuple, 2)); | ||
65 | case 4 -> Tuple.of(unwrap(viatraTuple, 0), unwrap(viatraTuple, 1), unwrap(viatraTuple, 2), | ||
66 | unwrap(viatraTuple, 3)); | ||
67 | default -> { | ||
68 | var entries = new int[targetArity]; | ||
69 | for (int i = 0; i < targetArity; i++) { | ||
70 | entries[i] = unwrap(viatraTuple, i); | ||
71 | } | ||
72 | yield Tuple.of(entries); | ||
73 | } | ||
74 | }; | ||
75 | } | ||
76 | |||
77 | private static Tuple1 getWrapper(ITuple viatraTuple, int index) { | ||
78 | if (!((viatraTuple.get(index)) instanceof Tuple1 wrappedObjectId)) { | ||
79 | throw new IllegalArgumentException("Element %d of tuple %s is not an object id" | ||
80 | .formatted(index, viatraTuple)); | ||
81 | } | ||
82 | return wrappedObjectId; | ||
83 | } | ||
84 | |||
85 | private static int unwrap(ITuple viatraTuple, int index) { | ||
86 | return getWrapper(viatraTuple, index).value0(); | ||
87 | } | ||
29 | 88 | ||
30 | public static <T> T getSingleValue(@Nullable Iterable<? extends ITuple> tuples) { | 89 | public static <T> T getSingleValue(@Nullable Iterable<? extends ITuple> viatraTuples) { |
31 | if (tuples == null) { | 90 | if (viatraTuples == null) { |
32 | return null; | 91 | return null; |
33 | } | 92 | } |
34 | return getSingleValue(tuples.iterator()); | 93 | return getSingleValue(viatraTuples.iterator()); |
35 | } | 94 | } |
36 | 95 | ||
37 | public static <T> T getSingleValue(Iterator<? extends ITuple> iterator) { | 96 | public static <T> T getSingleValue(Iterator<? extends ITuple> iterator) { |
@@ -42,7 +101,7 @@ final class MatcherUtils { | |||
42 | @SuppressWarnings("unchecked") | 101 | @SuppressWarnings("unchecked") |
43 | var result = (T) match.get(match.getSize() - 1); | 102 | var result = (T) match.get(match.getSize() - 1); |
44 | if (iterator.hasNext()) { | 103 | if (iterator.hasNext()) { |
45 | var input = new OmitOutputViatraTupleLike(match); | 104 | var input = keyToRefineryTuple(match); |
46 | throw new IllegalStateException("Query is not functional for input tuple: " + input); | 105 | throw new IllegalStateException("Query is not functional for input tuple: " + input); |
47 | } | 106 | } |
48 | return result; | 107 | return result; |
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/OmitOutputViatraTupleLike.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/OmitOutputViatraTupleLike.java deleted file mode 100644 index bd9301ba..00000000 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/OmitOutputViatraTupleLike.java +++ /dev/null | |||
@@ -1,23 +0,0 @@ | |||
1 | package tools.refinery.store.query.viatra.internal.matcher; | ||
2 | |||
3 | import org.eclipse.viatra.query.runtime.matchers.tuple.ITuple; | ||
4 | import tools.refinery.store.tuple.Tuple1; | ||
5 | import tools.refinery.store.tuple.TupleLike; | ||
6 | |||
7 | record OmitOutputViatraTupleLike(ITuple wrappedTuple) implements TupleLike { | ||
8 | @Override | ||
9 | public int getSize() { | ||
10 | return wrappedTuple.getSize() - 1; | ||
11 | } | ||
12 | |||
13 | @Override | ||
14 | public int get(int element) { | ||
15 | var wrappedValue = (Tuple1) wrappedTuple.get(element); | ||
16 | return wrappedValue.value0(); | ||
17 | } | ||
18 | |||
19 | @Override | ||
20 | public String toString() { | ||
21 | return TupleLike.toString(this); | ||
22 | } | ||
23 | } | ||
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/RawPatternMatcher.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/RawPatternMatcher.java index b3d05967..5b82c4b7 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/RawPatternMatcher.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/RawPatternMatcher.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.viatra.internal.matcher; | 6 | package tools.refinery.store.query.viatra.internal.matcher; |
2 | 7 | ||
3 | import org.eclipse.viatra.query.runtime.api.GenericPatternMatcher; | 8 | import org.eclipse.viatra.query.runtime.api.GenericPatternMatcher; |
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/RelationalCursor.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/RelationalCursor.java index c2dcc565..1dc8f5db 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/RelationalCursor.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/RelationalCursor.java | |||
@@ -1,22 +1,27 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.viatra.internal.matcher; | 6 | package tools.refinery.store.query.viatra.internal.matcher; |
2 | 7 | ||
3 | import org.eclipse.viatra.query.runtime.matchers.tuple.ITuple; | 8 | import org.eclipse.viatra.query.runtime.matchers.tuple.ITuple; |
4 | import tools.refinery.store.map.Cursor; | 9 | import tools.refinery.store.map.Cursor; |
5 | import tools.refinery.store.tuple.TupleLike; | 10 | import tools.refinery.store.tuple.Tuple; |
6 | 11 | ||
7 | import java.util.Iterator; | 12 | import java.util.Iterator; |
8 | 13 | ||
9 | class RelationalCursor implements Cursor<TupleLike, Boolean> { | 14 | class RelationalCursor implements Cursor<Tuple, Boolean> { |
10 | private final Iterator<? extends ITuple> tuplesIterator; | 15 | private final Iterator<? extends ITuple> tuplesIterator; |
11 | private boolean terminated; | 16 | private boolean terminated; |
12 | private TupleLike key; | 17 | private Tuple key; |
13 | 18 | ||
14 | public RelationalCursor(Iterator<? extends ITuple> tuplesIterator) { | 19 | public RelationalCursor(Iterator<? extends ITuple> tuplesIterator) { |
15 | this.tuplesIterator = tuplesIterator; | 20 | this.tuplesIterator = tuplesIterator; |
16 | } | 21 | } |
17 | 22 | ||
18 | @Override | 23 | @Override |
19 | public TupleLike getKey() { | 24 | public Tuple getKey() { |
20 | return key; | 25 | return key; |
21 | } | 26 | } |
22 | 27 | ||
@@ -33,7 +38,7 @@ class RelationalCursor implements Cursor<TupleLike, Boolean> { | |||
33 | @Override | 38 | @Override |
34 | public boolean move() { | 39 | public boolean move() { |
35 | if (!terminated && tuplesIterator.hasNext()) { | 40 | if (!terminated && tuplesIterator.hasNext()) { |
36 | key = new ViatraTupleLike(tuplesIterator.next()); | 41 | key = MatcherUtils.toRefineryTuple(tuplesIterator.next()); |
37 | return true; | 42 | return true; |
38 | } | 43 | } |
39 | terminated = true; | 44 | terminated = true; |
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/RelationalViatraMatcher.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/RelationalViatraMatcher.java index b9bc3f1e..d1476920 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/RelationalViatraMatcher.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/RelationalViatraMatcher.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.viatra.internal.matcher; | 6 | package tools.refinery.store.query.viatra.internal.matcher; |
2 | 7 | ||
3 | import org.eclipse.viatra.query.runtime.matchers.backend.IQueryResultProvider; | 8 | import org.eclipse.viatra.query.runtime.matchers.backend.IQueryResultProvider; |
@@ -12,7 +17,7 @@ import tools.refinery.store.query.ResultSet; | |||
12 | import tools.refinery.store.query.dnf.Query; | 17 | import tools.refinery.store.query.dnf.Query; |
13 | import tools.refinery.store.query.dnf.RelationalQuery; | 18 | import tools.refinery.store.query.dnf.RelationalQuery; |
14 | import tools.refinery.store.query.viatra.internal.ViatraModelQueryAdapterImpl; | 19 | import tools.refinery.store.query.viatra.internal.ViatraModelQueryAdapterImpl; |
15 | import tools.refinery.store.tuple.TupleLike; | 20 | import tools.refinery.store.tuple.Tuple; |
16 | 21 | ||
17 | /** | 22 | /** |
18 | * Directly access the tuples inside a VIATRA pattern matcher.<p> | 23 | * Directly access the tuples inside a VIATRA pattern matcher.<p> |
@@ -58,7 +63,7 @@ public class RelationalViatraMatcher implements ResultSet<Boolean> { | |||
58 | } | 63 | } |
59 | 64 | ||
60 | @Override | 65 | @Override |
61 | public Boolean get(TupleLike parameters) { | 66 | public Boolean get(Tuple parameters) { |
62 | var tuple = MatcherUtils.toViatraTuple(parameters); | 67 | var tuple = MatcherUtils.toViatraTuple(parameters); |
63 | if (emptyMaskIndexer == null) { | 68 | if (emptyMaskIndexer == null) { |
64 | return backend.hasMatch(identityMask, tuple); | 69 | return backend.hasMatch(identityMask, tuple); |
@@ -68,7 +73,7 @@ public class RelationalViatraMatcher implements ResultSet<Boolean> { | |||
68 | } | 73 | } |
69 | 74 | ||
70 | @Override | 75 | @Override |
71 | public Cursor<TupleLike, Boolean> getAll() { | 76 | public Cursor<Tuple, Boolean> getAll() { |
72 | if (emptyMaskIndexer == null) { | 77 | if (emptyMaskIndexer == null) { |
73 | var allMatches = backend.getAllMatches(emptyMask, Tuples.staticArityFlatTupleOf()); | 78 | var allMatches = backend.getAllMatches(emptyMask, Tuples.staticArityFlatTupleOf()); |
74 | return new RelationalCursor(allMatches.iterator()); | 79 | return new RelationalCursor(allMatches.iterator()); |
@@ -85,5 +90,4 @@ public class RelationalViatraMatcher implements ResultSet<Boolean> { | |||
85 | var matches = emptyMaskIndexer.get(Tuples.staticArityFlatTupleOf()); | 90 | var matches = emptyMaskIndexer.get(Tuples.staticArityFlatTupleOf()); |
86 | return matches == null ? 0 : matches.size(); | 91 | return matches == null ? 0 : matches.size(); |
87 | } | 92 | } |
88 | |||
89 | } | 93 | } |
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/UnsafeFunctionalCursor.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/UnsafeFunctionalCursor.java index 6c53fff1..4a41d724 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/UnsafeFunctionalCursor.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/UnsafeFunctionalCursor.java | |||
@@ -1,8 +1,13 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.viatra.internal.matcher; | 6 | package tools.refinery.store.query.viatra.internal.matcher; |
2 | 7 | ||
3 | import org.eclipse.viatra.query.runtime.matchers.tuple.ITuple; | 8 | import org.eclipse.viatra.query.runtime.matchers.tuple.ITuple; |
4 | import tools.refinery.store.map.Cursor; | 9 | import tools.refinery.store.map.Cursor; |
5 | import tools.refinery.store.tuple.TupleLike; | 10 | import tools.refinery.store.tuple.Tuple; |
6 | 11 | ||
7 | import java.util.Iterator; | 12 | import java.util.Iterator; |
8 | 13 | ||
@@ -11,10 +16,10 @@ import java.util.Iterator; | |||
11 | * functional dependency of the output on the inputs is obeyed. | 16 | * functional dependency of the output on the inputs is obeyed. |
12 | * @param <T> The output type. | 17 | * @param <T> The output type. |
13 | */ | 18 | */ |
14 | class UnsafeFunctionalCursor<T> implements Cursor<TupleLike, T> { | 19 | class UnsafeFunctionalCursor<T> implements Cursor<Tuple, T> { |
15 | private final Iterator<? extends ITuple> tuplesIterator; | 20 | private final Iterator<? extends ITuple> tuplesIterator; |
16 | private boolean terminated; | 21 | private boolean terminated; |
17 | private TupleLike key; | 22 | private Tuple key; |
18 | private T value; | 23 | private T value; |
19 | 24 | ||
20 | public UnsafeFunctionalCursor(Iterator<? extends ITuple> tuplesIterator) { | 25 | public UnsafeFunctionalCursor(Iterator<? extends ITuple> tuplesIterator) { |
@@ -22,7 +27,7 @@ class UnsafeFunctionalCursor<T> implements Cursor<TupleLike, T> { | |||
22 | } | 27 | } |
23 | 28 | ||
24 | @Override | 29 | @Override |
25 | public TupleLike getKey() { | 30 | public Tuple getKey() { |
26 | return key; | 31 | return key; |
27 | } | 32 | } |
28 | 33 | ||
@@ -40,7 +45,7 @@ class UnsafeFunctionalCursor<T> implements Cursor<TupleLike, T> { | |||
40 | public boolean move() { | 45 | public boolean move() { |
41 | if (!terminated && tuplesIterator.hasNext()) { | 46 | if (!terminated && tuplesIterator.hasNext()) { |
42 | var match = tuplesIterator.next(); | 47 | var match = tuplesIterator.next(); |
43 | key = new OmitOutputViatraTupleLike(match); | 48 | key = MatcherUtils.keyToRefineryTuple(match); |
44 | @SuppressWarnings("unchecked") | 49 | @SuppressWarnings("unchecked") |
45 | var typedValue = (T) match.get(match.getSize() - 1); | 50 | var typedValue = (T) match.get(match.getSize() - 1); |
46 | value = typedValue; | 51 | value = typedValue; |
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/ViatraTupleLike.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/ViatraTupleLike.java deleted file mode 100644 index 76a3e40b..00000000 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/matcher/ViatraTupleLike.java +++ /dev/null | |||
@@ -1,23 +0,0 @@ | |||
1 | package tools.refinery.store.query.viatra.internal.matcher; | ||
2 | |||
3 | import org.eclipse.viatra.query.runtime.matchers.tuple.ITuple; | ||
4 | import tools.refinery.store.tuple.Tuple1; | ||
5 | import tools.refinery.store.tuple.TupleLike; | ||
6 | |||
7 | record ViatraTupleLike(ITuple wrappedTuple) implements TupleLike { | ||
8 | @Override | ||
9 | public int getSize() { | ||
10 | return wrappedTuple.getSize(); | ||
11 | } | ||
12 | |||
13 | @Override | ||
14 | public int get(int element) { | ||
15 | var wrappedValue = (Tuple1) wrappedTuple.get(element); | ||
16 | return wrappedValue.value0(); | ||
17 | } | ||
18 | |||
19 | @Override | ||
20 | public String toString() { | ||
21 | return TupleLike.toString(this); | ||
22 | } | ||
23 | } | ||
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/AssumptionEvaluator.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/AssumptionEvaluator.java index a80b0f90..cf127291 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/AssumptionEvaluator.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/AssumptionEvaluator.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.viatra.internal.pquery; | 6 | package tools.refinery.store.query.viatra.internal.pquery; |
2 | 7 | ||
3 | import org.eclipse.viatra.query.runtime.matchers.psystem.IValueProvider; | 8 | import org.eclipse.viatra.query.runtime.matchers.psystem.IValueProvider; |
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/Dnf2PQuery.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/Dnf2PQuery.java index 7afeb977..5b0ea61d 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/Dnf2PQuery.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/Dnf2PQuery.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.viatra.internal.pquery; | 6 | package tools.refinery.store.query.viatra.internal.pquery; |
2 | 7 | ||
3 | import org.eclipse.viatra.query.runtime.matchers.backend.IQueryBackendFactory; | 8 | import org.eclipse.viatra.query.runtime.matchers.backend.IQueryBackendFactory; |
@@ -14,17 +19,19 @@ import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.Consta | |||
14 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.PositivePatternCall; | 19 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.PositivePatternCall; |
15 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.TypeConstraint; | 20 | import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.TypeConstraint; |
16 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PParameter; | 21 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PParameter; |
22 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PParameterDirection; | ||
17 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery; | 23 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery; |
18 | import org.eclipse.viatra.query.runtime.matchers.tuple.Tuple; | 24 | import org.eclipse.viatra.query.runtime.matchers.tuple.Tuple; |
19 | import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples; | 25 | import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples; |
20 | import tools.refinery.store.query.dnf.Dnf; | 26 | import tools.refinery.store.query.dnf.Dnf; |
21 | import tools.refinery.store.query.dnf.DnfClause; | 27 | import tools.refinery.store.query.dnf.DnfClause; |
28 | import tools.refinery.store.query.dnf.SymbolicParameter; | ||
22 | import tools.refinery.store.query.literal.*; | 29 | import tools.refinery.store.query.literal.*; |
23 | import tools.refinery.store.query.term.ConstantTerm; | 30 | import tools.refinery.store.query.term.ConstantTerm; |
24 | import tools.refinery.store.query.term.StatefulAggregator; | 31 | import tools.refinery.store.query.term.StatefulAggregator; |
25 | import tools.refinery.store.query.term.StatelessAggregator; | 32 | import tools.refinery.store.query.term.StatelessAggregator; |
26 | import tools.refinery.store.query.term.Variable; | 33 | import tools.refinery.store.query.term.Variable; |
27 | import tools.refinery.store.query.view.AnyRelationView; | 34 | import tools.refinery.store.query.view.AnySymbolView; |
28 | import tools.refinery.store.util.CycleDetectingMapper; | 35 | import tools.refinery.store.util.CycleDetectingMapper; |
29 | 36 | ||
30 | import java.util.*; | 37 | import java.util.*; |
@@ -48,8 +55,8 @@ public class Dnf2PQuery { | |||
48 | return mapper.map(dnfQuery); | 55 | return mapper.map(dnfQuery); |
49 | } | 56 | } |
50 | 57 | ||
51 | public Map<AnyRelationView, IInputKey> getRelationViews() { | 58 | public Map<AnySymbolView, IInputKey> getSymbolViews() { |
52 | return wrapperFactory.getRelationViews(); | 59 | return wrapperFactory.getSymbolViews(); |
53 | } | 60 | } |
54 | 61 | ||
55 | public void hint(Dnf dnf, QueryEvaluationHint hint) { | 62 | public void hint(Dnf dnf, QueryEvaluationHint hint) { |
@@ -77,15 +84,19 @@ public class Dnf2PQuery { | |||
77 | var pQuery = new RawPQuery(dnfQuery.getUniqueName()); | 84 | var pQuery = new RawPQuery(dnfQuery.getUniqueName()); |
78 | pQuery.setEvaluationHints(consumeHint(dnfQuery)); | 85 | pQuery.setEvaluationHints(consumeHint(dnfQuery)); |
79 | 86 | ||
80 | Map<Variable, PParameter> parameters = new HashMap<>(); | 87 | Map<SymbolicParameter, PParameter> parameters = new HashMap<>(); |
81 | for (Variable variable : dnfQuery.getParameters()) { | ||
82 | parameters.put(variable, new PParameter(variable.getUniqueName())); | ||
83 | } | ||
84 | |||
85 | List<PParameter> parameterList = new ArrayList<>(); | 88 | List<PParameter> parameterList = new ArrayList<>(); |
86 | for (var param : dnfQuery.getParameters()) { | 89 | for (var parameter : dnfQuery.getSymbolicParameters()) { |
87 | parameterList.add(parameters.get(param)); | 90 | var direction = switch (parameter.getDirection()) { |
91 | case OUT -> parameter.isUnifiable() ? PParameterDirection.INOUT : PParameterDirection.OUT; | ||
92 | case IN -> throw new IllegalArgumentException("Query %s with input parameter %s is not supported" | ||
93 | .formatted(dnfQuery, parameter.getVariable())); | ||
94 | }; | ||
95 | var pParameter = new PParameter(parameter.getVariable().getUniqueName(), null, null, direction); | ||
96 | parameters.put(parameter, pParameter); | ||
97 | parameterList.add(pParameter); | ||
88 | } | 98 | } |
99 | |||
89 | pQuery.setParameters(parameterList); | 100 | pQuery.setParameters(parameterList); |
90 | 101 | ||
91 | for (var functionalDependency : dnfQuery.getFunctionalDependencies()) { | 102 | for (var functionalDependency : dnfQuery.getFunctionalDependencies()) { |
@@ -105,15 +116,15 @@ public class Dnf2PQuery { | |||
105 | synchronized (P_CONSTRAINT_LOCK) { | 116 | synchronized (P_CONSTRAINT_LOCK) { |
106 | for (DnfClause clause : dnfQuery.getClauses()) { | 117 | for (DnfClause clause : dnfQuery.getClauses()) { |
107 | PBody body = new PBody(pQuery); | 118 | PBody body = new PBody(pQuery); |
108 | List<ExportedParameter> symbolicParameters = new ArrayList<>(); | 119 | List<ExportedParameter> parameterExports = new ArrayList<>(); |
109 | for (var param : dnfQuery.getParameters()) { | 120 | for (var parameter : dnfQuery.getSymbolicParameters()) { |
110 | PVariable pVar = body.getOrCreateVariableByName(param.getUniqueName()); | 121 | PVariable pVar = body.getOrCreateVariableByName(parameter.getVariable().getUniqueName()); |
111 | symbolicParameters.add(new ExportedParameter(body, pVar, parameters.get(param))); | 122 | parameterExports.add(new ExportedParameter(body, pVar, parameters.get(parameter))); |
112 | } | 123 | } |
113 | body.setSymbolicParameters(symbolicParameters); | 124 | body.setSymbolicParameters(parameterExports); |
114 | pQuery.addBody(body); | 125 | pQuery.addBody(body); |
115 | for (Literal literal : clause.literals()) { | 126 | for (Literal literal : clause.literals()) { |
116 | translateLiteral(literal, clause, body); | 127 | translateLiteral(literal, body); |
117 | } | 128 | } |
118 | } | 129 | } |
119 | } | 130 | } |
@@ -121,11 +132,11 @@ public class Dnf2PQuery { | |||
121 | return pQuery; | 132 | return pQuery; |
122 | } | 133 | } |
123 | 134 | ||
124 | private void translateLiteral(Literal literal, DnfClause clause, PBody body) { | 135 | private void translateLiteral(Literal literal, PBody body) { |
125 | if (literal instanceof EquivalenceLiteral equivalenceLiteral) { | 136 | if (literal instanceof EquivalenceLiteral equivalenceLiteral) { |
126 | translateEquivalenceLiteral(equivalenceLiteral, body); | 137 | translateEquivalenceLiteral(equivalenceLiteral, body); |
127 | } else if (literal instanceof CallLiteral callLiteral) { | 138 | } else if (literal instanceof CallLiteral callLiteral) { |
128 | translateCallLiteral(callLiteral, clause, body); | 139 | translateCallLiteral(callLiteral, body); |
129 | } else if (literal instanceof ConstantLiteral constantLiteral) { | 140 | } else if (literal instanceof ConstantLiteral constantLiteral) { |
130 | translateConstantLiteral(constantLiteral, body); | 141 | translateConstantLiteral(constantLiteral, body); |
131 | } else if (literal instanceof AssignLiteral<?> assignLiteral) { | 142 | } else if (literal instanceof AssignLiteral<?> assignLiteral) { |
@@ -133,9 +144,9 @@ public class Dnf2PQuery { | |||
133 | } else if (literal instanceof AssumeLiteral assumeLiteral) { | 144 | } else if (literal instanceof AssumeLiteral assumeLiteral) { |
134 | translateAssumeLiteral(assumeLiteral, body); | 145 | translateAssumeLiteral(assumeLiteral, body); |
135 | } else if (literal instanceof CountLiteral countLiteral) { | 146 | } else if (literal instanceof CountLiteral countLiteral) { |
136 | translateCountLiteral(countLiteral, clause, body); | 147 | translateCountLiteral(countLiteral, body); |
137 | } else if (literal instanceof AggregationLiteral<?, ?> aggregationLiteral) { | 148 | } else if (literal instanceof AggregationLiteral<?, ?> aggregationLiteral) { |
138 | translateAggregationLiteral(aggregationLiteral, clause, body); | 149 | translateAggregationLiteral(aggregationLiteral, body); |
139 | } else { | 150 | } else { |
140 | throw new IllegalArgumentException("Unknown literal: " + literal.toString()); | 151 | throw new IllegalArgumentException("Unknown literal: " + literal.toString()); |
141 | } | 152 | } |
@@ -151,7 +162,7 @@ public class Dnf2PQuery { | |||
151 | } | 162 | } |
152 | } | 163 | } |
153 | 164 | ||
154 | private void translateCallLiteral(CallLiteral callLiteral, DnfClause clause, PBody body) { | 165 | private void translateCallLiteral(CallLiteral callLiteral, PBody body) { |
155 | var polarity = callLiteral.getPolarity(); | 166 | var polarity = callLiteral.getPolarity(); |
156 | switch (polarity) { | 167 | switch (polarity) { |
157 | case POSITIVE -> { | 168 | case POSITIVE -> { |
@@ -160,8 +171,8 @@ public class Dnf2PQuery { | |||
160 | if (constraint instanceof Dnf dnf) { | 171 | if (constraint instanceof Dnf dnf) { |
161 | var pattern = translate(dnf); | 172 | var pattern = translate(dnf); |
162 | new PositivePatternCall(body, substitution, pattern); | 173 | new PositivePatternCall(body, substitution, pattern); |
163 | } else if (constraint instanceof AnyRelationView relationView) { | 174 | } else if (constraint instanceof AnySymbolView symbolView) { |
164 | var inputKey = wrapperFactory.getInputKey(relationView); | 175 | var inputKey = wrapperFactory.getInputKey(symbolView); |
165 | new TypeConstraint(body, substitution, inputKey); | 176 | new TypeConstraint(body, substitution, inputKey); |
166 | } else { | 177 | } else { |
167 | throw new IllegalArgumentException("Unknown Constraint: " + constraint); | 178 | throw new IllegalArgumentException("Unknown Constraint: " + constraint); |
@@ -173,15 +184,15 @@ public class Dnf2PQuery { | |||
173 | PQuery pattern; | 184 | PQuery pattern; |
174 | if (constraint instanceof Dnf dnf) { | 185 | if (constraint instanceof Dnf dnf) { |
175 | pattern = translate(dnf); | 186 | pattern = translate(dnf); |
176 | } else if (constraint instanceof AnyRelationView relationView) { | 187 | } else if (constraint instanceof AnySymbolView symbolView) { |
177 | pattern = wrapperFactory.wrapRelationViewIdentityArguments(relationView); | 188 | pattern = wrapperFactory.wrapSymbolViewIdentityArguments(symbolView); |
178 | } else { | 189 | } else { |
179 | throw new IllegalArgumentException("Unknown Constraint: " + constraint); | 190 | throw new IllegalArgumentException("Unknown Constraint: " + constraint); |
180 | } | 191 | } |
181 | new BinaryTransitiveClosure(body, substitution, pattern); | 192 | new BinaryTransitiveClosure(body, substitution, pattern); |
182 | } | 193 | } |
183 | case NEGATIVE -> { | 194 | case NEGATIVE -> { |
184 | var wrappedCall = wrapperFactory.maybeWrapConstraint(callLiteral, clause); | 195 | var wrappedCall = wrapperFactory.maybeWrapConstraint(callLiteral); |
185 | var substitution = translateSubstitution(wrappedCall.remappedArguments(), body); | 196 | var substitution = translateSubstitution(wrappedCall.remappedArguments(), body); |
186 | var pattern = wrappedCall.pattern(); | 197 | var pattern = wrappedCall.pattern(); |
187 | new NegativePatternCall(body, substitution, pattern); | 198 | new NegativePatternCall(body, substitution, pattern); |
@@ -221,15 +232,14 @@ public class Dnf2PQuery { | |||
221 | new ExpressionEvaluation(body, evaluator, null); | 232 | new ExpressionEvaluation(body, evaluator, null); |
222 | } | 233 | } |
223 | 234 | ||
224 | private void translateCountLiteral(CountLiteral countLiteral, DnfClause clause, PBody body) { | 235 | private void translateCountLiteral(CountLiteral countLiteral, PBody body) { |
225 | var wrappedCall = wrapperFactory.maybeWrapConstraint(countLiteral, clause); | 236 | var wrappedCall = wrapperFactory.maybeWrapConstraint(countLiteral); |
226 | var substitution = translateSubstitution(wrappedCall.remappedArguments(), body); | 237 | var substitution = translateSubstitution(wrappedCall.remappedArguments(), body); |
227 | var resultVariable = body.getOrCreateVariableByName(countLiteral.getResultVariable().getUniqueName()); | 238 | var resultVariable = body.getOrCreateVariableByName(countLiteral.getResultVariable().getUniqueName()); |
228 | new PatternMatchCounter(body, substitution, wrappedCall.pattern(), resultVariable); | 239 | new PatternMatchCounter(body, substitution, wrappedCall.pattern(), resultVariable); |
229 | } | 240 | } |
230 | 241 | ||
231 | private <R, T> void translateAggregationLiteral(AggregationLiteral<R, T> aggregationLiteral, DnfClause clause, | 242 | private <R, T> void translateAggregationLiteral(AggregationLiteral<R, T> aggregationLiteral, PBody body) { |
232 | PBody body) { | ||
233 | var aggregator = aggregationLiteral.getAggregator(); | 243 | var aggregator = aggregationLiteral.getAggregator(); |
234 | IMultisetAggregationOperator<T, ?, R> aggregationOperator; | 244 | IMultisetAggregationOperator<T, ?, R> aggregationOperator; |
235 | if (aggregator instanceof StatelessAggregator<R, T> statelessAggregator) { | 245 | if (aggregator instanceof StatelessAggregator<R, T> statelessAggregator) { |
@@ -239,7 +249,7 @@ public class Dnf2PQuery { | |||
239 | } else { | 249 | } else { |
240 | throw new IllegalArgumentException("Unknown aggregator: " + aggregator); | 250 | throw new IllegalArgumentException("Unknown aggregator: " + aggregator); |
241 | } | 251 | } |
242 | var wrappedCall = wrapperFactory.maybeWrapConstraint(aggregationLiteral, clause); | 252 | var wrappedCall = wrapperFactory.maybeWrapConstraint(aggregationLiteral); |
243 | var substitution = translateSubstitution(wrappedCall.remappedArguments(), body); | 253 | var substitution = translateSubstitution(wrappedCall.remappedArguments(), body); |
244 | var inputVariable = body.getOrCreateVariableByName(aggregationLiteral.getInputVariable().getUniqueName()); | 254 | var inputVariable = body.getOrCreateVariableByName(aggregationLiteral.getInputVariable().getUniqueName()); |
245 | var aggregatedColumn = substitution.invertIndex().get(inputVariable); | 255 | var aggregatedColumn = substitution.invertIndex().get(inputVariable); |
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/QueryWrapperFactory.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/QueryWrapperFactory.java index 24ae5196..2b7280f2 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/QueryWrapperFactory.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/QueryWrapperFactory.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.viatra.internal.pquery; | 6 | package tools.refinery.store.query.viatra.internal.pquery; |
2 | 7 | ||
3 | import org.eclipse.viatra.query.runtime.matchers.context.IInputKey; | 8 | import org.eclipse.viatra.query.runtime.matchers.context.IInputKey; |
@@ -9,15 +14,16 @@ import org.eclipse.viatra.query.runtime.matchers.psystem.basicenumerables.TypeCo | |||
9 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PParameter; | 14 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PParameter; |
10 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery; | 15 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PQuery; |
11 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PVisibility; | 16 | import org.eclipse.viatra.query.runtime.matchers.psystem.queries.PVisibility; |
17 | import org.eclipse.viatra.query.runtime.matchers.tuple.Tuple; | ||
12 | import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples; | 18 | import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples; |
13 | import tools.refinery.store.query.Constraint; | 19 | import tools.refinery.store.query.Constraint; |
14 | import tools.refinery.store.query.dnf.Dnf; | 20 | import tools.refinery.store.query.dnf.Dnf; |
15 | import tools.refinery.store.query.dnf.DnfClause; | ||
16 | import tools.refinery.store.query.dnf.DnfUtils; | 21 | import tools.refinery.store.query.dnf.DnfUtils; |
17 | import tools.refinery.store.query.literal.AbstractCallLiteral; | 22 | import tools.refinery.store.query.literal.AbstractCallLiteral; |
23 | import tools.refinery.store.query.term.ParameterDirection; | ||
18 | import tools.refinery.store.query.term.Variable; | 24 | import tools.refinery.store.query.term.Variable; |
19 | import tools.refinery.store.query.view.AnyRelationView; | 25 | import tools.refinery.store.query.view.AnySymbolView; |
20 | import tools.refinery.store.query.view.RelationView; | 26 | import tools.refinery.store.query.view.SymbolView; |
21 | import tools.refinery.store.util.CycleDetectingMapper; | 27 | import tools.refinery.store.util.CycleDetectingMapper; |
22 | 28 | ||
23 | import java.util.*; | 29 | import java.util.*; |
@@ -25,7 +31,7 @@ import java.util.function.ToIntFunction; | |||
25 | 31 | ||
26 | class QueryWrapperFactory { | 32 | class QueryWrapperFactory { |
27 | private final Dnf2PQuery dnf2PQuery; | 33 | private final Dnf2PQuery dnf2PQuery; |
28 | private final Map<AnyRelationView, RelationViewWrapper> view2WrapperMap = new LinkedHashMap<>(); | 34 | private final Map<AnySymbolView, SymbolViewWrapper> view2WrapperMap = new LinkedHashMap<>(); |
29 | private final CycleDetectingMapper<RemappedConstraint, RawPQuery> wrapConstraint = new CycleDetectingMapper<>( | 35 | private final CycleDetectingMapper<RemappedConstraint, RawPQuery> wrapConstraint = new CycleDetectingMapper<>( |
30 | RemappedConstraint::toString, this::doWrapConstraint); | 36 | RemappedConstraint::toString, this::doWrapConstraint); |
31 | 37 | ||
@@ -33,28 +39,24 @@ class QueryWrapperFactory { | |||
33 | this.dnf2PQuery = dnf2PQuery; | 39 | this.dnf2PQuery = dnf2PQuery; |
34 | } | 40 | } |
35 | 41 | ||
36 | public PQuery wrapRelationViewIdentityArguments(AnyRelationView relationView) { | 42 | public PQuery wrapSymbolViewIdentityArguments(AnySymbolView symbolView) { |
37 | var identity = new int[relationView.arity()]; | 43 | var identity = new int[symbolView.arity()]; |
38 | for (int i = 0; i < identity.length; i++) { | 44 | for (int i = 0; i < identity.length; i++) { |
39 | identity[i] = i; | 45 | identity[i] = i; |
40 | } | 46 | } |
41 | return maybeWrapConstraint(relationView, identity); | 47 | return maybeWrapConstraint(symbolView, identity); |
42 | } | 48 | } |
43 | public WrappedCall maybeWrapConstraint(AbstractCallLiteral callLiteral, DnfClause clause) { | 49 | |
50 | public WrappedCall maybeWrapConstraint(AbstractCallLiteral callLiteral) { | ||
44 | var arguments = callLiteral.getArguments(); | 51 | var arguments = callLiteral.getArguments(); |
45 | int arity = arguments.size(); | 52 | int arity = arguments.size(); |
46 | var remappedParameters = new int[arity]; | 53 | var remappedParameters = new int[arity]; |
47 | var boundVariables = clause.boundVariables(); | ||
48 | var unboundVariableIndices = new HashMap<Variable, Integer>(); | 54 | var unboundVariableIndices = new HashMap<Variable, Integer>(); |
49 | var appendVariable = new VariableAppender(); | 55 | var appendVariable = new VariableAppender(); |
50 | for (int i = 0; i < arity; i++) { | 56 | for (int i = 0; i < arity; i++) { |
51 | var variable = arguments.get(i); | 57 | var variable = arguments.get(i); |
52 | if (boundVariables.contains(variable)) { | 58 | // Unify all variables to avoid VIATRA bugs, even if they're bound in the containing clause. |
53 | // Do not join bound variable to make sure that the embedded pattern stays as general as possible. | 59 | remappedParameters[i] = unboundVariableIndices.computeIfAbsent(variable, appendVariable::applyAsInt); |
54 | remappedParameters[i] = appendVariable.applyAsInt(variable); | ||
55 | } else { | ||
56 | remappedParameters[i] = unboundVariableIndices.computeIfAbsent(variable, appendVariable::applyAsInt); | ||
57 | } | ||
58 | } | 60 | } |
59 | var pattern = maybeWrapConstraint(callLiteral.getTarget(), remappedParameters); | 61 | var pattern = maybeWrapConstraint(callLiteral.getTarget(), remappedParameters); |
60 | return new WrappedCall(pattern, appendVariable.getRemappedArguments()); | 62 | return new WrappedCall(pattern, appendVariable.getRemappedArguments()); |
@@ -84,6 +86,8 @@ class QueryWrapperFactory { | |||
84 | var constraint = remappedConstraint.constraint(); | 86 | var constraint = remappedConstraint.constraint(); |
85 | var remappedParameters = remappedConstraint.remappedParameters(); | 87 | var remappedParameters = remappedConstraint.remappedParameters(); |
86 | 88 | ||
89 | checkNoInputParameters(constraint); | ||
90 | |||
87 | var embeddedPQuery = new RawPQuery(DnfUtils.generateUniqueName(constraint.name()), PVisibility.EMBEDDED); | 91 | var embeddedPQuery = new RawPQuery(DnfUtils.generateUniqueName(constraint.name()), PVisibility.EMBEDDED); |
88 | var body = new PBody(embeddedPQuery); | 92 | var body = new PBody(embeddedPQuery); |
89 | int arity = Arrays.stream(remappedParameters).max().orElse(-1) + 1; | 93 | int arity = Arrays.stream(remappedParameters).max().orElse(-1) + 1; |
@@ -107,24 +111,36 @@ class QueryWrapperFactory { | |||
107 | } | 111 | } |
108 | var argumentTuple = Tuples.flatTupleOf(arguments); | 112 | var argumentTuple = Tuples.flatTupleOf(arguments); |
109 | 113 | ||
110 | if (constraint instanceof RelationView<?> relationView) { | 114 | addPositiveConstraint(constraint, body, argumentTuple); |
111 | new TypeConstraint(body, argumentTuple, getInputKey(relationView)); | 115 | embeddedPQuery.addBody(body); |
116 | return embeddedPQuery; | ||
117 | } | ||
118 | |||
119 | private static void checkNoInputParameters(Constraint constraint) { | ||
120 | for (var constraintParameter : constraint.getParameters()) { | ||
121 | if (constraintParameter.getDirection() == ParameterDirection.IN) { | ||
122 | throw new IllegalArgumentException("Input parameter %s of %s is not supported" | ||
123 | .formatted(constraintParameter, constraint)); | ||
124 | } | ||
125 | } | ||
126 | } | ||
127 | |||
128 | private void addPositiveConstraint(Constraint constraint, PBody body, Tuple argumentTuple) { | ||
129 | if (constraint instanceof SymbolView<?> view) { | ||
130 | new TypeConstraint(body, argumentTuple, getInputKey(view)); | ||
112 | } else if (constraint instanceof Dnf dnf) { | 131 | } else if (constraint instanceof Dnf dnf) { |
113 | var calledPQuery = dnf2PQuery.translate(dnf); | 132 | var calledPQuery = dnf2PQuery.translate(dnf); |
114 | new PositivePatternCall(body, argumentTuple, calledPQuery); | 133 | new PositivePatternCall(body, argumentTuple, calledPQuery); |
115 | } else { | 134 | } else { |
116 | throw new IllegalArgumentException("Unknown Constraint: " + constraint); | 135 | throw new IllegalArgumentException("Unknown Constraint: " + constraint); |
117 | } | 136 | } |
118 | |||
119 | embeddedPQuery.addBody(body); | ||
120 | return embeddedPQuery; | ||
121 | } | 137 | } |
122 | 138 | ||
123 | public IInputKey getInputKey(AnyRelationView relationView) { | 139 | public IInputKey getInputKey(AnySymbolView symbolView) { |
124 | return view2WrapperMap.computeIfAbsent(relationView, RelationViewWrapper::new); | 140 | return view2WrapperMap.computeIfAbsent(symbolView, SymbolViewWrapper::new); |
125 | } | 141 | } |
126 | 142 | ||
127 | public Map<AnyRelationView, IInputKey> getRelationViews() { | 143 | public Map<AnySymbolView, IInputKey> getSymbolViews() { |
128 | return Collections.unmodifiableMap(view2WrapperMap); | 144 | return Collections.unmodifiableMap(view2WrapperMap); |
129 | } | 145 | } |
130 | 146 | ||
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/RawPQuery.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/RawPQuery.java index aad4ba3c..255738c5 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/RawPQuery.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/RawPQuery.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.viatra.internal.pquery; | 6 | package tools.refinery.store.query.viatra.internal.pquery; |
2 | 7 | ||
3 | import org.eclipse.viatra.query.runtime.api.GenericQuerySpecification; | 8 | import org.eclipse.viatra.query.runtime.api.GenericQuerySpecification; |
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/StatefulMultisetAggregator.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/StatefulMultisetAggregator.java index 2798a252..461416f7 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/StatefulMultisetAggregator.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/StatefulMultisetAggregator.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.viatra.internal.pquery; | 6 | package tools.refinery.store.query.viatra.internal.pquery; |
2 | 7 | ||
3 | import org.eclipse.viatra.query.runtime.matchers.psystem.aggregations.IMultisetAggregationOperator; | 8 | import org.eclipse.viatra.query.runtime.matchers.psystem.aggregations.IMultisetAggregationOperator; |
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/StatelessMultisetAggregator.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/StatelessMultisetAggregator.java index 7cc71ee9..49175d75 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/StatelessMultisetAggregator.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/StatelessMultisetAggregator.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.viatra.internal.pquery; | 6 | package tools.refinery.store.query.viatra.internal.pquery; |
2 | 7 | ||
3 | import org.eclipse.viatra.query.runtime.matchers.psystem.aggregations.IMultisetAggregationOperator; | 8 | import org.eclipse.viatra.query.runtime.matchers.psystem.aggregations.IMultisetAggregationOperator; |
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/RelationViewWrapper.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/SymbolViewWrapper.java index 48bf558d..a777613e 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/RelationViewWrapper.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/SymbolViewWrapper.java | |||
@@ -1,10 +1,15 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.viatra.internal.pquery; | 6 | package tools.refinery.store.query.viatra.internal.pquery; |
2 | 7 | ||
3 | import org.eclipse.viatra.query.runtime.matchers.context.common.BaseInputKeyWrapper; | 8 | import org.eclipse.viatra.query.runtime.matchers.context.common.BaseInputKeyWrapper; |
4 | import tools.refinery.store.query.view.AnyRelationView; | 9 | import tools.refinery.store.query.view.AnySymbolView; |
5 | 10 | ||
6 | public class RelationViewWrapper extends BaseInputKeyWrapper<AnyRelationView> { | 11 | public class SymbolViewWrapper extends BaseInputKeyWrapper<AnySymbolView> { |
7 | public RelationViewWrapper(AnyRelationView wrappedKey) { | 12 | public SymbolViewWrapper(AnySymbolView wrappedKey) { |
8 | super(wrappedKey); | 13 | super(wrappedKey); |
9 | } | 14 | } |
10 | 15 | ||
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/TermEvaluator.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/TermEvaluator.java index ab123c50..1187f57a 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/TermEvaluator.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/TermEvaluator.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.viatra.internal.pquery; | 6 | package tools.refinery.store.query.viatra.internal.pquery; |
2 | 7 | ||
3 | import org.eclipse.viatra.query.runtime.matchers.psystem.IExpressionEvaluator; | 8 | import org.eclipse.viatra.query.runtime.matchers.psystem.IExpressionEvaluator; |
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/ValueProviderBasedValuation.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/ValueProviderBasedValuation.java index 30c2fce7..62cb8b3a 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/ValueProviderBasedValuation.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/pquery/ValueProviderBasedValuation.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.viatra.internal.pquery; | 6 | package tools.refinery.store.query.viatra.internal.pquery; |
2 | 7 | ||
3 | import org.eclipse.viatra.query.runtime.matchers.psystem.IValueProvider; | 8 | import org.eclipse.viatra.query.runtime.matchers.psystem.IValueProvider; |
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/ModelUpdateListener.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/ModelUpdateListener.java index fc935aa6..986bb0b1 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/ModelUpdateListener.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/ModelUpdateListener.java | |||
@@ -1,46 +1,51 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.viatra.internal.update; | 6 | package tools.refinery.store.query.viatra.internal.update; |
2 | 7 | ||
3 | import org.eclipse.viatra.query.runtime.matchers.context.IInputKey; | 8 | import org.eclipse.viatra.query.runtime.matchers.context.IInputKey; |
4 | import org.eclipse.viatra.query.runtime.matchers.context.IQueryRuntimeContextListener; | 9 | import org.eclipse.viatra.query.runtime.matchers.context.IQueryRuntimeContextListener; |
5 | import org.eclipse.viatra.query.runtime.matchers.tuple.ITuple; | 10 | import org.eclipse.viatra.query.runtime.matchers.tuple.ITuple; |
6 | import tools.refinery.store.query.viatra.internal.ViatraModelQueryAdapterImpl; | 11 | import tools.refinery.store.query.viatra.internal.ViatraModelQueryAdapterImpl; |
7 | import tools.refinery.store.query.view.AnyRelationView; | 12 | import tools.refinery.store.query.view.AnySymbolView; |
8 | import tools.refinery.store.query.view.RelationView; | 13 | import tools.refinery.store.query.view.SymbolView; |
9 | 14 | ||
10 | import java.util.HashMap; | 15 | import java.util.HashMap; |
11 | import java.util.Map; | 16 | import java.util.Map; |
12 | 17 | ||
13 | public class ModelUpdateListener { | 18 | public class ModelUpdateListener { |
14 | private final Map<AnyRelationView, RelationViewUpdateListener<?>> relationViewUpdateListeners; | 19 | private final Map<AnySymbolView, SymbolViewUpdateListener<?>> symbolViewUpdateListeners; |
15 | 20 | ||
16 | public ModelUpdateListener(ViatraModelQueryAdapterImpl adapter) { | 21 | public ModelUpdateListener(ViatraModelQueryAdapterImpl adapter) { |
17 | var relationViews = adapter.getStoreAdapter().getInputKeys().keySet(); | 22 | var symbolViews = adapter.getStoreAdapter().getInputKeys().keySet(); |
18 | relationViewUpdateListeners = new HashMap<>(relationViews.size()); | 23 | symbolViewUpdateListeners = new HashMap<>(symbolViews.size()); |
19 | for (var relationView : relationViews) { | 24 | for (var symbolView : symbolViews) { |
20 | registerView(adapter, (RelationView<?>) relationView); | 25 | registerView(adapter, (SymbolView<?>) symbolView); |
21 | } | 26 | } |
22 | } | 27 | } |
23 | 28 | ||
24 | private <T> void registerView(ViatraModelQueryAdapterImpl adapter, RelationView<T> relationView) { | 29 | private <T> void registerView(ViatraModelQueryAdapterImpl adapter, SymbolView<T> view) { |
25 | var model = adapter.getModel(); | 30 | var model = adapter.getModel(); |
26 | var interpretation = model.getInterpretation(relationView.getSymbol()); | 31 | var interpretation = model.getInterpretation(view.getSymbol()); |
27 | var listener = RelationViewUpdateListener.of(adapter, relationView, interpretation); | 32 | var listener = SymbolViewUpdateListener.of(adapter, view, interpretation); |
28 | relationViewUpdateListeners.put(relationView, listener); | 33 | symbolViewUpdateListeners.put(view, listener); |
29 | } | 34 | } |
30 | 35 | ||
31 | public boolean containsRelationView(AnyRelationView relationView) { | 36 | public boolean containsSymbolView(AnySymbolView relationView) { |
32 | return relationViewUpdateListeners.containsKey(relationView); | 37 | return symbolViewUpdateListeners.containsKey(relationView); |
33 | } | 38 | } |
34 | 39 | ||
35 | public void addListener(IInputKey key, AnyRelationView relationView, ITuple seed, | 40 | public void addListener(IInputKey key, AnySymbolView symbolView, ITuple seed, |
36 | IQueryRuntimeContextListener listener) { | 41 | IQueryRuntimeContextListener listener) { |
37 | var relationViewUpdateListener = relationViewUpdateListeners.get(relationView); | 42 | var symbolViewUpdateListener = symbolViewUpdateListeners.get(symbolView); |
38 | relationViewUpdateListener.addFilter(key, seed, listener); | 43 | symbolViewUpdateListener.addFilter(key, seed, listener); |
39 | } | 44 | } |
40 | 45 | ||
41 | public void removeListener(IInputKey key, AnyRelationView relationView, ITuple seed, | 46 | public void removeListener(IInputKey key, AnySymbolView symbolView, ITuple seed, |
42 | IQueryRuntimeContextListener listener) { | 47 | IQueryRuntimeContextListener listener) { |
43 | var relationViewUpdateListener = relationViewUpdateListeners.get(relationView); | 48 | var symbolViewUpdateListener = symbolViewUpdateListeners.get(symbolView); |
44 | relationViewUpdateListener.removeFilter(key, seed, listener); | 49 | symbolViewUpdateListener.removeFilter(key, seed, listener); |
45 | } | 50 | } |
46 | } | 51 | } |
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/RelationViewFilter.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/RelationViewFilter.java index 221f1b4a..efdbfcbe 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/RelationViewFilter.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/RelationViewFilter.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.viatra.internal.update; | 6 | package tools.refinery.store.query.viatra.internal.update; |
2 | 7 | ||
3 | import org.eclipse.viatra.query.runtime.matchers.context.IInputKey; | 8 | import org.eclipse.viatra.query.runtime.matchers.context.IInputKey; |
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/RelationViewUpdateListener.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/SymbolViewUpdateListener.java index 5e5f60e3..f1a2ac7c 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/RelationViewUpdateListener.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/SymbolViewUpdateListener.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.viatra.internal.update; | 6 | package tools.refinery.store.query.viatra.internal.update; |
2 | 7 | ||
3 | import org.eclipse.viatra.query.runtime.matchers.context.IInputKey; | 8 | import org.eclipse.viatra.query.runtime.matchers.context.IInputKey; |
@@ -7,18 +12,18 @@ import org.eclipse.viatra.query.runtime.matchers.tuple.Tuple; | |||
7 | import tools.refinery.store.model.Interpretation; | 12 | import tools.refinery.store.model.Interpretation; |
8 | import tools.refinery.store.model.InterpretationListener; | 13 | import tools.refinery.store.model.InterpretationListener; |
9 | import tools.refinery.store.query.viatra.internal.ViatraModelQueryAdapterImpl; | 14 | import tools.refinery.store.query.viatra.internal.ViatraModelQueryAdapterImpl; |
10 | import tools.refinery.store.query.view.RelationView; | 15 | import tools.refinery.store.query.view.SymbolView; |
11 | import tools.refinery.store.query.view.TuplePreservingRelationView; | 16 | import tools.refinery.store.query.view.TuplePreservingView; |
12 | 17 | ||
13 | import java.util.ArrayList; | 18 | import java.util.ArrayList; |
14 | import java.util.List; | 19 | import java.util.List; |
15 | 20 | ||
16 | public abstract class RelationViewUpdateListener<T> implements InterpretationListener<T> { | 21 | public abstract class SymbolViewUpdateListener<T> implements InterpretationListener<T> { |
17 | private final ViatraModelQueryAdapterImpl adapter; | 22 | private final ViatraModelQueryAdapterImpl adapter; |
18 | private final Interpretation<T> interpretation; | 23 | private final Interpretation<T> interpretation; |
19 | private final List<RelationViewFilter> filters = new ArrayList<>(); | 24 | private final List<RelationViewFilter> filters = new ArrayList<>(); |
20 | 25 | ||
21 | protected RelationViewUpdateListener(ViatraModelQueryAdapterImpl adapter, Interpretation<T> interpretation) { | 26 | protected SymbolViewUpdateListener(ViatraModelQueryAdapterImpl adapter, Interpretation<T> interpretation) { |
22 | this.adapter = adapter; | 27 | this.adapter = adapter; |
23 | this.interpretation = interpretation; | 28 | this.interpretation = interpretation; |
24 | } | 29 | } |
@@ -48,13 +53,13 @@ public abstract class RelationViewUpdateListener<T> implements InterpretationLis | |||
48 | } | 53 | } |
49 | } | 54 | } |
50 | 55 | ||
51 | public static <T> RelationViewUpdateListener<T> of(ViatraModelQueryAdapterImpl adapter, | 56 | public static <T> SymbolViewUpdateListener<T> of(ViatraModelQueryAdapterImpl adapter, |
52 | RelationView<T> relationView, | 57 | SymbolView<T> view, |
53 | Interpretation<T> interpretation) { | 58 | Interpretation<T> interpretation) { |
54 | if (relationView instanceof TuplePreservingRelationView<T> tuplePreservingRelationView) { | 59 | if (view instanceof TuplePreservingView<T> tuplePreservingRelationView) { |
55 | return new TuplePreservingRelationViewUpdateListener<>(adapter, tuplePreservingRelationView, | 60 | return new TuplePreservingViewUpdateListener<>(adapter, tuplePreservingRelationView, |
56 | interpretation); | 61 | interpretation); |
57 | } | 62 | } |
58 | return new TupleChangingRelationViewUpdateListener<>(adapter, relationView, interpretation); | 63 | return new TupleChangingViewUpdateListener<>(adapter, view, interpretation); |
59 | } | 64 | } |
60 | } | 65 | } |
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/TupleChangingRelationViewUpdateListener.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/TupleChangingRelationViewUpdateListener.java deleted file mode 100644 index 0f6ed3b3..00000000 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/TupleChangingRelationViewUpdateListener.java +++ /dev/null | |||
@@ -1,39 +0,0 @@ | |||
1 | package tools.refinery.store.query.viatra.internal.update; | ||
2 | |||
3 | import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples; | ||
4 | import tools.refinery.store.model.Interpretation; | ||
5 | import tools.refinery.store.query.viatra.internal.ViatraModelQueryAdapterImpl; | ||
6 | import tools.refinery.store.query.view.RelationView; | ||
7 | import tools.refinery.store.tuple.Tuple; | ||
8 | |||
9 | import java.util.Arrays; | ||
10 | |||
11 | public class TupleChangingRelationViewUpdateListener<T> extends RelationViewUpdateListener<T> { | ||
12 | private final RelationView<T> relationView; | ||
13 | |||
14 | TupleChangingRelationViewUpdateListener(ViatraModelQueryAdapterImpl adapter, RelationView<T> relationView, | ||
15 | Interpretation<T> interpretation) { | ||
16 | super(adapter, interpretation); | ||
17 | this.relationView = relationView; | ||
18 | } | ||
19 | |||
20 | @Override | ||
21 | public void put(Tuple key, T fromValue, T toValue, boolean restoring) { | ||
22 | boolean fromPresent = relationView.filter(key, fromValue); | ||
23 | boolean toPresent = relationView.filter(key, toValue); | ||
24 | if (fromPresent) { | ||
25 | if (toPresent) { // value change | ||
26 | var fromArray = relationView.forwardMap(key, fromValue); | ||
27 | var toArray = relationView.forwardMap(key, toValue); | ||
28 | if (!Arrays.equals(fromArray, toArray)) { | ||
29 | processUpdate(Tuples.flatTupleOf(fromArray), false); | ||
30 | processUpdate(Tuples.flatTupleOf(toArray), true); | ||
31 | } | ||
32 | } else { // fromValue disappears | ||
33 | processUpdate(Tuples.flatTupleOf(relationView.forwardMap(key, fromValue)), false); | ||
34 | } | ||
35 | } else if (toPresent) { // toValue appears | ||
36 | processUpdate(Tuples.flatTupleOf(relationView.forwardMap(key, toValue)), true); | ||
37 | } | ||
38 | } | ||
39 | } | ||
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/TupleChangingViewUpdateListener.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/TupleChangingViewUpdateListener.java new file mode 100644 index 00000000..45d35571 --- /dev/null +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/TupleChangingViewUpdateListener.java | |||
@@ -0,0 +1,44 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.viatra.internal.update; | ||
7 | |||
8 | import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples; | ||
9 | import tools.refinery.store.model.Interpretation; | ||
10 | import tools.refinery.store.query.viatra.internal.ViatraModelQueryAdapterImpl; | ||
11 | import tools.refinery.store.query.view.SymbolView; | ||
12 | import tools.refinery.store.tuple.Tuple; | ||
13 | |||
14 | import java.util.Arrays; | ||
15 | |||
16 | public class TupleChangingViewUpdateListener<T> extends SymbolViewUpdateListener<T> { | ||
17 | private final SymbolView<T> view; | ||
18 | |||
19 | TupleChangingViewUpdateListener(ViatraModelQueryAdapterImpl adapter, SymbolView<T> view, | ||
20 | Interpretation<T> interpretation) { | ||
21 | super(adapter, interpretation); | ||
22 | this.view = view; | ||
23 | } | ||
24 | |||
25 | @Override | ||
26 | public void put(Tuple key, T fromValue, T toValue, boolean restoring) { | ||
27 | boolean fromPresent = view.filter(key, fromValue); | ||
28 | boolean toPresent = view.filter(key, toValue); | ||
29 | if (fromPresent) { | ||
30 | if (toPresent) { // value change | ||
31 | var fromArray = view.forwardMap(key, fromValue); | ||
32 | var toArray = view.forwardMap(key, toValue); | ||
33 | if (!Arrays.equals(fromArray, toArray)) { | ||
34 | processUpdate(Tuples.flatTupleOf(fromArray), false); | ||
35 | processUpdate(Tuples.flatTupleOf(toArray), true); | ||
36 | } | ||
37 | } else { // fromValue disappears | ||
38 | processUpdate(Tuples.flatTupleOf(view.forwardMap(key, fromValue)), false); | ||
39 | } | ||
40 | } else if (toPresent) { // toValue appears | ||
41 | processUpdate(Tuples.flatTupleOf(view.forwardMap(key, toValue)), true); | ||
42 | } | ||
43 | } | ||
44 | } | ||
diff --git a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/TuplePreservingRelationViewUpdateListener.java b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/TuplePreservingViewUpdateListener.java index 91e9371b..c18dbafb 100644 --- a/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/TuplePreservingRelationViewUpdateListener.java +++ b/subprojects/store-query-viatra/src/main/java/tools/refinery/store/query/viatra/internal/update/TuplePreservingViewUpdateListener.java | |||
@@ -1,16 +1,21 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.viatra.internal.update; | 6 | package tools.refinery.store.query.viatra.internal.update; |
2 | 7 | ||
3 | import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples; | 8 | import org.eclipse.viatra.query.runtime.matchers.tuple.Tuples; |
4 | import tools.refinery.store.model.Interpretation; | 9 | import tools.refinery.store.model.Interpretation; |
5 | import tools.refinery.store.query.viatra.internal.ViatraModelQueryAdapterImpl; | 10 | import tools.refinery.store.query.viatra.internal.ViatraModelQueryAdapterImpl; |
6 | import tools.refinery.store.query.view.TuplePreservingRelationView; | 11 | import tools.refinery.store.query.view.TuplePreservingView; |
7 | import tools.refinery.store.tuple.Tuple; | 12 | import tools.refinery.store.tuple.Tuple; |
8 | 13 | ||
9 | public class TuplePreservingRelationViewUpdateListener<T> extends RelationViewUpdateListener<T> { | 14 | public class TuplePreservingViewUpdateListener<T> extends SymbolViewUpdateListener<T> { |
10 | private final TuplePreservingRelationView<T> view; | 15 | private final TuplePreservingView<T> view; |
11 | 16 | ||
12 | TuplePreservingRelationViewUpdateListener(ViatraModelQueryAdapterImpl adapter, | 17 | TuplePreservingViewUpdateListener(ViatraModelQueryAdapterImpl adapter, TuplePreservingView<T> view, |
13 | TuplePreservingRelationView<T> view, Interpretation<T> interpretation) { | 18 | Interpretation<T> interpretation) { |
14 | super(adapter, interpretation); | 19 | super(adapter, interpretation); |
15 | this.view = view; | 20 | this.view = view; |
16 | } | 21 | } |
diff --git a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/DiagonalQueryTest.java b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/DiagonalQueryTest.java index 90229b73..6aae2ebe 100644 --- a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/DiagonalQueryTest.java +++ b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/DiagonalQueryTest.java | |||
@@ -1,17 +1,23 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.viatra; | 6 | package tools.refinery.store.query.viatra; |
2 | 7 | ||
3 | import org.eclipse.viatra.query.runtime.matchers.backend.QueryEvaluationHint; | 8 | import org.eclipse.viatra.query.runtime.matchers.backend.QueryEvaluationHint; |
4 | import tools.refinery.store.model.ModelStore; | 9 | import tools.refinery.store.model.ModelStore; |
5 | import tools.refinery.store.query.ModelQuery; | 10 | import tools.refinery.store.query.ModelQueryAdapter; |
6 | import tools.refinery.store.query.dnf.Dnf; | 11 | import tools.refinery.store.query.dnf.Dnf; |
7 | import tools.refinery.store.query.dnf.Query; | 12 | import tools.refinery.store.query.dnf.Query; |
8 | import tools.refinery.store.query.term.Variable; | ||
9 | import tools.refinery.store.query.viatra.tests.QueryEngineTest; | 13 | import tools.refinery.store.query.viatra.tests.QueryEngineTest; |
10 | import tools.refinery.store.query.view.FunctionalRelationView; | 14 | import tools.refinery.store.query.view.AnySymbolView; |
11 | import tools.refinery.store.query.view.KeyOnlyRelationView; | 15 | import tools.refinery.store.query.view.FunctionView; |
16 | import tools.refinery.store.query.view.KeyOnlyView; | ||
12 | import tools.refinery.store.representation.Symbol; | 17 | import tools.refinery.store.representation.Symbol; |
13 | import tools.refinery.store.tuple.Tuple; | 18 | import tools.refinery.store.tuple.Tuple; |
14 | 19 | ||
20 | import java.util.List; | ||
15 | import java.util.Map; | 21 | import java.util.Map; |
16 | import java.util.Optional; | 22 | import java.util.Optional; |
17 | 23 | ||
@@ -21,34 +27,33 @@ import static tools.refinery.store.query.viatra.tests.QueryAssertions.assertNull | |||
21 | import static tools.refinery.store.query.viatra.tests.QueryAssertions.assertResults; | 27 | import static tools.refinery.store.query.viatra.tests.QueryAssertions.assertResults; |
22 | 28 | ||
23 | class DiagonalQueryTest { | 29 | class DiagonalQueryTest { |
30 | private static final Symbol<Boolean> person = Symbol.of("Person", 1); | ||
31 | private static final Symbol<Boolean> friend = Symbol.of("friend", 2); | ||
32 | private static final Symbol<Boolean> symbol = Symbol.of("symbol", 4); | ||
33 | private static final Symbol<Integer> intSymbol = Symbol.of("intSymbol", 4, Integer.class); | ||
34 | private static final AnySymbolView personView = new KeyOnlyView<>(person); | ||
35 | private static final AnySymbolView friendView = new KeyOnlyView<>(friend); | ||
36 | private static final AnySymbolView symbolView = new KeyOnlyView<>(symbol); | ||
37 | private static final FunctionView<Integer> intSymbolView = new FunctionView<>(intSymbol); | ||
38 | |||
24 | @QueryEngineTest | 39 | @QueryEngineTest |
25 | void inputKeyNegationTest(QueryEvaluationHint hint) { | 40 | void inputKeyNegationTest(QueryEvaluationHint hint) { |
26 | var person = new Symbol<>("Person", 1, Boolean.class, false); | 41 | var query = Query.of("Diagonal", (builder, p1) -> builder.clause(p2 -> List.of( |
27 | var symbol = new Symbol<>("symbol", 4, Boolean.class, false); | 42 | personView.call(p1), |
28 | var personView = new KeyOnlyRelationView<>(person); | 43 | not(symbolView.call(p1, p1, p2, p2)) |
29 | var symbolView = new KeyOnlyRelationView<>(symbol); | 44 | ))); |
30 | |||
31 | var p1 = Variable.of("p1"); | ||
32 | var p2 = Variable.of("p2"); | ||
33 | var query = Query.builder("Diagonal") | ||
34 | .parameter(p1) | ||
35 | .clause( | ||
36 | personView.call(p1), | ||
37 | not(symbolView.call(p1, p1, p2, p2)) | ||
38 | ) | ||
39 | .build(); | ||
40 | 45 | ||
41 | var store = ModelStore.builder() | 46 | var store = ModelStore.builder() |
42 | .symbols(person, symbol) | 47 | .symbols(person, symbol) |
43 | .with(ViatraModelQuery.ADAPTER) | 48 | .with(ViatraModelQueryAdapter.builder() |
44 | .defaultHint(hint) | 49 | .defaultHint(hint) |
45 | .queries(query) | 50 | .queries(query)) |
46 | .build(); | 51 | .build(); |
47 | 52 | ||
48 | var model = store.createEmptyModel(); | 53 | var model = store.createEmptyModel(); |
49 | var personInterpretation = model.getInterpretation(person); | 54 | var personInterpretation = model.getInterpretation(person); |
50 | var symbolInterpretation = model.getInterpretation(symbol); | 55 | var symbolInterpretation = model.getInterpretation(symbol); |
51 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | 56 | var queryEngine = model.getAdapter(ModelQueryAdapter.class); |
52 | var queryResultSet = queryEngine.getResultSet(query); | 57 | var queryResultSet = queryEngine.getResultSet(query); |
53 | 58 | ||
54 | personInterpretation.put(Tuple.of(0), true); | 59 | personInterpretation.put(Tuple.of(0), true); |
@@ -71,17 +76,7 @@ class DiagonalQueryTest { | |||
71 | 76 | ||
72 | @QueryEngineTest | 77 | @QueryEngineTest |
73 | void subQueryNegationTest(QueryEvaluationHint hint) { | 78 | void subQueryNegationTest(QueryEvaluationHint hint) { |
74 | var person = new Symbol<>("Person", 1, Boolean.class, false); | 79 | var subQuery = Query.of("SubQuery", (builder, p1, p2, p3, p4) -> builder |
75 | var symbol = new Symbol<>("symbol", 4, Boolean.class, false); | ||
76 | var personView = new KeyOnlyRelationView<>(person); | ||
77 | var symbolView = new KeyOnlyRelationView<>(symbol); | ||
78 | |||
79 | var p1 = Variable.of("p1"); | ||
80 | var p2 = Variable.of("p2"); | ||
81 | var p3 = Variable.of("p3"); | ||
82 | var p4 = Variable.of("p4"); | ||
83 | var subQuery = Dnf.builder("SubQuery") | ||
84 | .parameters(p1, p2, p3, p4) | ||
85 | .clause( | 80 | .clause( |
86 | personView.call(p1), | 81 | personView.call(p1), |
87 | symbolView.call(p1, p2, p3, p4) | 82 | symbolView.call(p1, p2, p3, p4) |
@@ -89,27 +84,23 @@ class DiagonalQueryTest { | |||
89 | .clause( | 84 | .clause( |
90 | personView.call(p2), | 85 | personView.call(p2), |
91 | symbolView.call(p1, p2, p3, p4) | 86 | symbolView.call(p1, p2, p3, p4) |
92 | ) | 87 | )); |
93 | .build(); | 88 | var query = Query.of("Diagonal", (builder, p1) -> builder.clause(p2 -> List.of( |
94 | var query = Query.builder("Diagonal") | 89 | personView.call(p1), |
95 | .parameter(p1) | 90 | not(subQuery.call(p1, p1, p2, p2)) |
96 | .clause( | 91 | ))); |
97 | personView.call(p1), | ||
98 | not(subQuery.call(p1, p1, p2, p2)) | ||
99 | ) | ||
100 | .build(); | ||
101 | 92 | ||
102 | var store = ModelStore.builder() | 93 | var store = ModelStore.builder() |
103 | .symbols(person, symbol) | 94 | .symbols(person, symbol) |
104 | .with(ViatraModelQuery.ADAPTER) | 95 | .with(ViatraModelQueryAdapter.builder() |
105 | .defaultHint(hint) | 96 | .defaultHint(hint) |
106 | .queries(query) | 97 | .queries(query)) |
107 | .build(); | 98 | .build(); |
108 | 99 | ||
109 | var model = store.createEmptyModel(); | 100 | var model = store.createEmptyModel(); |
110 | var personInterpretation = model.getInterpretation(person); | 101 | var personInterpretation = model.getInterpretation(person); |
111 | var symbolInterpretation = model.getInterpretation(symbol); | 102 | var symbolInterpretation = model.getInterpretation(symbol); |
112 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | 103 | var queryEngine = model.getAdapter(ModelQueryAdapter.class); |
113 | var queryResultSet = queryEngine.getResultSet(query); | 104 | var queryResultSet = queryEngine.getResultSet(query); |
114 | 105 | ||
115 | personInterpretation.put(Tuple.of(0), true); | 106 | personInterpretation.put(Tuple.of(0), true); |
@@ -132,34 +123,22 @@ class DiagonalQueryTest { | |||
132 | 123 | ||
133 | @QueryEngineTest | 124 | @QueryEngineTest |
134 | void inputKeyCountTest(QueryEvaluationHint hint) { | 125 | void inputKeyCountTest(QueryEvaluationHint hint) { |
135 | var person = new Symbol<>("Person", 1, Boolean.class, false); | 126 | var query = Query.of("Diagonal", Integer.class, (builder, p1, output) -> builder.clause(p2 -> List.of( |
136 | var symbol = new Symbol<>("symbol", 4, Boolean.class, false); | 127 | personView.call(p1), |
137 | var personView = new KeyOnlyRelationView<>(person); | 128 | output.assign(symbolView.count(p1, p1, p2, p2)) |
138 | var symbolView = new KeyOnlyRelationView<>(symbol); | 129 | ))); |
139 | |||
140 | var p1 = Variable.of("p1"); | ||
141 | var p2 = Variable.of("p2"); | ||
142 | var x = Variable.of("x", Integer.class); | ||
143 | var query = Query.builder("Diagonal") | ||
144 | .parameter(p1) | ||
145 | .output(x) | ||
146 | .clause( | ||
147 | personView.call(p1), | ||
148 | x.assign(symbolView.count(p1, p1, p2, p2)) | ||
149 | ) | ||
150 | .build(); | ||
151 | 130 | ||
152 | var store = ModelStore.builder() | 131 | var store = ModelStore.builder() |
153 | .symbols(person, symbol) | 132 | .symbols(person, symbol) |
154 | .with(ViatraModelQuery.ADAPTER) | 133 | .with(ViatraModelQueryAdapter.builder() |
155 | .defaultHint(hint) | 134 | .defaultHint(hint) |
156 | .queries(query) | 135 | .queries(query)) |
157 | .build(); | 136 | .build(); |
158 | 137 | ||
159 | var model = store.createEmptyModel(); | 138 | var model = store.createEmptyModel(); |
160 | var personInterpretation = model.getInterpretation(person); | 139 | var personInterpretation = model.getInterpretation(person); |
161 | var symbolInterpretation = model.getInterpretation(symbol); | 140 | var symbolInterpretation = model.getInterpretation(symbol); |
162 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | 141 | var queryEngine = model.getAdapter(ModelQueryAdapter.class); |
163 | var queryResultSet = queryEngine.getResultSet(query); | 142 | var queryResultSet = queryEngine.getResultSet(query); |
164 | 143 | ||
165 | personInterpretation.put(Tuple.of(0), true); | 144 | personInterpretation.put(Tuple.of(0), true); |
@@ -183,47 +162,30 @@ class DiagonalQueryTest { | |||
183 | 162 | ||
184 | @QueryEngineTest | 163 | @QueryEngineTest |
185 | void subQueryCountTest(QueryEvaluationHint hint) { | 164 | void subQueryCountTest(QueryEvaluationHint hint) { |
186 | var person = new Symbol<>("Person", 1, Boolean.class, false); | 165 | var subQuery = Query.of("SubQuery", (builder, p1, p2, p3, p4) -> builder.clause( |
187 | var symbol = new Symbol<>("symbol", 4, Boolean.class, false); | ||
188 | var personView = new KeyOnlyRelationView<>(person); | ||
189 | var symbolView = new KeyOnlyRelationView<>(symbol); | ||
190 | |||
191 | var p1 = Variable.of("p1"); | ||
192 | var p2 = Variable.of("p2"); | ||
193 | var p3 = Variable.of("p3"); | ||
194 | var p4 = Variable.of("p4"); | ||
195 | var x = Variable.of("x", Integer.class); | ||
196 | var subQuery = Dnf.builder("SubQuery") | ||
197 | .parameters(p1, p2, p3, p4) | ||
198 | .clause( | ||
199 | personView.call(p1), | 166 | personView.call(p1), |
200 | symbolView.call(p1, p2, p3, p4) | 167 | symbolView.call(p1, p2, p3, p4) |
201 | ) | 168 | ) |
202 | .clause( | 169 | .clause( |
203 | personView.call(p2), | 170 | personView.call(p2), |
204 | symbolView.call(p1, p2, p3, p4) | 171 | symbolView.call(p1, p2, p3, p4) |
205 | ) | 172 | )); |
206 | .build(); | 173 | var query = Query.of("Diagonal", Integer.class, (builder, p1, output) -> builder.clause(p2 -> List.of( |
207 | var query = Query.builder("Diagonal") | 174 | personView.call(p1), |
208 | .parameter(p1) | 175 | output.assign(subQuery.count(p1, p1, p2, p2)) |
209 | .output(x) | 176 | ))); |
210 | .clause( | ||
211 | personView.call(p1), | ||
212 | x.assign(subQuery.count(p1, p1, p2, p2)) | ||
213 | ) | ||
214 | .build(); | ||
215 | 177 | ||
216 | var store = ModelStore.builder() | 178 | var store = ModelStore.builder() |
217 | .symbols(person, symbol) | 179 | .symbols(person, symbol) |
218 | .with(ViatraModelQuery.ADAPTER) | 180 | .with(ViatraModelQueryAdapter.builder() |
219 | .defaultHint(hint) | 181 | .defaultHint(hint) |
220 | .queries(query) | 182 | .queries(query)) |
221 | .build(); | 183 | .build(); |
222 | 184 | ||
223 | var model = store.createEmptyModel(); | 185 | var model = store.createEmptyModel(); |
224 | var personInterpretation = model.getInterpretation(person); | 186 | var personInterpretation = model.getInterpretation(person); |
225 | var symbolInterpretation = model.getInterpretation(symbol); | 187 | var symbolInterpretation = model.getInterpretation(symbol); |
226 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | 188 | var queryEngine = model.getAdapter(ModelQueryAdapter.class); |
227 | var queryResultSet = queryEngine.getResultSet(query); | 189 | var queryResultSet = queryEngine.getResultSet(query); |
228 | 190 | ||
229 | personInterpretation.put(Tuple.of(0), true); | 191 | personInterpretation.put(Tuple.of(0), true); |
@@ -247,46 +209,34 @@ class DiagonalQueryTest { | |||
247 | 209 | ||
248 | @QueryEngineTest | 210 | @QueryEngineTest |
249 | void inputKeyAggregationTest(QueryEvaluationHint hint) { | 211 | void inputKeyAggregationTest(QueryEvaluationHint hint) { |
250 | var person = new Symbol<>("Person", 1, Boolean.class, false); | 212 | var query = Query.of("Diagonal", Integer.class, (builder, p1, output) -> builder |
251 | var symbol = new Symbol<>("symbol", 4, Integer.class, null); | 213 | .clause((p2) -> List.of( |
252 | var personView = new KeyOnlyRelationView<>(person); | ||
253 | var symbolView = new FunctionalRelationView<>(symbol); | ||
254 | |||
255 | var p1 = Variable.of("p1"); | ||
256 | var p2 = Variable.of("p2"); | ||
257 | var x = Variable.of("x", Integer.class); | ||
258 | var y = Variable.of("y", Integer.class); | ||
259 | var query = Query.builder("Diagonal") | ||
260 | .parameter(p1) | ||
261 | .output(x) | ||
262 | .clause( | ||
263 | personView.call(p1), | 214 | personView.call(p1), |
264 | x.assign(symbolView.aggregate(y, INT_SUM, p1, p1, p2, p2, y)) | 215 | output.assign(intSymbolView.aggregate(INT_SUM, p1, p1, p2, p2)) |
265 | ) | 216 | ))); |
266 | .build(); | ||
267 | 217 | ||
268 | var store = ModelStore.builder() | 218 | var store = ModelStore.builder() |
269 | .symbols(person, symbol) | 219 | .symbols(person, intSymbol) |
270 | .with(ViatraModelQuery.ADAPTER) | 220 | .with(ViatraModelQueryAdapter.builder() |
271 | .defaultHint(hint) | 221 | .defaultHint(hint) |
272 | .queries(query) | 222 | .queries(query)) |
273 | .build(); | 223 | .build(); |
274 | 224 | ||
275 | var model = store.createEmptyModel(); | 225 | var model = store.createEmptyModel(); |
276 | var personInterpretation = model.getInterpretation(person); | 226 | var personInterpretation = model.getInterpretation(person); |
277 | var symbolInterpretation = model.getInterpretation(symbol); | 227 | var intSymbolInterpretation = model.getInterpretation(intSymbol); |
278 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | 228 | var queryEngine = model.getAdapter(ModelQueryAdapter.class); |
279 | var queryResultSet = queryEngine.getResultSet(query); | 229 | var queryResultSet = queryEngine.getResultSet(query); |
280 | 230 | ||
281 | personInterpretation.put(Tuple.of(0), true); | 231 | personInterpretation.put(Tuple.of(0), true); |
282 | personInterpretation.put(Tuple.of(1), true); | 232 | personInterpretation.put(Tuple.of(1), true); |
283 | personInterpretation.put(Tuple.of(2), true); | 233 | personInterpretation.put(Tuple.of(2), true); |
284 | 234 | ||
285 | symbolInterpretation.put(Tuple.of(0, 0, 1, 1), 1); | 235 | intSymbolInterpretation.put(Tuple.of(0, 0, 1, 1), 1); |
286 | symbolInterpretation.put(Tuple.of(0, 0, 2, 2), 2); | 236 | intSymbolInterpretation.put(Tuple.of(0, 0, 2, 2), 2); |
287 | symbolInterpretation.put(Tuple.of(0, 0, 1, 2), 10); | 237 | intSymbolInterpretation.put(Tuple.of(0, 0, 1, 2), 10); |
288 | symbolInterpretation.put(Tuple.of(1, 1, 0, 1), 11); | 238 | intSymbolInterpretation.put(Tuple.of(1, 1, 0, 1), 11); |
289 | symbolInterpretation.put(Tuple.of(1, 2, 1, 1), 12); | 239 | intSymbolInterpretation.put(Tuple.of(1, 2, 1, 1), 12); |
290 | 240 | ||
291 | queryEngine.flushChanges(); | 241 | queryEngine.flushChanges(); |
292 | assertNullableResults(Map.of( | 242 | assertNullableResults(Map.of( |
@@ -299,62 +249,52 @@ class DiagonalQueryTest { | |||
299 | 249 | ||
300 | @QueryEngineTest | 250 | @QueryEngineTest |
301 | void subQueryAggregationTest(QueryEvaluationHint hint) { | 251 | void subQueryAggregationTest(QueryEvaluationHint hint) { |
302 | var person = new Symbol<>("Person", 1, Boolean.class, false); | 252 | var subQuery = Dnf.of("SubQuery", builder -> { |
303 | var symbol = new Symbol<>("symbol", 4, Integer.class, null); | 253 | var p1 = builder.parameter("p1"); |
304 | var personView = new KeyOnlyRelationView<>(person); | 254 | var p2 = builder.parameter("p2"); |
305 | var symbolView = new FunctionalRelationView<>(symbol); | 255 | var p3 = builder.parameter("p3"); |
306 | 256 | var p4 = builder.parameter("p4"); | |
307 | var p1 = Variable.of("p1"); | 257 | var x = builder.parameter("x", Integer.class); |
308 | var p2 = Variable.of("p2"); | 258 | var y = builder.parameter("y", Integer.class); |
309 | var p3 = Variable.of("p3"); | 259 | builder.clause( |
310 | var p4 = Variable.of("p4"); | 260 | personView.call(p1), |
311 | var x = Variable.of("x", Integer.class); | 261 | intSymbolView.call(p1, p2, p3, p4, x), |
312 | var y = Variable.of("y", Integer.class); | 262 | y.assign(x) |
313 | var z = Variable.of("z", Integer.class); | 263 | ); |
314 | var subQuery = Dnf.builder("SubQuery") | 264 | builder.clause( |
315 | .parameters(p1, p2, p3, p4, x, y) | 265 | personView.call(p2), |
316 | .clause( | 266 | intSymbolView.call(p1, p2, p3, p4, x), |
267 | y.assign(x) | ||
268 | ); | ||
269 | }); | ||
270 | var query = Query.of("Diagonal", Integer.class, (builder, p1, output) -> builder | ||
271 | .clause(Integer.class, Integer.class, (p2, y, z) -> List.of( | ||
317 | personView.call(p1), | 272 | personView.call(p1), |
318 | symbolView.call(p1, p2, p3, p4, x), | 273 | output.assign(subQuery.aggregateBy(y, INT_SUM, p1, p1, p2, p2, y, z)) |
319 | y.assign(x) | 274 | ))); |
320 | ) | ||
321 | .clause( | ||
322 | personView.call(p2), | ||
323 | symbolView.call(p1, p2, p3, p4, x), | ||
324 | y.assign(x) | ||
325 | ) | ||
326 | .build(); | ||
327 | var query = Query.builder("Diagonal") | ||
328 | .parameter(p1) | ||
329 | .output(x) | ||
330 | .clause( | ||
331 | personView.call(p1), | ||
332 | x.assign(subQuery.aggregate(z, INT_SUM, p1, p1, p2, p2, z, z)) | ||
333 | ) | ||
334 | .build(); | ||
335 | 275 | ||
336 | var store = ModelStore.builder() | 276 | var store = ModelStore.builder() |
337 | .symbols(person, symbol) | 277 | .symbols(person, intSymbol) |
338 | .with(ViatraModelQuery.ADAPTER) | 278 | .with(ViatraModelQueryAdapter.builder() |
339 | .defaultHint(hint) | 279 | .defaultHint(hint) |
340 | .queries(query) | 280 | .queries(query)) |
341 | .build(); | 281 | .build(); |
342 | 282 | ||
343 | var model = store.createEmptyModel(); | 283 | var model = store.createEmptyModel(); |
344 | var personInterpretation = model.getInterpretation(person); | 284 | var personInterpretation = model.getInterpretation(person); |
345 | var symbolInterpretation = model.getInterpretation(symbol); | 285 | var intSymbolInterpretation = model.getInterpretation(intSymbol); |
346 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | 286 | var queryEngine = model.getAdapter(ModelQueryAdapter.class); |
347 | var queryResultSet = queryEngine.getResultSet(query); | 287 | var queryResultSet = queryEngine.getResultSet(query); |
348 | 288 | ||
349 | personInterpretation.put(Tuple.of(0), true); | 289 | personInterpretation.put(Tuple.of(0), true); |
350 | personInterpretation.put(Tuple.of(1), true); | 290 | personInterpretation.put(Tuple.of(1), true); |
351 | personInterpretation.put(Tuple.of(2), true); | 291 | personInterpretation.put(Tuple.of(2), true); |
352 | 292 | ||
353 | symbolInterpretation.put(Tuple.of(0, 0, 1, 1), 1); | 293 | intSymbolInterpretation.put(Tuple.of(0, 0, 1, 1), 1); |
354 | symbolInterpretation.put(Tuple.of(0, 0, 2, 2), 2); | 294 | intSymbolInterpretation.put(Tuple.of(0, 0, 2, 2), 2); |
355 | symbolInterpretation.put(Tuple.of(0, 0, 1, 2), 10); | 295 | intSymbolInterpretation.put(Tuple.of(0, 0, 1, 2), 10); |
356 | symbolInterpretation.put(Tuple.of(1, 1, 0, 1), 11); | 296 | intSymbolInterpretation.put(Tuple.of(1, 1, 0, 1), 11); |
357 | symbolInterpretation.put(Tuple.of(1, 2, 1, 1), 12); | 297 | intSymbolInterpretation.put(Tuple.of(1, 2, 1, 1), 12); |
358 | 298 | ||
359 | queryEngine.flushChanges(); | 299 | queryEngine.flushChanges(); |
360 | assertNullableResults(Map.of( | 300 | assertNullableResults(Map.of( |
@@ -367,40 +307,31 @@ class DiagonalQueryTest { | |||
367 | 307 | ||
368 | @QueryEngineTest | 308 | @QueryEngineTest |
369 | void inputKeyTransitiveTest(QueryEvaluationHint hint) { | 309 | void inputKeyTransitiveTest(QueryEvaluationHint hint) { |
370 | var person = new Symbol<>("Person", 1, Boolean.class, false); | 310 | var query = Query.of("Diagonal", (builder, p1) -> builder.clause( |
371 | var symbol = new Symbol<>("symbol", 2, Boolean.class, false); | 311 | personView.call(p1), |
372 | var personView = new KeyOnlyRelationView<>(person); | 312 | friendView.callTransitive(p1, p1) |
373 | var symbolView = new KeyOnlyRelationView<>(symbol); | 313 | )); |
374 | |||
375 | var p1 = Variable.of("p1"); | ||
376 | var query = Query.builder("Diagonal") | ||
377 | .parameter(p1) | ||
378 | .clause( | ||
379 | personView.call(p1), | ||
380 | symbolView.callTransitive(p1, p1) | ||
381 | ) | ||
382 | .build(); | ||
383 | 314 | ||
384 | var store = ModelStore.builder() | 315 | var store = ModelStore.builder() |
385 | .symbols(person, symbol) | 316 | .symbols(person, friend) |
386 | .with(ViatraModelQuery.ADAPTER) | 317 | .with(ViatraModelQueryAdapter.builder() |
387 | .defaultHint(hint) | 318 | .defaultHint(hint) |
388 | .queries(query) | 319 | .queries(query)) |
389 | .build(); | 320 | .build(); |
390 | 321 | ||
391 | var model = store.createEmptyModel(); | 322 | var model = store.createEmptyModel(); |
392 | var personInterpretation = model.getInterpretation(person); | 323 | var personInterpretation = model.getInterpretation(person); |
393 | var symbolInterpretation = model.getInterpretation(symbol); | 324 | var friendInterpretation = model.getInterpretation(friend); |
394 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | 325 | var queryEngine = model.getAdapter(ModelQueryAdapter.class); |
395 | var queryResultSet = queryEngine.getResultSet(query); | 326 | var queryResultSet = queryEngine.getResultSet(query); |
396 | 327 | ||
397 | personInterpretation.put(Tuple.of(0), true); | 328 | personInterpretation.put(Tuple.of(0), true); |
398 | personInterpretation.put(Tuple.of(1), true); | 329 | personInterpretation.put(Tuple.of(1), true); |
399 | personInterpretation.put(Tuple.of(2), true); | 330 | personInterpretation.put(Tuple.of(2), true); |
400 | 331 | ||
401 | symbolInterpretation.put(Tuple.of(0, 0), true); | 332 | friendInterpretation.put(Tuple.of(0, 0), true); |
402 | symbolInterpretation.put(Tuple.of(0, 1), true); | 333 | friendInterpretation.put(Tuple.of(0, 1), true); |
403 | symbolInterpretation.put(Tuple.of(1, 2), true); | 334 | friendInterpretation.put(Tuple.of(1, 2), true); |
404 | 335 | ||
405 | queryEngine.flushChanges(); | 336 | queryEngine.flushChanges(); |
406 | assertResults(Map.of( | 337 | assertResults(Map.of( |
@@ -413,52 +344,40 @@ class DiagonalQueryTest { | |||
413 | 344 | ||
414 | @QueryEngineTest | 345 | @QueryEngineTest |
415 | void subQueryTransitiveTest(QueryEvaluationHint hint) { | 346 | void subQueryTransitiveTest(QueryEvaluationHint hint) { |
416 | var person = new Symbol<>("Person", 1, Boolean.class, false); | 347 | var subQuery = Query.of("SubQuery", (builder, p1, p2) -> builder |
417 | var symbol = new Symbol<>("symbol", 2, Boolean.class, false); | ||
418 | var personView = new KeyOnlyRelationView<>(person); | ||
419 | var symbolView = new KeyOnlyRelationView<>(symbol); | ||
420 | |||
421 | var p1 = Variable.of("p1"); | ||
422 | var p2 = Variable.of("p2"); | ||
423 | var subQuery = Dnf.builder("SubQuery") | ||
424 | .parameters(p1, p2) | ||
425 | .clause( | 348 | .clause( |
426 | personView.call(p1), | 349 | personView.call(p1), |
427 | symbolView.call(p1, p2) | 350 | friendView.call(p1, p2) |
428 | ) | 351 | ) |
429 | .clause( | 352 | .clause( |
430 | personView.call(p2), | 353 | personView.call(p2), |
431 | symbolView.call(p1, p2) | 354 | friendView.call(p1, p2) |
432 | ) | 355 | )); |
433 | .build(); | 356 | var query = Query.of("Diagonal", (builder, p1) -> builder.clause( |
434 | var query = Query.builder("Diagonal") | 357 | personView.call(p1), |
435 | .parameter(p1) | 358 | subQuery.callTransitive(p1, p1) |
436 | .clause( | 359 | )); |
437 | personView.call(p1), | ||
438 | subQuery.callTransitive(p1, p1) | ||
439 | ) | ||
440 | .build(); | ||
441 | 360 | ||
442 | var store = ModelStore.builder() | 361 | var store = ModelStore.builder() |
443 | .symbols(person, symbol) | 362 | .symbols(person, friend) |
444 | .with(ViatraModelQuery.ADAPTER) | 363 | .with(ViatraModelQueryAdapter.builder() |
445 | .defaultHint(hint) | 364 | .defaultHint(hint) |
446 | .queries(query) | 365 | .queries(query)) |
447 | .build(); | 366 | .build(); |
448 | 367 | ||
449 | var model = store.createEmptyModel(); | 368 | var model = store.createEmptyModel(); |
450 | var personInterpretation = model.getInterpretation(person); | 369 | var personInterpretation = model.getInterpretation(person); |
451 | var symbolInterpretation = model.getInterpretation(symbol); | 370 | var friendInterpretation = model.getInterpretation(friend); |
452 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | 371 | var queryEngine = model.getAdapter(ModelQueryAdapter.class); |
453 | var queryResultSet = queryEngine.getResultSet(query); | 372 | var queryResultSet = queryEngine.getResultSet(query); |
454 | 373 | ||
455 | personInterpretation.put(Tuple.of(0), true); | 374 | personInterpretation.put(Tuple.of(0), true); |
456 | personInterpretation.put(Tuple.of(1), true); | 375 | personInterpretation.put(Tuple.of(1), true); |
457 | personInterpretation.put(Tuple.of(2), true); | 376 | personInterpretation.put(Tuple.of(2), true); |
458 | 377 | ||
459 | symbolInterpretation.put(Tuple.of(0, 0), true); | 378 | friendInterpretation.put(Tuple.of(0, 0), true); |
460 | symbolInterpretation.put(Tuple.of(0, 1), true); | 379 | friendInterpretation.put(Tuple.of(0, 1), true); |
461 | symbolInterpretation.put(Tuple.of(1, 2), true); | 380 | friendInterpretation.put(Tuple.of(1, 2), true); |
462 | 381 | ||
463 | queryEngine.flushChanges(); | 382 | queryEngine.flushChanges(); |
464 | assertResults(Map.of( | 383 | assertResults(Map.of( |
diff --git a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/FunctionalQueryTest.java b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/FunctionalQueryTest.java index fa2a008f..258127e7 100644 --- a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/FunctionalQueryTest.java +++ b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/FunctionalQueryTest.java | |||
@@ -1,20 +1,26 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.viatra; | 6 | package tools.refinery.store.query.viatra; |
2 | 7 | ||
3 | import org.eclipse.viatra.query.runtime.matchers.backend.QueryEvaluationHint; | 8 | import org.eclipse.viatra.query.runtime.matchers.backend.QueryEvaluationHint; |
4 | import tools.refinery.store.map.Cursor; | 9 | import tools.refinery.store.map.Cursor; |
5 | import tools.refinery.store.model.ModelStore; | 10 | import tools.refinery.store.model.ModelStore; |
6 | import tools.refinery.store.query.ModelQuery; | 11 | import tools.refinery.store.query.ModelQueryAdapter; |
7 | import tools.refinery.store.query.dnf.Dnf; | ||
8 | import tools.refinery.store.query.dnf.Query; | 12 | import tools.refinery.store.query.dnf.Query; |
9 | import tools.refinery.store.query.term.Variable; | 13 | import tools.refinery.store.query.term.Variable; |
10 | import tools.refinery.store.query.viatra.tests.QueryEngineTest; | 14 | import tools.refinery.store.query.viatra.tests.QueryEngineTest; |
11 | import tools.refinery.store.query.view.FilteredRelationView; | 15 | import tools.refinery.store.query.view.AnySymbolView; |
12 | import tools.refinery.store.query.view.FunctionalRelationView; | 16 | import tools.refinery.store.query.view.FilteredView; |
13 | import tools.refinery.store.query.view.KeyOnlyRelationView; | 17 | import tools.refinery.store.query.view.FunctionView; |
18 | import tools.refinery.store.query.view.KeyOnlyView; | ||
14 | import tools.refinery.store.representation.Symbol; | 19 | import tools.refinery.store.representation.Symbol; |
15 | import tools.refinery.store.representation.TruthValue; | 20 | import tools.refinery.store.representation.TruthValue; |
16 | import tools.refinery.store.tuple.Tuple; | 21 | import tools.refinery.store.tuple.Tuple; |
17 | 22 | ||
23 | import java.util.List; | ||
18 | import java.util.Map; | 24 | import java.util.Map; |
19 | import java.util.Optional; | 25 | import java.util.Optional; |
20 | 26 | ||
@@ -29,35 +35,31 @@ import static tools.refinery.store.query.viatra.tests.QueryAssertions.assertNull | |||
29 | import static tools.refinery.store.query.viatra.tests.QueryAssertions.assertResults; | 35 | import static tools.refinery.store.query.viatra.tests.QueryAssertions.assertResults; |
30 | 36 | ||
31 | class FunctionalQueryTest { | 37 | class FunctionalQueryTest { |
38 | private static final Symbol<Boolean> person = Symbol.of("Person", 1); | ||
39 | private static final Symbol<Integer> age = Symbol.of("age", 1, Integer.class); | ||
40 | private static final Symbol<TruthValue> friend = Symbol.of("friend", 2, TruthValue.class, TruthValue.FALSE); | ||
41 | private static final AnySymbolView personView = new KeyOnlyView<>(person); | ||
42 | private static final FunctionView<Integer> ageView = new FunctionView<>(age); | ||
43 | private static final AnySymbolView friendMustView = new FilteredView<>(friend, "must", TruthValue::must); | ||
44 | |||
32 | @QueryEngineTest | 45 | @QueryEngineTest |
33 | void inputKeyTest(QueryEvaluationHint hint) { | 46 | void inputKeyTest(QueryEvaluationHint hint) { |
34 | var person = new Symbol<>("Person", 1, Boolean.class, false); | 47 | var query = Query.of("InputKey", Integer.class, (builder, p1, output) -> builder.clause( |
35 | var age = new Symbol<>("age", 1, Integer.class, null); | 48 | personView.call(p1), |
36 | var personView = new KeyOnlyRelationView<>(person); | 49 | ageView.call(p1, output) |
37 | var ageView = new FunctionalRelationView<>(age); | 50 | )); |
38 | |||
39 | var p1 = Variable.of("p1"); | ||
40 | var x = Variable.of("x", Integer.class); | ||
41 | var query = Query.builder("InputKey") | ||
42 | .parameter(p1) | ||
43 | .output(x) | ||
44 | .clause( | ||
45 | personView.call(p1), | ||
46 | ageView.call(p1, x) | ||
47 | ) | ||
48 | .build(); | ||
49 | 51 | ||
50 | var store = ModelStore.builder() | 52 | var store = ModelStore.builder() |
51 | .symbols(person, age) | 53 | .symbols(person, age) |
52 | .with(ViatraModelQuery.ADAPTER) | 54 | .with(ViatraModelQueryAdapter.builder() |
53 | .defaultHint(hint) | 55 | .defaultHint(hint) |
54 | .queries(query) | 56 | .queries(query)) |
55 | .build(); | 57 | .build(); |
56 | 58 | ||
57 | var model = store.createEmptyModel(); | 59 | var model = store.createEmptyModel(); |
58 | var personInterpretation = model.getInterpretation(person); | 60 | var personInterpretation = model.getInterpretation(person); |
59 | var ageInterpretation = model.getInterpretation(age); | 61 | var ageInterpretation = model.getInterpretation(age); |
60 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | 62 | var queryEngine = model.getAdapter(ModelQueryAdapter.class); |
61 | var queryResultSet = queryEngine.getResultSet(query); | 63 | var queryResultSet = queryEngine.getResultSet(query); |
62 | 64 | ||
63 | personInterpretation.put(Tuple.of(0), true); | 65 | personInterpretation.put(Tuple.of(0), true); |
@@ -77,40 +79,26 @@ class FunctionalQueryTest { | |||
77 | 79 | ||
78 | @QueryEngineTest | 80 | @QueryEngineTest |
79 | void predicateTest(QueryEvaluationHint hint) { | 81 | void predicateTest(QueryEvaluationHint hint) { |
80 | var person = new Symbol<>("Person", 1, Boolean.class, false); | 82 | var subQuery = Query.of("SubQuery", Integer.class, (builder, p1, x) -> builder.clause( |
81 | var age = new Symbol<>("age", 1, Integer.class, null); | 83 | personView.call(p1), |
82 | var personView = new KeyOnlyRelationView<>(person); | 84 | ageView.call(p1, x) |
83 | var ageView = new FunctionalRelationView<>(age); | 85 | )); |
84 | 86 | var query = Query.of("Predicate", Integer.class, (builder, p1, output) -> builder.clause( | |
85 | var p1 = Variable.of("p1"); | 87 | personView.call(p1), |
86 | var x = Variable.of("x", Integer.class); | 88 | output.assign(subQuery.call(p1)) |
87 | var subQuery = Dnf.builder("SubQuery") | 89 | )); |
88 | .parameters(p1, x) | ||
89 | .clause( | ||
90 | personView.call(p1), | ||
91 | ageView.call(p1, x) | ||
92 | ) | ||
93 | .build(); | ||
94 | var query = Query.builder("Predicate") | ||
95 | .parameter(p1) | ||
96 | .output(x) | ||
97 | .clause( | ||
98 | personView.call(p1), | ||
99 | subQuery.call(p1, x) | ||
100 | ) | ||
101 | .build(); | ||
102 | 90 | ||
103 | var store = ModelStore.builder() | 91 | var store = ModelStore.builder() |
104 | .symbols(person, age) | 92 | .symbols(person, age) |
105 | .with(ViatraModelQuery.ADAPTER) | 93 | .with(ViatraModelQueryAdapter.builder() |
106 | .defaultHint(hint) | 94 | .defaultHint(hint) |
107 | .queries(query) | 95 | .queries(query)) |
108 | .build(); | 96 | .build(); |
109 | 97 | ||
110 | var model = store.createEmptyModel(); | 98 | var model = store.createEmptyModel(); |
111 | var personInterpretation = model.getInterpretation(person); | 99 | var personInterpretation = model.getInterpretation(person); |
112 | var ageInterpretation = model.getInterpretation(age); | 100 | var ageInterpretation = model.getInterpretation(age); |
113 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | 101 | var queryEngine = model.getAdapter(ModelQueryAdapter.class); |
114 | var queryResultSet = queryEngine.getResultSet(query); | 102 | var queryResultSet = queryEngine.getResultSet(query); |
115 | 103 | ||
116 | personInterpretation.put(Tuple.of(0), true); | 104 | personInterpretation.put(Tuple.of(0), true); |
@@ -130,35 +118,26 @@ class FunctionalQueryTest { | |||
130 | 118 | ||
131 | @QueryEngineTest | 119 | @QueryEngineTest |
132 | void computationTest(QueryEvaluationHint hint) { | 120 | void computationTest(QueryEvaluationHint hint) { |
133 | var person = new Symbol<>("Person", 1, Boolean.class, false); | 121 | var query = Query.of("Computation", Integer.class, (builder, p1, output) -> builder.clause(() -> { |
134 | var age = new Symbol<>("age", 1, Integer.class, null); | 122 | var x = Variable.of("x", Integer.class); |
135 | var personView = new KeyOnlyRelationView<>(person); | 123 | return List.of( |
136 | var ageView = new FunctionalRelationView<>(age); | 124 | personView.call(p1), |
137 | 125 | ageView.call(p1, x), | |
138 | var p1 = Variable.of("p1"); | 126 | output.assign(mul(x, constant(7))) |
139 | var x = Variable.of("x", Integer.class); | 127 | ); |
140 | var y = Variable.of("y", Integer.class); | 128 | })); |
141 | var query = Query.builder("Computation") | ||
142 | .parameter(p1) | ||
143 | .output(y) | ||
144 | .clause( | ||
145 | personView.call(p1), | ||
146 | ageView.call(p1, x), | ||
147 | y.assign(mul(x, constant(7))) | ||
148 | ) | ||
149 | .build(); | ||
150 | 129 | ||
151 | var store = ModelStore.builder() | 130 | var store = ModelStore.builder() |
152 | .symbols(person, age) | 131 | .symbols(person, age) |
153 | .with(ViatraModelQuery.ADAPTER) | 132 | .with(ViatraModelQueryAdapter.builder() |
154 | .defaultHint(hint) | 133 | .defaultHint(hint) |
155 | .queries(query) | 134 | .queries(query)) |
156 | .build(); | 135 | .build(); |
157 | 136 | ||
158 | var model = store.createEmptyModel(); | 137 | var model = store.createEmptyModel(); |
159 | var personInterpretation = model.getInterpretation(person); | 138 | var personInterpretation = model.getInterpretation(person); |
160 | var ageInterpretation = model.getInterpretation(age); | 139 | var ageInterpretation = model.getInterpretation(age); |
161 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | 140 | var queryEngine = model.getAdapter(ModelQueryAdapter.class); |
162 | var queryResultSet = queryEngine.getResultSet(query); | 141 | var queryResultSet = queryEngine.getResultSet(query); |
163 | 142 | ||
164 | personInterpretation.put(Tuple.of(0), true); | 143 | personInterpretation.put(Tuple.of(0), true); |
@@ -177,34 +156,22 @@ class FunctionalQueryTest { | |||
177 | 156 | ||
178 | @QueryEngineTest | 157 | @QueryEngineTest |
179 | void inputKeyCountTest(QueryEvaluationHint hint) { | 158 | void inputKeyCountTest(QueryEvaluationHint hint) { |
180 | var person = new Symbol<>("Person", 1, Boolean.class, false); | 159 | var query = Query.of("Count", Integer.class, (builder, p1, output) -> builder.clause( |
181 | var friend = new Symbol<>("friend", 2, TruthValue.class, TruthValue.FALSE); | 160 | personView.call(p1), |
182 | var personView = new KeyOnlyRelationView<>(person); | 161 | output.assign(friendMustView.count(p1, Variable.of())) |
183 | var friendMustView = new FilteredRelationView<>(friend, "must", TruthValue::must); | 162 | )); |
184 | |||
185 | var p1 = Variable.of("p1"); | ||
186 | var p2 = Variable.of("p2"); | ||
187 | var x = Variable.of("x", Integer.class); | ||
188 | var query = Query.builder("Count") | ||
189 | .parameter(p1) | ||
190 | .output(x) | ||
191 | .clause( | ||
192 | personView.call(p1), | ||
193 | x.assign(friendMustView.count(p1, p2)) | ||
194 | ) | ||
195 | .build(); | ||
196 | 163 | ||
197 | var store = ModelStore.builder() | 164 | var store = ModelStore.builder() |
198 | .symbols(person, friend) | 165 | .symbols(person, friend) |
199 | .with(ViatraModelQuery.ADAPTER) | 166 | .with(ViatraModelQueryAdapter.builder() |
200 | .defaultHint(hint) | 167 | .defaultHint(hint) |
201 | .queries(query) | 168 | .queries(query)) |
202 | .build(); | 169 | .build(); |
203 | 170 | ||
204 | var model = store.createEmptyModel(); | 171 | var model = store.createEmptyModel(); |
205 | var personInterpretation = model.getInterpretation(person); | 172 | var personInterpretation = model.getInterpretation(person); |
206 | var friendInterpretation = model.getInterpretation(friend); | 173 | var friendInterpretation = model.getInterpretation(friend); |
207 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | 174 | var queryEngine = model.getAdapter(ModelQueryAdapter.class); |
208 | var queryResultSet = queryEngine.getResultSet(query); | 175 | var queryResultSet = queryEngine.getResultSet(query); |
209 | 176 | ||
210 | personInterpretation.put(Tuple.of(0), true); | 177 | personInterpretation.put(Tuple.of(0), true); |
@@ -226,42 +193,27 @@ class FunctionalQueryTest { | |||
226 | 193 | ||
227 | @QueryEngineTest | 194 | @QueryEngineTest |
228 | void predicateCountTest(QueryEvaluationHint hint) { | 195 | void predicateCountTest(QueryEvaluationHint hint) { |
229 | var person = new Symbol<>("Person", 1, Boolean.class, false); | 196 | var subQuery = Query.of("SubQuery", (builder, p1, p2) -> builder.clause( |
230 | var friend = new Symbol<>("friend", 2, TruthValue.class, TruthValue.FALSE); | 197 | personView.call(p1), |
231 | var personView = new KeyOnlyRelationView<>(person); | 198 | personView.call(p2), |
232 | var friendMustView = new FilteredRelationView<>(friend, "must", TruthValue::must); | 199 | friendMustView.call(p1, p2) |
233 | 200 | )); | |
234 | var p1 = Variable.of("p1"); | 201 | var query = Query.of("Count", Integer.class, (builder, p1, output) -> builder.clause( |
235 | var p2 = Variable.of("p2"); | 202 | personView.call(p1), |
236 | var x = Variable.of("x", Integer.class); | 203 | output.assign(subQuery.count(p1, Variable.of())) |
237 | var subQuery = Dnf.builder("SubQuery") | 204 | )); |
238 | .parameters(p1, p2) | ||
239 | .clause( | ||
240 | personView.call(p1), | ||
241 | personView.call(p2), | ||
242 | friendMustView.call(p1, p2) | ||
243 | ) | ||
244 | .build(); | ||
245 | var query = Query.builder("Count") | ||
246 | .parameter(p1) | ||
247 | .output(x) | ||
248 | .clause( | ||
249 | personView.call(p1), | ||
250 | x.assign(subQuery.count(p1, p2)) | ||
251 | ) | ||
252 | .build(); | ||
253 | 205 | ||
254 | var store = ModelStore.builder() | 206 | var store = ModelStore.builder() |
255 | .symbols(person, friend) | 207 | .symbols(person, friend) |
256 | .with(ViatraModelQuery.ADAPTER) | 208 | .with(ViatraModelQueryAdapter.builder() |
257 | .defaultHint(hint) | 209 | .defaultHint(hint) |
258 | .queries(query) | 210 | .queries(query)) |
259 | .build(); | 211 | .build(); |
260 | 212 | ||
261 | var model = store.createEmptyModel(); | 213 | var model = store.createEmptyModel(); |
262 | var personInterpretation = model.getInterpretation(person); | 214 | var personInterpretation = model.getInterpretation(person); |
263 | var friendInterpretation = model.getInterpretation(friend); | 215 | var friendInterpretation = model.getInterpretation(friend); |
264 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | 216 | var queryEngine = model.getAdapter(ModelQueryAdapter.class); |
265 | var queryResultSet = queryEngine.getResultSet(query); | 217 | var queryResultSet = queryEngine.getResultSet(query); |
266 | 218 | ||
267 | personInterpretation.put(Tuple.of(0), true); | 219 | personInterpretation.put(Tuple.of(0), true); |
@@ -283,29 +235,20 @@ class FunctionalQueryTest { | |||
283 | 235 | ||
284 | @QueryEngineTest | 236 | @QueryEngineTest |
285 | void inputKeyAggregationTest(QueryEvaluationHint hint) { | 237 | void inputKeyAggregationTest(QueryEvaluationHint hint) { |
286 | var age = new Symbol<>("age", 1, Integer.class, null); | 238 | var query = Query.of("Aggregate", Integer.class, (builder, output) -> builder.clause( |
287 | var ageView = new FunctionalRelationView<>(age); | 239 | output.assign(ageView.aggregate(INT_SUM, Variable.of())) |
288 | 240 | )); | |
289 | var p1 = Variable.of("p1"); | ||
290 | var x = Variable.of("x", Integer.class); | ||
291 | var y = Variable.of("y", Integer.class); | ||
292 | var query = Query.builder("Aggregate") | ||
293 | .output(x) | ||
294 | .clause( | ||
295 | x.assign(ageView.aggregate(y, INT_SUM, p1, y)) | ||
296 | ) | ||
297 | .build(); | ||
298 | 241 | ||
299 | var store = ModelStore.builder() | 242 | var store = ModelStore.builder() |
300 | .symbols(age) | 243 | .symbols(age) |
301 | .with(ViatraModelQuery.ADAPTER) | 244 | .with(ViatraModelQueryAdapter.builder() |
302 | .defaultHint(hint) | 245 | .defaultHint(hint) |
303 | .queries(query) | 246 | .queries(query)) |
304 | .build(); | 247 | .build(); |
305 | 248 | ||
306 | var model = store.createEmptyModel(); | 249 | var model = store.createEmptyModel(); |
307 | var ageInterpretation = model.getInterpretation(age); | 250 | var ageInterpretation = model.getInterpretation(age); |
308 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | 251 | var queryEngine = model.getAdapter(ModelQueryAdapter.class); |
309 | var queryResultSet = queryEngine.getResultSet(query); | 252 | var queryResultSet = queryEngine.getResultSet(query); |
310 | 253 | ||
311 | ageInterpretation.put(Tuple.of(0), 12); | 254 | ageInterpretation.put(Tuple.of(0), 12); |
@@ -317,39 +260,25 @@ class FunctionalQueryTest { | |||
317 | 260 | ||
318 | @QueryEngineTest | 261 | @QueryEngineTest |
319 | void predicateAggregationTest(QueryEvaluationHint hint) { | 262 | void predicateAggregationTest(QueryEvaluationHint hint) { |
320 | var person = new Symbol<>("Person", 1, Boolean.class, false); | 263 | var subQuery = Query.of("SubQuery", Integer.class, (builder, p1, x) -> builder.clause( |
321 | var age = new Symbol<>("age", 1, Integer.class, null); | 264 | personView.call(p1), |
322 | var personView = new KeyOnlyRelationView<>(person); | 265 | ageView.call(p1, x) |
323 | var ageView = new FunctionalRelationView<>(age); | 266 | )); |
324 | 267 | var query = Query.of("Aggregate", Integer.class, (builder, output) -> builder.clause( | |
325 | var p1 = Variable.of("p1"); | 268 | output.assign(subQuery.aggregate(INT_SUM, Variable.of())) |
326 | var x = Variable.of("x", Integer.class); | 269 | )); |
327 | var y = Variable.of("y", Integer.class); | ||
328 | var subQuery = Dnf.builder("SubQuery") | ||
329 | .parameters(p1, x) | ||
330 | .clause( | ||
331 | personView.call(p1), | ||
332 | ageView.call(p1, x) | ||
333 | ) | ||
334 | .build(); | ||
335 | var query = Query.builder("Aggregate") | ||
336 | .output(x) | ||
337 | .clause( | ||
338 | x.assign(subQuery.aggregate(y, INT_SUM, p1, y)) | ||
339 | ) | ||
340 | .build(); | ||
341 | 270 | ||
342 | var store = ModelStore.builder() | 271 | var store = ModelStore.builder() |
343 | .symbols(person, age) | 272 | .symbols(person, age) |
344 | .with(ViatraModelQuery.ADAPTER) | 273 | .with(ViatraModelQueryAdapter.builder() |
345 | .defaultHint(hint) | 274 | .defaultHint(hint) |
346 | .queries(query) | 275 | .queries(query)) |
347 | .build(); | 276 | .build(); |
348 | 277 | ||
349 | var model = store.createEmptyModel(); | 278 | var model = store.createEmptyModel(); |
350 | var personInterpretation = model.getInterpretation(person); | 279 | var personInterpretation = model.getInterpretation(person); |
351 | var ageInterpretation = model.getInterpretation(age); | 280 | var ageInterpretation = model.getInterpretation(age); |
352 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | 281 | var queryEngine = model.getAdapter(ModelQueryAdapter.class); |
353 | var queryResultSet = queryEngine.getResultSet(query); | 282 | var queryResultSet = queryEngine.getResultSet(query); |
354 | 283 | ||
355 | personInterpretation.put(Tuple.of(0), true); | 284 | personInterpretation.put(Tuple.of(0), true); |
@@ -364,46 +293,28 @@ class FunctionalQueryTest { | |||
364 | 293 | ||
365 | @QueryEngineTest | 294 | @QueryEngineTest |
366 | void extremeValueTest(QueryEvaluationHint hint) { | 295 | void extremeValueTest(QueryEvaluationHint hint) { |
367 | var person = new Symbol<>("Person", 1, Boolean.class, false); | 296 | var subQuery = Query.of("SubQuery", Integer.class, (builder, p1, x) -> builder.clause( |
368 | var friend = new Symbol<>("friend", 2, TruthValue.class, TruthValue.FALSE); | 297 | personView.call(p1), |
369 | var personView = new KeyOnlyRelationView<>(person); | 298 | x.assign(friendMustView.count(p1, Variable.of())) |
370 | var friendMustView = new FilteredRelationView<>(friend, "must", TruthValue::must); | 299 | )); |
371 | 300 | var minQuery = Query.of("Min", Integer.class, (builder, output) -> builder.clause( | |
372 | var p1 = Variable.of("p1"); | 301 | output.assign(subQuery.aggregate(INT_MIN, Variable.of())) |
373 | var p2 = Variable.of("p2"); | 302 | )); |
374 | var x = Variable.of("x", Integer.class); | 303 | var maxQuery = Query.of("Max", Integer.class, (builder, output) -> builder.clause( |
375 | var y = Variable.of("y", Integer.class); | 304 | output.assign(subQuery.aggregate(INT_MAX, Variable.of())) |
376 | var subQuery = Dnf.builder("SubQuery") | 305 | )); |
377 | .parameters(p1, x) | ||
378 | .clause( | ||
379 | personView.call(p1), | ||
380 | x.assign(friendMustView.count(p1, p2)) | ||
381 | ) | ||
382 | .build(); | ||
383 | var minQuery = Query.builder("Min") | ||
384 | .output(x) | ||
385 | .clause( | ||
386 | x.assign(subQuery.aggregate(y, INT_MIN, p1, y)) | ||
387 | ) | ||
388 | .build(); | ||
389 | var maxQuery = Query.builder("Max") | ||
390 | .output(x) | ||
391 | .clause( | ||
392 | x.assign(subQuery.aggregate(y, INT_MAX, p1, y)) | ||
393 | ) | ||
394 | .build(); | ||
395 | 306 | ||
396 | var store = ModelStore.builder() | 307 | var store = ModelStore.builder() |
397 | .symbols(person, friend) | 308 | .symbols(person, friend) |
398 | .with(ViatraModelQuery.ADAPTER) | 309 | .with(ViatraModelQueryAdapter.builder() |
399 | .defaultHint(hint) | 310 | .defaultHint(hint) |
400 | .queries(minQuery, maxQuery) | 311 | .queries(minQuery, maxQuery)) |
401 | .build(); | 312 | .build(); |
402 | 313 | ||
403 | var model = store.createEmptyModel(); | 314 | var model = store.createEmptyModel(); |
404 | var personInterpretation = model.getInterpretation(person); | 315 | var personInterpretation = model.getInterpretation(person); |
405 | var friendInterpretation = model.getInterpretation(friend); | 316 | var friendInterpretation = model.getInterpretation(friend); |
406 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | 317 | var queryEngine = model.getAdapter(ModelQueryAdapter.class); |
407 | var minResultSet = queryEngine.getResultSet(minQuery); | 318 | var minResultSet = queryEngine.getResultSet(minQuery); |
408 | var maxResultSet = queryEngine.getResultSet(maxQuery); | 319 | var maxResultSet = queryEngine.getResultSet(maxQuery); |
409 | 320 | ||
@@ -440,35 +351,24 @@ class FunctionalQueryTest { | |||
440 | 351 | ||
441 | @QueryEngineTest | 352 | @QueryEngineTest |
442 | void invalidComputationTest(QueryEvaluationHint hint) { | 353 | void invalidComputationTest(QueryEvaluationHint hint) { |
443 | var person = new Symbol<>("Person", 1, Boolean.class, false); | 354 | var query = Query.of("InvalidComputation", Integer.class, |
444 | var age = new Symbol<>("age", 1, Integer.class, null); | 355 | (builder, p1, output) -> builder.clause(Integer.class, (x) -> List.of( |
445 | var personView = new KeyOnlyRelationView<>(person); | ||
446 | var ageView = new FunctionalRelationView<>(age); | ||
447 | |||
448 | var p1 = Variable.of("p1"); | ||
449 | var x = Variable.of("x", Integer.class); | ||
450 | var y = Variable.of("y", Integer.class); | ||
451 | var query = Query.builder("InvalidComputation") | ||
452 | .parameter(p1) | ||
453 | .output(y) | ||
454 | .clause( | ||
455 | personView.call(p1), | 356 | personView.call(p1), |
456 | ageView.call(p1, x), | 357 | ageView.call(p1, x), |
457 | y.assign(div(constant(120), x)) | 358 | output.assign(div(constant(120), x)) |
458 | ) | 359 | ))); |
459 | .build(); | ||
460 | 360 | ||
461 | var store = ModelStore.builder() | 361 | var store = ModelStore.builder() |
462 | .symbols(person, age) | 362 | .symbols(person, age) |
463 | .with(ViatraModelQuery.ADAPTER) | 363 | .with(ViatraModelQueryAdapter.builder() |
464 | .defaultHint(hint) | 364 | .defaultHint(hint) |
465 | .queries(query) | 365 | .queries(query)) |
466 | .build(); | 366 | .build(); |
467 | 367 | ||
468 | var model = store.createEmptyModel(); | 368 | var model = store.createEmptyModel(); |
469 | var personInterpretation = model.getInterpretation(person); | 369 | var personInterpretation = model.getInterpretation(person); |
470 | var ageInterpretation = model.getInterpretation(age); | 370 | var ageInterpretation = model.getInterpretation(age); |
471 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | 371 | var queryEngine = model.getAdapter(ModelQueryAdapter.class); |
472 | var queryResultSet = queryEngine.getResultSet(query); | 372 | var queryResultSet = queryEngine.getResultSet(query); |
473 | 373 | ||
474 | personInterpretation.put(Tuple.of(0), true); | 374 | personInterpretation.put(Tuple.of(0), true); |
@@ -487,33 +387,23 @@ class FunctionalQueryTest { | |||
487 | 387 | ||
488 | @QueryEngineTest | 388 | @QueryEngineTest |
489 | void invalidAssumeTest(QueryEvaluationHint hint) { | 389 | void invalidAssumeTest(QueryEvaluationHint hint) { |
490 | var person = new Symbol<>("Person", 1, Boolean.class, false); | 390 | var query = Query.of("InvalidAssume", (builder, p1) -> builder.clause(Integer.class, (x) -> List.of( |
491 | var age = new Symbol<>("age", 1, Integer.class, null); | 391 | personView.call(p1), |
492 | var personView = new KeyOnlyRelationView<>(person); | 392 | ageView.call(p1, x), |
493 | var ageView = new FunctionalRelationView<>(age); | 393 | assume(lessEq(div(constant(120), x), constant(5))) |
494 | 394 | ))); | |
495 | var p1 = Variable.of("p1"); | ||
496 | var x = Variable.of("x", Integer.class); | ||
497 | var query = Query.builder("InvalidComputation") | ||
498 | .parameter(p1) | ||
499 | .clause( | ||
500 | personView.call(p1), | ||
501 | ageView.call(p1, x), | ||
502 | assume(lessEq(div(constant(120), x), constant(5))) | ||
503 | ) | ||
504 | .build(); | ||
505 | 395 | ||
506 | var store = ModelStore.builder() | 396 | var store = ModelStore.builder() |
507 | .symbols(person, age) | 397 | .symbols(person, age) |
508 | .with(ViatraModelQuery.ADAPTER) | 398 | .with(ViatraModelQueryAdapter.builder() |
509 | .defaultHint(hint) | 399 | .defaultHint(hint) |
510 | .queries(query) | 400 | .queries(query)) |
511 | .build(); | 401 | .build(); |
512 | 402 | ||
513 | var model = store.createEmptyModel(); | 403 | var model = store.createEmptyModel(); |
514 | var personInterpretation = model.getInterpretation(person); | 404 | var personInterpretation = model.getInterpretation(person); |
515 | var ageInterpretation = model.getInterpretation(age); | 405 | var ageInterpretation = model.getInterpretation(age); |
516 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | 406 | var queryEngine = model.getAdapter(ModelQueryAdapter.class); |
517 | var queryResultSet = queryEngine.getResultSet(query); | 407 | var queryResultSet = queryEngine.getResultSet(query); |
518 | 408 | ||
519 | personInterpretation.put(Tuple.of(0), true); | 409 | personInterpretation.put(Tuple.of(0), true); |
@@ -535,38 +425,24 @@ class FunctionalQueryTest { | |||
535 | 425 | ||
536 | @QueryEngineTest | 426 | @QueryEngineTest |
537 | void notFunctionalTest(QueryEvaluationHint hint) { | 427 | void notFunctionalTest(QueryEvaluationHint hint) { |
538 | var person = new Symbol<>("Person", 1, Boolean.class, false); | 428 | var query = Query.of("NotFunctional", Integer.class, (builder, p1, output) -> builder.clause((p2) -> List.of( |
539 | var age = new Symbol<>("age", 1, Integer.class, null); | 429 | personView.call(p1), |
540 | var friend = new Symbol<>("friend", 2, TruthValue.class, TruthValue.FALSE); | 430 | friendMustView.call(p1, p2), |
541 | var personView = new KeyOnlyRelationView<>(person); | 431 | ageView.call(p2, output) |
542 | var ageView = new FunctionalRelationView<>(age); | 432 | ))); |
543 | var friendMustView = new FilteredRelationView<>(friend, "must", TruthValue::must); | ||
544 | |||
545 | var p1 = Variable.of("p1"); | ||
546 | var p2 = Variable.of("p2"); | ||
547 | var x = Variable.of("x", Integer.class); | ||
548 | var query = Query.builder("NotFunctional") | ||
549 | .parameter(p1) | ||
550 | .output(x) | ||
551 | .clause( | ||
552 | personView.call(p1), | ||
553 | friendMustView.call(p1, p2), | ||
554 | ageView.call(p2, x) | ||
555 | ) | ||
556 | .build(); | ||
557 | 433 | ||
558 | var store = ModelStore.builder() | 434 | var store = ModelStore.builder() |
559 | .symbols(person, age, friend) | 435 | .symbols(person, age, friend) |
560 | .with(ViatraModelQuery.ADAPTER) | 436 | .with(ViatraModelQueryAdapter.builder() |
561 | .defaultHint(hint) | 437 | .defaultHint(hint) |
562 | .query(query) | 438 | .queries(query)) |
563 | .build(); | 439 | .build(); |
564 | 440 | ||
565 | var model = store.createEmptyModel(); | 441 | var model = store.createEmptyModel(); |
566 | var personInterpretation = model.getInterpretation(person); | 442 | var personInterpretation = model.getInterpretation(person); |
567 | var ageInterpretation = model.getInterpretation(age); | 443 | var ageInterpretation = model.getInterpretation(age); |
568 | var friendInterpretation = model.getInterpretation(friend); | 444 | var friendInterpretation = model.getInterpretation(friend); |
569 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | 445 | var queryEngine = model.getAdapter(ModelQueryAdapter.class); |
570 | var queryResultSet = queryEngine.getResultSet(query); | 446 | var queryResultSet = queryEngine.getResultSet(query); |
571 | 447 | ||
572 | personInterpretation.put(Tuple.of(0), true); | 448 | personInterpretation.put(Tuple.of(0), true); |
diff --git a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/QueryTest.java b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/QueryTest.java index 8a3f9d88..297cdf04 100644 --- a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/QueryTest.java +++ b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/QueryTest.java | |||
@@ -1,23 +1,28 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.viatra; | 6 | package tools.refinery.store.query.viatra; |
2 | 7 | ||
3 | import org.eclipse.viatra.query.runtime.matchers.backend.QueryEvaluationHint; | 8 | import org.eclipse.viatra.query.runtime.matchers.backend.QueryEvaluationHint; |
4 | import org.junit.jupiter.api.Test; | 9 | import org.junit.jupiter.api.Test; |
5 | import tools.refinery.store.model.ModelStore; | 10 | import tools.refinery.store.model.ModelStore; |
6 | import tools.refinery.store.query.ModelQuery; | 11 | import tools.refinery.store.query.ModelQueryAdapter; |
7 | import tools.refinery.store.query.dnf.Dnf; | ||
8 | import tools.refinery.store.query.dnf.Query; | 12 | import tools.refinery.store.query.dnf.Query; |
9 | import tools.refinery.store.query.term.Variable; | 13 | import tools.refinery.store.query.term.Variable; |
10 | import tools.refinery.store.query.viatra.tests.QueryEngineTest; | 14 | import tools.refinery.store.query.viatra.tests.QueryEngineTest; |
11 | import tools.refinery.store.query.view.FilteredRelationView; | 15 | import tools.refinery.store.query.view.AnySymbolView; |
12 | import tools.refinery.store.query.view.FunctionalRelationView; | 16 | import tools.refinery.store.query.view.FilteredView; |
13 | import tools.refinery.store.query.view.KeyOnlyRelationView; | 17 | import tools.refinery.store.query.view.FunctionView; |
18 | import tools.refinery.store.query.view.KeyOnlyView; | ||
14 | import tools.refinery.store.representation.Symbol; | 19 | import tools.refinery.store.representation.Symbol; |
15 | import tools.refinery.store.representation.TruthValue; | 20 | import tools.refinery.store.representation.TruthValue; |
16 | import tools.refinery.store.tuple.Tuple; | 21 | import tools.refinery.store.tuple.Tuple; |
17 | 22 | ||
23 | import java.util.List; | ||
18 | import java.util.Map; | 24 | import java.util.Map; |
19 | 25 | ||
20 | import static org.junit.jupiter.api.Assertions.assertThrows; | ||
21 | import static tools.refinery.store.query.literal.Literals.assume; | 26 | import static tools.refinery.store.query.literal.Literals.assume; |
22 | import static tools.refinery.store.query.literal.Literals.not; | 27 | import static tools.refinery.store.query.literal.Literals.not; |
23 | import static tools.refinery.store.query.term.int_.IntTerms.constant; | 28 | import static tools.refinery.store.query.term.int_.IntTerms.constant; |
@@ -25,29 +30,28 @@ import static tools.refinery.store.query.term.int_.IntTerms.greaterEq; | |||
25 | import static tools.refinery.store.query.viatra.tests.QueryAssertions.assertResults; | 30 | import static tools.refinery.store.query.viatra.tests.QueryAssertions.assertResults; |
26 | 31 | ||
27 | class QueryTest { | 32 | class QueryTest { |
33 | private static final Symbol<Boolean> person = Symbol.of("Person", 1); | ||
34 | private static final Symbol<TruthValue> friend = Symbol.of("friend", 2, TruthValue.class, TruthValue.FALSE); | ||
35 | private static final AnySymbolView personView = new KeyOnlyView<>(person); | ||
36 | private static final AnySymbolView friendMustView = new FilteredView<>(friend, "must", TruthValue::must); | ||
37 | |||
28 | @QueryEngineTest | 38 | @QueryEngineTest |
29 | void typeConstraintTest(QueryEvaluationHint hint) { | 39 | void typeConstraintTest(QueryEvaluationHint hint) { |
30 | var person = new Symbol<>("Person", 1, Boolean.class, false); | 40 | var asset = Symbol.of("Asset", 1); |
31 | var asset = new Symbol<>("Asset", 1, Boolean.class, false); | 41 | |
32 | var personView = new KeyOnlyRelationView<>(person); | 42 | var predicate = Query.of("TypeConstraint", (builder, p1) -> builder.clause(personView.call(p1))); |
33 | |||
34 | var p1 = Variable.of("p1"); | ||
35 | var predicate = Query.builder("TypeConstraint") | ||
36 | .parameters(p1) | ||
37 | .clause(personView.call(p1)) | ||
38 | .build(); | ||
39 | 43 | ||
40 | var store = ModelStore.builder() | 44 | var store = ModelStore.builder() |
41 | .symbols(person, asset) | 45 | .symbols(person, asset) |
42 | .with(ViatraModelQuery.ADAPTER) | 46 | .with(ViatraModelQueryAdapter.builder() |
43 | .defaultHint(hint) | 47 | .defaultHint(hint) |
44 | .query(predicate) | 48 | .queries(predicate)) |
45 | .build(); | 49 | .build(); |
46 | 50 | ||
47 | var model = store.createEmptyModel(); | 51 | var model = store.createEmptyModel(); |
48 | var personInterpretation = model.getInterpretation(person); | 52 | var personInterpretation = model.getInterpretation(person); |
49 | var assetInterpretation = model.getInterpretation(asset); | 53 | var assetInterpretation = model.getInterpretation(asset); |
50 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | 54 | var queryEngine = model.getAdapter(ModelQueryAdapter.class); |
51 | var predicateResultSet = queryEngine.getResultSet(predicate); | 55 | var predicateResultSet = queryEngine.getResultSet(predicate); |
52 | 56 | ||
53 | personInterpretation.put(Tuple.of(0), true); | 57 | personInterpretation.put(Tuple.of(0), true); |
@@ -66,33 +70,23 @@ class QueryTest { | |||
66 | 70 | ||
67 | @QueryEngineTest | 71 | @QueryEngineTest |
68 | void relationConstraintTest(QueryEvaluationHint hint) { | 72 | void relationConstraintTest(QueryEvaluationHint hint) { |
69 | var person = new Symbol<>("Person", 1, Boolean.class, false); | 73 | var predicate = Query.of("RelationConstraint", (builder, p1, p2) -> builder.clause( |
70 | var friend = new Symbol<>("friend", 2, TruthValue.class, TruthValue.FALSE); | 74 | personView.call(p1), |
71 | var personView = new KeyOnlyRelationView<>(person); | 75 | personView.call(p2), |
72 | var friendMustView = new FilteredRelationView<>(friend, "must", TruthValue::must); | 76 | friendMustView.call(p1, p2) |
73 | 77 | )); | |
74 | var p1 = Variable.of("p1"); | ||
75 | var p2 = Variable.of("p2"); | ||
76 | var predicate = Query.builder("RelationConstraint") | ||
77 | .parameters(p1, p2) | ||
78 | .clause( | ||
79 | personView.call(p1), | ||
80 | personView.call(p2), | ||
81 | friendMustView.call(p1, p2) | ||
82 | ) | ||
83 | .build(); | ||
84 | 78 | ||
85 | var store = ModelStore.builder() | 79 | var store = ModelStore.builder() |
86 | .symbols(person, friend) | 80 | .symbols(person, friend) |
87 | .with(ViatraModelQuery.ADAPTER) | 81 | .with(ViatraModelQueryAdapter.builder() |
88 | .defaultHint(hint) | 82 | .defaultHint(hint) |
89 | .queries(predicate) | 83 | .queries(predicate)) |
90 | .build(); | 84 | .build(); |
91 | 85 | ||
92 | var model = store.createEmptyModel(); | 86 | var model = store.createEmptyModel(); |
93 | var personInterpretation = model.getInterpretation(person); | 87 | var personInterpretation = model.getInterpretation(person); |
94 | var friendInterpretation = model.getInterpretation(friend); | 88 | var friendInterpretation = model.getInterpretation(friend); |
95 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | 89 | var queryEngine = model.getAdapter(ModelQueryAdapter.class); |
96 | var predicateResultSet = queryEngine.getResultSet(predicate); | 90 | var predicateResultSet = queryEngine.getResultSet(predicate); |
97 | 91 | ||
98 | personInterpretation.put(Tuple.of(0), true); | 92 | personInterpretation.put(Tuple.of(0), true); |
@@ -115,33 +109,23 @@ class QueryTest { | |||
115 | 109 | ||
116 | @QueryEngineTest | 110 | @QueryEngineTest |
117 | void existTest(QueryEvaluationHint hint) { | 111 | void existTest(QueryEvaluationHint hint) { |
118 | var person = new Symbol<>("Person", 1, Boolean.class, false); | 112 | var predicate = Query.of("Exists", (builder, p1) -> builder.clause((p2) -> List.of( |
119 | var friend = new Symbol<>("friend", 2, TruthValue.class, TruthValue.FALSE); | 113 | personView.call(p1), |
120 | var personView = new KeyOnlyRelationView<>(person); | 114 | personView.call(p2), |
121 | var friendMustView = new FilteredRelationView<>(friend, "must", TruthValue::must); | 115 | friendMustView.call(p1, p2) |
122 | 116 | ))); | |
123 | var p1 = Variable.of("p1"); | ||
124 | var p2 = Variable.of("p2"); | ||
125 | var predicate = Query.builder("RelationConstraint") | ||
126 | .parameters(p1) | ||
127 | .clause( | ||
128 | personView.call(p1), | ||
129 | personView.call(p2), | ||
130 | friendMustView.call(p1, p2) | ||
131 | ) | ||
132 | .build(); | ||
133 | 117 | ||
134 | var store = ModelStore.builder() | 118 | var store = ModelStore.builder() |
135 | .symbols(person, friend) | 119 | .symbols(person, friend) |
136 | .with(ViatraModelQuery.ADAPTER) | 120 | .with(ViatraModelQueryAdapter.builder() |
137 | .defaultHint(hint) | 121 | .defaultHint(hint) |
138 | .queries(predicate) | 122 | .queries(predicate)) |
139 | .build(); | 123 | .build(); |
140 | 124 | ||
141 | var model = store.createEmptyModel(); | 125 | var model = store.createEmptyModel(); |
142 | var personInterpretation = model.getInterpretation(person); | 126 | var personInterpretation = model.getInterpretation(person); |
143 | var friendInterpretation = model.getInterpretation(friend); | 127 | var friendInterpretation = model.getInterpretation(friend); |
144 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | 128 | var queryEngine = model.getAdapter(ModelQueryAdapter.class); |
145 | var predicateResultSet = queryEngine.getResultSet(predicate); | 129 | var predicateResultSet = queryEngine.getResultSet(predicate); |
146 | 130 | ||
147 | personInterpretation.put(Tuple.of(0), true); | 131 | personInterpretation.put(Tuple.of(0), true); |
@@ -164,41 +148,31 @@ class QueryTest { | |||
164 | 148 | ||
165 | @QueryEngineTest | 149 | @QueryEngineTest |
166 | void orTest(QueryEvaluationHint hint) { | 150 | void orTest(QueryEvaluationHint hint) { |
167 | var person = new Symbol<>("Person", 1, Boolean.class, false); | 151 | var animal = Symbol.of("Animal", 1); |
168 | var animal = new Symbol<>("Animal", 1, Boolean.class, false); | 152 | var animalView = new KeyOnlyView<>(animal); |
169 | var friend = new Symbol<>("friend", 2, TruthValue.class, TruthValue.FALSE); | 153 | |
170 | var personView = new KeyOnlyRelationView<>(person); | 154 | var predicate = Query.of("Or", (builder, p1, p2) -> builder.clause( |
171 | var animalView = new KeyOnlyRelationView<>(animal); | 155 | personView.call(p1), |
172 | var friendMustView = new FilteredRelationView<>(friend, "must", TruthValue::must); | 156 | personView.call(p2), |
173 | 157 | friendMustView.call(p1, p2) | |
174 | var p1 = Variable.of("p1"); | 158 | ).clause( |
175 | var p2 = Variable.of("p2"); | 159 | animalView.call(p1), |
176 | var predicate = Query.builder("Or") | 160 | animalView.call(p2), |
177 | .parameters(p1, p2) | 161 | friendMustView.call(p1, p2) |
178 | .clause( | 162 | )); |
179 | personView.call(p1), | ||
180 | personView.call(p2), | ||
181 | friendMustView.call(p1, p2) | ||
182 | ) | ||
183 | .clause( | ||
184 | animalView.call(p1), | ||
185 | animalView.call(p2), | ||
186 | friendMustView.call(p1, p2) | ||
187 | ) | ||
188 | .build(); | ||
189 | 163 | ||
190 | var store = ModelStore.builder() | 164 | var store = ModelStore.builder() |
191 | .symbols(person, animal, friend) | 165 | .symbols(person, animal, friend) |
192 | .with(ViatraModelQuery.ADAPTER) | 166 | .with(ViatraModelQueryAdapter.builder() |
193 | .defaultHint(hint) | 167 | .defaultHint(hint) |
194 | .queries(predicate) | 168 | .queries(predicate)) |
195 | .build(); | 169 | .build(); |
196 | 170 | ||
197 | var model = store.createEmptyModel(); | 171 | var model = store.createEmptyModel(); |
198 | var personInterpretation = model.getInterpretation(person); | 172 | var personInterpretation = model.getInterpretation(person); |
199 | var animalInterpretation = model.getInterpretation(animal); | 173 | var animalInterpretation = model.getInterpretation(animal); |
200 | var friendInterpretation = model.getInterpretation(friend); | 174 | var friendInterpretation = model.getInterpretation(friend); |
201 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | 175 | var queryEngine = model.getAdapter(ModelQueryAdapter.class); |
202 | var predicateResultSet = queryEngine.getResultSet(predicate); | 176 | var predicateResultSet = queryEngine.getResultSet(predicate); |
203 | 177 | ||
204 | personInterpretation.put(Tuple.of(0), true); | 178 | personInterpretation.put(Tuple.of(0), true); |
@@ -224,30 +198,22 @@ class QueryTest { | |||
224 | 198 | ||
225 | @QueryEngineTest | 199 | @QueryEngineTest |
226 | void equalityTest(QueryEvaluationHint hint) { | 200 | void equalityTest(QueryEvaluationHint hint) { |
227 | var person = new Symbol<>("Person", 1, Boolean.class, false); | 201 | var predicate = Query.of("Equality", (builder, p1, p2) -> builder.clause( |
228 | var personView = new KeyOnlyRelationView<>(person); | 202 | personView.call(p1), |
229 | 203 | personView.call(p2), | |
230 | var p1 = Variable.of("p1"); | 204 | p1.isEquivalent(p2) |
231 | var p2 = Variable.of("p2"); | 205 | )); |
232 | var predicate = Query.builder("Equality") | ||
233 | .parameters(p1, p2) | ||
234 | .clause( | ||
235 | personView.call(p1), | ||
236 | personView.call(p2), | ||
237 | p1.isEquivalent(p2) | ||
238 | ) | ||
239 | .build(); | ||
240 | 206 | ||
241 | var store = ModelStore.builder() | 207 | var store = ModelStore.builder() |
242 | .symbols(person) | 208 | .symbols(person) |
243 | .with(ViatraModelQuery.ADAPTER) | 209 | .with(ViatraModelQueryAdapter.builder() |
244 | .defaultHint(hint) | 210 | .defaultHint(hint) |
245 | .queries(predicate) | 211 | .queries(predicate)) |
246 | .build(); | 212 | .build(); |
247 | 213 | ||
248 | var model = store.createEmptyModel(); | 214 | var model = store.createEmptyModel(); |
249 | var personInterpretation = model.getInterpretation(person); | 215 | var personInterpretation = model.getInterpretation(person); |
250 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | 216 | var queryEngine = model.getAdapter(ModelQueryAdapter.class); |
251 | var predicateResultSet = queryEngine.getResultSet(predicate); | 217 | var predicateResultSet = queryEngine.getResultSet(predicate); |
252 | 218 | ||
253 | personInterpretation.put(Tuple.of(0), true); | 219 | personInterpretation.put(Tuple.of(0), true); |
@@ -266,36 +232,25 @@ class QueryTest { | |||
266 | 232 | ||
267 | @QueryEngineTest | 233 | @QueryEngineTest |
268 | void inequalityTest(QueryEvaluationHint hint) { | 234 | void inequalityTest(QueryEvaluationHint hint) { |
269 | var person = new Symbol<>("Person", 1, Boolean.class, false); | 235 | var predicate = Query.of("Inequality", (builder, p1, p2, p3) -> builder.clause( |
270 | var friend = new Symbol<>("friend", 2, TruthValue.class, TruthValue.FALSE); | 236 | personView.call(p1), |
271 | var personView = new KeyOnlyRelationView<>(person); | 237 | personView.call(p2), |
272 | var friendMustView = new FilteredRelationView<>(friend, "must", TruthValue::must); | 238 | friendMustView.call(p1, p3), |
273 | 239 | friendMustView.call(p2, p3), | |
274 | var p1 = Variable.of("p1"); | 240 | p1.notEquivalent(p2) |
275 | var p2 = Variable.of("p2"); | 241 | )); |
276 | var p3 = Variable.of("p3"); | ||
277 | var predicate = Query.builder("Inequality") | ||
278 | .parameters(p1, p2, p3) | ||
279 | .clause( | ||
280 | personView.call(p1), | ||
281 | personView.call(p2), | ||
282 | friendMustView.call(p1, p3), | ||
283 | friendMustView.call(p2, p3), | ||
284 | p1.notEquivalent(p2) | ||
285 | ) | ||
286 | .build(); | ||
287 | 242 | ||
288 | var store = ModelStore.builder() | 243 | var store = ModelStore.builder() |
289 | .symbols(person, friend) | 244 | .symbols(person, friend) |
290 | .with(ViatraModelQuery.ADAPTER) | 245 | .with(ViatraModelQueryAdapter.builder() |
291 | .defaultHint(hint) | 246 | .defaultHint(hint) |
292 | .queries(predicate) | 247 | .queries(predicate)) |
293 | .build(); | 248 | .build(); |
294 | 249 | ||
295 | var model = store.createEmptyModel(); | 250 | var model = store.createEmptyModel(); |
296 | var personInterpretation = model.getInterpretation(person); | 251 | var personInterpretation = model.getInterpretation(person); |
297 | var friendInterpretation = model.getInterpretation(friend); | 252 | var friendInterpretation = model.getInterpretation(friend); |
298 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | 253 | var queryEngine = model.getAdapter(ModelQueryAdapter.class); |
299 | var predicateResultSet = queryEngine.getResultSet(predicate); | 254 | var predicateResultSet = queryEngine.getResultSet(predicate); |
300 | 255 | ||
301 | personInterpretation.put(Tuple.of(0), true); | 256 | personInterpretation.put(Tuple.of(0), true); |
@@ -315,44 +270,28 @@ class QueryTest { | |||
315 | 270 | ||
316 | @QueryEngineTest | 271 | @QueryEngineTest |
317 | void patternCallTest(QueryEvaluationHint hint) { | 272 | void patternCallTest(QueryEvaluationHint hint) { |
318 | var person = new Symbol<>("Person", 1, Boolean.class, false); | 273 | var friendPredicate = Query.of("Friend", (builder, p1, p2) -> builder.clause( |
319 | var friend = new Symbol<>("friend", 2, TruthValue.class, TruthValue.FALSE); | 274 | personView.call(p1), |
320 | var personView = new KeyOnlyRelationView<>(person); | 275 | personView.call(p2), |
321 | var friendMustView = new FilteredRelationView<>(friend, "must", TruthValue::must); | 276 | friendMustView.call(p1, p2) |
322 | 277 | )); | |
323 | var p1 = Variable.of("p1"); | 278 | var predicate = Query.of("PositivePatternCall", (builder, p3, p4) -> builder.clause( |
324 | var p2 = Variable.of("p2"); | 279 | personView.call(p3), |
325 | var friendPredicate = Dnf.builder("RelationConstraint") | 280 | personView.call(p4), |
326 | .parameters(p1, p2) | 281 | friendPredicate.call(p3, p4) |
327 | .clause( | 282 | )); |
328 | personView.call(p1), | ||
329 | personView.call(p2), | ||
330 | friendMustView.call(p1, p2) | ||
331 | ) | ||
332 | .build(); | ||
333 | |||
334 | var p3 = Variable.of("p3"); | ||
335 | var p4 = Variable.of("p4"); | ||
336 | var predicate = Query.builder("PositivePatternCall") | ||
337 | .parameters(p3, p4) | ||
338 | .clause( | ||
339 | personView.call(p3), | ||
340 | personView.call(p4), | ||
341 | friendPredicate.call(p3, p4) | ||
342 | ) | ||
343 | .build(); | ||
344 | 283 | ||
345 | var store = ModelStore.builder() | 284 | var store = ModelStore.builder() |
346 | .symbols(person, friend) | 285 | .symbols(person, friend) |
347 | .with(ViatraModelQuery.ADAPTER) | 286 | .with(ViatraModelQueryAdapter.builder() |
348 | .defaultHint(hint) | 287 | .defaultHint(hint) |
349 | .queries(predicate) | 288 | .queries(predicate)) |
350 | .build(); | 289 | .build(); |
351 | 290 | ||
352 | var model = store.createEmptyModel(); | 291 | var model = store.createEmptyModel(); |
353 | var personInterpretation = model.getInterpretation(person); | 292 | var personInterpretation = model.getInterpretation(person); |
354 | var friendInterpretation = model.getInterpretation(friend); | 293 | var friendInterpretation = model.getInterpretation(friend); |
355 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | 294 | var queryEngine = model.getAdapter(ModelQueryAdapter.class); |
356 | var predicateResultSet = queryEngine.getResultSet(predicate); | 295 | var predicateResultSet = queryEngine.getResultSet(predicate); |
357 | 296 | ||
358 | personInterpretation.put(Tuple.of(0), true); | 297 | personInterpretation.put(Tuple.of(0), true); |
@@ -374,33 +313,23 @@ class QueryTest { | |||
374 | 313 | ||
375 | @QueryEngineTest | 314 | @QueryEngineTest |
376 | void negativeRelationViewTest(QueryEvaluationHint hint) { | 315 | void negativeRelationViewTest(QueryEvaluationHint hint) { |
377 | var person = new Symbol<>("Person", 1, Boolean.class, false); | 316 | var predicate = Query.of("NegativePatternCall", (builder, p1, p2) -> builder.clause( |
378 | var friend = new Symbol<>("friend", 2, TruthValue.class, TruthValue.FALSE); | 317 | personView.call(p1), |
379 | var personView = new KeyOnlyRelationView<>(person); | 318 | personView.call(p2), |
380 | var friendMustView = new FilteredRelationView<>(friend, "must", TruthValue::must); | 319 | not(friendMustView.call(p1, p2)) |
381 | 320 | )); | |
382 | var p1 = Variable.of("p1"); | ||
383 | var p2 = Variable.of("p2"); | ||
384 | var predicate = Query.builder("NegativePatternCall") | ||
385 | .parameters(p1, p2) | ||
386 | .clause( | ||
387 | personView.call(p1), | ||
388 | personView.call(p2), | ||
389 | not(friendMustView.call(p1, p2)) | ||
390 | ) | ||
391 | .build(); | ||
392 | 321 | ||
393 | var store = ModelStore.builder() | 322 | var store = ModelStore.builder() |
394 | .symbols(person, friend) | 323 | .symbols(person, friend) |
395 | .with(ViatraModelQuery.ADAPTER) | 324 | .with(ViatraModelQueryAdapter.builder() |
396 | .defaultHint(hint) | 325 | .defaultHint(hint) |
397 | .queries(predicate) | 326 | .queries(predicate)) |
398 | .build(); | 327 | .build(); |
399 | 328 | ||
400 | var model = store.createEmptyModel(); | 329 | var model = store.createEmptyModel(); |
401 | var personInterpretation = model.getInterpretation(person); | 330 | var personInterpretation = model.getInterpretation(person); |
402 | var friendInterpretation = model.getInterpretation(friend); | 331 | var friendInterpretation = model.getInterpretation(friend); |
403 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | 332 | var queryEngine = model.getAdapter(ModelQueryAdapter.class); |
404 | var predicateResultSet = queryEngine.getResultSet(predicate); | 333 | var predicateResultSet = queryEngine.getResultSet(predicate); |
405 | 334 | ||
406 | personInterpretation.put(Tuple.of(0), true); | 335 | personInterpretation.put(Tuple.of(0), true); |
@@ -428,44 +357,28 @@ class QueryTest { | |||
428 | 357 | ||
429 | @QueryEngineTest | 358 | @QueryEngineTest |
430 | void negativePatternCallTest(QueryEvaluationHint hint) { | 359 | void negativePatternCallTest(QueryEvaluationHint hint) { |
431 | var person = new Symbol<>("Person", 1, Boolean.class, false); | 360 | var friendPredicate = Query.of("Friend", (builder, p1, p2) -> builder.clause( |
432 | var friend = new Symbol<>("friend", 2, TruthValue.class, TruthValue.FALSE); | 361 | personView.call(p1), |
433 | var personView = new KeyOnlyRelationView<>(person); | 362 | personView.call(p2), |
434 | var friendMustView = new FilteredRelationView<>(friend, "must", TruthValue::must); | 363 | friendMustView.call(p1, p2) |
435 | 364 | )); | |
436 | var p1 = Variable.of("p1"); | 365 | var predicate = Query.of("NegativePatternCall", (builder, p3, p4) -> builder.clause( |
437 | var p2 = Variable.of("p2"); | 366 | personView.call(p3), |
438 | var friendPredicate = Dnf.builder("RelationConstraint") | 367 | personView.call(p4), |
439 | .parameters(p1, p2) | 368 | not(friendPredicate.call(p3, p4)) |
440 | .clause( | 369 | )); |
441 | personView.call(p1), | ||
442 | personView.call(p2), | ||
443 | friendMustView.call(p1, p2) | ||
444 | ) | ||
445 | .build(); | ||
446 | |||
447 | var p3 = Variable.of("p3"); | ||
448 | var p4 = Variable.of("p4"); | ||
449 | var predicate = Query.builder("NegativePatternCall") | ||
450 | .parameters(p3, p4) | ||
451 | .clause( | ||
452 | personView.call(p3), | ||
453 | personView.call(p4), | ||
454 | not(friendPredicate.call(p3, p4)) | ||
455 | ) | ||
456 | .build(); | ||
457 | 370 | ||
458 | var store = ModelStore.builder() | 371 | var store = ModelStore.builder() |
459 | .symbols(person, friend) | 372 | .symbols(person, friend) |
460 | .with(ViatraModelQuery.ADAPTER) | 373 | .with(ViatraModelQueryAdapter.builder() |
461 | .defaultHint(hint) | 374 | .defaultHint(hint) |
462 | .queries(predicate) | 375 | .queries(predicate)) |
463 | .build(); | 376 | .build(); |
464 | 377 | ||
465 | var model = store.createEmptyModel(); | 378 | var model = store.createEmptyModel(); |
466 | var personInterpretation = model.getInterpretation(person); | 379 | var personInterpretation = model.getInterpretation(person); |
467 | var friendInterpretation = model.getInterpretation(friend); | 380 | var friendInterpretation = model.getInterpretation(friend); |
468 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | 381 | var queryEngine = model.getAdapter(ModelQueryAdapter.class); |
469 | var predicateResultSet = queryEngine.getResultSet(predicate); | 382 | var predicateResultSet = queryEngine.getResultSet(predicate); |
470 | 383 | ||
471 | personInterpretation.put(Tuple.of(0), true); | 384 | personInterpretation.put(Tuple.of(0), true); |
@@ -493,33 +406,22 @@ class QueryTest { | |||
493 | 406 | ||
494 | @QueryEngineTest | 407 | @QueryEngineTest |
495 | void negativeRelationViewWithQuantificationTest(QueryEvaluationHint hint) { | 408 | void negativeRelationViewWithQuantificationTest(QueryEvaluationHint hint) { |
496 | var person = new Symbol<>("Person", 1, Boolean.class, false); | 409 | var predicate = Query.of("Negative", (builder, p1) -> builder.clause( |
497 | var friend = new Symbol<>("friend", 2, TruthValue.class, TruthValue.FALSE); | 410 | personView.call(p1), |
498 | var personView = new KeyOnlyRelationView<>(person); | 411 | not(friendMustView.call(p1, Variable.of())) |
499 | var friendMustView = new FilteredRelationView<>(friend, "must", TruthValue::must); | 412 | )); |
500 | |||
501 | var p1 = Variable.of("p1"); | ||
502 | var p2 = Variable.of("p2"); | ||
503 | |||
504 | var predicate = Query.builder("Count") | ||
505 | .parameters(p1) | ||
506 | .clause( | ||
507 | personView.call(p1), | ||
508 | not(friendMustView.call(p1, p2)) | ||
509 | ) | ||
510 | .build(); | ||
511 | 413 | ||
512 | var store = ModelStore.builder() | 414 | var store = ModelStore.builder() |
513 | .symbols(person, friend) | 415 | .symbols(person, friend) |
514 | .with(ViatraModelQuery.ADAPTER) | 416 | .with(ViatraModelQueryAdapter.builder() |
515 | .defaultHint(hint) | 417 | .defaultHint(hint) |
516 | .queries(predicate) | 418 | .queries(predicate)) |
517 | .build(); | 419 | .build(); |
518 | 420 | ||
519 | var model = store.createEmptyModel(); | 421 | var model = store.createEmptyModel(); |
520 | var personInterpretation = model.getInterpretation(person); | 422 | var personInterpretation = model.getInterpretation(person); |
521 | var friendInterpretation = model.getInterpretation(friend); | 423 | var friendInterpretation = model.getInterpretation(friend); |
522 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | 424 | var queryEngine = model.getAdapter(ModelQueryAdapter.class); |
523 | var predicateResultSet = queryEngine.getResultSet(predicate); | 425 | var predicateResultSet = queryEngine.getResultSet(predicate); |
524 | 426 | ||
525 | personInterpretation.put(Tuple.of(0), true); | 427 | personInterpretation.put(Tuple.of(0), true); |
@@ -540,42 +442,27 @@ class QueryTest { | |||
540 | 442 | ||
541 | @QueryEngineTest | 443 | @QueryEngineTest |
542 | void negativeWithQuantificationTest(QueryEvaluationHint hint) { | 444 | void negativeWithQuantificationTest(QueryEvaluationHint hint) { |
543 | var person = new Symbol<>("Person", 1, Boolean.class, false); | 445 | var called = Query.of("Called", (builder, p1, p2) -> builder.clause( |
544 | var friend = new Symbol<>("friend", 2, TruthValue.class, TruthValue.FALSE); | 446 | personView.call(p1), |
545 | var personView = new KeyOnlyRelationView<>(person); | 447 | personView.call(p2), |
546 | var friendMustView = new FilteredRelationView<>(friend, "must", TruthValue::must); | 448 | friendMustView.call(p1, p2) |
547 | 449 | )); | |
548 | var p1 = Variable.of("p1"); | 450 | var predicate = Query.of("Negative", (builder, p1) -> builder.clause( |
549 | var p2 = Variable.of("p2"); | 451 | personView.call(p1), |
550 | 452 | not(called.call(p1, Variable.of())) | |
551 | var called = Dnf.builder("Called") | 453 | )); |
552 | .parameters(p1, p2) | ||
553 | .clause( | ||
554 | personView.call(p1), | ||
555 | personView.call(p2), | ||
556 | friendMustView.call(p1, p2) | ||
557 | ) | ||
558 | .build(); | ||
559 | |||
560 | var predicate = Query.builder("Count") | ||
561 | .parameters(p1) | ||
562 | .clause( | ||
563 | personView.call(p1), | ||
564 | not(called.call(p1, p2)) | ||
565 | ) | ||
566 | .build(); | ||
567 | 454 | ||
568 | var store = ModelStore.builder() | 455 | var store = ModelStore.builder() |
569 | .symbols(person, friend) | 456 | .symbols(person, friend) |
570 | .with(ViatraModelQuery.ADAPTER) | 457 | .with(ViatraModelQueryAdapter.builder() |
571 | .defaultHint(hint) | 458 | .defaultHint(hint) |
572 | .queries(predicate) | 459 | .queries(predicate)) |
573 | .build(); | 460 | .build(); |
574 | 461 | ||
575 | var model = store.createEmptyModel(); | 462 | var model = store.createEmptyModel(); |
576 | var personInterpretation = model.getInterpretation(person); | 463 | var personInterpretation = model.getInterpretation(person); |
577 | var friendInterpretation = model.getInterpretation(friend); | 464 | var friendInterpretation = model.getInterpretation(friend); |
578 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | 465 | var queryEngine = model.getAdapter(ModelQueryAdapter.class); |
579 | var predicateResultSet = queryEngine.getResultSet(predicate); | 466 | var predicateResultSet = queryEngine.getResultSet(predicate); |
580 | 467 | ||
581 | personInterpretation.put(Tuple.of(0), true); | 468 | personInterpretation.put(Tuple.of(0), true); |
@@ -596,33 +483,23 @@ class QueryTest { | |||
596 | 483 | ||
597 | @QueryEngineTest | 484 | @QueryEngineTest |
598 | void transitiveRelationViewTest(QueryEvaluationHint hint) { | 485 | void transitiveRelationViewTest(QueryEvaluationHint hint) { |
599 | var person = new Symbol<>("Person", 1, Boolean.class, false); | 486 | var predicate = Query.of("Transitive", (builder, p1, p2) -> builder.clause( |
600 | var friend = new Symbol<>("friend", 2, TruthValue.class, TruthValue.FALSE); | 487 | personView.call(p1), |
601 | var personView = new KeyOnlyRelationView<>(person); | 488 | personView.call(p2), |
602 | var friendMustView = new FilteredRelationView<>(friend, "must", TruthValue::must); | 489 | friendMustView.callTransitive(p1, p2) |
603 | 490 | )); | |
604 | var p1 = Variable.of("p1"); | ||
605 | var p2 = Variable.of("p2"); | ||
606 | var predicate = Query.builder("TransitivePatternCall") | ||
607 | .parameters(p1, p2) | ||
608 | .clause( | ||
609 | personView.call(p1), | ||
610 | personView.call(p2), | ||
611 | friendMustView.callTransitive(p1, p2) | ||
612 | ) | ||
613 | .build(); | ||
614 | 491 | ||
615 | var store = ModelStore.builder() | 492 | var store = ModelStore.builder() |
616 | .symbols(person, friend) | 493 | .symbols(person, friend) |
617 | .with(ViatraModelQuery.ADAPTER) | 494 | .with(ViatraModelQueryAdapter.builder() |
618 | .defaultHint(hint) | 495 | .defaultHint(hint) |
619 | .queries(predicate) | 496 | .queries(predicate)) |
620 | .build(); | 497 | .build(); |
621 | 498 | ||
622 | var model = store.createEmptyModel(); | 499 | var model = store.createEmptyModel(); |
623 | var personInterpretation = model.getInterpretation(person); | 500 | var personInterpretation = model.getInterpretation(person); |
624 | var friendInterpretation = model.getInterpretation(friend); | 501 | var friendInterpretation = model.getInterpretation(friend); |
625 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | 502 | var queryEngine = model.getAdapter(ModelQueryAdapter.class); |
626 | var predicateResultSet = queryEngine.getResultSet(predicate); | 503 | var predicateResultSet = queryEngine.getResultSet(predicate); |
627 | 504 | ||
628 | personInterpretation.put(Tuple.of(0), true); | 505 | personInterpretation.put(Tuple.of(0), true); |
@@ -649,44 +526,28 @@ class QueryTest { | |||
649 | 526 | ||
650 | @QueryEngineTest | 527 | @QueryEngineTest |
651 | void transitivePatternCallTest(QueryEvaluationHint hint) { | 528 | void transitivePatternCallTest(QueryEvaluationHint hint) { |
652 | var person = new Symbol<>("Person", 1, Boolean.class, false); | 529 | var called = Query.of("Called", (builder, p1, p2) -> builder.clause( |
653 | var friend = new Symbol<>("friend", 2, TruthValue.class, TruthValue.FALSE); | 530 | personView.call(p1), |
654 | var personView = new KeyOnlyRelationView<>(person); | 531 | personView.call(p2), |
655 | var friendMustView = new FilteredRelationView<>(friend, "must", TruthValue::must); | 532 | friendMustView.call(p1, p2) |
656 | 533 | )); | |
657 | var p1 = Variable.of("p1"); | 534 | var predicate = Query.of("Transitive", (builder, p1, p2) -> builder.clause( |
658 | var p2 = Variable.of("p2"); | 535 | personView.call(p1), |
659 | var friendPredicate = Dnf.builder("RelationConstraint") | 536 | personView.call(p2), |
660 | .parameters(p1, p2) | 537 | called.callTransitive(p1, p2) |
661 | .clause( | 538 | )); |
662 | personView.call(p1), | ||
663 | personView.call(p2), | ||
664 | friendMustView.call(p1, p2) | ||
665 | ) | ||
666 | .build(); | ||
667 | |||
668 | var p3 = Variable.of("p3"); | ||
669 | var p4 = Variable.of("p4"); | ||
670 | var predicate = Query.builder("TransitivePatternCall") | ||
671 | .parameters(p3, p4) | ||
672 | .clause( | ||
673 | personView.call(p3), | ||
674 | personView.call(p4), | ||
675 | friendPredicate.callTransitive(p3, p4) | ||
676 | ) | ||
677 | .build(); | ||
678 | 539 | ||
679 | var store = ModelStore.builder() | 540 | var store = ModelStore.builder() |
680 | .symbols(person, friend) | 541 | .symbols(person, friend) |
681 | .with(ViatraModelQuery.ADAPTER) | 542 | .with(ViatraModelQueryAdapter.builder() |
682 | .defaultHint(hint) | 543 | .defaultHint(hint) |
683 | .queries(predicate) | 544 | .queries(predicate)) |
684 | .build(); | 545 | .build(); |
685 | 546 | ||
686 | var model = store.createEmptyModel(); | 547 | var model = store.createEmptyModel(); |
687 | var personInterpretation = model.getInterpretation(person); | 548 | var personInterpretation = model.getInterpretation(person); |
688 | var friendInterpretation = model.getInterpretation(friend); | 549 | var friendInterpretation = model.getInterpretation(friend); |
689 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | 550 | var queryEngine = model.getAdapter(ModelQueryAdapter.class); |
690 | var predicateResultSet = queryEngine.getResultSet(predicate); | 551 | var predicateResultSet = queryEngine.getResultSet(predicate); |
691 | 552 | ||
692 | personInterpretation.put(Tuple.of(0), true); | 553 | personInterpretation.put(Tuple.of(0), true); |
@@ -713,33 +574,26 @@ class QueryTest { | |||
713 | 574 | ||
714 | @QueryEngineTest | 575 | @QueryEngineTest |
715 | void assumeTest(QueryEvaluationHint hint) { | 576 | void assumeTest(QueryEvaluationHint hint) { |
716 | var person = new Symbol<>("Person", 1, Boolean.class, false); | 577 | var age = Symbol.of("age", 1, Integer.class); |
717 | var age = new Symbol<>("age", 1, Integer.class, null); | 578 | var ageView = new FunctionView<>(age); |
718 | var personView = new KeyOnlyRelationView<>(person); | 579 | |
719 | var ageView = new FunctionalRelationView<>(age); | 580 | var query = Query.of("Constraint", (builder, p1) -> builder.clause(Integer.class, (x) -> List.of( |
720 | 581 | personView.call(p1), | |
721 | var p1 = Variable.of("p1"); | 582 | ageView.call(p1, x), |
722 | var x = Variable.of("x", Integer.class); | 583 | assume(greaterEq(x, constant(18))) |
723 | var query = Query.builder("Constraint") | 584 | ))); |
724 | .parameter(p1) | ||
725 | .clause( | ||
726 | personView.call(p1), | ||
727 | ageView.call(p1, x), | ||
728 | assume(greaterEq(x, constant(18))) | ||
729 | ) | ||
730 | .build(); | ||
731 | 585 | ||
732 | var store = ModelStore.builder() | 586 | var store = ModelStore.builder() |
733 | .symbols(person, age) | 587 | .symbols(person, age) |
734 | .with(ViatraModelQuery.ADAPTER) | 588 | .with(ViatraModelQueryAdapter.builder() |
735 | .defaultHint(hint) | 589 | .defaultHint(hint) |
736 | .queries(query) | 590 | .queries(query)) |
737 | .build(); | 591 | .build(); |
738 | 592 | ||
739 | var model = store.createEmptyModel(); | 593 | var model = store.createEmptyModel(); |
740 | var personInterpretation = model.getInterpretation(person); | 594 | var personInterpretation = model.getInterpretation(person); |
741 | var ageInterpretation = model.getInterpretation(age); | 595 | var ageInterpretation = model.getInterpretation(age); |
742 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | 596 | var queryEngine = model.getAdapter(ModelQueryAdapter.class); |
743 | var queryResultSet = queryEngine.getResultSet(query); | 597 | var queryResultSet = queryEngine.getResultSet(query); |
744 | 598 | ||
745 | personInterpretation.put(Tuple.of(0), true); | 599 | personInterpretation.put(Tuple.of(0), true); |
@@ -758,20 +612,17 @@ class QueryTest { | |||
758 | 612 | ||
759 | @Test | 613 | @Test |
760 | void alwaysFalseTest() { | 614 | void alwaysFalseTest() { |
761 | var person = new Symbol<>("Person", 1, Boolean.class, false); | 615 | var predicate = Query.of("AlwaysFalse", builder -> builder.parameter("p1")); |
762 | |||
763 | var p1 = Variable.of("p1"); | ||
764 | var predicate = Query.builder("AlwaysFalse").parameters(p1).build(); | ||
765 | 616 | ||
766 | var store = ModelStore.builder() | 617 | var store = ModelStore.builder() |
767 | .symbols(person) | 618 | .symbols(person) |
768 | .with(ViatraModelQuery.ADAPTER) | 619 | .with(ViatraModelQueryAdapter.builder() |
769 | .queries(predicate) | 620 | .queries(predicate)) |
770 | .build(); | 621 | .build(); |
771 | 622 | ||
772 | var model = store.createEmptyModel(); | 623 | var model = store.createEmptyModel(); |
773 | var personInterpretation = model.getInterpretation(person); | 624 | var personInterpretation = model.getInterpretation(person); |
774 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | 625 | var queryEngine = model.getAdapter(ModelQueryAdapter.class); |
775 | var predicateResultSet = queryEngine.getResultSet(predicate); | 626 | var predicateResultSet = queryEngine.getResultSet(predicate); |
776 | 627 | ||
777 | personInterpretation.put(Tuple.of(0), true); | 628 | personInterpretation.put(Tuple.of(0), true); |
@@ -781,17 +632,4 @@ class QueryTest { | |||
781 | queryEngine.flushChanges(); | 632 | queryEngine.flushChanges(); |
782 | assertResults(Map.of(), predicateResultSet); | 633 | assertResults(Map.of(), predicateResultSet); |
783 | } | 634 | } |
784 | |||
785 | @Test | ||
786 | void alwaysTrueTest() { | ||
787 | var person = new Symbol<>("Person", 1, Boolean.class, false); | ||
788 | |||
789 | var p1 = Variable.of("p1"); | ||
790 | var predicate = Query.builder("AlwaysTrue").parameters(p1).clause().build(); | ||
791 | |||
792 | var storeBuilder = ModelStore.builder().symbols(person); | ||
793 | var queryBuilder = storeBuilder.with(ViatraModelQuery.ADAPTER); | ||
794 | |||
795 | assertThrows(IllegalArgumentException.class, () -> queryBuilder.queries(predicate)); | ||
796 | } | ||
797 | } | 635 | } |
diff --git a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/QueryTransactionTest.java b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/QueryTransactionTest.java index abd49341..66f043c6 100644 --- a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/QueryTransactionTest.java +++ b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/QueryTransactionTest.java | |||
@@ -1,15 +1,21 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.viatra; | 6 | package tools.refinery.store.query.viatra; |
2 | 7 | ||
3 | import org.eclipse.viatra.query.runtime.matchers.backend.QueryEvaluationHint; | 8 | import org.eclipse.viatra.query.runtime.matchers.backend.QueryEvaluationHint; |
4 | import org.junit.jupiter.api.Disabled; | 9 | import org.junit.jupiter.api.Disabled; |
5 | import org.junit.jupiter.api.Test; | 10 | import org.junit.jupiter.api.Test; |
6 | import tools.refinery.store.model.ModelStore; | 11 | import tools.refinery.store.model.ModelStore; |
7 | import tools.refinery.store.query.ModelQuery; | 12 | import tools.refinery.store.query.ModelQueryAdapter; |
8 | import tools.refinery.store.query.dnf.Query; | 13 | import tools.refinery.store.query.dnf.Query; |
9 | import tools.refinery.store.query.term.Variable; | 14 | import tools.refinery.store.query.dnf.RelationalQuery; |
10 | import tools.refinery.store.query.view.FilteredRelationView; | 15 | import tools.refinery.store.query.view.AnySymbolView; |
11 | import tools.refinery.store.query.view.FunctionalRelationView; | 16 | import tools.refinery.store.query.view.FilteredView; |
12 | import tools.refinery.store.query.view.KeyOnlyRelationView; | 17 | import tools.refinery.store.query.view.FunctionView; |
18 | import tools.refinery.store.query.view.KeyOnlyView; | ||
13 | import tools.refinery.store.representation.Symbol; | 19 | import tools.refinery.store.representation.Symbol; |
14 | import tools.refinery.store.tuple.Tuple; | 20 | import tools.refinery.store.tuple.Tuple; |
15 | 21 | ||
@@ -22,26 +28,24 @@ import static tools.refinery.store.query.viatra.tests.QueryAssertions.assertNull | |||
22 | import static tools.refinery.store.query.viatra.tests.QueryAssertions.assertResults; | 28 | import static tools.refinery.store.query.viatra.tests.QueryAssertions.assertResults; |
23 | 29 | ||
24 | class QueryTransactionTest { | 30 | class QueryTransactionTest { |
31 | private static final Symbol<Boolean> person = Symbol.of("Person", 1); | ||
32 | private static final Symbol<Integer> age = Symbol.of("age", 1, Integer.class); | ||
33 | private static final AnySymbolView personView = new KeyOnlyView<>(person); | ||
34 | private static final AnySymbolView ageView = new FunctionView<>(age); | ||
35 | private static final RelationalQuery predicate = Query.of("TypeConstraint", (builder, p1) -> | ||
36 | builder.clause(personView.call(p1))); | ||
37 | |||
25 | @Test | 38 | @Test |
26 | void flushTest() { | 39 | void flushTest() { |
27 | var person = new Symbol<>("Person", 1, Boolean.class, false); | ||
28 | var personView = new KeyOnlyRelationView<>(person); | ||
29 | |||
30 | var p1 = Variable.of("p1"); | ||
31 | var predicate = Query.builder("TypeConstraint") | ||
32 | .parameters(p1) | ||
33 | .clause(personView.call(p1)) | ||
34 | .build(); | ||
35 | |||
36 | var store = ModelStore.builder() | 40 | var store = ModelStore.builder() |
37 | .symbols(person) | 41 | .symbols(person) |
38 | .with(ViatraModelQuery.ADAPTER) | 42 | .with(ViatraModelQueryAdapter.builder() |
39 | .queries(predicate) | 43 | .queries(predicate)) |
40 | .build(); | 44 | .build(); |
41 | 45 | ||
42 | var model = store.createEmptyModel(); | 46 | var model = store.createEmptyModel(); |
43 | var personInterpretation = model.getInterpretation(person); | 47 | var personInterpretation = model.getInterpretation(person); |
44 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | 48 | var queryEngine = model.getAdapter(ModelQueryAdapter.class); |
45 | var predicateResultSet = queryEngine.getResultSet(predicate); | 49 | var predicateResultSet = queryEngine.getResultSet(predicate); |
46 | 50 | ||
47 | assertResults(Map.of( | 51 | assertResults(Map.of( |
@@ -95,25 +99,16 @@ class QueryTransactionTest { | |||
95 | 99 | ||
96 | @Test | 100 | @Test |
97 | void localSearchTest() { | 101 | void localSearchTest() { |
98 | var person = new Symbol<>("Person", 1, Boolean.class, false); | ||
99 | var personView = new KeyOnlyRelationView<>(person); | ||
100 | |||
101 | var p1 = Variable.of("p1"); | ||
102 | var predicate = Query.builder("TypeConstraint") | ||
103 | .parameters(p1) | ||
104 | .clause(personView.call(p1)) | ||
105 | .build(); | ||
106 | |||
107 | var store = ModelStore.builder() | 102 | var store = ModelStore.builder() |
108 | .symbols(person) | 103 | .symbols(person) |
109 | .with(ViatraModelQuery.ADAPTER) | 104 | .with(ViatraModelQueryAdapter.builder() |
110 | .defaultHint(new QueryEvaluationHint(null, QueryEvaluationHint.BackendRequirement.DEFAULT_SEARCH)) | 105 | .defaultHint(new QueryEvaluationHint(null, QueryEvaluationHint.BackendRequirement.DEFAULT_SEARCH)) |
111 | .queries(predicate) | 106 | .queries(predicate)) |
112 | .build(); | 107 | .build(); |
113 | 108 | ||
114 | var model = store.createEmptyModel(); | 109 | var model = store.createEmptyModel(); |
115 | var personInterpretation = model.getInterpretation(person); | 110 | var personInterpretation = model.getInterpretation(person); |
116 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | 111 | var queryEngine = model.getAdapter(ModelQueryAdapter.class); |
117 | var predicateResultSet = queryEngine.getResultSet(predicate); | 112 | var predicateResultSet = queryEngine.getResultSet(predicate); |
118 | 113 | ||
119 | assertResults(Map.of( | 114 | assertResults(Map.of( |
@@ -149,26 +144,18 @@ class QueryTransactionTest { | |||
149 | 144 | ||
150 | @Test | 145 | @Test |
151 | void unrelatedChangesTest() { | 146 | void unrelatedChangesTest() { |
152 | var person = new Symbol<>("Person", 1, Boolean.class, false); | 147 | var asset = Symbol.of("Asset", 1); |
153 | var asset = new Symbol<>("Asset", 1, Boolean.class, false); | ||
154 | var personView = new KeyOnlyRelationView<>(person); | ||
155 | |||
156 | var p1 = Variable.of("p1"); | ||
157 | var predicate = Query.builder("TypeConstraint") | ||
158 | .parameters(p1) | ||
159 | .clause(personView.call(p1)) | ||
160 | .build(); | ||
161 | 148 | ||
162 | var store = ModelStore.builder() | 149 | var store = ModelStore.builder() |
163 | .symbols(person, asset) | 150 | .symbols(person, asset) |
164 | .with(ViatraModelQuery.ADAPTER) | 151 | .with(ViatraModelQueryAdapter.builder() |
165 | .queries(predicate) | 152 | .queries(predicate)) |
166 | .build(); | 153 | .build(); |
167 | 154 | ||
168 | var model = store.createEmptyModel(); | 155 | var model = store.createEmptyModel(); |
169 | var personInterpretation = model.getInterpretation(person); | 156 | var personInterpretation = model.getInterpretation(person); |
170 | var assetInterpretation = model.getInterpretation(asset); | 157 | var assetInterpretation = model.getInterpretation(asset); |
171 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | 158 | var queryEngine = model.getAdapter(ModelQueryAdapter.class); |
172 | var predicateResultSet = queryEngine.getResultSet(predicate); | 159 | var predicateResultSet = queryEngine.getResultSet(predicate); |
173 | 160 | ||
174 | assertFalse(queryEngine.hasPendingChanges()); | 161 | assertFalse(queryEngine.hasPendingChanges()); |
@@ -222,32 +209,21 @@ class QueryTransactionTest { | |||
222 | 209 | ||
223 | @Test | 210 | @Test |
224 | void tupleChangingChangeTest() { | 211 | void tupleChangingChangeTest() { |
225 | var person = new Symbol<>("Person", 1, Boolean.class, false); | 212 | var query = Query.of("TypeConstraint", Integer.class, (builder, p1, output) -> builder.clause( |
226 | var age = new Symbol<>("age", 1, Integer.class, null); | 213 | personView.call(p1), |
227 | var personView = new KeyOnlyRelationView<>(person); | 214 | ageView.call(p1, output) |
228 | var ageView = new FunctionalRelationView<>(age); | 215 | )); |
229 | |||
230 | var p1 = Variable.of("p1"); | ||
231 | var x = Variable.of("x", Integer.class); | ||
232 | var query = Query.builder() | ||
233 | .parameter(p1) | ||
234 | .output(x) | ||
235 | .clause( | ||
236 | personView.call(p1), | ||
237 | ageView.call(p1, x) | ||
238 | ) | ||
239 | .build(); | ||
240 | 216 | ||
241 | var store = ModelStore.builder() | 217 | var store = ModelStore.builder() |
242 | .symbols(person, age) | 218 | .symbols(person, age) |
243 | .with(ViatraModelQuery.ADAPTER) | 219 | .with(ViatraModelQueryAdapter.builder() |
244 | .query(query) | 220 | .queries(query)) |
245 | .build(); | 221 | .build(); |
246 | 222 | ||
247 | var model = store.createEmptyModel(); | 223 | var model = store.createEmptyModel(); |
248 | var personInterpretation = model.getInterpretation(person); | 224 | var personInterpretation = model.getInterpretation(person); |
249 | var ageInterpretation = model.getInterpretation(age); | 225 | var ageInterpretation = model.getInterpretation(age); |
250 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | 226 | var queryEngine = model.getAdapter(ModelQueryAdapter.class); |
251 | var queryResultSet = queryEngine.getResultSet(query); | 227 | var queryResultSet = queryEngine.getResultSet(query); |
252 | 228 | ||
253 | personInterpretation.put(Tuple.of(0), true); | 229 | personInterpretation.put(Tuple.of(0), true); |
@@ -270,31 +246,23 @@ class QueryTransactionTest { | |||
270 | 246 | ||
271 | @Test | 247 | @Test |
272 | void tuplePreservingUnchangedTest() { | 248 | void tuplePreservingUnchangedTest() { |
273 | var person = new Symbol<>("Person", 1, Boolean.class, false); | 249 | var adultView = new FilteredView<>(age, "adult", n -> n != null && n >= 18); |
274 | var age = new Symbol<>("age", 1, Integer.class, null); | 250 | |
275 | var personView = new KeyOnlyRelationView<>(person); | 251 | var query = Query.of("TypeConstraint", (builder, p1) -> builder.clause( |
276 | var adultView = new FilteredRelationView<>(age, "adult", n -> n != null && n >= 18); | 252 | personView.call(p1), |
277 | 253 | adultView.call(p1) | |
278 | var p1 = Variable.of("p1"); | 254 | )); |
279 | var x = Variable.of("x", Integer.class); | ||
280 | var query = Query.builder() | ||
281 | .parameter(p1) | ||
282 | .clause( | ||
283 | personView.call(p1), | ||
284 | adultView.call(p1) | ||
285 | ) | ||
286 | .build(); | ||
287 | 255 | ||
288 | var store = ModelStore.builder() | 256 | var store = ModelStore.builder() |
289 | .symbols(person, age) | 257 | .symbols(person, age) |
290 | .with(ViatraModelQuery.ADAPTER) | 258 | .with(ViatraModelQueryAdapter.builder() |
291 | .query(query) | 259 | .queries(query)) |
292 | .build(); | 260 | .build(); |
293 | 261 | ||
294 | var model = store.createEmptyModel(); | 262 | var model = store.createEmptyModel(); |
295 | var personInterpretation = model.getInterpretation(person); | 263 | var personInterpretation = model.getInterpretation(person); |
296 | var ageInterpretation = model.getInterpretation(age); | 264 | var ageInterpretation = model.getInterpretation(age); |
297 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | 265 | var queryEngine = model.getAdapter(ModelQueryAdapter.class); |
298 | var queryResultSet = queryEngine.getResultSet(query); | 266 | var queryResultSet = queryEngine.getResultSet(query); |
299 | 267 | ||
300 | personInterpretation.put(Tuple.of(0), true); | 268 | personInterpretation.put(Tuple.of(0), true); |
@@ -318,24 +286,15 @@ class QueryTransactionTest { | |||
318 | @Disabled("TODO Fix DiffCursor") | 286 | @Disabled("TODO Fix DiffCursor") |
319 | @Test | 287 | @Test |
320 | void commitAfterFlushTest() { | 288 | void commitAfterFlushTest() { |
321 | var person = new Symbol<>("Person", 1, Boolean.class, false); | ||
322 | var personView = new KeyOnlyRelationView<>(person); | ||
323 | |||
324 | var p1 = Variable.of("p1"); | ||
325 | var predicate = Query.builder("TypeConstraint") | ||
326 | .parameters(p1) | ||
327 | .clause(personView.call(p1)) | ||
328 | .build(); | ||
329 | |||
330 | var store = ModelStore.builder() | 289 | var store = ModelStore.builder() |
331 | .symbols(person) | 290 | .symbols(person) |
332 | .with(ViatraModelQuery.ADAPTER) | 291 | .with(ViatraModelQueryAdapter.builder() |
333 | .queries(predicate) | 292 | .queries(predicate)) |
334 | .build(); | 293 | .build(); |
335 | 294 | ||
336 | var model = store.createEmptyModel(); | 295 | var model = store.createEmptyModel(); |
337 | var personInterpretation = model.getInterpretation(person); | 296 | var personInterpretation = model.getInterpretation(person); |
338 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | 297 | var queryEngine = model.getAdapter(ModelQueryAdapter.class); |
339 | var predicateResultSet = queryEngine.getResultSet(predicate); | 298 | var predicateResultSet = queryEngine.getResultSet(predicate); |
340 | 299 | ||
341 | personInterpretation.put(Tuple.of(0), true); | 300 | personInterpretation.put(Tuple.of(0), true); |
@@ -376,24 +335,15 @@ class QueryTransactionTest { | |||
376 | @Disabled("TODO Fix DiffCursor") | 335 | @Disabled("TODO Fix DiffCursor") |
377 | @Test | 336 | @Test |
378 | void commitWithoutFlushTest() { | 337 | void commitWithoutFlushTest() { |
379 | var person = new Symbol<>("Person", 1, Boolean.class, false); | ||
380 | var personView = new KeyOnlyRelationView<>(person); | ||
381 | |||
382 | var p1 = Variable.of("p1"); | ||
383 | var predicate = Query.builder("TypeConstraint") | ||
384 | .parameters(p1) | ||
385 | .clause(personView.call(p1)) | ||
386 | .build(); | ||
387 | |||
388 | var store = ModelStore.builder() | 338 | var store = ModelStore.builder() |
389 | .symbols(person) | 339 | .symbols(person) |
390 | .with(ViatraModelQuery.ADAPTER) | 340 | .with(ViatraModelQueryAdapter.builder() |
391 | .queries(predicate) | 341 | .queries(predicate)) |
392 | .build(); | 342 | .build(); |
393 | 343 | ||
394 | var model = store.createEmptyModel(); | 344 | var model = store.createEmptyModel(); |
395 | var personInterpretation = model.getInterpretation(person); | 345 | var personInterpretation = model.getInterpretation(person); |
396 | var queryEngine = model.getAdapter(ModelQuery.ADAPTER); | 346 | var queryEngine = model.getAdapter(ModelQueryAdapter.class); |
397 | var predicateResultSet = queryEngine.getResultSet(predicate); | 347 | var predicateResultSet = queryEngine.getResultSet(predicate); |
398 | 348 | ||
399 | personInterpretation.put(Tuple.of(0), true); | 349 | personInterpretation.put(Tuple.of(0), true); |
diff --git a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/internal/cardinality/UpperCardinalitySumAggregationOperatorTest.java b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/internal/cardinality/UpperCardinalitySumAggregationOperatorTest.java deleted file mode 100644 index 20dad543..00000000 --- a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/internal/cardinality/UpperCardinalitySumAggregationOperatorTest.java +++ /dev/null | |||
@@ -1,87 +0,0 @@ | |||
1 | package tools.refinery.store.query.viatra.internal.cardinality; | ||
2 | |||
3 | import org.junit.jupiter.api.BeforeEach; | ||
4 | import org.junit.jupiter.api.Test; | ||
5 | import tools.refinery.store.representation.cardinality.UpperCardinalities; | ||
6 | import tools.refinery.store.representation.cardinality.UpperCardinality; | ||
7 | |||
8 | import static org.hamcrest.MatcherAssert.assertThat; | ||
9 | import static org.hamcrest.Matchers.equalTo; | ||
10 | |||
11 | class UpperCardinalitySumAggregationOperatorTest { | ||
12 | private UpperCardinalitySumAggregationOperator.Accumulator accumulator; | ||
13 | |||
14 | @BeforeEach | ||
15 | void beforeEach() { | ||
16 | accumulator = UpperCardinalitySumAggregationOperator.INSTANCE.createNeutral(); | ||
17 | } | ||
18 | |||
19 | @Test | ||
20 | void emptyAggregationTest() { | ||
21 | assertResult(UpperCardinality.of(0)); | ||
22 | } | ||
23 | |||
24 | @Test | ||
25 | void singleBoundedTest() { | ||
26 | insert(UpperCardinality.of(3)); | ||
27 | assertResult(UpperCardinality.of(3)); | ||
28 | } | ||
29 | |||
30 | @Test | ||
31 | void multipleBoundedTest() { | ||
32 | insert(UpperCardinality.of(2)); | ||
33 | insert(UpperCardinality.of(3)); | ||
34 | assertResult(UpperCardinality.of(5)); | ||
35 | } | ||
36 | |||
37 | @Test | ||
38 | void singleUnboundedTest() { | ||
39 | insert(UpperCardinalities.UNBOUNDED); | ||
40 | assertResult(UpperCardinalities.UNBOUNDED); | ||
41 | } | ||
42 | |||
43 | @Test | ||
44 | void multipleUnboundedTest() { | ||
45 | insert(UpperCardinalities.UNBOUNDED); | ||
46 | insert(UpperCardinalities.UNBOUNDED); | ||
47 | assertResult(UpperCardinalities.UNBOUNDED); | ||
48 | } | ||
49 | |||
50 | @Test | ||
51 | void removeBoundedTest() { | ||
52 | insert(UpperCardinality.of(2)); | ||
53 | insert(UpperCardinality.of(3)); | ||
54 | remove(UpperCardinality.of(2)); | ||
55 | assertResult(UpperCardinality.of(3)); | ||
56 | } | ||
57 | |||
58 | @Test | ||
59 | void removeAllUnboundedTest() { | ||
60 | insert(UpperCardinalities.UNBOUNDED); | ||
61 | insert(UpperCardinality.of(3)); | ||
62 | remove(UpperCardinalities.UNBOUNDED); | ||
63 | assertResult(UpperCardinality.of(3)); | ||
64 | } | ||
65 | |||
66 | @Test | ||
67 | void removeSomeUnboundedTest() { | ||
68 | insert(UpperCardinalities.UNBOUNDED); | ||
69 | insert(UpperCardinalities.UNBOUNDED); | ||
70 | insert(UpperCardinality.of(3)); | ||
71 | remove(UpperCardinalities.UNBOUNDED); | ||
72 | assertResult(UpperCardinalities.UNBOUNDED); | ||
73 | } | ||
74 | |||
75 | private void insert(UpperCardinality value) { | ||
76 | accumulator = UpperCardinalitySumAggregationOperator.INSTANCE.update(accumulator, value, true); | ||
77 | } | ||
78 | |||
79 | private void remove(UpperCardinality value) { | ||
80 | accumulator = UpperCardinalitySumAggregationOperator.INSTANCE.update(accumulator, value, false); | ||
81 | } | ||
82 | |||
83 | private void assertResult(UpperCardinality expected) { | ||
84 | var result = UpperCardinalitySumAggregationOperator.INSTANCE.getAggregate(accumulator); | ||
85 | assertThat(result, equalTo(expected)); | ||
86 | } | ||
87 | } | ||
diff --git a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/internal/matcher/MatcherUtilsTest.java b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/internal/matcher/MatcherUtilsTest.java new file mode 100644 index 00000000..968c6c5e --- /dev/null +++ b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/internal/matcher/MatcherUtilsTest.java | |||
@@ -0,0 +1,239 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.viatra.internal.matcher; | ||
7 | |||
8 | import org.eclipse.viatra.query.runtime.matchers.tuple.*; | ||
9 | import org.junit.jupiter.api.Test; | ||
10 | import tools.refinery.store.tuple.Tuple; | ||
11 | import tools.refinery.store.tuple.*; | ||
12 | |||
13 | import java.util.List; | ||
14 | |||
15 | import static org.hamcrest.MatcherAssert.assertThat; | ||
16 | import static org.hamcrest.Matchers.*; | ||
17 | import static org.junit.jupiter.api.Assertions.assertThrows; | ||
18 | |||
19 | class MatcherUtilsTest { | ||
20 | @Test | ||
21 | void toViatra0Test() { | ||
22 | var viatraTuple = MatcherUtils.toViatraTuple(Tuple.of()); | ||
23 | assertThat(viatraTuple.getSize(), is(0)); | ||
24 | assertThat(viatraTuple, instanceOf(FlatTuple0.class)); | ||
25 | } | ||
26 | |||
27 | @Test | ||
28 | void toViatra1Test() { | ||
29 | var viatraTuple = MatcherUtils.toViatraTuple(Tuple.of(2)); | ||
30 | assertThat(viatraTuple.getSize(), is(1)); | ||
31 | assertThat(viatraTuple.get(0), is(Tuple.of(2))); | ||
32 | assertThat(viatraTuple, instanceOf(FlatTuple1.class)); | ||
33 | } | ||
34 | |||
35 | @Test | ||
36 | void toViatra2Test() { | ||
37 | var viatraTuple = MatcherUtils.toViatraTuple(Tuple.of(2, 3)); | ||
38 | assertThat(viatraTuple.getSize(), is(2)); | ||
39 | assertThat(viatraTuple.get(0), is(Tuple.of(2))); | ||
40 | assertThat(viatraTuple.get(1), is(Tuple.of(3))); | ||
41 | assertThat(viatraTuple, instanceOf(FlatTuple2.class)); | ||
42 | } | ||
43 | |||
44 | @Test | ||
45 | void toViatra3Test() { | ||
46 | var viatraTuple = MatcherUtils.toViatraTuple(Tuple.of(2, 3, 5)); | ||
47 | assertThat(viatraTuple.getSize(), is(3)); | ||
48 | assertThat(viatraTuple.get(0), is(Tuple.of(2))); | ||
49 | assertThat(viatraTuple.get(1), is(Tuple.of(3))); | ||
50 | assertThat(viatraTuple.get(2), is(Tuple.of(5))); | ||
51 | assertThat(viatraTuple, instanceOf(FlatTuple3.class)); | ||
52 | } | ||
53 | |||
54 | @Test | ||
55 | void toViatra4Test() { | ||
56 | var viatraTuple = MatcherUtils.toViatraTuple(Tuple.of(2, 3, 5, 8)); | ||
57 | assertThat(viatraTuple.getSize(), is(4)); | ||
58 | assertThat(viatraTuple.get(0), is(Tuple.of(2))); | ||
59 | assertThat(viatraTuple.get(1), is(Tuple.of(3))); | ||
60 | assertThat(viatraTuple.get(2), is(Tuple.of(5))); | ||
61 | assertThat(viatraTuple.get(3), is(Tuple.of(8))); | ||
62 | assertThat(viatraTuple, instanceOf(FlatTuple4.class)); | ||
63 | } | ||
64 | |||
65 | @Test | ||
66 | void toViatra5Test() { | ||
67 | var viatraTuple = MatcherUtils.toViatraTuple(Tuple.of(2, 3, 5, 8, 13)); | ||
68 | assertThat(viatraTuple.getSize(), is(5)); | ||
69 | assertThat(viatraTuple.get(0), is(Tuple.of(2))); | ||
70 | assertThat(viatraTuple.get(1), is(Tuple.of(3))); | ||
71 | assertThat(viatraTuple.get(2), is(Tuple.of(5))); | ||
72 | assertThat(viatraTuple.get(3), is(Tuple.of(8))); | ||
73 | assertThat(viatraTuple.get(4), is(Tuple.of(13))); | ||
74 | assertThat(viatraTuple, instanceOf(FlatTuple.class)); | ||
75 | } | ||
76 | |||
77 | @Test | ||
78 | void toRefinery0Test() { | ||
79 | var refineryTuple = MatcherUtils.toRefineryTuple(Tuples.flatTupleOf()); | ||
80 | assertThat(refineryTuple.getSize(), is(0)); | ||
81 | assertThat(refineryTuple, instanceOf(Tuple0.class)); | ||
82 | } | ||
83 | |||
84 | @Test | ||
85 | void toRefinery1Test() { | ||
86 | var refineryTuple = MatcherUtils.toRefineryTuple(Tuples.flatTupleOf(Tuple.of(2))); | ||
87 | assertThat(refineryTuple.getSize(), is(1)); | ||
88 | assertThat(refineryTuple.get(0), is(2)); | ||
89 | assertThat(refineryTuple, instanceOf(Tuple1.class)); | ||
90 | } | ||
91 | |||
92 | @Test | ||
93 | void toRefinery2Test() { | ||
94 | var refineryTuple = MatcherUtils.toRefineryTuple(Tuples.flatTupleOf(Tuple.of(2), Tuple.of(3))); | ||
95 | assertThat(refineryTuple.getSize(), is(2)); | ||
96 | assertThat(refineryTuple.get(0), is(2)); | ||
97 | assertThat(refineryTuple.get(1), is(3)); | ||
98 | assertThat(refineryTuple, instanceOf(Tuple2.class)); | ||
99 | } | ||
100 | |||
101 | @Test | ||
102 | void toRefinery3Test() { | ||
103 | var refineryTuple = MatcherUtils.toRefineryTuple(Tuples.flatTupleOf(Tuple.of(2), Tuple.of(3), Tuple.of(5))); | ||
104 | assertThat(refineryTuple.getSize(), is(3)); | ||
105 | assertThat(refineryTuple.get(0), is(2)); | ||
106 | assertThat(refineryTuple.get(1), is(3)); | ||
107 | assertThat(refineryTuple.get(2), is(5)); | ||
108 | assertThat(refineryTuple, instanceOf(Tuple3.class)); | ||
109 | } | ||
110 | |||
111 | @Test | ||
112 | void toRefinery4Test() { | ||
113 | var refineryTuple = MatcherUtils.toRefineryTuple(Tuples.flatTupleOf(Tuple.of(2), Tuple.of(3), Tuple.of(5), | ||
114 | Tuple.of(8))); | ||
115 | assertThat(refineryTuple.getSize(), is(4)); | ||
116 | assertThat(refineryTuple.get(0), is(2)); | ||
117 | assertThat(refineryTuple.get(1), is(3)); | ||
118 | assertThat(refineryTuple.get(2), is(5)); | ||
119 | assertThat(refineryTuple.get(3), is(8)); | ||
120 | assertThat(refineryTuple, instanceOf(Tuple4.class)); | ||
121 | } | ||
122 | |||
123 | @Test | ||
124 | void toRefinery5Test() { | ||
125 | var refineryTuple = MatcherUtils.toRefineryTuple(Tuples.flatTupleOf(Tuple.of(2), Tuple.of(3), Tuple.of(5), | ||
126 | Tuple.of(8), Tuple.of(13))); | ||
127 | assertThat(refineryTuple.getSize(), is(5)); | ||
128 | assertThat(refineryTuple.get(0), is(2)); | ||
129 | assertThat(refineryTuple.get(1), is(3)); | ||
130 | assertThat(refineryTuple.get(2), is(5)); | ||
131 | assertThat(refineryTuple.get(3), is(8)); | ||
132 | assertThat(refineryTuple.get(4), is(13)); | ||
133 | assertThat(refineryTuple, instanceOf(TupleN.class)); | ||
134 | } | ||
135 | |||
136 | @Test | ||
137 | void toRefineryInvalidValueTest() { | ||
138 | var viatraTuple = Tuples.flatTupleOf(Tuple.of(2), -98); | ||
139 | assertThrows(IllegalArgumentException.class, () -> MatcherUtils.toRefineryTuple(viatraTuple)); | ||
140 | } | ||
141 | |||
142 | @Test | ||
143 | void keyToRefinery0Test() { | ||
144 | var refineryTuple = MatcherUtils.keyToRefineryTuple(Tuples.flatTupleOf(-99)); | ||
145 | assertThat(refineryTuple.getSize(), is(0)); | ||
146 | assertThat(refineryTuple, instanceOf(Tuple0.class)); | ||
147 | } | ||
148 | |||
149 | @Test | ||
150 | void keyToRefinery1Test() { | ||
151 | var refineryTuple = MatcherUtils.keyToRefineryTuple(Tuples.flatTupleOf(Tuple.of(2), -99)); | ||
152 | assertThat(refineryTuple.getSize(), is(1)); | ||
153 | assertThat(refineryTuple.get(0), is(2)); | ||
154 | assertThat(refineryTuple, instanceOf(Tuple1.class)); | ||
155 | } | ||
156 | |||
157 | @Test | ||
158 | void keyToRefinery2Test() { | ||
159 | var refineryTuple = MatcherUtils.keyToRefineryTuple(Tuples.flatTupleOf(Tuple.of(2), Tuple.of(3), -99)); | ||
160 | assertThat(refineryTuple.getSize(), is(2)); | ||
161 | assertThat(refineryTuple.get(0), is(2)); | ||
162 | assertThat(refineryTuple.get(1), is(3)); | ||
163 | assertThat(refineryTuple, instanceOf(Tuple2.class)); | ||
164 | } | ||
165 | |||
166 | @Test | ||
167 | void keyToRefinery3Test() { | ||
168 | var refineryTuple = MatcherUtils.keyToRefineryTuple(Tuples.flatTupleOf(Tuple.of(2), Tuple.of(3), Tuple.of(5), | ||
169 | -99)); | ||
170 | assertThat(refineryTuple.getSize(), is(3)); | ||
171 | assertThat(refineryTuple.get(0), is(2)); | ||
172 | assertThat(refineryTuple.get(1), is(3)); | ||
173 | assertThat(refineryTuple.get(2), is(5)); | ||
174 | assertThat(refineryTuple, instanceOf(Tuple3.class)); | ||
175 | } | ||
176 | |||
177 | @Test | ||
178 | void keyToRefinery4Test() { | ||
179 | var refineryTuple = MatcherUtils.keyToRefineryTuple(Tuples.flatTupleOf(Tuple.of(2), Tuple.of(3), Tuple.of(5), | ||
180 | Tuple.of(8), -99)); | ||
181 | assertThat(refineryTuple.getSize(), is(4)); | ||
182 | assertThat(refineryTuple.get(0), is(2)); | ||
183 | assertThat(refineryTuple.get(1), is(3)); | ||
184 | assertThat(refineryTuple.get(2), is(5)); | ||
185 | assertThat(refineryTuple.get(3), is(8)); | ||
186 | assertThat(refineryTuple, instanceOf(Tuple4.class)); | ||
187 | } | ||
188 | |||
189 | @Test | ||
190 | void keyToRefinery5Test() { | ||
191 | var refineryTuple = MatcherUtils.keyToRefineryTuple(Tuples.flatTupleOf(Tuple.of(2), Tuple.of(3), Tuple.of(5), | ||
192 | Tuple.of(8), Tuple.of(13), -99)); | ||
193 | assertThat(refineryTuple.getSize(), is(5)); | ||
194 | assertThat(refineryTuple.get(0), is(2)); | ||
195 | assertThat(refineryTuple.get(1), is(3)); | ||
196 | assertThat(refineryTuple.get(2), is(5)); | ||
197 | assertThat(refineryTuple.get(3), is(8)); | ||
198 | assertThat(refineryTuple.get(4), is(13)); | ||
199 | assertThat(refineryTuple, instanceOf(TupleN.class)); | ||
200 | } | ||
201 | |||
202 | @Test | ||
203 | void keyToRefineryTooShortTest() { | ||
204 | var viatraTuple = Tuples.flatTupleOf(); | ||
205 | assertThrows(IllegalArgumentException.class, () -> MatcherUtils.keyToRefineryTuple(viatraTuple)); | ||
206 | } | ||
207 | |||
208 | @Test | ||
209 | void keyToRefineryInvalidValueTest() { | ||
210 | var viatraTuple = Tuples.flatTupleOf(Tuple.of(2), -98, -99); | ||
211 | assertThrows(IllegalArgumentException.class, () -> MatcherUtils.keyToRefineryTuple(viatraTuple)); | ||
212 | } | ||
213 | |||
214 | @Test | ||
215 | void getSingleValueTest() { | ||
216 | var value = MatcherUtils.getSingleValue(List.of(Tuples.flatTupleOf(Tuple.of(2), -99))); | ||
217 | assertThat(value, is(-99)); | ||
218 | } | ||
219 | |||
220 | // Static analysis accurately determines that the result is always {@code null}, but we check anyways. | ||
221 | @SuppressWarnings("ConstantValue") | ||
222 | @Test | ||
223 | void getSingleValueNullTest() { | ||
224 | var value = MatcherUtils.getSingleValue((Iterable<? extends ITuple>) null); | ||
225 | assertThat(value, nullValue()); | ||
226 | } | ||
227 | |||
228 | @Test | ||
229 | void getSingleValueEmptyTest() { | ||
230 | var value = MatcherUtils.getSingleValue(List.of()); | ||
231 | assertThat(value, nullValue()); | ||
232 | } | ||
233 | |||
234 | @Test | ||
235 | void getSingleValueMultipleTest() { | ||
236 | var viatraTuples = List.of(Tuples.flatTupleOf(Tuple.of(2), -98), Tuples.flatTupleOf(Tuple.of(2), -99)); | ||
237 | assertThrows(IllegalStateException.class, () -> MatcherUtils.getSingleValue(viatraTuples)); | ||
238 | } | ||
239 | } | ||
diff --git a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryAssertions.java b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryAssertions.java index 6f50ec73..7a25cfdc 100644 --- a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryAssertions.java +++ b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryAssertions.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.viatra.tests; | 6 | package tools.refinery.store.query.viatra.tests; |
2 | 7 | ||
3 | import org.junit.jupiter.api.function.Executable; | 8 | import org.junit.jupiter.api.function.Executable; |
@@ -42,7 +47,7 @@ public final class QueryAssertions { | |||
42 | var cursor = resultSet.getAll(); | 47 | var cursor = resultSet.getAll(); |
43 | while (cursor.move()) { | 48 | while (cursor.move()) { |
44 | var key = cursor.getKey(); | 49 | var key = cursor.getKey(); |
45 | var previous = actual.put(key.toTuple(), cursor.getValue()); | 50 | var previous = actual.put(key, cursor.getValue()); |
46 | assertThat("duplicate value for key " + key, previous, nullValue()); | 51 | assertThat("duplicate value for key " + key, previous, nullValue()); |
47 | } | 52 | } |
48 | executables.add(() -> assertThat("results cursor", actual, is(filteredExpected))); | 53 | executables.add(() -> assertThat("results cursor", actual, is(filteredExpected))); |
diff --git a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryBackendHint.java b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryBackendHint.java index b1818a17..dc0e92c8 100644 --- a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryBackendHint.java +++ b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryBackendHint.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.viatra.tests; | 6 | package tools.refinery.store.query.viatra.tests; |
2 | 7 | ||
3 | import org.eclipse.viatra.query.runtime.matchers.backend.QueryEvaluationHint; | 8 | import org.eclipse.viatra.query.runtime.matchers.backend.QueryEvaluationHint; |
diff --git a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryEngineTest.java b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryEngineTest.java index f129520c..d4f16da7 100644 --- a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryEngineTest.java +++ b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryEngineTest.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.viatra.tests; | 6 | package tools.refinery.store.query.viatra.tests; |
2 | 7 | ||
3 | import org.junit.jupiter.params.ParameterizedTest; | 8 | import org.junit.jupiter.params.ParameterizedTest; |
diff --git a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryEvaluationHintSource.java b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryEvaluationHintSource.java index a55762e2..9e75d5f3 100644 --- a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryEvaluationHintSource.java +++ b/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/tests/QueryEvaluationHintSource.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.viatra.tests; | 6 | package tools.refinery.store.query.viatra.tests; |
2 | 7 | ||
3 | import org.eclipse.viatra.query.runtime.matchers.backend.QueryEvaluationHint; | 8 | import org.eclipse.viatra.query.runtime.matchers.backend.QueryEvaluationHint; |
diff --git a/subprojects/store-query/build.gradle b/subprojects/store-query/build.gradle deleted file mode 100644 index 97761936..00000000 --- a/subprojects/store-query/build.gradle +++ /dev/null | |||
@@ -1,9 +0,0 @@ | |||
1 | plugins { | ||
2 | id 'refinery-java-library' | ||
3 | id 'refinery-java-test-fixtures' | ||
4 | } | ||
5 | |||
6 | dependencies { | ||
7 | api project(':refinery-store') | ||
8 | testFixturesApi libs.hamcrest | ||
9 | } | ||
diff --git a/subprojects/store-query/build.gradle.kts b/subprojects/store-query/build.gradle.kts new file mode 100644 index 00000000..4d8e2605 --- /dev/null +++ b/subprojects/store-query/build.gradle.kts | |||
@@ -0,0 +1,15 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
7 | plugins { | ||
8 | id("tools.refinery.gradle.java-library") | ||
9 | id("tools.refinery.gradle.java-test-fixtures") | ||
10 | } | ||
11 | |||
12 | dependencies { | ||
13 | api(project(":refinery-store")) | ||
14 | testFixturesApi(libs.hamcrest) | ||
15 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/AnyResultSet.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/AnyResultSet.java index 6d411212..f29bb278 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/AnyResultSet.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/AnyResultSet.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query; | 6 | package tools.refinery.store.query; |
2 | 7 | ||
3 | import tools.refinery.store.query.dnf.AnyQuery; | 8 | import tools.refinery.store.query.dnf.AnyQuery; |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/Constraint.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/Constraint.java index cec4c19f..916fb35c 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/Constraint.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/Constraint.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query; | 6 | package tools.refinery.store.query; |
2 | 7 | ||
3 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | 8 | import tools.refinery.store.query.equality.LiteralEqualityHelper; |
@@ -9,25 +14,27 @@ import java.util.List; | |||
9 | public interface Constraint { | 14 | public interface Constraint { |
10 | String name(); | 15 | String name(); |
11 | 16 | ||
12 | List<Sort> getSorts(); | 17 | List<Parameter> getParameters(); |
13 | 18 | ||
14 | default int arity() { | 19 | default int arity() { |
15 | return getSorts().size(); | 20 | return getParameters().size(); |
16 | } | 21 | } |
17 | 22 | ||
18 | default boolean invalidIndex(int i) { | 23 | default boolean invalidIndex(int i) { |
19 | return i < 0 || i >= arity(); | 24 | return i < 0 || i >= arity(); |
20 | } | 25 | } |
21 | 26 | ||
22 | default LiteralReduction getReduction() { | 27 | default Reduction getReduction() { |
23 | return LiteralReduction.NOT_REDUCIBLE; | 28 | return Reduction.NOT_REDUCIBLE; |
24 | } | 29 | } |
25 | 30 | ||
26 | default boolean equals(LiteralEqualityHelper helper, Constraint other) { | 31 | default boolean equals(LiteralEqualityHelper helper, Constraint other) { |
27 | return equals(other); | 32 | return equals(other); |
28 | } | 33 | } |
29 | 34 | ||
30 | String toReferenceString(); | 35 | default String toReferenceString() { |
36 | return name(); | ||
37 | } | ||
31 | 38 | ||
32 | default CallLiteral call(CallPolarity polarity, List<Variable> arguments) { | 39 | default CallLiteral call(CallPolarity polarity, List<Variable> arguments) { |
33 | return new CallLiteral(polarity, this, arguments); | 40 | return new CallLiteral(polarity, this, arguments); |
@@ -53,13 +60,13 @@ public interface Constraint { | |||
53 | return count(List.of(arguments)); | 60 | return count(List.of(arguments)); |
54 | } | 61 | } |
55 | 62 | ||
56 | default <R, T> AssignedValue<R> aggregate(DataVariable<T> inputVariable, Aggregator<R, T> aggregator, | 63 | default <R, T> AssignedValue<R> aggregateBy(DataVariable<T> inputVariable, Aggregator<R, T> aggregator, |
57 | List<Variable> arguments) { | 64 | List<Variable> arguments) { |
58 | return targetVariable -> new AggregationLiteral<>(targetVariable, aggregator, inputVariable, this, arguments); | 65 | return targetVariable -> new AggregationLiteral<>(targetVariable, aggregator, inputVariable, this, arguments); |
59 | } | 66 | } |
60 | 67 | ||
61 | default <R, T> AssignedValue<R> aggregate(DataVariable<T> inputVariable, Aggregator<R, T> aggregator, | 68 | default <R, T> AssignedValue<R> aggregateBy(DataVariable<T> inputVariable, Aggregator<R, T> aggregator, |
62 | Variable... arguments) { | 69 | Variable... arguments) { |
63 | return aggregate(inputVariable, aggregator, List.of(arguments)); | 70 | return aggregateBy(inputVariable, aggregator, List.of(arguments)); |
64 | } | 71 | } |
65 | } | 72 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/EmptyResultSet.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/EmptyResultSet.java index 9af73bdd..5361f645 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/EmptyResultSet.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/EmptyResultSet.java | |||
@@ -1,9 +1,14 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query; | 6 | package tools.refinery.store.query; |
2 | 7 | ||
3 | import tools.refinery.store.map.Cursor; | 8 | import tools.refinery.store.map.Cursor; |
4 | import tools.refinery.store.map.Cursors; | 9 | import tools.refinery.store.map.Cursors; |
5 | import tools.refinery.store.query.dnf.Query; | 10 | import tools.refinery.store.query.dnf.Query; |
6 | import tools.refinery.store.tuple.TupleLike; | 11 | import tools.refinery.store.tuple.Tuple; |
7 | 12 | ||
8 | public record EmptyResultSet<T>(ModelQueryAdapter adapter, Query<T> query) implements ResultSet<T> { | 13 | public record EmptyResultSet<T>(ModelQueryAdapter adapter, Query<T> query) implements ResultSet<T> { |
9 | @Override | 14 | @Override |
@@ -17,13 +22,12 @@ public record EmptyResultSet<T>(ModelQueryAdapter adapter, Query<T> query) imple | |||
17 | } | 22 | } |
18 | 23 | ||
19 | @Override | 24 | @Override |
20 | public T get(TupleLike parameters) { | 25 | public T get(Tuple parameters) { |
21 | return query.defaultValue(); | 26 | return query.defaultValue(); |
22 | } | 27 | } |
23 | 28 | ||
24 | |||
25 | @Override | 29 | @Override |
26 | public Cursor<TupleLike, T> getAll() { | 30 | public Cursor<Tuple, T> getAll() { |
27 | return Cursors.empty(); | 31 | return Cursors.empty(); |
28 | } | 32 | } |
29 | 33 | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/ModelQuery.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/ModelQuery.java deleted file mode 100644 index 6a1aeabb..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/ModelQuery.java +++ /dev/null | |||
@@ -1,11 +0,0 @@ | |||
1 | package tools.refinery.store.query; | ||
2 | |||
3 | import tools.refinery.store.adapter.ModelAdapterType; | ||
4 | |||
5 | public final class ModelQuery extends ModelAdapterType<ModelQueryAdapter, ModelQueryStoreAdapter, ModelQueryBuilder> { | ||
6 | public static final ModelQuery ADAPTER = new ModelQuery(); | ||
7 | |||
8 | private ModelQuery() { | ||
9 | super(ModelQueryAdapter.class, ModelQueryStoreAdapter.class, ModelQueryBuilder.class); | ||
10 | } | ||
11 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/ModelQueryAdapter.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/ModelQueryAdapter.java index 2e30fec4..ae3bbcbb 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/ModelQueryAdapter.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/ModelQueryAdapter.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query; | 6 | package tools.refinery.store.query; |
2 | 7 | ||
3 | import tools.refinery.store.adapter.ModelAdapter; | 8 | import tools.refinery.store.adapter.ModelAdapter; |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/ModelQueryBuilder.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/ModelQueryBuilder.java index 4fdc9210..c62a95b5 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/ModelQueryBuilder.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/ModelQueryBuilder.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query; | 6 | package tools.refinery.store.query; |
2 | 7 | ||
3 | import tools.refinery.store.adapter.ModelAdapterBuilder; | 8 | import tools.refinery.store.adapter.ModelAdapterBuilder; |
@@ -21,5 +26,5 @@ public interface ModelQueryBuilder extends ModelAdapterBuilder { | |||
21 | ModelQueryBuilder query(AnyQuery query); | 26 | ModelQueryBuilder query(AnyQuery query); |
22 | 27 | ||
23 | @Override | 28 | @Override |
24 | ModelQueryStoreAdapter createStoreAdapter(ModelStore store); | 29 | ModelQueryStoreAdapter build(ModelStore store); |
25 | } | 30 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/ModelQueryStoreAdapter.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/ModelQueryStoreAdapter.java index 514e582b..f0a950a6 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/ModelQueryStoreAdapter.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/ModelQueryStoreAdapter.java | |||
@@ -1,14 +1,19 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query; | 6 | package tools.refinery.store.query; |
2 | 7 | ||
3 | import tools.refinery.store.adapter.ModelStoreAdapter; | 8 | import tools.refinery.store.adapter.ModelStoreAdapter; |
4 | import tools.refinery.store.model.Model; | 9 | import tools.refinery.store.model.Model; |
5 | import tools.refinery.store.query.dnf.AnyQuery; | 10 | import tools.refinery.store.query.dnf.AnyQuery; |
6 | import tools.refinery.store.query.view.AnyRelationView; | 11 | import tools.refinery.store.query.view.AnySymbolView; |
7 | 12 | ||
8 | import java.util.Collection; | 13 | import java.util.Collection; |
9 | 14 | ||
10 | public interface ModelQueryStoreAdapter extends ModelStoreAdapter { | 15 | public interface ModelQueryStoreAdapter extends ModelStoreAdapter { |
11 | Collection<AnyRelationView> getRelationViews(); | 16 | Collection<AnySymbolView> getSymbolViews(); |
12 | 17 | ||
13 | Collection<AnyQuery> getQueries(); | 18 | Collection<AnyQuery> getQueries(); |
14 | 19 | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/LiteralReduction.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/Reduction.java index 146089f6..82c52b04 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/LiteralReduction.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/Reduction.java | |||
@@ -1,6 +1,11 @@ | |||
1 | package tools.refinery.store.query.literal; | 1 | /* |
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query; | ||
2 | 7 | ||
3 | public enum LiteralReduction { | 8 | public enum Reduction { |
4 | /** | 9 | /** |
5 | * Signifies that a literal should be preserved in the clause. | 10 | * Signifies that a literal should be preserved in the clause. |
6 | */ | 11 | */ |
@@ -16,7 +21,7 @@ public enum LiteralReduction { | |||
16 | */ | 21 | */ |
17 | ALWAYS_FALSE; | 22 | ALWAYS_FALSE; |
18 | 23 | ||
19 | public LiteralReduction negate() { | 24 | public Reduction negate() { |
20 | return switch (this) { | 25 | return switch (this) { |
21 | case NOT_REDUCIBLE -> NOT_REDUCIBLE; | 26 | case NOT_REDUCIBLE -> NOT_REDUCIBLE; |
22 | case ALWAYS_TRUE -> ALWAYS_FALSE; | 27 | case ALWAYS_TRUE -> ALWAYS_FALSE; |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/ResultSet.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/ResultSet.java index 3f6bc06f..9ab83172 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/ResultSet.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/ResultSet.java | |||
@@ -1,13 +1,18 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query; | 6 | package tools.refinery.store.query; |
2 | 7 | ||
3 | import tools.refinery.store.map.Cursor; | 8 | import tools.refinery.store.map.Cursor; |
4 | import tools.refinery.store.query.dnf.Query; | 9 | import tools.refinery.store.query.dnf.Query; |
5 | import tools.refinery.store.tuple.TupleLike; | 10 | import tools.refinery.store.tuple.Tuple; |
6 | 11 | ||
7 | public non-sealed interface ResultSet<T> extends AnyResultSet { | 12 | public non-sealed interface ResultSet<T> extends AnyResultSet { |
8 | Query<T> getQuery(); | 13 | Query<T> getQuery(); |
9 | 14 | ||
10 | T get(TupleLike parameters); | 15 | T get(Tuple parameters); |
11 | 16 | ||
12 | Cursor<TupleLike, T> getAll(); | 17 | Cursor<Tuple, T> getAll(); |
13 | } | 18 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/AbstractQueryBuilder.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/AbstractQueryBuilder.java new file mode 100644 index 00000000..2a3e3ce0 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/AbstractQueryBuilder.java | |||
@@ -0,0 +1,175 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf; | ||
7 | |||
8 | import tools.refinery.store.query.dnf.callback.*; | ||
9 | import tools.refinery.store.query.literal.Literal; | ||
10 | import tools.refinery.store.query.term.NodeVariable; | ||
11 | import tools.refinery.store.query.term.ParameterDirection; | ||
12 | import tools.refinery.store.query.term.Variable; | ||
13 | |||
14 | import java.util.Collection; | ||
15 | import java.util.List; | ||
16 | import java.util.Set; | ||
17 | |||
18 | public abstract class AbstractQueryBuilder<T extends AbstractQueryBuilder<T>> { | ||
19 | protected final DnfBuilder dnfBuilder; | ||
20 | |||
21 | protected AbstractQueryBuilder(DnfBuilder dnfBuilder) { | ||
22 | this.dnfBuilder = dnfBuilder; | ||
23 | } | ||
24 | |||
25 | protected abstract T self(); | ||
26 | |||
27 | public NodeVariable parameter() { | ||
28 | return dnfBuilder.parameter(); | ||
29 | } | ||
30 | |||
31 | public NodeVariable parameter(String name) { | ||
32 | return dnfBuilder.parameter(name); | ||
33 | } | ||
34 | |||
35 | public NodeVariable parameter(ParameterDirection direction) { | ||
36 | return dnfBuilder.parameter(direction); | ||
37 | } | ||
38 | |||
39 | public NodeVariable parameter(String name, ParameterDirection direction) { | ||
40 | return dnfBuilder.parameter(name, direction); | ||
41 | } | ||
42 | |||
43 | public T parameter(NodeVariable variable) { | ||
44 | dnfBuilder.parameter(variable); | ||
45 | return self(); | ||
46 | } | ||
47 | |||
48 | public T parameter(NodeVariable variable, ParameterDirection direction) { | ||
49 | dnfBuilder.parameter(variable, direction); | ||
50 | return self(); | ||
51 | } | ||
52 | |||
53 | public T parameters(NodeVariable... variables) { | ||
54 | dnfBuilder.parameters(variables); | ||
55 | return self(); | ||
56 | } | ||
57 | |||
58 | public T parameters(List<NodeVariable> variables) { | ||
59 | dnfBuilder.parameters(variables); | ||
60 | return self(); | ||
61 | } | ||
62 | |||
63 | public T parameters(List<NodeVariable> variables, ParameterDirection direction) { | ||
64 | dnfBuilder.parameters(variables, direction); | ||
65 | return self(); | ||
66 | } | ||
67 | |||
68 | public T symbolicParameters(List<SymbolicParameter> parameters) { | ||
69 | dnfBuilder.symbolicParameters(parameters); | ||
70 | return self(); | ||
71 | } | ||
72 | |||
73 | public T functionalDependencies(Collection<FunctionalDependency<Variable>> functionalDependencies) { | ||
74 | dnfBuilder.functionalDependencies(functionalDependencies); | ||
75 | return self(); | ||
76 | } | ||
77 | |||
78 | public T functionalDependency(FunctionalDependency<Variable> functionalDependency) { | ||
79 | dnfBuilder.functionalDependency(functionalDependency); | ||
80 | return self(); | ||
81 | } | ||
82 | |||
83 | public T functionalDependency(Set<? extends Variable> forEach, Set<? extends Variable> unique) { | ||
84 | dnfBuilder.functionalDependency(forEach, unique); | ||
85 | return self(); | ||
86 | } | ||
87 | |||
88 | public T clause(ClauseCallback0 callback) { | ||
89 | dnfBuilder.clause(callback); | ||
90 | return self(); | ||
91 | } | ||
92 | |||
93 | public T clause(ClauseCallback1Data0 callback) { | ||
94 | dnfBuilder.clause(callback); | ||
95 | return self(); | ||
96 | } | ||
97 | |||
98 | public <U1> T clause(Class<U1> type1, ClauseCallback1Data1<U1> callback) { | ||
99 | dnfBuilder.clause(type1, callback); | ||
100 | return self(); | ||
101 | } | ||
102 | |||
103 | public T clause(ClauseCallback2Data0 callback) { | ||
104 | dnfBuilder.clause(callback); | ||
105 | return self(); | ||
106 | } | ||
107 | |||
108 | public <U1> T clause(Class<U1> type1, ClauseCallback2Data1<U1> callback) { | ||
109 | dnfBuilder.clause(type1, callback); | ||
110 | return self(); | ||
111 | } | ||
112 | |||
113 | public <U1, U2> T clause(Class<U1> type1, Class<U2> type2, ClauseCallback2Data2<U1, U2> callback) { | ||
114 | dnfBuilder.clause(type1, type2, callback); | ||
115 | return self(); | ||
116 | } | ||
117 | |||
118 | public T clause(ClauseCallback3Data0 callback) { | ||
119 | dnfBuilder.clause(callback); | ||
120 | return self(); | ||
121 | } | ||
122 | |||
123 | public <U1> T clause(Class<U1> type1, ClauseCallback3Data1<U1> callback) { | ||
124 | dnfBuilder.clause(type1, callback); | ||
125 | return self(); | ||
126 | } | ||
127 | |||
128 | public <U1, U2> T clause(Class<U1> type1, Class<U2> type2, ClauseCallback3Data2<U1, U2> callback) { | ||
129 | dnfBuilder.clause(type1, type2, callback); | ||
130 | return self(); | ||
131 | } | ||
132 | |||
133 | public <U1, U2, U3> T clause(Class<U1> type1, Class<U2> type2, Class<U3> type3, | ||
134 | ClauseCallback3Data3<U1, U2, U3> callback) { | ||
135 | dnfBuilder.clause(type1, type2, type3, callback); | ||
136 | return self(); | ||
137 | } | ||
138 | |||
139 | public T clause(ClauseCallback4Data0 callback) { | ||
140 | dnfBuilder.clause(callback); | ||
141 | return self(); | ||
142 | } | ||
143 | |||
144 | public <U1> T clause(Class<U1> type1, ClauseCallback4Data1<U1> callback) { | ||
145 | dnfBuilder.clause(type1, callback); | ||
146 | return self(); | ||
147 | } | ||
148 | |||
149 | public <U1, U2> T clause(Class<U1> type1, Class<U2> type2, ClauseCallback4Data2<U1, U2> callback) { | ||
150 | dnfBuilder.clause(type1, type2, callback); | ||
151 | return self(); | ||
152 | } | ||
153 | |||
154 | public <U1, U2, U3> T clause(Class<U1> type1, Class<U2> type2, Class<U3> type3, | ||
155 | ClauseCallback4Data3<U1, U2, U3> callback) { | ||
156 | dnfBuilder.clause(type1, type2, type3, callback); | ||
157 | return self(); | ||
158 | } | ||
159 | |||
160 | public <U1, U2, U3, U4> T clause(Class<U1> type1, Class<U2> type2, Class<U3> type3, Class<U4> type4, | ||
161 | ClauseCallback4Data4<U1, U2, U3, U4> callback) { | ||
162 | dnfBuilder.clause(type1, type2, type3, type4, callback); | ||
163 | return self(); | ||
164 | } | ||
165 | |||
166 | public T clause(Literal... literals) { | ||
167 | dnfBuilder.clause(literals); | ||
168 | return self(); | ||
169 | } | ||
170 | |||
171 | public T clause(Collection<? extends Literal> literals) { | ||
172 | dnfBuilder.clause(literals); | ||
173 | return self(); | ||
174 | } | ||
175 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/AnyQuery.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/AnyQuery.java index d0a2367f..5e28af68 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/AnyQuery.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/AnyQuery.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.dnf; | 6 | package tools.refinery.store.query.dnf; |
2 | 7 | ||
3 | public sealed interface AnyQuery permits Query { | 8 | public sealed interface AnyQuery permits Query { |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/ClausePostProcessor.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/ClausePostProcessor.java new file mode 100644 index 00000000..b5e7092b --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/ClausePostProcessor.java | |||
@@ -0,0 +1,324 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf; | ||
7 | |||
8 | import org.jetbrains.annotations.NotNull; | ||
9 | import tools.refinery.store.query.literal.BooleanLiteral; | ||
10 | import tools.refinery.store.query.literal.EquivalenceLiteral; | ||
11 | import tools.refinery.store.query.literal.Literal; | ||
12 | import tools.refinery.store.query.substitution.MapBasedSubstitution; | ||
13 | import tools.refinery.store.query.substitution.StatelessSubstitution; | ||
14 | import tools.refinery.store.query.substitution.Substitution; | ||
15 | import tools.refinery.store.query.term.NodeVariable; | ||
16 | import tools.refinery.store.query.term.ParameterDirection; | ||
17 | import tools.refinery.store.query.term.Variable; | ||
18 | |||
19 | import java.util.*; | ||
20 | import java.util.function.Function; | ||
21 | |||
22 | class ClausePostProcessor { | ||
23 | private final Map<Variable, ParameterInfo> parameters; | ||
24 | private final List<Literal> literals; | ||
25 | private final Map<NodeVariable, NodeVariable> representatives = new LinkedHashMap<>(); | ||
26 | private final Map<NodeVariable, Set<NodeVariable>> equivalencePartition = new HashMap<>(); | ||
27 | private List<Literal> substitutedLiterals; | ||
28 | private final Set<Variable> existentiallyQuantifiedVariables = new LinkedHashSet<>(); | ||
29 | private Set<Variable> positiveVariables; | ||
30 | private Map<Variable, Set<SortableLiteral>> variableToLiteralInputMap; | ||
31 | private PriorityQueue<SortableLiteral> literalsWithAllInputsBound; | ||
32 | private LinkedHashSet<Literal> topologicallySortedLiterals; | ||
33 | |||
34 | public ClausePostProcessor(Map<Variable, ParameterInfo> parameters, List<Literal> literals) { | ||
35 | this.parameters = parameters; | ||
36 | this.literals = literals; | ||
37 | } | ||
38 | |||
39 | public Result postProcessClause() { | ||
40 | mergeEquivalentNodeVariables(); | ||
41 | substitutedLiterals = new ArrayList<>(literals.size()); | ||
42 | keepParameterEquivalences(); | ||
43 | substituteLiterals(); | ||
44 | computeExistentiallyQuantifiedVariables(); | ||
45 | computePositiveVariables(); | ||
46 | validatePositiveRepresentatives(); | ||
47 | validatePrivateVariables(); | ||
48 | topologicallySortLiterals(); | ||
49 | var filteredLiterals = new ArrayList<Literal>(topologicallySortedLiterals.size()); | ||
50 | for (var literal : topologicallySortedLiterals) { | ||
51 | var reducedLiteral = literal.reduce(); | ||
52 | if (BooleanLiteral.FALSE.equals(reducedLiteral)) { | ||
53 | return ConstantResult.ALWAYS_FALSE; | ||
54 | } else if (!BooleanLiteral.TRUE.equals(reducedLiteral)) { | ||
55 | filteredLiterals.add(reducedLiteral); | ||
56 | } | ||
57 | } | ||
58 | if (filteredLiterals.isEmpty()) { | ||
59 | return ConstantResult.ALWAYS_TRUE; | ||
60 | } | ||
61 | var clause = new DnfClause(Collections.unmodifiableSet(positiveVariables), | ||
62 | Collections.unmodifiableList(filteredLiterals)); | ||
63 | return new ClauseResult(clause); | ||
64 | } | ||
65 | |||
66 | private void mergeEquivalentNodeVariables() { | ||
67 | for (var literal : literals) { | ||
68 | if (isPositiveEquivalence(literal)) { | ||
69 | var equivalenceLiteral = (EquivalenceLiteral) literal; | ||
70 | mergeVariables(equivalenceLiteral.left(), equivalenceLiteral.right()); | ||
71 | } | ||
72 | } | ||
73 | } | ||
74 | |||
75 | private static boolean isPositiveEquivalence(Literal literal) { | ||
76 | return literal instanceof EquivalenceLiteral equivalenceLiteral && equivalenceLiteral.positive(); | ||
77 | } | ||
78 | |||
79 | private void mergeVariables(NodeVariable left, NodeVariable right) { | ||
80 | var leftRepresentative = getRepresentative(left); | ||
81 | var rightRepresentative = getRepresentative(right); | ||
82 | var leftInfo = parameters.get(leftRepresentative); | ||
83 | var rightInfo = parameters.get(rightRepresentative); | ||
84 | if (leftInfo != null && (rightInfo == null || leftInfo.index() <= rightInfo.index())) { | ||
85 | // Prefer the variable occurring earlier in the parameter list as a representative. | ||
86 | doMergeVariables(leftRepresentative, rightRepresentative); | ||
87 | } else { | ||
88 | doMergeVariables(rightRepresentative, leftRepresentative); | ||
89 | } | ||
90 | } | ||
91 | |||
92 | private void doMergeVariables(NodeVariable parentRepresentative, NodeVariable newChildRepresentative) { | ||
93 | var parentSet = getEquivalentVariables(parentRepresentative); | ||
94 | var childSet = getEquivalentVariables(newChildRepresentative); | ||
95 | parentSet.addAll(childSet); | ||
96 | equivalencePartition.remove(newChildRepresentative); | ||
97 | for (var childEquivalentNodeVariable : childSet) { | ||
98 | representatives.put(childEquivalentNodeVariable, parentRepresentative); | ||
99 | } | ||
100 | } | ||
101 | |||
102 | private NodeVariable getRepresentative(NodeVariable variable) { | ||
103 | return representatives.computeIfAbsent(variable, Function.identity()); | ||
104 | } | ||
105 | |||
106 | private Set<NodeVariable> getEquivalentVariables(NodeVariable variable) { | ||
107 | var representative = getRepresentative(variable); | ||
108 | if (!representative.equals(variable)) { | ||
109 | throw new AssertionError("NodeVariable %s already has a representative %s" | ||
110 | .formatted(variable, representative)); | ||
111 | } | ||
112 | return equivalencePartition.computeIfAbsent(variable, key -> { | ||
113 | var set = new HashSet<NodeVariable>(1); | ||
114 | set.add(key); | ||
115 | return set; | ||
116 | }); | ||
117 | } | ||
118 | |||
119 | private void keepParameterEquivalences() { | ||
120 | for (var pair : representatives.entrySet()) { | ||
121 | var left = pair.getKey(); | ||
122 | var right = pair.getValue(); | ||
123 | if (!left.equals(right) && parameters.containsKey(left) && parameters.containsKey(right)) { | ||
124 | substitutedLiterals.add(left.isEquivalent(right)); | ||
125 | } | ||
126 | } | ||
127 | } | ||
128 | |||
129 | private void substituteLiterals() { | ||
130 | Substitution substitution; | ||
131 | if (representatives.isEmpty()) { | ||
132 | substitution = null; | ||
133 | } else { | ||
134 | substitution = new MapBasedSubstitution(Collections.unmodifiableMap(representatives), | ||
135 | StatelessSubstitution.IDENTITY); | ||
136 | } | ||
137 | for (var literal : literals) { | ||
138 | if (isPositiveEquivalence(literal)) { | ||
139 | // We already retained all equivalences that cannot be replaced with substitutions in | ||
140 | // {@link#keepParameterEquivalences()}. | ||
141 | continue; | ||
142 | } | ||
143 | var substitutedLiteral = substitution == null ? literal : literal.substitute(substitution); | ||
144 | substitutedLiterals.add(substitutedLiteral); | ||
145 | } | ||
146 | } | ||
147 | |||
148 | private void computeExistentiallyQuantifiedVariables() { | ||
149 | for (var literal : substitutedLiterals) { | ||
150 | for (var variable : literal.getOutputVariables()) { | ||
151 | boolean added = existentiallyQuantifiedVariables.add(variable); | ||
152 | if (!variable.isUnifiable()) { | ||
153 | var parameterInfo = parameters.get(variable); | ||
154 | if (parameterInfo != null && parameterInfo.direction() == ParameterDirection.IN) { | ||
155 | throw new IllegalArgumentException("Trying to bind %s parameter %s" | ||
156 | .formatted(ParameterDirection.IN, variable)); | ||
157 | } | ||
158 | if (!added) { | ||
159 | throw new IllegalArgumentException("Variable %s has multiple assigned values" | ||
160 | .formatted(variable)); | ||
161 | } | ||
162 | } | ||
163 | } | ||
164 | } | ||
165 | } | ||
166 | |||
167 | private void computePositiveVariables() { | ||
168 | positiveVariables = new LinkedHashSet<>(); | ||
169 | for (var pair : parameters.entrySet()) { | ||
170 | var variable = pair.getKey(); | ||
171 | if (pair.getValue().direction() == ParameterDirection.IN) { | ||
172 | // Inputs count as positive, because they are already bound when we evaluate literals. | ||
173 | positiveVariables.add(variable); | ||
174 | } else if (!existentiallyQuantifiedVariables.contains(variable)) { | ||
175 | throw new IllegalArgumentException("Unbound %s parameter %s" | ||
176 | .formatted(ParameterDirection.OUT, variable)); | ||
177 | } | ||
178 | } | ||
179 | positiveVariables.addAll(existentiallyQuantifiedVariables); | ||
180 | } | ||
181 | |||
182 | private void validatePositiveRepresentatives() { | ||
183 | for (var pair : equivalencePartition.entrySet()) { | ||
184 | var representative = pair.getKey(); | ||
185 | if (!positiveVariables.contains(representative)) { | ||
186 | var variableSet = pair.getValue(); | ||
187 | throw new IllegalArgumentException("Variables %s were merged by equivalence but are not bound" | ||
188 | .formatted(variableSet)); | ||
189 | } | ||
190 | } | ||
191 | } | ||
192 | |||
193 | private void validatePrivateVariables() { | ||
194 | var negativeVariablesMap = new HashMap<Variable, Literal>(); | ||
195 | for (var literal : substitutedLiterals) { | ||
196 | for (var variable : literal.getPrivateVariables(positiveVariables)) { | ||
197 | var oldLiteral = negativeVariablesMap.put(variable, literal); | ||
198 | if (oldLiteral != null) { | ||
199 | throw new IllegalArgumentException("Unbound variable %s appears in multiple literals %s and %s" | ||
200 | .formatted(variable, oldLiteral, literal)); | ||
201 | } | ||
202 | } | ||
203 | } | ||
204 | } | ||
205 | |||
206 | private void topologicallySortLiterals() { | ||
207 | topologicallySortedLiterals = new LinkedHashSet<>(substitutedLiterals.size()); | ||
208 | variableToLiteralInputMap = new HashMap<>(); | ||
209 | literalsWithAllInputsBound = new PriorityQueue<>(); | ||
210 | int size = substitutedLiterals.size(); | ||
211 | for (int i = 0; i < size; i++) { | ||
212 | var literal = substitutedLiterals.get(i); | ||
213 | var sortableLiteral = new SortableLiteral(i, literal); | ||
214 | sortableLiteral.enqueue(); | ||
215 | } | ||
216 | while (!literalsWithAllInputsBound.isEmpty()) { | ||
217 | var variable = literalsWithAllInputsBound.remove(); | ||
218 | variable.addToSortedLiterals(); | ||
219 | } | ||
220 | if (!variableToLiteralInputMap.isEmpty()) { | ||
221 | throw new IllegalArgumentException("Unbound input variables %s" | ||
222 | .formatted(variableToLiteralInputMap.keySet())); | ||
223 | } | ||
224 | } | ||
225 | |||
226 | private class SortableLiteral implements Comparable<SortableLiteral> { | ||
227 | private final int index; | ||
228 | private final Literal literal; | ||
229 | private final Set<Variable> remainingInputs; | ||
230 | |||
231 | private SortableLiteral(int index, Literal literal) { | ||
232 | this.index = index; | ||
233 | this.literal = literal; | ||
234 | remainingInputs = new HashSet<>(literal.getInputVariables(positiveVariables)); | ||
235 | for (var pair : parameters.entrySet()) { | ||
236 | if (pair.getValue().direction() == ParameterDirection.IN) { | ||
237 | remainingInputs.remove(pair.getKey()); | ||
238 | } | ||
239 | } | ||
240 | } | ||
241 | |||
242 | public void enqueue() { | ||
243 | if (allInputsBound()) { | ||
244 | addToAllInputsBoundQueue(); | ||
245 | } else { | ||
246 | addToVariableToLiteralInputMap(); | ||
247 | } | ||
248 | } | ||
249 | |||
250 | private void bindVariable(Variable input) { | ||
251 | if (!remainingInputs.remove(input)) { | ||
252 | throw new AssertionError("Already processed input %s of literal %s".formatted(input, literal)); | ||
253 | } | ||
254 | if (allInputsBound()) { | ||
255 | addToAllInputsBoundQueue(); | ||
256 | } | ||
257 | } | ||
258 | |||
259 | private boolean allInputsBound() { | ||
260 | return remainingInputs.isEmpty(); | ||
261 | } | ||
262 | |||
263 | private void addToVariableToLiteralInputMap() { | ||
264 | for (var inputVariable : remainingInputs) { | ||
265 | var literalSetForInput = variableToLiteralInputMap.computeIfAbsent( | ||
266 | inputVariable, key -> new HashSet<>()); | ||
267 | literalSetForInput.add(this); | ||
268 | } | ||
269 | } | ||
270 | |||
271 | private void addToAllInputsBoundQueue() { | ||
272 | literalsWithAllInputsBound.add(this); | ||
273 | } | ||
274 | |||
275 | public void addToSortedLiterals() { | ||
276 | if (!allInputsBound()) { | ||
277 | throw new AssertionError("Inputs %s of %s are not yet bound".formatted(remainingInputs, literal)); | ||
278 | } | ||
279 | // Add literal if we haven't yet added a duplicate of this literal. | ||
280 | topologicallySortedLiterals.add(literal); | ||
281 | for (var variable : literal.getOutputVariables()) { | ||
282 | var literalSetForInput = variableToLiteralInputMap.remove(variable); | ||
283 | if (literalSetForInput == null) { | ||
284 | continue; | ||
285 | } | ||
286 | for (var targetSortableLiteral : literalSetForInput) { | ||
287 | targetSortableLiteral.bindVariable(variable); | ||
288 | } | ||
289 | } | ||
290 | } | ||
291 | |||
292 | @Override | ||
293 | public int compareTo(@NotNull ClausePostProcessor.SortableLiteral other) { | ||
294 | return Integer.compare(index, other.index); | ||
295 | } | ||
296 | |||
297 | @Override | ||
298 | public boolean equals(Object o) { | ||
299 | if (this == o) return true; | ||
300 | if (o == null || getClass() != o.getClass()) return false; | ||
301 | SortableLiteral that = (SortableLiteral) o; | ||
302 | return index == that.index && Objects.equals(literal, that.literal); | ||
303 | } | ||
304 | |||
305 | @Override | ||
306 | public int hashCode() { | ||
307 | return Objects.hash(index, literal); | ||
308 | } | ||
309 | } | ||
310 | |||
311 | public sealed interface Result permits ClauseResult, ConstantResult { | ||
312 | } | ||
313 | |||
314 | public record ClauseResult(DnfClause clause) implements Result { | ||
315 | } | ||
316 | |||
317 | public enum ConstantResult implements Result { | ||
318 | ALWAYS_TRUE, | ||
319 | ALWAYS_FALSE | ||
320 | } | ||
321 | |||
322 | public record ParameterInfo(ParameterDirection direction, int index) { | ||
323 | } | ||
324 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/Dnf.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/Dnf.java index 1b7759c7..c5b51b81 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/Dnf.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/Dnf.java | |||
@@ -1,57 +1,61 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.dnf; | 6 | package tools.refinery.store.query.dnf; |
2 | 7 | ||
8 | import tools.refinery.store.query.Constraint; | ||
9 | import tools.refinery.store.query.Reduction; | ||
3 | import tools.refinery.store.query.equality.DnfEqualityChecker; | 10 | import tools.refinery.store.query.equality.DnfEqualityChecker; |
4 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | 11 | import tools.refinery.store.query.equality.LiteralEqualityHelper; |
5 | import tools.refinery.store.query.Constraint; | 12 | import tools.refinery.store.query.term.Parameter; |
6 | import tools.refinery.store.query.literal.LiteralReduction; | ||
7 | import tools.refinery.store.query.term.Sort; | ||
8 | import tools.refinery.store.query.term.Variable; | 13 | import tools.refinery.store.query.term.Variable; |
9 | 14 | ||
10 | import java.util.Collection; | 15 | import java.util.Collection; |
11 | import java.util.HashSet; | 16 | import java.util.Collections; |
12 | import java.util.List; | 17 | import java.util.List; |
13 | import java.util.Set; | 18 | import java.util.Set; |
19 | import java.util.function.Consumer; | ||
20 | import java.util.stream.Collectors; | ||
14 | 21 | ||
15 | public final class Dnf implements Constraint { | 22 | public final class Dnf implements Constraint { |
16 | private static final String INDENTATION = " "; | 23 | private static final String INDENTATION = " "; |
17 | 24 | ||
18 | private final String name; | 25 | private final String name; |
19 | |||
20 | private final String uniqueName; | 26 | private final String uniqueName; |
21 | 27 | private final List<SymbolicParameter> symbolicParameters; | |
22 | private final List<Variable> parameters; | ||
23 | |||
24 | private final List<FunctionalDependency<Variable>> functionalDependencies; | 28 | private final List<FunctionalDependency<Variable>> functionalDependencies; |
25 | |||
26 | private final List<DnfClause> clauses; | 29 | private final List<DnfClause> clauses; |
27 | 30 | ||
28 | Dnf(String name, List<Variable> parameters, List<FunctionalDependency<Variable>> functionalDependencies, | 31 | Dnf(String name, List<SymbolicParameter> symbolicParameters, |
29 | List<DnfClause> clauses) { | 32 | List<FunctionalDependency<Variable>> functionalDependencies, List<DnfClause> clauses) { |
30 | validateFunctionalDependencies(parameters, functionalDependencies); | 33 | validateFunctionalDependencies(symbolicParameters, functionalDependencies); |
31 | this.name = name; | 34 | this.name = name; |
32 | this.uniqueName = DnfUtils.generateUniqueName(name); | 35 | this.uniqueName = DnfUtils.generateUniqueName(name); |
33 | this.parameters = parameters; | 36 | this.symbolicParameters = symbolicParameters; |
34 | this.functionalDependencies = functionalDependencies; | 37 | this.functionalDependencies = functionalDependencies; |
35 | this.clauses = clauses; | 38 | this.clauses = clauses; |
36 | } | 39 | } |
37 | 40 | ||
38 | private static void validateFunctionalDependencies( | 41 | private static void validateFunctionalDependencies( |
39 | Collection<Variable> parameters, Collection<FunctionalDependency<Variable>> functionalDependencies) { | 42 | Collection<SymbolicParameter> symbolicParameters, |
40 | var parameterSet = new HashSet<>(parameters); | 43 | Collection<FunctionalDependency<Variable>> functionalDependencies) { |
44 | var parameterSet = symbolicParameters.stream().map(SymbolicParameter::getVariable).collect(Collectors.toSet()); | ||
41 | for (var functionalDependency : functionalDependencies) { | 45 | for (var functionalDependency : functionalDependencies) { |
42 | validateParameters(parameters, parameterSet, functionalDependency.forEach(), functionalDependency); | 46 | validateParameters(symbolicParameters, parameterSet, functionalDependency.forEach(), functionalDependency); |
43 | validateParameters(parameters, parameterSet, functionalDependency.unique(), functionalDependency); | 47 | validateParameters(symbolicParameters, parameterSet, functionalDependency.unique(), functionalDependency); |
44 | } | 48 | } |
45 | } | 49 | } |
46 | 50 | ||
47 | private static void validateParameters(Collection<Variable> parameters, Set<Variable> parameterSet, | 51 | private static void validateParameters(Collection<SymbolicParameter> symbolicParameters, |
48 | Collection<Variable> toValidate, | 52 | Set<Variable> parameterSet, Collection<Variable> toValidate, |
49 | FunctionalDependency<Variable> functionalDependency) { | 53 | FunctionalDependency<Variable> functionalDependency) { |
50 | for (var variable : toValidate) { | 54 | for (var variable : toValidate) { |
51 | if (!parameterSet.contains(variable)) { | 55 | if (!parameterSet.contains(variable)) { |
52 | throw new IllegalArgumentException( | 56 | throw new IllegalArgumentException( |
53 | "Variable %s of functional dependency %s does not appear in the parameter list %s" | 57 | "Variable %s of functional dependency %s does not appear in the parameter list %s" |
54 | .formatted(variable, functionalDependency, parameters)); | 58 | .formatted(variable, functionalDependency, symbolicParameters)); |
55 | } | 59 | } |
56 | } | 60 | } |
57 | } | 61 | } |
@@ -69,13 +73,12 @@ public final class Dnf implements Constraint { | |||
69 | return uniqueName; | 73 | return uniqueName; |
70 | } | 74 | } |
71 | 75 | ||
72 | public List<Variable> getParameters() { | 76 | public List<SymbolicParameter> getSymbolicParameters() { |
73 | return parameters; | 77 | return symbolicParameters; |
74 | } | 78 | } |
75 | 79 | ||
76 | @Override | 80 | public List<Parameter> getParameters() { |
77 | public List<Sort> getSorts() { | 81 | return Collections.unmodifiableList(symbolicParameters); |
78 | return parameters.stream().map(Variable::getSort).toList(); | ||
79 | } | 82 | } |
80 | 83 | ||
81 | public List<FunctionalDependency<Variable>> getFunctionalDependencies() { | 84 | public List<FunctionalDependency<Variable>> getFunctionalDependencies() { |
@@ -84,7 +87,7 @@ public final class Dnf implements Constraint { | |||
84 | 87 | ||
85 | @Override | 88 | @Override |
86 | public int arity() { | 89 | public int arity() { |
87 | return parameters.size(); | 90 | return symbolicParameters.size(); |
88 | } | 91 | } |
89 | 92 | ||
90 | public List<DnfClause> getClauses() { | 93 | public List<DnfClause> getClauses() { |
@@ -100,28 +103,34 @@ public final class Dnf implements Constraint { | |||
100 | } | 103 | } |
101 | 104 | ||
102 | @Override | 105 | @Override |
103 | public LiteralReduction getReduction() { | 106 | public Reduction getReduction() { |
104 | if (clauses.isEmpty()) { | 107 | if (clauses.isEmpty()) { |
105 | return LiteralReduction.ALWAYS_FALSE; | 108 | return Reduction.ALWAYS_FALSE; |
106 | } | 109 | } |
107 | for (var clause : clauses) { | 110 | for (var clause : clauses) { |
108 | if (clause.literals().isEmpty()) { | 111 | if (clause.literals().isEmpty()) { |
109 | return LiteralReduction.ALWAYS_TRUE; | 112 | return Reduction.ALWAYS_TRUE; |
110 | } | 113 | } |
111 | } | 114 | } |
112 | return LiteralReduction.NOT_REDUCIBLE; | 115 | return Reduction.NOT_REDUCIBLE; |
113 | } | 116 | } |
114 | 117 | ||
115 | public boolean equalsWithSubstitution(DnfEqualityChecker callEqualityChecker, Dnf other) { | 118 | public boolean equalsWithSubstitution(DnfEqualityChecker callEqualityChecker, Dnf other) { |
116 | if (arity() != other.arity()) { | 119 | if (arity() != other.arity()) { |
117 | return false; | 120 | return false; |
118 | } | 121 | } |
122 | for (int i = 0; i < arity(); i++) { | ||
123 | if (!symbolicParameters.get(i).getDirection().equals(other.getSymbolicParameters().get(i).getDirection())) { | ||
124 | return false; | ||
125 | } | ||
126 | } | ||
119 | int numClauses = clauses.size(); | 127 | int numClauses = clauses.size(); |
120 | if (numClauses != other.clauses.size()) { | 128 | if (numClauses != other.clauses.size()) { |
121 | return false; | 129 | return false; |
122 | } | 130 | } |
123 | for (int i = 0; i < numClauses; i++) { | 131 | for (int i = 0; i < numClauses; i++) { |
124 | var literalEqualityHelper = new LiteralEqualityHelper(callEqualityChecker, parameters, other.parameters); | 132 | var literalEqualityHelper = new LiteralEqualityHelper(callEqualityChecker, symbolicParameters, |
133 | other.symbolicParameters); | ||
125 | if (!clauses.get(i).equalsWithSubstitution(literalEqualityHelper, other.clauses.get(i))) { | 134 | if (!clauses.get(i).equalsWithSubstitution(literalEqualityHelper, other.clauses.get(i))) { |
126 | return false; | 135 | return false; |
127 | } | 136 | } |
@@ -139,18 +148,18 @@ public final class Dnf implements Constraint { | |||
139 | 148 | ||
140 | @Override | 149 | @Override |
141 | public String toString() { | 150 | public String toString() { |
142 | return "%s/%d".formatted(name, arity()); | 151 | return "%s/%d".formatted(name(), arity()); |
143 | } | 152 | } |
144 | 153 | ||
145 | @Override | 154 | @Override |
146 | public String toReferenceString() { | 155 | public String toReferenceString() { |
147 | return "@Dnf " + name; | 156 | return "@Dnf " + name(); |
148 | } | 157 | } |
149 | 158 | ||
150 | public String toDefinitionString() { | 159 | public String toDefinitionString() { |
151 | var builder = new StringBuilder(); | 160 | var builder = new StringBuilder(); |
152 | builder.append("pred ").append(name()).append("("); | 161 | builder.append("pred ").append(name()).append("("); |
153 | var parameterIterator = parameters.iterator(); | 162 | var parameterIterator = symbolicParameters.iterator(); |
154 | if (parameterIterator.hasNext()) { | 163 | if (parameterIterator.hasNext()) { |
155 | builder.append(parameterIterator.next()); | 164 | builder.append(parameterIterator.next()); |
156 | while (parameterIterator.hasNext()) { | 165 | while (parameterIterator.hasNext()) { |
@@ -191,4 +200,14 @@ public final class Dnf implements Constraint { | |||
191 | public static DnfBuilder builder(String name) { | 200 | public static DnfBuilder builder(String name) { |
192 | return new DnfBuilder(name); | 201 | return new DnfBuilder(name); |
193 | } | 202 | } |
203 | |||
204 | public static Dnf of(Consumer<DnfBuilder> callback) { | ||
205 | return of(null, callback); | ||
206 | } | ||
207 | |||
208 | public static Dnf of(String name, Consumer<DnfBuilder> callback) { | ||
209 | var builder = builder(name); | ||
210 | callback.accept(builder); | ||
211 | return builder.build(); | ||
212 | } | ||
194 | } | 213 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/DnfBuilder.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/DnfBuilder.java index aad5a85f..8e38ca6b 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/DnfBuilder.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/DnfBuilder.java | |||
@@ -1,7 +1,15 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.dnf; | 6 | package tools.refinery.store.query.dnf; |
2 | 7 | ||
8 | import tools.refinery.store.query.dnf.callback.*; | ||
3 | import tools.refinery.store.query.literal.Literal; | 9 | import tools.refinery.store.query.literal.Literal; |
4 | import tools.refinery.store.query.term.DataVariable; | 10 | import tools.refinery.store.query.term.DataVariable; |
11 | import tools.refinery.store.query.term.NodeVariable; | ||
12 | import tools.refinery.store.query.term.ParameterDirection; | ||
5 | import tools.refinery.store.query.term.Variable; | 13 | import tools.refinery.store.query.term.Variable; |
6 | 14 | ||
7 | import java.util.*; | 15 | import java.util.*; |
@@ -9,23 +17,57 @@ import java.util.*; | |||
9 | @SuppressWarnings("UnusedReturnValue") | 17 | @SuppressWarnings("UnusedReturnValue") |
10 | public final class DnfBuilder { | 18 | public final class DnfBuilder { |
11 | private final String name; | 19 | private final String name; |
12 | 20 | private final Set<Variable> parameterVariables = new LinkedHashSet<>(); | |
13 | private final List<Variable> parameters = new ArrayList<>(); | 21 | private final List<SymbolicParameter> parameters = new ArrayList<>(); |
14 | |||
15 | private final List<FunctionalDependency<Variable>> functionalDependencies = new ArrayList<>(); | 22 | private final List<FunctionalDependency<Variable>> functionalDependencies = new ArrayList<>(); |
16 | |||
17 | private final List<List<Literal>> clauses = new ArrayList<>(); | 23 | private final List<List<Literal>> clauses = new ArrayList<>(); |
18 | 24 | ||
19 | DnfBuilder(String name) { | 25 | DnfBuilder(String name) { |
20 | this.name = name; | 26 | this.name = name; |
21 | } | 27 | } |
22 | 28 | ||
29 | public NodeVariable parameter() { | ||
30 | return parameter((String) null); | ||
31 | } | ||
32 | |||
33 | public NodeVariable parameter(String name) { | ||
34 | return parameter(name, ParameterDirection.OUT); | ||
35 | } | ||
36 | |||
37 | public NodeVariable parameter(ParameterDirection direction) { | ||
38 | return parameter((String) null, direction); | ||
39 | } | ||
40 | |||
41 | public NodeVariable parameter(String name, ParameterDirection direction) { | ||
42 | var variable = Variable.of(name); | ||
43 | parameter(variable, direction); | ||
44 | return variable; | ||
45 | } | ||
46 | |||
47 | public <T> DataVariable<T> parameter(Class<T> type) { | ||
48 | return parameter(null, type); | ||
49 | } | ||
50 | |||
51 | public <T> DataVariable<T> parameter(String name, Class<T> type) { | ||
52 | return parameter(name, type, ParameterDirection.OUT); | ||
53 | } | ||
54 | |||
55 | public <T> DataVariable<T> parameter(Class<T> type, ParameterDirection direction) { | ||
56 | return parameter(null, type, direction); | ||
57 | } | ||
58 | |||
59 | public <T> DataVariable<T> parameter(String name, Class<T> type, ParameterDirection direction) { | ||
60 | var variable = Variable.of(name, type); | ||
61 | parameter(variable, direction); | ||
62 | return variable; | ||
63 | } | ||
64 | |||
23 | public DnfBuilder parameter(Variable variable) { | 65 | public DnfBuilder parameter(Variable variable) { |
24 | if (parameters.contains(variable)) { | 66 | return parameter(variable, ParameterDirection.OUT); |
25 | throw new IllegalArgumentException("Duplicate parameter: " + variable); | 67 | } |
26 | } | 68 | |
27 | parameters.add(variable); | 69 | public DnfBuilder parameter(Variable variable, ParameterDirection direction) { |
28 | return this; | 70 | return symbolicParameter(new SymbolicParameter(variable, direction)); |
29 | } | 71 | } |
30 | 72 | ||
31 | public DnfBuilder parameters(Variable... variables) { | 73 | public DnfBuilder parameters(Variable... variables) { |
@@ -33,7 +75,34 @@ public final class DnfBuilder { | |||
33 | } | 75 | } |
34 | 76 | ||
35 | public DnfBuilder parameters(Collection<? extends Variable> variables) { | 77 | public DnfBuilder parameters(Collection<? extends Variable> variables) { |
36 | parameters.addAll(variables); | 78 | return parameters(variables, ParameterDirection.OUT); |
79 | } | ||
80 | |||
81 | public DnfBuilder parameters(Collection<? extends Variable> variables, ParameterDirection direction) { | ||
82 | for (var variable : variables) { | ||
83 | parameter(variable, direction); | ||
84 | } | ||
85 | return this; | ||
86 | } | ||
87 | |||
88 | public DnfBuilder symbolicParameter(SymbolicParameter symbolicParameter) { | ||
89 | var variable = symbolicParameter.getVariable(); | ||
90 | if (!parameterVariables.add(variable)) { | ||
91 | throw new IllegalArgumentException("Variable %s is already on the parameter list %s" | ||
92 | .formatted(variable, parameters)); | ||
93 | } | ||
94 | parameters.add(symbolicParameter); | ||
95 | return this; | ||
96 | } | ||
97 | |||
98 | public DnfBuilder symbolicParameters(SymbolicParameter... symbolicParameters) { | ||
99 | return symbolicParameters(List.of(symbolicParameters)); | ||
100 | } | ||
101 | |||
102 | public DnfBuilder symbolicParameters(Collection<SymbolicParameter> symbolicParameters) { | ||
103 | for (var symbolicParameter : symbolicParameters) { | ||
104 | symbolicParameter(symbolicParameter); | ||
105 | } | ||
37 | return this; | 106 | return this; |
38 | } | 107 | } |
39 | 108 | ||
@@ -51,33 +120,91 @@ public final class DnfBuilder { | |||
51 | return functionalDependency(new FunctionalDependency<>(Set.copyOf(forEach), Set.copyOf(unique))); | 120 | return functionalDependency(new FunctionalDependency<>(Set.copyOf(forEach), Set.copyOf(unique))); |
52 | } | 121 | } |
53 | 122 | ||
123 | public DnfBuilder clause(ClauseCallback0 callback) { | ||
124 | return clause(callback.toLiterals()); | ||
125 | } | ||
126 | |||
127 | public DnfBuilder clause(ClauseCallback1Data0 callback) { | ||
128 | return clause(callback.toLiterals(Variable.of("v1"))); | ||
129 | } | ||
130 | |||
131 | public <T> DnfBuilder clause(Class<T> type1, ClauseCallback1Data1<T> callback) { | ||
132 | return clause(callback.toLiterals(Variable.of("v1", type1))); | ||
133 | } | ||
134 | |||
135 | public DnfBuilder clause(ClauseCallback2Data0 callback) { | ||
136 | return clause(callback.toLiterals(Variable.of("v1"), Variable.of("v2"))); | ||
137 | } | ||
138 | |||
139 | public <T> DnfBuilder clause(Class<T> type1, ClauseCallback2Data1<T> callback) { | ||
140 | return clause(callback.toLiterals(Variable.of("v1"), Variable.of("d1", type1))); | ||
141 | } | ||
142 | |||
143 | public <T1, T2> DnfBuilder clause(Class<T1> type1, Class<T2> type2, ClauseCallback2Data2<T1, T2> callback) { | ||
144 | return clause(callback.toLiterals(Variable.of("d1", type1), Variable.of("d2", type2))); | ||
145 | } | ||
146 | |||
147 | public DnfBuilder clause(ClauseCallback3Data0 callback) { | ||
148 | return clause(callback.toLiterals(Variable.of("v1"), Variable.of("v2"), Variable.of("v3"))); | ||
149 | } | ||
150 | |||
151 | public <T> DnfBuilder clause(Class<T> type1, ClauseCallback3Data1<T> callback) { | ||
152 | return clause(callback.toLiterals(Variable.of("v1"), Variable.of("v2"), Variable.of("d1", type1))); | ||
153 | } | ||
154 | |||
155 | public <T1, T2> DnfBuilder clause(Class<T1> type1, Class<T2> type2, ClauseCallback3Data2<T1, T2> callback) { | ||
156 | return clause(callback.toLiterals(Variable.of("v1"), Variable.of("d1", type1), Variable.of("d2", type2))); | ||
157 | } | ||
158 | |||
159 | public <T1, T2, T3> DnfBuilder clause(Class<T1> type1, Class<T2> type2, Class<T3> type3, | ||
160 | ClauseCallback3Data3<T1, T2, T3> callback) { | ||
161 | return clause(callback.toLiterals(Variable.of("d1", type1), Variable.of("d2", type2), | ||
162 | Variable.of("d3", type3))); | ||
163 | } | ||
164 | |||
165 | public DnfBuilder clause(ClauseCallback4Data0 callback) { | ||
166 | return clause(callback.toLiterals(Variable.of("v1"), Variable.of("v2"), Variable.of("v3"), Variable.of("v4"))); | ||
167 | } | ||
168 | |||
169 | public <T> DnfBuilder clause(Class<T> type1, ClauseCallback4Data1<T> callback) { | ||
170 | return clause(callback.toLiterals(Variable.of("v1"), Variable.of("v2"), Variable.of("v3"), Variable.of("d1", | ||
171 | type1))); | ||
172 | } | ||
173 | |||
174 | public <T1, T2> DnfBuilder clause(Class<T1> type1, Class<T2> type2, ClauseCallback4Data2<T1, T2> callback) { | ||
175 | return clause(callback.toLiterals(Variable.of("v1"), Variable.of("v2"), Variable.of("d1", type1), | ||
176 | Variable.of("d2", type2))); | ||
177 | } | ||
178 | |||
179 | public <T1, T2, T3> DnfBuilder clause(Class<T1> type1, Class<T2> type2, Class<T3> type3, | ||
180 | ClauseCallback4Data3<T1, T2, T3> callback) { | ||
181 | return clause(callback.toLiterals(Variable.of("v1"), Variable.of("d1", type1), Variable.of("d2", type2), | ||
182 | Variable.of("d3", type3))); | ||
183 | } | ||
184 | |||
185 | public <T1, T2, T3, T4> DnfBuilder clause(Class<T1> type1, Class<T2> type2, Class<T3> type3, Class<T4> type4, | ||
186 | ClauseCallback4Data4<T1, T2, T3, T4> callback) { | ||
187 | return clause(callback.toLiterals(Variable.of("d1", type1), Variable.of("d2", type2), | ||
188 | Variable.of("d3", type3), Variable.of("d4", type4))); | ||
189 | } | ||
190 | |||
54 | public DnfBuilder clause(Literal... literals) { | 191 | public DnfBuilder clause(Literal... literals) { |
55 | clause(List.of(literals)); | 192 | clause(List.of(literals)); |
56 | return this; | 193 | return this; |
57 | } | 194 | } |
58 | 195 | ||
59 | public DnfBuilder clause(Collection<? extends Literal> literals) { | 196 | public DnfBuilder clause(Collection<? extends Literal> literals) { |
60 | // Remove duplicates by using a hashed data structure. | 197 | clauses.add(List.copyOf(literals)); |
61 | var filteredLiterals = new LinkedHashSet<Literal>(literals.size()); | ||
62 | for (var literal : literals) { | ||
63 | var reduction = literal.getReduction(); | ||
64 | switch (reduction) { | ||
65 | case NOT_REDUCIBLE -> filteredLiterals.add(literal); | ||
66 | case ALWAYS_TRUE -> { | ||
67 | // Literals reducible to {@code true} can be omitted, because the model is always assumed to have at | ||
68 | // least on object. | ||
69 | } | ||
70 | case ALWAYS_FALSE -> { | ||
71 | // Clauses with {@code false} literals can be omitted entirely. | ||
72 | return this; | ||
73 | } | ||
74 | default -> throw new IllegalArgumentException("Invalid reduction: " + reduction); | ||
75 | } | ||
76 | } | ||
77 | clauses.add(List.copyOf(filteredLiterals)); | ||
78 | return this; | 198 | return this; |
79 | } | 199 | } |
80 | 200 | ||
201 | <T> void output(DataVariable<T> outputVariable) { | ||
202 | // Copy parameter variables to exclude the newly added {@code outputVariable}. | ||
203 | var fromParameters = Set.copyOf(parameterVariables); | ||
204 | parameter(outputVariable, ParameterDirection.OUT); | ||
205 | functionalDependency(fromParameters, Set.of(outputVariable)); | ||
206 | } | ||
207 | |||
81 | public Dnf build() { | 208 | public Dnf build() { |
82 | var postProcessedClauses = postProcessClauses(); | 209 | var postProcessedClauses = postProcessClauses(); |
83 | return new Dnf(name, Collections.unmodifiableList(parameters), | 210 | return new Dnf(name, Collections.unmodifiableList(parameters), |
@@ -85,26 +212,51 @@ public final class DnfBuilder { | |||
85 | Collections.unmodifiableList(postProcessedClauses)); | 212 | Collections.unmodifiableList(postProcessedClauses)); |
86 | } | 213 | } |
87 | 214 | ||
88 | <T> void output(DataVariable<T> outputVariable) { | ||
89 | functionalDependency(Set.copyOf(parameters), Set.of(outputVariable)); | ||
90 | parameter(outputVariable); | ||
91 | } | ||
92 | |||
93 | private List<DnfClause> postProcessClauses() { | 215 | private List<DnfClause> postProcessClauses() { |
216 | var parameterInfoMap = getParameterInfoMap(); | ||
94 | var postProcessedClauses = new ArrayList<DnfClause>(clauses.size()); | 217 | var postProcessedClauses = new ArrayList<DnfClause>(clauses.size()); |
95 | for (var literals : clauses) { | 218 | for (var literals : clauses) { |
96 | if (literals.isEmpty()) { | 219 | var postProcessor = new ClausePostProcessor(parameterInfoMap, literals); |
97 | // Predicate will always match, the other clauses are irrelevant. | 220 | var result = postProcessor.postProcessClause(); |
98 | return List.of(new DnfClause(Set.of(), List.of())); | 221 | if (result instanceof ClausePostProcessor.ClauseResult clauseResult) { |
99 | } | 222 | postProcessedClauses.add(clauseResult.clause()); |
100 | var variables = new HashSet<Variable>(); | 223 | } else if (result instanceof ClausePostProcessor.ConstantResult constantResult) { |
101 | for (var literal : literals) { | 224 | switch (constantResult) { |
102 | variables.addAll(literal.getBoundVariables()); | 225 | case ALWAYS_TRUE -> { |
226 | var inputVariables = getInputVariables(); | ||
227 | return List.of(new DnfClause(inputVariables, List.of())); | ||
228 | } | ||
229 | case ALWAYS_FALSE -> { | ||
230 | // Skip this clause because it can never match. | ||
231 | } | ||
232 | default -> throw new IllegalStateException("Unexpected ClausePostProcessor.ConstantResult: " + | ||
233 | constantResult); | ||
234 | } | ||
235 | } else { | ||
236 | throw new IllegalStateException("Unexpected ClausePostProcessor.Result: " + result); | ||
103 | } | 237 | } |
104 | parameters.forEach(variables::remove); | ||
105 | postProcessedClauses.add(new DnfClause(Collections.unmodifiableSet(variables), | ||
106 | Collections.unmodifiableList(literals))); | ||
107 | } | 238 | } |
108 | return postProcessedClauses; | 239 | return postProcessedClauses; |
109 | } | 240 | } |
241 | |||
242 | private Map<Variable, ClausePostProcessor.ParameterInfo> getParameterInfoMap() { | ||
243 | var mutableParameterInfoMap = new LinkedHashMap<Variable, ClausePostProcessor.ParameterInfo>(); | ||
244 | int arity = parameters.size(); | ||
245 | for (int i = 0; i < arity; i++) { | ||
246 | var parameter = parameters.get(i); | ||
247 | mutableParameterInfoMap.put(parameter.getVariable(), | ||
248 | new ClausePostProcessor.ParameterInfo(parameter.getDirection(), i)); | ||
249 | } | ||
250 | return Collections.unmodifiableMap(mutableParameterInfoMap); | ||
251 | } | ||
252 | |||
253 | private Set<Variable> getInputVariables() { | ||
254 | var inputParameters = new LinkedHashSet<Variable>(); | ||
255 | for (var parameter : parameters) { | ||
256 | if (parameter.getDirection() == ParameterDirection.IN) { | ||
257 | inputParameters.add(parameter.getVariable()); | ||
258 | } | ||
259 | } | ||
260 | return Collections.unmodifiableSet(inputParameters); | ||
261 | } | ||
110 | } | 262 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/DnfClause.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/DnfClause.java index 01830af1..fdd0d47c 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/DnfClause.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/DnfClause.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.dnf; | 6 | package tools.refinery.store.query.dnf; |
2 | 7 | ||
3 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | 8 | import tools.refinery.store.query.equality.LiteralEqualityHelper; |
@@ -7,7 +12,7 @@ import tools.refinery.store.query.term.Variable; | |||
7 | import java.util.List; | 12 | import java.util.List; |
8 | import java.util.Set; | 13 | import java.util.Set; |
9 | 14 | ||
10 | public record DnfClause(Set<Variable> boundVariables, List<Literal> literals) { | 15 | public record DnfClause(Set<Variable> positiveVariables, List<Literal> literals) { |
11 | public boolean equalsWithSubstitution(LiteralEqualityHelper helper, DnfClause other) { | 16 | public boolean equalsWithSubstitution(LiteralEqualityHelper helper, DnfClause other) { |
12 | int size = literals.size(); | 17 | int size = literals.size(); |
13 | if (size != other.literals.size()) { | 18 | if (size != other.literals.size()) { |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/DnfUtils.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/DnfUtils.java index 9bcf944c..65ab3634 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/DnfUtils.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/DnfUtils.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.dnf; | 6 | package tools.refinery.store.query.dnf; |
2 | 7 | ||
3 | import java.util.UUID; | 8 | import java.util.UUID; |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/FunctionalDependency.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/FunctionalDependency.java index f4cd109f..b00b2cb7 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/FunctionalDependency.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/FunctionalDependency.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.dnf; | 6 | package tools.refinery.store.query.dnf; |
2 | 7 | ||
3 | import java.util.HashSet; | 8 | import java.util.HashSet; |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/FunctionalQuery.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/FunctionalQuery.java index 5bf6f8c5..5a32b1ba 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/FunctionalQuery.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/FunctionalQuery.java | |||
@@ -1,44 +1,47 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.dnf; | 6 | package tools.refinery.store.query.dnf; |
2 | 7 | ||
3 | import tools.refinery.store.query.literal.CallPolarity; | 8 | import tools.refinery.store.query.literal.CallPolarity; |
4 | import tools.refinery.store.query.term.*; | 9 | import tools.refinery.store.query.term.Aggregator; |
10 | import tools.refinery.store.query.term.AssignedValue; | ||
11 | import tools.refinery.store.query.term.NodeVariable; | ||
12 | import tools.refinery.store.query.term.Variable; | ||
5 | 13 | ||
6 | import java.util.ArrayList; | 14 | import java.util.ArrayList; |
7 | import java.util.List; | 15 | import java.util.List; |
8 | import java.util.Objects; | 16 | import java.util.Objects; |
9 | 17 | ||
10 | public final class FunctionalQuery<T> implements Query<T> { | 18 | public final class FunctionalQuery<T> extends Query<T> { |
11 | private final Dnf dnf; | ||
12 | private final Class<T> type; | 19 | private final Class<T> type; |
13 | 20 | ||
14 | FunctionalQuery(Dnf dnf, Class<T> type) { | 21 | FunctionalQuery(Dnf dnf, Class<T> type) { |
15 | var parameters = dnf.getParameters(); | 22 | super(dnf); |
23 | var parameters = dnf.getSymbolicParameters(); | ||
16 | int outputIndex = dnf.arity() - 1; | 24 | int outputIndex = dnf.arity() - 1; |
17 | for (int i = 0; i < outputIndex; i++) { | 25 | for (int i = 0; i < outputIndex; i++) { |
18 | var parameter = parameters.get(i); | 26 | var parameter = parameters.get(i); |
19 | if (!(parameter instanceof NodeVariable)) { | 27 | var parameterType = parameter.tryGetType(); |
20 | throw new IllegalArgumentException("Expected parameter %s of %s to be of sort %s, but got %s instead" | 28 | if (parameterType.isPresent()) { |
21 | .formatted(parameter, dnf, NodeSort.INSTANCE, parameter.getSort())); | 29 | throw new IllegalArgumentException("Expected parameter %s of %s to be a node variable, got %s instead" |
30 | .formatted(parameter, dnf, parameterType.get().getName())); | ||
22 | } | 31 | } |
23 | } | 32 | } |
24 | var outputParameter = parameters.get(outputIndex); | 33 | var outputParameter = parameters.get(outputIndex); |
25 | if (!(outputParameter instanceof DataVariable<?> dataOutputParameter) || | 34 | var outputParameterType = outputParameter.tryGetType(); |
26 | !dataOutputParameter.getType().equals(type)) { | 35 | if (outputParameterType.isEmpty() || !outputParameterType.get().equals(type)) { |
27 | throw new IllegalArgumentException("Expected parameter %s of %s to be of sort %s, but got %s instead" | 36 | throw new IllegalArgumentException("Expected parameter %s of %s to be %s, but got %s instead".formatted( |
28 | .formatted(outputParameter, dnf, type, outputParameter.getSort())); | 37 | outputParameter, dnf, type, outputParameterType.map(Class::getName).orElse("node"))); |
29 | } | 38 | } |
30 | this.dnf = dnf; | ||
31 | this.type = type; | 39 | this.type = type; |
32 | } | 40 | } |
33 | 41 | ||
34 | @Override | 42 | @Override |
35 | public String name() { | ||
36 | return dnf.name(); | ||
37 | } | ||
38 | |||
39 | @Override | ||
40 | public int arity() { | 43 | public int arity() { |
41 | return dnf.arity() - 1; | 44 | return getDnf().arity() - 1; |
42 | } | 45 | } |
43 | 46 | ||
44 | @Override | 47 | @Override |
@@ -51,17 +54,12 @@ public final class FunctionalQuery<T> implements Query<T> { | |||
51 | return null; | 54 | return null; |
52 | } | 55 | } |
53 | 56 | ||
54 | @Override | ||
55 | public Dnf getDnf() { | ||
56 | return dnf; | ||
57 | } | ||
58 | |||
59 | public AssignedValue<T> call(List<NodeVariable> arguments) { | 57 | public AssignedValue<T> call(List<NodeVariable> arguments) { |
60 | return targetVariable -> { | 58 | return targetVariable -> { |
61 | var argumentsWithTarget = new ArrayList<Variable>(arguments.size() + 1); | 59 | var argumentsWithTarget = new ArrayList<Variable>(arguments.size() + 1); |
62 | argumentsWithTarget.addAll(arguments); | 60 | argumentsWithTarget.addAll(arguments); |
63 | argumentsWithTarget.add(targetVariable); | 61 | argumentsWithTarget.add(targetVariable); |
64 | return dnf.call(CallPolarity.POSITIVE, argumentsWithTarget); | 62 | return getDnf().call(CallPolarity.POSITIVE, argumentsWithTarget); |
65 | }; | 63 | }; |
66 | } | 64 | } |
67 | 65 | ||
@@ -75,7 +73,9 @@ public final class FunctionalQuery<T> implements Query<T> { | |||
75 | var argumentsWithPlaceholder = new ArrayList<Variable>(arguments.size() + 1); | 73 | var argumentsWithPlaceholder = new ArrayList<Variable>(arguments.size() + 1); |
76 | argumentsWithPlaceholder.addAll(arguments); | 74 | argumentsWithPlaceholder.addAll(arguments); |
77 | argumentsWithPlaceholder.add(placeholderVariable); | 75 | argumentsWithPlaceholder.add(placeholderVariable); |
78 | return dnf.aggregate(placeholderVariable, aggregator, argumentsWithPlaceholder).toLiteral(targetVariable); | 76 | return getDnf() |
77 | .aggregateBy(placeholderVariable, aggregator, argumentsWithPlaceholder) | ||
78 | .toLiteral(targetVariable); | ||
79 | }; | 79 | }; |
80 | } | 80 | } |
81 | 81 | ||
@@ -87,17 +87,13 @@ public final class FunctionalQuery<T> implements Query<T> { | |||
87 | public boolean equals(Object o) { | 87 | public boolean equals(Object o) { |
88 | if (this == o) return true; | 88 | if (this == o) return true; |
89 | if (o == null || getClass() != o.getClass()) return false; | 89 | if (o == null || getClass() != o.getClass()) return false; |
90 | if (!super.equals(o)) return false; | ||
90 | FunctionalQuery<?> that = (FunctionalQuery<?>) o; | 91 | FunctionalQuery<?> that = (FunctionalQuery<?>) o; |
91 | return dnf.equals(that.dnf) && type.equals(that.type); | 92 | return Objects.equals(type, that.type); |
92 | } | 93 | } |
93 | 94 | ||
94 | @Override | 95 | @Override |
95 | public int hashCode() { | 96 | public int hashCode() { |
96 | return Objects.hash(dnf, type); | 97 | return Objects.hash(super.hashCode(), type); |
97 | } | ||
98 | |||
99 | @Override | ||
100 | public String toString() { | ||
101 | return dnf.toString(); | ||
102 | } | 98 | } |
103 | } | 99 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/FunctionalQueryBuilder.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/FunctionalQueryBuilder.java index ca2bc006..d1cd7ba8 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/FunctionalQueryBuilder.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/FunctionalQueryBuilder.java | |||
@@ -1,46 +1,29 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.dnf; | 6 | package tools.refinery.store.query.dnf; |
2 | 7 | ||
3 | import tools.refinery.store.query.literal.Literal; | 8 | import tools.refinery.store.query.term.DataVariable; |
4 | import tools.refinery.store.query.term.Variable; | ||
5 | 9 | ||
6 | import java.util.Collection; | 10 | public final class FunctionalQueryBuilder<T> extends AbstractQueryBuilder<FunctionalQueryBuilder<T>> { |
7 | import java.util.Set; | 11 | private final DataVariable<T> outputVariable; |
8 | |||
9 | public final class FunctionalQueryBuilder<T> { | ||
10 | private final DnfBuilder dnfBuilder; | ||
11 | private final Class<T> type; | 12 | private final Class<T> type; |
12 | 13 | ||
13 | FunctionalQueryBuilder(DnfBuilder dnfBuilder, Class<T> type) { | 14 | FunctionalQueryBuilder(DataVariable<T> outputVariable, DnfBuilder dnfBuilder, Class<T> type) { |
14 | this.dnfBuilder = dnfBuilder; | 15 | super(dnfBuilder); |
16 | this.outputVariable = outputVariable; | ||
15 | this.type = type; | 17 | this.type = type; |
16 | } | 18 | } |
17 | 19 | ||
18 | public FunctionalQueryBuilder<T> functionalDependencies(Collection<FunctionalDependency<Variable>> functionalDependencies) { | 20 | @Override |
19 | dnfBuilder.functionalDependencies(functionalDependencies); | 21 | protected FunctionalQueryBuilder<T> self() { |
20 | return this; | ||
21 | } | ||
22 | |||
23 | public FunctionalQueryBuilder<T> functionalDependency(FunctionalDependency<Variable> functionalDependency) { | ||
24 | dnfBuilder.functionalDependency(functionalDependency); | ||
25 | return this; | ||
26 | } | ||
27 | |||
28 | public FunctionalQueryBuilder<T> functionalDependency(Set<? extends Variable> forEach, Set<? extends Variable> unique) { | ||
29 | dnfBuilder.functionalDependency(forEach, unique); | ||
30 | return this; | ||
31 | } | ||
32 | |||
33 | public FunctionalQueryBuilder<T> clause(Literal... literals) { | ||
34 | dnfBuilder.clause(literals); | ||
35 | return this; | ||
36 | } | ||
37 | |||
38 | public FunctionalQueryBuilder<T> clause(Collection<? extends Literal> literals) { | ||
39 | dnfBuilder.clause(literals); | ||
40 | return this; | 22 | return this; |
41 | } | 23 | } |
42 | 24 | ||
43 | public FunctionalQuery<T> build() { | 25 | public FunctionalQuery<T> build() { |
26 | dnfBuilder.output(outputVariable); | ||
44 | return dnfBuilder.build().asFunction(type); | 27 | return dnfBuilder.build().asFunction(type); |
45 | } | 28 | } |
46 | } | 29 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/Query.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/Query.java index 32e33052..aaa52ce6 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/Query.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/Query.java | |||
@@ -1,16 +1,179 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.dnf; | 6 | package tools.refinery.store.query.dnf; |
2 | 7 | ||
3 | public sealed interface Query<T> extends AnyQuery permits RelationalQuery, FunctionalQuery { | 8 | import tools.refinery.store.query.dnf.callback.*; |
9 | import tools.refinery.store.query.term.ParameterDirection; | ||
10 | import tools.refinery.store.query.term.Variable; | ||
11 | |||
12 | import java.util.Objects; | ||
13 | |||
14 | public abstract sealed class Query<T> implements AnyQuery permits FunctionalQuery, RelationalQuery { | ||
15 | private static final String OUTPUT_VARIABLE_NAME = "output"; | ||
16 | |||
17 | private final Dnf dnf; | ||
18 | |||
19 | protected Query(Dnf dnf) { | ||
20 | for (var parameter : dnf.getSymbolicParameters()) { | ||
21 | if (parameter.getDirection() != ParameterDirection.OUT) { | ||
22 | throw new IllegalArgumentException("Query parameter %s with direction %s is not allowed" | ||
23 | .formatted(parameter.getVariable(), parameter.getDirection())); | ||
24 | } | ||
25 | } | ||
26 | this.dnf = dnf; | ||
27 | } | ||
28 | |||
29 | @Override | ||
30 | public String name() { | ||
31 | return dnf.name(); | ||
32 | } | ||
33 | |||
34 | @Override | ||
35 | public Dnf getDnf() { | ||
36 | return dnf; | ||
37 | } | ||
38 | |||
39 | // Allow redeclaration of the method with refined return type. | ||
40 | @SuppressWarnings("squid:S3038") | ||
4 | @Override | 41 | @Override |
5 | Class<T> valueType(); | 42 | public abstract Class<T> valueType(); |
6 | 43 | ||
7 | T defaultValue(); | 44 | public abstract T defaultValue(); |
8 | 45 | ||
9 | static QueryBuilder builder() { | 46 | @Override |
10 | return new QueryBuilder(); | 47 | public boolean equals(Object o) { |
48 | if (this == o) return true; | ||
49 | if (o == null || getClass() != o.getClass()) return false; | ||
50 | Query<?> that = (Query<?>) o; | ||
51 | return Objects.equals(dnf, that.dnf); | ||
52 | } | ||
53 | |||
54 | @Override | ||
55 | public int hashCode() { | ||
56 | return Objects.hash(dnf); | ||
11 | } | 57 | } |
12 | 58 | ||
13 | static QueryBuilder builder(String name) { | 59 | @Override |
60 | public String toString() { | ||
61 | return dnf.toString(); | ||
62 | } | ||
63 | |||
64 | public static QueryBuilder builder() { | ||
65 | return builder(null); | ||
66 | } | ||
67 | |||
68 | public static QueryBuilder builder(String name) { | ||
14 | return new QueryBuilder(name); | 69 | return new QueryBuilder(name); |
15 | } | 70 | } |
71 | |||
72 | public static RelationalQuery of(QueryCallback0 callback) { | ||
73 | return of(null, callback); | ||
74 | } | ||
75 | |||
76 | public static RelationalQuery of(String name, QueryCallback0 callback) { | ||
77 | var builder = builder(name); | ||
78 | callback.accept(builder); | ||
79 | return builder.build(); | ||
80 | } | ||
81 | |||
82 | public static RelationalQuery of(QueryCallback1 callback) { | ||
83 | return of(null, callback); | ||
84 | } | ||
85 | |||
86 | public static RelationalQuery of(String name, QueryCallback1 callback) { | ||
87 | var builder = builder(name); | ||
88 | callback.accept(builder, builder.parameter("p1")); | ||
89 | return builder.build(); | ||
90 | } | ||
91 | |||
92 | public static RelationalQuery of(QueryCallback2 callback) { | ||
93 | return of(null, callback); | ||
94 | } | ||
95 | |||
96 | public static RelationalQuery of(String name, QueryCallback2 callback) { | ||
97 | var builder = builder(name); | ||
98 | callback.accept(builder, builder.parameter("p1"), builder.parameter("p2")); | ||
99 | return builder.build(); | ||
100 | } | ||
101 | |||
102 | public static RelationalQuery of(QueryCallback3 callback) { | ||
103 | return of(null, callback); | ||
104 | } | ||
105 | |||
106 | public static RelationalQuery of(String name, QueryCallback3 callback) { | ||
107 | var builder = builder(name); | ||
108 | callback.accept(builder, builder.parameter("p1"), builder.parameter("p2"), builder.parameter("p3")); | ||
109 | return builder.build(); | ||
110 | } | ||
111 | |||
112 | public static RelationalQuery of(QueryCallback4 callback) { | ||
113 | return of(null, callback); | ||
114 | } | ||
115 | |||
116 | public static RelationalQuery of(String name, QueryCallback4 callback) { | ||
117 | var builder = builder(name); | ||
118 | callback.accept(builder, builder.parameter("p1"), builder.parameter("p2"), builder.parameter("p3"), | ||
119 | builder.parameter("p4")); | ||
120 | return builder.build(); | ||
121 | } | ||
122 | |||
123 | public static <T> FunctionalQuery<T> of(Class<T> type, FunctionalQueryCallback0<T> callback) { | ||
124 | return of(null, type, callback); | ||
125 | } | ||
126 | |||
127 | public static <T> FunctionalQuery<T> of(String name, Class<T> type, FunctionalQueryCallback0<T> callback) { | ||
128 | var outputVariable = Variable.of(OUTPUT_VARIABLE_NAME, type); | ||
129 | var builder = builder(name).output(outputVariable); | ||
130 | callback.accept(builder, outputVariable); | ||
131 | return builder.build(); | ||
132 | } | ||
133 | |||
134 | public static <T> FunctionalQuery<T> of(Class<T> type, FunctionalQueryCallback1<T> callback) { | ||
135 | return of(null, type, callback); | ||
136 | } | ||
137 | |||
138 | public static <T> FunctionalQuery<T> of(String name, Class<T> type, FunctionalQueryCallback1<T> callback) { | ||
139 | var outputVariable = Variable.of(OUTPUT_VARIABLE_NAME, type); | ||
140 | var builder = builder(name).output(outputVariable); | ||
141 | callback.accept(builder, builder.parameter("p1"), outputVariable); | ||
142 | return builder.build(); | ||
143 | } | ||
144 | |||
145 | public static <T> FunctionalQuery<T> of(Class<T> type, FunctionalQueryCallback2<T> callback) { | ||
146 | return of(null, type, callback); | ||
147 | } | ||
148 | |||
149 | public static <T> FunctionalQuery<T> of(String name, Class<T> type, FunctionalQueryCallback2<T> callback) { | ||
150 | var outputVariable = Variable.of(OUTPUT_VARIABLE_NAME, type); | ||
151 | var builder = builder(name).output(outputVariable); | ||
152 | callback.accept(builder, builder.parameter("p1"), builder.parameter("p2"), outputVariable); | ||
153 | return builder.build(); | ||
154 | } | ||
155 | |||
156 | public static <T> FunctionalQuery<T> of(Class<T> type, FunctionalQueryCallback3<T> callback) { | ||
157 | return of(null, type, callback); | ||
158 | } | ||
159 | |||
160 | public static <T> FunctionalQuery<T> of(String name, Class<T> type, FunctionalQueryCallback3<T> callback) { | ||
161 | var outputVariable = Variable.of(OUTPUT_VARIABLE_NAME, type); | ||
162 | var builder = builder(name).output(outputVariable); | ||
163 | callback.accept(builder, builder.parameter("p1"), builder.parameter("p2"), builder.parameter("p3"), | ||
164 | outputVariable); | ||
165 | return builder.build(); | ||
166 | } | ||
167 | |||
168 | public static <T> FunctionalQuery<T> of(Class<T> type, FunctionalQueryCallback4<T> callback) { | ||
169 | return of(null, type, callback); | ||
170 | } | ||
171 | |||
172 | public static <T> FunctionalQuery<T> of(String name, Class<T> type, FunctionalQueryCallback4<T> callback) { | ||
173 | var outputVariable = Variable.of(OUTPUT_VARIABLE_NAME, type); | ||
174 | var builder = builder(name).output(outputVariable); | ||
175 | callback.accept(builder, builder.parameter("p1"), builder.parameter("p2"), builder.parameter("p3"), | ||
176 | builder.parameter("p4"), outputVariable); | ||
177 | return builder.build(); | ||
178 | } | ||
16 | } | 179 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/QueryBuilder.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/QueryBuilder.java index ed253cc9..138911bc 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/QueryBuilder.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/QueryBuilder.java | |||
@@ -1,68 +1,24 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.dnf; | 6 | package tools.refinery.store.query.dnf; |
2 | 7 | ||
3 | import tools.refinery.store.query.literal.Literal; | ||
4 | import tools.refinery.store.query.term.DataVariable; | 8 | import tools.refinery.store.query.term.DataVariable; |
5 | import tools.refinery.store.query.term.NodeVariable; | ||
6 | import tools.refinery.store.query.term.Variable; | ||
7 | |||
8 | import java.util.Collection; | ||
9 | import java.util.List; | ||
10 | import java.util.Set; | ||
11 | |||
12 | public final class QueryBuilder { | ||
13 | private final DnfBuilder dnfBuilder; | ||
14 | 9 | ||
10 | public final class QueryBuilder extends AbstractQueryBuilder<QueryBuilder> { | ||
15 | QueryBuilder(String name) { | 11 | QueryBuilder(String name) { |
16 | dnfBuilder = Dnf.builder(name); | 12 | super(Dnf.builder(name)); |
17 | } | ||
18 | |||
19 | QueryBuilder() { | ||
20 | dnfBuilder = Dnf.builder(); | ||
21 | } | ||
22 | |||
23 | public QueryBuilder parameter(NodeVariable variable) { | ||
24 | dnfBuilder.parameter(variable); | ||
25 | return this; | ||
26 | } | 13 | } |
27 | 14 | ||
28 | public QueryBuilder parameters(NodeVariable... variables) { | 15 | @Override |
29 | dnfBuilder.parameters(variables); | 16 | protected QueryBuilder self() { |
30 | return this; | ||
31 | } | ||
32 | |||
33 | public QueryBuilder parameters(List<NodeVariable> variables) { | ||
34 | dnfBuilder.parameters(variables); | ||
35 | return this; | 17 | return this; |
36 | } | 18 | } |
37 | 19 | ||
38 | public <T> FunctionalQueryBuilder<T> output(DataVariable<T> outputVariable) { | 20 | public <T> FunctionalQueryBuilder<T> output(DataVariable<T> outputVariable) { |
39 | dnfBuilder.output(outputVariable); | 21 | return new FunctionalQueryBuilder<>(outputVariable, dnfBuilder, outputVariable.getType()); |
40 | return new FunctionalQueryBuilder<>(dnfBuilder, outputVariable.getType()); | ||
41 | } | ||
42 | |||
43 | public QueryBuilder functionalDependencies(Collection<FunctionalDependency<Variable>> functionalDependencies) { | ||
44 | dnfBuilder.functionalDependencies(functionalDependencies); | ||
45 | return this; | ||
46 | } | ||
47 | |||
48 | public QueryBuilder functionalDependency(FunctionalDependency<Variable> functionalDependency) { | ||
49 | dnfBuilder.functionalDependency(functionalDependency); | ||
50 | return this; | ||
51 | } | ||
52 | |||
53 | public QueryBuilder functionalDependency(Set<? extends Variable> forEach, Set<? extends Variable> unique) { | ||
54 | dnfBuilder.functionalDependency(forEach, unique); | ||
55 | return this; | ||
56 | } | ||
57 | |||
58 | public QueryBuilder clause(Literal... literals) { | ||
59 | dnfBuilder.clause(literals); | ||
60 | return this; | ||
61 | } | ||
62 | |||
63 | public QueryBuilder clause(Collection<? extends Literal> literals) { | ||
64 | dnfBuilder.clause(literals); | ||
65 | return this; | ||
66 | } | 22 | } |
67 | 23 | ||
68 | public RelationalQuery build() { | 24 | public RelationalQuery build() { |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/RelationalQuery.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/RelationalQuery.java index 5307e509..d34a7ace 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/RelationalQuery.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/RelationalQuery.java | |||
@@ -1,36 +1,33 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.dnf; | 6 | package tools.refinery.store.query.dnf; |
2 | 7 | ||
3 | import tools.refinery.store.query.literal.CallLiteral; | 8 | import tools.refinery.store.query.literal.CallLiteral; |
4 | import tools.refinery.store.query.literal.CallPolarity; | 9 | import tools.refinery.store.query.literal.CallPolarity; |
5 | import tools.refinery.store.query.term.AssignedValue; | 10 | import tools.refinery.store.query.term.AssignedValue; |
6 | import tools.refinery.store.query.term.NodeSort; | ||
7 | import tools.refinery.store.query.term.NodeVariable; | 11 | import tools.refinery.store.query.term.NodeVariable; |
8 | 12 | ||
9 | import java.util.Collections; | 13 | import java.util.Collections; |
10 | import java.util.List; | 14 | import java.util.List; |
11 | import java.util.Objects; | ||
12 | |||
13 | public final class RelationalQuery implements Query<Boolean> { | ||
14 | private final Dnf dnf; | ||
15 | 15 | ||
16 | public final class RelationalQuery extends Query<Boolean> { | ||
16 | RelationalQuery(Dnf dnf) { | 17 | RelationalQuery(Dnf dnf) { |
17 | for (var parameter : dnf.getParameters()) { | 18 | super(dnf); |
18 | if (!(parameter instanceof NodeVariable)) { | 19 | for (var parameter : dnf.getSymbolicParameters()) { |
19 | throw new IllegalArgumentException("Expected parameter %s of %s to be of sort %s, but got %s instead" | 20 | var parameterType = parameter.tryGetType(); |
20 | .formatted(parameter, dnf, NodeSort.INSTANCE, parameter.getSort())); | 21 | if (parameterType.isPresent()) { |
22 | throw new IllegalArgumentException("Expected parameter %s of %s to be a node variable, got %s instead" | ||
23 | .formatted(parameter, dnf, parameterType.get().getName())); | ||
21 | } | 24 | } |
22 | } | 25 | } |
23 | this.dnf = dnf; | ||
24 | } | ||
25 | |||
26 | @Override | ||
27 | public String name() { | ||
28 | return dnf.name(); | ||
29 | } | 26 | } |
30 | 27 | ||
31 | @Override | 28 | @Override |
32 | public int arity() { | 29 | public int arity() { |
33 | return dnf.arity(); | 30 | return getDnf().arity(); |
34 | } | 31 | } |
35 | 32 | ||
36 | @Override | 33 | @Override |
@@ -43,51 +40,27 @@ public final class RelationalQuery implements Query<Boolean> { | |||
43 | return false; | 40 | return false; |
44 | } | 41 | } |
45 | 42 | ||
46 | @Override | ||
47 | public Dnf getDnf() { | ||
48 | return dnf; | ||
49 | } | ||
50 | |||
51 | public CallLiteral call(CallPolarity polarity, List<NodeVariable> arguments) { | 43 | public CallLiteral call(CallPolarity polarity, List<NodeVariable> arguments) { |
52 | return dnf.call(polarity, Collections.unmodifiableList(arguments)); | 44 | return getDnf().call(polarity, Collections.unmodifiableList(arguments)); |
53 | } | 45 | } |
54 | 46 | ||
55 | public CallLiteral call(CallPolarity polarity, NodeVariable... arguments) { | 47 | public CallLiteral call(CallPolarity polarity, NodeVariable... arguments) { |
56 | return dnf.call(polarity, arguments); | 48 | return getDnf().call(polarity, arguments); |
57 | } | 49 | } |
58 | 50 | ||
59 | public CallLiteral call(NodeVariable... arguments) { | 51 | public CallLiteral call(NodeVariable... arguments) { |
60 | return dnf.call(arguments); | 52 | return getDnf().call(arguments); |
61 | } | 53 | } |
62 | 54 | ||
63 | public CallLiteral callTransitive(NodeVariable left, NodeVariable right) { | 55 | public CallLiteral callTransitive(NodeVariable left, NodeVariable right) { |
64 | return dnf.callTransitive(left, right); | 56 | return getDnf().callTransitive(left, right); |
65 | } | 57 | } |
66 | 58 | ||
67 | public AssignedValue<Integer> count(List<NodeVariable> arguments) { | 59 | public AssignedValue<Integer> count(List<NodeVariable> arguments) { |
68 | return dnf.count(Collections.unmodifiableList(arguments)); | 60 | return getDnf().count(Collections.unmodifiableList(arguments)); |
69 | } | 61 | } |
70 | 62 | ||
71 | public AssignedValue<Integer> count(NodeVariable... arguments) { | 63 | public AssignedValue<Integer> count(NodeVariable... arguments) { |
72 | return dnf.count(arguments); | 64 | return getDnf().count(arguments); |
73 | } | ||
74 | |||
75 | |||
76 | @Override | ||
77 | public boolean equals(Object o) { | ||
78 | if (this == o) return true; | ||
79 | if (o == null || getClass() != o.getClass()) return false; | ||
80 | RelationalQuery that = (RelationalQuery) o; | ||
81 | return dnf.equals(that.dnf); | ||
82 | } | ||
83 | |||
84 | @Override | ||
85 | public int hashCode() { | ||
86 | return Objects.hash(dnf); | ||
87 | } | ||
88 | |||
89 | @Override | ||
90 | public String toString() { | ||
91 | return dnf.toString(); | ||
92 | } | 65 | } |
93 | } | 66 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/SymbolicParameter.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/SymbolicParameter.java new file mode 100644 index 00000000..e0d3ba1f --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/SymbolicParameter.java | |||
@@ -0,0 +1,52 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf; | ||
7 | |||
8 | import tools.refinery.store.query.term.Parameter; | ||
9 | import tools.refinery.store.query.term.ParameterDirection; | ||
10 | import tools.refinery.store.query.term.Variable; | ||
11 | |||
12 | import java.util.Objects; | ||
13 | |||
14 | public final class SymbolicParameter extends Parameter { | ||
15 | private final Variable variable; | ||
16 | |||
17 | public SymbolicParameter(Variable variable, ParameterDirection direction) { | ||
18 | super(variable.tryGetType().orElse(null), direction); | ||
19 | this.variable = variable; | ||
20 | } | ||
21 | |||
22 | public Variable getVariable() { | ||
23 | return variable; | ||
24 | } | ||
25 | |||
26 | public boolean isUnifiable() { | ||
27 | return variable.isUnifiable(); | ||
28 | } | ||
29 | |||
30 | @Override | ||
31 | public String toString() { | ||
32 | var direction = getDirection(); | ||
33 | if (direction == ParameterDirection.OUT) { | ||
34 | return variable.toString(); | ||
35 | } | ||
36 | return "%s %s".formatted(getDirection(), variable); | ||
37 | } | ||
38 | |||
39 | @Override | ||
40 | public boolean equals(Object o) { | ||
41 | if (this == o) return true; | ||
42 | if (o == null || getClass() != o.getClass()) return false; | ||
43 | if (!super.equals(o)) return false; | ||
44 | SymbolicParameter that = (SymbolicParameter) o; | ||
45 | return Objects.equals(variable, that.variable); | ||
46 | } | ||
47 | |||
48 | @Override | ||
49 | public int hashCode() { | ||
50 | return Objects.hash(super.hashCode(), variable); | ||
51 | } | ||
52 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback0.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback0.java new file mode 100644 index 00000000..d98dda2e --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback0.java | |||
@@ -0,0 +1,15 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.literal.Literal; | ||
9 | |||
10 | import java.util.Collection; | ||
11 | |||
12 | @FunctionalInterface | ||
13 | public interface ClauseCallback0 { | ||
14 | Collection<Literal> toLiterals(); | ||
15 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback1Data0.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback1Data0.java new file mode 100644 index 00000000..4c01a527 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback1Data0.java | |||
@@ -0,0 +1,16 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.literal.Literal; | ||
9 | import tools.refinery.store.query.term.NodeVariable; | ||
10 | |||
11 | import java.util.Collection; | ||
12 | |||
13 | @FunctionalInterface | ||
14 | public interface ClauseCallback1Data0 { | ||
15 | Collection<Literal> toLiterals(NodeVariable v1); | ||
16 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback1Data1.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback1Data1.java new file mode 100644 index 00000000..2c0cb6eb --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback1Data1.java | |||
@@ -0,0 +1,16 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.literal.Literal; | ||
9 | import tools.refinery.store.query.term.DataVariable; | ||
10 | |||
11 | import java.util.Collection; | ||
12 | |||
13 | @FunctionalInterface | ||
14 | public interface ClauseCallback1Data1<T> { | ||
15 | Collection<Literal> toLiterals(DataVariable<T> d1); | ||
16 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback2Data0.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback2Data0.java new file mode 100644 index 00000000..d764bdba --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback2Data0.java | |||
@@ -0,0 +1,16 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.literal.Literal; | ||
9 | import tools.refinery.store.query.term.NodeVariable; | ||
10 | |||
11 | import java.util.Collection; | ||
12 | |||
13 | @FunctionalInterface | ||
14 | public interface ClauseCallback2Data0 { | ||
15 | Collection<Literal> toLiterals(NodeVariable v1, NodeVariable v2); | ||
16 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback2Data1.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback2Data1.java new file mode 100644 index 00000000..140af03a --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback2Data1.java | |||
@@ -0,0 +1,17 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.literal.Literal; | ||
9 | import tools.refinery.store.query.term.DataVariable; | ||
10 | import tools.refinery.store.query.term.NodeVariable; | ||
11 | |||
12 | import java.util.Collection; | ||
13 | |||
14 | @FunctionalInterface | ||
15 | public interface ClauseCallback2Data1<T> { | ||
16 | Collection<Literal> toLiterals(NodeVariable v1, DataVariable<T> x1); | ||
17 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback2Data2.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback2Data2.java new file mode 100644 index 00000000..bfc8637c --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback2Data2.java | |||
@@ -0,0 +1,16 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.literal.Literal; | ||
9 | import tools.refinery.store.query.term.DataVariable; | ||
10 | |||
11 | import java.util.Collection; | ||
12 | |||
13 | @FunctionalInterface | ||
14 | public interface ClauseCallback2Data2<T1, T2> { | ||
15 | Collection<Literal> toLiterals(DataVariable<T1> x1, DataVariable<T2> x2); | ||
16 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback3Data0.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback3Data0.java new file mode 100644 index 00000000..074df65b --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback3Data0.java | |||
@@ -0,0 +1,16 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.literal.Literal; | ||
9 | import tools.refinery.store.query.term.NodeVariable; | ||
10 | |||
11 | import java.util.Collection; | ||
12 | |||
13 | @FunctionalInterface | ||
14 | public interface ClauseCallback3Data0 { | ||
15 | Collection<Literal> toLiterals(NodeVariable v1, NodeVariable v2, NodeVariable v3); | ||
16 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback3Data1.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback3Data1.java new file mode 100644 index 00000000..24ba5187 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback3Data1.java | |||
@@ -0,0 +1,17 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.literal.Literal; | ||
9 | import tools.refinery.store.query.term.DataVariable; | ||
10 | import tools.refinery.store.query.term.NodeVariable; | ||
11 | |||
12 | import java.util.Collection; | ||
13 | |||
14 | @FunctionalInterface | ||
15 | public interface ClauseCallback3Data1<T> { | ||
16 | Collection<Literal> toLiterals(NodeVariable v1, NodeVariable v2, DataVariable<T> d1); | ||
17 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback3Data2.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback3Data2.java new file mode 100644 index 00000000..2a2e837a --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback3Data2.java | |||
@@ -0,0 +1,17 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.literal.Literal; | ||
9 | import tools.refinery.store.query.term.DataVariable; | ||
10 | import tools.refinery.store.query.term.NodeVariable; | ||
11 | |||
12 | import java.util.Collection; | ||
13 | |||
14 | @FunctionalInterface | ||
15 | public interface ClauseCallback3Data2<T1, T2> { | ||
16 | Collection<Literal> toLiterals(NodeVariable v1, DataVariable<T1> d1, DataVariable<T2> d2); | ||
17 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback3Data3.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback3Data3.java new file mode 100644 index 00000000..8f4bdd01 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback3Data3.java | |||
@@ -0,0 +1,16 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.literal.Literal; | ||
9 | import tools.refinery.store.query.term.DataVariable; | ||
10 | |||
11 | import java.util.Collection; | ||
12 | |||
13 | @FunctionalInterface | ||
14 | public interface ClauseCallback3Data3<T1, T2, T3> { | ||
15 | Collection<Literal> toLiterals(DataVariable<T1> d1, DataVariable<T2> d2, DataVariable<T3> d3); | ||
16 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback4Data0.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback4Data0.java new file mode 100644 index 00000000..ed0f87b2 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback4Data0.java | |||
@@ -0,0 +1,16 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.literal.Literal; | ||
9 | import tools.refinery.store.query.term.NodeVariable; | ||
10 | |||
11 | import java.util.Collection; | ||
12 | |||
13 | @FunctionalInterface | ||
14 | public interface ClauseCallback4Data0 { | ||
15 | Collection<Literal> toLiterals(NodeVariable v1, NodeVariable v2, NodeVariable v3, NodeVariable v4); | ||
16 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback4Data1.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback4Data1.java new file mode 100644 index 00000000..9b27e2e1 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback4Data1.java | |||
@@ -0,0 +1,17 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.literal.Literal; | ||
9 | import tools.refinery.store.query.term.DataVariable; | ||
10 | import tools.refinery.store.query.term.NodeVariable; | ||
11 | |||
12 | import java.util.Collection; | ||
13 | |||
14 | @FunctionalInterface | ||
15 | public interface ClauseCallback4Data1<T> { | ||
16 | Collection<Literal> toLiterals(NodeVariable v1, NodeVariable v2, NodeVariable v3, DataVariable<T> d1); | ||
17 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback4Data2.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback4Data2.java new file mode 100644 index 00000000..cbc4808e --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback4Data2.java | |||
@@ -0,0 +1,17 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.literal.Literal; | ||
9 | import tools.refinery.store.query.term.DataVariable; | ||
10 | import tools.refinery.store.query.term.NodeVariable; | ||
11 | |||
12 | import java.util.Collection; | ||
13 | |||
14 | @FunctionalInterface | ||
15 | public interface ClauseCallback4Data2<T1, T2> { | ||
16 | Collection<Literal> toLiterals(NodeVariable v1, NodeVariable v2, DataVariable<T1> d1, DataVariable<T2> d2); | ||
17 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback4Data3.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback4Data3.java new file mode 100644 index 00000000..a6258f36 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback4Data3.java | |||
@@ -0,0 +1,17 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.literal.Literal; | ||
9 | import tools.refinery.store.query.term.DataVariable; | ||
10 | import tools.refinery.store.query.term.NodeVariable; | ||
11 | |||
12 | import java.util.Collection; | ||
13 | |||
14 | @FunctionalInterface | ||
15 | public interface ClauseCallback4Data3<T1, T2, T3> { | ||
16 | Collection<Literal> toLiterals(NodeVariable v1, DataVariable<T1> d1, DataVariable<T2> d2, DataVariable<T3> d3); | ||
17 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback4Data4.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback4Data4.java new file mode 100644 index 00000000..b52a911a --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/ClauseCallback4Data4.java | |||
@@ -0,0 +1,16 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.literal.Literal; | ||
9 | import tools.refinery.store.query.term.DataVariable; | ||
10 | |||
11 | import java.util.Collection; | ||
12 | |||
13 | @FunctionalInterface | ||
14 | public interface ClauseCallback4Data4<T1, T2, T3, T4> { | ||
15 | Collection<Literal> toLiterals(DataVariable<T1> d1, DataVariable<T2> d2, DataVariable<T3> d3, DataVariable<T4> d4); | ||
16 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/FunctionalQueryCallback0.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/FunctionalQueryCallback0.java new file mode 100644 index 00000000..63b3eee6 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/FunctionalQueryCallback0.java | |||
@@ -0,0 +1,14 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.dnf.FunctionalQueryBuilder; | ||
9 | import tools.refinery.store.query.term.DataVariable; | ||
10 | |||
11 | @FunctionalInterface | ||
12 | public interface FunctionalQueryCallback0<T> { | ||
13 | void accept(FunctionalQueryBuilder<T> builder, DataVariable<T> output); | ||
14 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/FunctionalQueryCallback1.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/FunctionalQueryCallback1.java new file mode 100644 index 00000000..1295a118 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/FunctionalQueryCallback1.java | |||
@@ -0,0 +1,15 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.dnf.FunctionalQueryBuilder; | ||
9 | import tools.refinery.store.query.term.DataVariable; | ||
10 | import tools.refinery.store.query.term.NodeVariable; | ||
11 | |||
12 | @FunctionalInterface | ||
13 | public interface FunctionalQueryCallback1<T> { | ||
14 | void accept(FunctionalQueryBuilder<T> builder, NodeVariable p1, DataVariable<T> output); | ||
15 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/FunctionalQueryCallback2.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/FunctionalQueryCallback2.java new file mode 100644 index 00000000..d5b7f9ff --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/FunctionalQueryCallback2.java | |||
@@ -0,0 +1,15 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.dnf.FunctionalQueryBuilder; | ||
9 | import tools.refinery.store.query.term.DataVariable; | ||
10 | import tools.refinery.store.query.term.NodeVariable; | ||
11 | |||
12 | @FunctionalInterface | ||
13 | public interface FunctionalQueryCallback2<T> { | ||
14 | void accept(FunctionalQueryBuilder<T> builder, NodeVariable p1, NodeVariable p2, DataVariable<T> output); | ||
15 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/FunctionalQueryCallback3.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/FunctionalQueryCallback3.java new file mode 100644 index 00000000..dc8404a0 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/FunctionalQueryCallback3.java | |||
@@ -0,0 +1,16 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.dnf.FunctionalQueryBuilder; | ||
9 | import tools.refinery.store.query.term.DataVariable; | ||
10 | import tools.refinery.store.query.term.NodeVariable; | ||
11 | |||
12 | @FunctionalInterface | ||
13 | public interface FunctionalQueryCallback3<T> { | ||
14 | void accept(FunctionalQueryBuilder<T> builder, NodeVariable p1, NodeVariable p2, NodeVariable p3, | ||
15 | DataVariable<T> output); | ||
16 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/FunctionalQueryCallback4.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/FunctionalQueryCallback4.java new file mode 100644 index 00000000..b6d3ddb0 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/FunctionalQueryCallback4.java | |||
@@ -0,0 +1,16 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.dnf.FunctionalQueryBuilder; | ||
9 | import tools.refinery.store.query.term.DataVariable; | ||
10 | import tools.refinery.store.query.term.NodeVariable; | ||
11 | |||
12 | @FunctionalInterface | ||
13 | public interface FunctionalQueryCallback4<T> { | ||
14 | void accept(FunctionalQueryBuilder<T> builder, NodeVariable p1, NodeVariable p2, NodeVariable p3, NodeVariable p4, | ||
15 | DataVariable<T> output); | ||
16 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/QueryCallback0.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/QueryCallback0.java new file mode 100644 index 00000000..3cf1de48 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/QueryCallback0.java | |||
@@ -0,0 +1,13 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.dnf.QueryBuilder; | ||
9 | |||
10 | @FunctionalInterface | ||
11 | public interface QueryCallback0 { | ||
12 | void accept(QueryBuilder builder); | ||
13 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/QueryCallback1.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/QueryCallback1.java new file mode 100644 index 00000000..0a150955 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/QueryCallback1.java | |||
@@ -0,0 +1,14 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.dnf.QueryBuilder; | ||
9 | import tools.refinery.store.query.term.NodeVariable; | ||
10 | |||
11 | @FunctionalInterface | ||
12 | public interface QueryCallback1 { | ||
13 | void accept(QueryBuilder builder, NodeVariable p1); | ||
14 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/QueryCallback2.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/QueryCallback2.java new file mode 100644 index 00000000..9493a7b4 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/QueryCallback2.java | |||
@@ -0,0 +1,14 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.dnf.QueryBuilder; | ||
9 | import tools.refinery.store.query.term.NodeVariable; | ||
10 | |||
11 | @FunctionalInterface | ||
12 | public interface QueryCallback2 { | ||
13 | void accept(QueryBuilder builder, NodeVariable p1, NodeVariable p2); | ||
14 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/QueryCallback3.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/QueryCallback3.java new file mode 100644 index 00000000..358c7da7 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/QueryCallback3.java | |||
@@ -0,0 +1,14 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.dnf.QueryBuilder; | ||
9 | import tools.refinery.store.query.term.NodeVariable; | ||
10 | |||
11 | @FunctionalInterface | ||
12 | public interface QueryCallback3 { | ||
13 | void accept(QueryBuilder builder, NodeVariable p1, NodeVariable p2, NodeVariable p3); | ||
14 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/QueryCallback4.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/QueryCallback4.java new file mode 100644 index 00000000..890dda16 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/dnf/callback/QueryCallback4.java | |||
@@ -0,0 +1,14 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf.callback; | ||
7 | |||
8 | import tools.refinery.store.query.dnf.QueryBuilder; | ||
9 | import tools.refinery.store.query.term.NodeVariable; | ||
10 | |||
11 | @FunctionalInterface | ||
12 | public interface QueryCallback4 { | ||
13 | void accept(QueryBuilder builder, NodeVariable p1, NodeVariable p2, NodeVariable p3, NodeVariable p4); | ||
14 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/DeepDnfEqualityChecker.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/DeepDnfEqualityChecker.java index c3bc3ea3..1eeb5723 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/DeepDnfEqualityChecker.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/DeepDnfEqualityChecker.java | |||
@@ -1,6 +1,14 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.equality; | 6 | package tools.refinery.store.query.equality; |
2 | 7 | ||
3 | import tools.refinery.store.query.dnf.Dnf; | 8 | import tools.refinery.store.query.dnf.Dnf; |
9 | import tools.refinery.store.query.dnf.DnfClause; | ||
10 | import tools.refinery.store.query.dnf.SymbolicParameter; | ||
11 | import tools.refinery.store.query.literal.Literal; | ||
4 | import tools.refinery.store.util.CycleDetectingMapper; | 12 | import tools.refinery.store.util.CycleDetectingMapper; |
5 | 13 | ||
6 | import java.util.List; | 14 | import java.util.List; |
@@ -14,6 +22,45 @@ public class DeepDnfEqualityChecker implements DnfEqualityChecker { | |||
14 | return mapper.map(new Pair(left, right)); | 22 | return mapper.map(new Pair(left, right)); |
15 | } | 23 | } |
16 | 24 | ||
25 | public boolean dnfEqualRaw(List<SymbolicParameter> symbolicParameters, | ||
26 | List<? extends List<? extends Literal>> clauses, Dnf other) { | ||
27 | int arity = symbolicParameters.size(); | ||
28 | if (arity != other.arity()) { | ||
29 | return false; | ||
30 | } | ||
31 | for (int i = 0; i < arity; i++) { | ||
32 | if (!symbolicParameters.get(i).getDirection().equals(other.getSymbolicParameters().get(i).getDirection())) { | ||
33 | return false; | ||
34 | } | ||
35 | } | ||
36 | int numClauses = clauses.size(); | ||
37 | if (numClauses != other.getClauses().size()) { | ||
38 | return false; | ||
39 | } | ||
40 | for (int i = 0; i < numClauses; i++) { | ||
41 | var literalEqualityHelper = new LiteralEqualityHelper(this, symbolicParameters, | ||
42 | other.getSymbolicParameters()); | ||
43 | if (!equalsWithSubstitutionRaw(literalEqualityHelper, clauses.get(i), other.getClauses().get(i))) { | ||
44 | return false; | ||
45 | } | ||
46 | } | ||
47 | return true; | ||
48 | } | ||
49 | |||
50 | private boolean equalsWithSubstitutionRaw(LiteralEqualityHelper helper, List<? extends Literal> literals, | ||
51 | DnfClause other) { | ||
52 | int size = literals.size(); | ||
53 | if (size != other.literals().size()) { | ||
54 | return false; | ||
55 | } | ||
56 | for (int i = 0; i < size; i++) { | ||
57 | if (!literals.get(i).equalsWithSubstitution(helper, other.literals().get(i))) { | ||
58 | return false; | ||
59 | } | ||
60 | } | ||
61 | return true; | ||
62 | } | ||
63 | |||
17 | protected boolean doCheckEqual(Pair pair) { | 64 | protected boolean doCheckEqual(Pair pair) { |
18 | return pair.left.equalsWithSubstitution(this, pair.right); | 65 | return pair.left.equalsWithSubstitution(this, pair.right); |
19 | } | 66 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/DnfEqualityChecker.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/DnfEqualityChecker.java index 6b1f2076..4a8bee3b 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/DnfEqualityChecker.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/DnfEqualityChecker.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.equality; | 6 | package tools.refinery.store.query.equality; |
2 | 7 | ||
3 | import tools.refinery.store.query.dnf.Dnf; | 8 | import tools.refinery.store.query.dnf.Dnf; |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/LiteralEqualityHelper.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/LiteralEqualityHelper.java index 07d261ea..9315fb30 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/LiteralEqualityHelper.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/equality/LiteralEqualityHelper.java | |||
@@ -1,6 +1,12 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.equality; | 6 | package tools.refinery.store.query.equality; |
2 | 7 | ||
3 | import tools.refinery.store.query.dnf.Dnf; | 8 | import tools.refinery.store.query.dnf.Dnf; |
9 | import tools.refinery.store.query.dnf.SymbolicParameter; | ||
4 | import tools.refinery.store.query.term.Variable; | 10 | import tools.refinery.store.query.term.Variable; |
5 | 11 | ||
6 | import java.util.HashMap; | 12 | import java.util.HashMap; |
@@ -12,8 +18,8 @@ public class LiteralEqualityHelper { | |||
12 | private final Map<Variable, Variable> leftToRight; | 18 | private final Map<Variable, Variable> leftToRight; |
13 | private final Map<Variable, Variable> rightToLeft; | 19 | private final Map<Variable, Variable> rightToLeft; |
14 | 20 | ||
15 | public LiteralEqualityHelper(DnfEqualityChecker dnfEqualityChecker, List<Variable> leftParameters, | 21 | public LiteralEqualityHelper(DnfEqualityChecker dnfEqualityChecker, List<SymbolicParameter> leftParameters, |
16 | List<Variable> rightParameters) { | 22 | List<SymbolicParameter> rightParameters) { |
17 | this.dnfEqualityChecker = dnfEqualityChecker; | 23 | this.dnfEqualityChecker = dnfEqualityChecker; |
18 | var arity = leftParameters.size(); | 24 | var arity = leftParameters.size(); |
19 | if (arity != rightParameters.size()) { | 25 | if (arity != rightParameters.size()) { |
@@ -22,7 +28,7 @@ public class LiteralEqualityHelper { | |||
22 | leftToRight = new HashMap<>(arity); | 28 | leftToRight = new HashMap<>(arity); |
23 | rightToLeft = new HashMap<>(arity); | 29 | rightToLeft = new HashMap<>(arity); |
24 | for (int i = 0; i < arity; i++) { | 30 | for (int i = 0; i < arity; i++) { |
25 | if (!variableEqual(leftParameters.get(i), rightParameters.get(i))) { | 31 | if (!variableEqual(leftParameters.get(i).getVariable(), rightParameters.get(i).getVariable())) { |
26 | throw new IllegalArgumentException("Parameter lists cannot be unified: duplicate parameter " + i); | 32 | throw new IllegalArgumentException("Parameter lists cannot be unified: duplicate parameter " + i); |
27 | } | 33 | } |
28 | } | 34 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AbstractCallLiteral.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AbstractCallLiteral.java index 657ca26b..8ef8e8b4 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AbstractCallLiteral.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AbstractCallLiteral.java | |||
@@ -1,17 +1,26 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.literal; | 6 | package tools.refinery.store.query.literal; |
2 | 7 | ||
3 | import tools.refinery.store.query.Constraint; | 8 | import tools.refinery.store.query.Constraint; |
4 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | 9 | import tools.refinery.store.query.equality.LiteralEqualityHelper; |
5 | import tools.refinery.store.query.substitution.Substitution; | 10 | import tools.refinery.store.query.substitution.Substitution; |
11 | import tools.refinery.store.query.term.ParameterDirection; | ||
6 | import tools.refinery.store.query.term.Variable; | 12 | import tools.refinery.store.query.term.Variable; |
7 | 13 | ||
8 | import java.util.List; | 14 | import java.util.*; |
9 | import java.util.Objects; | ||
10 | 15 | ||
11 | public abstract class AbstractCallLiteral implements Literal { | 16 | public abstract class AbstractCallLiteral implements Literal { |
12 | private final Constraint target; | 17 | private final Constraint target; |
13 | private final List<Variable> arguments; | 18 | private final List<Variable> arguments; |
19 | private final Set<Variable> inArguments; | ||
20 | private final Set<Variable> outArguments; | ||
14 | 21 | ||
22 | // Use exhaustive switch over enums. | ||
23 | @SuppressWarnings("squid:S1301") | ||
15 | protected AbstractCallLiteral(Constraint target, List<Variable> arguments) { | 24 | protected AbstractCallLiteral(Constraint target, List<Variable> arguments) { |
16 | int arity = target.arity(); | 25 | int arity = target.arity(); |
17 | if (arguments.size() != arity) { | 26 | if (arguments.size() != arity) { |
@@ -20,14 +29,46 @@ public abstract class AbstractCallLiteral implements Literal { | |||
20 | } | 29 | } |
21 | this.target = target; | 30 | this.target = target; |
22 | this.arguments = arguments; | 31 | this.arguments = arguments; |
23 | var sorts = target.getSorts(); | 32 | var mutableInArguments = new LinkedHashSet<Variable>(); |
33 | var mutableOutArguments = new LinkedHashSet<Variable>(); | ||
34 | var parameters = target.getParameters(); | ||
24 | for (int i = 0; i < arity; i++) { | 35 | for (int i = 0; i < arity; i++) { |
25 | var argument = arguments.get(i); | 36 | var argument = arguments.get(i); |
26 | var sort = sorts.get(i); | 37 | var parameter = parameters.get(i); |
27 | if (!sort.isInstance(argument)) { | 38 | if (!parameter.isAssignable(argument)) { |
28 | throw new IllegalArgumentException("Required argument %d of %s to be of sort %s, but got %s instead" | 39 | throw new IllegalArgumentException("Argument %d of %s is not assignable to parameter %s" |
29 | .formatted(i, target, sort, argument.getSort())); | 40 | .formatted(i, target, parameter)); |
30 | } | 41 | } |
42 | switch (parameter.getDirection()) { | ||
43 | case IN -> { | ||
44 | if (mutableOutArguments.remove(argument)) { | ||
45 | checkInOutUnifiable(argument); | ||
46 | } | ||
47 | mutableInArguments.add(argument); | ||
48 | } | ||
49 | case OUT -> { | ||
50 | if (mutableInArguments.contains(argument)) { | ||
51 | checkInOutUnifiable(argument); | ||
52 | } else if (!mutableOutArguments.add(argument)) { | ||
53 | checkDuplicateOutUnifiable(argument); | ||
54 | } | ||
55 | } | ||
56 | } | ||
57 | } | ||
58 | inArguments = Collections.unmodifiableSet(mutableInArguments); | ||
59 | outArguments = Collections.unmodifiableSet(mutableOutArguments); | ||
60 | } | ||
61 | |||
62 | private static void checkInOutUnifiable(Variable argument) { | ||
63 | if (!argument.isUnifiable()) { | ||
64 | throw new IllegalArgumentException("Argument %s cannot appear with both %s and %s direction" | ||
65 | .formatted(argument, ParameterDirection.IN, ParameterDirection.OUT)); | ||
66 | } | ||
67 | } | ||
68 | |||
69 | private static void checkDuplicateOutUnifiable(Variable argument) { | ||
70 | if (!argument.isUnifiable()) { | ||
71 | throw new IllegalArgumentException("Argument %s cannot be bound multiple times".formatted(argument)); | ||
31 | } | 72 | } |
32 | } | 73 | } |
33 | 74 | ||
@@ -39,6 +80,28 @@ public abstract class AbstractCallLiteral implements Literal { | |||
39 | return arguments; | 80 | return arguments; |
40 | } | 81 | } |
41 | 82 | ||
83 | protected Set<Variable> getArgumentsOfDirection(ParameterDirection direction) { | ||
84 | return switch (direction) { | ||
85 | case IN -> inArguments; | ||
86 | case OUT -> outArguments; | ||
87 | }; | ||
88 | } | ||
89 | |||
90 | @Override | ||
91 | public Set<Variable> getInputVariables(Set<? extends Variable> positiveVariablesInClause) { | ||
92 | var inputVariables = new LinkedHashSet<>(getArgumentsOfDirection(ParameterDirection.OUT)); | ||
93 | inputVariables.retainAll(positiveVariablesInClause); | ||
94 | inputVariables.addAll(getArgumentsOfDirection(ParameterDirection.IN)); | ||
95 | return Collections.unmodifiableSet(inputVariables); | ||
96 | } | ||
97 | |||
98 | @Override | ||
99 | public Set<Variable> getPrivateVariables(Set<? extends Variable> positiveVariablesInClause) { | ||
100 | var privateVariables = new LinkedHashSet<>(getArgumentsOfDirection(ParameterDirection.OUT)); | ||
101 | privateVariables.removeAll(positiveVariablesInClause); | ||
102 | return Collections.unmodifiableSet(privateVariables); | ||
103 | } | ||
104 | |||
42 | @Override | 105 | @Override |
43 | public Literal substitute(Substitution substitution) { | 106 | public Literal substitute(Substitution substitution) { |
44 | var substitutedArguments = arguments.stream().map(substitution::getSubstitute).toList(); | 107 | var substitutedArguments = arguments.stream().map(substitution::getSubstitute).toList(); |
@@ -75,6 +138,6 @@ public abstract class AbstractCallLiteral implements Literal { | |||
75 | 138 | ||
76 | @Override | 139 | @Override |
77 | public int hashCode() { | 140 | public int hashCode() { |
78 | return Objects.hash(target, arguments); | 141 | return Objects.hash(getClass(), target, arguments); |
79 | } | 142 | } |
80 | } | 143 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AggregationLiteral.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AggregationLiteral.java index df64839c..3a5eb5c7 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AggregationLiteral.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AggregationLiteral.java | |||
@@ -1,11 +1,14 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.literal; | 6 | package tools.refinery.store.query.literal; |
2 | 7 | ||
3 | import tools.refinery.store.query.Constraint; | 8 | import tools.refinery.store.query.Constraint; |
4 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | 9 | import tools.refinery.store.query.equality.LiteralEqualityHelper; |
5 | import tools.refinery.store.query.substitution.Substitution; | 10 | import tools.refinery.store.query.substitution.Substitution; |
6 | import tools.refinery.store.query.term.Aggregator; | 11 | import tools.refinery.store.query.term.*; |
7 | import tools.refinery.store.query.term.DataVariable; | ||
8 | import tools.refinery.store.query.term.Variable; | ||
9 | 12 | ||
10 | import java.util.List; | 13 | import java.util.List; |
11 | import java.util.Objects; | 14 | import java.util.Objects; |
@@ -23,14 +26,14 @@ public class AggregationLiteral<R, T> extends AbstractCallLiteral { | |||
23 | throw new IllegalArgumentException("Input variable %s must of type %s, got %s instead".formatted( | 26 | throw new IllegalArgumentException("Input variable %s must of type %s, got %s instead".formatted( |
24 | inputVariable, aggregator.getInputType().getName(), inputVariable.getType().getName())); | 27 | inputVariable, aggregator.getInputType().getName(), inputVariable.getType().getName())); |
25 | } | 28 | } |
29 | if (!getArgumentsOfDirection(ParameterDirection.OUT).contains(inputVariable)) { | ||
30 | throw new IllegalArgumentException("Input variable %s must be bound with direction %s in the argument list" | ||
31 | .formatted(inputVariable, ParameterDirection.OUT)); | ||
32 | } | ||
26 | if (!resultVariable.getType().equals(aggregator.getResultType())) { | 33 | if (!resultVariable.getType().equals(aggregator.getResultType())) { |
27 | throw new IllegalArgumentException("Result variable %s must of type %s, got %s instead".formatted( | 34 | throw new IllegalArgumentException("Result variable %s must of type %s, got %s instead".formatted( |
28 | resultVariable, aggregator.getResultType().getName(), resultVariable.getType().getName())); | 35 | resultVariable, aggregator.getResultType().getName(), resultVariable.getType().getName())); |
29 | } | 36 | } |
30 | if (!arguments.contains(inputVariable)) { | ||
31 | throw new IllegalArgumentException("Input variable %s must appear in the argument list".formatted( | ||
32 | inputVariable)); | ||
33 | } | ||
34 | if (arguments.contains(resultVariable)) { | 37 | if (arguments.contains(resultVariable)) { |
35 | throw new IllegalArgumentException("Result variable %s must not appear in the argument list".formatted( | 38 | throw new IllegalArgumentException("Result variable %s must not appear in the argument list".formatted( |
36 | resultVariable)); | 39 | resultVariable)); |
@@ -53,11 +56,33 @@ public class AggregationLiteral<R, T> extends AbstractCallLiteral { | |||
53 | } | 56 | } |
54 | 57 | ||
55 | @Override | 58 | @Override |
56 | public Set<Variable> getBoundVariables() { | 59 | public Set<Variable> getOutputVariables() { |
57 | return Set.of(resultVariable); | 60 | return Set.of(resultVariable); |
58 | } | 61 | } |
59 | 62 | ||
60 | @Override | 63 | @Override |
64 | public Set<Variable> getInputVariables(Set<? extends Variable> positiveVariablesInClause) { | ||
65 | if (positiveVariablesInClause.contains(inputVariable)) { | ||
66 | throw new IllegalArgumentException("Aggregation variable %s must not be bound".formatted(inputVariable)); | ||
67 | } | ||
68 | return super.getInputVariables(positiveVariablesInClause); | ||
69 | } | ||
70 | |||
71 | @Override | ||
72 | public Literal reduce() { | ||
73 | var reduction = getTarget().getReduction(); | ||
74 | return switch (reduction) { | ||
75 | case ALWAYS_FALSE -> { | ||
76 | var emptyValue = aggregator.getEmptyResult(); | ||
77 | yield emptyValue == null ? BooleanLiteral.FALSE : | ||
78 | resultVariable.assign(new ConstantTerm<>(resultVariable.getType(), emptyValue)); | ||
79 | } | ||
80 | case ALWAYS_TRUE -> throw new IllegalArgumentException("Trying to aggregate over an infinite set"); | ||
81 | case NOT_REDUCIBLE -> this; | ||
82 | }; | ||
83 | } | ||
84 | |||
85 | @Override | ||
61 | protected Literal doSubstitute(Substitution substitution, List<Variable> substitutedArguments) { | 86 | protected Literal doSubstitute(Substitution substitution, List<Variable> substitutedArguments) { |
62 | return new AggregationLiteral<>(substitution.getTypeSafeSubstitute(resultVariable), aggregator, | 87 | return new AggregationLiteral<>(substitution.getTypeSafeSubstitute(resultVariable), aggregator, |
63 | substitution.getTypeSafeSubstitute(inputVariable), getTarget(), substitutedArguments); | 88 | substitution.getTypeSafeSubstitute(inputVariable), getTarget(), substitutedArguments); |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AssignLiteral.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AssignLiteral.java index 52ac42d7..dbf999a2 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AssignLiteral.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AssignLiteral.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.literal; | 6 | package tools.refinery.store.query.literal; |
2 | 7 | ||
3 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | 8 | import tools.refinery.store.query.equality.LiteralEqualityHelper; |
@@ -6,6 +11,8 @@ import tools.refinery.store.query.term.DataVariable; | |||
6 | import tools.refinery.store.query.term.Term; | 11 | import tools.refinery.store.query.term.Term; |
7 | import tools.refinery.store.query.term.Variable; | 12 | import tools.refinery.store.query.term.Variable; |
8 | 13 | ||
14 | import java.util.Collections; | ||
15 | import java.util.Objects; | ||
9 | import java.util.Set; | 16 | import java.util.Set; |
10 | 17 | ||
11 | public record AssignLiteral<T>(DataVariable<T> variable, Term<T> term) implements Literal { | 18 | public record AssignLiteral<T>(DataVariable<T> variable, Term<T> term) implements Literal { |
@@ -14,14 +21,29 @@ public record AssignLiteral<T>(DataVariable<T> variable, Term<T> term) implement | |||
14 | throw new IllegalArgumentException("Term %s must be of type %s, got %s instead".formatted( | 21 | throw new IllegalArgumentException("Term %s must be of type %s, got %s instead".formatted( |
15 | term, variable.getType().getName(), term.getType().getName())); | 22 | term, variable.getType().getName(), term.getType().getName())); |
16 | } | 23 | } |
24 | var inputVariables = term.getInputVariables(); | ||
25 | if (inputVariables.contains(variable)) { | ||
26 | throw new IllegalArgumentException("Result variable %s must not appear in the term %s".formatted( | ||
27 | variable, term)); | ||
28 | } | ||
17 | } | 29 | } |
18 | 30 | ||
19 | @Override | 31 | @Override |
20 | public Set<Variable> getBoundVariables() { | 32 | public Set<Variable> getOutputVariables() { |
21 | return Set.of(variable); | 33 | return Set.of(variable); |
22 | } | 34 | } |
23 | 35 | ||
24 | @Override | 36 | @Override |
37 | public Set<Variable> getInputVariables(Set<? extends Variable> positiveVariablesInClause) { | ||
38 | return Collections.unmodifiableSet(term.getInputVariables()); | ||
39 | } | ||
40 | |||
41 | @Override | ||
42 | public Set<Variable> getPrivateVariables(Set<? extends Variable> positiveVariablesInClause) { | ||
43 | return Set.of(); | ||
44 | } | ||
45 | |||
46 | @Override | ||
25 | public Literal substitute(Substitution substitution) { | 47 | public Literal substitute(Substitution substitution) { |
26 | return new AssignLiteral<>(substitution.getTypeSafeSubstitute(variable), term.substitute(substitution)); | 48 | return new AssignLiteral<>(substitution.getTypeSafeSubstitute(variable), term.substitute(substitution)); |
27 | } | 49 | } |
@@ -36,9 +58,22 @@ public record AssignLiteral<T>(DataVariable<T> variable, Term<T> term) implement | |||
36 | otherLetLiteral.term); | 58 | otherLetLiteral.term); |
37 | } | 59 | } |
38 | 60 | ||
39 | |||
40 | @Override | 61 | @Override |
41 | public String toString() { | 62 | public String toString() { |
42 | return "%s is (%s)".formatted(variable, term); | 63 | return "%s is (%s)".formatted(variable, term); |
43 | } | 64 | } |
65 | |||
66 | @Override | ||
67 | public boolean equals(Object obj) { | ||
68 | if (obj == this) return true; | ||
69 | if (obj == null || obj.getClass() != this.getClass()) return false; | ||
70 | var that = (AssignLiteral<?>) obj; | ||
71 | return Objects.equals(this.variable, that.variable) && | ||
72 | Objects.equals(this.term, that.term); | ||
73 | } | ||
74 | |||
75 | @Override | ||
76 | public int hashCode() { | ||
77 | return Objects.hash(getClass(), variable, term); | ||
78 | } | ||
44 | } | 79 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AssumeLiteral.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AssumeLiteral.java index 0b4267b4..1ca04c77 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AssumeLiteral.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/AssumeLiteral.java | |||
@@ -1,11 +1,18 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.literal; | 6 | package tools.refinery.store.query.literal; |
2 | 7 | ||
3 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | 8 | import tools.refinery.store.query.equality.LiteralEqualityHelper; |
4 | import tools.refinery.store.query.substitution.Substitution; | 9 | import tools.refinery.store.query.substitution.Substitution; |
10 | import tools.refinery.store.query.term.ConstantTerm; | ||
5 | import tools.refinery.store.query.term.Term; | 11 | import tools.refinery.store.query.term.Term; |
6 | import tools.refinery.store.query.term.Variable; | 12 | import tools.refinery.store.query.term.Variable; |
7 | import tools.refinery.store.query.term.bool.BoolConstantTerm; | ||
8 | 13 | ||
14 | import java.util.Collections; | ||
15 | import java.util.Objects; | ||
9 | import java.util.Set; | 16 | import java.util.Set; |
10 | 17 | ||
11 | public record AssumeLiteral(Term<Boolean> term) implements Literal { | 18 | public record AssumeLiteral(Term<Boolean> term) implements Literal { |
@@ -17,11 +24,22 @@ public record AssumeLiteral(Term<Boolean> term) implements Literal { | |||
17 | } | 24 | } |
18 | 25 | ||
19 | @Override | 26 | @Override |
20 | public Set<Variable> getBoundVariables() { | 27 | public Set<Variable> getOutputVariables() { |
21 | return Set.of(); | 28 | return Set.of(); |
22 | } | 29 | } |
23 | 30 | ||
24 | @Override | 31 | @Override |
32 | public Set<Variable> getInputVariables(Set<? extends Variable> positiveVariablesInClause) { | ||
33 | return Collections.unmodifiableSet(term.getInputVariables()); | ||
34 | } | ||
35 | |||
36 | @Override | ||
37 | public Set<Variable> getPrivateVariables(Set<? extends Variable> positiveVariablesInClause) { | ||
38 | return Set.of(); | ||
39 | } | ||
40 | |||
41 | |||
42 | @Override | ||
25 | public Literal substitute(Substitution substitution) { | 43 | public Literal substitute(Substitution substitution) { |
26 | return new AssumeLiteral(term.substitute(substitution)); | 44 | return new AssumeLiteral(term.substitute(substitution)); |
27 | } | 45 | } |
@@ -36,18 +54,30 @@ public record AssumeLiteral(Term<Boolean> term) implements Literal { | |||
36 | } | 54 | } |
37 | 55 | ||
38 | @Override | 56 | @Override |
39 | public LiteralReduction getReduction() { | 57 | public Literal reduce() { |
40 | if (BoolConstantTerm.TRUE.equals(term)) { | 58 | if (term instanceof ConstantTerm<Boolean> constantTerm) { |
41 | return LiteralReduction.ALWAYS_TRUE; | 59 | // Return {@link BooleanLiteral#FALSE} for {@code false} or {@code null} literals. |
42 | } else if (BoolConstantTerm.FALSE.equals(term)) { | 60 | return Boolean.TRUE.equals(constantTerm.getValue()) ? BooleanLiteral.TRUE : |
43 | return LiteralReduction.ALWAYS_FALSE; | 61 | BooleanLiteral.FALSE; |
44 | } else { | ||
45 | return LiteralReduction.NOT_REDUCIBLE; | ||
46 | } | 62 | } |
63 | return this; | ||
47 | } | 64 | } |
48 | 65 | ||
49 | @Override | 66 | @Override |
50 | public String toString() { | 67 | public String toString() { |
51 | return "(%s)".formatted(term); | 68 | return "(%s)".formatted(term); |
52 | } | 69 | } |
70 | |||
71 | @Override | ||
72 | public boolean equals(Object obj) { | ||
73 | if (obj == this) return true; | ||
74 | if (obj == null || obj.getClass() != this.getClass()) return false; | ||
75 | var that = (AssumeLiteral) obj; | ||
76 | return Objects.equals(this.term, that.term); | ||
77 | } | ||
78 | |||
79 | @Override | ||
80 | public int hashCode() { | ||
81 | return Objects.hash(getClass(), term); | ||
82 | } | ||
53 | } | 83 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/BooleanLiteral.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/BooleanLiteral.java index 38be61a4..f312d202 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/BooleanLiteral.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/BooleanLiteral.java | |||
@@ -1,8 +1,13 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.literal; | 6 | package tools.refinery.store.query.literal; |
2 | 7 | ||
3 | import tools.refinery.store.query.term.Variable; | ||
4 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | 8 | import tools.refinery.store.query.equality.LiteralEqualityHelper; |
5 | import tools.refinery.store.query.substitution.Substitution; | 9 | import tools.refinery.store.query.substitution.Substitution; |
10 | import tools.refinery.store.query.term.Variable; | ||
6 | 11 | ||
7 | import java.util.Set; | 12 | import java.util.Set; |
8 | 13 | ||
@@ -17,19 +22,24 @@ public enum BooleanLiteral implements CanNegate<BooleanLiteral> { | |||
17 | } | 22 | } |
18 | 23 | ||
19 | @Override | 24 | @Override |
20 | public Set<Variable> getBoundVariables() { | 25 | public Set<Variable> getOutputVariables() { |
21 | return Set.of(); | 26 | return Set.of(); |
22 | } | 27 | } |
23 | 28 | ||
24 | @Override | 29 | @Override |
25 | public Literal substitute(Substitution substitution) { | 30 | public Set<Variable> getInputVariables(Set<? extends Variable> positiveVariablesInClause) { |
26 | // No variables to substitute. | 31 | return Set.of(); |
27 | return this; | ||
28 | } | 32 | } |
29 | 33 | ||
30 | @Override | 34 | @Override |
31 | public LiteralReduction getReduction() { | 35 | public Set<Variable> getPrivateVariables(Set<? extends Variable> positiveVariablesInClause) { |
32 | return value ? LiteralReduction.ALWAYS_TRUE : LiteralReduction.ALWAYS_FALSE; | 36 | return Set.of(); |
37 | } | ||
38 | |||
39 | @Override | ||
40 | public Literal substitute(Substitution substitution) { | ||
41 | // No variables to substitute. | ||
42 | return this; | ||
33 | } | 43 | } |
34 | 44 | ||
35 | @Override | 45 | @Override |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/CallLiteral.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/CallLiteral.java index 78fae7f5..29772aee 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/CallLiteral.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/CallLiteral.java | |||
@@ -1,26 +1,30 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.literal; | 6 | package tools.refinery.store.query.literal; |
2 | 7 | ||
3 | import tools.refinery.store.query.Constraint; | 8 | import tools.refinery.store.query.Constraint; |
4 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | 9 | import tools.refinery.store.query.equality.LiteralEqualityHelper; |
5 | import tools.refinery.store.query.substitution.Substitution; | 10 | import tools.refinery.store.query.substitution.Substitution; |
6 | import tools.refinery.store.query.term.NodeSort; | 11 | import tools.refinery.store.query.term.ParameterDirection; |
7 | import tools.refinery.store.query.term.Variable; | 12 | import tools.refinery.store.query.term.Variable; |
8 | 13 | ||
9 | import java.util.List; | 14 | import java.util.*; |
10 | import java.util.Objects; | ||
11 | import java.util.Set; | ||
12 | 15 | ||
13 | public final class CallLiteral extends AbstractCallLiteral implements CanNegate<CallLiteral> { | 16 | public final class CallLiteral extends AbstractCallLiteral implements CanNegate<CallLiteral> { |
14 | private final CallPolarity polarity; | 17 | private final CallPolarity polarity; |
15 | 18 | ||
16 | public CallLiteral(CallPolarity polarity, Constraint target, List<Variable> arguments) { | 19 | public CallLiteral(CallPolarity polarity, Constraint target, List<Variable> arguments) { |
17 | super(target, arguments); | 20 | super(target, arguments); |
21 | var parameters = target.getParameters(); | ||
22 | int arity = target.arity(); | ||
18 | if (polarity.isTransitive()) { | 23 | if (polarity.isTransitive()) { |
19 | if (target.arity() != 2) { | 24 | if (arity != 2) { |
20 | throw new IllegalArgumentException("Transitive closures can only take binary relations"); | 25 | throw new IllegalArgumentException("Transitive closures can only take binary relations"); |
21 | } | 26 | } |
22 | var sorts = target.getSorts(); | 27 | if (parameters.get(0).isDataVariable() || parameters.get(1).isDataVariable()) { |
23 | if (!sorts.get(0).equals(NodeSort.INSTANCE) || !sorts.get(1).equals(NodeSort.INSTANCE)) { | ||
24 | throw new IllegalArgumentException("Transitive closures can only be computed over nodes"); | 28 | throw new IllegalArgumentException("Transitive closures can only be computed over nodes"); |
25 | } | 29 | } |
26 | } | 30 | } |
@@ -32,19 +36,43 @@ public final class CallLiteral extends AbstractCallLiteral implements CanNegate< | |||
32 | } | 36 | } |
33 | 37 | ||
34 | @Override | 38 | @Override |
35 | public Set<Variable> getBoundVariables() { | 39 | protected Literal doSubstitute(Substitution substitution, List<Variable> substitutedArguments) { |
36 | return polarity.isPositive() ? Set.copyOf(getArguments()) : Set.of(); | 40 | return new CallLiteral(polarity, getTarget(), substitutedArguments); |
37 | } | 41 | } |
38 | 42 | ||
39 | @Override | 43 | @Override |
40 | protected Literal doSubstitute(Substitution substitution, List<Variable> substitutedArguments) { | 44 | public Set<Variable> getOutputVariables() { |
41 | return new CallLiteral(polarity, getTarget(), substitutedArguments); | 45 | if (polarity.isPositive()) { |
46 | return getArgumentsOfDirection(ParameterDirection.OUT); | ||
47 | } | ||
48 | return Set.of(); | ||
49 | } | ||
50 | |||
51 | @Override | ||
52 | public Set<Variable> getInputVariables(Set<? extends Variable> positiveVariablesInClause) { | ||
53 | if (polarity.isPositive()) { | ||
54 | return getArgumentsOfDirection(ParameterDirection.IN); | ||
55 | } | ||
56 | return super.getInputVariables(positiveVariablesInClause); | ||
57 | } | ||
58 | |||
59 | @Override | ||
60 | public Set<Variable> getPrivateVariables(Set<? extends Variable> positiveVariablesInClause) { | ||
61 | if (polarity.isPositive()) { | ||
62 | return Set.of(); | ||
63 | } | ||
64 | return super.getPrivateVariables(positiveVariablesInClause); | ||
42 | } | 65 | } |
43 | 66 | ||
44 | @Override | 67 | @Override |
45 | public LiteralReduction getReduction() { | 68 | public Literal reduce() { |
46 | var reduction = getTarget().getReduction(); | 69 | var reduction = getTarget().getReduction(); |
47 | return polarity.isPositive() ? reduction : reduction.negate(); | 70 | var negatedReduction = polarity.isPositive() ? reduction : reduction.negate(); |
71 | return switch (negatedReduction) { | ||
72 | case ALWAYS_TRUE -> BooleanLiteral.TRUE; | ||
73 | case ALWAYS_FALSE -> BooleanLiteral.FALSE; | ||
74 | default -> this; | ||
75 | }; | ||
48 | } | 76 | } |
49 | 77 | ||
50 | @Override | 78 | @Override |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/CallPolarity.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/CallPolarity.java index 84b4b771..ca70b0fd 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/CallPolarity.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/CallPolarity.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.literal; | 6 | package tools.refinery.store.query.literal; |
2 | 7 | ||
3 | public enum CallPolarity { | 8 | public enum CallPolarity { |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/CanNegate.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/CanNegate.java index 3e159c43..35dcb3fb 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/CanNegate.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/CanNegate.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.literal; | 6 | package tools.refinery.store.query.literal; |
2 | 7 | ||
3 | public interface CanNegate<T extends CanNegate<T>> extends Literal { | 8 | public interface CanNegate<T extends CanNegate<T>> extends Literal { |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/ConstantLiteral.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/ConstantLiteral.java index 93fa3df0..73545620 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/ConstantLiteral.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/ConstantLiteral.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.literal; | 6 | package tools.refinery.store.query.literal; |
2 | 7 | ||
3 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | 8 | import tools.refinery.store.query.equality.LiteralEqualityHelper; |
@@ -5,15 +10,26 @@ import tools.refinery.store.query.substitution.Substitution; | |||
5 | import tools.refinery.store.query.term.NodeVariable; | 10 | import tools.refinery.store.query.term.NodeVariable; |
6 | import tools.refinery.store.query.term.Variable; | 11 | import tools.refinery.store.query.term.Variable; |
7 | 12 | ||
13 | import java.util.Objects; | ||
8 | import java.util.Set; | 14 | import java.util.Set; |
9 | 15 | ||
10 | public record ConstantLiteral(NodeVariable variable, int nodeId) implements Literal { | 16 | public record ConstantLiteral(NodeVariable variable, int nodeId) implements Literal { |
11 | @Override | 17 | @Override |
12 | public Set<Variable> getBoundVariables() { | 18 | public Set<Variable> getOutputVariables() { |
13 | return Set.of(variable); | 19 | return Set.of(variable); |
14 | } | 20 | } |
15 | 21 | ||
16 | @Override | 22 | @Override |
23 | public Set<Variable> getInputVariables(Set<? extends Variable> positiveVariablesInClause) { | ||
24 | return Set.of(); | ||
25 | } | ||
26 | |||
27 | @Override | ||
28 | public Set<Variable> getPrivateVariables(Set<? extends Variable> positiveVariablesInClause) { | ||
29 | return Set.of(); | ||
30 | } | ||
31 | |||
32 | @Override | ||
17 | public ConstantLiteral substitute(Substitution substitution) { | 33 | public ConstantLiteral substitute(Substitution substitution) { |
18 | return new ConstantLiteral(substitution.getTypeSafeSubstitute(variable), nodeId); | 34 | return new ConstantLiteral(substitution.getTypeSafeSubstitute(variable), nodeId); |
19 | } | 35 | } |
@@ -27,8 +43,23 @@ public record ConstantLiteral(NodeVariable variable, int nodeId) implements Lite | |||
27 | return helper.variableEqual(variable, otherConstantLiteral.variable) && nodeId == otherConstantLiteral.nodeId; | 43 | return helper.variableEqual(variable, otherConstantLiteral.variable) && nodeId == otherConstantLiteral.nodeId; |
28 | } | 44 | } |
29 | 45 | ||
46 | |||
30 | @Override | 47 | @Override |
31 | public String toString() { | 48 | public String toString() { |
32 | return "%s === @Constant %d".formatted(variable, nodeId); | 49 | return "%s === @Constant %d".formatted(variable, nodeId); |
33 | } | 50 | } |
51 | |||
52 | @Override | ||
53 | public boolean equals(Object obj) { | ||
54 | if (obj == this) return true; | ||
55 | if (obj == null || obj.getClass() != this.getClass()) return false; | ||
56 | var that = (ConstantLiteral) obj; | ||
57 | return Objects.equals(this.variable, that.variable) && | ||
58 | this.nodeId == that.nodeId; | ||
59 | } | ||
60 | |||
61 | @Override | ||
62 | public int hashCode() { | ||
63 | return Objects.hash(getClass(), variable, nodeId); | ||
64 | } | ||
34 | } | 65 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/CountLiteral.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/CountLiteral.java index 32e7ba3a..4d4749c8 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/CountLiteral.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/CountLiteral.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.literal; | 6 | package tools.refinery.store.query.literal; |
2 | 7 | ||
3 | import tools.refinery.store.query.Constraint; | 8 | import tools.refinery.store.query.Constraint; |
@@ -5,6 +10,7 @@ import tools.refinery.store.query.equality.LiteralEqualityHelper; | |||
5 | import tools.refinery.store.query.substitution.Substitution; | 10 | import tools.refinery.store.query.substitution.Substitution; |
6 | import tools.refinery.store.query.term.DataVariable; | 11 | import tools.refinery.store.query.term.DataVariable; |
7 | import tools.refinery.store.query.term.Variable; | 12 | import tools.refinery.store.query.term.Variable; |
13 | import tools.refinery.store.query.term.int_.IntTerms; | ||
8 | 14 | ||
9 | import java.util.List; | 15 | import java.util.List; |
10 | import java.util.Objects; | 16 | import java.util.Objects; |
@@ -31,11 +37,23 @@ public class CountLiteral extends AbstractCallLiteral { | |||
31 | } | 37 | } |
32 | 38 | ||
33 | @Override | 39 | @Override |
34 | public Set<Variable> getBoundVariables() { | 40 | public Set<Variable> getOutputVariables() { |
35 | return Set.of(resultVariable); | 41 | return Set.of(resultVariable); |
36 | } | 42 | } |
37 | 43 | ||
38 | @Override | 44 | @Override |
45 | public Literal reduce() { | ||
46 | var reduction = getTarget().getReduction(); | ||
47 | return switch (reduction) { | ||
48 | case ALWAYS_FALSE -> getResultVariable().assign(IntTerms.constant(0)); | ||
49 | // The only way a constant {@code true} predicate can be called in a negative position is to have all of | ||
50 | // its arguments bound as input variables. Thus, there will only be a single match. | ||
51 | case ALWAYS_TRUE -> getResultVariable().assign(IntTerms.constant(1)); | ||
52 | case NOT_REDUCIBLE -> this; | ||
53 | }; | ||
54 | } | ||
55 | |||
56 | @Override | ||
39 | protected Literal doSubstitute(Substitution substitution, List<Variable> substitutedArguments) { | 57 | protected Literal doSubstitute(Substitution substitution, List<Variable> substitutedArguments) { |
40 | return new CountLiteral(substitution.getTypeSafeSubstitute(resultVariable), getTarget(), substitutedArguments); | 58 | return new CountLiteral(substitution.getTypeSafeSubstitute(resultVariable), getTarget(), substitutedArguments); |
41 | } | 59 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/EquivalenceLiteral.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/EquivalenceLiteral.java index 4dc86b98..28ba7625 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/EquivalenceLiteral.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/EquivalenceLiteral.java | |||
@@ -1,18 +1,32 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.literal; | 6 | package tools.refinery.store.query.literal; |
2 | 7 | ||
3 | import tools.refinery.store.query.term.NodeVariable; | ||
4 | import tools.refinery.store.query.term.Variable; | ||
5 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | 8 | import tools.refinery.store.query.equality.LiteralEqualityHelper; |
6 | import tools.refinery.store.query.substitution.Substitution; | 9 | import tools.refinery.store.query.substitution.Substitution; |
10 | import tools.refinery.store.query.term.NodeVariable; | ||
11 | import tools.refinery.store.query.term.Variable; | ||
7 | 12 | ||
13 | import java.util.Objects; | ||
8 | import java.util.Set; | 14 | import java.util.Set; |
9 | 15 | ||
10 | public record EquivalenceLiteral(boolean positive, NodeVariable left, NodeVariable right) | 16 | public record EquivalenceLiteral(boolean positive, NodeVariable left, NodeVariable right) |
11 | implements CanNegate<EquivalenceLiteral> { | 17 | implements CanNegate<EquivalenceLiteral> { |
12 | @Override | 18 | @Override |
13 | public Set<Variable> getBoundVariables() { | 19 | public Set<Variable> getOutputVariables() { |
14 | // If one side of a {@code positive} equivalence is bound, it may bind its other side, but we under-approximate | 20 | return Set.of(left); |
15 | // this behavior by not binding any of the sides by default. | 21 | } |
22 | |||
23 | @Override | ||
24 | public Set<Variable> getInputVariables(Set<? extends Variable> positiveVariablesInClause) { | ||
25 | return Set.of(right); | ||
26 | } | ||
27 | |||
28 | @Override | ||
29 | public Set<Variable> getPrivateVariables(Set<? extends Variable> positiveVariablesInClause) { | ||
16 | return Set.of(); | 30 | return Set.of(); |
17 | } | 31 | } |
18 | 32 | ||
@@ -28,11 +42,11 @@ public record EquivalenceLiteral(boolean positive, NodeVariable left, NodeVariab | |||
28 | } | 42 | } |
29 | 43 | ||
30 | @Override | 44 | @Override |
31 | public LiteralReduction getReduction() { | 45 | public Literal reduce() { |
32 | if (left.equals(right)) { | 46 | if (left.equals(right)) { |
33 | return positive ? LiteralReduction.ALWAYS_TRUE : LiteralReduction.ALWAYS_FALSE; | 47 | return positive ? BooleanLiteral.TRUE : BooleanLiteral.FALSE; |
34 | } | 48 | } |
35 | return LiteralReduction.NOT_REDUCIBLE; | 49 | return this; |
36 | } | 50 | } |
37 | 51 | ||
38 | @Override | 52 | @Override |
@@ -49,4 +63,19 @@ public record EquivalenceLiteral(boolean positive, NodeVariable left, NodeVariab | |||
49 | public String toString() { | 63 | public String toString() { |
50 | return "%s %s %s".formatted(left, positive ? "===" : "!==", right); | 64 | return "%s %s %s".formatted(left, positive ? "===" : "!==", right); |
51 | } | 65 | } |
66 | |||
67 | @Override | ||
68 | public boolean equals(Object obj) { | ||
69 | if (obj == this) return true; | ||
70 | if (obj == null || obj.getClass() != this.getClass()) return false; | ||
71 | var that = (EquivalenceLiteral) obj; | ||
72 | return this.positive == that.positive && | ||
73 | Objects.equals(this.left, that.left) && | ||
74 | Objects.equals(this.right, that.right); | ||
75 | } | ||
76 | |||
77 | @Override | ||
78 | public int hashCode() { | ||
79 | return Objects.hash(getClass(), positive, left, right); | ||
80 | } | ||
52 | } | 81 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/Literal.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/Literal.java index 6347410e..ce6c11fe 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/Literal.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/Literal.java | |||
@@ -1,18 +1,27 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.literal; | 6 | package tools.refinery.store.query.literal; |
2 | 7 | ||
3 | import tools.refinery.store.query.term.Variable; | ||
4 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | 8 | import tools.refinery.store.query.equality.LiteralEqualityHelper; |
5 | import tools.refinery.store.query.substitution.Substitution; | 9 | import tools.refinery.store.query.substitution.Substitution; |
10 | import tools.refinery.store.query.term.Variable; | ||
6 | 11 | ||
7 | import java.util.Set; | 12 | import java.util.Set; |
8 | 13 | ||
9 | public interface Literal { | 14 | public interface Literal { |
10 | Set<Variable> getBoundVariables(); | 15 | Set<Variable> getOutputVariables(); |
16 | |||
17 | Set<Variable> getInputVariables(Set<? extends Variable> positiveVariablesInClause); | ||
18 | |||
19 | Set<Variable> getPrivateVariables(Set<? extends Variable> positiveVariablesInClause); | ||
11 | 20 | ||
12 | Literal substitute(Substitution substitution); | 21 | Literal substitute(Substitution substitution); |
13 | 22 | ||
14 | default LiteralReduction getReduction() { | 23 | default Literal reduce() { |
15 | return LiteralReduction.NOT_REDUCIBLE; | 24 | return this; |
16 | } | 25 | } |
17 | 26 | ||
18 | @SuppressWarnings("BooleanMethodIsAlwaysInverted") | 27 | @SuppressWarnings("BooleanMethodIsAlwaysInverted") |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/Literals.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/Literals.java index 89039352..b3a87811 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/Literals.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/literal/Literals.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.literal; | 6 | package tools.refinery.store.query.literal; |
2 | 7 | ||
3 | import tools.refinery.store.query.term.Term; | 8 | import tools.refinery.store.query.term.Term; |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/CompositeSubstitution.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/CompositeSubstitution.java deleted file mode 100644 index f8064ca2..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/CompositeSubstitution.java +++ /dev/null | |||
@@ -1,10 +0,0 @@ | |||
1 | package tools.refinery.store.query.substitution; | ||
2 | |||
3 | import tools.refinery.store.query.term.Variable; | ||
4 | |||
5 | public record CompositeSubstitution(Substitution first, Substitution second) implements Substitution { | ||
6 | @Override | ||
7 | public Variable getSubstitute(Variable variable) { | ||
8 | return second.getSubstitute(first.getSubstitute(variable)); | ||
9 | } | ||
10 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/MapBasedSubstitution.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/MapBasedSubstitution.java index c7754619..a8201eef 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/MapBasedSubstitution.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/MapBasedSubstitution.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.substitution; | 6 | package tools.refinery.store.query.substitution; |
2 | 7 | ||
3 | import tools.refinery.store.query.term.Variable; | 8 | import tools.refinery.store.query.term.Variable; |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/RenewingSubstitution.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/RenewingSubstitution.java index 7847e582..9b737ceb 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/RenewingSubstitution.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/RenewingSubstitution.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.substitution; | 6 | package tools.refinery.store.query.substitution; |
2 | 7 | ||
3 | import tools.refinery.store.query.term.Variable; | 8 | import tools.refinery.store.query.term.Variable; |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/StatelessSubstitution.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/StatelessSubstitution.java index eed414d9..bb3803d3 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/StatelessSubstitution.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/StatelessSubstitution.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.substitution; | 6 | package tools.refinery.store.query.substitution; |
2 | 7 | ||
3 | import tools.refinery.store.query.term.Variable; | 8 | import tools.refinery.store.query.term.Variable; |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/Substitution.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/Substitution.java index 99f84b9e..834fce12 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/Substitution.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/Substitution.java | |||
@@ -1,6 +1,10 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.substitution; | 6 | package tools.refinery.store.query.substitution; |
2 | 7 | ||
3 | import tools.refinery.store.query.term.AnyDataVariable; | ||
4 | import tools.refinery.store.query.term.DataVariable; | 8 | import tools.refinery.store.query.term.DataVariable; |
5 | import tools.refinery.store.query.term.NodeVariable; | 9 | import tools.refinery.store.query.term.NodeVariable; |
6 | import tools.refinery.store.query.term.Variable; | 10 | import tools.refinery.store.query.term.Variable; |
@@ -14,16 +18,12 @@ public interface Substitution { | |||
14 | return substitute.asNodeVariable(); | 18 | return substitute.asNodeVariable(); |
15 | } | 19 | } |
16 | 20 | ||
17 | default AnyDataVariable getTypeSafeSubstitute(AnyDataVariable variable) { | ||
18 | return getTypeSafeSubstitute((DataVariable<?>) variable); | ||
19 | } | ||
20 | |||
21 | default <T> DataVariable<T> getTypeSafeSubstitute(DataVariable<T> variable) { | 21 | default <T> DataVariable<T> getTypeSafeSubstitute(DataVariable<T> variable) { |
22 | var substitute = getSubstitute(variable); | 22 | var substitute = getSubstitute(variable); |
23 | return substitute.asDataVariable(variable.getType()); | 23 | return substitute.asDataVariable(variable.getType()); |
24 | } | 24 | } |
25 | 25 | ||
26 | default Substitution andThen(Substitution second) { | 26 | static SubstitutionBuilder builder() { |
27 | return new CompositeSubstitution(this, second); | 27 | return new SubstitutionBuilder(); |
28 | } | 28 | } |
29 | } | 29 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/SubstitutionBuilder.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/SubstitutionBuilder.java new file mode 100644 index 00000000..37fb6908 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/SubstitutionBuilder.java | |||
@@ -0,0 +1,79 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.substitution; | ||
7 | |||
8 | import tools.refinery.store.query.term.DataVariable; | ||
9 | import tools.refinery.store.query.term.NodeVariable; | ||
10 | import tools.refinery.store.query.term.Variable; | ||
11 | |||
12 | import java.util.Collections; | ||
13 | import java.util.HashMap; | ||
14 | import java.util.List; | ||
15 | import java.util.Map; | ||
16 | |||
17 | @SuppressWarnings("UnusedReturnValue") | ||
18 | public class SubstitutionBuilder { | ||
19 | private final Map<Variable, Variable> map = new HashMap<>(); | ||
20 | private Substitution fallback; | ||
21 | |||
22 | SubstitutionBuilder() { | ||
23 | total(); | ||
24 | } | ||
25 | |||
26 | public SubstitutionBuilder put(NodeVariable original, NodeVariable substitute) { | ||
27 | return putChecked(original, substitute); | ||
28 | } | ||
29 | |||
30 | public <T> SubstitutionBuilder put(DataVariable<T> original, DataVariable<T> substitute) { | ||
31 | return putChecked(original, substitute); | ||
32 | } | ||
33 | |||
34 | public SubstitutionBuilder putChecked(Variable original, Variable substitute) { | ||
35 | if (!original.tryGetType().equals(substitute.tryGetType())) { | ||
36 | throw new IllegalArgumentException("Cannot substitute variable %s of sort %s with variable %s of sort %s" | ||
37 | .formatted(original, original.tryGetType().map(Class::getName).orElse("node"), substitute, | ||
38 | substitute.tryGetType().map(Class::getName).orElse("node"))); | ||
39 | } | ||
40 | if (map.containsKey(original)) { | ||
41 | throw new IllegalArgumentException("Already has substitution for variable %s".formatted(original)); | ||
42 | } | ||
43 | map.put(original, substitute); | ||
44 | return this; | ||
45 | } | ||
46 | |||
47 | public SubstitutionBuilder putManyChecked(List<Variable> originals, List<Variable> substitutes) { | ||
48 | int size = originals.size(); | ||
49 | if (size != substitutes.size()) { | ||
50 | throw new IllegalArgumentException("Cannot substitute %d variables %s with %d variables %s" | ||
51 | .formatted(size, originals, substitutes.size(), substitutes)); | ||
52 | } | ||
53 | for (int i = 0; i < size; i++) { | ||
54 | putChecked(originals.get(i), substitutes.get(i)); | ||
55 | } | ||
56 | return this; | ||
57 | } | ||
58 | |||
59 | public SubstitutionBuilder fallback(Substitution newFallback) { | ||
60 | fallback = newFallback; | ||
61 | return this; | ||
62 | } | ||
63 | |||
64 | public SubstitutionBuilder total() { | ||
65 | return fallback(StatelessSubstitution.FAILING); | ||
66 | } | ||
67 | |||
68 | public SubstitutionBuilder partial() { | ||
69 | return fallback(StatelessSubstitution.IDENTITY); | ||
70 | } | ||
71 | |||
72 | public SubstitutionBuilder renewing() { | ||
73 | return fallback(new RenewingSubstitution()); | ||
74 | } | ||
75 | |||
76 | public Substitution build() { | ||
77 | return map.isEmpty() ? fallback : new MapBasedSubstitution(Collections.unmodifiableMap(map), fallback); | ||
78 | } | ||
79 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/Substitutions.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/Substitutions.java deleted file mode 100644 index 5d4654da..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/substitution/Substitutions.java +++ /dev/null | |||
@@ -1,33 +0,0 @@ | |||
1 | package tools.refinery.store.query.substitution; | ||
2 | |||
3 | import org.jetbrains.annotations.NotNull; | ||
4 | import org.jetbrains.annotations.Nullable; | ||
5 | import tools.refinery.store.query.term.Variable; | ||
6 | |||
7 | import java.util.Map; | ||
8 | |||
9 | public final class Substitutions { | ||
10 | private Substitutions() { | ||
11 | throw new IllegalStateException("This is a static utility class and should not be instantiate directly"); | ||
12 | } | ||
13 | |||
14 | public static Substitution total(Map<Variable, Variable> map) { | ||
15 | return new MapBasedSubstitution(map, StatelessSubstitution.FAILING); | ||
16 | } | ||
17 | |||
18 | public static Substitution partial(Map<Variable, Variable> map) { | ||
19 | return new MapBasedSubstitution(map, StatelessSubstitution.IDENTITY); | ||
20 | } | ||
21 | |||
22 | public static Substitution renewing(Map<Variable, Variable> map) { | ||
23 | return new MapBasedSubstitution(map, renewing()); | ||
24 | } | ||
25 | |||
26 | public static Substitution renewing() { | ||
27 | return new RenewingSubstitution(); | ||
28 | } | ||
29 | |||
30 | public static Substitution compose(@Nullable Substitution first, @NotNull Substitution second) { | ||
31 | return first == null ? second : first.andThen(second); | ||
32 | } | ||
33 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/AbstractTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/AbstractTerm.java new file mode 100644 index 00000000..d0ae3c12 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/AbstractTerm.java | |||
@@ -0,0 +1,41 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term; | ||
7 | |||
8 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | ||
9 | |||
10 | import java.util.Objects; | ||
11 | |||
12 | public abstract class AbstractTerm<T> implements Term<T> { | ||
13 | private final Class<T> type; | ||
14 | |||
15 | protected AbstractTerm(Class<T> type) { | ||
16 | this.type = type; | ||
17 | } | ||
18 | |||
19 | @Override | ||
20 | public boolean equalsWithSubstitution(LiteralEqualityHelper helper, AnyTerm other) { | ||
21 | return getClass().equals(other.getClass()) && type.equals(other.getType()); | ||
22 | } | ||
23 | |||
24 | @Override | ||
25 | public Class<T> getType() { | ||
26 | return type; | ||
27 | } | ||
28 | |||
29 | @Override | ||
30 | public boolean equals(Object o) { | ||
31 | if (this == o) return true; | ||
32 | if (o == null || getClass() != o.getClass()) return false; | ||
33 | AbstractTerm<?> that = (AbstractTerm<?>) o; | ||
34 | return type.equals(that.type); | ||
35 | } | ||
36 | |||
37 | @Override | ||
38 | public int hashCode() { | ||
39 | return Objects.hash(getClass(), type); | ||
40 | } | ||
41 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/Aggregator.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/Aggregator.java index 47421a94..0684a9d9 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/Aggregator.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/Aggregator.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.term; | 6 | package tools.refinery.store.query.term; |
2 | 7 | ||
3 | import java.util.stream.Stream; | 8 | import java.util.stream.Stream; |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/AnyDataVariable.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/AnyDataVariable.java index ecfefcf9..192c39c5 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/AnyDataVariable.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/AnyDataVariable.java | |||
@@ -1,8 +1,14 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.term; | 6 | package tools.refinery.store.query.term; |
2 | 7 | ||
3 | import org.jetbrains.annotations.Nullable; | 8 | import org.jetbrains.annotations.Nullable; |
4 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | 9 | import tools.refinery.store.query.equality.LiteralEqualityHelper; |
5 | 10 | ||
11 | import java.util.Optional; | ||
6 | import java.util.Set; | 12 | import java.util.Set; |
7 | 13 | ||
8 | public abstract sealed class AnyDataVariable extends Variable implements AnyTerm permits DataVariable { | 14 | public abstract sealed class AnyDataVariable extends Variable implements AnyTerm permits DataVariable { |
@@ -11,6 +17,11 @@ public abstract sealed class AnyDataVariable extends Variable implements AnyTerm | |||
11 | } | 17 | } |
12 | 18 | ||
13 | @Override | 19 | @Override |
20 | public Optional<Class<?>> tryGetType() { | ||
21 | return Optional.of(getType()); | ||
22 | } | ||
23 | |||
24 | @Override | ||
14 | public NodeVariable asNodeVariable() { | 25 | public NodeVariable asNodeVariable() { |
15 | throw new IllegalStateException("%s is a data variable".formatted(this)); | 26 | throw new IllegalStateException("%s is a data variable".formatted(this)); |
16 | } | 27 | } |
@@ -26,6 +37,11 @@ public abstract sealed class AnyDataVariable extends Variable implements AnyTerm | |||
26 | } | 37 | } |
27 | 38 | ||
28 | @Override | 39 | @Override |
40 | public boolean isUnifiable() { | ||
41 | return false; | ||
42 | } | ||
43 | |||
44 | @Override | ||
29 | public abstract AnyDataVariable renew(@Nullable String name); | 45 | public abstract AnyDataVariable renew(@Nullable String name); |
30 | 46 | ||
31 | @Override | 47 | @Override |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/AnyTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/AnyTerm.java index 8f998d45..c12c0166 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/AnyTerm.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/AnyTerm.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.term; | 6 | package tools.refinery.store.query.term; |
2 | 7 | ||
3 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | 8 | import tools.refinery.store.query.equality.LiteralEqualityHelper; |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ArithmeticBinaryOperator.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ArithmeticBinaryOperator.java deleted file mode 100644 index 8706a046..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ArithmeticBinaryOperator.java +++ /dev/null | |||
@@ -1,26 +0,0 @@ | |||
1 | package tools.refinery.store.query.term; | ||
2 | |||
3 | public enum ArithmeticBinaryOperator { | ||
4 | ADD("+", true), | ||
5 | SUB("-", true), | ||
6 | MUL("*", true), | ||
7 | DIV("/", true), | ||
8 | POW("**", true), | ||
9 | MIN("min", false), | ||
10 | MAX("max", false); | ||
11 | |||
12 | private final String text; | ||
13 | private final boolean infix; | ||
14 | |||
15 | ArithmeticBinaryOperator(String text, boolean infix) { | ||
16 | this.text = text; | ||
17 | this.infix = infix; | ||
18 | } | ||
19 | |||
20 | public String formatString(String left, String right) { | ||
21 | if (infix) { | ||
22 | return "(%s) %s (%s)".formatted(left, text, right); | ||
23 | } | ||
24 | return "%s(%s, %s)".formatted(text, left, right); | ||
25 | } | ||
26 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ArithmeticBinaryTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ArithmeticBinaryTerm.java deleted file mode 100644 index 887a1e6e..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ArithmeticBinaryTerm.java +++ /dev/null | |||
@@ -1,56 +0,0 @@ | |||
1 | package tools.refinery.store.query.term; | ||
2 | |||
3 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | ||
4 | |||
5 | import java.util.Objects; | ||
6 | |||
7 | public abstract class ArithmeticBinaryTerm<T> extends BinaryTerm<T, T, T> { | ||
8 | private final ArithmeticBinaryOperator operator; | ||
9 | |||
10 | protected ArithmeticBinaryTerm(ArithmeticBinaryOperator operator, Term<T> left, Term<T> right) { | ||
11 | super(left, right); | ||
12 | this.operator = operator; | ||
13 | } | ||
14 | |||
15 | @Override | ||
16 | public Class<T> getLeftType() { | ||
17 | return getType(); | ||
18 | } | ||
19 | |||
20 | @Override | ||
21 | public Class<T> getRightType() { | ||
22 | return getType(); | ||
23 | } | ||
24 | |||
25 | public ArithmeticBinaryOperator getOperator() { | ||
26 | return operator; | ||
27 | } | ||
28 | |||
29 | @Override | ||
30 | public boolean equalsWithSubstitution(LiteralEqualityHelper helper, AnyTerm other) { | ||
31 | if (!super.equalsWithSubstitution(helper, other)) { | ||
32 | return false; | ||
33 | } | ||
34 | var otherArithmeticBinaryTerm = (ArithmeticBinaryTerm<?>) other; | ||
35 | return operator == otherArithmeticBinaryTerm.operator; | ||
36 | } | ||
37 | |||
38 | @Override | ||
39 | public String toString() { | ||
40 | return operator.formatString(getLeft().toString(), getRight().toString()); | ||
41 | } | ||
42 | |||
43 | @Override | ||
44 | public boolean equals(Object o) { | ||
45 | if (this == o) return true; | ||
46 | if (o == null || getClass() != o.getClass()) return false; | ||
47 | if (!super.equals(o)) return false; | ||
48 | ArithmeticBinaryTerm<?> that = (ArithmeticBinaryTerm<?>) o; | ||
49 | return operator == that.operator; | ||
50 | } | ||
51 | |||
52 | @Override | ||
53 | public int hashCode() { | ||
54 | return Objects.hash(super.hashCode(), operator); | ||
55 | } | ||
56 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ArithmeticUnaryOperator.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ArithmeticUnaryOperator.java deleted file mode 100644 index 6a7c25db..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ArithmeticUnaryOperator.java +++ /dev/null | |||
@@ -1,16 +0,0 @@ | |||
1 | package tools.refinery.store.query.term; | ||
2 | |||
3 | public enum ArithmeticUnaryOperator { | ||
4 | PLUS("+"), | ||
5 | MINUS("-"); | ||
6 | |||
7 | private final String prefix; | ||
8 | |||
9 | ArithmeticUnaryOperator(String prefix) { | ||
10 | this.prefix = prefix; | ||
11 | } | ||
12 | |||
13 | public String formatString(String body) { | ||
14 | return "%s(%s)".formatted(prefix, body); | ||
15 | } | ||
16 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ArithmeticUnaryTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ArithmeticUnaryTerm.java deleted file mode 100644 index b78239c7..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ArithmeticUnaryTerm.java +++ /dev/null | |||
@@ -1,51 +0,0 @@ | |||
1 | package tools.refinery.store.query.term; | ||
2 | |||
3 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | ||
4 | |||
5 | import java.util.Objects; | ||
6 | |||
7 | public abstract class ArithmeticUnaryTerm<T> extends UnaryTerm<T, T> { | ||
8 | private final ArithmeticUnaryOperator operator; | ||
9 | |||
10 | protected ArithmeticUnaryTerm(ArithmeticUnaryOperator operator, Term<T> body) { | ||
11 | super(body); | ||
12 | this.operator = operator; | ||
13 | } | ||
14 | |||
15 | @Override | ||
16 | public Class<T> getBodyType() { | ||
17 | return getType(); | ||
18 | } | ||
19 | |||
20 | public ArithmeticUnaryOperator getOperator() { | ||
21 | return operator; | ||
22 | } | ||
23 | |||
24 | @Override | ||
25 | public boolean equalsWithSubstitution(LiteralEqualityHelper helper, AnyTerm other) { | ||
26 | if (!super.equalsWithSubstitution(helper, other)) { | ||
27 | return false; | ||
28 | } | ||
29 | var otherArithmeticUnaryTerm = (ArithmeticUnaryTerm<?>) other; | ||
30 | return operator == otherArithmeticUnaryTerm.operator; | ||
31 | } | ||
32 | |||
33 | @Override | ||
34 | public String toString() { | ||
35 | return operator.formatString(getBody().toString()); | ||
36 | } | ||
37 | |||
38 | @Override | ||
39 | public boolean equals(Object o) { | ||
40 | if (this == o) return true; | ||
41 | if (o == null || getClass() != o.getClass()) return false; | ||
42 | if (!super.equals(o)) return false; | ||
43 | ArithmeticUnaryTerm<?> that = (ArithmeticUnaryTerm<?>) o; | ||
44 | return operator == that.operator; | ||
45 | } | ||
46 | |||
47 | @Override | ||
48 | public int hashCode() { | ||
49 | return Objects.hash(super.hashCode(), operator); | ||
50 | } | ||
51 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/AssignedValue.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/AssignedValue.java index 465e690f..0cf30aa6 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/AssignedValue.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/AssignedValue.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.term; | 6 | package tools.refinery.store.query.term; |
2 | 7 | ||
3 | import tools.refinery.store.query.literal.Literal; | 8 | import tools.refinery.store.query.literal.Literal; |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/BinaryTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/BinaryTerm.java index 34f48ccc..8ad17839 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/BinaryTerm.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/BinaryTerm.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.term; | 6 | package tools.refinery.store.query.term; |
2 | 7 | ||
3 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | 8 | import tools.refinery.store.query.equality.LiteralEqualityHelper; |
@@ -9,26 +14,35 @@ import java.util.HashSet; | |||
9 | import java.util.Objects; | 14 | import java.util.Objects; |
10 | import java.util.Set; | 15 | import java.util.Set; |
11 | 16 | ||
12 | public abstract class BinaryTerm<R, T1, T2> implements Term<R> { | 17 | public abstract class BinaryTerm<R, T1, T2> extends AbstractTerm<R> { |
18 | private final Class<T1> leftType; | ||
19 | private final Class<T2> rightType; | ||
13 | private final Term<T1> left; | 20 | private final Term<T1> left; |
14 | private final Term<T2> right; | 21 | private final Term<T2> right; |
15 | 22 | ||
16 | protected BinaryTerm(Term<T1> left, Term<T2> right) { | 23 | protected BinaryTerm(Class<R> type, Class<T1> leftType, Class<T2> rightType, Term<T1> left, Term<T2> right) { |
17 | if (!left.getType().equals(getLeftType())) { | 24 | super(type); |
18 | throw new IllegalArgumentException("Expected left %s to be of type %s, got %s instead".formatted(left, | 25 | if (!left.getType().equals(leftType)) { |
19 | getLeftType().getName(), left.getType().getName())); | 26 | throw new IllegalArgumentException("Expected left %s to be of type %s, got %s instead".formatted( |
27 | left, leftType.getName(), left.getType().getName())); | ||
20 | } | 28 | } |
21 | if (!right.getType().equals(getRightType())) { | 29 | if (!right.getType().equals(rightType)) { |
22 | throw new IllegalArgumentException("Expected right %s to be of type %s, got %s instead".formatted(right, | 30 | throw new IllegalArgumentException("Expected right %s to be of type %s, got %s instead".formatted( |
23 | getRightType().getName(), right.getType().getName())); | 31 | right, rightType.getName(), right.getType().getName())); |
24 | } | 32 | } |
33 | this.leftType = leftType; | ||
34 | this.rightType = rightType; | ||
25 | this.left = left; | 35 | this.left = left; |
26 | this.right = right; | 36 | this.right = right; |
27 | } | 37 | } |
28 | 38 | ||
29 | public abstract Class<T1> getLeftType(); | 39 | public Class<T1> getLeftType() { |
40 | return leftType; | ||
41 | } | ||
30 | 42 | ||
31 | public abstract Class<T2> getRightType(); | 43 | public Class<T2> getRightType() { |
44 | return rightType; | ||
45 | } | ||
32 | 46 | ||
33 | public Term<T1> getLeft() { | 47 | public Term<T1> getLeft() { |
34 | return left; | 48 | return left; |
@@ -55,12 +69,14 @@ public abstract class BinaryTerm<R, T1, T2> implements Term<R> { | |||
55 | 69 | ||
56 | @Override | 70 | @Override |
57 | public boolean equalsWithSubstitution(LiteralEqualityHelper helper, AnyTerm other) { | 71 | public boolean equalsWithSubstitution(LiteralEqualityHelper helper, AnyTerm other) { |
58 | if (getClass() != other.getClass()) { | 72 | if (!super.equalsWithSubstitution(helper, other)) { |
59 | return false; | 73 | return false; |
60 | } | 74 | } |
61 | var otherBinaryTerm = (BinaryTerm<?, ?, ?>) other; | 75 | var otherBinaryTerm = (BinaryTerm<?, ?, ?>) other; |
62 | return left.equalsWithSubstitution(helper, otherBinaryTerm.left) && right.equalsWithSubstitution(helper, | 76 | return leftType.equals(otherBinaryTerm.leftType) && |
63 | otherBinaryTerm.right); | 77 | rightType.equals(otherBinaryTerm.rightType) && |
78 | left.equalsWithSubstitution(helper, otherBinaryTerm.left) && | ||
79 | right.equalsWithSubstitution(helper, otherBinaryTerm.right); | ||
64 | } | 80 | } |
65 | 81 | ||
66 | @Override | 82 | @Override |
@@ -82,12 +98,16 @@ public abstract class BinaryTerm<R, T1, T2> implements Term<R> { | |||
82 | public boolean equals(Object o) { | 98 | public boolean equals(Object o) { |
83 | if (this == o) return true; | 99 | if (this == o) return true; |
84 | if (o == null || getClass() != o.getClass()) return false; | 100 | if (o == null || getClass() != o.getClass()) return false; |
101 | if (!super.equals(o)) return false; | ||
85 | BinaryTerm<?, ?, ?> that = (BinaryTerm<?, ?, ?>) o; | 102 | BinaryTerm<?, ?, ?> that = (BinaryTerm<?, ?, ?>) o; |
86 | return left.equals(that.left) && right.equals(that.right); | 103 | return Objects.equals(leftType, that.leftType) && |
104 | Objects.equals(rightType, that.rightType) && | ||
105 | Objects.equals(left, that.left) && | ||
106 | Objects.equals(right, that.right); | ||
87 | } | 107 | } |
88 | 108 | ||
89 | @Override | 109 | @Override |
90 | public int hashCode() { | 110 | public int hashCode() { |
91 | return Objects.hash(getClass(), left, right); | 111 | return Objects.hash(super.hashCode(), leftType, rightType, left, right); |
92 | } | 112 | } |
93 | } | 113 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ComparisonOperator.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ComparisonOperator.java deleted file mode 100644 index 44dcce10..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ComparisonOperator.java +++ /dev/null | |||
@@ -1,20 +0,0 @@ | |||
1 | package tools.refinery.store.query.term; | ||
2 | |||
3 | public enum ComparisonOperator { | ||
4 | EQ("=="), | ||
5 | NOT_EQ("!="), | ||
6 | LESS("<"), | ||
7 | LESS_EQ("<="), | ||
8 | GREATER(">"), | ||
9 | GREATER_EQ(">="); | ||
10 | |||
11 | private final String text; | ||
12 | |||
13 | ComparisonOperator(String text) { | ||
14 | this.text = text; | ||
15 | } | ||
16 | |||
17 | public String formatString(String left, String right) { | ||
18 | return "(%s) %s (%s)".formatted(left, text, right); | ||
19 | } | ||
20 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ComparisonTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ComparisonTerm.java deleted file mode 100644 index 320d42df..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ComparisonTerm.java +++ /dev/null | |||
@@ -1,63 +0,0 @@ | |||
1 | package tools.refinery.store.query.term; | ||
2 | |||
3 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | ||
4 | |||
5 | import java.util.Objects; | ||
6 | |||
7 | public abstract class ComparisonTerm<T> extends BinaryTerm<Boolean, T, T> { | ||
8 | private final ComparisonOperator operator; | ||
9 | |||
10 | protected ComparisonTerm(ComparisonOperator operator, Term<T> left, Term<T> right) { | ||
11 | super(left, right); | ||
12 | this.operator = operator; | ||
13 | } | ||
14 | |||
15 | @Override | ||
16 | public Class<Boolean> getType() { | ||
17 | return Boolean.class; | ||
18 | } | ||
19 | |||
20 | public abstract Class<T> getOperandType(); | ||
21 | |||
22 | @Override | ||
23 | public Class<T> getLeftType() { | ||
24 | return getOperandType(); | ||
25 | } | ||
26 | |||
27 | @Override | ||
28 | public Class<T> getRightType() { | ||
29 | return getOperandType(); | ||
30 | } | ||
31 | |||
32 | public ComparisonOperator getOperator() { | ||
33 | return operator; | ||
34 | } | ||
35 | |||
36 | @Override | ||
37 | public boolean equalsWithSubstitution(LiteralEqualityHelper helper, AnyTerm other) { | ||
38 | if (!super.equalsWithSubstitution(helper, other)) { | ||
39 | return false; | ||
40 | } | ||
41 | var otherComparisonTerm = (ComparisonTerm<?>) other; | ||
42 | return operator == otherComparisonTerm.operator; | ||
43 | } | ||
44 | |||
45 | @Override | ||
46 | public String toString() { | ||
47 | return operator.formatString(getLeft().toString(), getRight().toString()); | ||
48 | } | ||
49 | |||
50 | @Override | ||
51 | public boolean equals(Object o) { | ||
52 | if (this == o) return true; | ||
53 | if (o == null || getClass() != o.getClass()) return false; | ||
54 | if (!super.equals(o)) return false; | ||
55 | ComparisonTerm<?> that = (ComparisonTerm<?>) o; | ||
56 | return operator == that.operator; | ||
57 | } | ||
58 | |||
59 | @Override | ||
60 | public int hashCode() { | ||
61 | return Objects.hash(super.hashCode(), operator); | ||
62 | } | ||
63 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ConstantTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ConstantTerm.java index 2185fe37..2f6c56d1 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ConstantTerm.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ConstantTerm.java | |||
@@ -1,24 +1,26 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.term; | 6 | package tools.refinery.store.query.term; |
2 | 7 | ||
3 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | 8 | import tools.refinery.store.query.equality.LiteralEqualityHelper; |
4 | import tools.refinery.store.query.substitution.Substitution; | 9 | import tools.refinery.store.query.substitution.Substitution; |
5 | import tools.refinery.store.query.valuation.Valuation; | 10 | import tools.refinery.store.query.valuation.Valuation; |
6 | 11 | ||
12 | import java.util.Objects; | ||
7 | import java.util.Set; | 13 | import java.util.Set; |
8 | 14 | ||
9 | public record ConstantTerm<T>(Class<T> type, T value) implements Term<T> { | 15 | public final class ConstantTerm<T> extends AbstractTerm<T> { |
10 | public ConstantTerm { | 16 | private final T value; |
11 | if (value == null) { | ||
12 | throw new IllegalArgumentException("value should not be null"); | ||
13 | } | ||
14 | if (!type.isInstance(value)) { | ||
15 | throw new IllegalArgumentException("value %s is not an instance of %s".formatted(value, type.getName())); | ||
16 | } | ||
17 | } | ||
18 | 17 | ||
19 | @Override | 18 | public ConstantTerm(Class<T> type, T value) { |
20 | public Class<T> getType() { | 19 | super(type); |
21 | return type; | 20 | if (value != null && !type.isInstance(value)) { |
21 | throw new IllegalArgumentException("Value %s is not an instance of %s".formatted(value, type.getName())); | ||
22 | } | ||
23 | this.value = value; | ||
22 | } | 24 | } |
23 | 25 | ||
24 | public T getValue() { | 26 | public T getValue() { |
@@ -37,7 +39,11 @@ public record ConstantTerm<T>(Class<T> type, T value) implements Term<T> { | |||
37 | 39 | ||
38 | @Override | 40 | @Override |
39 | public boolean equalsWithSubstitution(LiteralEqualityHelper helper, AnyTerm other) { | 41 | public boolean equalsWithSubstitution(LiteralEqualityHelper helper, AnyTerm other) { |
40 | return equals(other); | 42 | if (!super.equalsWithSubstitution(helper, other)) { |
43 | return false; | ||
44 | } | ||
45 | var otherConstantTerm = (ConstantTerm<?>) other; | ||
46 | return Objects.equals(value, otherConstantTerm.value); | ||
41 | } | 47 | } |
42 | 48 | ||
43 | @Override | 49 | @Override |
@@ -47,6 +53,19 @@ public record ConstantTerm<T>(Class<T> type, T value) implements Term<T> { | |||
47 | 53 | ||
48 | @Override | 54 | @Override |
49 | public String toString() { | 55 | public String toString() { |
50 | return getValue().toString(); | 56 | return value.toString(); |
57 | } | ||
58 | |||
59 | @Override | ||
60 | public boolean equals(Object o) { | ||
61 | if (this == o) return true; | ||
62 | if (o == null || getClass() != o.getClass()) return false; | ||
63 | ConstantTerm<?> that = (ConstantTerm<?>) o; | ||
64 | return Objects.equals(value, that.value); | ||
65 | } | ||
66 | |||
67 | @Override | ||
68 | public int hashCode() { | ||
69 | return Objects.hash(value); | ||
51 | } | 70 | } |
52 | } | 71 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/DataSort.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/DataSort.java deleted file mode 100644 index 4fb44492..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/DataSort.java +++ /dev/null | |||
@@ -1,29 +0,0 @@ | |||
1 | package tools.refinery.store.query.term; | ||
2 | |||
3 | import org.jetbrains.annotations.Nullable; | ||
4 | |||
5 | public record DataSort<T>(Class<T> type) implements Sort { | ||
6 | public static final DataSort<Integer> INT = new DataSort<>(Integer.class); | ||
7 | |||
8 | public static final DataSort<Boolean> BOOL = new DataSort<>(Boolean.class); | ||
9 | |||
10 | @Override | ||
11 | public boolean isInstance(Variable variable) { | ||
12 | return variable instanceof DataVariable<?> dataVariable && type.equals(dataVariable.getType()); | ||
13 | } | ||
14 | |||
15 | @Override | ||
16 | public DataVariable<T> newInstance(@Nullable String name) { | ||
17 | return Variable.of(name, type); | ||
18 | } | ||
19 | |||
20 | @Override | ||
21 | public DataVariable<T> newInstance() { | ||
22 | return newInstance(null); | ||
23 | } | ||
24 | |||
25 | @Override | ||
26 | public String toString() { | ||
27 | return type.getName(); | ||
28 | } | ||
29 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/DataVariable.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/DataVariable.java index af070ca7..00950360 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/DataVariable.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/DataVariable.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.term; | 6 | package tools.refinery.store.query.term; |
2 | 7 | ||
3 | import org.jetbrains.annotations.Nullable; | 8 | import org.jetbrains.annotations.Nullable; |
@@ -17,11 +22,6 @@ public final class DataVariable<T> extends AnyDataVariable implements Term<T> { | |||
17 | } | 22 | } |
18 | 23 | ||
19 | @Override | 24 | @Override |
20 | public DataSort<T> getSort() { | ||
21 | return new DataSort<>(getType()); | ||
22 | } | ||
23 | |||
24 | @Override | ||
25 | public Class<T> getType() { | 25 | public Class<T> getType() { |
26 | return type; | 26 | return type; |
27 | } | 27 | } |
@@ -37,11 +37,6 @@ public final class DataVariable<T> extends AnyDataVariable implements Term<T> { | |||
37 | } | 37 | } |
38 | 38 | ||
39 | @Override | 39 | @Override |
40 | public NodeVariable asNodeVariable() { | ||
41 | throw new IllegalStateException("%s is a data variable".formatted(this)); | ||
42 | } | ||
43 | |||
44 | @Override | ||
45 | public <U> DataVariable<U> asDataVariable(Class<U> newType) { | 40 | public <U> DataVariable<U> asDataVariable(Class<U> newType) { |
46 | if (!getType().equals(newType)) { | 41 | if (!getType().equals(newType)) { |
47 | throw new IllegalStateException("%s is not of type %s but of type %s".formatted(this, newType.getName(), | 42 | throw new IllegalStateException("%s is not of type %s but of type %s".formatted(this, newType.getName(), |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ExtremeValueAggregator.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ExtremeValueAggregator.java index 57ff597c..657cb631 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ExtremeValueAggregator.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ExtremeValueAggregator.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.term; | 6 | package tools.refinery.store.query.term; |
2 | 7 | ||
3 | import java.util.Comparator; | 8 | import java.util.Comparator; |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/NodeSort.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/NodeSort.java deleted file mode 100644 index 1a4b2d4b..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/NodeSort.java +++ /dev/null | |||
@@ -1,30 +0,0 @@ | |||
1 | package tools.refinery.store.query.term; | ||
2 | |||
3 | import org.jetbrains.annotations.Nullable; | ||
4 | |||
5 | public final class NodeSort implements Sort { | ||
6 | public static final NodeSort INSTANCE = new NodeSort(); | ||
7 | |||
8 | private NodeSort() { | ||
9 | } | ||
10 | |||
11 | @Override | ||
12 | public boolean isInstance(Variable variable) { | ||
13 | return variable instanceof NodeVariable; | ||
14 | } | ||
15 | |||
16 | @Override | ||
17 | public NodeVariable newInstance(@Nullable String name) { | ||
18 | return new NodeVariable(name); | ||
19 | } | ||
20 | |||
21 | @Override | ||
22 | public NodeVariable newInstance() { | ||
23 | return newInstance(null); | ||
24 | } | ||
25 | |||
26 | @Override | ||
27 | public String toString() { | ||
28 | return "<node>"; | ||
29 | } | ||
30 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/NodeVariable.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/NodeVariable.java index 7419aaad..a2f3261f 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/NodeVariable.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/NodeVariable.java | |||
@@ -1,17 +1,29 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.term; | 6 | package tools.refinery.store.query.term; |
2 | 7 | ||
3 | import org.jetbrains.annotations.Nullable; | 8 | import org.jetbrains.annotations.Nullable; |
4 | import tools.refinery.store.query.literal.ConstantLiteral; | 9 | import tools.refinery.store.query.literal.ConstantLiteral; |
5 | import tools.refinery.store.query.literal.EquivalenceLiteral; | 10 | import tools.refinery.store.query.literal.EquivalenceLiteral; |
6 | 11 | ||
12 | import java.util.Optional; | ||
13 | |||
7 | public final class NodeVariable extends Variable { | 14 | public final class NodeVariable extends Variable { |
8 | NodeVariable(@Nullable String name) { | 15 | NodeVariable(@Nullable String name) { |
9 | super(name); | 16 | super(name); |
10 | } | 17 | } |
11 | 18 | ||
12 | @Override | 19 | @Override |
13 | public NodeSort getSort() { | 20 | public Optional<Class<?>> tryGetType() { |
14 | return NodeSort.INSTANCE; | 21 | return Optional.empty(); |
22 | } | ||
23 | |||
24 | @Override | ||
25 | public boolean isUnifiable() { | ||
26 | return true; | ||
15 | } | 27 | } |
16 | 28 | ||
17 | @Override | 29 | @Override |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/OpaqueTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/OpaqueTerm.java deleted file mode 100644 index 8faa9c75..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/OpaqueTerm.java +++ /dev/null | |||
@@ -1,80 +0,0 @@ | |||
1 | package tools.refinery.store.query.term; | ||
2 | |||
3 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | ||
4 | import tools.refinery.store.query.substitution.Substitution; | ||
5 | import tools.refinery.store.query.substitution.Substitutions; | ||
6 | import tools.refinery.store.query.valuation.Valuation; | ||
7 | |||
8 | import java.util.Objects; | ||
9 | import java.util.Set; | ||
10 | import java.util.function.Function; | ||
11 | import java.util.stream.Collectors; | ||
12 | |||
13 | public final class OpaqueTerm<T> implements Term<T> { | ||
14 | private final Class<T> type; | ||
15 | private final Function<? super Valuation, ? extends T> evaluator; | ||
16 | private final Set<AnyDataVariable> variables; | ||
17 | private final Substitution substitution; | ||
18 | |||
19 | public OpaqueTerm(Class<T> type, Function<? super Valuation, ? extends T> evaluator, | ||
20 | Set<? extends AnyDataVariable> variables) { | ||
21 | this(type, evaluator, variables, null); | ||
22 | } | ||
23 | |||
24 | private OpaqueTerm(Class<T> type, Function<? super Valuation, ? extends T> evaluator, | ||
25 | Set<? extends AnyDataVariable> variables, Substitution substitution) { | ||
26 | this.type = type; | ||
27 | this.evaluator = evaluator; | ||
28 | this.variables = Set.copyOf(variables); | ||
29 | this.substitution = substitution; | ||
30 | } | ||
31 | |||
32 | @Override | ||
33 | public Class<T> getType() { | ||
34 | return type; | ||
35 | } | ||
36 | |||
37 | @Override | ||
38 | public Set<AnyDataVariable> getInputVariables() { | ||
39 | return variables; | ||
40 | } | ||
41 | |||
42 | @Override | ||
43 | public T evaluate(Valuation valuation) { | ||
44 | return evaluator.apply(valuation.substitute(substitution)); | ||
45 | } | ||
46 | |||
47 | @Override | ||
48 | public Term<T> substitute(Substitution newSubstitution) { | ||
49 | var substitutedVariables = variables.stream() | ||
50 | .map(newSubstitution::getTypeSafeSubstitute) | ||
51 | .collect(Collectors.toUnmodifiableSet()); | ||
52 | return new OpaqueTerm<>(type, evaluator, substitutedVariables, | ||
53 | Substitutions.compose(substitution, newSubstitution)); | ||
54 | } | ||
55 | |||
56 | @Override | ||
57 | public boolean equalsWithSubstitution(LiteralEqualityHelper helper, AnyTerm other) { | ||
58 | // Cannot inspect the opaque evaluator for deep equality. | ||
59 | return equals(other); | ||
60 | } | ||
61 | |||
62 | @Override | ||
63 | public String toString() { | ||
64 | return "<opaque>"; | ||
65 | } | ||
66 | |||
67 | @Override | ||
68 | public boolean equals(Object o) { | ||
69 | if (this == o) return true; | ||
70 | if (o == null || getClass() != o.getClass()) return false; | ||
71 | OpaqueTerm<?> that = (OpaqueTerm<?>) o; | ||
72 | return type.equals(that.type) && evaluator.equals(that.evaluator) && Objects.equals(substitution, | ||
73 | that.substitution); | ||
74 | } | ||
75 | |||
76 | @Override | ||
77 | public int hashCode() { | ||
78 | return Objects.hash(type, evaluator, substitution); | ||
79 | } | ||
80 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/Parameter.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/Parameter.java new file mode 100644 index 00000000..e5a0cdf1 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/Parameter.java | |||
@@ -0,0 +1,60 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term; | ||
7 | |||
8 | import java.util.Objects; | ||
9 | import java.util.Optional; | ||
10 | |||
11 | public class Parameter { | ||
12 | public static final Parameter NODE_OUT = new Parameter(null, ParameterDirection.OUT); | ||
13 | |||
14 | private final Class<?> dataType; | ||
15 | private final ParameterDirection direction; | ||
16 | |||
17 | public Parameter(Class<?> dataType, ParameterDirection direction) { | ||
18 | this.dataType = dataType; | ||
19 | this.direction = direction; | ||
20 | } | ||
21 | |||
22 | public boolean isNodeVariable() { | ||
23 | return dataType == null; | ||
24 | } | ||
25 | |||
26 | public boolean isDataVariable() { | ||
27 | return !isNodeVariable(); | ||
28 | } | ||
29 | |||
30 | public Optional<Class<?>> tryGetType() { | ||
31 | return Optional.ofNullable(dataType); | ||
32 | } | ||
33 | |||
34 | public ParameterDirection getDirection() { | ||
35 | return direction; | ||
36 | } | ||
37 | |||
38 | public boolean isAssignable(Variable variable) { | ||
39 | if (variable instanceof AnyDataVariable dataVariable) { | ||
40 | return dataVariable.getType().equals(dataType); | ||
41 | } else if (variable instanceof NodeVariable) { | ||
42 | return !isDataVariable(); | ||
43 | } else { | ||
44 | throw new IllegalArgumentException("Unknown variable " + variable); | ||
45 | } | ||
46 | } | ||
47 | |||
48 | @Override | ||
49 | public boolean equals(Object o) { | ||
50 | if (this == o) return true; | ||
51 | if (o == null || getClass() != o.getClass()) return false; | ||
52 | Parameter parameter = (Parameter) o; | ||
53 | return Objects.equals(dataType, parameter.dataType) && direction == parameter.direction; | ||
54 | } | ||
55 | |||
56 | @Override | ||
57 | public int hashCode() { | ||
58 | return Objects.hash(dataType, direction); | ||
59 | } | ||
60 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ParameterDirection.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ParameterDirection.java new file mode 100644 index 00000000..cd0739be --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/ParameterDirection.java | |||
@@ -0,0 +1,22 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term; | ||
7 | |||
8 | public enum ParameterDirection { | ||
9 | OUT("@Out"), | ||
10 | IN("@In"); | ||
11 | |||
12 | private final String name; | ||
13 | |||
14 | ParameterDirection(String name) { | ||
15 | this.name = name; | ||
16 | } | ||
17 | |||
18 | @Override | ||
19 | public String toString() { | ||
20 | return name; | ||
21 | } | ||
22 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/Sort.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/Sort.java deleted file mode 100644 index 622bcfce..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/Sort.java +++ /dev/null | |||
@@ -1,11 +0,0 @@ | |||
1 | package tools.refinery.store.query.term; | ||
2 | |||
3 | import org.jetbrains.annotations.Nullable; | ||
4 | |||
5 | public sealed interface Sort permits DataSort, NodeSort { | ||
6 | boolean isInstance(Variable variable); | ||
7 | |||
8 | Variable newInstance(@Nullable String name); | ||
9 | |||
10 | Variable newInstance(); | ||
11 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/StatefulAggregate.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/StatefulAggregate.java index 7ce91305..ab310556 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/StatefulAggregate.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/StatefulAggregate.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.term; | 6 | package tools.refinery.store.query.term; |
2 | 7 | ||
3 | public interface StatefulAggregate<R, T> { | 8 | public interface StatefulAggregate<R, T> { |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/StatefulAggregator.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/StatefulAggregator.java index c215a511..df746a90 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/StatefulAggregator.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/StatefulAggregator.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.term; | 6 | package tools.refinery.store.query.term; |
2 | 7 | ||
3 | import java.util.stream.Stream; | 8 | import java.util.stream.Stream; |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/StatelessAggregator.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/StatelessAggregator.java index 74dbd335..a094919e 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/StatelessAggregator.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/StatelessAggregator.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.term; | 6 | package tools.refinery.store.query.term; |
2 | 7 | ||
3 | import java.util.stream.Stream; | 8 | import java.util.stream.Stream; |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/Term.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/Term.java index 95434db2..e6818b88 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/Term.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/Term.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.term; | 6 | package tools.refinery.store.query.term; |
2 | 7 | ||
3 | import tools.refinery.store.query.literal.AssignLiteral; | 8 | import tools.refinery.store.query.literal.AssignLiteral; |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/UnaryTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/UnaryTerm.java index 4083111a..a46ebe31 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/UnaryTerm.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/UnaryTerm.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.term; | 6 | package tools.refinery.store.query.term; |
2 | 7 | ||
3 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | 8 | import tools.refinery.store.query.equality.LiteralEqualityHelper; |
@@ -7,18 +12,23 @@ import tools.refinery.store.query.valuation.Valuation; | |||
7 | import java.util.Objects; | 12 | import java.util.Objects; |
8 | import java.util.Set; | 13 | import java.util.Set; |
9 | 14 | ||
10 | public abstract class UnaryTerm<R, T> implements Term<R> { | 15 | public abstract class UnaryTerm<R, T> extends AbstractTerm<R> { |
16 | private final Class<T> bodyType; | ||
11 | private final Term<T> body; | 17 | private final Term<T> body; |
12 | 18 | ||
13 | protected UnaryTerm(Term<T> body) { | 19 | protected UnaryTerm(Class<R> type, Class<T> bodyType, Term<T> body) { |
14 | if (!body.getType().equals(getBodyType())) { | 20 | super(type); |
21 | if (!body.getType().equals(bodyType)) { | ||
15 | throw new IllegalArgumentException("Expected body %s to be of type %s, got %s instead".formatted(body, | 22 | throw new IllegalArgumentException("Expected body %s to be of type %s, got %s instead".formatted(body, |
16 | getBodyType().getName(), body.getType().getName())); | 23 | bodyType.getName(), body.getType().getName())); |
17 | } | 24 | } |
25 | this.bodyType = bodyType; | ||
18 | this.body = body; | 26 | this.body = body; |
19 | } | 27 | } |
20 | 28 | ||
21 | public abstract Class<T> getBodyType(); | 29 | public Class<T> getBodyType() { |
30 | return bodyType; | ||
31 | } | ||
22 | 32 | ||
23 | public Term<T> getBody() { | 33 | public Term<T> getBody() { |
24 | return body; | 34 | return body; |
@@ -34,11 +44,11 @@ public abstract class UnaryTerm<R, T> implements Term<R> { | |||
34 | 44 | ||
35 | @Override | 45 | @Override |
36 | public boolean equalsWithSubstitution(LiteralEqualityHelper helper, AnyTerm other) { | 46 | public boolean equalsWithSubstitution(LiteralEqualityHelper helper, AnyTerm other) { |
37 | if (getClass() != other.getClass()) { | 47 | if (!super.equalsWithSubstitution(helper, other)) { |
38 | return false; | 48 | return false; |
39 | } | 49 | } |
40 | var otherUnaryTerm = (UnaryTerm<?, ?>) other; | 50 | var otherUnaryTerm = (UnaryTerm<?, ?>) other; |
41 | return body.equalsWithSubstitution(helper, otherUnaryTerm.body); | 51 | return bodyType.equals(otherUnaryTerm.bodyType) && body.equalsWithSubstitution(helper, otherUnaryTerm.body); |
42 | } | 52 | } |
43 | 53 | ||
44 | @Override | 54 | @Override |
@@ -57,12 +67,13 @@ public abstract class UnaryTerm<R, T> implements Term<R> { | |||
57 | public boolean equals(Object o) { | 67 | public boolean equals(Object o) { |
58 | if (this == o) return true; | 68 | if (this == o) return true; |
59 | if (o == null || getClass() != o.getClass()) return false; | 69 | if (o == null || getClass() != o.getClass()) return false; |
70 | if (!super.equals(o)) return false; | ||
60 | UnaryTerm<?, ?> unaryTerm = (UnaryTerm<?, ?>) o; | 71 | UnaryTerm<?, ?> unaryTerm = (UnaryTerm<?, ?>) o; |
61 | return body.equals(unaryTerm.body); | 72 | return Objects.equals(bodyType, unaryTerm.bodyType) && Objects.equals(body, unaryTerm.body); |
62 | } | 73 | } |
63 | 74 | ||
64 | @Override | 75 | @Override |
65 | public int hashCode() { | 76 | public int hashCode() { |
66 | return Objects.hash(getClass(), body); | 77 | return Objects.hash(super.hashCode(), bodyType, body); |
67 | } | 78 | } |
68 | } | 79 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/Variable.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/Variable.java index 957e10f8..a0268c8e 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/Variable.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/Variable.java | |||
@@ -1,9 +1,15 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.term; | 6 | package tools.refinery.store.query.term; |
2 | 7 | ||
3 | import org.jetbrains.annotations.Nullable; | 8 | import org.jetbrains.annotations.Nullable; |
4 | import tools.refinery.store.query.dnf.DnfUtils; | 9 | import tools.refinery.store.query.dnf.DnfUtils; |
5 | 10 | ||
6 | import java.util.Objects; | 11 | import java.util.Objects; |
12 | import java.util.Optional; | ||
7 | 13 | ||
8 | public abstract sealed class Variable permits AnyDataVariable, NodeVariable { | 14 | public abstract sealed class Variable permits AnyDataVariable, NodeVariable { |
9 | private final String explicitName; | 15 | private final String explicitName; |
@@ -14,7 +20,7 @@ public abstract sealed class Variable permits AnyDataVariable, NodeVariable { | |||
14 | uniqueName = DnfUtils.generateUniqueName(name); | 20 | uniqueName = DnfUtils.generateUniqueName(name); |
15 | } | 21 | } |
16 | 22 | ||
17 | public abstract Sort getSort(); | 23 | public abstract Optional<Class<?>> tryGetType(); |
18 | 24 | ||
19 | public String getName() { | 25 | public String getName() { |
20 | return explicitName == null ? uniqueName : explicitName; | 26 | return explicitName == null ? uniqueName : explicitName; |
@@ -32,6 +38,8 @@ public abstract sealed class Variable permits AnyDataVariable, NodeVariable { | |||
32 | return uniqueName; | 38 | return uniqueName; |
33 | } | 39 | } |
34 | 40 | ||
41 | public abstract boolean isUnifiable(); | ||
42 | |||
35 | public abstract Variable renew(@Nullable String name); | 43 | public abstract Variable renew(@Nullable String name); |
36 | 44 | ||
37 | public abstract Variable renew(); | 45 | public abstract Variable renew(); |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolAndTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolAndTerm.java new file mode 100644 index 00000000..f9e1c06f --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolAndTerm.java | |||
@@ -0,0 +1,31 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.bool; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public class BoolAndTerm extends BoolBinaryTerm { | ||
12 | public BoolAndTerm(Term<Boolean> left, Term<Boolean> right) { | ||
13 | super(left, right); | ||
14 | } | ||
15 | |||
16 | @Override | ||
17 | public Term<Boolean> doSubstitute(Substitution substitution, Term<Boolean> substitutedLeft, | ||
18 | Term<Boolean> substitutedRight) { | ||
19 | return new BoolAndTerm(substitutedLeft, substitutedRight); | ||
20 | } | ||
21 | |||
22 | @Override | ||
23 | protected Boolean doEvaluate(Boolean leftValue, Boolean rightValue) { | ||
24 | return leftValue && rightValue; | ||
25 | } | ||
26 | |||
27 | @Override | ||
28 | public String toString() { | ||
29 | return "(%s && %s)".formatted(getLeft(), getRight()); | ||
30 | } | ||
31 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolBinaryTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolBinaryTerm.java new file mode 100644 index 00000000..a85aa63a --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolBinaryTerm.java | |||
@@ -0,0 +1,15 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.bool; | ||
7 | |||
8 | import tools.refinery.store.query.term.BinaryTerm; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public abstract class BoolBinaryTerm extends BinaryTerm<Boolean, Boolean, Boolean> { | ||
12 | protected BoolBinaryTerm(Term<Boolean> left, Term<Boolean> right) { | ||
13 | super(Boolean.class, Boolean.class, Boolean.class, left, right); | ||
14 | } | ||
15 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolConstantTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolConstantTerm.java deleted file mode 100644 index 5079f1ce..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolConstantTerm.java +++ /dev/null | |||
@@ -1,16 +0,0 @@ | |||
1 | package tools.refinery.store.query.term.bool; | ||
2 | |||
3 | import tools.refinery.store.query.term.ConstantTerm; | ||
4 | |||
5 | public final class BoolConstantTerm { | ||
6 | public static final ConstantTerm<Boolean> TRUE = new ConstantTerm<>(Boolean.class, true); | ||
7 | public static final ConstantTerm<Boolean> FALSE = new ConstantTerm<>(Boolean.class, false); | ||
8 | |||
9 | private BoolConstantTerm() { | ||
10 | throw new IllegalStateException("This is a static utility class and should not be instantiated directly"); | ||
11 | } | ||
12 | |||
13 | public static ConstantTerm<Boolean> valueOf(boolean boolValue) { | ||
14 | return boolValue ? TRUE : FALSE; | ||
15 | } | ||
16 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolLogicBinaryTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolLogicBinaryTerm.java deleted file mode 100644 index d85f864d..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolLogicBinaryTerm.java +++ /dev/null | |||
@@ -1,78 +0,0 @@ | |||
1 | package tools.refinery.store.query.term.bool; | ||
2 | |||
3 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | ||
4 | import tools.refinery.store.query.substitution.Substitution; | ||
5 | import tools.refinery.store.query.term.*; | ||
6 | |||
7 | import java.util.Objects; | ||
8 | |||
9 | public class BoolLogicBinaryTerm extends BinaryTerm<Boolean, Boolean, Boolean> { | ||
10 | private final LogicBinaryOperator operator; | ||
11 | |||
12 | protected BoolLogicBinaryTerm(LogicBinaryOperator operator, Term<Boolean> left, Term<Boolean> right) { | ||
13 | super(left, right); | ||
14 | this.operator = operator; | ||
15 | } | ||
16 | |||
17 | @Override | ||
18 | public Class<Boolean> getType() { | ||
19 | return Boolean.class; | ||
20 | } | ||
21 | |||
22 | @Override | ||
23 | public Class<Boolean> getLeftType() { | ||
24 | return getType(); | ||
25 | } | ||
26 | |||
27 | @Override | ||
28 | public Class<Boolean> getRightType() { | ||
29 | return getType(); | ||
30 | } | ||
31 | |||
32 | public LogicBinaryOperator getOperator() { | ||
33 | return operator; | ||
34 | } | ||
35 | |||
36 | @Override | ||
37 | public boolean equalsWithSubstitution(LiteralEqualityHelper helper, AnyTerm other) { | ||
38 | if (!super.equalsWithSubstitution(helper, other)) { | ||
39 | return false; | ||
40 | } | ||
41 | var otherBoolLogicBinaryTerm = (BoolLogicBinaryTerm) other; | ||
42 | return operator == otherBoolLogicBinaryTerm.operator; | ||
43 | } | ||
44 | |||
45 | @Override | ||
46 | public Term<Boolean> doSubstitute(Substitution substitution, Term<Boolean> substitutedLeft, | ||
47 | Term<Boolean> substitutedRight) { | ||
48 | return new BoolLogicBinaryTerm(getOperator(), substitutedLeft, substitutedRight); | ||
49 | } | ||
50 | |||
51 | @Override | ||
52 | protected Boolean doEvaluate(Boolean leftValue, Boolean rightValue) { | ||
53 | return switch (getOperator()) { | ||
54 | case AND -> leftValue && rightValue; | ||
55 | case OR -> leftValue || rightValue; | ||
56 | case XOR -> leftValue ^ rightValue; | ||
57 | }; | ||
58 | } | ||
59 | |||
60 | @Override | ||
61 | public String toString() { | ||
62 | return operator.formatString(getLeft().toString(), getRight().toString()); | ||
63 | } | ||
64 | |||
65 | @Override | ||
66 | public boolean equals(Object o) { | ||
67 | if (this == o) return true; | ||
68 | if (o == null || getClass() != o.getClass()) return false; | ||
69 | if (!super.equals(o)) return false; | ||
70 | BoolLogicBinaryTerm that = (BoolLogicBinaryTerm) o; | ||
71 | return operator == that.operator; | ||
72 | } | ||
73 | |||
74 | @Override | ||
75 | public int hashCode() { | ||
76 | return Objects.hash(super.hashCode(), operator); | ||
77 | } | ||
78 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolNotTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolNotTerm.java index 855139b5..8d3382b3 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolNotTerm.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolNotTerm.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.term.bool; | 6 | package tools.refinery.store.query.term.bool; |
2 | 7 | ||
3 | import tools.refinery.store.query.substitution.Substitution; | 8 | import tools.refinery.store.query.substitution.Substitution; |
@@ -6,17 +11,7 @@ import tools.refinery.store.query.term.UnaryTerm; | |||
6 | 11 | ||
7 | public class BoolNotTerm extends UnaryTerm<Boolean, Boolean> { | 12 | public class BoolNotTerm extends UnaryTerm<Boolean, Boolean> { |
8 | protected BoolNotTerm(Term<Boolean> body) { | 13 | protected BoolNotTerm(Term<Boolean> body) { |
9 | super(body); | 14 | super(Boolean.class, Boolean.class, body); |
10 | } | ||
11 | |||
12 | @Override | ||
13 | public Class<Boolean> getType() { | ||
14 | return Boolean.class; | ||
15 | } | ||
16 | |||
17 | @Override | ||
18 | public Class<Boolean> getBodyType() { | ||
19 | return getType(); | ||
20 | } | 15 | } |
21 | 16 | ||
22 | @Override | 17 | @Override |
@@ -31,6 +26,6 @@ public class BoolNotTerm extends UnaryTerm<Boolean, Boolean> { | |||
31 | 26 | ||
32 | @Override | 27 | @Override |
33 | public String toString() { | 28 | public String toString() { |
34 | return "!(%s)".formatted(getBody()); | 29 | return "(!%s)".formatted(getBody()); |
35 | } | 30 | } |
36 | } | 31 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolOrTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolOrTerm.java new file mode 100644 index 00000000..b5195d52 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolOrTerm.java | |||
@@ -0,0 +1,31 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.bool; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public class BoolOrTerm extends BoolBinaryTerm { | ||
12 | public BoolOrTerm(Term<Boolean> left, Term<Boolean> right) { | ||
13 | super(left, right); | ||
14 | } | ||
15 | |||
16 | @Override | ||
17 | public Term<Boolean> doSubstitute(Substitution substitution, Term<Boolean> substitutedLeft, | ||
18 | Term<Boolean> substitutedRight) { | ||
19 | return new BoolOrTerm(substitutedLeft, substitutedRight); | ||
20 | } | ||
21 | |||
22 | @Override | ||
23 | protected Boolean doEvaluate(Boolean leftValue, Boolean rightValue) { | ||
24 | return leftValue || rightValue; | ||
25 | } | ||
26 | |||
27 | @Override | ||
28 | public String toString() { | ||
29 | return "(%s || %s)".formatted(getLeft(), getRight()); | ||
30 | } | ||
31 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolTerms.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolTerms.java index 3d6c8d9d..fa54f686 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolTerms.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolTerms.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.term.bool; | 6 | package tools.refinery.store.query.term.bool; |
2 | 7 | ||
3 | import tools.refinery.store.query.term.ConstantTerm; | 8 | import tools.refinery.store.query.term.ConstantTerm; |
@@ -8,23 +13,23 @@ public final class BoolTerms { | |||
8 | throw new IllegalArgumentException("This is a static utility class and should not be instantiated directly"); | 13 | throw new IllegalArgumentException("This is a static utility class and should not be instantiated directly"); |
9 | } | 14 | } |
10 | 15 | ||
11 | public static ConstantTerm<Boolean> constant(boolean value) { | 16 | public static Term<Boolean> constant(Boolean value) { |
12 | return BoolConstantTerm.valueOf(value); | 17 | return new ConstantTerm<>(Boolean.class, value); |
13 | } | 18 | } |
14 | 19 | ||
15 | public static BoolNotTerm not(Term<Boolean> body) { | 20 | public static Term<Boolean> not(Term<Boolean> body) { |
16 | return new BoolNotTerm(body); | 21 | return new BoolNotTerm(body); |
17 | } | 22 | } |
18 | 23 | ||
19 | public static BoolLogicBinaryTerm and(Term<Boolean> left, Term<Boolean> right) { | 24 | public static Term<Boolean> and(Term<Boolean> left, Term<Boolean> right) { |
20 | return new BoolLogicBinaryTerm(LogicBinaryOperator.AND, left, right); | 25 | return new BoolAndTerm(left, right); |
21 | } | 26 | } |
22 | 27 | ||
23 | public static BoolLogicBinaryTerm or(Term<Boolean> left, Term<Boolean> right) { | 28 | public static Term<Boolean> or(Term<Boolean> left, Term<Boolean> right) { |
24 | return new BoolLogicBinaryTerm(LogicBinaryOperator.OR, left, right); | 29 | return new BoolOrTerm(left, right); |
25 | } | 30 | } |
26 | 31 | ||
27 | public static BoolLogicBinaryTerm xor(Term<Boolean> left, Term<Boolean> right) { | 32 | public static Term<Boolean> xor(Term<Boolean> left, Term<Boolean> right) { |
28 | return new BoolLogicBinaryTerm(LogicBinaryOperator.XOR, left, right); | 33 | return new BoolXorTerm(left, right); |
29 | } | 34 | } |
30 | } | 35 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolXorTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolXorTerm.java new file mode 100644 index 00000000..7478b8a5 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/BoolXorTerm.java | |||
@@ -0,0 +1,31 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.bool; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public class BoolXorTerm extends BoolBinaryTerm { | ||
12 | public BoolXorTerm(Term<Boolean> left, Term<Boolean> right) { | ||
13 | super(left, right); | ||
14 | } | ||
15 | |||
16 | @Override | ||
17 | public Term<Boolean> doSubstitute(Substitution substitution, Term<Boolean> substitutedLeft, | ||
18 | Term<Boolean> substitutedRight) { | ||
19 | return new BoolXorTerm(substitutedLeft, substitutedRight); | ||
20 | } | ||
21 | |||
22 | @Override | ||
23 | protected Boolean doEvaluate(Boolean leftValue, Boolean rightValue) { | ||
24 | return leftValue ^ rightValue; | ||
25 | } | ||
26 | |||
27 | @Override | ||
28 | public String toString() { | ||
29 | return "(%s ^^ %s)".formatted(getLeft(), getRight()); | ||
30 | } | ||
31 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/LogicBinaryOperator.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/LogicBinaryOperator.java deleted file mode 100644 index ca9ac66e..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/bool/LogicBinaryOperator.java +++ /dev/null | |||
@@ -1,17 +0,0 @@ | |||
1 | package tools.refinery.store.query.term.bool; | ||
2 | |||
3 | public enum LogicBinaryOperator { | ||
4 | AND("&&"), | ||
5 | OR("||"), | ||
6 | XOR("^^"); | ||
7 | |||
8 | private final String text; | ||
9 | |||
10 | LogicBinaryOperator(String text) { | ||
11 | this.text = text; | ||
12 | } | ||
13 | |||
14 | public String formatString(String left, String right) { | ||
15 | return "(%s) %s (%s)".formatted(left, text, right); | ||
16 | } | ||
17 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/ComparisonTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/ComparisonTerm.java new file mode 100644 index 00000000..5ca5a0a1 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/ComparisonTerm.java | |||
@@ -0,0 +1,19 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.comparable; | ||
7 | |||
8 | import tools.refinery.store.query.term.BinaryTerm; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public abstract class ComparisonTerm<T> extends BinaryTerm<Boolean, T, T> { | ||
12 | protected ComparisonTerm(Class<T> argumentType, Term<T> left, Term<T> right) { | ||
13 | super(Boolean.class, argumentType, argumentType, left, right); | ||
14 | } | ||
15 | |||
16 | public Class<T> getArgumentType() { | ||
17 | return getLeftType(); | ||
18 | } | ||
19 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/EqTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/EqTerm.java new file mode 100644 index 00000000..b8cf36f8 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/EqTerm.java | |||
@@ -0,0 +1,30 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.comparable; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public class EqTerm<T> extends ComparisonTerm<T> { | ||
12 | public EqTerm(Class<T> argumentType, Term<T> left, Term<T> right) { | ||
13 | super(argumentType, left, right); | ||
14 | } | ||
15 | |||
16 | @Override | ||
17 | protected Boolean doEvaluate(T leftValue, T rightValue) { | ||
18 | return leftValue.equals(rightValue); | ||
19 | } | ||
20 | |||
21 | @Override | ||
22 | public Term<Boolean> doSubstitute(Substitution substitution, Term<T> substitutedLeft, Term<T> substitutedRight) { | ||
23 | return new EqTerm<>(getArgumentType(), substitutedLeft, substitutedRight); | ||
24 | } | ||
25 | |||
26 | @Override | ||
27 | public String toString() { | ||
28 | return "(%s == %s)".formatted(getLeft(), getRight()); | ||
29 | } | ||
30 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/GreaterEqTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/GreaterEqTerm.java new file mode 100644 index 00000000..b109eb1a --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/GreaterEqTerm.java | |||
@@ -0,0 +1,30 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.comparable; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public class GreaterEqTerm<T extends Comparable<T>> extends ComparisonTerm<T> { | ||
12 | public GreaterEqTerm(Class<T> argumentType, Term<T> left, Term<T> right) { | ||
13 | super(argumentType, left, right); | ||
14 | } | ||
15 | |||
16 | @Override | ||
17 | protected Boolean doEvaluate(T leftValue, T rightValue) { | ||
18 | return leftValue.compareTo(rightValue) >= 0; | ||
19 | } | ||
20 | |||
21 | @Override | ||
22 | public Term<Boolean> doSubstitute(Substitution substitution, Term<T> substitutedLeft, Term<T> substitutedRight) { | ||
23 | return new GreaterEqTerm<>(getArgumentType(), substitutedLeft, substitutedRight); | ||
24 | } | ||
25 | |||
26 | @Override | ||
27 | public String toString() { | ||
28 | return "(%s >= %s)".formatted(getLeft(), getRight()); | ||
29 | } | ||
30 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/GreaterTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/GreaterTerm.java new file mode 100644 index 00000000..1b67f8b5 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/GreaterTerm.java | |||
@@ -0,0 +1,30 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.comparable; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public class GreaterTerm<T extends Comparable<T>> extends ComparisonTerm<T> { | ||
12 | public GreaterTerm(Class<T> argumentType, Term<T> left, Term<T> right) { | ||
13 | super(argumentType, left, right); | ||
14 | } | ||
15 | |||
16 | @Override | ||
17 | protected Boolean doEvaluate(T leftValue, T rightValue) { | ||
18 | return leftValue.compareTo(rightValue) > 0; | ||
19 | } | ||
20 | |||
21 | @Override | ||
22 | public Term<Boolean> doSubstitute(Substitution substitution, Term<T> substitutedLeft, Term<T> substitutedRight) { | ||
23 | return new GreaterTerm<>(getArgumentType(), substitutedLeft, substitutedRight); | ||
24 | } | ||
25 | |||
26 | @Override | ||
27 | public String toString() { | ||
28 | return "(%s > %s)".formatted(getLeft(), getRight()); | ||
29 | } | ||
30 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/LessEqTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/LessEqTerm.java new file mode 100644 index 00000000..1b34535f --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/LessEqTerm.java | |||
@@ -0,0 +1,30 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.comparable; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public class LessEqTerm<T extends Comparable<T>> extends ComparisonTerm<T> { | ||
12 | public LessEqTerm(Class<T> argumentType, Term<T> left, Term<T> right) { | ||
13 | super(argumentType, left, right); | ||
14 | } | ||
15 | |||
16 | @Override | ||
17 | protected Boolean doEvaluate(T leftValue, T rightValue) { | ||
18 | return leftValue.compareTo(rightValue) <= 0; | ||
19 | } | ||
20 | |||
21 | @Override | ||
22 | public Term<Boolean> doSubstitute(Substitution substitution, Term<T> substitutedLeft, Term<T> substitutedRight) { | ||
23 | return new LessEqTerm<>(getArgumentType(), substitutedLeft, substitutedRight); | ||
24 | } | ||
25 | |||
26 | @Override | ||
27 | public String toString() { | ||
28 | return "(%s <= %s)".formatted(getLeft(), getRight()); | ||
29 | } | ||
30 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/LessTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/LessTerm.java new file mode 100644 index 00000000..44e70902 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/LessTerm.java | |||
@@ -0,0 +1,30 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.comparable; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public class LessTerm<T extends Comparable<T>> extends ComparisonTerm<T> { | ||
12 | public LessTerm(Class<T> argumentType, Term<T> left, Term<T> right) { | ||
13 | super(argumentType, left, right); | ||
14 | } | ||
15 | |||
16 | @Override | ||
17 | protected Boolean doEvaluate(T leftValue, T rightValue) { | ||
18 | return leftValue.compareTo(rightValue) < 0; | ||
19 | } | ||
20 | |||
21 | @Override | ||
22 | public Term<Boolean> doSubstitute(Substitution substitution, Term<T> substitutedLeft, Term<T> substitutedRight) { | ||
23 | return new LessTerm<>(getArgumentType(), substitutedLeft, substitutedRight); | ||
24 | } | ||
25 | |||
26 | @Override | ||
27 | public String toString() { | ||
28 | return "(%s < %s)".formatted(getLeft(), getRight()); | ||
29 | } | ||
30 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/NotEqTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/NotEqTerm.java new file mode 100644 index 00000000..1f9734c4 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/comparable/NotEqTerm.java | |||
@@ -0,0 +1,30 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.comparable; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public class NotEqTerm<T> extends ComparisonTerm<T> { | ||
12 | public NotEqTerm(Class<T> argumentType, Term<T> left, Term<T> right) { | ||
13 | super(argumentType, left, right); | ||
14 | } | ||
15 | |||
16 | @Override | ||
17 | protected Boolean doEvaluate(T leftValue, T rightValue) { | ||
18 | return !leftValue.equals(rightValue); | ||
19 | } | ||
20 | |||
21 | @Override | ||
22 | public Term<Boolean> doSubstitute(Substitution substitution, Term<T> substitutedLeft, Term<T> substitutedRight) { | ||
23 | return new NotEqTerm<>(getArgumentType(), substitutedLeft, substitutedRight); | ||
24 | } | ||
25 | |||
26 | @Override | ||
27 | public String toString() { | ||
28 | return "(%s != %s)".formatted(getLeft(), getRight()); | ||
29 | } | ||
30 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntAddTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntAddTerm.java new file mode 100644 index 00000000..dbea3efc --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntAddTerm.java | |||
@@ -0,0 +1,31 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.int_; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public class IntAddTerm extends IntBinaryTerm { | ||
12 | public IntAddTerm(Term<Integer> left, Term<Integer> right) { | ||
13 | super(left, right); | ||
14 | } | ||
15 | |||
16 | @Override | ||
17 | public Term<Integer> doSubstitute(Substitution substitution, Term<Integer> substitutedLeft, | ||
18 | Term<Integer> substitutedRight) { | ||
19 | return new IntAddTerm(substitutedLeft, substitutedRight); | ||
20 | } | ||
21 | |||
22 | @Override | ||
23 | protected Integer doEvaluate(Integer leftValue, Integer rightValue) { | ||
24 | return leftValue + rightValue; | ||
25 | } | ||
26 | |||
27 | @Override | ||
28 | public String toString() { | ||
29 | return "(%s + %s)".formatted(getLeft(), getRight()); | ||
30 | } | ||
31 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntArithmeticBinaryTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntArithmeticBinaryTerm.java deleted file mode 100644 index 32e41718..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntArithmeticBinaryTerm.java +++ /dev/null | |||
@@ -1,48 +0,0 @@ | |||
1 | package tools.refinery.store.query.term.int_; | ||
2 | |||
3 | import tools.refinery.store.query.substitution.Substitution; | ||
4 | import tools.refinery.store.query.term.ArithmeticBinaryOperator; | ||
5 | import tools.refinery.store.query.term.ArithmeticBinaryTerm; | ||
6 | import tools.refinery.store.query.term.Term; | ||
7 | |||
8 | public class IntArithmeticBinaryTerm extends ArithmeticBinaryTerm<Integer> { | ||
9 | public IntArithmeticBinaryTerm(ArithmeticBinaryOperator operator, Term<Integer> left, Term<Integer> right) { | ||
10 | super(operator, left, right); | ||
11 | } | ||
12 | |||
13 | @Override | ||
14 | public Class<Integer> getType() { | ||
15 | return Integer.class; | ||
16 | } | ||
17 | |||
18 | @Override | ||
19 | public Term<Integer> doSubstitute(Substitution substitution, Term<Integer> substitutedLeft, | ||
20 | Term<Integer> substitutedRight) { | ||
21 | return new IntArithmeticBinaryTerm(getOperator(), substitutedLeft, substitutedRight); | ||
22 | } | ||
23 | |||
24 | @Override | ||
25 | protected Integer doEvaluate(Integer leftValue, Integer rightValue) { | ||
26 | return switch (getOperator()) { | ||
27 | case ADD -> leftValue + rightValue; | ||
28 | case SUB -> leftValue - rightValue; | ||
29 | case MUL -> leftValue * rightValue; | ||
30 | case DIV -> rightValue == 0 ? null : leftValue / rightValue; | ||
31 | case POW -> rightValue < 0 ? null : power(leftValue, rightValue); | ||
32 | case MIN -> Math.min(leftValue, rightValue); | ||
33 | case MAX -> Math.max(leftValue, rightValue); | ||
34 | }; | ||
35 | } | ||
36 | |||
37 | private static int power(int base, int exponent) { | ||
38 | int accum = 1; | ||
39 | while (exponent > 0) { | ||
40 | if (exponent % 2 == 1) { | ||
41 | accum = accum * base; | ||
42 | } | ||
43 | base = base * base; | ||
44 | exponent = exponent / 2; | ||
45 | } | ||
46 | return accum; | ||
47 | } | ||
48 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntArithmeticUnaryTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntArithmeticUnaryTerm.java deleted file mode 100644 index 1e769259..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntArithmeticUnaryTerm.java +++ /dev/null | |||
@@ -1,30 +0,0 @@ | |||
1 | package tools.refinery.store.query.term.int_; | ||
2 | |||
3 | import tools.refinery.store.query.substitution.Substitution; | ||
4 | import tools.refinery.store.query.term.Term; | ||
5 | import tools.refinery.store.query.term.ArithmeticUnaryOperator; | ||
6 | import tools.refinery.store.query.term.ArithmeticUnaryTerm; | ||
7 | |||
8 | public class IntArithmeticUnaryTerm extends ArithmeticUnaryTerm<Integer> { | ||
9 | public IntArithmeticUnaryTerm(ArithmeticUnaryOperator operation, Term<Integer> body) { | ||
10 | super(operation, body); | ||
11 | } | ||
12 | |||
13 | @Override | ||
14 | public Class<Integer> getType() { | ||
15 | return Integer.class; | ||
16 | } | ||
17 | |||
18 | @Override | ||
19 | protected Term<Integer> doSubstitute(Substitution substitution, Term<Integer> substitutedBody) { | ||
20 | return new IntArithmeticUnaryTerm(getOperator(), substitutedBody); | ||
21 | } | ||
22 | |||
23 | @Override | ||
24 | protected Integer doEvaluate(Integer bodyValue) { | ||
25 | return switch(getOperator()) { | ||
26 | case PLUS -> bodyValue; | ||
27 | case MINUS -> -bodyValue; | ||
28 | }; | ||
29 | } | ||
30 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntBinaryTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntBinaryTerm.java new file mode 100644 index 00000000..27ced4e4 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntBinaryTerm.java | |||
@@ -0,0 +1,15 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.int_; | ||
7 | |||
8 | import tools.refinery.store.query.term.BinaryTerm; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public abstract class IntBinaryTerm extends BinaryTerm<Integer, Integer, Integer> { | ||
12 | protected IntBinaryTerm(Term<Integer> left, Term<Integer> right) { | ||
13 | super(Integer.class, Integer.class, Integer.class, left, right); | ||
14 | } | ||
15 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntComparisonTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntComparisonTerm.java deleted file mode 100644 index 322d2b80..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntComparisonTerm.java +++ /dev/null | |||
@@ -1,34 +0,0 @@ | |||
1 | package tools.refinery.store.query.term.int_; | ||
2 | import tools.refinery.store.query.substitution.Substitution; | ||
3 | import tools.refinery.store.query.term.ComparisonOperator; | ||
4 | import tools.refinery.store.query.term.ComparisonTerm; | ||
5 | import tools.refinery.store.query.term.Term; | ||
6 | |||
7 | public class IntComparisonTerm extends ComparisonTerm<Integer> { | ||
8 | public IntComparisonTerm(ComparisonOperator operator, Term<Integer> left, Term<Integer> right) { | ||
9 | super(operator, left, right); | ||
10 | } | ||
11 | |||
12 | @Override | ||
13 | public Class<Integer> getOperandType() { | ||
14 | return Integer.class; | ||
15 | } | ||
16 | |||
17 | @Override | ||
18 | public Term<Boolean> doSubstitute(Substitution substitution, Term<Integer> substitutedLeft, | ||
19 | Term<Integer> substitutedRight) { | ||
20 | return new IntComparisonTerm(getOperator(), substitutedLeft, substitutedRight); | ||
21 | } | ||
22 | |||
23 | @Override | ||
24 | protected Boolean doEvaluate(Integer leftValue, Integer rightValue) { | ||
25 | return switch (getOperator()) { | ||
26 | case EQ -> leftValue.equals(rightValue); | ||
27 | case NOT_EQ -> !leftValue.equals(rightValue); | ||
28 | case LESS -> leftValue < rightValue; | ||
29 | case LESS_EQ -> leftValue <= rightValue; | ||
30 | case GREATER -> leftValue > rightValue; | ||
31 | case GREATER_EQ -> leftValue >= rightValue; | ||
32 | }; | ||
33 | } | ||
34 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntDivTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntDivTerm.java new file mode 100644 index 00000000..2a35058c --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntDivTerm.java | |||
@@ -0,0 +1,31 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.int_; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public class IntDivTerm extends IntBinaryTerm { | ||
12 | public IntDivTerm(Term<Integer> left, Term<Integer> right) { | ||
13 | super(left, right); | ||
14 | } | ||
15 | |||
16 | @Override | ||
17 | public Term<Integer> doSubstitute(Substitution substitution, Term<Integer> substitutedLeft, | ||
18 | Term<Integer> substitutedRight) { | ||
19 | return new IntDivTerm(substitutedLeft, substitutedRight); | ||
20 | } | ||
21 | |||
22 | @Override | ||
23 | protected Integer doEvaluate(Integer leftValue, Integer rightValue) { | ||
24 | return rightValue == 0 ? null : leftValue / rightValue; | ||
25 | } | ||
26 | |||
27 | @Override | ||
28 | public String toString() { | ||
29 | return "(%s / %s)".formatted(getLeft(), getRight()); | ||
30 | } | ||
31 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntExtremeValueAggregator.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntExtremeValueAggregator.java deleted file mode 100644 index d5a6add0..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntExtremeValueAggregator.java +++ /dev/null | |||
@@ -1,17 +0,0 @@ | |||
1 | package tools.refinery.store.query.term.int_; | ||
2 | |||
3 | import tools.refinery.store.query.term.ExtremeValueAggregator; | ||
4 | |||
5 | import java.util.Comparator; | ||
6 | |||
7 | public final class IntExtremeValueAggregator { | ||
8 | public static final ExtremeValueAggregator<Integer> MINIMUM = new ExtremeValueAggregator<>(Integer.class, | ||
9 | Integer.MAX_VALUE); | ||
10 | |||
11 | public static final ExtremeValueAggregator<Integer> MAXIMUM = new ExtremeValueAggregator<>(Integer.class, | ||
12 | Integer.MIN_VALUE, Comparator.reverseOrder()); | ||
13 | |||
14 | private IntExtremeValueAggregator() { | ||
15 | throw new IllegalStateException("This is a static utility class and should not be instantiated directly"); | ||
16 | } | ||
17 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntMaxTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntMaxTerm.java new file mode 100644 index 00000000..f81fc509 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntMaxTerm.java | |||
@@ -0,0 +1,31 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.int_; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public class IntMaxTerm extends IntBinaryTerm { | ||
12 | public IntMaxTerm(Term<Integer> left, Term<Integer> right) { | ||
13 | super(left, right); | ||
14 | } | ||
15 | |||
16 | @Override | ||
17 | public Term<Integer> doSubstitute(Substitution substitution, Term<Integer> substitutedLeft, | ||
18 | Term<Integer> substitutedRight) { | ||
19 | return new IntMaxTerm(substitutedLeft, substitutedRight); | ||
20 | } | ||
21 | |||
22 | @Override | ||
23 | protected Integer doEvaluate(Integer leftValue, Integer rightValue) { | ||
24 | return Math.max(rightValue, leftValue); | ||
25 | } | ||
26 | |||
27 | @Override | ||
28 | public String toString() { | ||
29 | return "max(%s, %s)".formatted(getLeft(), getRight()); | ||
30 | } | ||
31 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntMinTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntMinTerm.java new file mode 100644 index 00000000..89182e26 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntMinTerm.java | |||
@@ -0,0 +1,31 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.int_; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public class IntMinTerm extends IntBinaryTerm { | ||
12 | public IntMinTerm(Term<Integer> left, Term<Integer> right) { | ||
13 | super(left, right); | ||
14 | } | ||
15 | |||
16 | @Override | ||
17 | public Term<Integer> doSubstitute(Substitution substitution, Term<Integer> substitutedLeft, | ||
18 | Term<Integer> substitutedRight) { | ||
19 | return new IntMinTerm(substitutedLeft, substitutedRight); | ||
20 | } | ||
21 | |||
22 | @Override | ||
23 | protected Integer doEvaluate(Integer leftValue, Integer rightValue) { | ||
24 | return Math.min(rightValue, leftValue); | ||
25 | } | ||
26 | |||
27 | @Override | ||
28 | public String toString() { | ||
29 | return "min(%s, %s)".formatted(getLeft(), getRight()); | ||
30 | } | ||
31 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntMinusTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntMinusTerm.java new file mode 100644 index 00000000..709aa5ba --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntMinusTerm.java | |||
@@ -0,0 +1,30 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.int_; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public class IntMinusTerm extends IntUnaryTerm { | ||
12 | public IntMinusTerm(Term<Integer> body) { | ||
13 | super(body); | ||
14 | } | ||
15 | |||
16 | @Override | ||
17 | protected Term<Integer> doSubstitute(Substitution substitution, Term<Integer> substitutedBody) { | ||
18 | return new IntMinusTerm(substitutedBody); | ||
19 | } | ||
20 | |||
21 | @Override | ||
22 | protected Integer doEvaluate(Integer bodyValue) { | ||
23 | return -bodyValue; | ||
24 | } | ||
25 | |||
26 | @Override | ||
27 | public String toString() { | ||
28 | return "(-%s)".formatted(getBody()); | ||
29 | } | ||
30 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntMulTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntMulTerm.java new file mode 100644 index 00000000..89d4c5f4 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntMulTerm.java | |||
@@ -0,0 +1,31 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.int_; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public class IntMulTerm extends IntBinaryTerm { | ||
12 | public IntMulTerm(Term<Integer> left, Term<Integer> right) { | ||
13 | super(left, right); | ||
14 | } | ||
15 | |||
16 | @Override | ||
17 | public Term<Integer> doSubstitute(Substitution substitution, Term<Integer> substitutedLeft, | ||
18 | Term<Integer> substitutedRight) { | ||
19 | return new IntMulTerm(substitutedLeft, substitutedRight); | ||
20 | } | ||
21 | |||
22 | @Override | ||
23 | protected Integer doEvaluate(Integer leftValue, Integer rightValue) { | ||
24 | return leftValue * rightValue; | ||
25 | } | ||
26 | |||
27 | @Override | ||
28 | public String toString() { | ||
29 | return "(%s * %s)".formatted(getLeft(), getRight()); | ||
30 | } | ||
31 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntPlusTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntPlusTerm.java new file mode 100644 index 00000000..aef83bb4 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntPlusTerm.java | |||
@@ -0,0 +1,30 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.int_; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public class IntPlusTerm extends IntUnaryTerm { | ||
12 | public IntPlusTerm(Term<Integer> body) { | ||
13 | super(body); | ||
14 | } | ||
15 | |||
16 | @Override | ||
17 | protected Term<Integer> doSubstitute(Substitution substitution, Term<Integer> substitutedBody) { | ||
18 | return new IntPlusTerm(substitutedBody); | ||
19 | } | ||
20 | |||
21 | @Override | ||
22 | protected Integer doEvaluate(Integer bodyValue) { | ||
23 | return bodyValue; | ||
24 | } | ||
25 | |||
26 | @Override | ||
27 | public String toString() { | ||
28 | return "(+%s)".formatted(getBody()); | ||
29 | } | ||
30 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntPowTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntPowTerm.java new file mode 100644 index 00000000..d5af97a1 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntPowTerm.java | |||
@@ -0,0 +1,43 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.int_; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public class IntPowTerm extends IntBinaryTerm { | ||
12 | public IntPowTerm(Term<Integer> left, Term<Integer> right) { | ||
13 | super(left, right); | ||
14 | } | ||
15 | |||
16 | @Override | ||
17 | public Term<Integer> doSubstitute(Substitution substitution, Term<Integer> substitutedLeft, | ||
18 | Term<Integer> substitutedRight) { | ||
19 | return new IntPowTerm(substitutedLeft, substitutedRight); | ||
20 | } | ||
21 | |||
22 | @Override | ||
23 | protected Integer doEvaluate(Integer leftValue, Integer rightValue) { | ||
24 | return rightValue < 0 ? null : power(leftValue, rightValue); | ||
25 | } | ||
26 | |||
27 | private static int power(int base, int exponent) { | ||
28 | int accum = 1; | ||
29 | while (exponent > 0) { | ||
30 | if (exponent % 2 == 1) { | ||
31 | accum = accum * base; | ||
32 | } | ||
33 | base = base * base; | ||
34 | exponent = exponent / 2; | ||
35 | } | ||
36 | return accum; | ||
37 | } | ||
38 | |||
39 | @Override | ||
40 | public String toString() { | ||
41 | return "(%s ** %s)".formatted(getLeft(), getRight()); | ||
42 | } | ||
43 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntSubTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntSubTerm.java new file mode 100644 index 00000000..2c27afb1 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntSubTerm.java | |||
@@ -0,0 +1,31 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.int_; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public class IntSubTerm extends IntBinaryTerm { | ||
12 | public IntSubTerm(Term<Integer> left, Term<Integer> right) { | ||
13 | super(left, right); | ||
14 | } | ||
15 | |||
16 | @Override | ||
17 | public Term<Integer> doSubstitute(Substitution substitution, Term<Integer> substitutedLeft, | ||
18 | Term<Integer> substitutedRight) { | ||
19 | return new IntSubTerm(substitutedLeft, substitutedRight); | ||
20 | } | ||
21 | |||
22 | @Override | ||
23 | protected Integer doEvaluate(Integer leftValue, Integer rightValue) { | ||
24 | return leftValue - rightValue; | ||
25 | } | ||
26 | |||
27 | @Override | ||
28 | public String toString() { | ||
29 | return "(%s - %s)".formatted(getLeft(), getRight()); | ||
30 | } | ||
31 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntSumAggregator.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntSumAggregator.java index 65024f52..cd718c53 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntSumAggregator.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntSumAggregator.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.term.int_; | 6 | package tools.refinery.store.query.term.int_; |
2 | 7 | ||
3 | import tools.refinery.store.query.term.StatelessAggregator; | 8 | import tools.refinery.store.query.term.StatelessAggregator; |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntTerms.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntTerms.java index 86594deb..acb98b94 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntTerms.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntTerms.java | |||
@@ -1,81 +1,94 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.term.int_; | 6 | package tools.refinery.store.query.term.int_; |
2 | 7 | ||
3 | import tools.refinery.store.query.term.*; | 8 | import tools.refinery.store.query.term.Aggregator; |
9 | import tools.refinery.store.query.term.ConstantTerm; | ||
10 | import tools.refinery.store.query.term.ExtremeValueAggregator; | ||
11 | import tools.refinery.store.query.term.Term; | ||
12 | import tools.refinery.store.query.term.comparable.*; | ||
13 | |||
14 | import java.util.Comparator; | ||
4 | 15 | ||
5 | public final class IntTerms { | 16 | public final class IntTerms { |
6 | public static final Aggregator<Integer, Integer> INT_SUM = IntSumAggregator.INSTANCE; | 17 | public static final Aggregator<Integer, Integer> INT_SUM = IntSumAggregator.INSTANCE; |
7 | public static final Aggregator<Integer, Integer> INT_MIN = IntExtremeValueAggregator.MINIMUM; | 18 | public static final Aggregator<Integer, Integer> INT_MIN = new ExtremeValueAggregator<>(Integer.class, |
8 | public static final Aggregator<Integer, Integer> INT_MAX = IntExtremeValueAggregator.MAXIMUM; | 19 | Integer.MAX_VALUE); |
20 | public static final Aggregator<Integer, Integer> INT_MAX = new ExtremeValueAggregator<>(Integer.class, | ||
21 | Integer.MIN_VALUE, Comparator.reverseOrder()); | ||
9 | 22 | ||
10 | private IntTerms() { | 23 | private IntTerms() { |
11 | throw new IllegalArgumentException("This is a static utility class and should not be instantiated directly"); | 24 | throw new IllegalArgumentException("This is a static utility class and should not be instantiated directly"); |
12 | } | 25 | } |
13 | 26 | ||
14 | public static ConstantTerm<Integer> constant(int value) { | 27 | public static Term<Integer> constant(Integer value) { |
15 | return new ConstantTerm<>(Integer.class, value); | 28 | return new ConstantTerm<>(Integer.class, value); |
16 | } | 29 | } |
17 | 30 | ||
18 | public static IntArithmeticUnaryTerm plus(Term<Integer> body) { | 31 | public static Term<Integer> plus(Term<Integer> body) { |
19 | return new IntArithmeticUnaryTerm(ArithmeticUnaryOperator.PLUS, body); | 32 | return new IntPlusTerm(body); |
20 | } | 33 | } |
21 | 34 | ||
22 | public static IntArithmeticUnaryTerm minus(Term<Integer> body) { | 35 | public static Term<Integer> minus(Term<Integer> body) { |
23 | return new IntArithmeticUnaryTerm(ArithmeticUnaryOperator.MINUS, body); | 36 | return new IntMinusTerm(body); |
24 | } | 37 | } |
25 | 38 | ||
26 | public static IntArithmeticBinaryTerm add(Term<Integer> left, Term<Integer> right) { | 39 | public static Term<Integer> add(Term<Integer> left, Term<Integer> right) { |
27 | return new IntArithmeticBinaryTerm(ArithmeticBinaryOperator.ADD, left, right); | 40 | return new IntAddTerm(left, right); |
28 | } | 41 | } |
29 | 42 | ||
30 | public static IntArithmeticBinaryTerm sub(Term<Integer> left, Term<Integer> right) { | 43 | public static Term<Integer> sub(Term<Integer> left, Term<Integer> right) { |
31 | return new IntArithmeticBinaryTerm(ArithmeticBinaryOperator.SUB, left, right); | 44 | return new IntSubTerm(left, right); |
32 | } | 45 | } |
33 | 46 | ||
34 | public static IntArithmeticBinaryTerm mul(Term<Integer> left, Term<Integer> right) { | 47 | public static Term<Integer> mul(Term<Integer> left, Term<Integer> right) { |
35 | return new IntArithmeticBinaryTerm(ArithmeticBinaryOperator.MUL, left, right); | 48 | return new IntMulTerm(left, right); |
36 | } | 49 | } |
37 | 50 | ||
38 | public static IntArithmeticBinaryTerm div(Term<Integer> left, Term<Integer> right) { | 51 | public static Term<Integer> div(Term<Integer> left, Term<Integer> right) { |
39 | return new IntArithmeticBinaryTerm(ArithmeticBinaryOperator.DIV, left, right); | 52 | return new IntDivTerm(left, right); |
40 | } | 53 | } |
41 | 54 | ||
42 | public static IntArithmeticBinaryTerm pow(Term<Integer> left, Term<Integer> right) { | 55 | public static Term<Integer> pow(Term<Integer> left, Term<Integer> right) { |
43 | return new IntArithmeticBinaryTerm(ArithmeticBinaryOperator.POW, left, right); | 56 | return new IntPowTerm(left, right); |
44 | } | 57 | } |
45 | 58 | ||
46 | public static IntArithmeticBinaryTerm min(Term<Integer> left, Term<Integer> right) { | 59 | public static Term<Integer> min(Term<Integer> left, Term<Integer> right) { |
47 | return new IntArithmeticBinaryTerm(ArithmeticBinaryOperator.MIN, left, right); | 60 | return new IntMinTerm(left, right); |
48 | } | 61 | } |
49 | 62 | ||
50 | public static IntArithmeticBinaryTerm max(Term<Integer> left, Term<Integer> right) { | 63 | public static Term<Integer> max(Term<Integer> left, Term<Integer> right) { |
51 | return new IntArithmeticBinaryTerm(ArithmeticBinaryOperator.MAX, left, right); | 64 | return new IntMaxTerm(left, right); |
52 | } | 65 | } |
53 | 66 | ||
54 | public static IntComparisonTerm eq(Term<Integer> left, Term<Integer> right) { | 67 | public static Term<Boolean> eq(Term<Integer> left, Term<Integer> right) { |
55 | return new IntComparisonTerm(ComparisonOperator.EQ, left, right); | 68 | return new EqTerm<>(Integer.class, left, right); |
56 | } | 69 | } |
57 | 70 | ||
58 | public static IntComparisonTerm notEq(Term<Integer> left, Term<Integer> right) { | 71 | public static Term<Boolean> notEq(Term<Integer> left, Term<Integer> right) { |
59 | return new IntComparisonTerm(ComparisonOperator.NOT_EQ, left, right); | 72 | return new NotEqTerm<>(Integer.class, left, right); |
60 | } | 73 | } |
61 | 74 | ||
62 | public static IntComparisonTerm less(Term<Integer> left, Term<Integer> right) { | 75 | public static Term<Boolean> less(Term<Integer> left, Term<Integer> right) { |
63 | return new IntComparisonTerm(ComparisonOperator.LESS, left, right); | 76 | return new LessTerm<>(Integer.class, left, right); |
64 | } | 77 | } |
65 | 78 | ||
66 | public static IntComparisonTerm lessEq(Term<Integer> left, Term<Integer> right) { | 79 | public static Term<Boolean> lessEq(Term<Integer> left, Term<Integer> right) { |
67 | return new IntComparisonTerm(ComparisonOperator.LESS_EQ, left, right); | 80 | return new LessEqTerm<>(Integer.class, left, right); |
68 | } | 81 | } |
69 | 82 | ||
70 | public static IntComparisonTerm greater(Term<Integer> left, Term<Integer> right) { | 83 | public static Term<Boolean> greater(Term<Integer> left, Term<Integer> right) { |
71 | return new IntComparisonTerm(ComparisonOperator.GREATER, left, right); | 84 | return new GreaterTerm<>(Integer.class, left, right); |
72 | } | 85 | } |
73 | 86 | ||
74 | public static IntComparisonTerm greaterEq(Term<Integer> left, Term<Integer> right) { | 87 | public static Term<Boolean> greaterEq(Term<Integer> left, Term<Integer> right) { |
75 | return new IntComparisonTerm(ComparisonOperator.GREATER_EQ, left, right); | 88 | return new GreaterEqTerm<>(Integer.class, left, right); |
76 | } | 89 | } |
77 | 90 | ||
78 | public static RealToIntTerm asInt(Term<Double> body) { | 91 | public static Term<Integer> asInt(Term<Double> body) { |
79 | return new RealToIntTerm(body); | 92 | return new RealToIntTerm(body); |
80 | } | 93 | } |
81 | } | 94 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntUnaryTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntUnaryTerm.java new file mode 100644 index 00000000..49b4c647 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/IntUnaryTerm.java | |||
@@ -0,0 +1,15 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.int_; | ||
7 | |||
8 | import tools.refinery.store.query.term.Term; | ||
9 | import tools.refinery.store.query.term.UnaryTerm; | ||
10 | |||
11 | public abstract class IntUnaryTerm extends UnaryTerm<Integer, Integer> { | ||
12 | protected IntUnaryTerm(Term<Integer> body) { | ||
13 | super(Integer.class, Integer.class, body); | ||
14 | } | ||
15 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/RealToIntTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/RealToIntTerm.java index 53875ddc..7d383562 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/RealToIntTerm.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/int_/RealToIntTerm.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.term.int_; | 6 | package tools.refinery.store.query.term.int_; |
2 | 7 | ||
3 | import tools.refinery.store.query.substitution.Substitution; | 8 | import tools.refinery.store.query.substitution.Substitution; |
@@ -6,22 +11,12 @@ import tools.refinery.store.query.term.UnaryTerm; | |||
6 | 11 | ||
7 | public class RealToIntTerm extends UnaryTerm<Integer, Double> { | 12 | public class RealToIntTerm extends UnaryTerm<Integer, Double> { |
8 | protected RealToIntTerm(Term<Double> body) { | 13 | protected RealToIntTerm(Term<Double> body) { |
9 | super(body); | 14 | super(Integer.class, Double.class, body); |
10 | } | ||
11 | |||
12 | @Override | ||
13 | public Class<Integer> getType() { | ||
14 | return Integer.class; | ||
15 | } | ||
16 | |||
17 | @Override | ||
18 | public Class<Double> getBodyType() { | ||
19 | return Double.class; | ||
20 | } | 15 | } |
21 | 16 | ||
22 | @Override | 17 | @Override |
23 | protected Integer doEvaluate(Double bodyValue) { | 18 | protected Integer doEvaluate(Double bodyValue) { |
24 | return bodyValue.intValue(); | 19 | return bodyValue.isNaN() ? null : bodyValue.intValue(); |
25 | } | 20 | } |
26 | 21 | ||
27 | @Override | 22 | @Override |
@@ -31,6 +26,6 @@ public class RealToIntTerm extends UnaryTerm<Integer, Double> { | |||
31 | 26 | ||
32 | @Override | 27 | @Override |
33 | public String toString() { | 28 | public String toString() { |
34 | return "(%s) as int".formatted(getBody()); | 29 | return "(%s as int)".formatted(getBody()); |
35 | } | 30 | } |
36 | } | 31 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/IntToRealTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/IntToRealTerm.java index 55590824..2f53117a 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/IntToRealTerm.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/IntToRealTerm.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.term.real; | 6 | package tools.refinery.store.query.term.real; |
2 | 7 | ||
3 | import tools.refinery.store.query.substitution.Substitution; | 8 | import tools.refinery.store.query.substitution.Substitution; |
@@ -6,17 +11,7 @@ import tools.refinery.store.query.term.UnaryTerm; | |||
6 | 11 | ||
7 | public class IntToRealTerm extends UnaryTerm<Double, Integer> { | 12 | public class IntToRealTerm extends UnaryTerm<Double, Integer> { |
8 | protected IntToRealTerm(Term<Integer> body) { | 13 | protected IntToRealTerm(Term<Integer> body) { |
9 | super(body); | 14 | super(Double.class, Integer.class, body); |
10 | } | ||
11 | |||
12 | @Override | ||
13 | public Class<Double> getType() { | ||
14 | return Double.class; | ||
15 | } | ||
16 | |||
17 | @Override | ||
18 | public Class<Integer> getBodyType() { | ||
19 | return Integer.class; | ||
20 | } | 15 | } |
21 | 16 | ||
22 | @Override | 17 | @Override |
@@ -31,6 +26,6 @@ public class IntToRealTerm extends UnaryTerm<Double, Integer> { | |||
31 | 26 | ||
32 | @Override | 27 | @Override |
33 | public String toString() { | 28 | public String toString() { |
34 | return "(%s) as real".formatted(getBody()); | 29 | return "(%s as real)".formatted(getBody()); |
35 | } | 30 | } |
36 | } | 31 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealAddTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealAddTerm.java new file mode 100644 index 00000000..33fc9e41 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealAddTerm.java | |||
@@ -0,0 +1,31 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.real; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public class RealAddTerm extends RealBinaryTerm { | ||
12 | public RealAddTerm(Term<Double> left, Term<Double> right) { | ||
13 | super(left, right); | ||
14 | } | ||
15 | |||
16 | @Override | ||
17 | public Term<Double> doSubstitute(Substitution substitution, Term<Double> substitutedLeft, | ||
18 | Term<Double> substitutedRight) { | ||
19 | return new RealAddTerm(substitutedLeft, substitutedRight); | ||
20 | } | ||
21 | |||
22 | @Override | ||
23 | protected Double doEvaluate(Double leftValue, Double rightValue) { | ||
24 | return leftValue + rightValue; | ||
25 | } | ||
26 | |||
27 | @Override | ||
28 | public String toString() { | ||
29 | return "(%s + %s)".formatted(getLeft(), getRight()); | ||
30 | } | ||
31 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealArithmeticBinaryTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealArithmeticBinaryTerm.java deleted file mode 100644 index 57bcbe5e..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealArithmeticBinaryTerm.java +++ /dev/null | |||
@@ -1,36 +0,0 @@ | |||
1 | package tools.refinery.store.query.term.real; | ||
2 | |||
3 | import tools.refinery.store.query.substitution.Substitution; | ||
4 | import tools.refinery.store.query.term.ArithmeticBinaryOperator; | ||
5 | import tools.refinery.store.query.term.ArithmeticBinaryTerm; | ||
6 | import tools.refinery.store.query.term.Term; | ||
7 | |||
8 | public class RealArithmeticBinaryTerm extends ArithmeticBinaryTerm<Double> { | ||
9 | public RealArithmeticBinaryTerm(ArithmeticBinaryOperator operator, Term<Double> left, Term<Double> right) { | ||
10 | super(operator, left, right); | ||
11 | } | ||
12 | |||
13 | @Override | ||
14 | public Class<Double> getType() { | ||
15 | return Double.class; | ||
16 | } | ||
17 | |||
18 | @Override | ||
19 | public Term<Double> doSubstitute(Substitution substitution, Term<Double> substitutedLeft, | ||
20 | Term<Double> substitutedRight) { | ||
21 | return new RealArithmeticBinaryTerm(getOperator(), substitutedLeft, substitutedRight); | ||
22 | } | ||
23 | |||
24 | @Override | ||
25 | protected Double doEvaluate(Double leftValue, Double rightValue) { | ||
26 | return switch (getOperator()) { | ||
27 | case ADD -> leftValue + rightValue; | ||
28 | case SUB -> leftValue - rightValue; | ||
29 | case MUL -> leftValue * rightValue; | ||
30 | case DIV -> leftValue / rightValue; | ||
31 | case POW -> Math.pow(leftValue, rightValue); | ||
32 | case MIN -> Math.min(leftValue, rightValue); | ||
33 | case MAX -> Math.max(leftValue, rightValue); | ||
34 | }; | ||
35 | } | ||
36 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealArithmeticUnaryTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealArithmeticUnaryTerm.java deleted file mode 100644 index 632e68bf..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealArithmeticUnaryTerm.java +++ /dev/null | |||
@@ -1,30 +0,0 @@ | |||
1 | package tools.refinery.store.query.term.real; | ||
2 | |||
3 | import tools.refinery.store.query.substitution.Substitution; | ||
4 | import tools.refinery.store.query.term.ArithmeticUnaryOperator; | ||
5 | import tools.refinery.store.query.term.ArithmeticUnaryTerm; | ||
6 | import tools.refinery.store.query.term.Term; | ||
7 | |||
8 | public class RealArithmeticUnaryTerm extends ArithmeticUnaryTerm<Double> { | ||
9 | public RealArithmeticUnaryTerm(ArithmeticUnaryOperator operation, Term<Double> body) { | ||
10 | super(operation, body); | ||
11 | } | ||
12 | |||
13 | @Override | ||
14 | public Class<Double> getType() { | ||
15 | return Double.class; | ||
16 | } | ||
17 | |||
18 | @Override | ||
19 | protected Term<Double> doSubstitute(Substitution substitution, Term<Double> substitutedBody) { | ||
20 | return new RealArithmeticUnaryTerm(getOperator(), substitutedBody); | ||
21 | } | ||
22 | |||
23 | @Override | ||
24 | protected Double doEvaluate(Double bodyValue) { | ||
25 | return switch(getOperator()) { | ||
26 | case PLUS -> bodyValue; | ||
27 | case MINUS -> -bodyValue; | ||
28 | }; | ||
29 | } | ||
30 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealBinaryTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealBinaryTerm.java new file mode 100644 index 00000000..000f3623 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealBinaryTerm.java | |||
@@ -0,0 +1,15 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.real; | ||
7 | |||
8 | import tools.refinery.store.query.term.BinaryTerm; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public abstract class RealBinaryTerm extends BinaryTerm<Double, Double, Double> { | ||
12 | protected RealBinaryTerm(Term<Double> left, Term<Double> right) { | ||
13 | super(Double.class, Double.class, Double.class, left, right); | ||
14 | } | ||
15 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealComparisonTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealComparisonTerm.java deleted file mode 100644 index 75d97adb..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealComparisonTerm.java +++ /dev/null | |||
@@ -1,35 +0,0 @@ | |||
1 | package tools.refinery.store.query.term.real; | ||
2 | |||
3 | import tools.refinery.store.query.substitution.Substitution; | ||
4 | import tools.refinery.store.query.term.ComparisonOperator; | ||
5 | import tools.refinery.store.query.term.ComparisonTerm; | ||
6 | import tools.refinery.store.query.term.Term; | ||
7 | |||
8 | public class RealComparisonTerm extends ComparisonTerm<Double> { | ||
9 | public RealComparisonTerm(ComparisonOperator operator, Term<Double> left, Term<Double> right) { | ||
10 | super(operator, left, right); | ||
11 | } | ||
12 | |||
13 | @Override | ||
14 | public Class<Double> getOperandType() { | ||
15 | return Double.class; | ||
16 | } | ||
17 | |||
18 | @Override | ||
19 | public Term<Boolean> doSubstitute(Substitution substitution, Term<Double> substitutedLeft, | ||
20 | Term<Double> substitutedRight) { | ||
21 | return new RealComparisonTerm(getOperator(), substitutedLeft, substitutedRight); | ||
22 | } | ||
23 | |||
24 | @Override | ||
25 | protected Boolean doEvaluate(Double leftValue, Double rightValue) { | ||
26 | return switch (getOperator()) { | ||
27 | case EQ -> leftValue.equals(rightValue); | ||
28 | case NOT_EQ -> !leftValue.equals(rightValue); | ||
29 | case LESS -> leftValue < rightValue; | ||
30 | case LESS_EQ -> leftValue <= rightValue; | ||
31 | case GREATER -> leftValue > rightValue; | ||
32 | case GREATER_EQ -> leftValue >= rightValue; | ||
33 | }; | ||
34 | } | ||
35 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealDivTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealDivTerm.java new file mode 100644 index 00000000..1e55bf42 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealDivTerm.java | |||
@@ -0,0 +1,31 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.real; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public class RealDivTerm extends RealBinaryTerm { | ||
12 | public RealDivTerm(Term<Double> left, Term<Double> right) { | ||
13 | super(left, right); | ||
14 | } | ||
15 | |||
16 | @Override | ||
17 | public Term<Double> doSubstitute(Substitution substitution, Term<Double> substitutedLeft, | ||
18 | Term<Double> substitutedRight) { | ||
19 | return new RealDivTerm(substitutedLeft, substitutedRight); | ||
20 | } | ||
21 | |||
22 | @Override | ||
23 | protected Double doEvaluate(Double leftValue, Double rightValue) { | ||
24 | return leftValue / rightValue; | ||
25 | } | ||
26 | |||
27 | @Override | ||
28 | public String toString() { | ||
29 | return "(%s / %s)".formatted(getLeft(), getRight()); | ||
30 | } | ||
31 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealExtremeValueAggregator.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealExtremeValueAggregator.java deleted file mode 100644 index 23384530..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealExtremeValueAggregator.java +++ /dev/null | |||
@@ -1,17 +0,0 @@ | |||
1 | package tools.refinery.store.query.term.real; | ||
2 | |||
3 | import tools.refinery.store.query.term.ExtremeValueAggregator; | ||
4 | |||
5 | import java.util.Comparator; | ||
6 | |||
7 | public final class RealExtremeValueAggregator { | ||
8 | public static final ExtremeValueAggregator<Double> MINIMUM = new ExtremeValueAggregator<>(Double.class, | ||
9 | Double.POSITIVE_INFINITY); | ||
10 | |||
11 | public static final ExtremeValueAggregator<Double> MAXIMUM = new ExtremeValueAggregator<>(Double.class, | ||
12 | Double.NEGATIVE_INFINITY, Comparator.reverseOrder()); | ||
13 | |||
14 | private RealExtremeValueAggregator() { | ||
15 | throw new IllegalStateException("This is a static utility class and should not be instantiated directly"); | ||
16 | } | ||
17 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealMaxTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealMaxTerm.java new file mode 100644 index 00000000..2a249496 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealMaxTerm.java | |||
@@ -0,0 +1,31 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.real; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public class RealMaxTerm extends RealBinaryTerm { | ||
12 | public RealMaxTerm(Term<Double> left, Term<Double> right) { | ||
13 | super(left, right); | ||
14 | } | ||
15 | |||
16 | @Override | ||
17 | public Term<Double> doSubstitute(Substitution substitution, Term<Double> substitutedLeft, | ||
18 | Term<Double> substitutedRight) { | ||
19 | return new RealMaxTerm(substitutedLeft, substitutedRight); | ||
20 | } | ||
21 | |||
22 | @Override | ||
23 | protected Double doEvaluate(Double leftValue, Double rightValue) { | ||
24 | return Math.max(leftValue, rightValue); | ||
25 | } | ||
26 | |||
27 | @Override | ||
28 | public String toString() { | ||
29 | return "max(%s, %s)".formatted(getLeft(), getRight()); | ||
30 | } | ||
31 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealMinTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealMinTerm.java new file mode 100644 index 00000000..2eb4cc1e --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealMinTerm.java | |||
@@ -0,0 +1,31 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.real; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public class RealMinTerm extends RealBinaryTerm { | ||
12 | public RealMinTerm(Term<Double> left, Term<Double> right) { | ||
13 | super(left, right); | ||
14 | } | ||
15 | |||
16 | @Override | ||
17 | public Term<Double> doSubstitute(Substitution substitution, Term<Double> substitutedLeft, | ||
18 | Term<Double> substitutedRight) { | ||
19 | return new RealMinTerm(substitutedLeft, substitutedRight); | ||
20 | } | ||
21 | |||
22 | @Override | ||
23 | protected Double doEvaluate(Double leftValue, Double rightValue) { | ||
24 | return Math.min(leftValue, rightValue); | ||
25 | } | ||
26 | |||
27 | @Override | ||
28 | public String toString() { | ||
29 | return "min(%s, %s)".formatted(getLeft(), getRight()); | ||
30 | } | ||
31 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealMinusTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealMinusTerm.java new file mode 100644 index 00000000..4afec7a1 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealMinusTerm.java | |||
@@ -0,0 +1,30 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.real; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public class RealMinusTerm extends RealUnaryTerm { | ||
12 | public RealMinusTerm(Term<Double> body) { | ||
13 | super(body); | ||
14 | } | ||
15 | |||
16 | @Override | ||
17 | protected Term<Double> doSubstitute(Substitution substitution, Term<Double> substitutedBody) { | ||
18 | return new RealMinusTerm(substitutedBody); | ||
19 | } | ||
20 | |||
21 | @Override | ||
22 | protected Double doEvaluate(Double bodyValue) { | ||
23 | return -bodyValue; | ||
24 | } | ||
25 | |||
26 | @Override | ||
27 | public String toString() { | ||
28 | return "(-%s)".formatted(getBody()); | ||
29 | } | ||
30 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealMulTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealMulTerm.java new file mode 100644 index 00000000..ec95ac6f --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealMulTerm.java | |||
@@ -0,0 +1,31 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.real; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public class RealMulTerm extends RealBinaryTerm { | ||
12 | public RealMulTerm(Term<Double> left, Term<Double> right) { | ||
13 | super(left, right); | ||
14 | } | ||
15 | |||
16 | @Override | ||
17 | public Term<Double> doSubstitute(Substitution substitution, Term<Double> substitutedLeft, | ||
18 | Term<Double> substitutedRight) { | ||
19 | return new RealMulTerm(substitutedLeft, substitutedRight); | ||
20 | } | ||
21 | |||
22 | @Override | ||
23 | protected Double doEvaluate(Double leftValue, Double rightValue) { | ||
24 | return leftValue * rightValue; | ||
25 | } | ||
26 | |||
27 | @Override | ||
28 | public String toString() { | ||
29 | return "(%s * %s)".formatted(getLeft(), getRight()); | ||
30 | } | ||
31 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealPlusTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealPlusTerm.java new file mode 100644 index 00000000..64dd2e70 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealPlusTerm.java | |||
@@ -0,0 +1,30 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.real; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public class RealPlusTerm extends RealUnaryTerm { | ||
12 | public RealPlusTerm(Term<Double> body) { | ||
13 | super(body); | ||
14 | } | ||
15 | |||
16 | @Override | ||
17 | protected Term<Double> doSubstitute(Substitution substitution, Term<Double> substitutedBody) { | ||
18 | return new RealPlusTerm(substitutedBody); | ||
19 | } | ||
20 | |||
21 | @Override | ||
22 | protected Double doEvaluate(Double bodyValue) { | ||
23 | return bodyValue; | ||
24 | } | ||
25 | |||
26 | @Override | ||
27 | public String toString() { | ||
28 | return "(+%s)".formatted(getBody()); | ||
29 | } | ||
30 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealPowTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealPowTerm.java new file mode 100644 index 00000000..11c952ea --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealPowTerm.java | |||
@@ -0,0 +1,31 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.real; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public class RealPowTerm extends RealBinaryTerm { | ||
12 | public RealPowTerm(Term<Double> left, Term<Double> right) { | ||
13 | super(left, right); | ||
14 | } | ||
15 | |||
16 | @Override | ||
17 | public Term<Double> doSubstitute(Substitution substitution, Term<Double> substitutedLeft, | ||
18 | Term<Double> substitutedRight) { | ||
19 | return new RealPowTerm(substitutedLeft, substitutedRight); | ||
20 | } | ||
21 | |||
22 | @Override | ||
23 | protected Double doEvaluate(Double leftValue, Double rightValue) { | ||
24 | return Math.pow(leftValue, rightValue); | ||
25 | } | ||
26 | |||
27 | @Override | ||
28 | public String toString() { | ||
29 | return "(%s ** %s)".formatted(getLeft(), getRight()); | ||
30 | } | ||
31 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealSubTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealSubTerm.java new file mode 100644 index 00000000..8cc701ed --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealSubTerm.java | |||
@@ -0,0 +1,31 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.real; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | |||
11 | public class RealSubTerm extends RealBinaryTerm { | ||
12 | public RealSubTerm(Term<Double> left, Term<Double> right) { | ||
13 | super(left, right); | ||
14 | } | ||
15 | |||
16 | @Override | ||
17 | public Term<Double> doSubstitute(Substitution substitution, Term<Double> substitutedLeft, | ||
18 | Term<Double> substitutedRight) { | ||
19 | return new RealSubTerm(substitutedLeft, substitutedRight); | ||
20 | } | ||
21 | |||
22 | @Override | ||
23 | protected Double doEvaluate(Double leftValue, Double rightValue) { | ||
24 | return leftValue - rightValue; | ||
25 | } | ||
26 | |||
27 | @Override | ||
28 | public String toString() { | ||
29 | return "(%s - %s)".formatted(getLeft(), getRight()); | ||
30 | } | ||
31 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealSumAggregator.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealSumAggregator.java index d5888664..d21048e9 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealSumAggregator.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealSumAggregator.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.term.real; | 6 | package tools.refinery.store.query.term.real; |
2 | 7 | ||
3 | import tools.refinery.store.query.term.StatefulAggregate; | 8 | import tools.refinery.store.query.term.StatefulAggregate; |
@@ -14,12 +19,12 @@ public final class RealSumAggregator implements StatefulAggregator<Double, Doubl | |||
14 | 19 | ||
15 | @Override | 20 | @Override |
16 | public Class<Double> getResultType() { | 21 | public Class<Double> getResultType() { |
17 | return null; | 22 | return Double.class; |
18 | } | 23 | } |
19 | 24 | ||
20 | @Override | 25 | @Override |
21 | public Class<Double> getInputType() { | 26 | public Class<Double> getInputType() { |
22 | return null; | 27 | return Double.class; |
23 | } | 28 | } |
24 | 29 | ||
25 | @Override | 30 | @Override |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealTerms.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealTerms.java index a8117842..79220358 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealTerms.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealTerms.java | |||
@@ -1,81 +1,94 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.term.real; | 6 | package tools.refinery.store.query.term.real; |
2 | 7 | ||
3 | import tools.refinery.store.query.term.*; | 8 | import tools.refinery.store.query.term.Aggregator; |
9 | import tools.refinery.store.query.term.ConstantTerm; | ||
10 | import tools.refinery.store.query.term.ExtremeValueAggregator; | ||
11 | import tools.refinery.store.query.term.Term; | ||
12 | import tools.refinery.store.query.term.comparable.*; | ||
13 | |||
14 | import java.util.Comparator; | ||
4 | 15 | ||
5 | public final class RealTerms { | 16 | public final class RealTerms { |
6 | public static final Aggregator<Double, Double> REAL_SUM = RealSumAggregator.INSTANCE; | 17 | public static final Aggregator<Double, Double> REAL_SUM = RealSumAggregator.INSTANCE; |
7 | public static final Aggregator<Double, Double> REAL_MIN = RealExtremeValueAggregator.MINIMUM; | 18 | public static final Aggregator<Double, Double> REAL_MIN = new ExtremeValueAggregator<>(Double.class, |
8 | public static final Aggregator<Double, Double> REAL_MAX = RealExtremeValueAggregator.MAXIMUM; | 19 | Double.POSITIVE_INFINITY); |
20 | public static final Aggregator<Double, Double> REAL_MAX = new ExtremeValueAggregator<>(Double.class, | ||
21 | Double.NEGATIVE_INFINITY, Comparator.reverseOrder()); | ||
9 | 22 | ||
10 | private RealTerms() { | 23 | private RealTerms() { |
11 | throw new IllegalArgumentException("This is a static utility class and should not be instantiated directly"); | 24 | throw new IllegalArgumentException("This is a static utility class and should not be instantiated directly"); |
12 | } | 25 | } |
13 | 26 | ||
14 | public static ConstantTerm<Double> constant(double value) { | 27 | public static Term<Double> constant(Double value) { |
15 | return new ConstantTerm<>(Double.class, value); | 28 | return new ConstantTerm<>(Double.class, value); |
16 | } | 29 | } |
17 | 30 | ||
18 | public static RealArithmeticUnaryTerm plus(Term<Double> body) { | 31 | public static Term<Double> plus(Term<Double> body) { |
19 | return new RealArithmeticUnaryTerm(ArithmeticUnaryOperator.PLUS, body); | 32 | return new RealPlusTerm(body); |
20 | } | 33 | } |
21 | 34 | ||
22 | public static RealArithmeticUnaryTerm minus(Term<Double> body) { | 35 | public static Term<Double> minus(Term<Double> body) { |
23 | return new RealArithmeticUnaryTerm(ArithmeticUnaryOperator.MINUS, body); | 36 | return new RealMinusTerm(body); |
24 | } | 37 | } |
25 | 38 | ||
26 | public static RealArithmeticBinaryTerm add(Term<Double> left, Term<Double> right) { | 39 | public static Term<Double> add(Term<Double> left, Term<Double> right) { |
27 | return new RealArithmeticBinaryTerm(ArithmeticBinaryOperator.ADD, left, right); | 40 | return new RealAddTerm(left, right); |
28 | } | 41 | } |
29 | 42 | ||
30 | public static RealArithmeticBinaryTerm sub(Term<Double> left, Term<Double> right) { | 43 | public static Term<Double> sub(Term<Double> left, Term<Double> right) { |
31 | return new RealArithmeticBinaryTerm(ArithmeticBinaryOperator.SUB, left, right); | 44 | return new RealSubTerm(left, right); |
32 | } | 45 | } |
33 | 46 | ||
34 | public static RealArithmeticBinaryTerm mul(Term<Double> left, Term<Double> right) { | 47 | public static Term<Double> mul(Term<Double> left, Term<Double> right) { |
35 | return new RealArithmeticBinaryTerm(ArithmeticBinaryOperator.MUL, left, right); | 48 | return new RealMulTerm(left, right); |
36 | } | 49 | } |
37 | 50 | ||
38 | public static RealArithmeticBinaryTerm div(Term<Double> left, Term<Double> right) { | 51 | public static Term<Double> div(Term<Double> left, Term<Double> right) { |
39 | return new RealArithmeticBinaryTerm(ArithmeticBinaryOperator.DIV, left, right); | 52 | return new RealDivTerm(left, right); |
40 | } | 53 | } |
41 | 54 | ||
42 | public static RealArithmeticBinaryTerm pow(Term<Double> left, Term<Double> right) { | 55 | public static Term<Double> pow(Term<Double> left, Term<Double> right) { |
43 | return new RealArithmeticBinaryTerm(ArithmeticBinaryOperator.POW, left, right); | 56 | return new RealPowTerm(left, right); |
44 | } | 57 | } |
45 | 58 | ||
46 | public static RealArithmeticBinaryTerm min(Term<Double> left, Term<Double> right) { | 59 | public static Term<Double> min(Term<Double> left, Term<Double> right) { |
47 | return new RealArithmeticBinaryTerm(ArithmeticBinaryOperator.MIN, left, right); | 60 | return new RealMinTerm(left, right); |
48 | } | 61 | } |
49 | 62 | ||
50 | public static RealArithmeticBinaryTerm max(Term<Double> left, Term<Double> right) { | 63 | public static Term<Double> max(Term<Double> left, Term<Double> right) { |
51 | return new RealArithmeticBinaryTerm(ArithmeticBinaryOperator.MAX, left, right); | 64 | return new RealMaxTerm(left, right); |
52 | } | 65 | } |
53 | 66 | ||
54 | public static RealComparisonTerm eq(Term<Double> left, Term<Double> right) { | 67 | public static Term<Boolean> eq(Term<Double> left, Term<Double> right) { |
55 | return new RealComparisonTerm(ComparisonOperator.EQ, left, right); | 68 | return new EqTerm<>(Double.class, left, right); |
56 | } | 69 | } |
57 | 70 | ||
58 | public static RealComparisonTerm notEq(Term<Double> left, Term<Double> right) { | 71 | public static Term<Boolean> notEq(Term<Double> left, Term<Double> right) { |
59 | return new RealComparisonTerm(ComparisonOperator.NOT_EQ, left, right); | 72 | return new NotEqTerm<>(Double.class, left, right); |
60 | } | 73 | } |
61 | 74 | ||
62 | public static RealComparisonTerm less(Term<Double> left, Term<Double> right) { | 75 | public static Term<Boolean> less(Term<Double> left, Term<Double> right) { |
63 | return new RealComparisonTerm(ComparisonOperator.LESS, left, right); | 76 | return new LessTerm<>(Double.class, left, right); |
64 | } | 77 | } |
65 | 78 | ||
66 | public static RealComparisonTerm lessEq(Term<Double> left, Term<Double> right) { | 79 | public static Term<Boolean> lessEq(Term<Double> left, Term<Double> right) { |
67 | return new RealComparisonTerm(ComparisonOperator.LESS_EQ, left, right); | 80 | return new LessEqTerm<>(Double.class, left, right); |
68 | } | 81 | } |
69 | 82 | ||
70 | public static RealComparisonTerm greater(Term<Double> left, Term<Double> right) { | 83 | public static Term<Boolean> greater(Term<Double> left, Term<Double> right) { |
71 | return new RealComparisonTerm(ComparisonOperator.GREATER, left, right); | 84 | return new GreaterTerm<>(Double.class, left, right); |
72 | } | 85 | } |
73 | 86 | ||
74 | public static RealComparisonTerm greaterEq(Term<Double> left, Term<Double> right) { | 87 | public static Term<Boolean> greaterEq(Term<Double> left, Term<Double> right) { |
75 | return new RealComparisonTerm(ComparisonOperator.GREATER_EQ, left, right); | 88 | return new GreaterEqTerm<>(Double.class, left, right); |
76 | } | 89 | } |
77 | 90 | ||
78 | public static IntToRealTerm asReal(Term<Integer> body) { | 91 | public static Term<Double> asReal(Term<Integer> body) { |
79 | return new IntToRealTerm(body); | 92 | return new IntToRealTerm(body); |
80 | } | 93 | } |
81 | } | 94 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealUnaryTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealUnaryTerm.java new file mode 100644 index 00000000..d41c4ed9 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/real/RealUnaryTerm.java | |||
@@ -0,0 +1,15 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.real; | ||
7 | |||
8 | import tools.refinery.store.query.term.Term; | ||
9 | import tools.refinery.store.query.term.UnaryTerm; | ||
10 | |||
11 | public abstract class RealUnaryTerm extends UnaryTerm<Double, Double> { | ||
12 | protected RealUnaryTerm(Term<Double> body) { | ||
13 | super(Double.class, Double.class, body); | ||
14 | } | ||
15 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityAddTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityAddTerm.java new file mode 100644 index 00000000..68905f51 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityAddTerm.java | |||
@@ -0,0 +1,31 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.uppercardinality; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | import tools.refinery.store.representation.cardinality.UpperCardinality; | ||
11 | |||
12 | public class UpperCardinalityAddTerm extends UpperCardinalityBinaryTerm { | ||
13 | protected UpperCardinalityAddTerm(Term<UpperCardinality> left, Term<UpperCardinality> right) { | ||
14 | super(left, right); | ||
15 | } | ||
16 | |||
17 | @Override | ||
18 | protected UpperCardinality doEvaluate(UpperCardinality leftValue, UpperCardinality rightValue) { | ||
19 | return leftValue.add(rightValue); | ||
20 | } | ||
21 | |||
22 | @Override | ||
23 | public Term<UpperCardinality> doSubstitute(Substitution substitution, Term<UpperCardinality> substitutedLeft, Term<UpperCardinality> substitutedRight) { | ||
24 | return new UpperCardinalityAddTerm(substitutedLeft, substitutedRight); | ||
25 | } | ||
26 | |||
27 | @Override | ||
28 | public String toString() { | ||
29 | return "(%s + %s)".formatted(getLeft(), getRight()); | ||
30 | } | ||
31 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityBinaryTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityBinaryTerm.java new file mode 100644 index 00000000..0cf8fe44 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityBinaryTerm.java | |||
@@ -0,0 +1,17 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.uppercardinality; | ||
7 | |||
8 | import tools.refinery.store.query.term.BinaryTerm; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | import tools.refinery.store.representation.cardinality.UpperCardinality; | ||
11 | |||
12 | public abstract class UpperCardinalityBinaryTerm extends BinaryTerm<UpperCardinality, UpperCardinality, | ||
13 | UpperCardinality> { | ||
14 | protected UpperCardinalityBinaryTerm(Term<UpperCardinality> left, Term<UpperCardinality> right) { | ||
15 | super(UpperCardinality.class, UpperCardinality.class, UpperCardinality.class, left, right); | ||
16 | } | ||
17 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityMaxTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityMaxTerm.java new file mode 100644 index 00000000..ff75f64e --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityMaxTerm.java | |||
@@ -0,0 +1,31 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.uppercardinality; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | import tools.refinery.store.representation.cardinality.UpperCardinality; | ||
11 | |||
12 | public class UpperCardinalityMaxTerm extends UpperCardinalityBinaryTerm { | ||
13 | protected UpperCardinalityMaxTerm(Term<UpperCardinality> left, Term<UpperCardinality> right) { | ||
14 | super(left, right); | ||
15 | } | ||
16 | |||
17 | @Override | ||
18 | protected UpperCardinality doEvaluate(UpperCardinality leftValue, UpperCardinality rightValue) { | ||
19 | return leftValue.max(rightValue); | ||
20 | } | ||
21 | |||
22 | @Override | ||
23 | public Term<UpperCardinality> doSubstitute(Substitution substitution, Term<UpperCardinality> substitutedLeft, Term<UpperCardinality> substitutedRight) { | ||
24 | return new UpperCardinalityMaxTerm(substitutedLeft, substitutedRight); | ||
25 | } | ||
26 | |||
27 | @Override | ||
28 | public String toString() { | ||
29 | return "max(%s, %s)".formatted(getLeft(), getRight()); | ||
30 | } | ||
31 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityMinTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityMinTerm.java new file mode 100644 index 00000000..1e89e9f4 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityMinTerm.java | |||
@@ -0,0 +1,31 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.uppercardinality; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | import tools.refinery.store.representation.cardinality.UpperCardinality; | ||
11 | |||
12 | public class UpperCardinalityMinTerm extends UpperCardinalityBinaryTerm { | ||
13 | protected UpperCardinalityMinTerm(Term<UpperCardinality> left, Term<UpperCardinality> right) { | ||
14 | super(left, right); | ||
15 | } | ||
16 | |||
17 | @Override | ||
18 | protected UpperCardinality doEvaluate(UpperCardinality leftValue, UpperCardinality rightValue) { | ||
19 | return leftValue.min(rightValue); | ||
20 | } | ||
21 | |||
22 | @Override | ||
23 | public Term<UpperCardinality> doSubstitute(Substitution substitution, Term<UpperCardinality> substitutedLeft, Term<UpperCardinality> substitutedRight) { | ||
24 | return new UpperCardinalityMinTerm(substitutedLeft, substitutedRight); | ||
25 | } | ||
26 | |||
27 | @Override | ||
28 | public String toString() { | ||
29 | return "min(%s, %s)".formatted(getLeft(), getRight()); | ||
30 | } | ||
31 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityMulTerm.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityMulTerm.java new file mode 100644 index 00000000..3b4970f4 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityMulTerm.java | |||
@@ -0,0 +1,31 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.uppercardinality; | ||
7 | |||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
9 | import tools.refinery.store.query.term.Term; | ||
10 | import tools.refinery.store.representation.cardinality.UpperCardinality; | ||
11 | |||
12 | public class UpperCardinalityMulTerm extends UpperCardinalityBinaryTerm { | ||
13 | protected UpperCardinalityMulTerm(Term<UpperCardinality> left, Term<UpperCardinality> right) { | ||
14 | super(left, right); | ||
15 | } | ||
16 | |||
17 | @Override | ||
18 | protected UpperCardinality doEvaluate(UpperCardinality leftValue, UpperCardinality rightValue) { | ||
19 | return leftValue.multiply(rightValue); | ||
20 | } | ||
21 | |||
22 | @Override | ||
23 | public Term<UpperCardinality> doSubstitute(Substitution substitution, Term<UpperCardinality> substitutedLeft, Term<UpperCardinality> substitutedRight) { | ||
24 | return new UpperCardinalityMulTerm(substitutedLeft, substitutedRight); | ||
25 | } | ||
26 | |||
27 | @Override | ||
28 | public String toString() { | ||
29 | return "(%s * %s)".formatted(getLeft(), getRight()); | ||
30 | } | ||
31 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalitySumAggregator.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalitySumAggregator.java new file mode 100644 index 00000000..5bbd3081 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalitySumAggregator.java | |||
@@ -0,0 +1,86 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.uppercardinality; | ||
7 | |||
8 | import tools.refinery.store.query.term.StatefulAggregate; | ||
9 | import tools.refinery.store.query.term.StatefulAggregator; | ||
10 | import tools.refinery.store.representation.cardinality.FiniteUpperCardinality; | ||
11 | import tools.refinery.store.representation.cardinality.UnboundedUpperCardinality; | ||
12 | import tools.refinery.store.representation.cardinality.UpperCardinalities; | ||
13 | import tools.refinery.store.representation.cardinality.UpperCardinality; | ||
14 | |||
15 | public class UpperCardinalitySumAggregator implements StatefulAggregator<UpperCardinality, UpperCardinality> { | ||
16 | public static final UpperCardinalitySumAggregator INSTANCE = new UpperCardinalitySumAggregator(); | ||
17 | |||
18 | private UpperCardinalitySumAggregator() { | ||
19 | } | ||
20 | |||
21 | @Override | ||
22 | public Class<UpperCardinality> getResultType() { | ||
23 | return UpperCardinality.class; | ||
24 | } | ||
25 | |||
26 | @Override | ||
27 | public Class<UpperCardinality> getInputType() { | ||
28 | return UpperCardinality.class; | ||
29 | } | ||
30 | |||
31 | @Override | ||
32 | public StatefulAggregate<UpperCardinality, UpperCardinality> createEmptyAggregate() { | ||
33 | return new Aggregate(); | ||
34 | } | ||
35 | |||
36 | private static class Aggregate implements StatefulAggregate<UpperCardinality, UpperCardinality> { | ||
37 | private int sumFiniteUpperBounds; | ||
38 | private int countUnbounded; | ||
39 | |||
40 | public Aggregate() { | ||
41 | this(0, 0); | ||
42 | } | ||
43 | |||
44 | private Aggregate(int sumFiniteUpperBounds, int countUnbounded) { | ||
45 | this.sumFiniteUpperBounds = sumFiniteUpperBounds; | ||
46 | this.countUnbounded = countUnbounded; | ||
47 | } | ||
48 | |||
49 | @Override | ||
50 | public void add(UpperCardinality value) { | ||
51 | if (value instanceof FiniteUpperCardinality finiteUpperCardinality) { | ||
52 | sumFiniteUpperBounds += finiteUpperCardinality.finiteUpperBound(); | ||
53 | } else if (value instanceof UnboundedUpperCardinality) { | ||
54 | countUnbounded += 1; | ||
55 | } else { | ||
56 | throw new IllegalArgumentException("Unknown UpperCardinality: " + value); | ||
57 | } | ||
58 | } | ||
59 | |||
60 | @Override | ||
61 | public void remove(UpperCardinality value) { | ||
62 | if (value instanceof FiniteUpperCardinality finiteUpperCardinality) { | ||
63 | sumFiniteUpperBounds -= finiteUpperCardinality.finiteUpperBound(); | ||
64 | } else if (value instanceof UnboundedUpperCardinality) { | ||
65 | countUnbounded -= 1; | ||
66 | } else { | ||
67 | throw new IllegalArgumentException("Unknown UpperCardinality: " + value); | ||
68 | } | ||
69 | } | ||
70 | |||
71 | @Override | ||
72 | public UpperCardinality getResult() { | ||
73 | return countUnbounded > 0 ? UpperCardinalities.UNBOUNDED : UpperCardinalities.valueOf(sumFiniteUpperBounds); | ||
74 | } | ||
75 | |||
76 | @Override | ||
77 | public boolean isEmpty() { | ||
78 | return sumFiniteUpperBounds == 0 && countUnbounded == 0; | ||
79 | } | ||
80 | |||
81 | @Override | ||
82 | public StatefulAggregate<UpperCardinality, UpperCardinality> deepCopy() { | ||
83 | return new Aggregate(sumFiniteUpperBounds, countUnbounded); | ||
84 | } | ||
85 | } | ||
86 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityTerms.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityTerms.java new file mode 100644 index 00000000..13914f2d --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityTerms.java | |||
@@ -0,0 +1,73 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.uppercardinality; | ||
7 | |||
8 | import tools.refinery.store.query.term.Aggregator; | ||
9 | import tools.refinery.store.query.term.ConstantTerm; | ||
10 | import tools.refinery.store.query.term.ExtremeValueAggregator; | ||
11 | import tools.refinery.store.query.term.Term; | ||
12 | import tools.refinery.store.query.term.comparable.*; | ||
13 | import tools.refinery.store.representation.cardinality.UpperCardinalities; | ||
14 | import tools.refinery.store.representation.cardinality.UpperCardinality; | ||
15 | |||
16 | import java.util.Comparator; | ||
17 | |||
18 | public final class UpperCardinalityTerms { | ||
19 | public static final Aggregator<UpperCardinality, UpperCardinality> UPPER_CARDINALITY_SUM = | ||
20 | UpperCardinalitySumAggregator.INSTANCE; | ||
21 | public static final Aggregator<UpperCardinality, UpperCardinality> UPPER_CARDINALITY_MIN = | ||
22 | new ExtremeValueAggregator<>(UpperCardinality.class, UpperCardinalities.UNBOUNDED); | ||
23 | public static final Aggregator<UpperCardinality, UpperCardinality> UPPER_CARDINALITY_MAX = | ||
24 | new ExtremeValueAggregator<>(UpperCardinality.class, UpperCardinalities.ZERO, Comparator.reverseOrder()); | ||
25 | |||
26 | private UpperCardinalityTerms() { | ||
27 | throw new IllegalStateException("This is a static utility class and should not be instantiated directly"); | ||
28 | } | ||
29 | |||
30 | public static Term<UpperCardinality> constant(UpperCardinality value) { | ||
31 | return new ConstantTerm<>(UpperCardinality.class, value); | ||
32 | } | ||
33 | |||
34 | public static Term<UpperCardinality> add(Term<UpperCardinality> left, Term<UpperCardinality> right) { | ||
35 | return new UpperCardinalityAddTerm(left, right); | ||
36 | } | ||
37 | |||
38 | public static Term<UpperCardinality> mul(Term<UpperCardinality> left, Term<UpperCardinality> right) { | ||
39 | return new UpperCardinalityMulTerm(left, right); | ||
40 | } | ||
41 | |||
42 | public static Term<UpperCardinality> min(Term<UpperCardinality> left, Term<UpperCardinality> right) { | ||
43 | return new UpperCardinalityMinTerm(left, right); | ||
44 | } | ||
45 | |||
46 | public static Term<UpperCardinality> max(Term<UpperCardinality> left, Term<UpperCardinality> right) { | ||
47 | return new UpperCardinalityMaxTerm(left, right); | ||
48 | } | ||
49 | |||
50 | public static Term<Boolean> eq(Term<UpperCardinality> left, Term<UpperCardinality> right) { | ||
51 | return new EqTerm<>(UpperCardinality.class, left, right); | ||
52 | } | ||
53 | |||
54 | public static Term<Boolean> notEq(Term<UpperCardinality> left, Term<UpperCardinality> right) { | ||
55 | return new NotEqTerm<>(UpperCardinality.class, left, right); | ||
56 | } | ||
57 | |||
58 | public static Term<Boolean> less(Term<UpperCardinality> left, Term<UpperCardinality> right) { | ||
59 | return new LessTerm<>(UpperCardinality.class, left, right); | ||
60 | } | ||
61 | |||
62 | public static Term<Boolean> lessEq(Term<UpperCardinality> left, Term<UpperCardinality> right) { | ||
63 | return new LessEqTerm<>(UpperCardinality.class, left, right); | ||
64 | } | ||
65 | |||
66 | public static Term<Boolean> greater(Term<UpperCardinality> left, Term<UpperCardinality> right) { | ||
67 | return new GreaterTerm<>(UpperCardinality.class, left, right); | ||
68 | } | ||
69 | |||
70 | public static Term<Boolean> greaterEq(Term<UpperCardinality> left, Term<UpperCardinality> right) { | ||
71 | return new GreaterEqTerm<>(UpperCardinality.class, left, right); | ||
72 | } | ||
73 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/valuation/MapBasedValuation.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/valuation/MapBasedValuation.java new file mode 100644 index 00000000..261ceaa5 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/valuation/MapBasedValuation.java | |||
@@ -0,0 +1,22 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.valuation; | ||
7 | |||
8 | import tools.refinery.store.query.term.AnyDataVariable; | ||
9 | import tools.refinery.store.query.term.DataVariable; | ||
10 | |||
11 | import java.util.Map; | ||
12 | |||
13 | record MapBasedValuation(Map<AnyDataVariable, Object> values) implements Valuation { | ||
14 | @Override | ||
15 | public <T> T getValue(DataVariable<T> variable) { | ||
16 | if (!values.containsKey(variable)) { | ||
17 | throw new IllegalArgumentException("No value for variable %s".formatted(variable)); | ||
18 | } | ||
19 | var value = values.get(variable); | ||
20 | return variable.getType().cast(value); | ||
21 | } | ||
22 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/valuation/RestrictedValuation.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/valuation/RestrictedValuation.java index fb512d88..fc8406aa 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/valuation/RestrictedValuation.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/valuation/RestrictedValuation.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.valuation; | 6 | package tools.refinery.store.query.valuation; |
2 | 7 | ||
3 | import tools.refinery.store.query.term.AnyDataVariable; | 8 | import tools.refinery.store.query.term.AnyDataVariable; |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/valuation/SubstitutedValuation.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/valuation/SubstitutedValuation.java index 8e79663c..1c14112c 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/valuation/SubstitutedValuation.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/valuation/SubstitutedValuation.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.valuation; | 6 | package tools.refinery.store.query.valuation; |
2 | 7 | ||
3 | import tools.refinery.store.query.substitution.Substitution; | 8 | import tools.refinery.store.query.substitution.Substitution; |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/valuation/Valuation.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/valuation/Valuation.java index 3ba9a6b8..1588e957 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/valuation/Valuation.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/valuation/Valuation.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.valuation; | 6 | package tools.refinery.store.query.valuation; |
2 | 7 | ||
3 | import org.jetbrains.annotations.Nullable; | 8 | import org.jetbrains.annotations.Nullable; |
@@ -5,6 +10,7 @@ import tools.refinery.store.query.substitution.Substitution; | |||
5 | import tools.refinery.store.query.term.AnyDataVariable; | 10 | import tools.refinery.store.query.term.AnyDataVariable; |
6 | import tools.refinery.store.query.term.DataVariable; | 11 | import tools.refinery.store.query.term.DataVariable; |
7 | 12 | ||
13 | import java.util.Map; | ||
8 | import java.util.Set; | 14 | import java.util.Set; |
9 | 15 | ||
10 | public interface Valuation { | 16 | public interface Valuation { |
@@ -20,4 +26,12 @@ public interface Valuation { | |||
20 | default Valuation restrict(Set<? extends AnyDataVariable> allowedVariables) { | 26 | default Valuation restrict(Set<? extends AnyDataVariable> allowedVariables) { |
21 | return new RestrictedValuation(this, Set.copyOf(allowedVariables)); | 27 | return new RestrictedValuation(this, Set.copyOf(allowedVariables)); |
22 | } | 28 | } |
29 | |||
30 | static ValuationBuilder builder() { | ||
31 | return new ValuationBuilder(); | ||
32 | } | ||
33 | |||
34 | static Valuation empty() { | ||
35 | return new MapBasedValuation(Map.of()); | ||
36 | } | ||
23 | } | 37 | } |
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/valuation/ValuationBuilder.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/valuation/ValuationBuilder.java new file mode 100644 index 00000000..7337dbc3 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/valuation/ValuationBuilder.java | |||
@@ -0,0 +1,40 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.valuation; | ||
7 | |||
8 | import tools.refinery.store.query.term.AnyDataVariable; | ||
9 | import tools.refinery.store.query.term.DataVariable; | ||
10 | |||
11 | import java.util.Collections; | ||
12 | import java.util.HashMap; | ||
13 | import java.util.Map; | ||
14 | |||
15 | public class ValuationBuilder { | ||
16 | private final Map<AnyDataVariable, Object> values = new HashMap<>(); | ||
17 | |||
18 | ValuationBuilder() { | ||
19 | } | ||
20 | |||
21 | public <T> ValuationBuilder put(DataVariable<T> variable, T value) { | ||
22 | return putChecked(variable, value); | ||
23 | } | ||
24 | |||
25 | public ValuationBuilder putChecked(AnyDataVariable variable, Object value) { | ||
26 | if (value != null && !variable.getType().isInstance(value)) { | ||
27 | throw new IllegalArgumentException("Value %s is not an instance of %s" | ||
28 | .formatted(value, variable.getType().getName())); | ||
29 | } | ||
30 | if (values.containsKey(variable)) { | ||
31 | throw new IllegalArgumentException("Already has value for variable %s".formatted(variable)); | ||
32 | } | ||
33 | values.put(variable, value); | ||
34 | return this; | ||
35 | } | ||
36 | |||
37 | public Valuation build() { | ||
38 | return new MapBasedValuation(Collections.unmodifiableMap(values)); | ||
39 | } | ||
40 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/AbstractFunctionView.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/AbstractFunctionView.java new file mode 100644 index 00000000..c1f9d688 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/AbstractFunctionView.java | |||
@@ -0,0 +1,112 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.view; | ||
7 | |||
8 | import tools.refinery.store.model.Model; | ||
9 | import tools.refinery.store.query.dnf.FunctionalDependency; | ||
10 | import tools.refinery.store.query.term.Parameter; | ||
11 | import tools.refinery.store.representation.Symbol; | ||
12 | import tools.refinery.store.tuple.Tuple; | ||
13 | import tools.refinery.store.tuple.Tuple1; | ||
14 | |||
15 | import java.util.Arrays; | ||
16 | import java.util.List; | ||
17 | import java.util.Objects; | ||
18 | import java.util.Set; | ||
19 | import java.util.stream.Collectors; | ||
20 | import java.util.stream.IntStream; | ||
21 | |||
22 | public abstract class AbstractFunctionView<T> extends SymbolView<T> { | ||
23 | private final T defaultValue; | ||
24 | private final List<Parameter> parameters; | ||
25 | |||
26 | protected AbstractFunctionView(Symbol<T> symbol, String name, Parameter outParameter) { | ||
27 | super(symbol, name); | ||
28 | defaultValue = symbol.defaultValue(); | ||
29 | parameters = createParameters(symbol.arity(), outParameter); | ||
30 | } | ||
31 | |||
32 | @Override | ||
33 | public Set<FunctionalDependency<Integer>> getFunctionalDependencies() { | ||
34 | var arity = getSymbol().arity(); | ||
35 | var forEach = IntStream.range(0, arity).boxed().collect(Collectors.toUnmodifiableSet()); | ||
36 | var unique = Set.of(arity); | ||
37 | return Set.of(new FunctionalDependency<>(forEach, unique)); | ||
38 | } | ||
39 | |||
40 | @Override | ||
41 | public Set<ViewImplication> getImpliedRelationViews() { | ||
42 | var symbol = getSymbol(); | ||
43 | var impliedIndices = IntStream.range(0, symbol.arity()).boxed().toList(); | ||
44 | var keysView = new KeyOnlyView<>(symbol); | ||
45 | return Set.of(new ViewImplication(this, keysView, impliedIndices)); | ||
46 | } | ||
47 | |||
48 | @Override | ||
49 | public final boolean filter(Tuple key, T value) { | ||
50 | return !Objects.equals(defaultValue, value); | ||
51 | } | ||
52 | |||
53 | protected Object forwardMapValue(Tuple key, T value) { | ||
54 | return value; | ||
55 | } | ||
56 | |||
57 | protected boolean valueEquals(Tuple key, T value, Object otherForwardMappedValue) { | ||
58 | return Objects.equals(otherForwardMappedValue, forwardMapValue(key, value)); | ||
59 | } | ||
60 | |||
61 | @Override | ||
62 | public Object[] forwardMap(Tuple key, T value) { | ||
63 | int size = key.getSize(); | ||
64 | Object[] result = new Object[size + 1]; | ||
65 | for (int i = 0; i < size; i++) { | ||
66 | result[i] = Tuple.of(key.get(i)); | ||
67 | } | ||
68 | result[key.getSize()] = forwardMapValue(key, value); | ||
69 | return result; | ||
70 | } | ||
71 | |||
72 | @Override | ||
73 | public boolean get(Model model, Object[] tuple) { | ||
74 | int[] content = new int[tuple.length - 1]; | ||
75 | for (int i = 0; i < tuple.length - 1; i++) { | ||
76 | if (!(tuple[i] instanceof Tuple1 wrapper)) { | ||
77 | return false; | ||
78 | } | ||
79 | content[i] = wrapper.value0(); | ||
80 | } | ||
81 | Tuple key = Tuple.of(content); | ||
82 | var valueInTuple = tuple[tuple.length - 1]; | ||
83 | T valueInMap = model.getInterpretation(getSymbol()).get(key); | ||
84 | return valueEquals(key, valueInMap, valueInTuple); | ||
85 | } | ||
86 | |||
87 | @Override | ||
88 | public List<Parameter> getParameters() { | ||
89 | return parameters; | ||
90 | } | ||
91 | |||
92 | @Override | ||
93 | public boolean equals(Object o) { | ||
94 | if (this == o) return true; | ||
95 | if (o == null || getClass() != o.getClass()) return false; | ||
96 | if (!super.equals(o)) return false; | ||
97 | AbstractFunctionView<?> that = (AbstractFunctionView<?>) o; | ||
98 | return Objects.equals(defaultValue, that.defaultValue) && Objects.equals(parameters, that.parameters); | ||
99 | } | ||
100 | |||
101 | @Override | ||
102 | public int hashCode() { | ||
103 | return Objects.hash(super.hashCode(), defaultValue, parameters); | ||
104 | } | ||
105 | |||
106 | private static List<Parameter> createParameters(int symbolArity, Parameter outParameter) { | ||
107 | var parameters = new Parameter[symbolArity + 1]; | ||
108 | Arrays.fill(parameters, Parameter.NODE_OUT); | ||
109 | parameters[symbolArity] = outParameter; | ||
110 | return List.of(parameters); | ||
111 | } | ||
112 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/AnyRelationView.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/AnySymbolView.java index 6ae410f2..90b27ebb 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/AnyRelationView.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/AnySymbolView.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.view; | 6 | package tools.refinery.store.query.view; |
2 | 7 | ||
3 | import tools.refinery.store.model.Model; | 8 | import tools.refinery.store.model.Model; |
@@ -7,7 +12,7 @@ import tools.refinery.store.query.Constraint; | |||
7 | 12 | ||
8 | import java.util.Set; | 13 | import java.util.Set; |
9 | 14 | ||
10 | public sealed interface AnyRelationView extends Constraint permits RelationView { | 15 | public sealed interface AnySymbolView extends Constraint permits SymbolView { |
11 | AnySymbol getSymbol(); | 16 | AnySymbol getSymbol(); |
12 | 17 | ||
13 | String getViewName(); | 18 | String getViewName(); |
@@ -16,7 +21,7 @@ public sealed interface AnyRelationView extends Constraint permits RelationView | |||
16 | return Set.of(); | 21 | return Set.of(); |
17 | } | 22 | } |
18 | 23 | ||
19 | default Set<RelationViewImplication> getImpliedRelationViews() { | 24 | default Set<ViewImplication> getImpliedRelationViews() { |
20 | return Set.of(); | 25 | return Set.of(); |
21 | } | 26 | } |
22 | 27 | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/FilteredRelationView.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/FilteredView.java index 64c601bb..922c7355 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/FilteredRelationView.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/FilteredView.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.view; | 6 | package tools.refinery.store.query.view; |
2 | 7 | ||
3 | import tools.refinery.store.tuple.Tuple; | 8 | import tools.refinery.store.tuple.Tuple; |
@@ -7,24 +12,24 @@ import java.util.Objects; | |||
7 | import java.util.function.BiPredicate; | 12 | import java.util.function.BiPredicate; |
8 | import java.util.function.Predicate; | 13 | import java.util.function.Predicate; |
9 | 14 | ||
10 | public class FilteredRelationView<T> extends TuplePreservingRelationView<T> { | 15 | public class FilteredView<T> extends TuplePreservingView<T> { |
11 | private final BiPredicate<Tuple, T> predicate; | 16 | private final BiPredicate<Tuple, T> predicate; |
12 | 17 | ||
13 | public FilteredRelationView(Symbol<T> symbol, String name, BiPredicate<Tuple, T> predicate) { | 18 | public FilteredView(Symbol<T> symbol, String name, BiPredicate<Tuple, T> predicate) { |
14 | super(symbol, name); | 19 | super(symbol, name); |
15 | this.predicate = predicate; | 20 | this.predicate = predicate; |
16 | } | 21 | } |
17 | 22 | ||
18 | public FilteredRelationView(Symbol<T> symbol, BiPredicate<Tuple, T> predicate) { | 23 | public FilteredView(Symbol<T> symbol, BiPredicate<Tuple, T> predicate) { |
19 | super(symbol); | 24 | super(symbol); |
20 | this.predicate = predicate; | 25 | this.predicate = predicate; |
21 | } | 26 | } |
22 | 27 | ||
23 | public FilteredRelationView(Symbol<T> symbol, String name, Predicate<T> predicate) { | 28 | public FilteredView(Symbol<T> symbol, String name, Predicate<T> predicate) { |
24 | this(symbol, name, (k, v) -> predicate.test(v)); | 29 | this(symbol, name, (k, v) -> predicate.test(v)); |
25 | } | 30 | } |
26 | 31 | ||
27 | public FilteredRelationView(Symbol<T> symbol, Predicate<T> predicate) { | 32 | public FilteredView(Symbol<T> symbol, Predicate<T> predicate) { |
28 | this(symbol, (k, v) -> predicate.test(v)); | 33 | this(symbol, (k, v) -> predicate.test(v)); |
29 | } | 34 | } |
30 | 35 | ||
@@ -38,7 +43,7 @@ public class FilteredRelationView<T> extends TuplePreservingRelationView<T> { | |||
38 | if (this == o) return true; | 43 | if (this == o) return true; |
39 | if (o == null || getClass() != o.getClass()) return false; | 44 | if (o == null || getClass() != o.getClass()) return false; |
40 | if (!super.equals(o)) return false; | 45 | if (!super.equals(o)) return false; |
41 | FilteredRelationView<?> that = (FilteredRelationView<?>) o; | 46 | FilteredView<?> that = (FilteredView<?>) o; |
42 | return Objects.equals(predicate, that.predicate); | 47 | return Objects.equals(predicate, that.predicate); |
43 | } | 48 | } |
44 | 49 | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/ForbiddenRelationView.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/ForbiddenView.java index 050b9496..26b717ee 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/ForbiddenRelationView.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/ForbiddenView.java | |||
@@ -1,11 +1,16 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.view; | 6 | package tools.refinery.store.query.view; |
2 | 7 | ||
3 | import tools.refinery.store.representation.Symbol; | 8 | import tools.refinery.store.representation.Symbol; |
4 | import tools.refinery.store.representation.TruthValue; | 9 | import tools.refinery.store.representation.TruthValue; |
5 | import tools.refinery.store.tuple.Tuple; | 10 | import tools.refinery.store.tuple.Tuple; |
6 | 11 | ||
7 | public class ForbiddenRelationView extends TuplePreservingRelationView<TruthValue> { | 12 | public class ForbiddenView extends TuplePreservingView<TruthValue> { |
8 | public ForbiddenRelationView(Symbol<TruthValue> symbol) { | 13 | public ForbiddenView(Symbol<TruthValue> symbol) { |
9 | super(symbol, "forbidden"); | 14 | super(symbol, "forbidden"); |
10 | } | 15 | } |
11 | 16 | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/FunctionView.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/FunctionView.java new file mode 100644 index 00000000..74a5be07 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/FunctionView.java | |||
@@ -0,0 +1,36 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.view; | ||
7 | |||
8 | import tools.refinery.store.query.term.*; | ||
9 | import tools.refinery.store.representation.Symbol; | ||
10 | |||
11 | import java.util.ArrayList; | ||
12 | import java.util.List; | ||
13 | |||
14 | public final class FunctionView<T> extends AbstractFunctionView<T> { | ||
15 | public FunctionView(Symbol<T> symbol, String name) { | ||
16 | super(symbol, name, new Parameter(symbol.valueType(), ParameterDirection.OUT)); | ||
17 | } | ||
18 | |||
19 | public FunctionView(Symbol<T> symbol) { | ||
20 | this(symbol, "function"); | ||
21 | } | ||
22 | |||
23 | public <R> AssignedValue<R> aggregate(Aggregator<R, T> aggregator, List<NodeVariable> arguments) { | ||
24 | return targetVariable -> { | ||
25 | var placeholderVariable = Variable.of(getSymbol().valueType()); | ||
26 | var argumentsWithPlaceholder = new ArrayList<Variable>(arguments.size() + 1); | ||
27 | argumentsWithPlaceholder.addAll(arguments); | ||
28 | argumentsWithPlaceholder.add(placeholderVariable); | ||
29 | return aggregateBy(placeholderVariable, aggregator, argumentsWithPlaceholder).toLiteral(targetVariable); | ||
30 | }; | ||
31 | } | ||
32 | |||
33 | public <R> AssignedValue<R> aggregate(Aggregator<R, T> aggregator, NodeVariable... arguments) { | ||
34 | return aggregate(aggregator, List.of(arguments)); | ||
35 | } | ||
36 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/FunctionalRelationView.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/FunctionalRelationView.java deleted file mode 100644 index 7ec9e7ac..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/FunctionalRelationView.java +++ /dev/null | |||
@@ -1,105 +0,0 @@ | |||
1 | package tools.refinery.store.query.view; | ||
2 | |||
3 | import tools.refinery.store.model.Model; | ||
4 | import tools.refinery.store.query.dnf.FunctionalDependency; | ||
5 | import tools.refinery.store.query.term.DataSort; | ||
6 | import tools.refinery.store.query.term.NodeSort; | ||
7 | import tools.refinery.store.query.term.Sort; | ||
8 | import tools.refinery.store.representation.Symbol; | ||
9 | import tools.refinery.store.tuple.Tuple; | ||
10 | import tools.refinery.store.tuple.Tuple1; | ||
11 | |||
12 | import java.util.List; | ||
13 | import java.util.Objects; | ||
14 | import java.util.Set; | ||
15 | import java.util.stream.Collectors; | ||
16 | import java.util.stream.IntStream; | ||
17 | |||
18 | public final class FunctionalRelationView<T> extends RelationView<T> { | ||
19 | private final T defaultValue; | ||
20 | |||
21 | public FunctionalRelationView(Symbol<T> symbol, String name) { | ||
22 | super(symbol, name); | ||
23 | defaultValue = symbol.defaultValue(); | ||
24 | } | ||
25 | |||
26 | public FunctionalRelationView(Symbol<T> symbol) { | ||
27 | super(symbol); | ||
28 | defaultValue = symbol.defaultValue(); | ||
29 | } | ||
30 | |||
31 | @Override | ||
32 | public Set<FunctionalDependency<Integer>> getFunctionalDependencies() { | ||
33 | var arity = getSymbol().arity(); | ||
34 | var forEach = IntStream.range(0, arity).boxed().collect(Collectors.toUnmodifiableSet()); | ||
35 | var unique = Set.of(arity); | ||
36 | return Set.of(new FunctionalDependency<>(forEach, unique)); | ||
37 | } | ||
38 | |||
39 | @Override | ||
40 | public Set<RelationViewImplication> getImpliedRelationViews() { | ||
41 | var symbol = getSymbol(); | ||
42 | var impliedIndices = IntStream.range(0, symbol.arity()).boxed().toList(); | ||
43 | var keyOnlyRelationView = new KeyOnlyRelationView<>(symbol); | ||
44 | return Set.of(new RelationViewImplication(this, keyOnlyRelationView, impliedIndices)); | ||
45 | } | ||
46 | |||
47 | @Override | ||
48 | public boolean filter(Tuple key, T value) { | ||
49 | return !Objects.equals(defaultValue, value); | ||
50 | } | ||
51 | |||
52 | @Override | ||
53 | public Object[] forwardMap(Tuple key, T value) { | ||
54 | int size = key.getSize(); | ||
55 | Object[] result = new Object[size + 1]; | ||
56 | for (int i = 0; i < size; i++) { | ||
57 | result[i] = Tuple.of(key.get(i)); | ||
58 | } | ||
59 | result[key.getSize()] = value; | ||
60 | return result; | ||
61 | } | ||
62 | |||
63 | @Override | ||
64 | public boolean get(Model model, Object[] tuple) { | ||
65 | int[] content = new int[tuple.length - 1]; | ||
66 | for (int i = 0; i < tuple.length - 1; i++) { | ||
67 | content[i] = ((Tuple1) tuple[i]).value0(); | ||
68 | } | ||
69 | Tuple key = Tuple.of(content); | ||
70 | @SuppressWarnings("unchecked") | ||
71 | T valueInTuple = (T) tuple[tuple.length - 1]; | ||
72 | T valueInMap = model.getInterpretation(getSymbol()).get(key); | ||
73 | return valueInTuple.equals(valueInMap); | ||
74 | } | ||
75 | |||
76 | @Override | ||
77 | public int arity() { | ||
78 | return getSymbol().arity() + 1; | ||
79 | } | ||
80 | |||
81 | @Override | ||
82 | public List<Sort> getSorts() { | ||
83 | var sorts = new Sort[arity()]; | ||
84 | int valueIndex = sorts.length - 1; | ||
85 | for (int i = 0; i < valueIndex; i++) { | ||
86 | sorts[i] = NodeSort.INSTANCE; | ||
87 | } | ||
88 | sorts[valueIndex] = new DataSort<>(getSymbol().valueType()); | ||
89 | return List.of(sorts); | ||
90 | } | ||
91 | |||
92 | @Override | ||
93 | public boolean equals(Object o) { | ||
94 | if (this == o) return true; | ||
95 | if (o == null || getClass() != o.getClass()) return false; | ||
96 | if (!super.equals(o)) return false; | ||
97 | FunctionalRelationView<?> that = (FunctionalRelationView<?>) o; | ||
98 | return Objects.equals(defaultValue, that.defaultValue); | ||
99 | } | ||
100 | |||
101 | @Override | ||
102 | public int hashCode() { | ||
103 | return Objects.hash(super.hashCode(), defaultValue); | ||
104 | } | ||
105 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/KeyOnlyRelationView.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/KeyOnlyView.java index e1b2e45b..7e86f6e4 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/KeyOnlyRelationView.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/KeyOnlyView.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.view; | 6 | package tools.refinery.store.query.view; |
2 | 7 | ||
3 | import tools.refinery.store.representation.Symbol; | 8 | import tools.refinery.store.representation.Symbol; |
@@ -5,12 +10,12 @@ import tools.refinery.store.tuple.Tuple; | |||
5 | 10 | ||
6 | import java.util.Objects; | 11 | import java.util.Objects; |
7 | 12 | ||
8 | public final class KeyOnlyRelationView<T> extends TuplePreservingRelationView<T> { | 13 | public final class KeyOnlyView<T> extends TuplePreservingView<T> { |
9 | public static final String VIEW_NAME = "key"; | 14 | public static final String VIEW_NAME = "key"; |
10 | 15 | ||
11 | private final T defaultValue; | 16 | private final T defaultValue; |
12 | 17 | ||
13 | public KeyOnlyRelationView(Symbol<T> symbol) { | 18 | public KeyOnlyView(Symbol<T> symbol) { |
14 | super(symbol, VIEW_NAME); | 19 | super(symbol, VIEW_NAME); |
15 | defaultValue = symbol.defaultValue(); | 20 | defaultValue = symbol.defaultValue(); |
16 | } | 21 | } |
@@ -25,7 +30,7 @@ public final class KeyOnlyRelationView<T> extends TuplePreservingRelationView<T> | |||
25 | if (this == o) return true; | 30 | if (this == o) return true; |
26 | if (o == null || getClass() != o.getClass()) return false; | 31 | if (o == null || getClass() != o.getClass()) return false; |
27 | if (!super.equals(o)) return false; | 32 | if (!super.equals(o)) return false; |
28 | KeyOnlyRelationView<?> that = (KeyOnlyRelationView<?>) o; | 33 | KeyOnlyView<?> that = (KeyOnlyView<?>) o; |
29 | return Objects.equals(defaultValue, that.defaultValue); | 34 | return Objects.equals(defaultValue, that.defaultValue); |
30 | } | 35 | } |
31 | 36 | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/MayRelationView.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/MayView.java index a2a84b3c..e75a8171 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/MayRelationView.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/MayView.java | |||
@@ -1,11 +1,16 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.view; | 6 | package tools.refinery.store.query.view; |
2 | 7 | ||
3 | import tools.refinery.store.representation.Symbol; | 8 | import tools.refinery.store.representation.Symbol; |
4 | import tools.refinery.store.representation.TruthValue; | 9 | import tools.refinery.store.representation.TruthValue; |
5 | import tools.refinery.store.tuple.Tuple; | 10 | import tools.refinery.store.tuple.Tuple; |
6 | 11 | ||
7 | public class MayRelationView extends TuplePreservingRelationView<TruthValue> { | 12 | public class MayView extends TuplePreservingView<TruthValue> { |
8 | public MayRelationView(Symbol<TruthValue> symbol) { | 13 | public MayView(Symbol<TruthValue> symbol) { |
9 | super(symbol, "may"); | 14 | super(symbol, "may"); |
10 | } | 15 | } |
11 | 16 | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/MustRelationView.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/MustView.java index 72ac0ca3..a48f8045 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/MustRelationView.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/MustView.java | |||
@@ -1,11 +1,16 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.view; | 6 | package tools.refinery.store.query.view; |
2 | 7 | ||
3 | import tools.refinery.store.representation.Symbol; | 8 | import tools.refinery.store.representation.Symbol; |
4 | import tools.refinery.store.representation.TruthValue; | 9 | import tools.refinery.store.representation.TruthValue; |
5 | import tools.refinery.store.tuple.Tuple; | 10 | import tools.refinery.store.tuple.Tuple; |
6 | 11 | ||
7 | public class MustRelationView extends TuplePreservingRelationView<TruthValue> { | 12 | public class MustView extends TuplePreservingView<TruthValue> { |
8 | public MustRelationView(Symbol<TruthValue> symbol) { | 13 | public MustView(Symbol<TruthValue> symbol) { |
9 | super(symbol, "must"); | 14 | super(symbol, "must"); |
10 | } | 15 | } |
11 | 16 | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/NodeFunctionView.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/NodeFunctionView.java new file mode 100644 index 00000000..fcf11506 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/NodeFunctionView.java | |||
@@ -0,0 +1,20 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.view; | ||
7 | |||
8 | import tools.refinery.store.query.term.Parameter; | ||
9 | import tools.refinery.store.representation.Symbol; | ||
10 | import tools.refinery.store.tuple.Tuple1; | ||
11 | |||
12 | public final class NodeFunctionView extends AbstractFunctionView<Tuple1> { | ||
13 | public NodeFunctionView(Symbol<Tuple1> symbol, String name) { | ||
14 | super(symbol, name, Parameter.NODE_OUT); | ||
15 | } | ||
16 | |||
17 | public NodeFunctionView(Symbol<Tuple1> symbol) { | ||
18 | this(symbol, "function"); | ||
19 | } | ||
20 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/RelationViewImplication.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/RelationViewImplication.java deleted file mode 100644 index 2ba1fcc4..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/RelationViewImplication.java +++ /dev/null | |||
@@ -1,19 +0,0 @@ | |||
1 | package tools.refinery.store.query.view; | ||
2 | |||
3 | import java.util.List; | ||
4 | |||
5 | public record RelationViewImplication(AnyRelationView implyingRelationView, AnyRelationView impliedRelationView, | ||
6 | List<Integer> impliedIndices) { | ||
7 | public RelationViewImplication { | ||
8 | if (impliedIndices.size() != impliedRelationView.arity()) { | ||
9 | throw new IllegalArgumentException("Expected %d implied indices for %s, but %d are provided" | ||
10 | .formatted(impliedRelationView.arity(), impliedRelationView, impliedIndices.size())); | ||
11 | } | ||
12 | for (var index : impliedIndices) { | ||
13 | if (impliedRelationView.invalidIndex(index)) { | ||
14 | throw new IllegalArgumentException("%d is not a valid index for %s".formatted(index, | ||
15 | implyingRelationView)); | ||
16 | } | ||
17 | } | ||
18 | } | ||
19 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/RelationView.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/SymbolView.java index d7164b3b..267a99d3 100644 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/RelationView.java +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/SymbolView.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.view; | 6 | package tools.refinery.store.query.view; |
2 | 7 | ||
3 | import tools.refinery.store.map.CursorAsIterator; | 8 | import tools.refinery.store.map.CursorAsIterator; |
@@ -14,17 +19,17 @@ import java.util.UUID; | |||
14 | * @param <T> | 19 | * @param <T> |
15 | * @author Oszkar Semerath | 20 | * @author Oszkar Semerath |
16 | */ | 21 | */ |
17 | public abstract non-sealed class RelationView<T> implements AnyRelationView { | 22 | public abstract non-sealed class SymbolView<T> implements AnySymbolView { |
18 | private final Symbol<T> symbol; | 23 | private final Symbol<T> symbol; |
19 | 24 | ||
20 | private final String viewName; | 25 | private final String viewName; |
21 | 26 | ||
22 | protected RelationView(Symbol<T> symbol, String viewName) { | 27 | protected SymbolView(Symbol<T> symbol, String viewName) { |
23 | this.symbol = symbol; | 28 | this.symbol = symbol; |
24 | this.viewName = viewName; | 29 | this.viewName = viewName; |
25 | } | 30 | } |
26 | 31 | ||
27 | protected RelationView(Symbol<T> representation) { | 32 | protected SymbolView(Symbol<T> representation) { |
28 | this(representation, UUID.randomUUID().toString()); | 33 | this(representation, UUID.randomUUID().toString()); |
29 | } | 34 | } |
30 | 35 | ||
@@ -66,7 +71,7 @@ public abstract non-sealed class RelationView<T> implements AnyRelationView { | |||
66 | public boolean equals(Object o) { | 71 | public boolean equals(Object o) { |
67 | if (this == o) return true; | 72 | if (this == o) return true; |
68 | if (o == null || getClass() != o.getClass()) return false; | 73 | if (o == null || getClass() != o.getClass()) return false; |
69 | RelationView<?> that = (RelationView<?>) o; | 74 | SymbolView<?> that = (SymbolView<?>) o; |
70 | return Objects.equals(symbol, that.symbol) && Objects.equals(viewName, that.viewName); | 75 | return Objects.equals(symbol, that.symbol) && Objects.equals(viewName, that.viewName); |
71 | } | 76 | } |
72 | 77 | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/TuplePreservingRelationView.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/TuplePreservingRelationView.java deleted file mode 100644 index 234b3a9a..00000000 --- a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/TuplePreservingRelationView.java +++ /dev/null | |||
@@ -1,57 +0,0 @@ | |||
1 | package tools.refinery.store.query.view; | ||
2 | |||
3 | import tools.refinery.store.model.Model; | ||
4 | import tools.refinery.store.query.term.NodeSort; | ||
5 | import tools.refinery.store.query.term.Sort; | ||
6 | import tools.refinery.store.tuple.Tuple; | ||
7 | import tools.refinery.store.tuple.Tuple1; | ||
8 | import tools.refinery.store.representation.Symbol; | ||
9 | |||
10 | import java.util.Arrays; | ||
11 | import java.util.List; | ||
12 | |||
13 | public abstract class TuplePreservingRelationView<T> extends RelationView<T> { | ||
14 | protected TuplePreservingRelationView(Symbol<T> symbol, String name) { | ||
15 | super(symbol, name); | ||
16 | } | ||
17 | |||
18 | protected TuplePreservingRelationView(Symbol<T> symbol) { | ||
19 | super(symbol); | ||
20 | } | ||
21 | |||
22 | public Object[] forwardMap(Tuple key) { | ||
23 | Object[] result = new Object[key.getSize()]; | ||
24 | for (int i = 0; i < key.getSize(); i++) { | ||
25 | result[i] = Tuple.of(key.get(i)); | ||
26 | } | ||
27 | return result; | ||
28 | } | ||
29 | |||
30 | @Override | ||
31 | public Object[] forwardMap(Tuple key, T value) { | ||
32 | return forwardMap(key); | ||
33 | } | ||
34 | |||
35 | @Override | ||
36 | public boolean get(Model model, Object[] tuple) { | ||
37 | int[] content = new int[tuple.length]; | ||
38 | for (int i = 0; i < tuple.length; i++) { | ||
39 | content[i] = ((Tuple1) tuple[i]).value0(); | ||
40 | } | ||
41 | Tuple key = Tuple.of(content); | ||
42 | T value = model.getInterpretation(getSymbol()).get(key); | ||
43 | return filter(key, value); | ||
44 | } | ||
45 | |||
46 | @Override | ||
47 | public int arity() { | ||
48 | return this.getSymbol().arity(); | ||
49 | } | ||
50 | |||
51 | @Override | ||
52 | public List<Sort> getSorts() { | ||
53 | var sorts = new Sort[arity()]; | ||
54 | Arrays.fill(sorts, NodeSort.INSTANCE); | ||
55 | return List.of(sorts); | ||
56 | } | ||
57 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/TuplePreservingView.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/TuplePreservingView.java new file mode 100644 index 00000000..6bc5a708 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/TuplePreservingView.java | |||
@@ -0,0 +1,82 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.view; | ||
7 | |||
8 | import tools.refinery.store.model.Model; | ||
9 | import tools.refinery.store.query.term.Parameter; | ||
10 | import tools.refinery.store.representation.Symbol; | ||
11 | import tools.refinery.store.tuple.Tuple; | ||
12 | import tools.refinery.store.tuple.Tuple1; | ||
13 | |||
14 | import java.util.Arrays; | ||
15 | import java.util.List; | ||
16 | import java.util.Objects; | ||
17 | |||
18 | public abstract class TuplePreservingView<T> extends SymbolView<T> { | ||
19 | private final List<Parameter> parameters; | ||
20 | |||
21 | protected TuplePreservingView(Symbol<T> symbol, String name) { | ||
22 | super(symbol, name); | ||
23 | this.parameters = createParameters(symbol.arity()); | ||
24 | } | ||
25 | |||
26 | protected TuplePreservingView(Symbol<T> symbol) { | ||
27 | super(symbol); | ||
28 | this.parameters = createParameters(symbol.arity()); | ||
29 | } | ||
30 | |||
31 | public Object[] forwardMap(Tuple key) { | ||
32 | Object[] result = new Object[key.getSize()]; | ||
33 | for (int i = 0; i < key.getSize(); i++) { | ||
34 | result[i] = Tuple.of(key.get(i)); | ||
35 | } | ||
36 | return result; | ||
37 | } | ||
38 | |||
39 | @Override | ||
40 | public Object[] forwardMap(Tuple key, T value) { | ||
41 | return forwardMap(key); | ||
42 | } | ||
43 | |||
44 | @Override | ||
45 | public boolean get(Model model, Object[] tuple) { | ||
46 | int[] content = new int[tuple.length]; | ||
47 | for (int i = 0; i < tuple.length; i++) { | ||
48 | if (!(tuple[i] instanceof Tuple1 wrapper)) { | ||
49 | return false; | ||
50 | } | ||
51 | content[i] = wrapper.value0(); | ||
52 | } | ||
53 | Tuple key = Tuple.of(content); | ||
54 | T value = model.getInterpretation(getSymbol()).get(key); | ||
55 | return filter(key, value); | ||
56 | } | ||
57 | |||
58 | @Override | ||
59 | public List<Parameter> getParameters() { | ||
60 | return parameters; | ||
61 | } | ||
62 | |||
63 | @Override | ||
64 | public boolean equals(Object o) { | ||
65 | if (this == o) return true; | ||
66 | if (o == null || getClass() != o.getClass()) return false; | ||
67 | if (!super.equals(o)) return false; | ||
68 | TuplePreservingView<?> that = (TuplePreservingView<?>) o; | ||
69 | return Objects.equals(parameters, that.parameters); | ||
70 | } | ||
71 | |||
72 | @Override | ||
73 | public int hashCode() { | ||
74 | return Objects.hash(super.hashCode(), parameters); | ||
75 | } | ||
76 | |||
77 | private static List<Parameter> createParameters(int arity) { | ||
78 | var parameters = new Parameter[arity]; | ||
79 | Arrays.fill(parameters, Parameter.NODE_OUT); | ||
80 | return List.of(parameters); | ||
81 | } | ||
82 | } | ||
diff --git a/subprojects/store-query/src/main/java/tools/refinery/store/query/view/ViewImplication.java b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/ViewImplication.java new file mode 100644 index 00000000..fc2db9f2 --- /dev/null +++ b/subprojects/store-query/src/main/java/tools/refinery/store/query/view/ViewImplication.java | |||
@@ -0,0 +1,23 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.view; | ||
7 | |||
8 | import java.util.List; | ||
9 | |||
10 | public record ViewImplication(AnySymbolView implyingView, AnySymbolView impliedView, List<Integer> impliedIndices) { | ||
11 | public ViewImplication { | ||
12 | if (impliedIndices.size() != impliedView.arity()) { | ||
13 | throw new IllegalArgumentException("Expected %d implied indices for %s, but %d are provided" | ||
14 | .formatted(impliedView.arity(), impliedView, impliedIndices.size())); | ||
15 | } | ||
16 | for (var index : impliedIndices) { | ||
17 | if (impliedView.invalidIndex(index)) { | ||
18 | throw new IllegalArgumentException("%d is not a valid index for %s".formatted(index, | ||
19 | implyingView)); | ||
20 | } | ||
21 | } | ||
22 | } | ||
23 | } | ||
diff --git a/subprojects/store-query/src/test/java/tools/refinery/store/query/DnfBuilderTest.java b/subprojects/store-query/src/test/java/tools/refinery/store/query/dnf/DnfBuilderLiteralEliminationTest.java index ceb46d6f..e17496e3 100644 --- a/subprojects/store-query/src/test/java/tools/refinery/store/query/DnfBuilderTest.java +++ b/subprojects/store-query/src/test/java/tools/refinery/store/query/dnf/DnfBuilderLiteralEliminationTest.java | |||
@@ -1,24 +1,39 @@ | |||
1 | package tools.refinery.store.query; | 1 | /* |
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf; | ||
2 | 7 | ||
3 | import org.junit.jupiter.api.Test; | 8 | import org.junit.jupiter.api.Test; |
4 | import tools.refinery.store.query.dnf.Dnf; | 9 | import org.junit.jupiter.params.ParameterizedTest; |
10 | import org.junit.jupiter.params.provider.CsvSource; | ||
5 | import tools.refinery.store.query.literal.BooleanLiteral; | 11 | import tools.refinery.store.query.literal.BooleanLiteral; |
12 | import tools.refinery.store.query.term.NodeVariable; | ||
13 | import tools.refinery.store.query.term.ParameterDirection; | ||
6 | import tools.refinery.store.query.term.Variable; | 14 | import tools.refinery.store.query.term.Variable; |
7 | import tools.refinery.store.query.view.KeyOnlyRelationView; | 15 | import tools.refinery.store.query.term.bool.BoolTerms; |
16 | import tools.refinery.store.query.view.KeyOnlyView; | ||
17 | import tools.refinery.store.query.view.SymbolView; | ||
8 | import tools.refinery.store.representation.Symbol; | 18 | import tools.refinery.store.representation.Symbol; |
9 | 19 | ||
20 | import java.util.List; | ||
21 | |||
10 | import static org.hamcrest.MatcherAssert.assertThat; | 22 | import static org.hamcrest.MatcherAssert.assertThat; |
23 | import static tools.refinery.store.query.literal.Literals.assume; | ||
11 | import static tools.refinery.store.query.literal.Literals.not; | 24 | import static tools.refinery.store.query.literal.Literals.not; |
12 | import static tools.refinery.store.query.tests.QueryMatchers.structurallyEqualTo; | 25 | import static tools.refinery.store.query.tests.QueryMatchers.structurallyEqualTo; |
13 | 26 | ||
14 | class DnfBuilderTest { | 27 | class DnfBuilderLiteralEliminationTest { |
28 | private final Symbol<Boolean> friend = Symbol.of("friend", 2); | ||
29 | private final SymbolView<Boolean> friendView = new KeyOnlyView<>(friend); | ||
30 | private final NodeVariable p = Variable.of("p"); | ||
31 | private final NodeVariable q = Variable.of("q"); | ||
32 | private final Dnf trueDnf = Dnf.builder().parameter(p, ParameterDirection.IN).clause().build(); | ||
33 | private final Dnf falseDnf = Dnf.builder().parameter(p).build(); | ||
34 | |||
15 | @Test | 35 | @Test |
16 | void eliminateTrueTest() { | 36 | void eliminateTrueTest() { |
17 | var p = Variable.of("p"); | ||
18 | var q = Variable.of("q"); | ||
19 | var friend = new Symbol<>("friend", 2, Boolean.class, false); | ||
20 | var friendView = new KeyOnlyRelationView<>(friend); | ||
21 | |||
22 | var actual = Dnf.builder() | 37 | var actual = Dnf.builder() |
23 | .parameters(p, q) | 38 | .parameters(p, q) |
24 | .clause(BooleanLiteral.TRUE, friendView.call(p, q)) | 39 | .clause(BooleanLiteral.TRUE, friendView.call(p, q)) |
@@ -29,12 +44,18 @@ class DnfBuilderTest { | |||
29 | } | 44 | } |
30 | 45 | ||
31 | @Test | 46 | @Test |
32 | void eliminateFalseTest() { | 47 | void eliminateTrueAssumptionTest() { |
33 | var p = Variable.of("p"); | 48 | var actual = Dnf.builder() |
34 | var q = Variable.of("q"); | 49 | .parameters(p, q) |
35 | var friend = new Symbol<>("friend", 2, Boolean.class, false); | 50 | .clause(assume(BoolTerms.constant(true)), friendView.call(p, q)) |
36 | var friendView = new KeyOnlyRelationView<>(friend); | 51 | .build(); |
52 | var expected = Dnf.builder().parameters(p, q).clause(friendView.call(p, q)).build(); | ||
53 | |||
54 | assertThat(actual, structurallyEqualTo(expected)); | ||
55 | } | ||
37 | 56 | ||
57 | @Test | ||
58 | void eliminateFalseTest() { | ||
38 | var actual = Dnf.builder() | 59 | var actual = Dnf.builder() |
39 | .parameters(p, q) | 60 | .parameters(p, q) |
40 | .clause(friendView.call(p, q)) | 61 | .clause(friendView.call(p, q)) |
@@ -45,30 +66,36 @@ class DnfBuilderTest { | |||
45 | assertThat(actual, structurallyEqualTo(expected)); | 66 | assertThat(actual, structurallyEqualTo(expected)); |
46 | } | 67 | } |
47 | 68 | ||
69 | @ParameterizedTest | ||
70 | @CsvSource(value = { | ||
71 | "false", | ||
72 | "null" | ||
73 | }, nullValues = "null") | ||
74 | void eliminateFalseAssumptionTest(Boolean value) { | ||
75 | var actual = Dnf.builder() | ||
76 | .parameters(p, q) | ||
77 | .clause(friendView.call(p, q)) | ||
78 | .clause(friendView.call(q, p), assume(BoolTerms.constant(value))) | ||
79 | .build(); | ||
80 | var expected = Dnf.builder().parameters(p, q).clause(friendView.call(p, q)).build(); | ||
81 | |||
82 | assertThat(actual, structurallyEqualTo(expected)); | ||
83 | } | ||
84 | |||
48 | @Test | 85 | @Test |
49 | void alwaysTrueTest() { | 86 | void alwaysTrueTest() { |
50 | var p = Variable.of("p"); | ||
51 | var q = Variable.of("q"); | ||
52 | var friend = new Symbol<>("friend", 2, Boolean.class, false); | ||
53 | var friendView = new KeyOnlyRelationView<>(friend); | ||
54 | |||
55 | var actual = Dnf.builder() | 87 | var actual = Dnf.builder() |
56 | .parameters(p, q) | 88 | .parameters(List.of(p, q), ParameterDirection.IN) |
57 | .clause(friendView.call(p, q)) | 89 | .clause(friendView.call(p, q)) |
58 | .clause(BooleanLiteral.TRUE) | 90 | .clause(BooleanLiteral.TRUE) |
59 | .build(); | 91 | .build(); |
60 | var expected = Dnf.builder().parameters(p, q).clause().build(); | 92 | var expected = Dnf.builder().parameters(List.of(p, q), ParameterDirection.IN).clause().build(); |
61 | 93 | ||
62 | assertThat(actual, structurallyEqualTo(expected)); | 94 | assertThat(actual, structurallyEqualTo(expected)); |
63 | } | 95 | } |
64 | 96 | ||
65 | @Test | 97 | @Test |
66 | void alwaysFalseTest() { | 98 | void alwaysFalseTest() { |
67 | var p = Variable.of("p"); | ||
68 | var q = Variable.of("q"); | ||
69 | var friend = new Symbol<>("friend", 2, Boolean.class, false); | ||
70 | var friendView = new KeyOnlyRelationView<>(friend); | ||
71 | |||
72 | var actual = Dnf.builder() | 99 | var actual = Dnf.builder() |
73 | .parameters(p, q) | 100 | .parameters(p, q) |
74 | .clause(friendView.call(p, q), BooleanLiteral.FALSE) | 101 | .clause(friendView.call(p, q), BooleanLiteral.FALSE) |
@@ -80,12 +107,6 @@ class DnfBuilderTest { | |||
80 | 107 | ||
81 | @Test | 108 | @Test |
82 | void eliminateTrueDnfTest() { | 109 | void eliminateTrueDnfTest() { |
83 | var p = Variable.of("p"); | ||
84 | var q = Variable.of("q"); | ||
85 | var friend = new Symbol<>("friend", 2, Boolean.class, false); | ||
86 | var friendView = new KeyOnlyRelationView<>(friend); | ||
87 | var trueDnf = Dnf.builder().parameter(p).clause().build(); | ||
88 | |||
89 | var actual = Dnf.builder() | 110 | var actual = Dnf.builder() |
90 | .parameters(p, q) | 111 | .parameters(p, q) |
91 | .clause(trueDnf.call(q), friendView.call(p, q)) | 112 | .clause(trueDnf.call(q), friendView.call(p, q)) |
@@ -97,12 +118,6 @@ class DnfBuilderTest { | |||
97 | 118 | ||
98 | @Test | 119 | @Test |
99 | void eliminateFalseDnfTest() { | 120 | void eliminateFalseDnfTest() { |
100 | var p = Variable.of("p"); | ||
101 | var q = Variable.of("q"); | ||
102 | var friend = new Symbol<>("friend", 2, Boolean.class, false); | ||
103 | var friendView = new KeyOnlyRelationView<>(friend); | ||
104 | var falseDnf = Dnf.builder().parameter(p).build(); | ||
105 | |||
106 | var actual = Dnf.builder() | 121 | var actual = Dnf.builder() |
107 | .parameters(p, q) | 122 | .parameters(p, q) |
108 | .clause(friendView.call(p, q)) | 123 | .clause(friendView.call(p, q)) |
@@ -115,30 +130,18 @@ class DnfBuilderTest { | |||
115 | 130 | ||
116 | @Test | 131 | @Test |
117 | void alwaysTrueDnfTest() { | 132 | void alwaysTrueDnfTest() { |
118 | var p = Variable.of("p"); | ||
119 | var q = Variable.of("q"); | ||
120 | var friend = new Symbol<>("friend", 2, Boolean.class, false); | ||
121 | var friendView = new KeyOnlyRelationView<>(friend); | ||
122 | var trueDnf = Dnf.builder().parameter(p).clause().build(); | ||
123 | |||
124 | var actual = Dnf.builder() | 133 | var actual = Dnf.builder() |
125 | .parameters(p, q) | 134 | .parameters(List.of(p, q), ParameterDirection.IN) |
126 | .clause(friendView.call(p, q)) | 135 | .clause(friendView.call(p, q)) |
127 | .clause(trueDnf.call(q)) | 136 | .clause(trueDnf.call(q)) |
128 | .build(); | 137 | .build(); |
129 | var expected = Dnf.builder().parameters(p, q).clause().build(); | 138 | var expected = Dnf.builder().parameters(List.of(p, q), ParameterDirection.IN).clause().build(); |
130 | 139 | ||
131 | assertThat(actual, structurallyEqualTo(expected)); | 140 | assertThat(actual, structurallyEqualTo(expected)); |
132 | } | 141 | } |
133 | 142 | ||
134 | @Test | 143 | @Test |
135 | void alwaysFalseDnfTest() { | 144 | void alwaysFalseDnfTest() { |
136 | var p = Variable.of("p"); | ||
137 | var q = Variable.of("q"); | ||
138 | var friend = new Symbol<>("friend", 2, Boolean.class, false); | ||
139 | var friendView = new KeyOnlyRelationView<>(friend); | ||
140 | var falseDnf = Dnf.builder().parameter(p).build(); | ||
141 | |||
142 | var actual = Dnf.builder() | 145 | var actual = Dnf.builder() |
143 | .parameters(p, q) | 146 | .parameters(p, q) |
144 | .clause(friendView.call(p, q), falseDnf.call(q)) | 147 | .clause(friendView.call(p, q), falseDnf.call(q)) |
@@ -150,12 +153,6 @@ class DnfBuilderTest { | |||
150 | 153 | ||
151 | @Test | 154 | @Test |
152 | void eliminateNotFalseDnfTest() { | 155 | void eliminateNotFalseDnfTest() { |
153 | var p = Variable.of("p"); | ||
154 | var q = Variable.of("q"); | ||
155 | var friend = new Symbol<>("friend", 2, Boolean.class, false); | ||
156 | var friendView = new KeyOnlyRelationView<>(friend); | ||
157 | var falseDnf = Dnf.builder().parameter(p).build(); | ||
158 | |||
159 | var actual = Dnf.builder() | 156 | var actual = Dnf.builder() |
160 | .parameters(p, q) | 157 | .parameters(p, q) |
161 | .clause(not(falseDnf.call(q)), friendView.call(p, q)) | 158 | .clause(not(falseDnf.call(q)), friendView.call(p, q)) |
@@ -167,12 +164,6 @@ class DnfBuilderTest { | |||
167 | 164 | ||
168 | @Test | 165 | @Test |
169 | void eliminateNotTrueDnfTest() { | 166 | void eliminateNotTrueDnfTest() { |
170 | var p = Variable.of("p"); | ||
171 | var q = Variable.of("q"); | ||
172 | var friend = new Symbol<>("friend", 2, Boolean.class, false); | ||
173 | var friendView = new KeyOnlyRelationView<>(friend); | ||
174 | var trueDnf = Dnf.builder().parameter(p).clause().build(); | ||
175 | |||
176 | var actual = Dnf.builder() | 167 | var actual = Dnf.builder() |
177 | .parameters(p, q) | 168 | .parameters(p, q) |
178 | .clause(friendView.call(p, q)) | 169 | .clause(friendView.call(p, q)) |
@@ -185,30 +176,18 @@ class DnfBuilderTest { | |||
185 | 176 | ||
186 | @Test | 177 | @Test |
187 | void alwaysNotFalseDnfTest() { | 178 | void alwaysNotFalseDnfTest() { |
188 | var p = Variable.of("p"); | ||
189 | var q = Variable.of("q"); | ||
190 | var friend = new Symbol<>("friend", 2, Boolean.class, false); | ||
191 | var friendView = new KeyOnlyRelationView<>(friend); | ||
192 | var falseDnf = Dnf.builder().parameter(p).build(); | ||
193 | |||
194 | var actual = Dnf.builder() | 179 | var actual = Dnf.builder() |
195 | .parameters(p, q) | 180 | .parameters(List.of(p, q), ParameterDirection.IN) |
196 | .clause(friendView.call(p, q)) | 181 | .clause(friendView.call(p, q)) |
197 | .clause(not(falseDnf.call(q))) | 182 | .clause(not(falseDnf.call(q))) |
198 | .build(); | 183 | .build(); |
199 | var expected = Dnf.builder().parameters(p, q).clause().build(); | 184 | var expected = Dnf.builder().parameters(List.of(p, q), ParameterDirection.IN).clause().build(); |
200 | 185 | ||
201 | assertThat(actual, structurallyEqualTo(expected)); | 186 | assertThat(actual, structurallyEqualTo(expected)); |
202 | } | 187 | } |
203 | 188 | ||
204 | @Test | 189 | @Test |
205 | void alwaysNotTrueDnfTest() { | 190 | void alwaysNotTrueDnfTest() { |
206 | var p = Variable.of("p"); | ||
207 | var q = Variable.of("q"); | ||
208 | var friend = new Symbol<>("friend", 2, Boolean.class, false); | ||
209 | var friendView = new KeyOnlyRelationView<>(friend); | ||
210 | var trueDnf = Dnf.builder().parameter(p).clause().build(); | ||
211 | |||
212 | var actual = Dnf.builder() | 191 | var actual = Dnf.builder() |
213 | .parameters(p, q) | 192 | .parameters(p, q) |
214 | .clause(friendView.call(p, q), not(trueDnf.call(q))) | 193 | .clause(friendView.call(p, q), not(trueDnf.call(q))) |
@@ -217,4 +196,15 @@ class DnfBuilderTest { | |||
217 | 196 | ||
218 | assertThat(actual, structurallyEqualTo(expected)); | 197 | assertThat(actual, structurallyEqualTo(expected)); |
219 | } | 198 | } |
199 | |||
200 | @Test | ||
201 | void removeDuplicateTest() { | ||
202 | var actual = Dnf.of(builder -> builder.clause((p, q) -> List.of( | ||
203 | friendView.call(p, q), | ||
204 | friendView.call(p, q) | ||
205 | ))); | ||
206 | var expected = Dnf.of(builder -> builder.clause((p, q) -> List.of(friendView.call(p, q)))); | ||
207 | |||
208 | assertThat(actual, structurallyEqualTo(expected)); | ||
209 | } | ||
220 | } | 210 | } |
diff --git a/subprojects/store-query/src/test/java/tools/refinery/store/query/dnf/DnfBuilderVariableUnificationTest.java b/subprojects/store-query/src/test/java/tools/refinery/store/query/dnf/DnfBuilderVariableUnificationTest.java new file mode 100644 index 00000000..fc40c7b3 --- /dev/null +++ b/subprojects/store-query/src/test/java/tools/refinery/store/query/dnf/DnfBuilderVariableUnificationTest.java | |||
@@ -0,0 +1,325 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf; | ||
7 | |||
8 | import org.junit.jupiter.api.Test; | ||
9 | import tools.refinery.store.query.term.ParameterDirection; | ||
10 | import tools.refinery.store.query.term.Variable; | ||
11 | import tools.refinery.store.query.view.KeyOnlyView; | ||
12 | import tools.refinery.store.query.view.SymbolView; | ||
13 | import tools.refinery.store.representation.Symbol; | ||
14 | |||
15 | import java.util.List; | ||
16 | |||
17 | import static org.hamcrest.MatcherAssert.assertThat; | ||
18 | import static tools.refinery.store.query.tests.QueryMatchers.structurallyEqualTo; | ||
19 | |||
20 | class DnfBuilderVariableUnificationTest { | ||
21 | private final Symbol<Boolean> friend = Symbol.of("friend", 2); | ||
22 | private final Symbol<Boolean> children = Symbol.of("children", 2); | ||
23 | private final SymbolView<Boolean> friendView = new KeyOnlyView<>(friend); | ||
24 | private final SymbolView<Boolean> childrenView = new KeyOnlyView<>(children); | ||
25 | |||
26 | @Test | ||
27 | void equalToParameterTest() { | ||
28 | var actual = Dnf.of(builder -> { | ||
29 | var p = builder.parameter("p"); | ||
30 | builder.clause(q -> List.of( | ||
31 | friendView.call(p, q), | ||
32 | p.isEquivalent(q) | ||
33 | )); | ||
34 | }); | ||
35 | |||
36 | var expectedP = Variable.of("p"); | ||
37 | assertThat(actual, structurallyEqualTo( | ||
38 | List.of(new SymbolicParameter(expectedP, ParameterDirection.OUT)), | ||
39 | List.of( | ||
40 | List.of(friendView.call(expectedP, expectedP)) | ||
41 | ) | ||
42 | )); | ||
43 | } | ||
44 | |||
45 | @Test | ||
46 | void equalToParameterReverseTest() { | ||
47 | var actual = Dnf.of(builder -> { | ||
48 | var p = builder.parameter("p"); | ||
49 | builder.clause(q -> List.of( | ||
50 | friendView.call(p, q), | ||
51 | q.isEquivalent(p) | ||
52 | )); | ||
53 | }); | ||
54 | |||
55 | var expectedP = Variable.of("p"); | ||
56 | assertThat(actual, structurallyEqualTo( | ||
57 | List.of(new SymbolicParameter(expectedP, ParameterDirection.OUT)), | ||
58 | List.of( | ||
59 | List.of(friendView.call(expectedP, expectedP)) | ||
60 | ) | ||
61 | )); | ||
62 | } | ||
63 | |||
64 | @Test | ||
65 | void equalQuantifiedTest() { | ||
66 | var actual = Dnf.of(builder -> builder.clause((p, q) -> List.of( | ||
67 | friendView.call(p, q), | ||
68 | p.isEquivalent(q) | ||
69 | ))); | ||
70 | |||
71 | var expectedP = Variable.of("p"); | ||
72 | assertThat(actual, structurallyEqualTo( | ||
73 | List.of(), | ||
74 | List.of( | ||
75 | List.of(friendView.call(expectedP, expectedP)) | ||
76 | ) | ||
77 | )); | ||
78 | } | ||
79 | |||
80 | @Test | ||
81 | void equalQuantifiedTransitiveTest() { | ||
82 | var actual = Dnf.of(builder -> builder.clause((p, q, r) -> List.of( | ||
83 | friendView.call(p, q), | ||
84 | p.isEquivalent(q), | ||
85 | childrenView.call(p, r), | ||
86 | q.isEquivalent(r) | ||
87 | ))); | ||
88 | |||
89 | var expectedP = Variable.of("p"); | ||
90 | assertThat(actual, structurallyEqualTo( | ||
91 | List.of(), | ||
92 | List.of( | ||
93 | List.of(friendView.call(expectedP, expectedP), childrenView.call(expectedP, expectedP)) | ||
94 | ) | ||
95 | )); | ||
96 | } | ||
97 | |||
98 | @Test | ||
99 | void equalQuantifiedTransitiveRemoveDuplicateTest() { | ||
100 | var actual = Dnf.of(builder -> builder.clause((p, q, r) -> List.of( | ||
101 | friendView.call(p, q), | ||
102 | p.isEquivalent(q), | ||
103 | friendView.call(p, r), | ||
104 | q.isEquivalent(r) | ||
105 | ))); | ||
106 | |||
107 | var expectedP = Variable.of("p"); | ||
108 | assertThat(actual, structurallyEqualTo( | ||
109 | List.of(), | ||
110 | List.of( | ||
111 | List.of(friendView.call(expectedP, expectedP)) | ||
112 | ) | ||
113 | )); | ||
114 | } | ||
115 | |||
116 | @Test | ||
117 | void parametersEqualTest() { | ||
118 | var actual = Dnf.of(builder -> { | ||
119 | var p = builder.parameter("p"); | ||
120 | var q = builder.parameter("q"); | ||
121 | builder.clause( | ||
122 | friendView.call(p, q), | ||
123 | p.isEquivalent(q) | ||
124 | ); | ||
125 | }); | ||
126 | |||
127 | var expectedP = Variable.of("p"); | ||
128 | var expectedQ = Variable.of("q"); | ||
129 | assertThat(actual, structurallyEqualTo( | ||
130 | List.of( | ||
131 | new SymbolicParameter(expectedP, ParameterDirection.OUT), | ||
132 | new SymbolicParameter(expectedQ, ParameterDirection.OUT) | ||
133 | ), | ||
134 | List.of( | ||
135 | List.of(friendView.call(expectedP, expectedP), expectedQ.isEquivalent(expectedP)) | ||
136 | ) | ||
137 | )); | ||
138 | } | ||
139 | |||
140 | @Test | ||
141 | void parametersEqualTransitiveTest() { | ||
142 | var actual = Dnf.of(builder -> { | ||
143 | var p = builder.parameter("p"); | ||
144 | var q = builder.parameter("q"); | ||
145 | var r = builder.parameter("r"); | ||
146 | builder.clause( | ||
147 | friendView.call(p, q), | ||
148 | childrenView.call(p, r), | ||
149 | p.isEquivalent(q), | ||
150 | r.isEquivalent(q) | ||
151 | ); | ||
152 | }); | ||
153 | |||
154 | var expectedP = Variable.of("p"); | ||
155 | var expectedQ = Variable.of("q"); | ||
156 | var expectedR = Variable.of("r"); | ||
157 | assertThat(actual, structurallyEqualTo( | ||
158 | List.of( | ||
159 | new SymbolicParameter(expectedP, ParameterDirection.OUT), | ||
160 | new SymbolicParameter(expectedQ, ParameterDirection.OUT), | ||
161 | new SymbolicParameter(expectedR, ParameterDirection.OUT) | ||
162 | ), | ||
163 | List.of( | ||
164 | List.of( | ||
165 | friendView.call(expectedP, expectedP), | ||
166 | expectedQ.isEquivalent(expectedP), | ||
167 | expectedR.isEquivalent(expectedP), | ||
168 | childrenView.call(expectedP, expectedP) | ||
169 | ) | ||
170 | ) | ||
171 | )); | ||
172 | } | ||
173 | |||
174 | @Test | ||
175 | void parameterAndQuantifiedEqualsTest() { | ||
176 | var actual = Dnf.of(builder -> { | ||
177 | var p = builder.parameter("p"); | ||
178 | var q = builder.parameter("q"); | ||
179 | builder.clause((r) -> List.of( | ||
180 | friendView.call(p, r), | ||
181 | p.isEquivalent(r), | ||
182 | childrenView.call(q, r), | ||
183 | q.isEquivalent(r) | ||
184 | )); | ||
185 | }); | ||
186 | |||
187 | |||
188 | var expectedP = Variable.of("p"); | ||
189 | var expectedQ = Variable.of("q"); | ||
190 | assertThat(actual, structurallyEqualTo( | ||
191 | List.of( | ||
192 | new SymbolicParameter(expectedP, ParameterDirection.OUT), | ||
193 | new SymbolicParameter(expectedQ, ParameterDirection.OUT) | ||
194 | ), | ||
195 | List.of( | ||
196 | List.of( | ||
197 | friendView.call(expectedP, expectedP), | ||
198 | expectedQ.isEquivalent(expectedP), | ||
199 | childrenView.call(expectedP, expectedP) | ||
200 | ) | ||
201 | ) | ||
202 | )); | ||
203 | } | ||
204 | |||
205 | @Test | ||
206 | void parameterAndQuantifiedEqualsReverseFirstTest() { | ||
207 | var actual = Dnf.of(builder -> { | ||
208 | var p = builder.parameter("p"); | ||
209 | var q = builder.parameter("q"); | ||
210 | builder.clause((r) -> List.of( | ||
211 | friendView.call(p, r), | ||
212 | r.isEquivalent(p), | ||
213 | childrenView.call(q, r), | ||
214 | q.isEquivalent(r) | ||
215 | )); | ||
216 | }); | ||
217 | |||
218 | var expectedP = Variable.of("p"); | ||
219 | var expectedQ = Variable.of("q"); | ||
220 | assertThat(actual, structurallyEqualTo( | ||
221 | List.of( | ||
222 | new SymbolicParameter(expectedP, ParameterDirection.OUT), | ||
223 | new SymbolicParameter(expectedQ, ParameterDirection.OUT) | ||
224 | ), | ||
225 | List.of( | ||
226 | List.of( | ||
227 | friendView.call(expectedP, expectedP), | ||
228 | expectedQ.isEquivalent(expectedP), | ||
229 | childrenView.call(expectedP, expectedP) | ||
230 | ) | ||
231 | ) | ||
232 | )); | ||
233 | } | ||
234 | |||
235 | @Test | ||
236 | void parameterAndQuantifiedEqualsReverseSecondTest() { | ||
237 | var actual = Dnf.of(builder -> { | ||
238 | var p = builder.parameter("p"); | ||
239 | var q = builder.parameter("q"); | ||
240 | builder.clause((r) -> List.of( | ||
241 | friendView.call(p, r), | ||
242 | p.isEquivalent(r), | ||
243 | childrenView.call(q, r), | ||
244 | r.isEquivalent(q) | ||
245 | )); | ||
246 | }); | ||
247 | |||
248 | var expectedP = Variable.of("p"); | ||
249 | var expectedQ = Variable.of("q"); | ||
250 | assertThat(actual, structurallyEqualTo( | ||
251 | List.of( | ||
252 | new SymbolicParameter(expectedP, ParameterDirection.OUT), | ||
253 | new SymbolicParameter(expectedQ, ParameterDirection.OUT) | ||
254 | ), | ||
255 | List.of( | ||
256 | List.of( | ||
257 | friendView.call(expectedP, expectedP), | ||
258 | expectedQ.isEquivalent(expectedP), | ||
259 | childrenView.call(expectedP, expectedP) | ||
260 | ) | ||
261 | ) | ||
262 | )); | ||
263 | } | ||
264 | |||
265 | @Test | ||
266 | void parameterAndQuantifiedEqualsReverseBoth() { | ||
267 | var actual = Dnf.of(builder -> { | ||
268 | var p = builder.parameter("p"); | ||
269 | var q = builder.parameter("q"); | ||
270 | builder.clause((r) -> List.of( | ||
271 | friendView.call(p, r), | ||
272 | p.isEquivalent(r), | ||
273 | childrenView.call(q, r), | ||
274 | r.isEquivalent(q) | ||
275 | )); | ||
276 | }); | ||
277 | |||
278 | var expectedP = Variable.of("p"); | ||
279 | var expectedQ = Variable.of("q"); | ||
280 | assertThat(actual, structurallyEqualTo( | ||
281 | List.of( | ||
282 | new SymbolicParameter(expectedP, ParameterDirection.OUT), | ||
283 | new SymbolicParameter(expectedQ, ParameterDirection.OUT) | ||
284 | ), | ||
285 | List.of( | ||
286 | List.of( | ||
287 | friendView.call(expectedP, expectedP), | ||
288 | expectedQ.isEquivalent(expectedP), | ||
289 | childrenView.call(expectedP, expectedP) | ||
290 | ) | ||
291 | ) | ||
292 | )); | ||
293 | } | ||
294 | |||
295 | @Test | ||
296 | void parameterAndTwoQuantifiedEqualsTest() { | ||
297 | var actual = Dnf.of(builder -> { | ||
298 | var p = builder.parameter("p"); | ||
299 | var q = builder.parameter("q"); | ||
300 | builder.clause((r, s) -> List.of( | ||
301 | r.isEquivalent(s), | ||
302 | friendView.call(p, r), | ||
303 | p.isEquivalent(r), | ||
304 | childrenView.call(q, s), | ||
305 | q.isEquivalent(s) | ||
306 | )); | ||
307 | }); | ||
308 | |||
309 | var expectedP = Variable.of("p"); | ||
310 | var expectedQ = Variable.of("q"); | ||
311 | assertThat(actual, structurallyEqualTo( | ||
312 | List.of( | ||
313 | new SymbolicParameter(expectedP, ParameterDirection.OUT), | ||
314 | new SymbolicParameter(expectedQ, ParameterDirection.OUT) | ||
315 | ), | ||
316 | List.of( | ||
317 | List.of( | ||
318 | friendView.call(expectedP, expectedP), | ||
319 | expectedQ.isEquivalent(expectedP), | ||
320 | childrenView.call(expectedP, expectedP) | ||
321 | ) | ||
322 | ) | ||
323 | )); | ||
324 | } | ||
325 | } | ||
diff --git a/subprojects/store-query/src/test/java/tools/refinery/store/query/DnfToDefinitionStringTest.java b/subprojects/store-query/src/test/java/tools/refinery/store/query/dnf/DnfToDefinitionStringTest.java index 9b469bb0..d75d7f17 100644 --- a/subprojects/store-query/src/test/java/tools/refinery/store/query/DnfToDefinitionStringTest.java +++ b/subprojects/store-query/src/test/java/tools/refinery/store/query/dnf/DnfToDefinitionStringTest.java | |||
@@ -1,9 +1,16 @@ | |||
1 | package tools.refinery.store.query; | 1 | /* |
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf; | ||
2 | 7 | ||
3 | import org.junit.jupiter.api.Test; | 8 | import org.junit.jupiter.api.Test; |
4 | import tools.refinery.store.query.dnf.Dnf; | 9 | import tools.refinery.store.query.term.NodeVariable; |
10 | import tools.refinery.store.query.term.ParameterDirection; | ||
5 | import tools.refinery.store.query.term.Variable; | 11 | import tools.refinery.store.query.term.Variable; |
6 | import tools.refinery.store.query.view.KeyOnlyRelationView; | 12 | import tools.refinery.store.query.view.AnySymbolView; |
13 | import tools.refinery.store.query.view.KeyOnlyView; | ||
7 | import tools.refinery.store.representation.Symbol; | 14 | import tools.refinery.store.representation.Symbol; |
8 | 15 | ||
9 | import static org.hamcrest.MatcherAssert.assertThat; | 16 | import static org.hamcrest.MatcherAssert.assertThat; |
@@ -11,9 +18,15 @@ import static org.hamcrest.Matchers.is; | |||
11 | import static tools.refinery.store.query.literal.Literals.not; | 18 | import static tools.refinery.store.query.literal.Literals.not; |
12 | 19 | ||
13 | class DnfToDefinitionStringTest { | 20 | class DnfToDefinitionStringTest { |
21 | private static final Symbol<Boolean> person = Symbol.of("person", 1); | ||
22 | private static final Symbol<Boolean> friend = Symbol.of("friend", 2); | ||
23 | private static final AnySymbolView personView = new KeyOnlyView<>(person); | ||
24 | private static final AnySymbolView friendView = new KeyOnlyView<>(friend); | ||
25 | private static final NodeVariable p = Variable.of("p"); | ||
26 | private static final NodeVariable q = Variable.of("q"); | ||
27 | |||
14 | @Test | 28 | @Test |
15 | void noClausesTest() { | 29 | void noClausesTest() { |
16 | var p = Variable.of("p"); | ||
17 | var dnf = Dnf.builder("Example").parameter(p).build(); | 30 | var dnf = Dnf.builder("Example").parameter(p).build(); |
18 | 31 | ||
19 | assertThat(dnf.toDefinitionString(), is(""" | 32 | assertThat(dnf.toDefinitionString(), is(""" |
@@ -34,21 +47,16 @@ class DnfToDefinitionStringTest { | |||
34 | 47 | ||
35 | @Test | 48 | @Test |
36 | void emptyClauseTest() { | 49 | void emptyClauseTest() { |
37 | var p = Variable.of("p"); | 50 | var dnf = Dnf.builder("Example").parameter(p, ParameterDirection.IN).clause().build(); |
38 | var dnf = Dnf.builder("Example").parameter(p).clause().build(); | ||
39 | 51 | ||
40 | assertThat(dnf.toDefinitionString(), is(""" | 52 | assertThat(dnf.toDefinitionString(), is(""" |
41 | pred Example(p) <-> | 53 | pred Example(@In p) <-> |
42 | <empty>. | 54 | <empty>. |
43 | """)); | 55 | """)); |
44 | } | 56 | } |
45 | 57 | ||
46 | @Test | 58 | @Test |
47 | void relationViewPositiveTest() { | 59 | void relationViewPositiveTest() { |
48 | var p = Variable.of("p"); | ||
49 | var q = Variable.of("q"); | ||
50 | var friend = new Symbol<>("friend", 2, Boolean.class, false); | ||
51 | var friendView = new KeyOnlyRelationView<>(friend); | ||
52 | var dnf = Dnf.builder("Example").parameter(p).clause(friendView.call(p, q)).build(); | 60 | var dnf = Dnf.builder("Example").parameter(p).clause(friendView.call(p, q)).build(); |
53 | 61 | ||
54 | assertThat(dnf.toDefinitionString(), is(""" | 62 | assertThat(dnf.toDefinitionString(), is(""" |
@@ -59,24 +67,19 @@ class DnfToDefinitionStringTest { | |||
59 | 67 | ||
60 | @Test | 68 | @Test |
61 | void relationViewNegativeTest() { | 69 | void relationViewNegativeTest() { |
62 | var p = Variable.of("p"); | 70 | var dnf = Dnf.builder("Example") |
63 | var q = Variable.of("q"); | 71 | .parameter(p, ParameterDirection.IN) |
64 | var friend = new Symbol<>("friend", 2, Boolean.class, false); | 72 | .clause(not(friendView.call(p, q))) |
65 | var friendView = new KeyOnlyRelationView<>(friend); | 73 | .build(); |
66 | var dnf = Dnf.builder("Example").parameter(p).clause(not(friendView.call(p, q))).build(); | ||
67 | 74 | ||
68 | assertThat(dnf.toDefinitionString(), is(""" | 75 | assertThat(dnf.toDefinitionString(), is(""" |
69 | pred Example(p) <-> | 76 | pred Example(@In p) <-> |
70 | !(@RelationView("key") friend(p, q)). | 77 | !(@RelationView("key") friend(p, q)). |
71 | """)); | 78 | """)); |
72 | } | 79 | } |
73 | 80 | ||
74 | @Test | 81 | @Test |
75 | void relationViewTransitiveTest() { | 82 | void relationViewTransitiveTest() { |
76 | var p = Variable.of("p"); | ||
77 | var q = Variable.of("q"); | ||
78 | var friend = new Symbol<>("friend", 2, Boolean.class, false); | ||
79 | var friendView = new KeyOnlyRelationView<>(friend); | ||
80 | var dnf = Dnf.builder("Example").parameter(p).clause(friendView.callTransitive(p, q)).build(); | 83 | var dnf = Dnf.builder("Example").parameter(p).clause(friendView.callTransitive(p, q)).build(); |
81 | 84 | ||
82 | assertThat(dnf.toDefinitionString(), is(""" | 85 | assertThat(dnf.toDefinitionString(), is(""" |
@@ -87,10 +90,6 @@ class DnfToDefinitionStringTest { | |||
87 | 90 | ||
88 | @Test | 91 | @Test |
89 | void multipleParametersTest() { | 92 | void multipleParametersTest() { |
90 | var p = Variable.of("p"); | ||
91 | var q = Variable.of("q"); | ||
92 | var friend = new Symbol<>("friend", 2, Boolean.class, false); | ||
93 | var friendView = new KeyOnlyRelationView<>(friend); | ||
94 | var dnf = Dnf.builder("Example").parameters(p, q).clause(friendView.call(p, q)).build(); | 93 | var dnf = Dnf.builder("Example").parameters(p, q).clause(friendView.call(p, q)).build(); |
95 | 94 | ||
96 | assertThat(dnf.toDefinitionString(), is(""" | 95 | assertThat(dnf.toDefinitionString(), is(""" |
@@ -101,12 +100,6 @@ class DnfToDefinitionStringTest { | |||
101 | 100 | ||
102 | @Test | 101 | @Test |
103 | void multipleLiteralsTest() { | 102 | void multipleLiteralsTest() { |
104 | var p = Variable.of("p"); | ||
105 | var q = Variable.of("q"); | ||
106 | var person = new Symbol<>("person", 1, Boolean.class, false); | ||
107 | var personView = new KeyOnlyRelationView<>(person); | ||
108 | var friend = new Symbol<>("friend", 2, Boolean.class, false); | ||
109 | var friendView = new KeyOnlyRelationView<>(friend); | ||
110 | var dnf = Dnf.builder("Example") | 103 | var dnf = Dnf.builder("Example") |
111 | .parameter(p) | 104 | .parameter(p) |
112 | .clause( | 105 | .clause( |
@@ -126,10 +119,6 @@ class DnfToDefinitionStringTest { | |||
126 | 119 | ||
127 | @Test | 120 | @Test |
128 | void multipleClausesTest() { | 121 | void multipleClausesTest() { |
129 | var p = Variable.of("p"); | ||
130 | var q = Variable.of("q"); | ||
131 | var friend = new Symbol<>("friend", 2, Boolean.class, false); | ||
132 | var friendView = new KeyOnlyRelationView<>(friend); | ||
133 | var dnf = Dnf.builder("Example") | 122 | var dnf = Dnf.builder("Example") |
134 | .parameter(p) | 123 | .parameter(p) |
135 | .clause(friendView.call(p, q)) | 124 | .clause(friendView.call(p, q)) |
@@ -146,14 +135,8 @@ class DnfToDefinitionStringTest { | |||
146 | 135 | ||
147 | @Test | 136 | @Test |
148 | void dnfTest() { | 137 | void dnfTest() { |
149 | var p = Variable.of("p"); | ||
150 | var q = Variable.of("q"); | ||
151 | var r = Variable.of("r"); | 138 | var r = Variable.of("r"); |
152 | var s = Variable.of("s"); | 139 | var s = Variable.of("s"); |
153 | var person = new Symbol<>("person", 1, Boolean.class, false); | ||
154 | var personView = new KeyOnlyRelationView<>(person); | ||
155 | var friend = new Symbol<>("friend", 2, Boolean.class, false); | ||
156 | var friendView = new KeyOnlyRelationView<>(friend); | ||
157 | var called = Dnf.builder("Called").parameters(r, s).clause(friendView.call(r, s)).build(); | 140 | var called = Dnf.builder("Called").parameters(r, s).clause(friendView.call(r, s)).build(); |
158 | var dnf = Dnf.builder("Example") | 141 | var dnf = Dnf.builder("Example") |
159 | .parameter(p) | 142 | .parameter(p) |
diff --git a/subprojects/store-query/src/test/java/tools/refinery/store/query/dnf/TopologicalSortTest.java b/subprojects/store-query/src/test/java/tools/refinery/store/query/dnf/TopologicalSortTest.java new file mode 100644 index 00000000..e22dbb21 --- /dev/null +++ b/subprojects/store-query/src/test/java/tools/refinery/store/query/dnf/TopologicalSortTest.java | |||
@@ -0,0 +1,112 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf; | ||
7 | |||
8 | import org.junit.jupiter.api.Test; | ||
9 | import tools.refinery.store.query.term.NodeVariable; | ||
10 | import tools.refinery.store.query.term.ParameterDirection; | ||
11 | import tools.refinery.store.query.term.Variable; | ||
12 | import tools.refinery.store.query.view.AnySymbolView; | ||
13 | import tools.refinery.store.query.view.KeyOnlyView; | ||
14 | import tools.refinery.store.representation.Symbol; | ||
15 | |||
16 | import java.util.List; | ||
17 | |||
18 | import static org.hamcrest.MatcherAssert.assertThat; | ||
19 | import static org.junit.jupiter.api.Assertions.assertThrows; | ||
20 | import static tools.refinery.store.query.literal.Literals.not; | ||
21 | import static tools.refinery.store.query.tests.QueryMatchers.structurallyEqualTo; | ||
22 | |||
23 | class TopologicalSortTest { | ||
24 | private static final Symbol<Boolean> friend = Symbol.of("friend", 2); | ||
25 | private static final AnySymbolView friendView = new KeyOnlyView<>(friend); | ||
26 | private static final Dnf example = Dnf.of("example", builder -> { | ||
27 | var a = builder.parameter("a", ParameterDirection.IN); | ||
28 | var b = builder.parameter("b", ParameterDirection.IN); | ||
29 | var c = builder.parameter("c", ParameterDirection.OUT); | ||
30 | var d = builder.parameter("d", ParameterDirection.OUT); | ||
31 | builder.clause( | ||
32 | friendView.call(a, b), | ||
33 | friendView.call(b, c), | ||
34 | friendView.call(c, d) | ||
35 | ); | ||
36 | }); | ||
37 | private static final NodeVariable p = Variable.of("p"); | ||
38 | private static final NodeVariable q = Variable.of("q"); | ||
39 | private static final NodeVariable r = Variable.of("r"); | ||
40 | private static final NodeVariable s = Variable.of("s"); | ||
41 | private static final NodeVariable t = Variable.of("t"); | ||
42 | |||
43 | @Test | ||
44 | void topologicalSortTest() { | ||
45 | var actual = Dnf.builder("Actual") | ||
46 | .parameter(p, ParameterDirection.IN) | ||
47 | .parameter(q, ParameterDirection.OUT) | ||
48 | .clause( | ||
49 | not(friendView.call(p, q)), | ||
50 | example.call(p, q, r, s), | ||
51 | example.call(r, t, q, s), | ||
52 | friendView.call(r, t) | ||
53 | ) | ||
54 | .build(); | ||
55 | |||
56 | assertThat(actual, structurallyEqualTo( | ||
57 | List.of( | ||
58 | new SymbolicParameter(p, ParameterDirection.IN), | ||
59 | new SymbolicParameter(q, ParameterDirection.OUT) | ||
60 | ), | ||
61 | List.of( | ||
62 | List.of( | ||
63 | friendView.call(r, t), | ||
64 | example.call(r, t, q, s), | ||
65 | not(friendView.call(p, q)), | ||
66 | example.call(p, q, r, s) | ||
67 | ) | ||
68 | ) | ||
69 | )); | ||
70 | } | ||
71 | |||
72 | @Test | ||
73 | void missingInputTest() { | ||
74 | var builder = Dnf.builder("Actual") | ||
75 | .parameter(p, ParameterDirection.OUT) | ||
76 | .parameter(q, ParameterDirection.OUT) | ||
77 | .clause( | ||
78 | not(friendView.call(p, q)), | ||
79 | example.call(p, q, r, s), | ||
80 | example.call(r, t, q, s), | ||
81 | friendView.call(r, t) | ||
82 | ); | ||
83 | assertThrows(IllegalArgumentException.class, builder::build); | ||
84 | } | ||
85 | |||
86 | @Test | ||
87 | void missingVariableTest() { | ||
88 | var builder = Dnf.builder("Actual") | ||
89 | .parameter(p, ParameterDirection.IN) | ||
90 | .parameter(q, ParameterDirection.OUT) | ||
91 | .clause( | ||
92 | not(friendView.call(p, q)), | ||
93 | example.call(p, q, r, s), | ||
94 | example.call(r, t, q, s) | ||
95 | ); | ||
96 | assertThrows(IllegalArgumentException.class, builder::build); | ||
97 | } | ||
98 | |||
99 | @Test | ||
100 | void circularDependencyTest() { | ||
101 | var builder = Dnf.builder("Actual") | ||
102 | .parameter(p, ParameterDirection.IN) | ||
103 | .parameter(q, ParameterDirection.OUT) | ||
104 | .clause( | ||
105 | not(friendView.call(p, q)), | ||
106 | example.call(p, q, r, s), | ||
107 | example.call(r, t, q, s), | ||
108 | example.call(p, q, r, t) | ||
109 | ); | ||
110 | assertThrows(IllegalArgumentException.class, builder::build); | ||
111 | } | ||
112 | } | ||
diff --git a/subprojects/store-query/src/test/java/tools/refinery/store/query/dnf/VariableDirectionTest.java b/subprojects/store-query/src/test/java/tools/refinery/store/query/dnf/VariableDirectionTest.java new file mode 100644 index 00000000..c52d26b2 --- /dev/null +++ b/subprojects/store-query/src/test/java/tools/refinery/store/query/dnf/VariableDirectionTest.java | |||
@@ -0,0 +1,428 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.dnf; | ||
7 | |||
8 | import org.junit.jupiter.params.ParameterizedTest; | ||
9 | import org.junit.jupiter.params.provider.Arguments; | ||
10 | import org.junit.jupiter.params.provider.MethodSource; | ||
11 | import tools.refinery.store.query.literal.BooleanLiteral; | ||
12 | import tools.refinery.store.query.literal.Literal; | ||
13 | import tools.refinery.store.query.term.DataVariable; | ||
14 | import tools.refinery.store.query.term.NodeVariable; | ||
15 | import tools.refinery.store.query.term.ParameterDirection; | ||
16 | import tools.refinery.store.query.term.Variable; | ||
17 | import tools.refinery.store.query.view.AnySymbolView; | ||
18 | import tools.refinery.store.query.view.FunctionView; | ||
19 | import tools.refinery.store.query.view.KeyOnlyView; | ||
20 | import tools.refinery.store.representation.Symbol; | ||
21 | |||
22 | import java.util.ArrayList; | ||
23 | import java.util.List; | ||
24 | import java.util.stream.Stream; | ||
25 | |||
26 | import static org.hamcrest.MatcherAssert.assertThat; | ||
27 | import static org.hamcrest.Matchers.hasItem; | ||
28 | import static org.hamcrest.Matchers.not; | ||
29 | import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; | ||
30 | import static org.junit.jupiter.api.Assertions.assertThrows; | ||
31 | import static tools.refinery.store.query.literal.Literals.assume; | ||
32 | import static tools.refinery.store.query.literal.Literals.not; | ||
33 | import static tools.refinery.store.query.term.int_.IntTerms.*; | ||
34 | |||
35 | class VariableDirectionTest { | ||
36 | private static final Symbol<Boolean> person = Symbol.of("Person", 1); | ||
37 | private static final Symbol<Boolean> friend = Symbol.of("friend", 2); | ||
38 | private static final Symbol<Integer> age = Symbol.of("age", 1, Integer.class); | ||
39 | private static final AnySymbolView personView = new KeyOnlyView<>(person); | ||
40 | private static final AnySymbolView friendView = new KeyOnlyView<>(friend); | ||
41 | private static final FunctionView<Integer> ageView = new FunctionView<>(age); | ||
42 | private static final NodeVariable p = Variable.of("p"); | ||
43 | private static final NodeVariable q = Variable.of("q"); | ||
44 | private static final DataVariable<Integer> x = Variable.of("x", Integer.class); | ||
45 | private static final DataVariable<Integer> y = Variable.of("y", Integer.class); | ||
46 | private static final DataVariable<Integer> z = Variable.of("z", Integer.class); | ||
47 | |||
48 | @ParameterizedTest | ||
49 | @MethodSource("clausesWithVariableInput") | ||
50 | void unboundOutVariableTest(List<? extends Literal> clause) { | ||
51 | var builder = Dnf.builder().parameter(p, ParameterDirection.OUT).clause(clause); | ||
52 | assertThrows(IllegalArgumentException.class, builder::build); | ||
53 | } | ||
54 | |||
55 | @ParameterizedTest | ||
56 | @MethodSource("clausesWithVariableInput") | ||
57 | void unboundInVariableTest(List<? extends Literal> clause) { | ||
58 | var builder = Dnf.builder().parameter(p, ParameterDirection.IN).clause(clause); | ||
59 | var dnf = assertDoesNotThrow(builder::build); | ||
60 | var clauses = dnf.getClauses(); | ||
61 | if (clauses.size() > 0) { | ||
62 | assertThat(clauses.get(0).positiveVariables(), hasItem(p)); | ||
63 | } | ||
64 | } | ||
65 | |||
66 | @ParameterizedTest | ||
67 | @MethodSource("clausesWithVariableInput") | ||
68 | void boundPrivateVariableTest(List<? extends Literal> clause) { | ||
69 | var clauseWithBinding = new ArrayList<Literal>(clause); | ||
70 | clauseWithBinding.add(personView.call(p)); | ||
71 | var builder = Dnf.builder().clause(clauseWithBinding); | ||
72 | var dnf = assertDoesNotThrow(builder::build); | ||
73 | var clauses = dnf.getClauses(); | ||
74 | if (clauses.size() > 0) { | ||
75 | assertThat(clauses.get(0).positiveVariables(), hasItem(p)); | ||
76 | } | ||
77 | } | ||
78 | |||
79 | static Stream<Arguments> clausesWithVariableInput() { | ||
80 | return Stream.concat( | ||
81 | clausesNotBindingVariable(), | ||
82 | literalToClauseArgumentStream(literalsWithRequiredVariableInput()) | ||
83 | ); | ||
84 | } | ||
85 | |||
86 | @ParameterizedTest | ||
87 | @MethodSource("clausesNotBindingVariable") | ||
88 | void unboundPrivateVariableTest(List<? extends Literal> clause) { | ||
89 | var builder = Dnf.builder().clause(clause); | ||
90 | var dnf = assertDoesNotThrow(builder::build); | ||
91 | var clauses = dnf.getClauses(); | ||
92 | if (clauses.size() > 0) { | ||
93 | assertThat(clauses.get(0).positiveVariables(), not(hasItem(p))); | ||
94 | } | ||
95 | } | ||
96 | |||
97 | @ParameterizedTest | ||
98 | @MethodSource("clausesNotBindingVariable") | ||
99 | void unboundByEquivalencePrivateVariableTest(List<? extends Literal> clause) { | ||
100 | var r = Variable.of("r"); | ||
101 | var clauseWithEquivalence = new ArrayList<Literal>(clause); | ||
102 | clauseWithEquivalence.add(r.isEquivalent(p)); | ||
103 | var builder = Dnf.builder().clause(clauseWithEquivalence); | ||
104 | assertThrows(IllegalArgumentException.class, builder::build); | ||
105 | } | ||
106 | |||
107 | static Stream<Arguments> clausesNotBindingVariable() { | ||
108 | return Stream.concat( | ||
109 | Stream.of( | ||
110 | Arguments.of(List.of()), | ||
111 | Arguments.of(List.of(BooleanLiteral.TRUE)), | ||
112 | Arguments.of(List.of(BooleanLiteral.FALSE)) | ||
113 | ), | ||
114 | literalToClauseArgumentStream(literalsWithPrivateVariable()) | ||
115 | ); | ||
116 | } | ||
117 | |||
118 | @ParameterizedTest | ||
119 | @MethodSource("literalsWithPrivateVariable") | ||
120 | void unboundTwicePrivateVariableTest(Literal literal) { | ||
121 | var builder = Dnf.builder().clause(not(personView.call(p)), literal); | ||
122 | assertThrows(IllegalArgumentException.class, builder::build); | ||
123 | } | ||
124 | |||
125 | @ParameterizedTest | ||
126 | @MethodSource("literalsWithPrivateVariable") | ||
127 | void unboundTwiceByEquivalencePrivateVariableTest(Literal literal) { | ||
128 | var r = Variable.of("r"); | ||
129 | var builder = Dnf.builder().clause(not(personView.call(r)), r.isEquivalent(p), literal); | ||
130 | assertThrows(IllegalArgumentException.class, builder::build); | ||
131 | } | ||
132 | |||
133 | static Stream<Arguments> literalsWithPrivateVariable() { | ||
134 | var dnfWithOutput = Dnf.builder("WithOutput") | ||
135 | .parameter(p, ParameterDirection.OUT) | ||
136 | .parameter(q, ParameterDirection.OUT) | ||
137 | .clause(friendView.call(p, q)) | ||
138 | .build(); | ||
139 | var dnfWithOutputToAggregate = Dnf.builder("WithOutputToAggregate") | ||
140 | .parameter(p, ParameterDirection.OUT) | ||
141 | .parameter(q, ParameterDirection.OUT) | ||
142 | .parameter(x, ParameterDirection.OUT) | ||
143 | .clause( | ||
144 | friendView.call(p, q), | ||
145 | ageView.call(q, x) | ||
146 | ) | ||
147 | .build(); | ||
148 | |||
149 | return Stream.of( | ||
150 | Arguments.of(not(friendView.call(p, q))), | ||
151 | Arguments.of(y.assign(friendView.count(p, q))), | ||
152 | Arguments.of(y.assign(ageView.aggregate(INT_SUM, p))), | ||
153 | Arguments.of(not(dnfWithOutput.call(p, q))), | ||
154 | Arguments.of(y.assign(dnfWithOutput.count(p, q))), | ||
155 | Arguments.of(y.assign(dnfWithOutputToAggregate.aggregateBy(z, INT_SUM, p, q, z))) | ||
156 | ); | ||
157 | } | ||
158 | |||
159 | @ParameterizedTest | ||
160 | @MethodSource("literalsWithRequiredVariableInput") | ||
161 | void unboundPrivateVariableTest(Literal literal) { | ||
162 | var builder = Dnf.builder().clause(literal); | ||
163 | assertThrows(IllegalArgumentException.class, builder::build); | ||
164 | } | ||
165 | |||
166 | @ParameterizedTest | ||
167 | @MethodSource("literalsWithRequiredVariableInput") | ||
168 | void boundPrivateVariableInputTest(Literal literal) { | ||
169 | var builder = Dnf.builder().clause(personView.call(p), literal); | ||
170 | var dnf = assertDoesNotThrow(builder::build); | ||
171 | assertThat(dnf.getClauses().get(0).positiveVariables(), hasItem(p)); | ||
172 | } | ||
173 | |||
174 | static Stream<Arguments> literalsWithRequiredVariableInput() { | ||
175 | var dnfWithInput = Dnf.builder("WithInput") | ||
176 | .parameter(p, ParameterDirection.IN) | ||
177 | .parameter(q, ParameterDirection.OUT) | ||
178 | .clause(friendView.call(p, q)).build(); | ||
179 | var dnfWithInputToAggregate = Dnf.builder("WithInputToAggregate") | ||
180 | .parameter(p, ParameterDirection.IN) | ||
181 | .parameter(q, ParameterDirection.OUT) | ||
182 | .parameter(x, ParameterDirection.OUT) | ||
183 | .clause( | ||
184 | friendView.call(p, q), | ||
185 | ageView.call(q, x) | ||
186 | ).build(); | ||
187 | |||
188 | return Stream.of( | ||
189 | Arguments.of(dnfWithInput.call(p, q)), | ||
190 | Arguments.of(dnfWithInput.call(p, p)), | ||
191 | Arguments.of(not(dnfWithInput.call(p, q))), | ||
192 | Arguments.of(not(dnfWithInput.call(p, p))), | ||
193 | Arguments.of(y.assign(dnfWithInput.count(p, q))), | ||
194 | Arguments.of(y.assign(dnfWithInput.count(p, p))), | ||
195 | Arguments.of(y.assign(dnfWithInputToAggregate.aggregateBy(z, INT_SUM, p, q, z))), | ||
196 | Arguments.of(y.assign(dnfWithInputToAggregate.aggregateBy(z, INT_SUM, p, p, z))) | ||
197 | ); | ||
198 | } | ||
199 | |||
200 | @ParameterizedTest | ||
201 | @MethodSource("literalsWithVariableOutput") | ||
202 | void boundParameterTest(Literal literal) { | ||
203 | var builder = Dnf.builder().parameter(p, ParameterDirection.OUT).clause(literal); | ||
204 | var dnf = assertDoesNotThrow(builder::build); | ||
205 | assertThat(dnf.getClauses().get(0).positiveVariables(), hasItem(p)); | ||
206 | } | ||
207 | |||
208 | @ParameterizedTest | ||
209 | @MethodSource("literalsWithVariableOutput") | ||
210 | void boundTwiceParameterTest(Literal literal) { | ||
211 | var builder = Dnf.builder().parameter(p, ParameterDirection.IN).clause(literal); | ||
212 | var dnf = assertDoesNotThrow(builder::build); | ||
213 | assertThat(dnf.getClauses().get(0).positiveVariables(), hasItem(p)); | ||
214 | } | ||
215 | |||
216 | @ParameterizedTest | ||
217 | @MethodSource("literalsWithVariableOutput") | ||
218 | void boundPrivateVariableOutputTest(Literal literal) { | ||
219 | var dnfWithInput = Dnf.builder("WithInput") | ||
220 | .parameter(p, ParameterDirection.IN) | ||
221 | .clause(personView.call(p)) | ||
222 | .build(); | ||
223 | var builder = Dnf.builder().clause(dnfWithInput.call(p), literal); | ||
224 | var dnf = assertDoesNotThrow(builder::build); | ||
225 | assertThat(dnf.getClauses().get(0).positiveVariables(), hasItem(p)); | ||
226 | } | ||
227 | |||
228 | @ParameterizedTest | ||
229 | @MethodSource("literalsWithVariableOutput") | ||
230 | void boundTwicePrivateVariableOutputTest(Literal literal) { | ||
231 | var builder = Dnf.builder().clause(personView.call(p), literal); | ||
232 | var dnf = assertDoesNotThrow(builder::build); | ||
233 | assertThat(dnf.getClauses().get(0).positiveVariables(), hasItem(p)); | ||
234 | } | ||
235 | |||
236 | static Stream<Arguments> literalsWithVariableOutput() { | ||
237 | var dnfWithOutput = Dnf.builder("WithOutput") | ||
238 | .parameter(p, ParameterDirection.OUT) | ||
239 | .parameter(q, ParameterDirection.OUT) | ||
240 | .clause(friendView.call(p, q)) | ||
241 | .build(); | ||
242 | |||
243 | return Stream.of( | ||
244 | Arguments.of(friendView.call(p, q)), | ||
245 | Arguments.of(dnfWithOutput.call(p, q)) | ||
246 | ); | ||
247 | } | ||
248 | |||
249 | @ParameterizedTest | ||
250 | @MethodSource("clausesWithDataVariableInput") | ||
251 | void unboundOutDataVariableTest(List<? extends Literal> clause) { | ||
252 | var builder = Dnf.builder().parameter(x, ParameterDirection.OUT).clause(clause); | ||
253 | assertThrows(IllegalArgumentException.class, builder::build); | ||
254 | } | ||
255 | |||
256 | @ParameterizedTest | ||
257 | @MethodSource("clausesWithDataVariableInput") | ||
258 | void unboundInDataVariableTest(List<? extends Literal> clause) { | ||
259 | var builder = Dnf.builder().parameter(x, ParameterDirection.IN).clause(clause); | ||
260 | var dnf = assertDoesNotThrow(builder::build); | ||
261 | var clauses = dnf.getClauses(); | ||
262 | if (clauses.size() > 0) { | ||
263 | assertThat(clauses.get(0).positiveVariables(), hasItem(x)); | ||
264 | } | ||
265 | } | ||
266 | |||
267 | @ParameterizedTest | ||
268 | @MethodSource("clausesWithDataVariableInput") | ||
269 | void boundPrivateDataVariableTest(List<? extends Literal> clause) { | ||
270 | var clauseWithBinding = new ArrayList<Literal>(clause); | ||
271 | clauseWithBinding.add(x.assign(constant(27))); | ||
272 | var builder = Dnf.builder().clause(clauseWithBinding); | ||
273 | var dnf = assertDoesNotThrow(builder::build); | ||
274 | var clauses = dnf.getClauses(); | ||
275 | if (clauses.size() > 0) { | ||
276 | assertThat(clauses.get(0).positiveVariables(), hasItem(x)); | ||
277 | } | ||
278 | } | ||
279 | |||
280 | static Stream<Arguments> clausesWithDataVariableInput() { | ||
281 | return Stream.concat( | ||
282 | clausesNotBindingDataVariable(), | ||
283 | literalToClauseArgumentStream(literalsWithRequiredDataVariableInput()) | ||
284 | ); | ||
285 | } | ||
286 | |||
287 | @ParameterizedTest | ||
288 | @MethodSource("clausesNotBindingDataVariable") | ||
289 | void unboundPrivateDataVariableTest(List<? extends Literal> clause) { | ||
290 | var builder = Dnf.builder().clause(clause); | ||
291 | var dnf = assertDoesNotThrow(builder::build); | ||
292 | var clauses = dnf.getClauses(); | ||
293 | if (clauses.size() > 0) { | ||
294 | assertThat(clauses.get(0).positiveVariables(), not(hasItem(x))); | ||
295 | } | ||
296 | } | ||
297 | |||
298 | static Stream<Arguments> clausesNotBindingDataVariable() { | ||
299 | return Stream.concat( | ||
300 | Stream.of( | ||
301 | Arguments.of(List.of()), | ||
302 | Arguments.of(List.of(BooleanLiteral.TRUE)), | ||
303 | Arguments.of(List.of(BooleanLiteral.FALSE)) | ||
304 | ), | ||
305 | literalToClauseArgumentStream(literalsWithPrivateDataVariable()) | ||
306 | ); | ||
307 | } | ||
308 | |||
309 | @ParameterizedTest | ||
310 | @MethodSource("literalsWithPrivateDataVariable") | ||
311 | void unboundTwicePrivateDataVariableTest(Literal literal) { | ||
312 | var builder = Dnf.builder().clause(not(ageView.call(p, x)), literal); | ||
313 | assertThrows(IllegalArgumentException.class, builder::build); | ||
314 | } | ||
315 | |||
316 | static Stream<Arguments> literalsWithPrivateDataVariable() { | ||
317 | var dnfWithOutput = Dnf.builder("WithDataOutput") | ||
318 | .parameter(y, ParameterDirection.OUT) | ||
319 | .parameter(q, ParameterDirection.OUT) | ||
320 | .clause(ageView.call(q, y)) | ||
321 | .build(); | ||
322 | |||
323 | return Stream.of( | ||
324 | Arguments.of(not(ageView.call(q, x))), | ||
325 | Arguments.of(y.assign(ageView.count(q, x))), | ||
326 | Arguments.of(not(dnfWithOutput.call(x, q))) | ||
327 | ); | ||
328 | } | ||
329 | |||
330 | @ParameterizedTest | ||
331 | @MethodSource("literalsWithRequiredDataVariableInput") | ||
332 | void unboundPrivateDataVariableTest(Literal literal) { | ||
333 | var builder = Dnf.builder().clause(literal); | ||
334 | assertThrows(IllegalArgumentException.class, builder::build); | ||
335 | } | ||
336 | |||
337 | static Stream<Arguments> literalsWithRequiredDataVariableInput() { | ||
338 | var dnfWithInput = Dnf.builder("WithDataInput") | ||
339 | .parameter(y, ParameterDirection.IN) | ||
340 | .parameter(q, ParameterDirection.OUT) | ||
341 | .clause(ageView.call(q, x)) | ||
342 | .build(); | ||
343 | // We are passing {@code y} to the parameter named {@code right} of {@code greaterEq}. | ||
344 | @SuppressWarnings("SuspiciousNameCombination") | ||
345 | var dnfWithInputToAggregate = Dnf.builder("WithDataInputToAggregate") | ||
346 | .parameter(y, ParameterDirection.IN) | ||
347 | .parameter(q, ParameterDirection.OUT) | ||
348 | .parameter(x, ParameterDirection.OUT) | ||
349 | .clause( | ||
350 | friendView.call(p, q), | ||
351 | ageView.call(q, x), | ||
352 | assume(greaterEq(x, y)) | ||
353 | ) | ||
354 | .build(); | ||
355 | |||
356 | return Stream.of( | ||
357 | Arguments.of(dnfWithInput.call(x, q)), | ||
358 | Arguments.of(not(dnfWithInput.call(x, q))), | ||
359 | Arguments.of(y.assign(dnfWithInput.count(x, q))), | ||
360 | Arguments.of(y.assign(dnfWithInputToAggregate.aggregateBy(z, INT_SUM, x, q, z))) | ||
361 | ); | ||
362 | } | ||
363 | |||
364 | @ParameterizedTest | ||
365 | @MethodSource("literalsWithDataVariableOutput") | ||
366 | void boundDataParameterTest(Literal literal) { | ||
367 | var builder = Dnf.builder().parameter(x, ParameterDirection.OUT).clause(literal); | ||
368 | var dnf = assertDoesNotThrow(builder::build); | ||
369 | assertThat(dnf.getClauses().get(0).positiveVariables(), hasItem(x)); | ||
370 | } | ||
371 | |||
372 | @ParameterizedTest | ||
373 | @MethodSource("literalsWithDataVariableOutput") | ||
374 | void boundTwiceDataParameterTest(Literal literal) { | ||
375 | var builder = Dnf.builder().parameter(x, ParameterDirection.IN).clause(literal); | ||
376 | assertThrows(IllegalArgumentException.class, builder::build); | ||
377 | } | ||
378 | |||
379 | @ParameterizedTest | ||
380 | @MethodSource("literalsWithDataVariableOutput") | ||
381 | void boundPrivateDataVariableOutputTest(Literal literal) { | ||
382 | var dnfWithInput = Dnf.builder("WithInput") | ||
383 | .parameter(x, ParameterDirection.IN) | ||
384 | .clause(assume(greaterEq(x, constant(24)))) | ||
385 | .build(); | ||
386 | var builder = Dnf.builder().clause(dnfWithInput.call(x), literal); | ||
387 | var dnf = assertDoesNotThrow(builder::build); | ||
388 | assertThat(dnf.getClauses().get(0).positiveVariables(), hasItem(x)); | ||
389 | } | ||
390 | |||
391 | @ParameterizedTest | ||
392 | @MethodSource("literalsWithDataVariableOutput") | ||
393 | void boundTwicePrivateDataVariableOutputTest(Literal literal) { | ||
394 | var builder = Dnf.builder().clause(x.assign(constant(27)), literal); | ||
395 | assertThrows(IllegalArgumentException.class, builder::build); | ||
396 | } | ||
397 | |||
398 | static Stream<Arguments> literalsWithDataVariableOutput() { | ||
399 | var dnfWithOutput = Dnf.builder("WithOutput") | ||
400 | .parameter(q, ParameterDirection.OUT) | ||
401 | .clause(personView.call(q)) | ||
402 | .build(); | ||
403 | var dnfWithDataOutput = Dnf.builder("WithDataOutput") | ||
404 | .parameter(y, ParameterDirection.OUT) | ||
405 | .parameter(q, ParameterDirection.OUT) | ||
406 | .clause(ageView.call(q, y)) | ||
407 | .build(); | ||
408 | var dnfWithOutputToAggregate = Dnf.builder("WithDataOutputToAggregate") | ||
409 | .parameter(q, ParameterDirection.OUT) | ||
410 | .parameter(y, ParameterDirection.OUT) | ||
411 | .clause(ageView.call(q, y)) | ||
412 | .build(); | ||
413 | |||
414 | return Stream.of( | ||
415 | Arguments.of(x.assign(constant(24))), | ||
416 | Arguments.of(ageView.call(q, x)), | ||
417 | Arguments.of(x.assign(personView.count(q))), | ||
418 | Arguments.of(x.assign(ageView.aggregate(INT_SUM, q))), | ||
419 | Arguments.of(dnfWithDataOutput.call(x, q)), | ||
420 | Arguments.of(x.assign(dnfWithOutput.count(q))), | ||
421 | Arguments.of(x.assign(dnfWithOutputToAggregate.aggregateBy(z, INT_SUM, q, z))) | ||
422 | ); | ||
423 | } | ||
424 | |||
425 | private static Stream<Arguments> literalToClauseArgumentStream(Stream<Arguments> literalArgumentsStream) { | ||
426 | return literalArgumentsStream.map(arguments -> Arguments.of(List.of(arguments.get()[0]))); | ||
427 | } | ||
428 | } | ||
diff --git a/subprojects/store-query/src/test/java/tools/refinery/store/query/literal/AggregationLiteralTest.java b/subprojects/store-query/src/test/java/tools/refinery/store/query/literal/AggregationLiteralTest.java new file mode 100644 index 00000000..35910e08 --- /dev/null +++ b/subprojects/store-query/src/test/java/tools/refinery/store/query/literal/AggregationLiteralTest.java | |||
@@ -0,0 +1,88 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.literal; | ||
7 | |||
8 | import org.junit.jupiter.api.Test; | ||
9 | import tools.refinery.store.query.Constraint; | ||
10 | import tools.refinery.store.query.dnf.Dnf; | ||
11 | import tools.refinery.store.query.term.*; | ||
12 | |||
13 | import java.util.List; | ||
14 | import java.util.Set; | ||
15 | |||
16 | import static org.hamcrest.MatcherAssert.assertThat; | ||
17 | import static org.hamcrest.Matchers.containsInAnyOrder; | ||
18 | import static org.hamcrest.Matchers.empty; | ||
19 | import static org.junit.jupiter.api.Assertions.assertAll; | ||
20 | import static org.junit.jupiter.api.Assertions.assertThrows; | ||
21 | import static tools.refinery.store.query.literal.Literals.not; | ||
22 | import static tools.refinery.store.query.term.int_.IntTerms.INT_SUM; | ||
23 | import static tools.refinery.store.query.term.int_.IntTerms.constant; | ||
24 | |||
25 | class AggregationLiteralTest { | ||
26 | private static final NodeVariable p = Variable.of("p"); | ||
27 | private static final DataVariable<Integer> x = Variable.of("x", Integer.class); | ||
28 | private static final DataVariable<Integer> y = Variable.of("y", Integer.class); | ||
29 | private static final DataVariable<Integer> z = Variable.of("z", Integer.class); | ||
30 | private static final Constraint fakeConstraint = new Constraint() { | ||
31 | @Override | ||
32 | public String name() { | ||
33 | return getClass().getName(); | ||
34 | } | ||
35 | |||
36 | @Override | ||
37 | public List<Parameter> getParameters() { | ||
38 | return List.of( | ||
39 | new Parameter(null, ParameterDirection.OUT), | ||
40 | new Parameter(Integer.class, ParameterDirection.OUT) | ||
41 | ); | ||
42 | } | ||
43 | }; | ||
44 | |||
45 | @Test | ||
46 | void parameterDirectionTest() { | ||
47 | var literal = x.assign(fakeConstraint.aggregateBy(y, INT_SUM, p, y)); | ||
48 | assertAll( | ||
49 | () -> assertThat(literal.getOutputVariables(), containsInAnyOrder(x)), | ||
50 | () -> assertThat(literal.getInputVariables(Set.of()), empty()), | ||
51 | () -> assertThat(literal.getInputVariables(Set.of(p)), containsInAnyOrder(p)), | ||
52 | () -> assertThat(literal.getPrivateVariables(Set.of()), containsInAnyOrder(p, y)), | ||
53 | () -> assertThat(literal.getPrivateVariables(Set.of(p)), containsInAnyOrder(y)) | ||
54 | ); | ||
55 | } | ||
56 | |||
57 | @Test | ||
58 | void missingAggregationVariableTest() { | ||
59 | var aggregation = fakeConstraint.aggregateBy(y, INT_SUM, p, z); | ||
60 | assertThrows(IllegalArgumentException.class, () -> x.assign(aggregation)); | ||
61 | } | ||
62 | |||
63 | @Test | ||
64 | void circularAggregationVariableTest() { | ||
65 | var aggregation = fakeConstraint.aggregateBy(x, INT_SUM, p, x); | ||
66 | assertThrows(IllegalArgumentException.class, () -> x.assign(aggregation)); | ||
67 | } | ||
68 | |||
69 | @Test | ||
70 | void unboundTwiceVariableTest() { | ||
71 | var builder = Dnf.builder() | ||
72 | .clause( | ||
73 | not(fakeConstraint.call(p, y)), | ||
74 | x.assign(fakeConstraint.aggregateBy(y, INT_SUM, p, y)) | ||
75 | ); | ||
76 | assertThrows(IllegalArgumentException.class, builder::build); | ||
77 | } | ||
78 | |||
79 | @Test | ||
80 | void unboundBoundVariableTest() { | ||
81 | var builder = Dnf.builder() | ||
82 | .clause( | ||
83 | y.assign(constant(27)), | ||
84 | x.assign(fakeConstraint.aggregateBy(y, INT_SUM, p, y)) | ||
85 | ); | ||
86 | assertThrows(IllegalArgumentException.class, builder::build); | ||
87 | } | ||
88 | } | ||
diff --git a/subprojects/store-query/src/test/java/tools/refinery/store/query/literal/CallLiteralTest.java b/subprojects/store-query/src/test/java/tools/refinery/store/query/literal/CallLiteralTest.java new file mode 100644 index 00000000..a01c6586 --- /dev/null +++ b/subprojects/store-query/src/test/java/tools/refinery/store/query/literal/CallLiteralTest.java | |||
@@ -0,0 +1,94 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.literal; | ||
7 | |||
8 | import org.junit.jupiter.api.Test; | ||
9 | import tools.refinery.store.query.Constraint; | ||
10 | import tools.refinery.store.query.term.NodeVariable; | ||
11 | import tools.refinery.store.query.term.Parameter; | ||
12 | import tools.refinery.store.query.term.ParameterDirection; | ||
13 | import tools.refinery.store.query.term.Variable; | ||
14 | |||
15 | import java.util.List; | ||
16 | import java.util.Set; | ||
17 | |||
18 | import static org.hamcrest.MatcherAssert.assertThat; | ||
19 | import static org.hamcrest.Matchers.containsInAnyOrder; | ||
20 | import static org.hamcrest.Matchers.empty; | ||
21 | import static org.junit.jupiter.api.Assertions.assertAll; | ||
22 | import static tools.refinery.store.query.literal.Literals.not; | ||
23 | |||
24 | class CallLiteralTest { | ||
25 | private static final NodeVariable p = Variable.of("p"); | ||
26 | private static final NodeVariable q = Variable.of("q"); | ||
27 | private static final NodeVariable r = Variable.of("r"); | ||
28 | private static final NodeVariable s = Variable.of("s"); | ||
29 | |||
30 | private static final Constraint fakeConstraint = new Constraint() { | ||
31 | @Override | ||
32 | public String name() { | ||
33 | return getClass().getName(); | ||
34 | } | ||
35 | |||
36 | @Override | ||
37 | public List<Parameter> getParameters() { | ||
38 | return List.of( | ||
39 | new Parameter(null, ParameterDirection.IN), | ||
40 | new Parameter(null, ParameterDirection.IN), | ||
41 | new Parameter(null, ParameterDirection.OUT), | ||
42 | new Parameter(null, ParameterDirection.OUT) | ||
43 | ); | ||
44 | } | ||
45 | }; | ||
46 | |||
47 | @Test | ||
48 | void notRepeatedPositiveDirectionTest() { | ||
49 | var literal = fakeConstraint.call(p, q, r, s); | ||
50 | assertAll( | ||
51 | () -> assertThat(literal.getOutputVariables(), containsInAnyOrder(r, s)), | ||
52 | () -> assertThat(literal.getInputVariables(Set.of()), containsInAnyOrder(p, q)), | ||
53 | () -> assertThat(literal.getInputVariables(Set.of(p, q, r)), containsInAnyOrder(p, q)), | ||
54 | () -> assertThat(literal.getPrivateVariables(Set.of()), empty()), | ||
55 | () -> assertThat(literal.getPrivateVariables(Set.of(p, q, r)), empty()) | ||
56 | ); | ||
57 | } | ||
58 | |||
59 | @Test | ||
60 | void notRepeatedNegativeDirectionTest() { | ||
61 | var literal = not(fakeConstraint.call(p, q, r, s)); | ||
62 | assertAll( | ||
63 | () -> assertThat(literal.getOutputVariables(), empty()), | ||
64 | () -> assertThat(literal.getInputVariables(Set.of()), containsInAnyOrder(p, q)), | ||
65 | () -> assertThat(literal.getInputVariables(Set.of(p, q, r)), containsInAnyOrder(p, q, r)), | ||
66 | () -> assertThat(literal.getPrivateVariables(Set.of()), containsInAnyOrder(r, s)), | ||
67 | () -> assertThat(literal.getPrivateVariables(Set.of(p, q, r)), containsInAnyOrder(s)) | ||
68 | ); | ||
69 | } | ||
70 | |||
71 | @Test | ||
72 | void repeatedPositiveDirectionTest() { | ||
73 | var literal = fakeConstraint.call(p, p, q, q); | ||
74 | assertAll( | ||
75 | () -> assertThat(literal.getOutputVariables(), containsInAnyOrder(q)), | ||
76 | () -> assertThat(literal.getInputVariables(Set.of()), containsInAnyOrder(p)), | ||
77 | () -> assertThat(literal.getInputVariables(Set.of(p, q)), containsInAnyOrder(p)), | ||
78 | () -> assertThat(literal.getPrivateVariables(Set.of()), empty()), | ||
79 | () -> assertThat(literal.getPrivateVariables(Set.of(p, q)), empty()) | ||
80 | ); | ||
81 | } | ||
82 | |||
83 | @Test | ||
84 | void repeatedNegativeDirectionTest() { | ||
85 | var literal = not(fakeConstraint.call(p, p, q, q)); | ||
86 | assertAll( | ||
87 | () -> assertThat(literal.getOutputVariables(), empty()), | ||
88 | () -> assertThat(literal.getInputVariables(Set.of()), containsInAnyOrder(p)), | ||
89 | () -> assertThat(literal.getInputVariables(Set.of(p, q)), containsInAnyOrder(p, q)), | ||
90 | () -> assertThat(literal.getPrivateVariables(Set.of()), containsInAnyOrder(q)), | ||
91 | () -> assertThat(literal.getPrivateVariables(Set.of(p, q)), empty()) | ||
92 | ); | ||
93 | } | ||
94 | } | ||
diff --git a/subprojects/store-query/src/test/java/tools/refinery/store/query/term/TermSubstitutionTest.java b/subprojects/store-query/src/test/java/tools/refinery/store/query/term/TermSubstitutionTest.java new file mode 100644 index 00000000..1cbc101a --- /dev/null +++ b/subprojects/store-query/src/test/java/tools/refinery/store/query/term/TermSubstitutionTest.java | |||
@@ -0,0 +1,97 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term; | ||
7 | |||
8 | import org.junit.jupiter.api.Assertions; | ||
9 | import org.junit.jupiter.params.ParameterizedTest; | ||
10 | import org.junit.jupiter.params.provider.Arguments; | ||
11 | import org.junit.jupiter.params.provider.MethodSource; | ||
12 | import tools.refinery.store.query.dnf.Dnf; | ||
13 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | ||
14 | import tools.refinery.store.query.substitution.Substitution; | ||
15 | import tools.refinery.store.query.term.bool.BoolTerms; | ||
16 | import tools.refinery.store.query.term.int_.IntTerms; | ||
17 | import tools.refinery.store.query.term.real.RealTerms; | ||
18 | import tools.refinery.store.query.term.uppercardinality.UpperCardinalityTerms; | ||
19 | import tools.refinery.store.representation.cardinality.UpperCardinality; | ||
20 | |||
21 | import java.util.List; | ||
22 | import java.util.stream.Stream; | ||
23 | |||
24 | class TermSubstitutionTest { | ||
25 | private final static DataVariable<Integer> intA = Variable.of("intA", Integer.class); | ||
26 | private final static DataVariable<Integer> intB = Variable.of("intB", Integer.class); | ||
27 | private final static DataVariable<Double> realA = Variable.of("realA", Double.class); | ||
28 | private final static DataVariable<Double> realB = Variable.of("realB", Double.class); | ||
29 | private final static DataVariable<Boolean> boolA = Variable.of("boolA", Boolean.class); | ||
30 | private final static DataVariable<Boolean> boolB = Variable.of("boolB", Boolean.class); | ||
31 | private final static DataVariable<UpperCardinality> upperCardinalityA = Variable.of("upperCardinalityA", | ||
32 | UpperCardinality.class); | ||
33 | private final static DataVariable<UpperCardinality> upperCardinalityB = Variable.of("upperCardinalityB", | ||
34 | UpperCardinality.class); | ||
35 | private final static Substitution substitution = Substitution.builder() | ||
36 | .put(intA, intB) | ||
37 | .put(intB, intA) | ||
38 | .put(realA, realB) | ||
39 | .put(realB, realA) | ||
40 | .put(boolA, boolB) | ||
41 | .put(boolB, boolA) | ||
42 | .put(upperCardinalityA, upperCardinalityB) | ||
43 | .put(upperCardinalityB, upperCardinalityA) | ||
44 | .build(); | ||
45 | |||
46 | @ParameterizedTest | ||
47 | @MethodSource | ||
48 | void substitutionTest(AnyTerm term) { | ||
49 | var substitutedTerm1 = term.substitute(substitution); | ||
50 | Assertions.assertNotEquals(term, substitutedTerm1, "Original term is not equal to substituted term"); | ||
51 | var helper = new LiteralEqualityHelper(Dnf::equals, List.of(), List.of()); | ||
52 | Assertions.assertTrue(term.equalsWithSubstitution(helper, substitutedTerm1), "Terms are equal by helper"); | ||
53 | // The {@link #substitution} is its own inverse. | ||
54 | var substitutedTerm2 = substitutedTerm1.substitute(substitution); | ||
55 | Assertions.assertEquals(term, substitutedTerm2, "Original term is not equal to back-substituted term"); | ||
56 | } | ||
57 | |||
58 | static Stream<Arguments> substitutionTest() { | ||
59 | return Stream.of( | ||
60 | Arguments.of(IntTerms.plus(intA)), | ||
61 | Arguments.of(IntTerms.minus(intA)), | ||
62 | Arguments.of(IntTerms.add(intA, intB)), | ||
63 | Arguments.of(IntTerms.sub(intA, intB)), | ||
64 | Arguments.of(IntTerms.mul(intA, intB)), | ||
65 | Arguments.of(IntTerms.div(intA, intB)), | ||
66 | Arguments.of(IntTerms.pow(intA, intB)), | ||
67 | Arguments.of(IntTerms.min(intA, intB)), | ||
68 | Arguments.of(IntTerms.max(intA, intB)), | ||
69 | Arguments.of(IntTerms.eq(intA, intB)), | ||
70 | Arguments.of(IntTerms.notEq(intA, intB)), | ||
71 | Arguments.of(IntTerms.less(intA, intB)), | ||
72 | Arguments.of(IntTerms.lessEq(intA, intB)), | ||
73 | Arguments.of(IntTerms.greater(intA, intB)), | ||
74 | Arguments.of(IntTerms.greaterEq(intA, intB)), | ||
75 | Arguments.of(IntTerms.asInt(realA)), | ||
76 | Arguments.of(RealTerms.plus(realA)), | ||
77 | Arguments.of(RealTerms.minus(realA)), | ||
78 | Arguments.of(RealTerms.add(realA, realB)), | ||
79 | Arguments.of(RealTerms.sub(realA, realB)), | ||
80 | Arguments.of(RealTerms.mul(realA, realB)), | ||
81 | Arguments.of(RealTerms.div(realA, realB)), | ||
82 | Arguments.of(RealTerms.pow(realA, realB)), | ||
83 | Arguments.of(RealTerms.min(realA, realB)), | ||
84 | Arguments.of(RealTerms.max(realA, realB)), | ||
85 | Arguments.of(RealTerms.asReal(intA)), | ||
86 | Arguments.of(BoolTerms.not(boolA)), | ||
87 | Arguments.of(BoolTerms.and(boolA, boolB)), | ||
88 | Arguments.of(BoolTerms.or(boolA, boolB)), | ||
89 | Arguments.of(BoolTerms.xor(boolA, boolB)), | ||
90 | Arguments.of(RealTerms.eq(realA, realB)), | ||
91 | Arguments.of(UpperCardinalityTerms.add(upperCardinalityA, upperCardinalityB)), | ||
92 | Arguments.of(UpperCardinalityTerms.mul(upperCardinalityA, upperCardinalityB)), | ||
93 | Arguments.of(UpperCardinalityTerms.min(upperCardinalityA, upperCardinalityB)), | ||
94 | Arguments.of(UpperCardinalityTerms.max(upperCardinalityA, upperCardinalityB)) | ||
95 | ); | ||
96 | } | ||
97 | } | ||
diff --git a/subprojects/store-query/src/test/java/tools/refinery/store/query/term/bool/BoolTermsEvaluateTest.java b/subprojects/store-query/src/test/java/tools/refinery/store/query/term/bool/BoolTermsEvaluateTest.java new file mode 100644 index 00000000..beff705e --- /dev/null +++ b/subprojects/store-query/src/test/java/tools/refinery/store/query/term/bool/BoolTermsEvaluateTest.java | |||
@@ -0,0 +1,75 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.bool; | ||
7 | |||
8 | import org.junit.jupiter.params.ParameterizedTest; | ||
9 | import org.junit.jupiter.params.provider.CsvSource; | ||
10 | import tools.refinery.store.query.valuation.Valuation; | ||
11 | |||
12 | import static org.hamcrest.MatcherAssert.assertThat; | ||
13 | import static org.hamcrest.Matchers.is; | ||
14 | |||
15 | class BoolTermsEvaluateTest { | ||
16 | @ParameterizedTest(name = "!{0} == {1}") | ||
17 | @CsvSource(value = { | ||
18 | "false, true", | ||
19 | "true, false", | ||
20 | "null, null" | ||
21 | }, nullValues = "null") | ||
22 | void notTest(Boolean a, Boolean result) { | ||
23 | var term = BoolTerms.not(BoolTerms.constant(a)); | ||
24 | assertThat(term.getType(), is(Boolean.class)); | ||
25 | assertThat(term.evaluate(Valuation.empty()), is(result)); | ||
26 | } | ||
27 | |||
28 | @ParameterizedTest(name = "{0} && {1} == {2}") | ||
29 | @CsvSource(value = { | ||
30 | "false, false, false", | ||
31 | "false, true, false", | ||
32 | "true, false, false", | ||
33 | "true, true, true", | ||
34 | "false, null, null", | ||
35 | "null, false, null", | ||
36 | "null, null, null" | ||
37 | }, nullValues = "null") | ||
38 | void andTest(Boolean a, Boolean b, Boolean result) { | ||
39 | var term = BoolTerms.and(BoolTerms.constant(a), BoolTerms.constant(b)); | ||
40 | assertThat(term.getType(), is(Boolean.class)); | ||
41 | assertThat(term.evaluate(Valuation.empty()), is(result)); | ||
42 | } | ||
43 | |||
44 | @ParameterizedTest(name = "{0} || {1} == {2}") | ||
45 | @CsvSource(value = { | ||
46 | "false, false, false", | ||
47 | "false, true, true", | ||
48 | "true, false, true", | ||
49 | "true, true, true", | ||
50 | "true, null, null", | ||
51 | "null, true, null", | ||
52 | "null, null, null" | ||
53 | }, nullValues = "null") | ||
54 | void orTest(Boolean a, Boolean b, Boolean result) { | ||
55 | var term = BoolTerms.or(BoolTerms.constant(a), BoolTerms.constant(b)); | ||
56 | assertThat(term.getType(), is(Boolean.class)); | ||
57 | assertThat(term.evaluate(Valuation.empty()), is(result)); | ||
58 | } | ||
59 | |||
60 | @ParameterizedTest(name = "{0} ^^ {1} == {2}") | ||
61 | @CsvSource(value = { | ||
62 | "false, false, false", | ||
63 | "false, true, true", | ||
64 | "true, false, true", | ||
65 | "true, true, false", | ||
66 | "false, null, null", | ||
67 | "null, false, null", | ||
68 | "null, null, null" | ||
69 | }, nullValues = "null") | ||
70 | void xorTest(Boolean a, Boolean b, Boolean result) { | ||
71 | var term = BoolTerms.xor(BoolTerms.constant(a), BoolTerms.constant(b)); | ||
72 | assertThat(term.getType(), is(Boolean.class)); | ||
73 | assertThat(term.evaluate(Valuation.empty()), is(result)); | ||
74 | } | ||
75 | } | ||
diff --git a/subprojects/store-query/src/test/java/tools/refinery/store/query/term/int_/IntTermsEvaluateTest.java b/subprojects/store-query/src/test/java/tools/refinery/store/query/term/int_/IntTermsEvaluateTest.java new file mode 100644 index 00000000..abe50d75 --- /dev/null +++ b/subprojects/store-query/src/test/java/tools/refinery/store/query/term/int_/IntTermsEvaluateTest.java | |||
@@ -0,0 +1,259 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.int_; | ||
7 | |||
8 | import org.junit.jupiter.params.ParameterizedTest; | ||
9 | import org.junit.jupiter.params.provider.Arguments; | ||
10 | import org.junit.jupiter.params.provider.CsvSource; | ||
11 | import org.junit.jupiter.params.provider.MethodSource; | ||
12 | import tools.refinery.store.query.term.real.RealTerms; | ||
13 | import tools.refinery.store.query.valuation.Valuation; | ||
14 | |||
15 | import java.util.stream.Stream; | ||
16 | |||
17 | import static org.hamcrest.Matchers.is; | ||
18 | import static org.hamcrest.MatcherAssert.assertThat; | ||
19 | |||
20 | class IntTermsEvaluateTest { | ||
21 | @ParameterizedTest(name = "+{0} == {1}") | ||
22 | @CsvSource(value = { | ||
23 | "2, 2", | ||
24 | "null, null" | ||
25 | }, nullValues = "null") | ||
26 | void plusTest(Integer a, Integer result) { | ||
27 | var term = IntTerms.plus(IntTerms.constant(a)); | ||
28 | assertThat(term.getType(), is(Integer.class)); | ||
29 | assertThat(term.evaluate(Valuation.empty()), is(result)); | ||
30 | } | ||
31 | |||
32 | @ParameterizedTest(name = "-{0} == {1}") | ||
33 | @CsvSource(value = { | ||
34 | "2, -2", | ||
35 | "null, null" | ||
36 | }, nullValues = "null") | ||
37 | void minusTest(Integer a, Integer result) { | ||
38 | var term = IntTerms.minus(IntTerms.constant(a)); | ||
39 | assertThat(term.getType(), is(Integer.class)); | ||
40 | assertThat(term.evaluate(Valuation.empty()), is(result)); | ||
41 | } | ||
42 | |||
43 | @ParameterizedTest(name = "{0} + {1} == {2}") | ||
44 | @CsvSource(value = { | ||
45 | "1, 2, 3", | ||
46 | "null, 2, null", | ||
47 | "1, null, null", | ||
48 | "null, null, null" | ||
49 | }, nullValues = "null") | ||
50 | void addTest(Integer a, Integer b, Integer result) { | ||
51 | var term = IntTerms.add(IntTerms.constant(a), IntTerms.constant(b)); | ||
52 | assertThat(term.getType(), is(Integer.class)); | ||
53 | assertThat(term.evaluate(Valuation.empty()), is(result)); | ||
54 | } | ||
55 | |||
56 | @ParameterizedTest(name = "{0} - {1} == {2}") | ||
57 | @CsvSource(value = { | ||
58 | "1, 3, -2", | ||
59 | "null, 3, null", | ||
60 | "1, null, null", | ||
61 | "null, null, null" | ||
62 | }, nullValues = "null") | ||
63 | void subTest(Integer a, Integer b, Integer result) { | ||
64 | var term = IntTerms.sub(IntTerms.constant(a), IntTerms.constant(b)); | ||
65 | assertThat(term.getType(), is(Integer.class)); | ||
66 | assertThat(term.evaluate(Valuation.empty()), is(result)); | ||
67 | } | ||
68 | |||
69 | @ParameterizedTest(name = "{0} * {1} == {2}") | ||
70 | @CsvSource(value = { | ||
71 | "2, 3, 6", | ||
72 | "null, 3, null", | ||
73 | "2, null, null", | ||
74 | "null, null, null" | ||
75 | }, nullValues = "null") | ||
76 | void mulTest(Integer a, Integer b, Integer result) { | ||
77 | var term = IntTerms.mul(IntTerms.constant(a), IntTerms.constant(b)); | ||
78 | assertThat(term.getType(), is(Integer.class)); | ||
79 | assertThat(term.evaluate(Valuation.empty()), is(result)); | ||
80 | } | ||
81 | |||
82 | @ParameterizedTest(name = "{0} * {1} == {2}") | ||
83 | @CsvSource(value = { | ||
84 | "6, 3, 2", | ||
85 | "7, 3, 2", | ||
86 | "6, 0, null", | ||
87 | "null, 3, null", | ||
88 | "6, null, null", | ||
89 | "null, null, null" | ||
90 | }, nullValues = "null") | ||
91 | void divTest(Integer a, Integer b, Integer result) { | ||
92 | var term = IntTerms.div(IntTerms.constant(a), IntTerms.constant(b)); | ||
93 | assertThat(term.getType(), is(Integer.class)); | ||
94 | assertThat(term.evaluate(Valuation.empty()), is(result)); | ||
95 | } | ||
96 | |||
97 | @ParameterizedTest(name = "{0} ** {1} == {2}") | ||
98 | @CsvSource(value = { | ||
99 | "1, 0, 1", | ||
100 | "1, 3, 1", | ||
101 | "1, -3, null", | ||
102 | "2, 0, 1", | ||
103 | "2, 2, 4", | ||
104 | "2, 3, 8", | ||
105 | "2, 4, 16", | ||
106 | "2, 5, 32", | ||
107 | "2, 6, 64", | ||
108 | "2, -3, null", | ||
109 | "null, 3, null", | ||
110 | "2, null, null", | ||
111 | "null, null, null" | ||
112 | }, nullValues = "null") | ||
113 | void powTest(Integer a, Integer b, Integer result) { | ||
114 | var term = IntTerms.pow(IntTerms.constant(a), IntTerms.constant(b)); | ||
115 | assertThat(term.getType(), is(Integer.class)); | ||
116 | assertThat(term.evaluate(Valuation.empty()), is(result)); | ||
117 | } | ||
118 | |||
119 | @ParameterizedTest(name = "min({0}, {1}) == {2}") | ||
120 | @CsvSource(value = { | ||
121 | "1, 2, 1", | ||
122 | "2, 1, 1", | ||
123 | "null, 2, null", | ||
124 | "1, null, null", | ||
125 | "null, null, null" | ||
126 | }, nullValues = "null") | ||
127 | void minTest(Integer a, Integer b, Integer result) { | ||
128 | var term = IntTerms.min(IntTerms.constant(a), IntTerms.constant(b)); | ||
129 | assertThat(term.getType(), is(Integer.class)); | ||
130 | assertThat(term.evaluate(Valuation.empty()), is(result)); | ||
131 | } | ||
132 | |||
133 | @ParameterizedTest(name = "max({0}, {1}) == {2}") | ||
134 | @CsvSource(value = { | ||
135 | "1, 2, 2", | ||
136 | "2, 1, 2", | ||
137 | "null, 2, null", | ||
138 | "1, null, null", | ||
139 | "null, null, null" | ||
140 | }, nullValues = "null") | ||
141 | void maxTest(Integer a, Integer b, Integer result) { | ||
142 | var term = IntTerms.max(IntTerms.constant(a), IntTerms.constant(b)); | ||
143 | assertThat(term.getType(), is(Integer.class)); | ||
144 | assertThat(term.evaluate(Valuation.empty()), is(result)); | ||
145 | } | ||
146 | |||
147 | @ParameterizedTest(name = "({0} == {1}) == {2}") | ||
148 | @CsvSource(value = { | ||
149 | "1, 1, true", | ||
150 | "1, 2, false", | ||
151 | "null, 1, null", | ||
152 | "1, null, null", | ||
153 | "null, null, null" | ||
154 | }, nullValues = "null") | ||
155 | void eqTest(Integer a, Integer b, Boolean result) { | ||
156 | var term = IntTerms.eq(IntTerms.constant(a), IntTerms.constant(b)); | ||
157 | assertThat(term.getType(), is(Boolean.class)); | ||
158 | assertThat(term.evaluate(Valuation.empty()), is(result)); | ||
159 | } | ||
160 | |||
161 | @ParameterizedTest(name = "({0} != {1}) == {2}") | ||
162 | @CsvSource(value = { | ||
163 | "1, 1, false", | ||
164 | "1, 2, true", | ||
165 | "null, 1, null", | ||
166 | "1, null, null", | ||
167 | "null, null, null" | ||
168 | }, nullValues = "null") | ||
169 | void notEqTest(Integer a, Integer b, Boolean result) { | ||
170 | var term = IntTerms.notEq(IntTerms.constant(a), IntTerms.constant(b)); | ||
171 | assertThat(term.getType(), is(Boolean.class)); | ||
172 | assertThat(term.evaluate(Valuation.empty()), is(result)); | ||
173 | } | ||
174 | |||
175 | @ParameterizedTest(name = "({0} < {1}) == {2}") | ||
176 | @CsvSource(value = { | ||
177 | "1, -2, false", | ||
178 | "1, 1, false", | ||
179 | "1, 2, true", | ||
180 | "null, 1, null", | ||
181 | "1, null, null", | ||
182 | "null, null, null" | ||
183 | }, nullValues = "null") | ||
184 | void lessTest(Integer a, Integer b, Boolean result) { | ||
185 | var term = IntTerms.less(IntTerms.constant(a), IntTerms.constant(b)); | ||
186 | assertThat(term.getType(), is(Boolean.class)); | ||
187 | assertThat(term.evaluate(Valuation.empty()), is(result)); | ||
188 | } | ||
189 | |||
190 | @ParameterizedTest(name = "({0} <= {1}) == {2}") | ||
191 | @CsvSource(value = { | ||
192 | "1, -2, false", | ||
193 | "1, 1, true", | ||
194 | "1, 2, true", | ||
195 | "null, 1, null", | ||
196 | "1, null, null", | ||
197 | "null, null, null" | ||
198 | }, nullValues = "null") | ||
199 | void lessEqTest(Integer a, Integer b, Boolean result) { | ||
200 | var term = IntTerms.lessEq(IntTerms.constant(a), IntTerms.constant(b)); | ||
201 | assertThat(term.getType(), is(Boolean.class)); | ||
202 | assertThat(term.evaluate(Valuation.empty()), is(result)); | ||
203 | } | ||
204 | |||
205 | @ParameterizedTest(name = "({0} > {1}) == {2}") | ||
206 | @CsvSource(value = { | ||
207 | "1, -2, true", | ||
208 | "1, 1, false", | ||
209 | "1, 2, false", | ||
210 | "null, 1, null", | ||
211 | "1, null, null", | ||
212 | "null, null, null" | ||
213 | }, nullValues = "null") | ||
214 | void greaterTest(Integer a, Integer b, Boolean result) { | ||
215 | var term = IntTerms.greater(IntTerms.constant(a), IntTerms.constant(b)); | ||
216 | assertThat(term.getType(), is(Boolean.class)); | ||
217 | assertThat(term.evaluate(Valuation.empty()), is(result)); | ||
218 | } | ||
219 | |||
220 | @ParameterizedTest(name = "({0} >= {1}) == {2}") | ||
221 | @CsvSource(value = { | ||
222 | "1, -2, true", | ||
223 | "1, 1, true", | ||
224 | "1, 2, false", | ||
225 | "null, 1, null", | ||
226 | "1, null, null", | ||
227 | "null, null, null" | ||
228 | }, nullValues = "null") | ||
229 | void greaterEqTest(Integer a, Integer b, Boolean result) { | ||
230 | var term = IntTerms.greaterEq(IntTerms.constant(a), IntTerms.constant(b)); | ||
231 | assertThat(term.getType(), is(Boolean.class)); | ||
232 | assertThat(term.evaluate(Valuation.empty()), is(result)); | ||
233 | } | ||
234 | |||
235 | @ParameterizedTest(name = "{0} as int == {1}") | ||
236 | @MethodSource | ||
237 | void asIntTest(Double a, Integer result) { | ||
238 | var term = IntTerms.asInt(RealTerms.constant(a)); | ||
239 | assertThat(term.getType(), is(Integer.class)); | ||
240 | assertThat(term.evaluate(Valuation.empty()), is(result)); | ||
241 | } | ||
242 | |||
243 | static Stream<Arguments> asIntTest() { | ||
244 | return Stream.of( | ||
245 | Arguments.of(2.0, 2), | ||
246 | Arguments.of(2.1, 2), | ||
247 | Arguments.of(2.9, 2), | ||
248 | Arguments.of(-2.0, -2), | ||
249 | Arguments.of(-2.1, -2), | ||
250 | Arguments.of(-2.9, -2), | ||
251 | Arguments.of(0.0, 0), | ||
252 | Arguments.of(-0.0, 0), | ||
253 | Arguments.of(Double.POSITIVE_INFINITY, Integer.MAX_VALUE), | ||
254 | Arguments.of(Double.NEGATIVE_INFINITY, Integer.MIN_VALUE), | ||
255 | Arguments.of(Double.NaN, null), | ||
256 | Arguments.of(null, null) | ||
257 | ); | ||
258 | } | ||
259 | } | ||
diff --git a/subprojects/store-query/src/test/java/tools/refinery/store/query/term/real/RealTermEvaluateTest.java b/subprojects/store-query/src/test/java/tools/refinery/store/query/term/real/RealTermEvaluateTest.java new file mode 100644 index 00000000..6a8eebf1 --- /dev/null +++ b/subprojects/store-query/src/test/java/tools/refinery/store/query/term/real/RealTermEvaluateTest.java | |||
@@ -0,0 +1,238 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.real; | ||
7 | |||
8 | import org.hamcrest.Matcher; | ||
9 | import org.junit.jupiter.params.ParameterizedTest; | ||
10 | import org.junit.jupiter.params.provider.CsvSource; | ||
11 | import tools.refinery.store.query.term.int_.IntTerms; | ||
12 | import tools.refinery.store.query.valuation.Valuation; | ||
13 | |||
14 | import static org.hamcrest.MatcherAssert.assertThat; | ||
15 | import static org.hamcrest.Matchers.*; | ||
16 | |||
17 | class RealTermEvaluateTest { | ||
18 | public static final double TOLERANCE = 1e-6; | ||
19 | |||
20 | private static Matcher<Double> closeToOrNull(Double expected) { | ||
21 | return expected == null ? nullValue(Double.class) : closeTo(expected, TOLERANCE); | ||
22 | } | ||
23 | |||
24 | @ParameterizedTest(name = "+{0} == {1}") | ||
25 | @CsvSource(value = { | ||
26 | "2.5, 2.5", | ||
27 | "null, null" | ||
28 | }, nullValues = "null") | ||
29 | void plusTest(Double a, Double result) { | ||
30 | var term = RealTerms.plus(RealTerms.constant(a)); | ||
31 | assertThat(term.getType(), is(Double.class)); | ||
32 | assertThat(term.evaluate(Valuation.empty()), closeToOrNull(result)); | ||
33 | } | ||
34 | |||
35 | @ParameterizedTest(name = "-{0} == {1}") | ||
36 | @CsvSource(value = { | ||
37 | "2.5, -2.5", | ||
38 | "null, null" | ||
39 | }, nullValues = "null") | ||
40 | void minusTest(Double a, Double result) { | ||
41 | var term = RealTerms.minus(RealTerms.constant(a)); | ||
42 | assertThat(term.getType(), is(Double.class)); | ||
43 | assertThat(term.evaluate(Valuation.empty()), closeToOrNull(result)); | ||
44 | } | ||
45 | |||
46 | @ParameterizedTest(name = "{0} + {1} == {2}") | ||
47 | @CsvSource(value = { | ||
48 | "1.2, 2.3, 3.5", | ||
49 | "null, 2.3, null", | ||
50 | "1.2, null, null", | ||
51 | "null, null, null" | ||
52 | }, nullValues = "null") | ||
53 | void addTest(Double a, Double b, Double result) { | ||
54 | var term = RealTerms.add(RealTerms.constant(a), RealTerms.constant(b)); | ||
55 | assertThat(term.getType(), is(Double.class)); | ||
56 | assertThat(term.evaluate(Valuation.empty()), closeToOrNull(result)); | ||
57 | } | ||
58 | |||
59 | @ParameterizedTest(name = "{0} - {1} == {2}") | ||
60 | @CsvSource(value = { | ||
61 | "1.2, 3.4, -2.2", | ||
62 | "null, 3.4, null", | ||
63 | "1.2, null, null", | ||
64 | "null, null, null" | ||
65 | }, nullValues = "null") | ||
66 | void subTest(Double a, Double b, Double result) { | ||
67 | var term = RealTerms.sub(RealTerms.constant(a), RealTerms.constant(b)); | ||
68 | assertThat(term.getType(), is(Double.class)); | ||
69 | assertThat(term.evaluate(Valuation.empty()), closeToOrNull(result)); | ||
70 | } | ||
71 | |||
72 | @ParameterizedTest(name = "{0} * {1} == {2}") | ||
73 | @CsvSource(value = { | ||
74 | "2.3, 3.4, 7.82", | ||
75 | "null, 3.4, null", | ||
76 | "2.3, null, null", | ||
77 | "null, null, null" | ||
78 | }, nullValues = "null") | ||
79 | void mulTest(Double a, Double b, Double result) { | ||
80 | var term = RealTerms.mul(RealTerms.constant(a), RealTerms.constant(b)); | ||
81 | assertThat(term.getType(), is(Double.class)); | ||
82 | assertThat(term.evaluate(Valuation.empty()), closeToOrNull(result)); | ||
83 | } | ||
84 | |||
85 | @ParameterizedTest(name = "{0} * {1} == {2}") | ||
86 | @CsvSource(value = { | ||
87 | "7.82, 3.4, 2.3", | ||
88 | "null, 3.4, null", | ||
89 | "7.82, null, null", | ||
90 | "null, null, null" | ||
91 | }, nullValues = "null") | ||
92 | void divTest(Double a, Double b, Double result) { | ||
93 | var term = RealTerms.div(RealTerms.constant(a), RealTerms.constant(b)); | ||
94 | assertThat(term.getType(), is(Double.class)); | ||
95 | assertThat(term.evaluate(Valuation.empty()), closeToOrNull(result)); | ||
96 | } | ||
97 | |||
98 | @ParameterizedTest(name = "{0} ** {1} == {2}") | ||
99 | @CsvSource(value = { | ||
100 | "2.0, 6.0, 64.0", | ||
101 | "null, 6.0, null", | ||
102 | "2.0, null, null", | ||
103 | "null, null, null" | ||
104 | }, nullValues = "null") | ||
105 | void powTest(Double a, Double b, Double result) { | ||
106 | var term = RealTerms.pow(RealTerms.constant(a), RealTerms.constant(b)); | ||
107 | assertThat(term.getType(), is(Double.class)); | ||
108 | assertThat(term.evaluate(Valuation.empty()), closeToOrNull(result)); | ||
109 | } | ||
110 | |||
111 | @ParameterizedTest(name = "min({0}, {1}) == {2}") | ||
112 | @CsvSource(value = { | ||
113 | "1.5, 2.7, 1.5", | ||
114 | "2.7, 1.5, 1.5", | ||
115 | "null, 2.7, null", | ||
116 | "1.5, null, null", | ||
117 | "null, null, null" | ||
118 | }, nullValues = "null") | ||
119 | void minTest(Double a, Double b, Double result) { | ||
120 | var term = RealTerms.min(RealTerms.constant(a), RealTerms.constant(b)); | ||
121 | assertThat(term.getType(), is(Double.class)); | ||
122 | assertThat(term.evaluate(Valuation.empty()), closeToOrNull(result)); | ||
123 | } | ||
124 | |||
125 | @ParameterizedTest(name = "max({0}, {1}) == {2}") | ||
126 | @CsvSource(value = { | ||
127 | "1.5, 2.7, 2.7", | ||
128 | "2.7, 1.7, 2.7", | ||
129 | "null, 2.7, null", | ||
130 | "1.5, null, null", | ||
131 | "null, null, null" | ||
132 | }, nullValues = "null") | ||
133 | void maxTest(Double a, Double b, Double result) { | ||
134 | var term = RealTerms.max(RealTerms.constant(a), RealTerms.constant(b)); | ||
135 | assertThat(term.getType(), is(Double.class)); | ||
136 | assertThat(term.evaluate(Valuation.empty()), closeToOrNull(result)); | ||
137 | } | ||
138 | |||
139 | @ParameterizedTest(name = "({0} == {1}) == {2}") | ||
140 | @CsvSource(value = { | ||
141 | "1.5, 1.5, true", | ||
142 | "1.5, 2.7, false", | ||
143 | "null, 1.5, null", | ||
144 | "1.5, null, null", | ||
145 | "null, null, null" | ||
146 | }, nullValues = "null") | ||
147 | void eqTest(Double a, Double b, Boolean result) { | ||
148 | var term = RealTerms.eq(RealTerms.constant(a), RealTerms.constant(b)); | ||
149 | assertThat(term.getType(), is(Boolean.class)); | ||
150 | assertThat(term.evaluate(Valuation.empty()), is(result)); | ||
151 | } | ||
152 | |||
153 | @ParameterizedTest(name = "({0} != {1}) == {2}") | ||
154 | @CsvSource(value = { | ||
155 | "1.5, 1.5, false", | ||
156 | "1.5, 2.7, true", | ||
157 | "null, 1.5, null", | ||
158 | "1.5, null, null", | ||
159 | "null, null, null" | ||
160 | }, nullValues = "null") | ||
161 | void notEqTest(Double a, Double b, Boolean result) { | ||
162 | var term = RealTerms.notEq(RealTerms.constant(a), RealTerms.constant(b)); | ||
163 | assertThat(term.getType(), is(Boolean.class)); | ||
164 | assertThat(term.evaluate(Valuation.empty()), is(result)); | ||
165 | } | ||
166 | |||
167 | @ParameterizedTest(name = "({0} < {1}) == {2}") | ||
168 | @CsvSource(value = { | ||
169 | "1.5, -2.7, false", | ||
170 | "1.5, 1.5, false", | ||
171 | "1.5, 2.7, true", | ||
172 | "null, 1.5, null", | ||
173 | "1.5, null, null", | ||
174 | "null, null, null" | ||
175 | }, nullValues = "null") | ||
176 | void lessTest(Double a, Double b, Boolean result) { | ||
177 | var term = RealTerms.less(RealTerms.constant(a), RealTerms.constant(b)); | ||
178 | assertThat(term.getType(), is(Boolean.class)); | ||
179 | assertThat(term.evaluate(Valuation.empty()), is(result)); | ||
180 | } | ||
181 | |||
182 | @ParameterizedTest(name = "({0} <= {1}) == {2}") | ||
183 | @CsvSource(value = { | ||
184 | "1.5, -2.7, false", | ||
185 | "1.5, 1.5, true", | ||
186 | "1.5, 2.7, true", | ||
187 | "null, 1.5, null", | ||
188 | "1.5, null, null", | ||
189 | "null, null, null" | ||
190 | }, nullValues = "null") | ||
191 | void lessEqTest(Double a, Double b, Boolean result) { | ||
192 | var term = RealTerms.lessEq(RealTerms.constant(a), RealTerms.constant(b)); | ||
193 | assertThat(term.getType(), is(Boolean.class)); | ||
194 | assertThat(term.evaluate(Valuation.empty()), is(result)); | ||
195 | } | ||
196 | |||
197 | @ParameterizedTest(name = "({0} > {1}) == {2}") | ||
198 | @CsvSource(value = { | ||
199 | "1.5, -2.7, true", | ||
200 | "1.5, 1.5, false", | ||
201 | "1.5, 2.7, false", | ||
202 | "null, 1.5, null", | ||
203 | "1.5, null, null", | ||
204 | "null, null, null" | ||
205 | }, nullValues = "null") | ||
206 | void greaterTest(Double a, Double b, Boolean result) { | ||
207 | var term = RealTerms.greater(RealTerms.constant(a), RealTerms.constant(b)); | ||
208 | assertThat(term.getType(), is(Boolean.class)); | ||
209 | assertThat(term.evaluate(Valuation.empty()), is(result)); | ||
210 | } | ||
211 | |||
212 | @ParameterizedTest(name = "({0} >= {1}) == {2}") | ||
213 | @CsvSource(value = { | ||
214 | "1.5, -2.7, true", | ||
215 | "1.5, 1.5, true", | ||
216 | "1.5, 2.7, false", | ||
217 | "null, 1.5, null", | ||
218 | "1.5, null, null", | ||
219 | "null, null, null" | ||
220 | }, nullValues = "null") | ||
221 | void greaterEqTest(Double a, Double b, Boolean result) { | ||
222 | var term = RealTerms.greaterEq(RealTerms.constant(a), RealTerms.constant(b)); | ||
223 | assertThat(term.getType(), is(Boolean.class)); | ||
224 | assertThat(term.evaluate(Valuation.empty()), is(result)); | ||
225 | } | ||
226 | |||
227 | @ParameterizedTest(name = "{0} as real == {1}") | ||
228 | @CsvSource(value = { | ||
229 | "0, 0.0", | ||
230 | "5, 5.0", | ||
231 | "null, null" | ||
232 | }, nullValues = "null") | ||
233 | void asRealTest(Integer a, Double result) { | ||
234 | var term = RealTerms.asReal(IntTerms.constant(a)); | ||
235 | assertThat(term.getType(), is(Double.class)); | ||
236 | assertThat(term.evaluate(Valuation.empty()), closeToOrNull(result)); | ||
237 | } | ||
238 | } | ||
diff --git a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/internal/cardinality/UpperCardinalitySumAggregationOperatorStreamTest.java b/subprojects/store-query/src/test/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalitySumAggregatorStreamTest.java index c529117e..31baf36e 100644 --- a/subprojects/store-query-viatra/src/test/java/tools/refinery/store/query/viatra/internal/cardinality/UpperCardinalitySumAggregationOperatorStreamTest.java +++ b/subprojects/store-query/src/test/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalitySumAggregatorStreamTest.java | |||
@@ -1,4 +1,9 @@ | |||
1 | package tools.refinery.store.query.viatra.internal.cardinality; | 1 | /* |
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.uppercardinality; | ||
2 | 7 | ||
3 | import org.junit.jupiter.params.ParameterizedTest; | 8 | import org.junit.jupiter.params.ParameterizedTest; |
4 | import org.junit.jupiter.params.provider.Arguments; | 9 | import org.junit.jupiter.params.provider.Arguments; |
@@ -10,14 +15,14 @@ import java.util.List; | |||
10 | import java.util.stream.Stream; | 15 | import java.util.stream.Stream; |
11 | 16 | ||
12 | import static org.hamcrest.MatcherAssert.assertThat; | 17 | import static org.hamcrest.MatcherAssert.assertThat; |
13 | import static org.hamcrest.Matchers.equalTo; | 18 | import static org.hamcrest.Matchers.is; |
14 | 19 | ||
15 | class UpperCardinalitySumAggregationOperatorStreamTest { | 20 | class UpperCardinalitySumAggregatorStreamTest { |
16 | @ParameterizedTest | 21 | @ParameterizedTest |
17 | @MethodSource | 22 | @MethodSource |
18 | void testStream(List<UpperCardinality> list, UpperCardinality expected) { | 23 | void testStream(List<UpperCardinality> list, UpperCardinality expected) { |
19 | var result = UpperCardinalitySumAggregationOperator.INSTANCE.aggregateStream(list.stream()); | 24 | var result = UpperCardinalitySumAggregator.INSTANCE.aggregateStream(list.stream()); |
20 | assertThat(result, equalTo(expected)); | 25 | assertThat(result, is(expected)); |
21 | } | 26 | } |
22 | 27 | ||
23 | static Stream<Arguments> testStream() { | 28 | static Stream<Arguments> testStream() { |
diff --git a/subprojects/store-query/src/test/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalitySumAggregatorTest.java b/subprojects/store-query/src/test/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalitySumAggregatorTest.java new file mode 100644 index 00000000..780cd0ab --- /dev/null +++ b/subprojects/store-query/src/test/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalitySumAggregatorTest.java | |||
@@ -0,0 +1,80 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.uppercardinality; | ||
7 | |||
8 | import org.junit.jupiter.api.BeforeEach; | ||
9 | import org.junit.jupiter.api.Test; | ||
10 | import tools.refinery.store.query.term.StatefulAggregate; | ||
11 | import tools.refinery.store.representation.cardinality.UpperCardinalities; | ||
12 | import tools.refinery.store.representation.cardinality.UpperCardinality; | ||
13 | |||
14 | import static org.hamcrest.MatcherAssert.assertThat; | ||
15 | import static org.hamcrest.Matchers.is; | ||
16 | |||
17 | class UpperCardinalitySumAggregatorTest { | ||
18 | private StatefulAggregate<UpperCardinality, UpperCardinality> accumulator; | ||
19 | |||
20 | @BeforeEach | ||
21 | void beforeEach() { | ||
22 | accumulator = UpperCardinalitySumAggregator.INSTANCE.createEmptyAggregate(); | ||
23 | } | ||
24 | |||
25 | @Test | ||
26 | void emptyAggregationTest() { | ||
27 | assertThat(accumulator.getResult(), is(UpperCardinality.of(0))); | ||
28 | } | ||
29 | |||
30 | @Test | ||
31 | void singleBoundedTest() { | ||
32 | accumulator.add(UpperCardinality.of(3)); | ||
33 | assertThat(accumulator.getResult(), is(UpperCardinality.of(3))); | ||
34 | } | ||
35 | |||
36 | @Test | ||
37 | void multipleBoundedTest() { | ||
38 | accumulator.add(UpperCardinality.of(2)); | ||
39 | accumulator.add(UpperCardinality.of(3)); | ||
40 | assertThat(accumulator.getResult(), is(UpperCardinality.of(5))); | ||
41 | } | ||
42 | |||
43 | @Test | ||
44 | void singleUnboundedTest() { | ||
45 | accumulator.add(UpperCardinalities.UNBOUNDED); | ||
46 | assertThat(accumulator.getResult(), is(UpperCardinalities.UNBOUNDED)); | ||
47 | } | ||
48 | |||
49 | @Test | ||
50 | void multipleUnboundedTest() { | ||
51 | accumulator.add(UpperCardinalities.UNBOUNDED); | ||
52 | accumulator.add(UpperCardinalities.UNBOUNDED); | ||
53 | assertThat(accumulator.getResult(), is(UpperCardinalities.UNBOUNDED)); | ||
54 | } | ||
55 | |||
56 | @Test | ||
57 | void removeBoundedTest() { | ||
58 | accumulator.add(UpperCardinality.of(2)); | ||
59 | accumulator.add(UpperCardinality.of(3)); | ||
60 | accumulator.remove(UpperCardinality.of(2)); | ||
61 | assertThat(accumulator.getResult(), is(UpperCardinality.of(3))); | ||
62 | } | ||
63 | |||
64 | @Test | ||
65 | void removeAllUnboundedTest() { | ||
66 | accumulator.add(UpperCardinalities.UNBOUNDED); | ||
67 | accumulator.add(UpperCardinality.of(3)); | ||
68 | accumulator.remove(UpperCardinalities.UNBOUNDED); | ||
69 | assertThat(accumulator.getResult(), is(UpperCardinality.of(3))); | ||
70 | } | ||
71 | |||
72 | @Test | ||
73 | void removeSomeUnboundedTest() { | ||
74 | accumulator.add(UpperCardinalities.UNBOUNDED); | ||
75 | accumulator.add(UpperCardinalities.UNBOUNDED); | ||
76 | accumulator.add(UpperCardinality.of(3)); | ||
77 | accumulator.remove(UpperCardinalities.UNBOUNDED); | ||
78 | assertThat(accumulator.getResult(), is(UpperCardinalities.UNBOUNDED)); | ||
79 | } | ||
80 | } | ||
diff --git a/subprojects/store-query/src/test/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityTermsEvaluateTest.java b/subprojects/store-query/src/test/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityTermsEvaluateTest.java new file mode 100644 index 00000000..9d0f3bde --- /dev/null +++ b/subprojects/store-query/src/test/java/tools/refinery/store/query/term/uppercardinality/UpperCardinalityTermsEvaluateTest.java | |||
@@ -0,0 +1,104 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.term.uppercardinality; | ||
7 | |||
8 | import org.junit.jupiter.params.ParameterizedTest; | ||
9 | import org.junit.jupiter.params.provider.Arguments; | ||
10 | import org.junit.jupiter.params.provider.MethodSource; | ||
11 | import tools.refinery.store.query.valuation.Valuation; | ||
12 | import tools.refinery.store.representation.cardinality.UpperCardinalities; | ||
13 | import tools.refinery.store.representation.cardinality.UpperCardinality; | ||
14 | |||
15 | import java.util.stream.Stream; | ||
16 | |||
17 | import static org.hamcrest.MatcherAssert.assertThat; | ||
18 | import static org.hamcrest.Matchers.is; | ||
19 | |||
20 | class UpperCardinalityTermsEvaluateTest { | ||
21 | @ParameterizedTest(name = "min({0}, {1}) == {2}") | ||
22 | @MethodSource | ||
23 | void minTest(UpperCardinality a, UpperCardinality b, UpperCardinality expected) { | ||
24 | var term = UpperCardinalityTerms.min(UpperCardinalityTerms.constant(a), UpperCardinalityTerms.constant(b)); | ||
25 | assertThat(term.getType(), is(UpperCardinality.class)); | ||
26 | assertThat(term.evaluate(Valuation.empty()), is(expected)); | ||
27 | } | ||
28 | |||
29 | static Stream<Arguments> minTest() { | ||
30 | return Stream.of( | ||
31 | Arguments.of(UpperCardinality.of(0), UpperCardinality.of(0), UpperCardinality.of(0)), | ||
32 | Arguments.of(UpperCardinality.of(0), UpperCardinality.of(1), UpperCardinality.of(0)), | ||
33 | Arguments.of(UpperCardinality.of(1), UpperCardinality.of(0), UpperCardinality.of(0)), | ||
34 | Arguments.of(UpperCardinality.of(0), UpperCardinalities.UNBOUNDED, UpperCardinality.of(0)), | ||
35 | Arguments.of(UpperCardinalities.UNBOUNDED, UpperCardinality.of(0), UpperCardinality.of(0)), | ||
36 | Arguments.of(UpperCardinalities.UNBOUNDED, UpperCardinalities.UNBOUNDED, UpperCardinalities.UNBOUNDED), | ||
37 | Arguments.of(UpperCardinality.of(1), null, null), | ||
38 | Arguments.of(null, UpperCardinality.of(1), null), | ||
39 | Arguments.of(null, null, null) | ||
40 | ); | ||
41 | } | ||
42 | |||
43 | @ParameterizedTest(name = "max({0}, {1}) == {2}") | ||
44 | @MethodSource | ||
45 | void maxTest(UpperCardinality a, UpperCardinality b, UpperCardinality expected) { | ||
46 | var term = UpperCardinalityTerms.max(UpperCardinalityTerms.constant(a), UpperCardinalityTerms.constant(b)); | ||
47 | assertThat(term.getType(), is(UpperCardinality.class)); | ||
48 | assertThat(term.evaluate(Valuation.empty()), is(expected)); | ||
49 | } | ||
50 | |||
51 | static Stream<Arguments> maxTest() { | ||
52 | return Stream.of( | ||
53 | Arguments.of(UpperCardinality.of(0), UpperCardinality.of(0), UpperCardinality.of(0)), | ||
54 | Arguments.of(UpperCardinality.of(0), UpperCardinality.of(1), UpperCardinality.of(1)), | ||
55 | Arguments.of(UpperCardinality.of(1), UpperCardinality.of(0), UpperCardinality.of(1)), | ||
56 | Arguments.of(UpperCardinality.of(0), UpperCardinalities.UNBOUNDED, UpperCardinalities.UNBOUNDED), | ||
57 | Arguments.of(UpperCardinalities.UNBOUNDED, UpperCardinality.of(0), UpperCardinalities.UNBOUNDED), | ||
58 | Arguments.of(UpperCardinalities.UNBOUNDED, UpperCardinalities.UNBOUNDED, UpperCardinalities.UNBOUNDED), | ||
59 | Arguments.of(UpperCardinality.of(1), null, null), | ||
60 | Arguments.of(null, UpperCardinality.of(1), null), | ||
61 | Arguments.of(null, null, null) | ||
62 | ); | ||
63 | } | ||
64 | |||
65 | @ParameterizedTest(name = "{0} + {1} == {2}") | ||
66 | @MethodSource | ||
67 | void addTest(UpperCardinality a, UpperCardinality b, UpperCardinality expected) { | ||
68 | var term = UpperCardinalityTerms.add(UpperCardinalityTerms.constant(a), UpperCardinalityTerms.constant(b)); | ||
69 | assertThat(term.getType(), is(UpperCardinality.class)); | ||
70 | assertThat(term.evaluate(Valuation.empty()), is(expected)); | ||
71 | } | ||
72 | |||
73 | static Stream<Arguments> addTest() { | ||
74 | return Stream.of( | ||
75 | Arguments.of(UpperCardinality.of(2), UpperCardinality.of(3), UpperCardinality.of(5)), | ||
76 | Arguments.of(UpperCardinality.of(2), UpperCardinalities.UNBOUNDED, UpperCardinalities.UNBOUNDED), | ||
77 | Arguments.of(UpperCardinalities.UNBOUNDED, UpperCardinality.of(2), UpperCardinalities.UNBOUNDED), | ||
78 | Arguments.of(UpperCardinalities.UNBOUNDED, UpperCardinalities.UNBOUNDED, UpperCardinalities.UNBOUNDED), | ||
79 | Arguments.of(UpperCardinality.of(1), null, null), | ||
80 | Arguments.of(null, UpperCardinality.of(1), null), | ||
81 | Arguments.of(null, null, null) | ||
82 | ); | ||
83 | } | ||
84 | |||
85 | @ParameterizedTest(name = "{0} * {1} == {2}") | ||
86 | @MethodSource | ||
87 | void mulTest(UpperCardinality a, UpperCardinality b, UpperCardinality expected) { | ||
88 | var term = UpperCardinalityTerms.mul(UpperCardinalityTerms.constant(a), UpperCardinalityTerms.constant(b)); | ||
89 | assertThat(term.getType(), is(UpperCardinality.class)); | ||
90 | assertThat(term.evaluate(Valuation.empty()), is(expected)); | ||
91 | } | ||
92 | |||
93 | static Stream<Arguments> mulTest() { | ||
94 | return Stream.of( | ||
95 | Arguments.of(UpperCardinality.of(2), UpperCardinality.of(3), UpperCardinality.of(6)), | ||
96 | Arguments.of(UpperCardinality.of(2), UpperCardinalities.UNBOUNDED, UpperCardinalities.UNBOUNDED), | ||
97 | Arguments.of(UpperCardinalities.UNBOUNDED, UpperCardinality.of(2), UpperCardinalities.UNBOUNDED), | ||
98 | Arguments.of(UpperCardinalities.UNBOUNDED, UpperCardinalities.UNBOUNDED, UpperCardinalities.UNBOUNDED), | ||
99 | Arguments.of(UpperCardinality.of(1), null, null), | ||
100 | Arguments.of(null, UpperCardinality.of(1), null), | ||
101 | Arguments.of(null, null, null) | ||
102 | ); | ||
103 | } | ||
104 | } | ||
diff --git a/subprojects/store-query/src/test/java/tools/refinery/store/query/tests/StructurallyEqualToRawTest.java b/subprojects/store-query/src/test/java/tools/refinery/store/query/tests/StructurallyEqualToRawTest.java new file mode 100644 index 00000000..d447e99c --- /dev/null +++ b/subprojects/store-query/src/test/java/tools/refinery/store/query/tests/StructurallyEqualToRawTest.java | |||
@@ -0,0 +1,159 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.tests; | ||
7 | |||
8 | import org.junit.jupiter.api.Test; | ||
9 | import tools.refinery.store.query.dnf.Dnf; | ||
10 | import tools.refinery.store.query.dnf.SymbolicParameter; | ||
11 | import tools.refinery.store.query.term.NodeVariable; | ||
12 | import tools.refinery.store.query.term.ParameterDirection; | ||
13 | import tools.refinery.store.query.term.Variable; | ||
14 | import tools.refinery.store.query.view.AnySymbolView; | ||
15 | import tools.refinery.store.query.view.KeyOnlyView; | ||
16 | import tools.refinery.store.representation.Symbol; | ||
17 | |||
18 | import java.util.List; | ||
19 | |||
20 | import static org.hamcrest.CoreMatchers.containsString; | ||
21 | import static org.hamcrest.MatcherAssert.assertThat; | ||
22 | import static org.hamcrest.Matchers.allOf; | ||
23 | import static org.junit.jupiter.api.Assertions.assertThrows; | ||
24 | import static tools.refinery.store.query.tests.QueryMatchers.structurallyEqualTo; | ||
25 | |||
26 | class StructurallyEqualToRawTest { | ||
27 | private static final Symbol<Boolean> person = Symbol.of("Person", 1); | ||
28 | private static final Symbol<Boolean> friend = Symbol.of("friend", 2); | ||
29 | private static final AnySymbolView personView = new KeyOnlyView<>(person); | ||
30 | private static final AnySymbolView friendView = new KeyOnlyView<>(friend); | ||
31 | private static final NodeVariable p = Variable.of("p"); | ||
32 | private static final NodeVariable q = Variable.of("q"); | ||
33 | |||
34 | @Test | ||
35 | void flatEqualsTest() { | ||
36 | var actual = Dnf.builder("Actual").parameters(p).clause(personView.call(p)).build(); | ||
37 | |||
38 | assertThat(actual, structurallyEqualTo( | ||
39 | List.of(new SymbolicParameter(q, ParameterDirection.OUT)), | ||
40 | List.of(List.of(personView.call(q))) | ||
41 | )); | ||
42 | } | ||
43 | |||
44 | @Test | ||
45 | void flatNotEqualsTest() { | ||
46 | var actual = Dnf.builder("Actual").parameters(p).clause(friendView.call(p, q)).build(); | ||
47 | |||
48 | var assertion = structurallyEqualTo( | ||
49 | List.of(new SymbolicParameter(q, ParameterDirection.OUT)), | ||
50 | List.of(List.of(friendView.call(q, q))) | ||
51 | ); | ||
52 | assertThrows(AssertionError.class, () -> assertThat(actual, assertion)); | ||
53 | } | ||
54 | |||
55 | @Test | ||
56 | void deepEqualsTest() { | ||
57 | var actual = Dnf.builder("Actual").parameters(q).clause( | ||
58 | Dnf.builder("Actual2").parameters(p).clause(personView.call(p)).build().call(q) | ||
59 | ).build(); | ||
60 | |||
61 | assertThat(actual, structurallyEqualTo( | ||
62 | List.of(new SymbolicParameter(q, ParameterDirection.OUT)), | ||
63 | List.of( | ||
64 | List.of( | ||
65 | Dnf.builder("Expected2").parameters(p).clause(personView.call(p)).build().call(q) | ||
66 | ) | ||
67 | ) | ||
68 | )); | ||
69 | } | ||
70 | |||
71 | @Test | ||
72 | void deepNotEqualsTest() { | ||
73 | var actual = Dnf.builder("Actual").parameter(q).clause( | ||
74 | Dnf.builder("Actual2").parameters(p).clause(friendView.call(p, q)).build().call(q) | ||
75 | ).build(); | ||
76 | |||
77 | var assertion = structurallyEqualTo( | ||
78 | List.of(new SymbolicParameter(q, ParameterDirection.OUT)), | ||
79 | List.of( | ||
80 | List.of( | ||
81 | Dnf.builder("Expected2") | ||
82 | .parameters(p) | ||
83 | .clause(friendView.call(p, p)) | ||
84 | .build() | ||
85 | .call(q) | ||
86 | ) | ||
87 | ) | ||
88 | ); | ||
89 | var error = assertThrows(AssertionError.class, () -> assertThat(actual, assertion)); | ||
90 | assertThat(error.getMessage(), allOf(containsString("Expected2"), containsString("Actual2"))); | ||
91 | } | ||
92 | |||
93 | @Test | ||
94 | void parameterListLengthMismatchTest() { | ||
95 | var actual = Dnf.builder("Actual").parameters(p, q).clause( | ||
96 | friendView.call(p, q) | ||
97 | ).build(); | ||
98 | |||
99 | var assertion = structurallyEqualTo( | ||
100 | List.of(new SymbolicParameter(p, ParameterDirection.OUT)), | ||
101 | List.of(List.of(friendView.call(p, p))) | ||
102 | ); | ||
103 | |||
104 | assertThrows(AssertionError.class, () -> assertThat(actual, assertion)); | ||
105 | } | ||
106 | |||
107 | @Test | ||
108 | void parameterDirectionMismatchTest() { | ||
109 | var actual = Dnf.builder("Actual").parameter(p, ParameterDirection.IN).clause( | ||
110 | personView.call(p) | ||
111 | ).build(); | ||
112 | |||
113 | var assertion = structurallyEqualTo( | ||
114 | List.of(new SymbolicParameter(p, ParameterDirection.OUT)), | ||
115 | List.of(List.of(personView.call(p))) | ||
116 | ); | ||
117 | |||
118 | assertThrows(AssertionError.class, () -> assertThat(actual, assertion)); | ||
119 | } | ||
120 | |||
121 | @Test | ||
122 | void clauseCountMismatchTest() { | ||
123 | var actual = Dnf.builder("Actual").parameters(p, q).clause( | ||
124 | friendView.call(p, q) | ||
125 | ).build(); | ||
126 | |||
127 | var assertion = structurallyEqualTo( | ||
128 | List.of( | ||
129 | new SymbolicParameter(p, ParameterDirection.OUT), | ||
130 | new SymbolicParameter(q, ParameterDirection.OUT) | ||
131 | ), | ||
132 | List.of( | ||
133 | List.of(friendView.call(p, q)), | ||
134 | List.of(friendView.call(q, p)) | ||
135 | ) | ||
136 | ); | ||
137 | |||
138 | assertThrows(AssertionError.class, () -> assertThat(actual, assertion)); | ||
139 | } | ||
140 | |||
141 | @Test | ||
142 | void literalCountMismatchTest() { | ||
143 | var actual = Dnf.builder("Actual").parameters(p, q).clause( | ||
144 | friendView.call(p, q) | ||
145 | ).build(); | ||
146 | |||
147 | var assertion = structurallyEqualTo( | ||
148 | List.of( | ||
149 | new SymbolicParameter(p, ParameterDirection.OUT), | ||
150 | new SymbolicParameter(q, ParameterDirection.OUT) | ||
151 | ), | ||
152 | List.of( | ||
153 | List.of(friendView.call(p, q), friendView.call(q, p)) | ||
154 | ) | ||
155 | ); | ||
156 | |||
157 | assertThrows(AssertionError.class, () -> assertThat(actual, assertion)); | ||
158 | } | ||
159 | } | ||
diff --git a/subprojects/store-query/src/test/java/tools/refinery/store/query/tests/StructurallyEqualToTest.java b/subprojects/store-query/src/test/java/tools/refinery/store/query/tests/StructurallyEqualToTest.java index a61e2b65..f716b805 100644 --- a/subprojects/store-query/src/test/java/tools/refinery/store/query/tests/StructurallyEqualToTest.java +++ b/subprojects/store-query/src/test/java/tools/refinery/store/query/tests/StructurallyEqualToTest.java | |||
@@ -1,9 +1,17 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.tests; | 6 | package tools.refinery.store.query.tests; |
2 | 7 | ||
3 | import org.junit.jupiter.api.Test; | 8 | import org.junit.jupiter.api.Test; |
4 | import tools.refinery.store.query.dnf.Dnf; | 9 | import tools.refinery.store.query.dnf.Dnf; |
10 | import tools.refinery.store.query.term.NodeVariable; | ||
11 | import tools.refinery.store.query.term.ParameterDirection; | ||
5 | import tools.refinery.store.query.term.Variable; | 12 | import tools.refinery.store.query.term.Variable; |
6 | import tools.refinery.store.query.view.KeyOnlyRelationView; | 13 | import tools.refinery.store.query.view.AnySymbolView; |
14 | import tools.refinery.store.query.view.KeyOnlyView; | ||
7 | import tools.refinery.store.representation.Symbol; | 15 | import tools.refinery.store.representation.Symbol; |
8 | 16 | ||
9 | import static org.hamcrest.CoreMatchers.containsString; | 17 | import static org.hamcrest.CoreMatchers.containsString; |
@@ -12,13 +20,15 @@ import static org.junit.jupiter.api.Assertions.assertThrows; | |||
12 | import static tools.refinery.store.query.tests.QueryMatchers.structurallyEqualTo; | 20 | import static tools.refinery.store.query.tests.QueryMatchers.structurallyEqualTo; |
13 | 21 | ||
14 | class StructurallyEqualToTest { | 22 | class StructurallyEqualToTest { |
23 | private static final Symbol<Boolean> person = Symbol.of("Person", 1); | ||
24 | private static final Symbol<Boolean> friend = Symbol.of("friend", 2); | ||
25 | private static final AnySymbolView personView = new KeyOnlyView<>(person); | ||
26 | private static final AnySymbolView friendView = new KeyOnlyView<>(friend); | ||
27 | private static final NodeVariable p = Variable.of("p"); | ||
28 | private static final NodeVariable q = Variable.of("q"); | ||
29 | |||
15 | @Test | 30 | @Test |
16 | void flatEqualsTest() { | 31 | void flatEqualsTest() { |
17 | var p = Variable.of("p"); | ||
18 | var q = Variable.of("q"); | ||
19 | var person = new Symbol<>("Person", 1, Boolean.class, false); | ||
20 | var personView = new KeyOnlyRelationView<>(person); | ||
21 | |||
22 | var expected = Dnf.builder("Expected").parameters(q).clause(personView.call(q)).build(); | 32 | var expected = Dnf.builder("Expected").parameters(q).clause(personView.call(q)).build(); |
23 | var actual = Dnf.builder("Actual").parameters(p).clause(personView.call(p)).build(); | 33 | var actual = Dnf.builder("Actual").parameters(p).clause(personView.call(p)).build(); |
24 | 34 | ||
@@ -27,13 +37,8 @@ class StructurallyEqualToTest { | |||
27 | 37 | ||
28 | @Test | 38 | @Test |
29 | void flatNotEqualsTest() { | 39 | void flatNotEqualsTest() { |
30 | var p = Variable.of("p"); | 40 | var expected = Dnf.builder("Expected").parameters(q).clause(friendView.call(q, q)).build(); |
31 | var q = Variable.of("q"); | 41 | var actual = Dnf.builder("Actual").parameters(p).clause(friendView.call(p, q)).build(); |
32 | var person = new Symbol<>("Person", 1, Boolean.class, false); | ||
33 | var personView = new KeyOnlyRelationView<>(person); | ||
34 | |||
35 | var expected = Dnf.builder("Expected").parameters(q).clause(personView.call(q)).build(); | ||
36 | var actual = Dnf.builder("Actual").parameters(p).clause(personView.call(q)).build(); | ||
37 | 42 | ||
38 | var assertion = structurallyEqualTo(expected); | 43 | var assertion = structurallyEqualTo(expected); |
39 | assertThrows(AssertionError.class, () -> assertThat(actual, assertion)); | 44 | assertThrows(AssertionError.class, () -> assertThat(actual, assertion)); |
@@ -41,11 +46,6 @@ class StructurallyEqualToTest { | |||
41 | 46 | ||
42 | @Test | 47 | @Test |
43 | void deepEqualsTest() { | 48 | void deepEqualsTest() { |
44 | var p = Variable.of("p"); | ||
45 | var q = Variable.of("q"); | ||
46 | var person = new Symbol<>("Person", 1, Boolean.class, false); | ||
47 | var personView = new KeyOnlyRelationView<>(person); | ||
48 | |||
49 | var expected = Dnf.builder("Expected").parameters(q).clause( | 49 | var expected = Dnf.builder("Expected").parameters(q).clause( |
50 | Dnf.builder("Expected2").parameters(p).clause(personView.call(p)).build().call(q) | 50 | Dnf.builder("Expected2").parameters(p).clause(personView.call(p)).build().call(q) |
51 | ).build(); | 51 | ).build(); |
@@ -58,20 +58,70 @@ class StructurallyEqualToTest { | |||
58 | 58 | ||
59 | @Test | 59 | @Test |
60 | void deepNotEqualsTest() { | 60 | void deepNotEqualsTest() { |
61 | var p = Variable.of("p"); | ||
62 | var q = Variable.of("q"); | ||
63 | var person = new Symbol<>("Person", 1, Boolean.class, false); | ||
64 | var personView = new KeyOnlyRelationView<>(person); | ||
65 | |||
66 | var expected = Dnf.builder("Expected").parameters(q).clause( | 61 | var expected = Dnf.builder("Expected").parameters(q).clause( |
67 | Dnf.builder("Expected2").parameters(p).clause(personView.call(p)).build().call(q) | 62 | Dnf.builder("Expected2").parameters(p).clause(friendView.call(p, p)).build().call(q) |
68 | ).build(); | 63 | ).build(); |
69 | var actual = Dnf.builder("Actual").parameters(q).clause( | 64 | var actual = Dnf.builder("Actual").parameter(q).clause( |
70 | Dnf.builder("Actual2").parameters(p).clause(personView.call(q)).build().call(q) | 65 | Dnf.builder("Actual2").parameters(p).clause(friendView.call(p, q)).build().call(q) |
71 | ).build(); | 66 | ).build(); |
72 | 67 | ||
73 | var assertion = structurallyEqualTo(expected); | 68 | var assertion = structurallyEqualTo(expected); |
74 | var error = assertThrows(AssertionError.class, () -> assertThat(actual, assertion)); | 69 | var error = assertThrows(AssertionError.class, () -> assertThat(actual, assertion)); |
75 | assertThat(error.getMessage(), containsString(" called from Expected/1 ")); | 70 | assertThat(error.getMessage(), containsString(" called from Expected/1 ")); |
76 | } | 71 | } |
72 | |||
73 | @Test | ||
74 | void parameterListLengthMismatchTest() { | ||
75 | var expected = Dnf.builder("Expected").parameter(p).clause( | ||
76 | friendView.call(p, p) | ||
77 | ).build(); | ||
78 | var actual = Dnf.builder("Actual").parameters(p, q).clause( | ||
79 | friendView.call(p, q) | ||
80 | ).build(); | ||
81 | |||
82 | var assertion = structurallyEqualTo(expected); | ||
83 | assertThrows(AssertionError.class, () -> assertThat(actual, assertion)); | ||
84 | } | ||
85 | |||
86 | @Test | ||
87 | void parameterDirectionMismatchTest() { | ||
88 | var expected = Dnf.builder("Expected").parameter(p, ParameterDirection.OUT).clause( | ||
89 | personView.call(p) | ||
90 | ).build(); | ||
91 | var actual = Dnf.builder("Actual").parameter(p, ParameterDirection.IN).clause( | ||
92 | personView.call(p) | ||
93 | ).build(); | ||
94 | |||
95 | var assertion = structurallyEqualTo(expected); | ||
96 | assertThrows(AssertionError.class, () -> assertThat(actual, assertion)); | ||
97 | } | ||
98 | |||
99 | @Test | ||
100 | void clauseCountMismatchTest() { | ||
101 | var expected = Dnf.builder("Expected") | ||
102 | .parameters(p, q) | ||
103 | .clause(friendView.call(p, q)) | ||
104 | .clause(friendView.call(q, p)) | ||
105 | .build(); | ||
106 | var actual = Dnf.builder("Actual").parameters(p, q).clause( | ||
107 | friendView.call(p, q) | ||
108 | ).build(); | ||
109 | |||
110 | var assertion = structurallyEqualTo(expected); | ||
111 | assertThrows(AssertionError.class, () -> assertThat(actual, assertion)); | ||
112 | } | ||
113 | |||
114 | @Test | ||
115 | void literalCountMismatchTest() { | ||
116 | var expected = Dnf.builder("Expected").parameters(p, q).clause( | ||
117 | friendView.call(p, q), | ||
118 | friendView.call(q, p) | ||
119 | ).build(); | ||
120 | var actual = Dnf.builder("Actual").parameters(p, q).clause( | ||
121 | friendView.call(p, q) | ||
122 | ).build(); | ||
123 | |||
124 | var assertion = structurallyEqualTo(expected); | ||
125 | assertThrows(AssertionError.class, () -> assertThat(actual, assertion)); | ||
126 | } | ||
77 | } | 127 | } |
diff --git a/subprojects/store-query/src/testFixtures/java/tools/refinery/store/query/tests/MismatchDescribingDnfEqualityChecker.java b/subprojects/store-query/src/testFixtures/java/tools/refinery/store/query/tests/MismatchDescribingDnfEqualityChecker.java index 685957c9..6a3301b3 100644 --- a/subprojects/store-query/src/testFixtures/java/tools/refinery/store/query/tests/MismatchDescribingDnfEqualityChecker.java +++ b/subprojects/store-query/src/testFixtures/java/tools/refinery/store/query/tests/MismatchDescribingDnfEqualityChecker.java | |||
@@ -1,27 +1,52 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.tests; | 6 | package tools.refinery.store.query.tests; |
2 | 7 | ||
3 | import org.hamcrest.Description; | 8 | import org.hamcrest.Description; |
9 | import tools.refinery.store.query.dnf.Dnf; | ||
10 | import tools.refinery.store.query.dnf.SymbolicParameter; | ||
4 | import tools.refinery.store.query.equality.DeepDnfEqualityChecker; | 11 | import tools.refinery.store.query.equality.DeepDnfEqualityChecker; |
12 | import tools.refinery.store.query.literal.Literal; | ||
13 | |||
14 | import java.util.List; | ||
5 | 15 | ||
6 | class MismatchDescribingDnfEqualityChecker extends DeepDnfEqualityChecker { | 16 | class MismatchDescribingDnfEqualityChecker extends DeepDnfEqualityChecker { |
7 | private final Description description; | 17 | private final Description description; |
8 | private boolean described; | 18 | private boolean raw; |
19 | private boolean needsDescription = true; | ||
9 | 20 | ||
10 | MismatchDescribingDnfEqualityChecker(Description description) { | 21 | MismatchDescribingDnfEqualityChecker(Description description) { |
11 | this.description = description; | 22 | this.description = description; |
12 | } | 23 | } |
13 | 24 | ||
14 | public boolean isDescribed() { | 25 | public boolean needsDescription() { |
15 | return described; | 26 | return needsDescription; |
27 | } | ||
28 | |||
29 | @Override | ||
30 | public boolean dnfEqualRaw(List<SymbolicParameter> symbolicParameters, List<? extends List<? extends Literal>> clauses, Dnf other) { | ||
31 | try { | ||
32 | raw = true; | ||
33 | boolean result = super.dnfEqualRaw(symbolicParameters, clauses, other); | ||
34 | if (!result && needsDescription) { | ||
35 | description.appendText("was ").appendText(other.toDefinitionString()); | ||
36 | } | ||
37 | return false; | ||
38 | } finally { | ||
39 | raw = false; | ||
40 | } | ||
16 | } | 41 | } |
17 | 42 | ||
18 | @Override | 43 | @Override |
19 | protected boolean doCheckEqual(Pair pair) { | 44 | protected boolean doCheckEqual(Pair pair) { |
20 | boolean result = super.doCheckEqual(pair); | 45 | boolean result = super.doCheckEqual(pair); |
21 | if (!result && !described) { | 46 | if (!result && needsDescription) { |
22 | describeMismatch(pair); | 47 | describeMismatch(pair); |
23 | // Only describe the first found (innermost) mismatch. | 48 | // Only describe the first found (innermost) mismatch. |
24 | described = true; | 49 | needsDescription = false; |
25 | } | 50 | } |
26 | return result; | 51 | return result; |
27 | } | 52 | } |
@@ -29,12 +54,12 @@ class MismatchDescribingDnfEqualityChecker extends DeepDnfEqualityChecker { | |||
29 | private void describeMismatch(Pair pair) { | 54 | private void describeMismatch(Pair pair) { |
30 | var inProgress = getInProgress(); | 55 | var inProgress = getInProgress(); |
31 | int size = inProgress.size(); | 56 | int size = inProgress.size(); |
32 | if (size <= 1) { | 57 | if (size <= 1 && !raw) { |
33 | description.appendText("was ").appendText(pair.left().toDefinitionString()); | 58 | description.appendText("was ").appendText(pair.right().toDefinitionString()); |
34 | return; | 59 | return; |
35 | } | 60 | } |
36 | var last = inProgress.get(size - 1); | 61 | var last = inProgress.get(size - 1); |
37 | description.appendText("expected ").appendText(last.right().toDefinitionString()); | 62 | description.appendText("expected ").appendText(last.left().toDefinitionString()); |
38 | for (int i = size - 2; i >= 0; i--) { | 63 | for (int i = size - 2; i >= 0; i--) { |
39 | description.appendText(" called from ").appendText(inProgress.get(i).left().toString()); | 64 | description.appendText(" called from ").appendText(inProgress.get(i).left().toString()); |
40 | } | 65 | } |
diff --git a/subprojects/store-query/src/testFixtures/java/tools/refinery/store/query/tests/QueryMatchers.java b/subprojects/store-query/src/testFixtures/java/tools/refinery/store/query/tests/QueryMatchers.java index bf1c1b74..cd449a6a 100644 --- a/subprojects/store-query/src/testFixtures/java/tools/refinery/store/query/tests/QueryMatchers.java +++ b/subprojects/store-query/src/testFixtures/java/tools/refinery/store/query/tests/QueryMatchers.java | |||
@@ -1,14 +1,46 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.tests; | 6 | package tools.refinery.store.query.tests; |
2 | 7 | ||
3 | import org.hamcrest.Matcher; | 8 | import org.hamcrest.Matcher; |
4 | import tools.refinery.store.query.dnf.Dnf; | 9 | import tools.refinery.store.query.dnf.Dnf; |
10 | import tools.refinery.store.query.dnf.SymbolicParameter; | ||
11 | import tools.refinery.store.query.literal.Literal; | ||
12 | |||
13 | import java.util.List; | ||
5 | 14 | ||
6 | public final class QueryMatchers { | 15 | public final class QueryMatchers { |
7 | private QueryMatchers() { | 16 | private QueryMatchers() { |
8 | throw new IllegalStateException("This is a static utility class and should not be instantiated directly"); | 17 | throw new IllegalStateException("This is a static utility class and should not be instantiated directly"); |
9 | } | 18 | } |
10 | 19 | ||
20 | /** | ||
21 | * Compare two {@link Dnf} instances up to renaming of variables. | ||
22 | * | ||
23 | * @param expected The expected {@link Dnf} instance. | ||
24 | * @return A Hamcrest matcher for equality up to renaming of variables. | ||
25 | */ | ||
11 | public static Matcher<Dnf> structurallyEqualTo(Dnf expected) { | 26 | public static Matcher<Dnf> structurallyEqualTo(Dnf expected) { |
12 | return new StructurallyEqualTo(expected); | 27 | return new StructurallyEqualTo(expected); |
13 | } | 28 | } |
29 | |||
30 | /** | ||
31 | * Compare a {@link Dnf} instance to another predicate in DNF form without constructing it. | ||
32 | * <p> | ||
33 | * This matcher should be used instead of {@link #structurallyEqualTo(Dnf)} when the validation and | ||
34 | * pre-processing associated with the {@link Dnf} constructor, i.e., validation of parameter directions, | ||
35 | * topological sorting of literals, and the reduction of trivial predicates is not desired. In particular, this | ||
36 | * matcher can be used to test for exact order of literal after pre-processing. | ||
37 | * | ||
38 | * @param expectedSymbolicParameters The expected list of symbolic parameters. | ||
39 | * @param expectedLiterals The expected clauses. Each clause is represented by a list of literals. | ||
40 | * @return A Hamcrest matcher for equality up to renaming of variables. | ||
41 | */ | ||
42 | public static Matcher<Dnf> structurallyEqualTo(List<SymbolicParameter> expectedSymbolicParameters, | ||
43 | List<? extends List<? extends Literal>> expectedLiterals) { | ||
44 | return new StructurallyEqualToRaw(expectedSymbolicParameters, expectedLiterals); | ||
45 | } | ||
14 | } | 46 | } |
diff --git a/subprojects/store-query/src/testFixtures/java/tools/refinery/store/query/tests/StructurallyEqualTo.java b/subprojects/store-query/src/testFixtures/java/tools/refinery/store/query/tests/StructurallyEqualTo.java index a9a78f88..86149141 100644 --- a/subprojects/store-query/src/testFixtures/java/tools/refinery/store/query/tests/StructurallyEqualTo.java +++ b/subprojects/store-query/src/testFixtures/java/tools/refinery/store/query/tests/StructurallyEqualTo.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.query.tests; | 6 | package tools.refinery.store.query.tests; |
2 | 7 | ||
3 | import org.hamcrest.Description; | 8 | import org.hamcrest.Description; |
@@ -24,7 +29,7 @@ public class StructurallyEqualTo extends TypeSafeMatcher<Dnf> { | |||
24 | if (describingChecker.dnfEqual(expected, item)) { | 29 | if (describingChecker.dnfEqual(expected, item)) { |
25 | throw new IllegalStateException("Mismatched Dnf was matching on repeated comparison"); | 30 | throw new IllegalStateException("Mismatched Dnf was matching on repeated comparison"); |
26 | } | 31 | } |
27 | if (!describingChecker.isDescribed()) { | 32 | if (describingChecker.needsDescription()) { |
28 | super.describeMismatchSafely(item, mismatchDescription); | 33 | super.describeMismatchSafely(item, mismatchDescription); |
29 | } | 34 | } |
30 | } | 35 | } |
diff --git a/subprojects/store-query/src/testFixtures/java/tools/refinery/store/query/tests/StructurallyEqualToRaw.java b/subprojects/store-query/src/testFixtures/java/tools/refinery/store/query/tests/StructurallyEqualToRaw.java new file mode 100644 index 00000000..2f8c2944 --- /dev/null +++ b/subprojects/store-query/src/testFixtures/java/tools/refinery/store/query/tests/StructurallyEqualToRaw.java | |||
@@ -0,0 +1,51 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.query.tests; | ||
7 | |||
8 | import org.hamcrest.Description; | ||
9 | import org.hamcrest.TypeSafeMatcher; | ||
10 | import tools.refinery.store.query.dnf.Dnf; | ||
11 | import tools.refinery.store.query.dnf.SymbolicParameter; | ||
12 | import tools.refinery.store.query.equality.DeepDnfEqualityChecker; | ||
13 | import tools.refinery.store.query.literal.Literal; | ||
14 | |||
15 | import java.util.List; | ||
16 | |||
17 | public class StructurallyEqualToRaw extends TypeSafeMatcher<Dnf> { | ||
18 | private final List<SymbolicParameter> expectedSymbolicParameters; | ||
19 | private final List<? extends List<? extends Literal>> expectedClauses; | ||
20 | |||
21 | public StructurallyEqualToRaw(List<SymbolicParameter> expectedSymbolicParameters, | ||
22 | List<? extends List<? extends Literal>> expectedClauses) { | ||
23 | this.expectedSymbolicParameters = expectedSymbolicParameters; | ||
24 | this.expectedClauses = expectedClauses; | ||
25 | } | ||
26 | |||
27 | @Override | ||
28 | protected boolean matchesSafely(Dnf item) { | ||
29 | var checker = new DeepDnfEqualityChecker(); | ||
30 | return checker.dnfEqualRaw(expectedSymbolicParameters, expectedClauses, item); | ||
31 | } | ||
32 | |||
33 | @Override | ||
34 | protected void describeMismatchSafely(Dnf item, Description mismatchDescription) { | ||
35 | var describingChecker = new MismatchDescribingDnfEqualityChecker(mismatchDescription); | ||
36 | if (describingChecker.dnfEqualRaw(expectedSymbolicParameters, expectedClauses, item)) { | ||
37 | throw new IllegalStateException("Mismatched Dnf was matching on repeated comparison"); | ||
38 | } | ||
39 | if (describingChecker.needsDescription()) { | ||
40 | super.describeMismatchSafely(item, mismatchDescription); | ||
41 | } | ||
42 | } | ||
43 | |||
44 | @Override | ||
45 | public void describeTo(Description description) { | ||
46 | description.appendText("structurally equal to ") | ||
47 | .appendValueList("(", ", ", ")", expectedSymbolicParameters) | ||
48 | .appendText(" <-> ") | ||
49 | .appendValueList("", ", ", ".", expectedClauses); | ||
50 | } | ||
51 | } | ||
diff --git a/subprojects/store-reasoning/build.gradle b/subprojects/store-reasoning/build.gradle deleted file mode 100644 index cb440d9f..00000000 --- a/subprojects/store-reasoning/build.gradle +++ /dev/null | |||
@@ -1,7 +0,0 @@ | |||
1 | plugins { | ||
2 | id 'refinery-java-library' | ||
3 | } | ||
4 | |||
5 | dependencies { | ||
6 | api project(':refinery-store-query') | ||
7 | } | ||
diff --git a/subprojects/store-reasoning/build.gradle.kts b/subprojects/store-reasoning/build.gradle.kts new file mode 100644 index 00000000..abad0491 --- /dev/null +++ b/subprojects/store-reasoning/build.gradle.kts | |||
@@ -0,0 +1,13 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
7 | plugins { | ||
8 | id("tools.refinery.gradle.java-library") | ||
9 | } | ||
10 | |||
11 | dependencies { | ||
12 | api(project(":refinery-store-query")) | ||
13 | } | ||
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/AnyPartialInterpretation.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/AnyPartialInterpretation.java index ebe82c8b..000171a1 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/AnyPartialInterpretation.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/AnyPartialInterpretation.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.reasoning; | 6 | package tools.refinery.store.reasoning; |
2 | 7 | ||
3 | import tools.refinery.store.reasoning.representation.AnyPartialSymbol; | 8 | import tools.refinery.store.reasoning.representation.AnyPartialSymbol; |
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/MergeResult.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/MergeResult.java index 0d51598b..d3a216d8 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/MergeResult.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/MergeResult.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.reasoning; | 6 | package tools.refinery.store.reasoning; |
2 | 7 | ||
3 | public enum MergeResult { | 8 | public enum MergeResult { |
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/PartialInterpretation.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/PartialInterpretation.java index 4f195e97..4140d640 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/PartialInterpretation.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/PartialInterpretation.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.reasoning; | 6 | package tools.refinery.store.reasoning; |
2 | 7 | ||
3 | import tools.refinery.store.reasoning.representation.PartialSymbol; | 8 | import tools.refinery.store.reasoning.representation.PartialSymbol; |
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/Reasoning.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/Reasoning.java deleted file mode 100644 index d7d0a999..00000000 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/Reasoning.java +++ /dev/null | |||
@@ -1,24 +0,0 @@ | |||
1 | package tools.refinery.store.reasoning; | ||
2 | |||
3 | import tools.refinery.store.reasoning.internal.ReasoningBuilderImpl; | ||
4 | import tools.refinery.store.adapter.ModelAdapterBuilderFactory; | ||
5 | import tools.refinery.store.model.ModelStoreBuilder; | ||
6 | import tools.refinery.store.reasoning.representation.PartialRelation; | ||
7 | |||
8 | public final class Reasoning extends ModelAdapterBuilderFactory<ReasoningAdapter, | ||
9 | ReasoningStoreAdapter, ReasoningBuilder> { | ||
10 | public static final Reasoning ADAPTER = new Reasoning(); | ||
11 | |||
12 | public static final PartialRelation EXISTS = new PartialRelation("exists", 1); | ||
13 | |||
14 | public static final PartialRelation EQUALS = new PartialRelation("equals", 1); | ||
15 | |||
16 | private Reasoning() { | ||
17 | super(ReasoningAdapter.class, ReasoningStoreAdapter.class, ReasoningBuilder.class); | ||
18 | } | ||
19 | |||
20 | @Override | ||
21 | public ReasoningBuilder createBuilder(ModelStoreBuilder storeBuilder) { | ||
22 | return new ReasoningBuilderImpl(storeBuilder); | ||
23 | } | ||
24 | } | ||
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/ReasoningAdapter.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/ReasoningAdapter.java index de039dd9..8f319242 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/ReasoningAdapter.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/ReasoningAdapter.java | |||
@@ -1,12 +1,20 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.reasoning; | 6 | package tools.refinery.store.reasoning; |
2 | 7 | ||
3 | import tools.refinery.store.adapter.ModelAdapter; | 8 | import tools.refinery.store.adapter.ModelAdapter; |
9 | import tools.refinery.store.query.ResultSet; | ||
10 | import tools.refinery.store.query.dnf.Dnf; | ||
4 | import tools.refinery.store.reasoning.representation.AnyPartialSymbol; | 11 | import tools.refinery.store.reasoning.representation.AnyPartialSymbol; |
12 | import tools.refinery.store.reasoning.representation.PartialRelation; | ||
5 | import tools.refinery.store.reasoning.representation.PartialSymbol; | 13 | import tools.refinery.store.reasoning.representation.PartialSymbol; |
6 | import tools.refinery.store.query.dnf.Dnf; | ||
7 | import tools.refinery.store.query.ResultSet; | ||
8 | 14 | ||
9 | public interface ReasoningAdapter extends ModelAdapter { | 15 | public interface ReasoningAdapter extends ModelAdapter { |
16 | PartialRelation EXISTS = new PartialRelation("exists", 1); | ||
17 | |||
10 | @Override | 18 | @Override |
11 | ReasoningStoreAdapter getStoreAdapter(); | 19 | ReasoningStoreAdapter getStoreAdapter(); |
12 | 20 | ||
@@ -18,5 +26,5 @@ public interface ReasoningAdapter extends ModelAdapter { | |||
18 | 26 | ||
19 | <A, C> PartialInterpretation<A, C> getPartialInterpretation(PartialSymbol<A, C> partialSymbol); | 27 | <A, C> PartialInterpretation<A, C> getPartialInterpretation(PartialSymbol<A, C> partialSymbol); |
20 | 28 | ||
21 | ResultSet getLiftedResultSet(Dnf query); | 29 | ResultSet<Boolean> getLiftedResultSet(Dnf query); |
22 | } | 30 | } |
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/ReasoningBuilder.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/ReasoningBuilder.java index 4030d296..d3a337e8 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/ReasoningBuilder.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/ReasoningBuilder.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.reasoning; | 6 | package tools.refinery.store.reasoning; |
2 | 7 | ||
3 | import tools.refinery.store.adapter.ModelAdapterBuilder; | 8 | import tools.refinery.store.adapter.ModelAdapterBuilder; |
@@ -24,5 +29,5 @@ public interface ReasoningBuilder extends ModelAdapterBuilder { | |||
24 | Dnf lift(Modality modality, Dnf query); | 29 | Dnf lift(Modality modality, Dnf query); |
25 | 30 | ||
26 | @Override | 31 | @Override |
27 | ReasoningStoreAdapter createStoreAdapter(ModelStore store); | 32 | ReasoningStoreAdapter build(ModelStore store); |
28 | } | 33 | } |
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/ReasoningStoreAdapter.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/ReasoningStoreAdapter.java index f6a6e414..c9795255 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/ReasoningStoreAdapter.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/ReasoningStoreAdapter.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.reasoning; | 6 | package tools.refinery.store.reasoning; |
2 | 7 | ||
3 | import tools.refinery.store.adapter.ModelStoreAdapter; | 8 | import tools.refinery.store.adapter.ModelStoreAdapter; |
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/internal/ReasoningAdapterImpl.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/internal/ReasoningAdapterImpl.java index 0acf0d49..33b6f3c6 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/internal/ReasoningAdapterImpl.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/internal/ReasoningAdapterImpl.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.reasoning.internal; | 6 | package tools.refinery.store.reasoning.internal; |
2 | 7 | ||
3 | import tools.refinery.store.model.Model; | 8 | import tools.refinery.store.model.Model; |
@@ -32,7 +37,7 @@ public class ReasoningAdapterImpl implements ReasoningAdapter { | |||
32 | } | 37 | } |
33 | 38 | ||
34 | @Override | 39 | @Override |
35 | public ResultSet getLiftedResultSet(Dnf query) { | 40 | public ResultSet<Boolean> getLiftedResultSet(Dnf query) { |
36 | return null; | 41 | return null; |
37 | } | 42 | } |
38 | } | 43 | } |
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/internal/ReasoningBuilderImpl.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/internal/ReasoningBuilderImpl.java index e11b14bf..aa71496c 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/internal/ReasoningBuilderImpl.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/internal/ReasoningBuilderImpl.java | |||
@@ -1,17 +1,18 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.reasoning.internal; | 6 | package tools.refinery.store.reasoning.internal; |
2 | 7 | ||
3 | import tools.refinery.store.adapter.AbstractModelAdapterBuilder; | 8 | import tools.refinery.store.adapter.AbstractModelAdapterBuilder; |
4 | import tools.refinery.store.model.ModelStore; | 9 | import tools.refinery.store.model.ModelStore; |
5 | import tools.refinery.store.model.ModelStoreBuilder; | 10 | import tools.refinery.store.query.dnf.Dnf; |
6 | import tools.refinery.store.reasoning.ReasoningBuilder; | 11 | import tools.refinery.store.reasoning.ReasoningBuilder; |
7 | import tools.refinery.store.reasoning.literal.Modality; | 12 | import tools.refinery.store.reasoning.literal.Modality; |
8 | import tools.refinery.store.query.dnf.Dnf; | ||
9 | |||
10 | public class ReasoningBuilderImpl extends AbstractModelAdapterBuilder implements ReasoningBuilder { | ||
11 | public ReasoningBuilderImpl(ModelStoreBuilder storeBuilder) { | ||
12 | super(storeBuilder); | ||
13 | } | ||
14 | 13 | ||
14 | public class ReasoningBuilderImpl extends AbstractModelAdapterBuilder<ReasoningStoreAdapterImpl> | ||
15 | implements ReasoningBuilder { | ||
15 | @Override | 16 | @Override |
16 | public ReasoningBuilder liftedQuery(Dnf liftedQuery) { | 17 | public ReasoningBuilder liftedQuery(Dnf liftedQuery) { |
17 | return null; | 18 | return null; |
@@ -19,11 +20,12 @@ public class ReasoningBuilderImpl extends AbstractModelAdapterBuilder implements | |||
19 | 20 | ||
20 | @Override | 21 | @Override |
21 | public Dnf lift(Modality modality, Dnf query) { | 22 | public Dnf lift(Modality modality, Dnf query) { |
23 | checkNotConfigured(); | ||
22 | return null; | 24 | return null; |
23 | } | 25 | } |
24 | 26 | ||
25 | @Override | 27 | @Override |
26 | public ReasoningStoreAdapterImpl createStoreAdapter(ModelStore store) { | 28 | public ReasoningStoreAdapterImpl doBuild(ModelStore store) { |
27 | return null; | 29 | return null; |
28 | } | 30 | } |
29 | } | 31 | } |
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/internal/ReasoningStoreAdapterImpl.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/internal/ReasoningStoreAdapterImpl.java index ac06e68b..cdddd8d6 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/internal/ReasoningStoreAdapterImpl.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/internal/ReasoningStoreAdapterImpl.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.reasoning.internal; | 6 | package tools.refinery.store.reasoning.internal; |
2 | 7 | ||
3 | import tools.refinery.store.reasoning.ReasoningStoreAdapter; | 8 | import tools.refinery.store.reasoning.ReasoningStoreAdapter; |
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/lifting/DnfLifter.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/lifting/DnfLifter.java index 2b0e0f08..ac41d170 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/lifting/DnfLifter.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/lifting/DnfLifter.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.reasoning.lifting; | 6 | package tools.refinery.store.reasoning.lifting; |
2 | 7 | ||
3 | import org.jetbrains.annotations.Nullable; | 8 | import org.jetbrains.annotations.Nullable; |
@@ -7,16 +12,16 @@ import tools.refinery.store.query.dnf.DnfClause; | |||
7 | import tools.refinery.store.query.literal.CallLiteral; | 12 | import tools.refinery.store.query.literal.CallLiteral; |
8 | import tools.refinery.store.query.literal.CallPolarity; | 13 | import tools.refinery.store.query.literal.CallPolarity; |
9 | import tools.refinery.store.query.literal.Literal; | 14 | import tools.refinery.store.query.literal.Literal; |
10 | import tools.refinery.store.query.term.DataVariable; | 15 | import tools.refinery.store.query.term.NodeVariable; |
11 | import tools.refinery.store.query.term.Variable; | 16 | import tools.refinery.store.query.term.Variable; |
12 | import tools.refinery.store.reasoning.Reasoning; | 17 | import tools.refinery.store.reasoning.ReasoningAdapter; |
13 | import tools.refinery.store.reasoning.literal.ModalConstraint; | 18 | import tools.refinery.store.reasoning.literal.ModalConstraint; |
14 | import tools.refinery.store.reasoning.literal.Modality; | 19 | import tools.refinery.store.reasoning.literal.Modality; |
15 | import tools.refinery.store.reasoning.literal.PartialLiterals; | 20 | import tools.refinery.store.reasoning.literal.PartialLiterals; |
16 | import tools.refinery.store.util.CycleDetectingMapper; | 21 | import tools.refinery.store.util.CycleDetectingMapper; |
17 | 22 | ||
18 | import java.util.ArrayList; | 23 | import java.util.ArrayList; |
19 | import java.util.HashSet; | 24 | import java.util.LinkedHashSet; |
20 | import java.util.List; | 25 | import java.util.List; |
21 | 26 | ||
22 | public class DnfLifter { | 27 | public class DnfLifter { |
@@ -31,10 +36,10 @@ public class DnfLifter { | |||
31 | var modality = modalDnf.modality(); | 36 | var modality = modalDnf.modality(); |
32 | var dnf = modalDnf.dnf(); | 37 | var dnf = modalDnf.dnf(); |
33 | var builder = Dnf.builder(); | 38 | var builder = Dnf.builder(); |
34 | builder.parameters(dnf.getParameters()); | 39 | builder.symbolicParameters(dnf.getSymbolicParameters()); |
35 | boolean changed = false; | 40 | boolean changed = false; |
36 | for (var clause : dnf.getClauses()) { | 41 | for (var clause : dnf.getClauses()) { |
37 | if (liftClause(modality, clause, builder)) { | 42 | if (liftClause(modality, dnf, clause, builder)) { |
38 | changed = true; | 43 | changed = true; |
39 | } | 44 | } |
40 | } | 45 | } |
@@ -44,12 +49,9 @@ public class DnfLifter { | |||
44 | return dnf; | 49 | return dnf; |
45 | } | 50 | } |
46 | 51 | ||
47 | private boolean liftClause(Modality modality, DnfClause clause, DnfBuilder builder) { | 52 | private boolean liftClause(Modality modality, Dnf originalDnf, DnfClause clause, DnfBuilder builder) { |
48 | boolean changed = false; | 53 | boolean changed = false; |
49 | var quantifiedVariables = new HashSet<>(clause.boundVariables() | 54 | var quantifiedVariables = getQuantifiedDataVariables(originalDnf, clause); |
50 | .stream() | ||
51 | .filter(DataVariable.class::isInstance) | ||
52 | .toList()); | ||
53 | var literals = clause.literals(); | 55 | var literals = clause.literals(); |
54 | var liftedLiterals = new ArrayList<Literal>(literals.size()); | 56 | var liftedLiterals = new ArrayList<Literal>(literals.size()); |
55 | for (var literal : literals) { | 57 | for (var literal : literals) { |
@@ -69,20 +71,30 @@ public class DnfLifter { | |||
69 | } | 71 | } |
70 | for (var quantifiedVariable : quantifiedVariables) { | 72 | for (var quantifiedVariable : quantifiedVariables) { |
71 | // Quantify over data variables that are not already quantified with the expected modality. | 73 | // Quantify over data variables that are not already quantified with the expected modality. |
72 | liftedLiterals.add(new CallLiteral(CallPolarity.POSITIVE, new ModalConstraint(modality, Reasoning.EXISTS), | 74 | liftedLiterals.add(new CallLiteral(CallPolarity.POSITIVE, |
73 | List.of(quantifiedVariable))); | 75 | new ModalConstraint(modality, ReasoningAdapter.EXISTS), List.of(quantifiedVariable))); |
74 | } | 76 | } |
75 | builder.clause(liftedLiterals); | 77 | builder.clause(liftedLiterals); |
76 | return changed || !quantifiedVariables.isEmpty(); | 78 | return changed || !quantifiedVariables.isEmpty(); |
77 | } | 79 | } |
78 | 80 | ||
81 | private static LinkedHashSet<Variable> getQuantifiedDataVariables(Dnf originalDnf, DnfClause clause) { | ||
82 | var quantifiedVariables = new LinkedHashSet<>(clause.positiveVariables()); | ||
83 | for (var symbolicParameter : originalDnf.getSymbolicParameters()) { | ||
84 | // The existence of parameters will be checked outside this DNF. | ||
85 | quantifiedVariables.remove(symbolicParameter.getVariable()); | ||
86 | } | ||
87 | quantifiedVariables.removeIf(variable -> !(variable instanceof NodeVariable)); | ||
88 | return quantifiedVariables; | ||
89 | } | ||
90 | |||
79 | @Nullable | 91 | @Nullable |
80 | private Variable isExistsLiteralForVariable(Modality modality, Literal literal) { | 92 | private Variable isExistsLiteralForVariable(Modality modality, Literal literal) { |
81 | if (literal instanceof CallLiteral callLiteral && | 93 | if (literal instanceof CallLiteral callLiteral && |
82 | callLiteral.getPolarity() == CallPolarity.POSITIVE && | 94 | callLiteral.getPolarity() == CallPolarity.POSITIVE && |
83 | callLiteral.getTarget() instanceof ModalConstraint modalConstraint && | 95 | callLiteral.getTarget() instanceof ModalConstraint modalConstraint && |
84 | modalConstraint.modality() == modality && | 96 | modalConstraint.modality() == modality && |
85 | modalConstraint.constraint().equals(Reasoning.EXISTS)) { | 97 | modalConstraint.constraint().equals(ReasoningAdapter.EXISTS)) { |
86 | return callLiteral.getArguments().get(0); | 98 | return callLiteral.getArguments().get(0); |
87 | } | 99 | } |
88 | return null; | 100 | return null; |
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/lifting/ModalDnf.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/lifting/ModalDnf.java index ec381bb8..16fb8fbf 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/lifting/ModalDnf.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/lifting/ModalDnf.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.reasoning.lifting; | 6 | package tools.refinery.store.reasoning.lifting; |
2 | 7 | ||
3 | import tools.refinery.store.query.dnf.Dnf; | 8 | import tools.refinery.store.query.dnf.Dnf; |
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/literal/ModalConstraint.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/literal/ModalConstraint.java index 2fbb4607..5ad1d5f8 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/literal/ModalConstraint.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/literal/ModalConstraint.java | |||
@@ -1,9 +1,14 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.reasoning.literal; | 6 | package tools.refinery.store.reasoning.literal; |
2 | 7 | ||
3 | import tools.refinery.store.query.Constraint; | 8 | import tools.refinery.store.query.Constraint; |
4 | import tools.refinery.store.query.equality.LiteralEqualityHelper; | 9 | import tools.refinery.store.query.equality.LiteralEqualityHelper; |
5 | import tools.refinery.store.query.literal.LiteralReduction; | 10 | import tools.refinery.store.query.Reduction; |
6 | import tools.refinery.store.query.term.Sort; | 11 | import tools.refinery.store.query.term.Parameter; |
7 | 12 | ||
8 | import java.util.List; | 13 | import java.util.List; |
9 | 14 | ||
@@ -16,12 +21,12 @@ public record ModalConstraint(Modality modality, Constraint constraint) implemen | |||
16 | } | 21 | } |
17 | 22 | ||
18 | @Override | 23 | @Override |
19 | public List<Sort> getSorts() { | 24 | public List<Parameter> getParameters() { |
20 | return constraint.getSorts(); | 25 | return constraint.getParameters(); |
21 | } | 26 | } |
22 | 27 | ||
23 | @Override | 28 | @Override |
24 | public LiteralReduction getReduction() { | 29 | public Reduction getReduction() { |
25 | return constraint.getReduction(); | 30 | return constraint.getReduction(); |
26 | } | 31 | } |
27 | 32 | ||
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/literal/Modality.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/literal/Modality.java index f0cb59de..96466d5c 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/literal/Modality.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/literal/Modality.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.reasoning.literal; | 6 | package tools.refinery.store.reasoning.literal; |
2 | 7 | ||
3 | import tools.refinery.store.query.literal.CallPolarity; | 8 | import tools.refinery.store.query.literal.CallPolarity; |
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/literal/PartialLiterals.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/literal/PartialLiterals.java index f991f87f..0e46a795 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/literal/PartialLiterals.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/literal/PartialLiterals.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.reasoning.literal; | 6 | package tools.refinery.store.reasoning.literal; |
2 | 7 | ||
3 | import tools.refinery.store.query.literal.CallLiteral; | 8 | import tools.refinery.store.query.literal.CallLiteral; |
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/representation/AnyPartialFunction.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/representation/AnyPartialFunction.java index e74cd58b..8d2cb5cf 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/representation/AnyPartialFunction.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/representation/AnyPartialFunction.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.reasoning.representation; | 6 | package tools.refinery.store.reasoning.representation; |
2 | 7 | ||
3 | public sealed interface AnyPartialFunction extends AnyPartialSymbol permits PartialFunction { | 8 | public sealed interface AnyPartialFunction extends AnyPartialSymbol permits PartialFunction { |
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/representation/AnyPartialSymbol.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/representation/AnyPartialSymbol.java index 6ff5031b..788eef73 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/representation/AnyPartialSymbol.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/representation/AnyPartialSymbol.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.reasoning.representation; | 6 | package tools.refinery.store.reasoning.representation; |
2 | 7 | ||
3 | import tools.refinery.store.representation.AnyAbstractDomain; | 8 | import tools.refinery.store.representation.AnyAbstractDomain; |
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/representation/PartialFunction.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/representation/PartialFunction.java index 59eeeefe..d58d026f 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/representation/PartialFunction.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/representation/PartialFunction.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.reasoning.representation; | 6 | package tools.refinery.store.reasoning.representation; |
2 | 7 | ||
3 | import tools.refinery.store.representation.AbstractDomain; | 8 | import tools.refinery.store.representation.AbstractDomain; |
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/representation/PartialRelation.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/representation/PartialRelation.java index 9bae53a9..6b2f050b 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/representation/PartialRelation.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/representation/PartialRelation.java | |||
@@ -1,8 +1,12 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.reasoning.representation; | 6 | package tools.refinery.store.reasoning.representation; |
2 | 7 | ||
3 | import tools.refinery.store.query.Constraint; | 8 | import tools.refinery.store.query.Constraint; |
4 | import tools.refinery.store.query.term.NodeSort; | 9 | import tools.refinery.store.query.term.Parameter; |
5 | import tools.refinery.store.query.term.Sort; | ||
6 | import tools.refinery.store.representation.AbstractDomain; | 10 | import tools.refinery.store.representation.AbstractDomain; |
7 | import tools.refinery.store.representation.TruthValue; | 11 | import tools.refinery.store.representation.TruthValue; |
8 | import tools.refinery.store.representation.TruthValueDomain; | 12 | import tools.refinery.store.representation.TruthValueDomain; |
@@ -27,10 +31,10 @@ public record PartialRelation(String name, int arity) implements PartialSymbol<T | |||
27 | } | 31 | } |
28 | 32 | ||
29 | @Override | 33 | @Override |
30 | public List<Sort> getSorts() { | 34 | public List<Parameter> getParameters() { |
31 | var sorts = new Sort[arity()]; | 35 | var parameters = new Parameter[arity]; |
32 | Arrays.fill(sorts, NodeSort.INSTANCE); | 36 | Arrays.fill(parameters, Parameter.NODE_OUT); |
33 | return List.of(sorts); | 37 | return List.of(parameters); |
34 | } | 38 | } |
35 | 39 | ||
36 | @Override | 40 | @Override |
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/representation/PartialSymbol.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/representation/PartialSymbol.java index 1af11f2e..3a08bdd8 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/representation/PartialSymbol.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/representation/PartialSymbol.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.reasoning.representation; | 6 | package tools.refinery.store.reasoning.representation; |
2 | 7 | ||
3 | import tools.refinery.store.representation.AbstractDomain; | 8 | import tools.refinery.store.representation.AbstractDomain; |
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/rule/RelationRefinementAction.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/rule/RelationRefinementAction.java index e8ed05a3..0beee248 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/rule/RelationRefinementAction.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/rule/RelationRefinementAction.java | |||
@@ -1,6 +1,11 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.reasoning.rule; | 6 | package tools.refinery.store.reasoning.rule; |
2 | 7 | ||
3 | import tools.refinery.store.reasoning.Reasoning; | 8 | import tools.refinery.store.reasoning.ReasoningAdapter; |
4 | import tools.refinery.store.reasoning.representation.PartialRelation; | 9 | import tools.refinery.store.reasoning.representation.PartialRelation; |
5 | import tools.refinery.store.model.Model; | 10 | import tools.refinery.store.model.Model; |
6 | import tools.refinery.store.query.term.Variable; | 11 | import tools.refinery.store.query.term.Variable; |
@@ -23,7 +28,7 @@ public record RelationRefinementAction(PartialRelation target, List<Variable> ar | |||
23 | 28 | ||
24 | @Override | 29 | @Override |
25 | public RuleActionExecutor createExecutor(int[] argumentIndices, Model model) { | 30 | public RuleActionExecutor createExecutor(int[] argumentIndices, Model model) { |
26 | var targetInterpretation = model.getAdapter(Reasoning.ADAPTER).getPartialInterpretation(target); | 31 | var targetInterpretation = model.getAdapter(ReasoningAdapter.class).getPartialInterpretation(target); |
27 | return activationTuple -> { | 32 | return activationTuple -> { |
28 | int arity = argumentIndices.length; | 33 | int arity = argumentIndices.length; |
29 | var arguments = new int[arity]; | 34 | var arguments = new int[arity]; |
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/rule/Rule.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/rule/Rule.java index c7b16d47..45b0f02e 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/rule/Rule.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/rule/Rule.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.reasoning.rule; | 6 | package tools.refinery.store.reasoning.rule; |
2 | 7 | ||
3 | import tools.refinery.store.model.Model; | 8 | import tools.refinery.store.model.Model; |
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/rule/RuleAction.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/rule/RuleAction.java index 4753b8bc..97ea7313 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/rule/RuleAction.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/rule/RuleAction.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.reasoning.rule; | 6 | package tools.refinery.store.reasoning.rule; |
2 | 7 | ||
3 | import tools.refinery.store.model.Model; | 8 | import tools.refinery.store.model.Model; |
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/rule/RuleActionExecutor.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/rule/RuleActionExecutor.java index 80bfa6f8..5d743869 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/rule/RuleActionExecutor.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/rule/RuleActionExecutor.java | |||
@@ -1,9 +1,14 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.reasoning.rule; | 6 | package tools.refinery.store.reasoning.rule; |
2 | 7 | ||
3 | import tools.refinery.store.reasoning.MergeResult; | 8 | import tools.refinery.store.reasoning.MergeResult; |
4 | import tools.refinery.store.tuple.TupleLike; | 9 | import tools.refinery.store.tuple.Tuple; |
5 | 10 | ||
6 | @FunctionalInterface | 11 | @FunctionalInterface |
7 | public interface RuleActionExecutor { | 12 | public interface RuleActionExecutor { |
8 | MergeResult execute(TupleLike activationTuple); | 13 | MergeResult execute(Tuple activationTuple); |
9 | } | 14 | } |
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/rule/RuleExecutor.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/rule/RuleExecutor.java index 1e5322b4..32cf13ea 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/rule/RuleExecutor.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/rule/RuleExecutor.java | |||
@@ -1,8 +1,13 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.reasoning.rule; | 6 | package tools.refinery.store.reasoning.rule; |
2 | 7 | ||
3 | import tools.refinery.store.reasoning.MergeResult; | ||
4 | import tools.refinery.store.model.Model; | 8 | import tools.refinery.store.model.Model; |
5 | import tools.refinery.store.tuple.TupleLike; | 9 | import tools.refinery.store.reasoning.MergeResult; |
10 | import tools.refinery.store.tuple.Tuple; | ||
6 | 11 | ||
7 | import java.util.List; | 12 | import java.util.List; |
8 | 13 | ||
@@ -24,7 +29,8 @@ public final class RuleExecutor { | |||
24 | public Model getModel() { | 29 | public Model getModel() { |
25 | return model; | 30 | return model; |
26 | } | 31 | } |
27 | public MergeResult execute(TupleLike activationTuple) { | 32 | |
33 | public MergeResult execute(Tuple activationTuple) { | ||
28 | MergeResult mergeResult = MergeResult.UNCHANGED; | 34 | MergeResult mergeResult = MergeResult.UNCHANGED; |
29 | for (var actionExecutor : actionExecutors) { | 35 | for (var actionExecutor : actionExecutors) { |
30 | mergeResult = mergeResult.andAlso(actionExecutor.execute(activationTuple)); | 36 | mergeResult = mergeResult.andAlso(actionExecutor.execute(activationTuple)); |
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/seed/Seed.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/seed/Seed.java index 90633495..08079f12 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/seed/Seed.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/seed/Seed.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.reasoning.seed; | 6 | package tools.refinery.store.reasoning.seed; |
2 | 7 | ||
3 | import tools.refinery.store.map.Cursor; | 8 | import tools.refinery.store.map.Cursor; |
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/seed/UniformSeed.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/seed/UniformSeed.java index a030f6ea..451d1513 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/seed/UniformSeed.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/seed/UniformSeed.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.reasoning.seed; | 6 | package tools.refinery.store.reasoning.seed; |
2 | 7 | ||
3 | import tools.refinery.store.map.Cursor; | 8 | import tools.refinery.store.map.Cursor; |
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/Advice.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/Advice.java index 5cdfedf7..d6a9e02c 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/Advice.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/Advice.java | |||
@@ -1,10 +1,15 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.reasoning.translator; | 6 | package tools.refinery.store.reasoning.translator; |
2 | 7 | ||
8 | import tools.refinery.store.query.substitution.Substitution; | ||
3 | import tools.refinery.store.reasoning.representation.AnyPartialSymbol; | 9 | import tools.refinery.store.reasoning.representation.AnyPartialSymbol; |
4 | import tools.refinery.store.reasoning.representation.PartialRelation; | 10 | import tools.refinery.store.reasoning.representation.PartialRelation; |
5 | import tools.refinery.store.query.term.Variable; | 11 | import tools.refinery.store.query.term.Variable; |
6 | import tools.refinery.store.query.literal.Literal; | 12 | import tools.refinery.store.query.literal.Literal; |
7 | import tools.refinery.store.query.substitution.Substitutions; | ||
8 | 13 | ||
9 | import java.util.*; | 14 | import java.util.*; |
10 | 15 | ||
@@ -61,14 +66,9 @@ public final class Advice { | |||
61 | public List<Literal> substitute(List<Variable> substituteParameters) { | 66 | public List<Literal> substitute(List<Variable> substituteParameters) { |
62 | checkArity(substituteParameters); | 67 | checkArity(substituteParameters); |
63 | markProcessed(); | 68 | markProcessed(); |
64 | int arity = parameters.size(); | ||
65 | var variableMap = new HashMap<Variable, Variable>(arity); | ||
66 | for (int i = 0; i < arity; i++) { | ||
67 | variableMap.put(parameters.get(i), substituteParameters.get(i)); | ||
68 | } | ||
69 | // Use a renewing substitution to remove any non-parameter variables and avoid clashed between variables | 69 | // Use a renewing substitution to remove any non-parameter variables and avoid clashed between variables |
70 | // coming from different advice in the same clause. | 70 | // coming from different advice in the same clause. |
71 | var substitution = Substitutions.renewing(variableMap); | 71 | var substitution = Substitution.builder().putManyChecked(parameters, substituteParameters).renewing().build(); |
72 | return literals.stream().map(literal -> literal.substitute(substitution)).toList(); | 72 | return literals.stream().map(literal -> literal.substitute(substitution)).toList(); |
73 | } | 73 | } |
74 | 74 | ||
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/AdviceSlot.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/AdviceSlot.java index f3bd9c5e..bab20340 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/AdviceSlot.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/AdviceSlot.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.reasoning.translator; | 6 | package tools.refinery.store.reasoning.translator; |
2 | 7 | ||
3 | import tools.refinery.store.representation.TruthValue; | 8 | import tools.refinery.store.representation.TruthValue; |
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/TranslatedRelation.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/TranslatedRelation.java index 9bab80c9..4a5a8843 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/TranslatedRelation.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/TranslatedRelation.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.reasoning.translator; | 6 | package tools.refinery.store.reasoning.translator; |
2 | 7 | ||
3 | import tools.refinery.store.model.Model; | 8 | import tools.refinery.store.model.Model; |
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/TranslationUnit.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/TranslationUnit.java index 24b93911..6e44a7d7 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/TranslationUnit.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/TranslationUnit.java | |||
@@ -1,7 +1,11 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.reasoning.translator; | 6 | package tools.refinery.store.reasoning.translator; |
2 | 7 | ||
3 | import tools.refinery.store.model.Model; | 8 | import tools.refinery.store.model.Model; |
4 | import tools.refinery.store.model.ModelStoreBuilder; | ||
5 | import tools.refinery.store.reasoning.ReasoningBuilder; | 9 | import tools.refinery.store.reasoning.ReasoningBuilder; |
6 | 10 | ||
7 | import java.util.Collection; | 11 | import java.util.Collection; |
@@ -18,10 +22,6 @@ public abstract class TranslationUnit { | |||
18 | configureReasoningBuilder(); | 22 | configureReasoningBuilder(); |
19 | } | 23 | } |
20 | 24 | ||
21 | protected ModelStoreBuilder getModelStoreBuilder() { | ||
22 | return reasoningBuilder.getStoreBuilder(); | ||
23 | } | ||
24 | |||
25 | protected void configureReasoningBuilder() { | 25 | protected void configureReasoningBuilder() { |
26 | // Nothing to configure by default. | 26 | // Nothing to configure by default. |
27 | } | 27 | } |
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/base/BaseDecisionInterpretation.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/base/BaseDecisionInterpretation.java index b703f142..e7b67ae4 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/base/BaseDecisionInterpretation.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/base/BaseDecisionInterpretation.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.reasoning.translator.base; | 6 | package tools.refinery.store.reasoning.translator.base; |
2 | 7 | ||
3 | import tools.refinery.store.map.Cursor; | 8 | import tools.refinery.store.map.Cursor; |
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/base/BaseDecisionTranslationUnit.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/base/BaseDecisionTranslationUnit.java index 36e2782a..a1e4b816 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/base/BaseDecisionTranslationUnit.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/base/BaseDecisionTranslationUnit.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.reasoning.translator.base; | 6 | package tools.refinery.store.reasoning.translator.base; |
2 | 7 | ||
3 | import tools.refinery.store.model.Model; | 8 | import tools.refinery.store.model.Model; |
@@ -24,7 +29,7 @@ public class BaseDecisionTranslationUnit extends TranslationUnit { | |||
24 | } | 29 | } |
25 | this.partialRelation = partialRelation; | 30 | this.partialRelation = partialRelation; |
26 | this.seed = seed; | 31 | this.seed = seed; |
27 | symbol = new Symbol<>(partialRelation.name(), partialRelation.arity(), TruthValue.class, TruthValue.UNKNOWN); | 32 | symbol = Symbol.of(partialRelation.name(), partialRelation.arity(), TruthValue.class, TruthValue.UNKNOWN); |
28 | } | 33 | } |
29 | 34 | ||
30 | public BaseDecisionTranslationUnit(PartialRelation partialRelation) { | 35 | public BaseDecisionTranslationUnit(PartialRelation partialRelation) { |
@@ -32,11 +37,6 @@ public class BaseDecisionTranslationUnit extends TranslationUnit { | |||
32 | } | 37 | } |
33 | 38 | ||
34 | @Override | 39 | @Override |
35 | protected void configureReasoningBuilder() { | ||
36 | getModelStoreBuilder().symbol(symbol); | ||
37 | } | ||
38 | |||
39 | @Override | ||
40 | public Collection<TranslatedRelation> getTranslatedRelations() { | 40 | public Collection<TranslatedRelation> getTranslatedRelations() { |
41 | return List.of(new TranslatedBaseDecision(getReasoningBuilder(), partialRelation, symbol)); | 41 | return List.of(new TranslatedBaseDecision(getReasoningBuilder(), partialRelation, symbol)); |
42 | } | 42 | } |
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/base/TranslatedBaseDecision.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/base/TranslatedBaseDecision.java index 2294b4fd..4782eb46 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/base/TranslatedBaseDecision.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/base/TranslatedBaseDecision.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.reasoning.translator.base; | 6 | package tools.refinery.store.reasoning.translator.base; |
2 | 7 | ||
3 | import tools.refinery.store.model.Model; | 8 | import tools.refinery.store.model.Model; |
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/EliminatedType.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/EliminatedType.java index 1b8d7cc9..6e4728db 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/EliminatedType.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/EliminatedType.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.reasoning.translator.typehierarchy; | 6 | package tools.refinery.store.reasoning.translator.typehierarchy; |
2 | 7 | ||
3 | import tools.refinery.store.reasoning.representation.PartialRelation; | 8 | import tools.refinery.store.reasoning.representation.PartialRelation; |
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/ExtendedTypeInfo.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/ExtendedTypeInfo.java index 43b8e1dd..7a917dcf 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/ExtendedTypeInfo.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/ExtendedTypeInfo.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.reasoning.translator.typehierarchy; | 6 | package tools.refinery.store.reasoning.translator.typehierarchy; |
2 | 7 | ||
3 | import org.jetbrains.annotations.NotNull; | 8 | import org.jetbrains.annotations.NotNull; |
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/InferredMayTypeRelationView.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/InferredMayTypeView.java index 12c37c86..ce2d6ff3 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/InferredMayTypeRelationView.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/InferredMayTypeView.java | |||
@@ -1,13 +1,18 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.reasoning.translator.typehierarchy; | 6 | package tools.refinery.store.reasoning.translator.typehierarchy; |
2 | 7 | ||
3 | import tools.refinery.store.reasoning.representation.PartialRelation; | 8 | import tools.refinery.store.reasoning.representation.PartialRelation; |
4 | import tools.refinery.store.query.view.TuplePreservingRelationView; | 9 | import tools.refinery.store.query.view.TuplePreservingView; |
5 | import tools.refinery.store.tuple.Tuple; | 10 | import tools.refinery.store.tuple.Tuple; |
6 | 11 | ||
7 | class InferredMayTypeRelationView extends TuplePreservingRelationView<InferredType> { | 12 | class InferredMayTypeView extends TuplePreservingView<InferredType> { |
8 | private final PartialRelation type; | 13 | private final PartialRelation type; |
9 | 14 | ||
10 | InferredMayTypeRelationView(PartialRelation type) { | 15 | InferredMayTypeView(PartialRelation type) { |
11 | super(TypeHierarchyTranslationUnit.INFERRED_TYPE_SYMBOL, "%s#may".formatted(type)); | 16 | super(TypeHierarchyTranslationUnit.INFERRED_TYPE_SYMBOL, "%s#may".formatted(type)); |
12 | this.type = type; | 17 | this.type = type; |
13 | } | 18 | } |
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/InferredMustTypeRelationView.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/InferredMustTypeView.java index 975f627e..beda1796 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/InferredMustTypeRelationView.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/InferredMustTypeView.java | |||
@@ -1,13 +1,18 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.reasoning.translator.typehierarchy; | 6 | package tools.refinery.store.reasoning.translator.typehierarchy; |
2 | 7 | ||
3 | import tools.refinery.store.reasoning.representation.PartialRelation; | 8 | import tools.refinery.store.reasoning.representation.PartialRelation; |
4 | import tools.refinery.store.query.view.TuplePreservingRelationView; | 9 | import tools.refinery.store.query.view.TuplePreservingView; |
5 | import tools.refinery.store.tuple.Tuple; | 10 | import tools.refinery.store.tuple.Tuple; |
6 | 11 | ||
7 | class InferredMustTypeRelationView extends TuplePreservingRelationView<InferredType> { | 12 | class InferredMustTypeView extends TuplePreservingView<InferredType> { |
8 | private final PartialRelation type; | 13 | private final PartialRelation type; |
9 | 14 | ||
10 | InferredMustTypeRelationView(PartialRelation type) { | 15 | InferredMustTypeView(PartialRelation type) { |
11 | super(TypeHierarchyTranslationUnit.INFERRED_TYPE_SYMBOL, "%s#must".formatted(type)); | 16 | super(TypeHierarchyTranslationUnit.INFERRED_TYPE_SYMBOL, "%s#must".formatted(type)); |
12 | this.type = type; | 17 | this.type = type; |
13 | } | 18 | } |
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/InferredType.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/InferredType.java index a366e262..fd05158b 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/InferredType.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/InferredType.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.reasoning.translator.typehierarchy; | 6 | package tools.refinery.store.reasoning.translator.typehierarchy; |
2 | 7 | ||
3 | import tools.refinery.store.reasoning.representation.PartialRelation; | 8 | import tools.refinery.store.reasoning.representation.PartialRelation; |
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/PreservedType.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/PreservedType.java index 63dba964..0696f4c3 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/PreservedType.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/PreservedType.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.reasoning.translator.typehierarchy; | 6 | package tools.refinery.store.reasoning.translator.typehierarchy; |
2 | 7 | ||
3 | import tools.refinery.store.reasoning.representation.PartialRelation; | 8 | import tools.refinery.store.reasoning.representation.PartialRelation; |
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/TypeAnalysisResult.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/TypeAnalysisResult.java index 4f915108..fbf8a7c9 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/TypeAnalysisResult.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/TypeAnalysisResult.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.reasoning.translator.typehierarchy; | 6 | package tools.refinery.store.reasoning.translator.typehierarchy; |
2 | 7 | ||
3 | sealed interface TypeAnalysisResult permits EliminatedType, PreservedType { | 8 | sealed interface TypeAnalysisResult permits EliminatedType, PreservedType { |
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/TypeAnalyzer.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/TypeAnalyzer.java index 62f8e750..e97ce954 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/TypeAnalyzer.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/TypeAnalyzer.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.reasoning.translator.typehierarchy; | 6 | package tools.refinery.store.reasoning.translator.typehierarchy; |
2 | 7 | ||
3 | import tools.refinery.store.reasoning.representation.PartialRelation; | 8 | import tools.refinery.store.reasoning.representation.PartialRelation; |
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/TypeHierarchyTranslationUnit.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/TypeHierarchyTranslationUnit.java index 4b0761f2..06e3c05f 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/TypeHierarchyTranslationUnit.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/TypeHierarchyTranslationUnit.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.reasoning.translator.typehierarchy; | 6 | package tools.refinery.store.reasoning.translator.typehierarchy; |
2 | 7 | ||
3 | import tools.refinery.store.model.Model; | 8 | import tools.refinery.store.model.Model; |
@@ -11,8 +16,8 @@ import java.util.List; | |||
11 | import java.util.Map; | 16 | import java.util.Map; |
12 | 17 | ||
13 | public class TypeHierarchyTranslationUnit extends TranslationUnit { | 18 | public class TypeHierarchyTranslationUnit extends TranslationUnit { |
14 | static final Symbol<InferredType> INFERRED_TYPE_SYMBOL = new Symbol<>("inferredType", 1, | 19 | static final Symbol<InferredType> INFERRED_TYPE_SYMBOL = Symbol.of( |
15 | InferredType.class, InferredType.UNTYPED); | 20 | "inferredType", 1, InferredType.class, InferredType.UNTYPED); |
16 | 21 | ||
17 | private final TypeAnalyzer typeAnalyzer; | 22 | private final TypeAnalyzer typeAnalyzer; |
18 | 23 | ||
diff --git a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/TypeInfo.java b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/TypeInfo.java index 313df4df..9f897e46 100644 --- a/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/TypeInfo.java +++ b/subprojects/store-reasoning/src/main/java/tools/refinery/store/reasoning/translator/typehierarchy/TypeInfo.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.reasoning.translator.typehierarchy; | 6 | package tools.refinery.store.reasoning.translator.typehierarchy; |
2 | 7 | ||
3 | import tools.refinery.store.reasoning.representation.PartialRelation; | 8 | import tools.refinery.store.reasoning.representation.PartialRelation; |
diff --git a/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/translator/typehierarchy/InferredTypeTest.java b/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/translator/typehierarchy/InferredTypeTest.java index a8df2312..1d76855c 100644 --- a/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/translator/typehierarchy/InferredTypeTest.java +++ b/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/translator/typehierarchy/InferredTypeTest.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.reasoning.translator.typehierarchy; | 6 | package tools.refinery.store.reasoning.translator.typehierarchy; |
2 | 7 | ||
3 | import org.junit.jupiter.api.Test; | 8 | import org.junit.jupiter.api.Test; |
diff --git a/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/translator/typehierarchy/TypeAnalyzerExampleHierarchyTest.java b/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/translator/typehierarchy/TypeAnalyzerExampleHierarchyTest.java index b2c1ef1b..05a476c6 100644 --- a/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/translator/typehierarchy/TypeAnalyzerExampleHierarchyTest.java +++ b/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/translator/typehierarchy/TypeAnalyzerExampleHierarchyTest.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.reasoning.translator.typehierarchy; | 6 | package tools.refinery.store.reasoning.translator.typehierarchy; |
2 | 7 | ||
3 | import org.junit.jupiter.api.BeforeEach; | 8 | import org.junit.jupiter.api.BeforeEach; |
diff --git a/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/translator/typehierarchy/TypeAnalyzerTest.java b/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/translator/typehierarchy/TypeAnalyzerTest.java index b7b69ed8..d0ef9d57 100644 --- a/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/translator/typehierarchy/TypeAnalyzerTest.java +++ b/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/translator/typehierarchy/TypeAnalyzerTest.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.reasoning.translator.typehierarchy; | 6 | package tools.refinery.store.reasoning.translator.typehierarchy; |
2 | 7 | ||
3 | import org.junit.jupiter.api.Test; | 8 | import org.junit.jupiter.api.Test; |
diff --git a/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/translator/typehierarchy/TypeAnalyzerTester.java b/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/translator/typehierarchy/TypeAnalyzerTester.java index 56407730..2924816e 100644 --- a/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/translator/typehierarchy/TypeAnalyzerTester.java +++ b/subprojects/store-reasoning/src/test/java/tools/refinery/store/reasoning/translator/typehierarchy/TypeAnalyzerTester.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.reasoning.translator.typehierarchy; | 6 | package tools.refinery.store.reasoning.translator.typehierarchy; |
2 | 7 | ||
3 | import tools.refinery.store.reasoning.representation.PartialRelation; | 8 | import tools.refinery.store.reasoning.representation.PartialRelation; |
diff --git a/subprojects/store/build.gradle b/subprojects/store/build.gradle deleted file mode 100644 index 370d094b..00000000 --- a/subprojects/store/build.gradle +++ /dev/null | |||
@@ -1,4 +0,0 @@ | |||
1 | plugins { | ||
2 | id 'refinery-java-library' | ||
3 | id 'refinery-jmh' | ||
4 | } | ||
diff --git a/subprojects/store/build.gradle.kts b/subprojects/store/build.gradle.kts new file mode 100644 index 00000000..2c485020 --- /dev/null +++ b/subprojects/store/build.gradle.kts | |||
@@ -0,0 +1,10 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
7 | plugins { | ||
8 | id("tools.refinery.gradle.java-library") | ||
9 | id("tools.refinery.gradle.jmh") | ||
10 | } | ||
diff --git a/subprojects/store/src/jmh/java/tools/refinery/store/map/benchmarks/ImmutablePutBenchmark.java b/subprojects/store/src/jmh/java/tools/refinery/store/map/benchmarks/ImmutablePutBenchmark.java index cdf3d3c8..485fda3d 100644 --- a/subprojects/store/src/jmh/java/tools/refinery/store/map/benchmarks/ImmutablePutBenchmark.java +++ b/subprojects/store/src/jmh/java/tools/refinery/store/map/benchmarks/ImmutablePutBenchmark.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map.benchmarks; | 6 | package tools.refinery.store.map.benchmarks; |
2 | 7 | ||
3 | import java.util.ArrayList; | 8 | import java.util.ArrayList; |
diff --git a/subprojects/store/src/jmh/java/tools/refinery/store/map/benchmarks/ImmutablePutExecutionPlan.java b/subprojects/store/src/jmh/java/tools/refinery/store/map/benchmarks/ImmutablePutExecutionPlan.java index 756d504e..edd4f53e 100644 --- a/subprojects/store/src/jmh/java/tools/refinery/store/map/benchmarks/ImmutablePutExecutionPlan.java +++ b/subprojects/store/src/jmh/java/tools/refinery/store/map/benchmarks/ImmutablePutExecutionPlan.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map.benchmarks; | 6 | package tools.refinery.store.map.benchmarks; |
2 | 7 | ||
3 | import java.util.Random; | 8 | import java.util.Random; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/adapter/AbstractModelAdapterBuilder.java b/subprojects/store/src/main/java/tools/refinery/store/adapter/AbstractModelAdapterBuilder.java index 4c142217..8d3e998e 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/adapter/AbstractModelAdapterBuilder.java +++ b/subprojects/store/src/main/java/tools/refinery/store/adapter/AbstractModelAdapterBuilder.java | |||
@@ -1,27 +1,48 @@ | |||
1 | package tools.refinery.store.adapter; | 1 | package tools.refinery.store.adapter; |
2 | 2 | /* | |
3 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
4 | * | ||
5 | * SPDX-License-Identifier: EPL-2.0 | ||
6 | */ | ||
3 | import tools.refinery.store.model.ModelStore; | 7 | import tools.refinery.store.model.ModelStore; |
4 | import tools.refinery.store.model.ModelStoreBuilder; | 8 | import tools.refinery.store.model.ModelStoreBuilder; |
5 | 9 | ||
6 | public abstract class AbstractModelAdapterBuilder implements ModelAdapterBuilder { | 10 | public abstract class AbstractModelAdapterBuilder<T extends ModelStoreAdapter> implements ModelAdapterBuilder { |
7 | private final ModelStoreBuilder storeBuilder; | 11 | private boolean configured; |
8 | 12 | ||
9 | protected AbstractModelAdapterBuilder(ModelStoreBuilder storeBuilder) { | 13 | @Override |
10 | this.storeBuilder = storeBuilder; | 14 | public boolean isConfigured() { |
15 | return configured; | ||
11 | } | 16 | } |
12 | 17 | ||
13 | @Override | 18 | protected void checkConfigured() { |
14 | public <T extends ModelAdapterBuilder> T with(ModelAdapterBuilderFactory<?, ?, T> adapterBuilderFactory) { | 19 | if (!configured) { |
15 | return storeBuilder.with(adapterBuilderFactory); | 20 | throw new IllegalStateException("Model adapter builder was not configured"); |
21 | } | ||
22 | } | ||
23 | |||
24 | protected void checkNotConfigured() { | ||
25 | if (configured) { | ||
26 | throw new IllegalStateException("Model adapter builder was already configured"); | ||
27 | } | ||
28 | } | ||
29 | |||
30 | protected void doConfigure(ModelStoreBuilder storeBuilder) { | ||
31 | // Nothing to configure by default. | ||
16 | } | 32 | } |
17 | 33 | ||
18 | @Override | 34 | @Override |
19 | public ModelStoreBuilder getStoreBuilder() { | 35 | public final void configure(ModelStoreBuilder storeBuilder) { |
20 | return storeBuilder; | 36 | checkNotConfigured(); |
37 | doConfigure(storeBuilder); | ||
38 | configured = true; | ||
21 | } | 39 | } |
22 | 40 | ||
41 | protected abstract T doBuild(ModelStore store); | ||
42 | |||
23 | @Override | 43 | @Override |
24 | public ModelStore build() { | 44 | public final T build(ModelStore store) { |
25 | return storeBuilder.build(); | 45 | checkConfigured(); |
46 | return doBuild(store); | ||
26 | } | 47 | } |
27 | } | 48 | } |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/adapter/AdapterList.java b/subprojects/store/src/main/java/tools/refinery/store/adapter/AdapterList.java deleted file mode 100644 index 74bae6f0..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/adapter/AdapterList.java +++ /dev/null | |||
@@ -1,97 +0,0 @@ | |||
1 | package tools.refinery.store.adapter; | ||
2 | |||
3 | import org.jetbrains.annotations.NotNull; | ||
4 | |||
5 | import java.util.*; | ||
6 | import java.util.function.Consumer; | ||
7 | |||
8 | public class AdapterList<T> implements Iterable<T> { | ||
9 | private final List<AnyModelAdapterType> adapterTypes; | ||
10 | private final List<T> adapters; | ||
11 | |||
12 | public AdapterList() { | ||
13 | adapterTypes = new ArrayList<>(); | ||
14 | adapters = new ArrayList<>(); | ||
15 | } | ||
16 | |||
17 | public AdapterList(int adapterCount) { | ||
18 | adapterTypes = new ArrayList<>(adapterCount); | ||
19 | adapters = new ArrayList<>(adapterCount); | ||
20 | } | ||
21 | |||
22 | public int size() { | ||
23 | return adapters.size(); | ||
24 | } | ||
25 | |||
26 | public void add(AnyModelAdapterType adapterType, T adapter) { | ||
27 | adapterTypes.add(adapterType); | ||
28 | adapters.add(adapter); | ||
29 | } | ||
30 | |||
31 | public <U extends T> Optional<U> tryGet(AnyModelAdapterType adapterType, Class<? extends U> adapterClass) { | ||
32 | int size = size(); | ||
33 | for (int i = 0; i < size; i++) { | ||
34 | if (getType(i).supports(adapterType)) { | ||
35 | return Optional.of(adapterClass.cast(get(i))); | ||
36 | } | ||
37 | } | ||
38 | return Optional.empty(); | ||
39 | } | ||
40 | |||
41 | public <U extends T> U get(AnyModelAdapterType adapterType, Class<U> adapterClass) { | ||
42 | return tryGet(adapterType, adapterClass).orElseThrow(() -> new IllegalArgumentException( | ||
43 | "No %s was configured".formatted(adapterType))); | ||
44 | } | ||
45 | |||
46 | public AnyModelAdapterType getType(int i) { | ||
47 | return adapterTypes.get(i); | ||
48 | } | ||
49 | |||
50 | public T get(int i) { | ||
51 | return adapters.get(i); | ||
52 | } | ||
53 | |||
54 | public Collection<AnyModelAdapterType> getAdapterTypes() { | ||
55 | return Collections.unmodifiableCollection(adapterTypes); | ||
56 | } | ||
57 | |||
58 | public Iterable<Entry<T>> withAdapterTypes() { | ||
59 | return () -> new Iterator<>() { | ||
60 | private int i = 0; | ||
61 | |||
62 | @Override | ||
63 | public boolean hasNext() { | ||
64 | return i < size(); | ||
65 | } | ||
66 | |||
67 | @Override | ||
68 | public Entry<T> next() { | ||
69 | if (i >= size()) { | ||
70 | throw new NoSuchElementException(); | ||
71 | } | ||
72 | var entry = new Entry<>(getType(i), get(i)); | ||
73 | i++; | ||
74 | return entry; | ||
75 | } | ||
76 | }; | ||
77 | } | ||
78 | |||
79 | @NotNull | ||
80 | @Override | ||
81 | public Iterator<T> iterator() { | ||
82 | return adapters.iterator(); | ||
83 | } | ||
84 | |||
85 | @Override | ||
86 | public void forEach(Consumer<? super T> action) { | ||
87 | adapters.forEach(action); | ||
88 | } | ||
89 | |||
90 | @Override | ||
91 | public Spliterator<T> spliterator() { | ||
92 | return adapters.spliterator(); | ||
93 | } | ||
94 | |||
95 | public record Entry<T>(AnyModelAdapterType adapterType, T adapter) { | ||
96 | } | ||
97 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/adapter/AdapterUtils.java b/subprojects/store/src/main/java/tools/refinery/store/adapter/AdapterUtils.java new file mode 100644 index 00000000..556e99f0 --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/adapter/AdapterUtils.java | |||
@@ -0,0 +1,33 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.adapter; | ||
7 | |||
8 | import java.util.Collection; | ||
9 | import java.util.Optional; | ||
10 | |||
11 | public class AdapterUtils { | ||
12 | private AdapterUtils() { | ||
13 | throw new IllegalStateException("This is a static utility class and should not be instantiated directly"); | ||
14 | } | ||
15 | |||
16 | public static <T, U extends T> Optional<U> tryGetAdapter(Collection<T> adapters, Class<? extends U> type) { | ||
17 | var iterator = adapters.stream().filter(type::isInstance).iterator(); | ||
18 | if (!iterator.hasNext()) { | ||
19 | return Optional.empty(); | ||
20 | } | ||
21 | var adapter = type.cast(iterator.next()); | ||
22 | if (iterator.hasNext()) { | ||
23 | throw new IllegalArgumentException("Ambiguous adapter: both %s and %s match %s" | ||
24 | .formatted(adapter.getClass().getName(), iterator.next().getClass().getName(), type.getName())); | ||
25 | } | ||
26 | return Optional.of(adapter); | ||
27 | } | ||
28 | |||
29 | public static <T> T getAdapter(Collection<? super T> adapters, Class<T> type) { | ||
30 | return tryGetAdapter(adapters, type).orElseThrow(() -> new IllegalArgumentException( | ||
31 | "No %s adapter was configured".formatted(type.getName()))); | ||
32 | } | ||
33 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/adapter/AnyModelAdapterType.java b/subprojects/store/src/main/java/tools/refinery/store/adapter/AnyModelAdapterType.java deleted file mode 100644 index 37a247fe..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/adapter/AnyModelAdapterType.java +++ /dev/null | |||
@@ -1,19 +0,0 @@ | |||
1 | package tools.refinery.store.adapter; | ||
2 | |||
3 | import java.util.Collection; | ||
4 | |||
5 | public sealed interface AnyModelAdapterType permits ModelAdapterType { | ||
6 | Class<? extends ModelAdapter> getModelAdapterClass(); | ||
7 | |||
8 | Class<? extends ModelStoreAdapter> getModelStoreAdapterClass(); | ||
9 | |||
10 | Class<? extends ModelAdapterBuilder> getModelAdapterBuilderClass(); | ||
11 | |||
12 | Collection<AnyModelAdapterType> getSupportedAdapterTypes(); | ||
13 | |||
14 | default boolean supports(AnyModelAdapterType targetAdapter) { | ||
15 | return getSupportedAdapterTypes().contains(targetAdapter); | ||
16 | } | ||
17 | |||
18 | String getName(); | ||
19 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/adapter/ModelAdapter.java b/subprojects/store/src/main/java/tools/refinery/store/adapter/ModelAdapter.java index aa079e01..672007aa 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/adapter/ModelAdapter.java +++ b/subprojects/store/src/main/java/tools/refinery/store/adapter/ModelAdapter.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.adapter; | 6 | package tools.refinery.store.adapter; |
2 | 7 | ||
3 | import tools.refinery.store.model.Model; | 8 | import tools.refinery.store.model.Model; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/adapter/ModelAdapterBuilder.java b/subprojects/store/src/main/java/tools/refinery/store/adapter/ModelAdapterBuilder.java index 64b3e59f..75e5e07d 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/adapter/ModelAdapterBuilder.java +++ b/subprojects/store/src/main/java/tools/refinery/store/adapter/ModelAdapterBuilder.java | |||
@@ -1,17 +1,17 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.adapter; | 6 | package tools.refinery.store.adapter; |
2 | 7 | ||
3 | import tools.refinery.store.model.ModelStore; | 8 | import tools.refinery.store.model.ModelStore; |
4 | import tools.refinery.store.model.ModelStoreBuilder; | 9 | import tools.refinery.store.model.ModelStoreBuilder; |
5 | 10 | ||
6 | public interface ModelAdapterBuilder { | 11 | public interface ModelAdapterBuilder { |
7 | ModelStoreAdapter createStoreAdapter(ModelStore store); | 12 | boolean isConfigured(); |
8 | 13 | ||
9 | <T extends ModelAdapterBuilder> T with(ModelAdapterBuilderFactory<?, ?, T> adapterBuilderFactory); | 14 | void configure(ModelStoreBuilder storeBuilder); |
10 | 15 | ||
11 | ModelStoreBuilder getStoreBuilder(); | 16 | ModelStoreAdapter build(ModelStore store); |
12 | |||
13 | default void configure() { | ||
14 | } | ||
15 | |||
16 | ModelStore build(); | ||
17 | } | 17 | } |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/adapter/ModelAdapterBuilderFactory.java b/subprojects/store/src/main/java/tools/refinery/store/adapter/ModelAdapterBuilderFactory.java deleted file mode 100644 index 7c9b01bc..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/adapter/ModelAdapterBuilderFactory.java +++ /dev/null | |||
@@ -1,14 +0,0 @@ | |||
1 | package tools.refinery.store.adapter; | ||
2 | |||
3 | import tools.refinery.store.model.ModelStoreBuilder; | ||
4 | |||
5 | public abstract class ModelAdapterBuilderFactory<T1 extends ModelAdapter, T2 extends ModelStoreAdapter, | ||
6 | T3 extends ModelAdapterBuilder> extends ModelAdapterType<T1, T2, T3> { | ||
7 | |||
8 | protected ModelAdapterBuilderFactory(Class<T1> modelAdapterClass, Class<T2> modelStoreAdapterClass, | ||
9 | Class<T3> modelAdapterBuilderClass) { | ||
10 | super(modelAdapterClass, modelStoreAdapterClass, modelAdapterBuilderClass); | ||
11 | } | ||
12 | |||
13 | public abstract T3 createBuilder(ModelStoreBuilder storeBuilder); | ||
14 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/adapter/ModelAdapterType.java b/subprojects/store/src/main/java/tools/refinery/store/adapter/ModelAdapterType.java deleted file mode 100644 index 82ddeb12..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/adapter/ModelAdapterType.java +++ /dev/null | |||
@@ -1,79 +0,0 @@ | |||
1 | package tools.refinery.store.adapter; | ||
2 | |||
3 | import tools.refinery.store.model.Model; | ||
4 | import tools.refinery.store.model.ModelStore; | ||
5 | |||
6 | import java.lang.reflect.Method; | ||
7 | import java.util.Collection; | ||
8 | import java.util.Collections; | ||
9 | import java.util.HashSet; | ||
10 | import java.util.Set; | ||
11 | |||
12 | public abstract non-sealed class ModelAdapterType<T1 extends ModelAdapter, T2 extends ModelStoreAdapter, | ||
13 | T3 extends ModelAdapterBuilder> implements AnyModelAdapterType { | ||
14 | private final Class<? extends T1> modelAdapterClass; | ||
15 | private final Class<? extends T2> modelStoreAdapterClass; | ||
16 | private final Class<? extends T3> modelAdapterBuilderClass; | ||
17 | private final Set<AnyModelAdapterType> supportedAdapters = new HashSet<>(); | ||
18 | |||
19 | protected ModelAdapterType(Class<T1> modelAdapterClass, Class<T2> modelStoreAdapterClass, | ||
20 | Class<T3> modelAdapterBuilderClass) { | ||
21 | checkReturnType(modelAdapterClass, modelStoreAdapterClass, "createModelAdapter", Model.class); | ||
22 | checkReturnType(modelStoreAdapterClass, modelAdapterBuilderClass, "createStoreAdapter", ModelStore.class); | ||
23 | this.modelAdapterClass = modelAdapterClass; | ||
24 | this.modelStoreAdapterClass = modelStoreAdapterClass; | ||
25 | this.modelAdapterBuilderClass = modelAdapterBuilderClass; | ||
26 | supportedAdapters.add(this); | ||
27 | } | ||
28 | |||
29 | private void checkReturnType(Class<?> expectedReturnType, Class<?> ownerClass, String methodName, | ||
30 | Class<?>... argumentTypes) { | ||
31 | Method method; | ||
32 | try { | ||
33 | method = ownerClass.getMethod(methodName, argumentTypes); | ||
34 | } catch (NoSuchMethodException e) { | ||
35 | throw new IllegalStateException("Invalid %s: %s#%s method is required" | ||
36 | .formatted(this, ownerClass.getName(), methodName), e); | ||
37 | } | ||
38 | var returnType = method.getReturnType(); | ||
39 | if (!expectedReturnType.isAssignableFrom(returnType)) { | ||
40 | throw new IllegalStateException("Invalid %s: %s is not assignable from the return type %s of %s#%s" | ||
41 | .formatted(this, expectedReturnType.getName(), returnType.getCanonicalName(), | ||
42 | ownerClass.getName(), methodName)); | ||
43 | } | ||
44 | } | ||
45 | |||
46 | protected void extendsAdapter(ModelAdapterType<? super T1, ? super T2, ? super T3> superAdapter) { | ||
47 | supportedAdapters.addAll(superAdapter.supportedAdapters); | ||
48 | } | ||
49 | |||
50 | @Override | ||
51 | public final Class<? extends T1> getModelAdapterClass() { | ||
52 | return modelAdapterClass; | ||
53 | } | ||
54 | |||
55 | @Override | ||
56 | public final Class<? extends T2> getModelStoreAdapterClass() { | ||
57 | return modelStoreAdapterClass; | ||
58 | } | ||
59 | |||
60 | @Override | ||
61 | public final Class<? extends T3> getModelAdapterBuilderClass() { | ||
62 | return modelAdapterBuilderClass; | ||
63 | } | ||
64 | |||
65 | @Override | ||
66 | public Collection<AnyModelAdapterType> getSupportedAdapterTypes() { | ||
67 | return Collections.unmodifiableCollection(supportedAdapters); | ||
68 | } | ||
69 | |||
70 | @Override | ||
71 | public String getName() { | ||
72 | return "%s.ADAPTER".formatted(this.getClass().getName()); | ||
73 | } | ||
74 | |||
75 | @Override | ||
76 | public String toString() { | ||
77 | return getName(); | ||
78 | } | ||
79 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/adapter/ModelStoreAdapter.java b/subprojects/store/src/main/java/tools/refinery/store/adapter/ModelStoreAdapter.java index 1eb40ada..bc5f7b6b 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/adapter/ModelStoreAdapter.java +++ b/subprojects/store/src/main/java/tools/refinery/store/adapter/ModelStoreAdapter.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.adapter; | 6 | package tools.refinery.store.adapter; |
2 | 7 | ||
3 | import tools.refinery.store.model.Model; | 8 | import tools.refinery.store.model.Model; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/AnyVersionedMap.java b/subprojects/store/src/main/java/tools/refinery/store/map/AnyVersionedMap.java index f82a8bb1..25fc91e6 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/map/AnyVersionedMap.java +++ b/subprojects/store/src/main/java/tools/refinery/store/map/AnyVersionedMap.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map; | 6 | package tools.refinery.store.map; |
2 | 7 | ||
3 | public sealed interface AnyVersionedMap extends Versioned permits VersionedMap { | 8 | public sealed interface AnyVersionedMap extends Versioned permits VersionedMap { |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/ContentHashCode.java b/subprojects/store/src/main/java/tools/refinery/store/map/ContentHashCode.java index 8deeab23..cbea05e1 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/map/ContentHashCode.java +++ b/subprojects/store/src/main/java/tools/refinery/store/map/ContentHashCode.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map; | 6 | package tools.refinery.store.map; |
2 | 7 | ||
3 | public enum ContentHashCode { | 8 | public enum ContentHashCode { |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/ContinousHashProvider.java b/subprojects/store/src/main/java/tools/refinery/store/map/ContinousHashProvider.java index 75f1e2ab..8e451230 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/map/ContinousHashProvider.java +++ b/subprojects/store/src/main/java/tools/refinery/store/map/ContinousHashProvider.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map; | 6 | package tools.refinery.store.map; |
2 | 7 | ||
3 | import tools.refinery.store.map.internal.Node; | 8 | import tools.refinery.store.map.internal.Node; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/Cursor.java b/subprojects/store/src/main/java/tools/refinery/store/map/Cursor.java index b420585c..3bdca104 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/map/Cursor.java +++ b/subprojects/store/src/main/java/tools/refinery/store/map/Cursor.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map; | 6 | package tools.refinery.store.map; |
2 | 7 | ||
3 | import java.util.Set; | 8 | import java.util.Set; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/CursorAsIterator.java b/subprojects/store/src/main/java/tools/refinery/store/map/CursorAsIterator.java index 65ae6648..c7e4d279 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/map/CursorAsIterator.java +++ b/subprojects/store/src/main/java/tools/refinery/store/map/CursorAsIterator.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map; | 6 | package tools.refinery.store.map; |
2 | 7 | ||
3 | import java.util.Iterator; | 8 | import java.util.Iterator; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/Cursors.java b/subprojects/store/src/main/java/tools/refinery/store/map/Cursors.java index fc8e628b..0a94d449 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/map/Cursors.java +++ b/subprojects/store/src/main/java/tools/refinery/store/map/Cursors.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map; | 6 | package tools.refinery.store.map; |
2 | 7 | ||
3 | public final class Cursors { | 8 | public final class Cursors { |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/DiffCursor.java b/subprojects/store/src/main/java/tools/refinery/store/map/DiffCursor.java index 701f3ec8..4322e041 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/map/DiffCursor.java +++ b/subprojects/store/src/main/java/tools/refinery/store/map/DiffCursor.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map; | 6 | package tools.refinery.store.map; |
2 | 7 | ||
3 | public interface DiffCursor<K, V> extends Cursor<K,V> { | 8 | public interface DiffCursor<K, V> extends Cursor<K,V> { |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/MapAsIterable.java b/subprojects/store/src/main/java/tools/refinery/store/map/MapAsIterable.java index 6b986732..199b548f 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/map/MapAsIterable.java +++ b/subprojects/store/src/main/java/tools/refinery/store/map/MapAsIterable.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map; | 6 | package tools.refinery.store.map; |
2 | 7 | ||
3 | import java.util.Iterator; | 8 | import java.util.Iterator; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/Versioned.java b/subprojects/store/src/main/java/tools/refinery/store/map/Versioned.java index 6a23e9d5..55720db3 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/map/Versioned.java +++ b/subprojects/store/src/main/java/tools/refinery/store/map/Versioned.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map; | 6 | package tools.refinery.store.map; |
2 | 7 | ||
3 | public interface Versioned { | 8 | public interface Versioned { |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMap.java b/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMap.java index 31985e94..9bbde24d 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMap.java +++ b/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMap.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map; | 6 | package tools.refinery.store.map; |
2 | 7 | ||
3 | public non-sealed interface VersionedMap<K, V> extends AnyVersionedMap { | 8 | public non-sealed interface VersionedMap<K, V> extends AnyVersionedMap { |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStore.java b/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStore.java index a8d7fb1a..5aafa338 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStore.java +++ b/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStore.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map; | 6 | package tools.refinery.store.map; |
2 | 7 | ||
3 | import java.util.Set; | 8 | import java.util.Set; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreConfiguration.java b/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreConfiguration.java index 3856460d..b00cd961 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreConfiguration.java +++ b/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreConfiguration.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map; | 6 | package tools.refinery.store.map; |
2 | 7 | ||
3 | public class VersionedMapStoreConfiguration { | 8 | public class VersionedMapStoreConfiguration { |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreImpl.java b/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreImpl.java index 113874e7..aade4aeb 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreImpl.java +++ b/subprojects/store/src/main/java/tools/refinery/store/map/VersionedMapStoreImpl.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map; | 6 | package tools.refinery.store.map; |
2 | 7 | ||
3 | import tools.refinery.store.map.internal.ImmutableNode; | 8 | import tools.refinery.store.map.internal.ImmutableNode; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/HashClash.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/HashClash.java index 5402ed4a..61b3d1b8 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/HashClash.java +++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/HashClash.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map.internal; | 6 | package tools.refinery.store.map.internal; |
2 | 7 | ||
3 | enum HashClash { | 8 | enum HashClash { |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/ImmutableNode.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/ImmutableNode.java index 9397dede..03dffc15 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/ImmutableNode.java +++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/ImmutableNode.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map.internal; | 6 | package tools.refinery.store.map.internal; |
2 | 7 | ||
3 | import java.util.Arrays; | 8 | import java.util.Arrays; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/MapCursor.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/MapCursor.java index 91a71e3d..f34ec7bb 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/MapCursor.java +++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/MapCursor.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map.internal; | 6 | package tools.refinery.store.map.internal; |
2 | 7 | ||
3 | import tools.refinery.store.map.AnyVersionedMap; | 8 | import tools.refinery.store.map.AnyVersionedMap; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/MapDiffCursor.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/MapDiffCursor.java index 9cd78113..d31f1a05 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/MapDiffCursor.java +++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/MapDiffCursor.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map.internal; | 6 | package tools.refinery.store.map.internal; |
2 | 7 | ||
3 | import tools.refinery.store.map.AnyVersionedMap; | 8 | import tools.refinery.store.map.AnyVersionedMap; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/MutableNode.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/MutableNode.java index 7c3cf7e8..1129ee5a 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/MutableNode.java +++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/MutableNode.java | |||
@@ -1,10 +1,15 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map.internal; | 6 | package tools.refinery.store.map.internal; |
2 | 7 | ||
8 | import tools.refinery.store.map.ContinousHashProvider; | ||
9 | |||
3 | import java.util.Arrays; | 10 | import java.util.Arrays; |
4 | import java.util.Map; | 11 | import java.util.Map; |
5 | 12 | ||
6 | import tools.refinery.store.map.ContinousHashProvider; | ||
7 | |||
8 | public class MutableNode<K, V> extends Node<K, V> { | 13 | public class MutableNode<K, V> extends Node<K, V> { |
9 | int cachedHash; | 14 | int cachedHash; |
10 | protected Object[] content; | 15 | protected Object[] content; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/Node.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/Node.java index 2260cd5b..958d645f 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/Node.java +++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/Node.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map.internal; | 6 | package tools.refinery.store.map.internal; |
2 | 7 | ||
3 | import java.util.Map; | 8 | import java.util.Map; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/OldValueBox.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/OldValueBox.java index 5534c703..354af51d 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/OldValueBox.java +++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/OldValueBox.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map.internal; | 6 | package tools.refinery.store.map.internal; |
2 | 7 | ||
3 | public class OldValueBox<V>{ | 8 | public class OldValueBox<V>{ |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/map/internal/VersionedMapImpl.java b/subprojects/store/src/main/java/tools/refinery/store/map/internal/VersionedMapImpl.java index 301bcb95..7abece0d 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/map/internal/VersionedMapImpl.java +++ b/subprojects/store/src/main/java/tools/refinery/store/map/internal/VersionedMapImpl.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map.internal; | 6 | package tools.refinery.store.map.internal; |
2 | 7 | ||
3 | import tools.refinery.store.map.*; | 8 | import tools.refinery.store.map.*; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/AnyInterpretation.java b/subprojects/store/src/main/java/tools/refinery/store/model/AnyInterpretation.java index d18ba71d..f906b48a 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/model/AnyInterpretation.java +++ b/subprojects/store/src/main/java/tools/refinery/store/model/AnyInterpretation.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.model; | 6 | package tools.refinery.store.model; |
2 | 7 | ||
3 | import tools.refinery.store.representation.AnySymbol; | 8 | import tools.refinery.store.representation.AnySymbol; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/Interpretation.java b/subprojects/store/src/main/java/tools/refinery/store/model/Interpretation.java index 55949d0c..26ad9a69 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/model/Interpretation.java +++ b/subprojects/store/src/main/java/tools/refinery/store/model/Interpretation.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.model; | 6 | package tools.refinery.store.model; |
2 | 7 | ||
3 | import tools.refinery.store.map.Cursor; | 8 | import tools.refinery.store.map.Cursor; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/InterpretationListener.java b/subprojects/store/src/main/java/tools/refinery/store/model/InterpretationListener.java index 73950779..6f7b24c1 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/model/InterpretationListener.java +++ b/subprojects/store/src/main/java/tools/refinery/store/model/InterpretationListener.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.model; | 6 | package tools.refinery.store.model; |
2 | 7 | ||
3 | import tools.refinery.store.tuple.Tuple; | 8 | import tools.refinery.store.tuple.Tuple; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/Model.java b/subprojects/store/src/main/java/tools/refinery/store/model/Model.java index 6ca1ac7b..d58d91c3 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/model/Model.java +++ b/subprojects/store/src/main/java/tools/refinery/store/model/Model.java | |||
@@ -1,7 +1,11 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.model; | 6 | package tools.refinery.store.model; |
2 | 7 | ||
3 | import tools.refinery.store.adapter.ModelAdapter; | 8 | import tools.refinery.store.adapter.ModelAdapter; |
4 | import tools.refinery.store.adapter.ModelAdapterType; | ||
5 | import tools.refinery.store.map.Versioned; | 9 | import tools.refinery.store.map.Versioned; |
6 | import tools.refinery.store.representation.AnySymbol; | 10 | import tools.refinery.store.representation.AnySymbol; |
7 | import tools.refinery.store.representation.Symbol; | 11 | import tools.refinery.store.representation.Symbol; |
@@ -25,9 +29,9 @@ public interface Model extends Versioned { | |||
25 | 29 | ||
26 | ModelDiffCursor getDiffCursor(long to); | 30 | ModelDiffCursor getDiffCursor(long to); |
27 | 31 | ||
28 | <T extends ModelAdapter> Optional<T> tryGetAdapter(ModelAdapterType<? extends T, ?, ?> adapterType); | 32 | <T extends ModelAdapter> Optional<T> tryGetAdapter(Class<? extends T> adapterType); |
29 | 33 | ||
30 | <T extends ModelAdapter> T getAdapter(ModelAdapterType<T, ?, ?> adapterType); | 34 | <T extends ModelAdapter> T getAdapter(Class<T> adapterType); |
31 | 35 | ||
32 | void addListener(ModelListener listener); | 36 | void addListener(ModelListener listener); |
33 | 37 | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/ModelDiffCursor.java b/subprojects/store/src/main/java/tools/refinery/store/model/ModelDiffCursor.java index 97bf2039..7b236891 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/model/ModelDiffCursor.java +++ b/subprojects/store/src/main/java/tools/refinery/store/model/ModelDiffCursor.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.model; | 6 | package tools.refinery.store.model; |
2 | 7 | ||
3 | import tools.refinery.store.map.DiffCursor; | 8 | import tools.refinery.store.map.DiffCursor; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/ModelListener.java b/subprojects/store/src/main/java/tools/refinery/store/model/ModelListener.java index f67540bb..a9ad8cfd 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/model/ModelListener.java +++ b/subprojects/store/src/main/java/tools/refinery/store/model/ModelListener.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.model; | 6 | package tools.refinery.store.model; |
2 | 7 | ||
3 | public interface ModelListener { | 8 | public interface ModelListener { |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/ModelStore.java b/subprojects/store/src/main/java/tools/refinery/store/model/ModelStore.java index 2e7e62c3..b10eb8a4 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/model/ModelStore.java +++ b/subprojects/store/src/main/java/tools/refinery/store/model/ModelStore.java | |||
@@ -1,6 +1,10 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.model; | 6 | package tools.refinery.store.model; |
2 | 7 | ||
3 | import tools.refinery.store.adapter.ModelAdapterType; | ||
4 | import tools.refinery.store.adapter.ModelStoreAdapter; | 8 | import tools.refinery.store.adapter.ModelStoreAdapter; |
5 | import tools.refinery.store.model.internal.ModelStoreBuilderImpl; | 9 | import tools.refinery.store.model.internal.ModelStoreBuilderImpl; |
6 | import tools.refinery.store.representation.AnySymbol; | 10 | import tools.refinery.store.representation.AnySymbol; |
@@ -20,9 +24,9 @@ public interface ModelStore { | |||
20 | 24 | ||
21 | ModelDiffCursor getDiffCursor(long from, long to); | 25 | ModelDiffCursor getDiffCursor(long from, long to); |
22 | 26 | ||
23 | <T extends ModelStoreAdapter> Optional<T> tryGetAdapter(ModelAdapterType<?, ? extends T, ?> adapterType); | 27 | <T extends ModelStoreAdapter> Optional<T> tryGetAdapter(Class<? extends T> adapterType); |
24 | 28 | ||
25 | <T extends ModelStoreAdapter> T getAdapter(ModelAdapterType<?, T, ?> adapterType); | 29 | <T extends ModelStoreAdapter> T getAdapter(Class<T> adapterType); |
26 | 30 | ||
27 | static ModelStoreBuilder builder() { | 31 | static ModelStoreBuilder builder() { |
28 | return new ModelStoreBuilderImpl(); | 32 | return new ModelStoreBuilderImpl(); |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/ModelStoreBuilder.java b/subprojects/store/src/main/java/tools/refinery/store/model/ModelStoreBuilder.java index 289099da..3a4024b5 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/model/ModelStoreBuilder.java +++ b/subprojects/store/src/main/java/tools/refinery/store/model/ModelStoreBuilder.java | |||
@@ -1,8 +1,11 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.model; | 6 | package tools.refinery.store.model; |
2 | 7 | ||
3 | import tools.refinery.store.adapter.ModelAdapterBuilder; | 8 | import tools.refinery.store.adapter.ModelAdapterBuilder; |
4 | import tools.refinery.store.adapter.ModelAdapterBuilderFactory; | ||
5 | import tools.refinery.store.adapter.ModelAdapterType; | ||
6 | import tools.refinery.store.representation.AnySymbol; | 9 | import tools.refinery.store.representation.AnySymbol; |
7 | import tools.refinery.store.representation.Symbol; | 10 | import tools.refinery.store.representation.Symbol; |
8 | 11 | ||
@@ -26,11 +29,11 @@ public interface ModelStoreBuilder { | |||
26 | 29 | ||
27 | <T> ModelStoreBuilder symbol(Symbol<T> symbol); | 30 | <T> ModelStoreBuilder symbol(Symbol<T> symbol); |
28 | 31 | ||
29 | <T extends ModelAdapterBuilder> T with(ModelAdapterBuilderFactory<?, ?, T> adapterBuilderFactory); | 32 | <T extends ModelAdapterBuilder> ModelStoreBuilder with(T adapterBuilder); |
30 | 33 | ||
31 | <T extends ModelAdapterBuilder> Optional<T> tryGetAdapter(ModelAdapterType<?, ?, ? extends T> adapterType); | 34 | <T extends ModelAdapterBuilder> Optional<T> tryGetAdapter(Class<? extends T> adapterType); |
32 | 35 | ||
33 | <T extends ModelAdapterBuilder> T getAdapter(ModelAdapterType<?, ?, T> adapterType); | 36 | <T extends ModelAdapterBuilder> T getAdapter(Class<T> adapterType); |
34 | 37 | ||
35 | ModelStore build(); | 38 | ModelStore build(); |
36 | } | 39 | } |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/TupleHashProvider.java b/subprojects/store/src/main/java/tools/refinery/store/model/TupleHashProvider.java index 4bcf9ff4..fe1c2ab5 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/model/TupleHashProvider.java +++ b/subprojects/store/src/main/java/tools/refinery/store/model/TupleHashProvider.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.model; | 6 | package tools.refinery.store.model; |
2 | 7 | ||
3 | import tools.refinery.store.map.ContinousHashProvider; | 8 | import tools.refinery.store.map.ContinousHashProvider; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/TupleHashProviderBitMagic.java b/subprojects/store/src/main/java/tools/refinery/store/model/TupleHashProviderBitMagic.java index 33059a1b..14116a90 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/model/TupleHashProviderBitMagic.java +++ b/subprojects/store/src/main/java/tools/refinery/store/model/TupleHashProviderBitMagic.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.model; | 6 | package tools.refinery.store.model; |
2 | 7 | ||
3 | import tools.refinery.store.map.ContinousHashProvider; | 8 | import tools.refinery.store.map.ContinousHashProvider; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelAction.java b/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelAction.java index f68859db..dbd95d80 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelAction.java +++ b/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelAction.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.model.internal; | 6 | package tools.refinery.store.model.internal; |
2 | 7 | ||
3 | public enum ModelAction { | 8 | public enum ModelAction { |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelImpl.java b/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelImpl.java index 9eb438c4..c5475a1a 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelImpl.java +++ b/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelImpl.java | |||
@@ -1,9 +1,12 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.model.internal; | 6 | package tools.refinery.store.model.internal; |
2 | 7 | ||
3 | import tools.refinery.store.adapter.AdapterList; | 8 | import tools.refinery.store.adapter.AdapterUtils; |
4 | import tools.refinery.store.adapter.AnyModelAdapterType; | ||
5 | import tools.refinery.store.adapter.ModelAdapter; | 9 | import tools.refinery.store.adapter.ModelAdapter; |
6 | import tools.refinery.store.adapter.ModelAdapterType; | ||
7 | import tools.refinery.store.map.DiffCursor; | 10 | import tools.refinery.store.map.DiffCursor; |
8 | import tools.refinery.store.model.*; | 11 | import tools.refinery.store.model.*; |
9 | import tools.refinery.store.representation.AnySymbol; | 12 | import tools.refinery.store.representation.AnySymbol; |
@@ -16,7 +19,7 @@ public class ModelImpl implements Model { | |||
16 | private final ModelStore store; | 19 | private final ModelStore store; |
17 | private long state; | 20 | private long state; |
18 | private Map<? extends AnySymbol, ? extends VersionedInterpretation<?>> interpretations; | 21 | private Map<? extends AnySymbol, ? extends VersionedInterpretation<?>> interpretations; |
19 | private final AdapterList<ModelAdapter> adapters; | 22 | private final List<ModelAdapter> adapters; |
20 | private final List<ModelListener> listeners = new ArrayList<>(); | 23 | private final List<ModelListener> listeners = new ArrayList<>(); |
21 | private boolean uncommittedChanges; | 24 | private boolean uncommittedChanges; |
22 | private ModelAction pendingAction = ModelAction.NONE; | 25 | private ModelAction pendingAction = ModelAction.NONE; |
@@ -25,7 +28,7 @@ public class ModelImpl implements Model { | |||
25 | ModelImpl(ModelStore store, long state, int adapterCount) { | 28 | ModelImpl(ModelStore store, long state, int adapterCount) { |
26 | this.store = store; | 29 | this.store = store; |
27 | this.state = state; | 30 | this.state = state; |
28 | adapters = new AdapterList<>(adapterCount); | 31 | adapters = new ArrayList<>(adapterCount); |
29 | } | 32 | } |
30 | 33 | ||
31 | void setInterpretations(Map<? extends AnySymbol, ? extends VersionedInterpretation<?>> interpretations) { | 34 | void setInterpretations(Map<? extends AnySymbol, ? extends VersionedInterpretation<?>> interpretations) { |
@@ -162,17 +165,17 @@ public class ModelImpl implements Model { | |||
162 | } | 165 | } |
163 | 166 | ||
164 | @Override | 167 | @Override |
165 | public <T extends ModelAdapter> Optional<T> tryGetAdapter(ModelAdapterType<? extends T, ?, ?> adapterType) { | 168 | public <T extends ModelAdapter> Optional<T> tryGetAdapter(Class<? extends T> adapterType) { |
166 | return adapters.tryGet(adapterType, adapterType.getModelAdapterClass()); | 169 | return AdapterUtils.tryGetAdapter(adapters, adapterType); |
167 | } | 170 | } |
168 | 171 | ||
169 | @Override | 172 | @Override |
170 | public <T extends ModelAdapter> T getAdapter(ModelAdapterType<T, ?, ?> adapterType) { | 173 | public <T extends ModelAdapter> T getAdapter(Class<T> adapterType) { |
171 | return adapters.get(adapterType, adapterType.getModelAdapterClass()); | 174 | return AdapterUtils.getAdapter(adapters, adapterType); |
172 | } | 175 | } |
173 | 176 | ||
174 | void addAdapter(AnyModelAdapterType adapterType, ModelAdapter adapter) { | 177 | void addAdapter(ModelAdapter adapter) { |
175 | adapters.add(adapterType, adapter); | 178 | adapters.add(adapter); |
176 | } | 179 | } |
177 | 180 | ||
178 | @Override | 181 | @Override |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelStoreBuilderImpl.java b/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelStoreBuilderImpl.java index 79f7195d..aafbe130 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelStoreBuilderImpl.java +++ b/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelStoreBuilderImpl.java | |||
@@ -1,9 +1,12 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.model.internal; | 6 | package tools.refinery.store.model.internal; |
2 | 7 | ||
3 | import tools.refinery.store.adapter.AdapterList; | 8 | import tools.refinery.store.adapter.AdapterUtils; |
4 | import tools.refinery.store.adapter.ModelAdapterBuilder; | 9 | import tools.refinery.store.adapter.ModelAdapterBuilder; |
5 | import tools.refinery.store.adapter.ModelAdapterBuilderFactory; | ||
6 | import tools.refinery.store.adapter.ModelAdapterType; | ||
7 | import tools.refinery.store.map.VersionedMapStore; | 10 | import tools.refinery.store.map.VersionedMapStore; |
8 | import tools.refinery.store.map.VersionedMapStoreImpl; | 11 | import tools.refinery.store.map.VersionedMapStoreImpl; |
9 | import tools.refinery.store.model.ModelStore; | 12 | import tools.refinery.store.model.ModelStore; |
@@ -18,7 +21,7 @@ import java.util.*; | |||
18 | public class ModelStoreBuilderImpl implements ModelStoreBuilder { | 21 | public class ModelStoreBuilderImpl implements ModelStoreBuilder { |
19 | private final Set<AnySymbol> allSymbols = new HashSet<>(); | 22 | private final Set<AnySymbol> allSymbols = new HashSet<>(); |
20 | private final Map<SymbolEquivalenceClass<?>, List<AnySymbol>> equivalenceClasses = new HashMap<>(); | 23 | private final Map<SymbolEquivalenceClass<?>, List<AnySymbol>> equivalenceClasses = new HashMap<>(); |
21 | private final AdapterList<ModelAdapterBuilder> adapters = new AdapterList<>(); | 24 | private final List<ModelAdapterBuilder> adapters = new ArrayList<>(); |
22 | 25 | ||
23 | @Override | 26 | @Override |
24 | public <T> ModelStoreBuilder symbol(Symbol<T> symbol) { | 27 | public <T> ModelStoreBuilder symbol(Symbol<T> symbol) { |
@@ -33,46 +36,25 @@ public class ModelStoreBuilderImpl implements ModelStoreBuilder { | |||
33 | } | 36 | } |
34 | 37 | ||
35 | @Override | 38 | @Override |
36 | public <T extends ModelAdapterBuilder> T with(ModelAdapterBuilderFactory<?, ?, T> adapterBuilderFactory) { | 39 | public <T extends ModelAdapterBuilder> ModelStoreBuilder with(T adapterBuilder) { |
37 | return adapters.<T>tryGet(adapterBuilderFactory, adapterBuilderFactory.getModelAdapterBuilderClass()) | 40 | for (var existingAdapter : adapters) { |
38 | .orElseGet(() -> addAdapter(adapterBuilderFactory)); | 41 | if (existingAdapter.getClass().equals(adapterBuilder.getClass())) { |
39 | } | 42 | throw new IllegalArgumentException("%s adapter was already configured for store builder" |
40 | 43 | .formatted(adapterBuilder.getClass().getName())); | |
41 | private <T extends ModelAdapterBuilder> T addAdapter(ModelAdapterBuilderFactory<?, ?, T> adapterBuilderFactory) { | ||
42 | for (var configuredAdapterType : adapters.getAdapterTypes()) { | ||
43 | var intersection = new HashSet<>(adapterBuilderFactory.getSupportedAdapterTypes()); | ||
44 | intersection.retainAll(configuredAdapterType.getSupportedAdapterTypes()); | ||
45 | if (!intersection.isEmpty()) { | ||
46 | if (configuredAdapterType.supports(adapterBuilderFactory)) { | ||
47 | // Impossible to end up here from <code>#with</code>, because we should have returned | ||
48 | // the existing adapter there instead of adding a new one. | ||
49 | throw new IllegalArgumentException( | ||
50 | "Cannot add %s, because it is already provided by configured adapter %s" | ||
51 | .formatted(adapterBuilderFactory, configuredAdapterType)); | ||
52 | } else if (adapterBuilderFactory.supports(configuredAdapterType)) { | ||
53 | throw new IllegalArgumentException( | ||
54 | "Cannot add %s, because it provides already configured adapter %s" | ||
55 | .formatted(adapterBuilderFactory, configuredAdapterType)); | ||
56 | } else { | ||
57 | throw new IllegalArgumentException( | ||
58 | "Cannot add %s, because configured adapter %s already provides %s" | ||
59 | .formatted(adapterBuilderFactory, configuredAdapterType, intersection)); | ||
60 | } | ||
61 | } | 44 | } |
62 | } | 45 | } |
63 | var newAdapter = adapterBuilderFactory.createBuilder(this); | 46 | adapters.add(adapterBuilder); |
64 | adapters.add(adapterBuilderFactory, newAdapter); | 47 | return this; |
65 | return newAdapter; | ||
66 | } | 48 | } |
67 | 49 | ||
68 | @Override | 50 | @Override |
69 | public <T extends ModelAdapterBuilder> Optional<T> tryGetAdapter(ModelAdapterType<?, ?, ? extends T> adapterType) { | 51 | public <T extends ModelAdapterBuilder> Optional<T> tryGetAdapter(Class<? extends T> adapterType) { |
70 | return adapters.tryGet(adapterType, adapterType.getModelAdapterBuilderClass()); | 52 | return AdapterUtils.tryGetAdapter(adapters, adapterType); |
71 | } | 53 | } |
72 | 54 | ||
73 | @Override | 55 | @Override |
74 | public <T extends ModelAdapterBuilder> T getAdapter(ModelAdapterType<?, ?, T> adapterType) { | 56 | public <T extends ModelAdapterBuilder> T getAdapter(Class<T> adapterType) { |
75 | return adapters.get(adapterType, adapterType.getModelAdapterBuilderClass()); | 57 | return AdapterUtils.getAdapter(adapters, adapterType); |
76 | } | 58 | } |
77 | 59 | ||
78 | @Override | 60 | @Override |
@@ -81,13 +63,13 @@ public class ModelStoreBuilderImpl implements ModelStoreBuilder { | |||
81 | for (var entry : equivalenceClasses.entrySet()) { | 63 | for (var entry : equivalenceClasses.entrySet()) { |
82 | createStores(stores, entry.getKey(), entry.getValue()); | 64 | createStores(stores, entry.getKey(), entry.getValue()); |
83 | } | 65 | } |
84 | var modelStore = new ModelStoreImpl(stores, adapters.size()); | ||
85 | for (int i = adapters.size() - 1; i >= 0; i--) { | 66 | for (int i = adapters.size() - 1; i >= 0; i--) { |
86 | adapters.get(i).configure(); | 67 | adapters.get(i).configure(this); |
87 | } | 68 | } |
88 | for (var entry : adapters.withAdapterTypes()) { | 69 | var modelStore = new ModelStoreImpl(stores, adapters.size()); |
89 | var adapter = entry.adapter().createStoreAdapter(modelStore); | 70 | for (var adapterBuilder : adapters) { |
90 | modelStore.addAdapter(entry.adapterType(), adapter); | 71 | var storeAdapter = adapterBuilder.build(modelStore); |
72 | modelStore.addAdapter(storeAdapter); | ||
91 | } | 73 | } |
92 | return modelStore; | 74 | return modelStore; |
93 | } | 75 | } |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelStoreImpl.java b/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelStoreImpl.java index e8c205e4..60b735e6 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelStoreImpl.java +++ b/subprojects/store/src/main/java/tools/refinery/store/model/internal/ModelStoreImpl.java | |||
@@ -1,8 +1,11 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.model.internal; | 6 | package tools.refinery.store.model.internal; |
2 | 7 | ||
3 | import tools.refinery.store.adapter.AdapterList; | 8 | import tools.refinery.store.adapter.AdapterUtils; |
4 | import tools.refinery.store.adapter.AnyModelAdapterType; | ||
5 | import tools.refinery.store.adapter.ModelAdapterType; | ||
6 | import tools.refinery.store.adapter.ModelStoreAdapter; | 9 | import tools.refinery.store.adapter.ModelStoreAdapter; |
7 | import tools.refinery.store.map.DiffCursor; | 10 | import tools.refinery.store.map.DiffCursor; |
8 | import tools.refinery.store.map.VersionedMapStore; | 11 | import tools.refinery.store.map.VersionedMapStore; |
@@ -16,11 +19,11 @@ import java.util.*; | |||
16 | 19 | ||
17 | public class ModelStoreImpl implements ModelStore { | 20 | public class ModelStoreImpl implements ModelStore { |
18 | private final Map<? extends AnySymbol, ? extends VersionedMapStore<Tuple, ?>> stores; | 21 | private final Map<? extends AnySymbol, ? extends VersionedMapStore<Tuple, ?>> stores; |
19 | private final AdapterList<ModelStoreAdapter> adapters; | 22 | private final List<ModelStoreAdapter> adapters; |
20 | 23 | ||
21 | ModelStoreImpl(Map<? extends AnySymbol, ? extends VersionedMapStore<Tuple, ?>> stores, int adapterCount) { | 24 | ModelStoreImpl(Map<? extends AnySymbol, ? extends VersionedMapStore<Tuple, ?>> stores, int adapterCount) { |
22 | this.stores = stores; | 25 | this.stores = stores; |
23 | adapters = new AdapterList<>(adapterCount); | 26 | adapters = new ArrayList<>(adapterCount); |
24 | } | 27 | } |
25 | 28 | ||
26 | @Override | 29 | @Override |
@@ -59,9 +62,9 @@ public class ModelStoreImpl implements ModelStore { | |||
59 | } | 62 | } |
60 | 63 | ||
61 | private void adaptModel(ModelImpl model) { | 64 | private void adaptModel(ModelImpl model) { |
62 | for (var entry : adapters.withAdapterTypes()) { | 65 | for (var storeAdapter : adapters) { |
63 | var adapter = entry.adapter().createModelAdapter(model); | 66 | var adapter = storeAdapter.createModelAdapter(model); |
64 | model.addAdapter(entry.adapterType(), adapter); | 67 | model.addAdapter(adapter); |
65 | } | 68 | } |
66 | } | 69 | } |
67 | 70 | ||
@@ -86,16 +89,16 @@ public class ModelStoreImpl implements ModelStore { | |||
86 | } | 89 | } |
87 | 90 | ||
88 | @Override | 91 | @Override |
89 | public <T extends ModelStoreAdapter> Optional<T> tryGetAdapter(ModelAdapterType<?, ? extends T, ?> adapterType) { | 92 | public <T extends ModelStoreAdapter> Optional<T> tryGetAdapter(Class<? extends T> adapterType) { |
90 | return adapters.tryGet(adapterType, adapterType.getModelStoreAdapterClass()); | 93 | return AdapterUtils.tryGetAdapter(adapters, adapterType); |
91 | } | 94 | } |
92 | 95 | ||
93 | @Override | 96 | @Override |
94 | public <T extends ModelStoreAdapter> T getAdapter(ModelAdapterType<?, T, ?> adapterType) { | 97 | public <T extends ModelStoreAdapter> T getAdapter(Class<T> adapterType) { |
95 | return adapters.get(adapterType, adapterType.getModelStoreAdapterClass()); | 98 | return AdapterUtils.getAdapter(adapters, adapterType); |
96 | } | 99 | } |
97 | 100 | ||
98 | void addAdapter(AnyModelAdapterType adapterType, ModelStoreAdapter adapter) { | 101 | void addAdapter(ModelStoreAdapter adapter) { |
99 | adapters.add(adapterType, adapter); | 102 | adapters.add(adapter); |
100 | } | 103 | } |
101 | } | 104 | } |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/internal/SymbolEquivalenceClass.java b/subprojects/store/src/main/java/tools/refinery/store/model/internal/SymbolEquivalenceClass.java index 5bf1b90d..136f2976 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/model/internal/SymbolEquivalenceClass.java +++ b/subprojects/store/src/main/java/tools/refinery/store/model/internal/SymbolEquivalenceClass.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.model.internal; | 6 | package tools.refinery.store.model.internal; |
2 | 7 | ||
3 | import tools.refinery.store.representation.Symbol; | 8 | import tools.refinery.store.representation.Symbol; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/model/internal/VersionedInterpretation.java b/subprojects/store/src/main/java/tools/refinery/store/model/internal/VersionedInterpretation.java index 6d82f5d7..86101ce3 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/model/internal/VersionedInterpretation.java +++ b/subprojects/store/src/main/java/tools/refinery/store/model/internal/VersionedInterpretation.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.model.internal; | 6 | package tools.refinery.store.model.internal; |
2 | 7 | ||
3 | import tools.refinery.store.map.Cursor; | 8 | import tools.refinery.store.map.Cursor; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/AbstractDomain.java b/subprojects/store/src/main/java/tools/refinery/store/representation/AbstractDomain.java index 18903ead..52c740e8 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/representation/AbstractDomain.java +++ b/subprojects/store/src/main/java/tools/refinery/store/representation/AbstractDomain.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.representation; | 6 | package tools.refinery.store.representation; |
2 | 7 | ||
3 | import java.util.Optional; | 8 | import java.util.Optional; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/AnyAbstractDomain.java b/subprojects/store/src/main/java/tools/refinery/store/representation/AnyAbstractDomain.java index 4c428a1e..c354fab7 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/representation/AnyAbstractDomain.java +++ b/subprojects/store/src/main/java/tools/refinery/store/representation/AnyAbstractDomain.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.representation; | 6 | package tools.refinery.store.representation; |
2 | 7 | ||
3 | public sealed interface AnyAbstractDomain permits AbstractDomain { | 8 | public sealed interface AnyAbstractDomain permits AbstractDomain { |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/AnySymbol.java b/subprojects/store/src/main/java/tools/refinery/store/representation/AnySymbol.java index 20b9eead..b2377905 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/representation/AnySymbol.java +++ b/subprojects/store/src/main/java/tools/refinery/store/representation/AnySymbol.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.representation; | 6 | package tools.refinery.store.representation; |
2 | 7 | ||
3 | public sealed interface AnySymbol permits Symbol { | 8 | public sealed interface AnySymbol permits Symbol { |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/Symbol.java b/subprojects/store/src/main/java/tools/refinery/store/representation/Symbol.java index 30b1c03f..cc748180 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/representation/Symbol.java +++ b/subprojects/store/src/main/java/tools/refinery/store/representation/Symbol.java | |||
@@ -1,19 +1,25 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.representation; | 6 | package tools.refinery.store.representation; |
2 | 7 | ||
3 | public record Symbol<T>(String name, int arity, Class<T> valueType, T defaultValue) implements AnySymbol { | 8 | public record Symbol<T>(String name, int arity, Class<T> valueType, T defaultValue) implements AnySymbol { |
4 | @Override | 9 | @Override |
5 | public boolean equals(Object o) { | 10 | public String toString() { |
6 | return this == o; | 11 | return "%s/%d".formatted(name, arity); |
7 | } | 12 | } |
8 | 13 | ||
9 | @Override | 14 | public static Symbol<Boolean> of(String name, int arity) { |
10 | public int hashCode() { | 15 | return of(name, arity, Boolean.class, false); |
11 | // Compare by identity to make hash table lookups more efficient. | ||
12 | return System.identityHashCode(this); | ||
13 | } | 16 | } |
14 | 17 | ||
15 | @Override | 18 | public static <T> Symbol<T> of(String name, int arity, Class<T> valueType) { |
16 | public String toString() { | 19 | return of(name, arity, valueType, null); |
17 | return "%s/%d".formatted(name, arity); | 20 | } |
21 | |||
22 | public static <T> Symbol<T> of(String name, int arity, Class<T> valueType, T defaultValue) { | ||
23 | return new Symbol<>(name, arity, valueType, defaultValue); | ||
18 | } | 24 | } |
19 | } | 25 | } |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/TruthValue.java b/subprojects/store/src/main/java/tools/refinery/store/representation/TruthValue.java index b7893fd3..40baf9a5 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/representation/TruthValue.java +++ b/subprojects/store/src/main/java/tools/refinery/store/representation/TruthValue.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.representation; | 6 | package tools.refinery.store.representation; |
2 | 7 | ||
3 | public enum TruthValue { | 8 | public enum TruthValue { |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/TruthValueDomain.java b/subprojects/store/src/main/java/tools/refinery/store/representation/TruthValueDomain.java index 29858bce..89f8dd19 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/representation/TruthValueDomain.java +++ b/subprojects/store/src/main/java/tools/refinery/store/representation/TruthValueDomain.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.representation; | 6 | package tools.refinery.store.representation; |
2 | 7 | ||
3 | import java.util.Optional; | 8 | import java.util.Optional; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/CardinalityInterval.java b/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/CardinalityInterval.java index 273d0de7..704ca2fc 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/CardinalityInterval.java +++ b/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/CardinalityInterval.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.representation.cardinality; | 6 | package tools.refinery.store.representation.cardinality; |
2 | 7 | ||
3 | public sealed interface CardinalityInterval permits NonEmptyCardinalityInterval, EmptyCardinalityInterval { | 8 | public sealed interface CardinalityInterval permits NonEmptyCardinalityInterval, EmptyCardinalityInterval { |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/CardinalityIntervals.java b/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/CardinalityIntervals.java index e1a08bf9..ad16a3e8 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/CardinalityIntervals.java +++ b/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/CardinalityIntervals.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.representation.cardinality; | 6 | package tools.refinery.store.representation.cardinality; |
2 | 7 | ||
3 | public final class CardinalityIntervals { | 8 | public final class CardinalityIntervals { |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/EmptyCardinalityInterval.java b/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/EmptyCardinalityInterval.java index ab3ad9d1..49911c29 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/EmptyCardinalityInterval.java +++ b/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/EmptyCardinalityInterval.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.representation.cardinality; | 6 | package tools.refinery.store.representation.cardinality; |
2 | 7 | ||
3 | public final class EmptyCardinalityInterval implements CardinalityInterval { | 8 | public final class EmptyCardinalityInterval implements CardinalityInterval { |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/FiniteUpperCardinality.java b/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/FiniteUpperCardinality.java index 381c8a57..82afdbbc 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/FiniteUpperCardinality.java +++ b/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/FiniteUpperCardinality.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.representation.cardinality; | 6 | package tools.refinery.store.representation.cardinality; |
2 | 7 | ||
3 | import org.jetbrains.annotations.NotNull; | 8 | import org.jetbrains.annotations.NotNull; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/NonEmptyCardinalityInterval.java b/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/NonEmptyCardinalityInterval.java index 32b3786f..38bd53bf 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/NonEmptyCardinalityInterval.java +++ b/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/NonEmptyCardinalityInterval.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.representation.cardinality; | 6 | package tools.refinery.store.representation.cardinality; |
2 | 7 | ||
3 | import java.util.function.BinaryOperator; | 8 | import java.util.function.BinaryOperator; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/UnboundedUpperCardinality.java b/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/UnboundedUpperCardinality.java index 593bc322..a5634020 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/UnboundedUpperCardinality.java +++ b/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/UnboundedUpperCardinality.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.representation.cardinality; | 6 | package tools.refinery.store.representation.cardinality; |
2 | 7 | ||
3 | import org.jetbrains.annotations.NotNull; | 8 | import org.jetbrains.annotations.NotNull; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/UpperCardinalities.java b/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/UpperCardinalities.java index d850fdc9..1e18dde0 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/UpperCardinalities.java +++ b/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/UpperCardinalities.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.representation.cardinality; | 6 | package tools.refinery.store.representation.cardinality; |
2 | 7 | ||
3 | public final class UpperCardinalities { | 8 | public final class UpperCardinalities { |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/UpperCardinality.java b/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/UpperCardinality.java index c6e31cb7..5dbaa922 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/UpperCardinality.java +++ b/subprojects/store/src/main/java/tools/refinery/store/representation/cardinality/UpperCardinality.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.representation.cardinality; | 6 | package tools.refinery.store.representation.cardinality; |
2 | 7 | ||
3 | public sealed interface UpperCardinality extends Comparable<UpperCardinality> permits FiniteUpperCardinality, | 8 | public sealed interface UpperCardinality extends Comparable<UpperCardinality> permits FiniteUpperCardinality, |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple.java b/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple.java index bf844c6d..6700417a 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple.java +++ b/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple.java | |||
@@ -1,28 +1,42 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.tuple; | 6 | package tools.refinery.store.tuple; |
2 | 7 | ||
3 | public sealed interface Tuple extends TupleLike permits Tuple0, Tuple1, Tuple2, TupleN { | 8 | public sealed interface Tuple permits Tuple0, Tuple1, Tuple2, Tuple3, Tuple4, TupleN { |
4 | @Override | 9 | int getSize(); |
5 | default Tuple toTuple() { | 10 | |
6 | return this; | 11 | int get(int element); |
7 | } | ||
8 | 12 | ||
9 | static Tuple of() { | 13 | static Tuple0 of() { |
10 | return Tuple0.INSTANCE; | 14 | return Tuple0.INSTANCE; |
11 | } | 15 | } |
12 | 16 | ||
13 | static Tuple of(int value) { | 17 | static Tuple1 of(int value) { |
14 | return Tuple1.Cache.INSTANCE.getOrCreate(value); | 18 | return Tuple1.Cache.INSTANCE.getOrCreate(value); |
15 | } | 19 | } |
16 | 20 | ||
17 | static Tuple of(int value1, int value2) { | 21 | static Tuple2 of(int value1, int value2) { |
18 | return new Tuple2(value1, value2); | 22 | return new Tuple2(value1, value2); |
19 | } | 23 | } |
20 | 24 | ||
25 | static Tuple3 of(int value1, int value2, int value3) { | ||
26 | return new Tuple3(value1, value2, value3); | ||
27 | } | ||
28 | |||
29 | static Tuple4 of(int value1, int value2, int value3, int value4) { | ||
30 | return new Tuple4(value1, value2, value3, value4); | ||
31 | } | ||
32 | |||
21 | static Tuple of(int... values) { | 33 | static Tuple of(int... values) { |
22 | return switch (values.length) { | 34 | return switch (values.length) { |
23 | case 0 -> of(); | 35 | case 0 -> of(); |
24 | case 1 -> of(values[0]); | 36 | case 1 -> of(values[0]); |
25 | case 2 -> of(values[0], values[1]); | 37 | case 2 -> of(values[0], values[1]); |
38 | case 3 -> of(values[0], values[1], values[2]); | ||
39 | case 4 -> of(values[0], values[1], values[2], values[3]); | ||
26 | default -> new TupleN(values); | 40 | default -> new TupleN(values); |
27 | }; | 41 | }; |
28 | } | 42 | } |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple0.java b/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple0.java index 8eea5c3a..1451099c 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple0.java +++ b/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple0.java | |||
@@ -1,7 +1,18 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.tuple; | 6 | package tools.refinery.store.tuple; |
2 | 7 | ||
3 | public record Tuple0() implements Tuple { | 8 | import static tools.refinery.store.tuple.TupleConstants.TUPLE_BEGIN; |
4 | public static Tuple0 INSTANCE = new Tuple0(); | 9 | import static tools.refinery.store.tuple.TupleConstants.TUPLE_END; |
10 | |||
11 | public final class Tuple0 implements Tuple { | ||
12 | public static final Tuple0 INSTANCE = new Tuple0(); | ||
13 | |||
14 | private Tuple0() { | ||
15 | } | ||
5 | 16 | ||
6 | @Override | 17 | @Override |
7 | public int getSize() { | 18 | public int getSize() { |
@@ -14,12 +25,7 @@ public record Tuple0() implements Tuple { | |||
14 | } | 25 | } |
15 | 26 | ||
16 | @Override | 27 | @Override |
17 | public int[] toArray() { | ||
18 | return new int[]{}; | ||
19 | } | ||
20 | |||
21 | @Override | ||
22 | public String toString() { | 28 | public String toString() { |
23 | return "[]"; | 29 | return TUPLE_BEGIN + TUPLE_END; |
24 | } | 30 | } |
25 | } | 31 | } |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple1.java b/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple1.java index 07380966..cda145d7 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple1.java +++ b/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple1.java | |||
@@ -1,10 +1,28 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.tuple; | 6 | package tools.refinery.store.tuple; |
2 | 7 | ||
3 | import tools.refinery.store.model.TupleHashProvider; | 8 | import tools.refinery.store.model.TupleHashProvider; |
4 | 9 | ||
5 | import java.util.Arrays; | 10 | import java.util.Arrays; |
6 | 11 | ||
7 | public record Tuple1(int value0) implements Tuple { | 12 | import static tools.refinery.store.tuple.TupleConstants.TUPLE_BEGIN; |
13 | import static tools.refinery.store.tuple.TupleConstants.TUPLE_END; | ||
14 | |||
15 | public final class Tuple1 implements Tuple { | ||
16 | private final int value0; | ||
17 | |||
18 | private Tuple1(int value0) { | ||
19 | this.value0 = value0; | ||
20 | } | ||
21 | |||
22 | public int value0() { | ||
23 | return value0; | ||
24 | } | ||
25 | |||
8 | @Override | 26 | @Override |
9 | public int getSize() { | 27 | public int getSize() { |
10 | return 1; | 28 | return 1; |
@@ -19,13 +37,21 @@ public record Tuple1(int value0) implements Tuple { | |||
19 | } | 37 | } |
20 | 38 | ||
21 | @Override | 39 | @Override |
22 | public int[] toArray() { | 40 | public String toString() { |
23 | return new int[]{value0}; | 41 | return TUPLE_BEGIN + value0 + TUPLE_END; |
24 | } | 42 | } |
25 | 43 | ||
26 | @Override | 44 | @Override |
27 | public String toString() { | 45 | public boolean equals(Object o) { |
28 | return "[" + value0 + "]"; | 46 | if (this == o) return true; |
47 | if (o == null || getClass() != o.getClass()) return false; | ||
48 | Tuple1 tuple1 = (Tuple1) o; | ||
49 | return value0 == tuple1.value0; | ||
50 | } | ||
51 | |||
52 | @Override | ||
53 | public int hashCode() { | ||
54 | return 31 + value0; | ||
29 | } | 55 | } |
30 | 56 | ||
31 | /** | 57 | /** |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple2.java b/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple2.java index 0836a32d..b669674b 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple2.java +++ b/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple2.java | |||
@@ -1,5 +1,12 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.tuple; | 6 | package tools.refinery.store.tuple; |
2 | 7 | ||
8 | import static tools.refinery.store.tuple.TupleConstants.*; | ||
9 | |||
3 | public record Tuple2(int value0, int value1) implements Tuple { | 10 | public record Tuple2(int value0, int value1) implements Tuple { |
4 | @Override | 11 | @Override |
5 | public int getSize() { | 12 | public int getSize() { |
@@ -16,12 +23,22 @@ public record Tuple2(int value0, int value1) implements Tuple { | |||
16 | } | 23 | } |
17 | 24 | ||
18 | @Override | 25 | @Override |
19 | public int[] toArray() { | 26 | public String toString() { |
20 | return new int[]{value0, value1}; | 27 | return TUPLE_BEGIN + value0 + TUPLE_SEPARATOR + value1 + TUPLE_END; |
21 | } | 28 | } |
22 | 29 | ||
23 | @Override | 30 | @Override |
24 | public String toString() { | 31 | public boolean equals(Object o) { |
25 | return "[" + value0 + ", " + value1 + "]"; | 32 | if (this == o) return true; |
33 | if (o == null || getClass() != o.getClass()) return false; | ||
34 | Tuple2 tuple2 = (Tuple2) o; | ||
35 | return value0 == tuple2.value0 && value1 == tuple2.value1; | ||
36 | } | ||
37 | |||
38 | @Override | ||
39 | public int hashCode() { | ||
40 | int hash = 31 + value0; | ||
41 | hash = 31 * hash + value1; | ||
42 | return hash; | ||
26 | } | 43 | } |
27 | } | 44 | } |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple3.java b/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple3.java new file mode 100644 index 00000000..542ed328 --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple3.java | |||
@@ -0,0 +1,46 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.tuple; | ||
7 | |||
8 | import static tools.refinery.store.tuple.TupleConstants.*; | ||
9 | |||
10 | public record Tuple3(int value0, int value1, int value2) implements Tuple { | ||
11 | @Override | ||
12 | public int getSize() { | ||
13 | return 3; | ||
14 | } | ||
15 | |||
16 | @Override | ||
17 | public int get(int element) { | ||
18 | return switch (element) { | ||
19 | case 0 -> value0; | ||
20 | case 1 -> value1; | ||
21 | case 2 -> value2; | ||
22 | default -> throw new ArrayIndexOutOfBoundsException(element); | ||
23 | }; | ||
24 | } | ||
25 | |||
26 | @Override | ||
27 | public String toString() { | ||
28 | return TUPLE_BEGIN + value0 + TUPLE_SEPARATOR + value1 + TUPLE_SEPARATOR + value2 + TUPLE_END; | ||
29 | } | ||
30 | |||
31 | @Override | ||
32 | public boolean equals(Object o) { | ||
33 | if (this == o) return true; | ||
34 | if (o == null || getClass() != o.getClass()) return false; | ||
35 | Tuple3 tuple3 = (Tuple3) o; | ||
36 | return value0 == tuple3.value0 && value1 == tuple3.value1 && value2 == tuple3.value2; | ||
37 | } | ||
38 | |||
39 | @Override | ||
40 | public int hashCode() { | ||
41 | int hash = 31 + value0; | ||
42 | hash = 31 * hash + value1; | ||
43 | hash = 31 * hash + value2; | ||
44 | return hash; | ||
45 | } | ||
46 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple4.java b/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple4.java new file mode 100644 index 00000000..121a15f6 --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/tuple/Tuple4.java | |||
@@ -0,0 +1,49 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.tuple; | ||
7 | |||
8 | import static tools.refinery.store.tuple.TupleConstants.*; | ||
9 | |||
10 | public record Tuple4(int value0, int value1, int value2, int value3) implements Tuple { | ||
11 | @Override | ||
12 | public int getSize() { | ||
13 | return 4; | ||
14 | } | ||
15 | |||
16 | @Override | ||
17 | public int get(int element) { | ||
18 | return switch (element) { | ||
19 | case 0 -> value0; | ||
20 | case 1 -> value1; | ||
21 | case 2 -> value2; | ||
22 | case 3 -> value3; | ||
23 | default -> throw new ArrayIndexOutOfBoundsException(element); | ||
24 | }; | ||
25 | } | ||
26 | |||
27 | @Override | ||
28 | public String toString() { | ||
29 | return TUPLE_BEGIN + value0 + TUPLE_SEPARATOR + value1 + TUPLE_SEPARATOR + value2 + TUPLE_SEPARATOR + value3 + | ||
30 | TUPLE_END; | ||
31 | } | ||
32 | |||
33 | @Override | ||
34 | public boolean equals(Object o) { | ||
35 | if (this == o) return true; | ||
36 | if (o == null || getClass() != o.getClass()) return false; | ||
37 | Tuple4 tuple4 = (Tuple4) o; | ||
38 | return value0 == tuple4.value0 && value1 == tuple4.value1 && value2 == tuple4.value2 && value3 == tuple4.value3; | ||
39 | } | ||
40 | |||
41 | @Override | ||
42 | public int hashCode() { | ||
43 | int hash = 31 + value0; | ||
44 | hash = 31 * hash + value1; | ||
45 | hash = 31 * hash + value2; | ||
46 | hash = 31 * hash + value3; | ||
47 | return hash; | ||
48 | } | ||
49 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/tuple/TupleConstants.java b/subprojects/store/src/main/java/tools/refinery/store/tuple/TupleConstants.java new file mode 100644 index 00000000..f7d27848 --- /dev/null +++ b/subprojects/store/src/main/java/tools/refinery/store/tuple/TupleConstants.java | |||
@@ -0,0 +1,17 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.store.tuple; | ||
7 | |||
8 | final class TupleConstants { | ||
9 | public static final int MAX_STATIC_ARITY_TUPLE_SIZE = 4; | ||
10 | public static final String TUPLE_BEGIN = "["; | ||
11 | public static final String TUPLE_SEPARATOR = ", "; | ||
12 | public static final String TUPLE_END = "]"; | ||
13 | |||
14 | private TupleConstants() { | ||
15 | throw new IllegalArgumentException("This is a static utility class an should not instantiated directly"); | ||
16 | } | ||
17 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/tuple/TupleLike.java b/subprojects/store/src/main/java/tools/refinery/store/tuple/TupleLike.java deleted file mode 100644 index 953ea9f8..00000000 --- a/subprojects/store/src/main/java/tools/refinery/store/tuple/TupleLike.java +++ /dev/null | |||
@@ -1,35 +0,0 @@ | |||
1 | package tools.refinery.store.tuple; | ||
2 | |||
3 | import java.util.stream.Collectors; | ||
4 | import java.util.stream.IntStream; | ||
5 | |||
6 | public interface TupleLike { | ||
7 | int getSize(); | ||
8 | |||
9 | int get(int element); | ||
10 | |||
11 | default int[] toArray() { | ||
12 | int size = getSize(); | ||
13 | var array = new int[size]; | ||
14 | for (int i = 0; i < size; i++) { | ||
15 | array[i] = get(i); | ||
16 | } | ||
17 | return array; | ||
18 | } | ||
19 | |||
20 | default Tuple toTuple() { | ||
21 | return switch (getSize()) { | ||
22 | case 0 -> Tuple.of(); | ||
23 | case 1 -> Tuple.of(get(0)); | ||
24 | case 2 -> Tuple.of(get(0), get(1)); | ||
25 | default -> Tuple.of(toArray()); | ||
26 | }; | ||
27 | } | ||
28 | |||
29 | static String toString(TupleLike tuple) { | ||
30 | var valuesString = IntStream.range(0, tuple.getSize()) | ||
31 | .mapToObj(i -> Integer.toString(tuple.get(i))) | ||
32 | .collect(Collectors.joining(", ")); | ||
33 | return "[" + valuesString + "]"; | ||
34 | } | ||
35 | } | ||
diff --git a/subprojects/store/src/main/java/tools/refinery/store/tuple/TupleN.java b/subprojects/store/src/main/java/tools/refinery/store/tuple/TupleN.java index c3aed847..b66af491 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/tuple/TupleN.java +++ b/subprojects/store/src/main/java/tools/refinery/store/tuple/TupleN.java | |||
@@ -1,13 +1,23 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.tuple; | 6 | package tools.refinery.store.tuple; |
2 | 7 | ||
3 | import java.util.Arrays; | 8 | import java.util.Arrays; |
9 | import java.util.stream.Collectors; | ||
4 | 10 | ||
5 | public record TupleN(int[] values) implements Tuple { | 11 | import static tools.refinery.store.tuple.TupleConstants.*; |
6 | static final int CUSTOM_TUPLE_SIZE = 2; | ||
7 | 12 | ||
8 | public TupleN(int[] values) { | 13 | public final class TupleN implements Tuple { |
9 | if (values.length < CUSTOM_TUPLE_SIZE) | 14 | private final int[] values; |
10 | throw new IllegalArgumentException(); | 15 | |
16 | TupleN(int[] values) { | ||
17 | if (values.length < MAX_STATIC_ARITY_TUPLE_SIZE) { | ||
18 | throw new IllegalArgumentException("Tuples of size at most %d must use static arity Tuple classes" | ||
19 | .formatted(MAX_STATIC_ARITY_TUPLE_SIZE)); | ||
20 | } | ||
11 | this.values = Arrays.copyOf(values, values.length); | 21 | this.values = Arrays.copyOf(values, values.length); |
12 | } | 22 | } |
13 | 23 | ||
@@ -22,18 +32,11 @@ public record TupleN(int[] values) implements Tuple { | |||
22 | } | 32 | } |
23 | 33 | ||
24 | @Override | 34 | @Override |
25 | public int[] toArray() { | ||
26 | return values; | ||
27 | } | ||
28 | |||
29 | @Override | ||
30 | public String toString() { | 35 | public String toString() { |
31 | return TupleLike.toString(this); | 36 | var valuesString = Arrays.stream(values) |
32 | } | 37 | .mapToObj(Integer::toString) |
33 | 38 | .collect(Collectors.joining(TUPLE_SEPARATOR)); | |
34 | @Override | 39 | return TUPLE_BEGIN + valuesString + TUPLE_END; |
35 | public int hashCode() { | ||
36 | return Arrays.hashCode(values); | ||
37 | } | 40 | } |
38 | 41 | ||
39 | @Override | 42 | @Override |
@@ -47,4 +50,9 @@ public record TupleN(int[] values) implements Tuple { | |||
47 | TupleN other = (TupleN) obj; | 50 | TupleN other = (TupleN) obj; |
48 | return Arrays.equals(values, other.values); | 51 | return Arrays.equals(values, other.values); |
49 | } | 52 | } |
53 | |||
54 | @Override | ||
55 | public int hashCode() { | ||
56 | return Arrays.hashCode(values); | ||
57 | } | ||
50 | } | 58 | } |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/util/CollectionsUtil.java b/subprojects/store/src/main/java/tools/refinery/store/util/CollectionsUtil.java index 841d0dfa..adecd79b 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/util/CollectionsUtil.java +++ b/subprojects/store/src/main/java/tools/refinery/store/util/CollectionsUtil.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.util; | 6 | package tools.refinery.store.util; |
2 | 7 | ||
3 | import java.util.Iterator; | 8 | import java.util.Iterator; |
diff --git a/subprojects/store/src/main/java/tools/refinery/store/util/CycleDetectingMapper.java b/subprojects/store/src/main/java/tools/refinery/store/util/CycleDetectingMapper.java index 8a151d01..78ad2ad7 100644 --- a/subprojects/store/src/main/java/tools/refinery/store/util/CycleDetectingMapper.java +++ b/subprojects/store/src/main/java/tools/refinery/store/util/CycleDetectingMapper.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.util; | 6 | package tools.refinery.store.util; |
2 | 7 | ||
3 | import java.util.*; | 8 | import java.util.*; |
diff --git a/subprojects/store/src/test/java/tools/refinery/store/map/tests/MapUnitTests.java b/subprojects/store/src/test/java/tools/refinery/store/map/tests/MapUnitTests.java index 77c62305..153f2e78 100644 --- a/subprojects/store/src/test/java/tools/refinery/store/map/tests/MapUnitTests.java +++ b/subprojects/store/src/test/java/tools/refinery/store/map/tests/MapUnitTests.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map.tests; | 6 | package tools.refinery.store.map.tests; |
2 | 7 | ||
3 | import org.junit.jupiter.api.Test; | 8 | import org.junit.jupiter.api.Test; |
diff --git a/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/CommitFuzzTest.java b/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/CommitFuzzTest.java index 1f9d022f..eabe5bd1 100644 --- a/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/CommitFuzzTest.java +++ b/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/CommitFuzzTest.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map.tests.fuzz; | 6 | package tools.refinery.store.map.tests.fuzz; |
2 | 7 | ||
3 | import static org.junit.jupiter.api.Assertions.fail; | 8 | import static org.junit.jupiter.api.Assertions.fail; |
diff --git a/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/ContentEqualsFuzzTest.java b/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/ContentEqualsFuzzTest.java index 93ecfec3..b0502a2b 100644 --- a/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/ContentEqualsFuzzTest.java +++ b/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/ContentEqualsFuzzTest.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map.tests.fuzz; | 6 | package tools.refinery.store.map.tests.fuzz; |
2 | 7 | ||
3 | import org.junit.jupiter.api.Tag; | 8 | import org.junit.jupiter.api.Tag; |
diff --git a/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/DiffCursorFuzzTest.java b/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/DiffCursorFuzzTest.java index e6334224..8274336e 100644 --- a/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/DiffCursorFuzzTest.java +++ b/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/DiffCursorFuzzTest.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map.tests.fuzz; | 6 | package tools.refinery.store.map.tests.fuzz; |
2 | 7 | ||
3 | import static org.junit.jupiter.api.Assertions.fail; | 8 | import static org.junit.jupiter.api.Assertions.fail; |
diff --git a/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/MultiThreadFuzzTest.java b/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/MultiThreadFuzzTest.java index 1ab431a8..ab2b9435 100644 --- a/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/MultiThreadFuzzTest.java +++ b/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/MultiThreadFuzzTest.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map.tests.fuzz; | 6 | package tools.refinery.store.map.tests.fuzz; |
2 | 7 | ||
3 | import static org.junit.jupiter.api.Assertions.assertEquals; | 8 | import static org.junit.jupiter.api.Assertions.assertEquals; |
diff --git a/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/MultiThreadTestRunnable.java b/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/MultiThreadTestRunnable.java index f77f9ee5..502c8362 100644 --- a/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/MultiThreadTestRunnable.java +++ b/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/MultiThreadTestRunnable.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map.tests.fuzz; | 6 | package tools.refinery.store.map.tests.fuzz; |
2 | 7 | ||
3 | import java.util.ArrayList; | 8 | import java.util.ArrayList; |
diff --git a/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/MutableFuzzTest.java b/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/MutableFuzzTest.java index d40c49c4..32dde0da 100644 --- a/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/MutableFuzzTest.java +++ b/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/MutableFuzzTest.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map.tests.fuzz; | 6 | package tools.refinery.store.map.tests.fuzz; |
2 | 7 | ||
3 | import static org.junit.jupiter.api.Assertions.fail; | 8 | import static org.junit.jupiter.api.Assertions.fail; |
diff --git a/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/MutableImmutableCompareFuzzTest.java b/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/MutableImmutableCompareFuzzTest.java index 410705a2..347c49be 100644 --- a/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/MutableImmutableCompareFuzzTest.java +++ b/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/MutableImmutableCompareFuzzTest.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map.tests.fuzz; | 6 | package tools.refinery.store.map.tests.fuzz; |
2 | 7 | ||
3 | import static org.junit.jupiter.api.Assertions.fail; | 8 | import static org.junit.jupiter.api.Assertions.fail; |
diff --git a/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/RestoreFuzzTest.java b/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/RestoreFuzzTest.java index 2e29a03f..f7b9d61e 100644 --- a/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/RestoreFuzzTest.java +++ b/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/RestoreFuzzTest.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map.tests.fuzz; | 6 | package tools.refinery.store.map.tests.fuzz; |
2 | 7 | ||
3 | import static org.junit.jupiter.api.Assertions.fail; | 8 | import static org.junit.jupiter.api.Assertions.fail; |
diff --git a/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/SharedStoreFuzzTest.java b/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/SharedStoreFuzzTest.java index 914a0f63..4b4172d0 100644 --- a/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/SharedStoreFuzzTest.java +++ b/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/SharedStoreFuzzTest.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map.tests.fuzz; | 6 | package tools.refinery.store.map.tests.fuzz; |
2 | 7 | ||
3 | import java.util.HashMap; | 8 | import java.util.HashMap; |
diff --git a/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/utils/FuzzTestUtils.java b/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/utils/FuzzTestUtils.java index e75d7f5a..a819d348 100644 --- a/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/utils/FuzzTestUtils.java +++ b/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/utils/FuzzTestUtils.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map.tests.fuzz.utils; | 6 | package tools.refinery.store.map.tests.fuzz.utils; |
2 | 7 | ||
3 | import java.util.Arrays; | 8 | import java.util.Arrays; |
diff --git a/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/utils/FuzzTestUtilsTest.java b/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/utils/FuzzTestUtilsTest.java index 72f2a46c..dc621574 100644 --- a/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/utils/FuzzTestUtilsTest.java +++ b/subprojects/store/src/test/java/tools/refinery/store/map/tests/fuzz/utils/FuzzTestUtilsTest.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map.tests.fuzz.utils; | 6 | package tools.refinery.store.map.tests.fuzz.utils; |
2 | 7 | ||
3 | import static org.junit.jupiter.api.Assertions.assertEquals; | 8 | import static org.junit.jupiter.api.Assertions.assertEquals; |
diff --git a/subprojects/store/src/test/java/tools/refinery/store/map/tests/utils/MapTestEnvironment.java b/subprojects/store/src/test/java/tools/refinery/store/map/tests/utils/MapTestEnvironment.java index 2d03ebaf..f861f496 100644 --- a/subprojects/store/src/test/java/tools/refinery/store/map/tests/utils/MapTestEnvironment.java +++ b/subprojects/store/src/test/java/tools/refinery/store/map/tests/utils/MapTestEnvironment.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.map.tests.utils; | 6 | package tools.refinery.store.map.tests.utils; |
2 | 7 | ||
3 | import tools.refinery.store.map.*; | 8 | import tools.refinery.store.map.*; |
diff --git a/subprojects/store/src/test/java/tools/refinery/store/model/hashtests/HashEfficiencyTest.java b/subprojects/store/src/test/java/tools/refinery/store/model/hashtests/HashEfficiencyTest.java index bb083805..4d4f5e26 100644 --- a/subprojects/store/src/test/java/tools/refinery/store/model/hashtests/HashEfficiencyTest.java +++ b/subprojects/store/src/test/java/tools/refinery/store/model/hashtests/HashEfficiencyTest.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.model.hashtests; | 6 | package tools.refinery.store.model.hashtests; |
2 | 7 | ||
3 | import static org.junit.jupiter.api.Assertions.assertEquals; | 8 | import static org.junit.jupiter.api.Assertions.assertEquals; |
diff --git a/subprojects/store/src/test/java/tools/refinery/store/model/tests/ModelTest.java b/subprojects/store/src/test/java/tools/refinery/store/model/tests/ModelTest.java index 9536a444..56b75804 100644 --- a/subprojects/store/src/test/java/tools/refinery/store/model/tests/ModelTest.java +++ b/subprojects/store/src/test/java/tools/refinery/store/model/tests/ModelTest.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.model.tests; | 6 | package tools.refinery.store.model.tests; |
2 | 7 | ||
3 | import org.junit.jupiter.api.Test; | 8 | import org.junit.jupiter.api.Test; |
@@ -9,27 +14,24 @@ import tools.refinery.store.tuple.Tuple; | |||
9 | import static org.junit.jupiter.api.Assertions.*; | 14 | import static org.junit.jupiter.api.Assertions.*; |
10 | 15 | ||
11 | class ModelTest { | 16 | class ModelTest { |
17 | private static final Symbol<Boolean> person = Symbol.of("Person", 1); | ||
18 | private static final Symbol<Integer> age = Symbol.of("age", 1, Integer.class); | ||
19 | private static final Symbol<Boolean> friend = Symbol.of("friend", 2); | ||
20 | |||
12 | @Test | 21 | @Test |
13 | void modelConstructionTest() { | 22 | void modelConstructionTest() { |
14 | var person = new Symbol<>("Person", 1, Boolean.class, false); | ||
15 | var friend = new Symbol<>("friend", 2, Boolean.class, false); | ||
16 | |||
17 | var store = ModelStore.builder().symbols(person, friend).build(); | 23 | var store = ModelStore.builder().symbols(person, friend).build(); |
18 | var symbols = store.getSymbols(); | 24 | var symbols = store.getSymbols(); |
19 | 25 | ||
20 | assertTrue(symbols.contains(person)); | 26 | assertTrue(symbols.contains(person)); |
21 | assertTrue(symbols.contains(friend)); | 27 | assertTrue(symbols.contains(friend)); |
22 | 28 | ||
23 | var other = new Symbol<>("other", 2, Integer.class, null); | 29 | var other = Symbol.of("other", 2, Integer.class); |
24 | assertFalse(symbols.contains(other)); | 30 | assertFalse(symbols.contains(other)); |
25 | } | 31 | } |
26 | 32 | ||
27 | @Test | 33 | @Test |
28 | void modelBuildingTest() { | 34 | void modelBuildingTest() { |
29 | var person = new Symbol<>("Person", 1, Boolean.class, false); | ||
30 | var age = new Symbol<>("age", 1, Integer.class, null); | ||
31 | var friend = new Symbol<>("friend", 2, Boolean.class, false); | ||
32 | |||
33 | var store = ModelStore.builder().symbols(person, age, friend).build(); | 35 | var store = ModelStore.builder().symbols(person, age, friend).build(); |
34 | var model = store.createEmptyModel(); | 36 | var model = store.createEmptyModel(); |
35 | var personInterpretation = model.getInterpretation(person); | 37 | var personInterpretation = model.getInterpretation(person); |
@@ -57,8 +59,6 @@ class ModelTest { | |||
57 | 59 | ||
58 | @Test | 60 | @Test |
59 | void modelBuildingArityFailTest() { | 61 | void modelBuildingArityFailTest() { |
60 | var person = new Symbol<>("Person", 1, Boolean.class, false); | ||
61 | |||
62 | var store = ModelStore.builder().symbols(person).build(); | 62 | var store = ModelStore.builder().symbols(person).build(); |
63 | var model = store.createEmptyModel(); | 63 | var model = store.createEmptyModel(); |
64 | var personInterpretation = model.getInterpretation(person); | 64 | var personInterpretation = model.getInterpretation(person); |
@@ -70,8 +70,6 @@ class ModelTest { | |||
70 | 70 | ||
71 | @Test | 71 | @Test |
72 | void modelBuildingNullFailTest() { | 72 | void modelBuildingNullFailTest() { |
73 | var age = new Symbol<>("age", 1, Integer.class, null); | ||
74 | |||
75 | var store = ModelStore.builder().symbols(age).build(); | 73 | var store = ModelStore.builder().symbols(age).build(); |
76 | var model = store.createEmptyModel(); | 74 | var model = store.createEmptyModel(); |
77 | var ageInterpretation = model.getInterpretation(age); | 75 | var ageInterpretation = model.getInterpretation(age); |
@@ -84,10 +82,6 @@ class ModelTest { | |||
84 | 82 | ||
85 | @Test | 83 | @Test |
86 | void modelUpdateTest() { | 84 | void modelUpdateTest() { |
87 | var person = new Symbol<>("Person", 1, Boolean.class, false); | ||
88 | var age = new Symbol<>("age", 1, Integer.class, null); | ||
89 | var friend = new Symbol<>("friend", 2, Boolean.class, false); | ||
90 | |||
91 | var store = ModelStore.builder().symbols(person, age, friend).build(); | 85 | var store = ModelStore.builder().symbols(person, age, friend).build(); |
92 | var model = store.createEmptyModel(); | 86 | var model = store.createEmptyModel(); |
93 | var personInterpretation = model.getInterpretation(person); | 87 | var personInterpretation = model.getInterpretation(person); |
@@ -113,9 +107,6 @@ class ModelTest { | |||
113 | 107 | ||
114 | @Test | 108 | @Test |
115 | void restoreTest() { | 109 | void restoreTest() { |
116 | var person = new Symbol<>("Person", 1, Boolean.class, false); | ||
117 | var friend = new Symbol<>("friend", 2, Boolean.class, false); | ||
118 | |||
119 | var store = ModelStore.builder().symbols(person, friend).build(); | 110 | var store = ModelStore.builder().symbols(person, friend).build(); |
120 | var model = store.createEmptyModel(); | 111 | var model = store.createEmptyModel(); |
121 | var personInterpretation = model.getInterpretation(person); | 112 | var personInterpretation = model.getInterpretation(person); |
diff --git a/subprojects/store/src/test/java/tools/refinery/store/representation/cardinality/CardinalityIntervalTest.java b/subprojects/store/src/test/java/tools/refinery/store/representation/cardinality/CardinalityIntervalTest.java index 96fdc49e..6a66fa84 100644 --- a/subprojects/store/src/test/java/tools/refinery/store/representation/cardinality/CardinalityIntervalTest.java +++ b/subprojects/store/src/test/java/tools/refinery/store/representation/cardinality/CardinalityIntervalTest.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.representation.cardinality; | 6 | package tools.refinery.store.representation.cardinality; |
2 | 7 | ||
3 | import org.junit.jupiter.params.ParameterizedTest; | 8 | import org.junit.jupiter.params.ParameterizedTest; |
diff --git a/subprojects/store/src/test/java/tools/refinery/store/representation/cardinality/CardinalityIntervalsTest.java b/subprojects/store/src/test/java/tools/refinery/store/representation/cardinality/CardinalityIntervalsTest.java index 4a9ef8da..9fe76159 100644 --- a/subprojects/store/src/test/java/tools/refinery/store/representation/cardinality/CardinalityIntervalsTest.java +++ b/subprojects/store/src/test/java/tools/refinery/store/representation/cardinality/CardinalityIntervalsTest.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.representation.cardinality; | 6 | package tools.refinery.store.representation.cardinality; |
2 | 7 | ||
3 | import org.junit.jupiter.api.Test; | 8 | import org.junit.jupiter.api.Test; |
diff --git a/subprojects/store/src/test/java/tools/refinery/store/representation/cardinality/EmptyCardinalityIntervalTest.java b/subprojects/store/src/test/java/tools/refinery/store/representation/cardinality/EmptyCardinalityIntervalTest.java index e8b77b9f..24a788a8 100644 --- a/subprojects/store/src/test/java/tools/refinery/store/representation/cardinality/EmptyCardinalityIntervalTest.java +++ b/subprojects/store/src/test/java/tools/refinery/store/representation/cardinality/EmptyCardinalityIntervalTest.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.representation.cardinality; | 6 | package tools.refinery.store.representation.cardinality; |
2 | 7 | ||
3 | import org.junit.jupiter.api.Test; | 8 | import org.junit.jupiter.api.Test; |
diff --git a/subprojects/store/src/test/java/tools/refinery/store/representation/cardinality/FiniteCardinalityIntervalTest.java b/subprojects/store/src/test/java/tools/refinery/store/representation/cardinality/FiniteCardinalityIntervalTest.java index 9a190818..6cf56fae 100644 --- a/subprojects/store/src/test/java/tools/refinery/store/representation/cardinality/FiniteCardinalityIntervalTest.java +++ b/subprojects/store/src/test/java/tools/refinery/store/representation/cardinality/FiniteCardinalityIntervalTest.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.representation.cardinality; | 6 | package tools.refinery.store.representation.cardinality; |
2 | 7 | ||
3 | import org.junit.jupiter.api.Test; | 8 | import org.junit.jupiter.api.Test; |
diff --git a/subprojects/store/src/test/java/tools/refinery/store/representation/cardinality/FiniteUpperCardinalityTest.java b/subprojects/store/src/test/java/tools/refinery/store/representation/cardinality/FiniteUpperCardinalityTest.java index 90c21759..7c641c47 100644 --- a/subprojects/store/src/test/java/tools/refinery/store/representation/cardinality/FiniteUpperCardinalityTest.java +++ b/subprojects/store/src/test/java/tools/refinery/store/representation/cardinality/FiniteUpperCardinalityTest.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.representation.cardinality; | 6 | package tools.refinery.store.representation.cardinality; |
2 | 7 | ||
3 | import org.junit.jupiter.api.Test; | 8 | import org.junit.jupiter.api.Test; |
diff --git a/subprojects/store/src/test/java/tools/refinery/store/representation/cardinality/UpperCardinalitiesTest.java b/subprojects/store/src/test/java/tools/refinery/store/representation/cardinality/UpperCardinalitiesTest.java index 3c7c0320..e61f7b36 100644 --- a/subprojects/store/src/test/java/tools/refinery/store/representation/cardinality/UpperCardinalitiesTest.java +++ b/subprojects/store/src/test/java/tools/refinery/store/representation/cardinality/UpperCardinalitiesTest.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.representation.cardinality; | 6 | package tools.refinery.store.representation.cardinality; |
2 | 7 | ||
3 | import org.junit.jupiter.api.Test; | 8 | import org.junit.jupiter.api.Test; |
diff --git a/subprojects/store/src/test/java/tools/refinery/store/representation/cardinality/UpperCardinalityTest.java b/subprojects/store/src/test/java/tools/refinery/store/representation/cardinality/UpperCardinalityTest.java index e87ce29b..10b4dd20 100644 --- a/subprojects/store/src/test/java/tools/refinery/store/representation/cardinality/UpperCardinalityTest.java +++ b/subprojects/store/src/test/java/tools/refinery/store/representation/cardinality/UpperCardinalityTest.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.representation.cardinality; | 6 | package tools.refinery.store.representation.cardinality; |
2 | 7 | ||
3 | import org.junit.jupiter.params.ParameterizedTest; | 8 | import org.junit.jupiter.params.ParameterizedTest; |
diff --git a/subprojects/store/src/test/java/tools/refinery/store/util/CollectionsUtilTests.java b/subprojects/store/src/test/java/tools/refinery/store/util/CollectionsUtilTests.java index 171be0e5..8d50fa8a 100644 --- a/subprojects/store/src/test/java/tools/refinery/store/util/CollectionsUtilTests.java +++ b/subprojects/store/src/test/java/tools/refinery/store/util/CollectionsUtilTests.java | |||
@@ -1,3 +1,8 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
1 | package tools.refinery.store.util; | 6 | package tools.refinery.store.util; |
2 | 7 | ||
3 | import static org.junit.jupiter.api.Assertions.assertEquals; | 8 | import static org.junit.jupiter.api.Assertions.assertEquals; |