.
This commit is contained in:
Generated
+141
-130
@@ -359,9 +359,9 @@ checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aws-lc-rs"
|
name = "aws-lc-rs"
|
||||||
version = "1.18.0"
|
version = "1.18.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ce2b2dcc879c3bae0d371e77c99f2238400ef24ec001394befa67b6e543add9e"
|
checksum = "b281d307588d634de920874890732659e2e7672f72b5e10e81badc1a8a83621e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aws-lc-sys",
|
"aws-lc-sys",
|
||||||
"zeroize",
|
"zeroize",
|
||||||
@@ -369,9 +369,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aws-lc-sys"
|
name = "aws-lc-sys"
|
||||||
version = "0.44.0"
|
version = "0.45.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f09fae7be8bb3174e05c6afdb34199e6dc0c7c04ba9fa237b1967adfbde27483"
|
checksum = "9bff6c3b54fad79a2e60b8102caf565819711497c1f5f092f49508e2f5c31b27"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"cmake",
|
"cmake",
|
||||||
@@ -511,11 +511,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "block-buffer"
|
name = "block-buffer"
|
||||||
version = "0.10.4"
|
version = "0.12.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
|
checksum = "d2f6c7dbe95a6ed67ad9f18e57daf93a2f034c524b99fd2b76d18fdfeb6660aa"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"generic-array",
|
"hybrid-array",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -677,12 +677,12 @@ checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "chacha20"
|
name = "chacha20"
|
||||||
version = "0.10.1"
|
version = "0.10.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d524456ba66e72eb8b115ff89e01e497f8e6d11d78b70b1aa13c0fbd97540a81"
|
checksum = "65c35e4b699c7e15ccbe7ee35c005e4fc0a278d22238a2857e6ce2dadeda1b06"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"cpufeatures 0.3.0",
|
"cpufeatures",
|
||||||
"rand_core 0.10.1",
|
"rand_core 0.10.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -829,6 +829,12 @@ dependencies = [
|
|||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "const-oid"
|
||||||
|
version = "0.10.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "core-foundation"
|
name = "core-foundation"
|
||||||
version = "0.9.4"
|
version = "0.9.4"
|
||||||
@@ -914,18 +920,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cpufeatures"
|
name = "cpufeatures"
|
||||||
version = "0.2.17"
|
version = "0.3.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
|
checksum = "5ca28b0ae3115b884660db4118d803791fd6756b6e88f39c0f3f7859060d7566"
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "cpufeatures"
|
|
||||||
version = "0.3.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
@@ -993,33 +990,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crypto-common"
|
name = "crypto-common"
|
||||||
version = "0.1.7"
|
version = "0.2.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"
|
checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"generic-array",
|
"hybrid-array",
|
||||||
"typenum",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "csv"
|
|
||||||
version = "1.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "52cd9d68cf7efc6ddfaaee42e7288d3a99d613d4b50f76ce9827ae0c6e14f938"
|
|
||||||
dependencies = [
|
|
||||||
"csv-core",
|
|
||||||
"itoa",
|
|
||||||
"ryu",
|
|
||||||
"serde_core",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "csv-core"
|
|
||||||
version = "0.1.13"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "704a3c26996a80471189265814dbc2c257598b96b8a7feae2d31ace646bb9782"
|
|
||||||
dependencies = [
|
|
||||||
"memchr",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1102,11 +1077,12 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "digest"
|
name = "digest"
|
||||||
version = "0.10.7"
|
version = "0.11.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"block-buffer",
|
"block-buffer",
|
||||||
|
"const-oid",
|
||||||
"crypto-common",
|
"crypto-common",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1557,16 +1533,6 @@ dependencies = [
|
|||||||
"slab",
|
"slab",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "generic-array"
|
|
||||||
version = "0.14.7"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
|
|
||||||
dependencies = [
|
|
||||||
"typenum",
|
|
||||||
"version_check",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gethostname"
|
name = "gethostname"
|
||||||
version = "1.1.0"
|
version = "1.1.0"
|
||||||
@@ -1661,7 +1627,6 @@ version = "0.1.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"color-eyre",
|
"color-eyre",
|
||||||
"csv",
|
|
||||||
"gl-graph",
|
"gl-graph",
|
||||||
"gl-inference",
|
"gl-inference",
|
||||||
"gl-search",
|
"gl-search",
|
||||||
@@ -1706,9 +1671,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "glam"
|
name = "glam"
|
||||||
version = "0.33.5"
|
version = "0.33.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c426daf70099baff33fac0ba85151c42424861c56828cef9ba02dacb78eb6b26"
|
checksum = "21fef0953c54fd3de2f44b743fbf77e044c81a25faee03636dfccc0d35135e23"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "glob"
|
name = "glob"
|
||||||
@@ -1855,9 +1820,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hermit-abi"
|
name = "hermit-abi"
|
||||||
version = "0.5.2"
|
version = "0.5.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c"
|
checksum = "e17592d60ebacc7d5e169f4663c5f84f9161cc90328abcfe8456f41e4dfcb284"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hex"
|
name = "hex"
|
||||||
@@ -1923,10 +1888,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
|
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hyper"
|
name = "hybrid-array"
|
||||||
version = "1.11.0"
|
version = "0.4.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d22053281f852e11534f5198498373cbb59295120a20771d90f7ed1897490a72"
|
checksum = "707114b52a152fa7bdb290cd7cd5912d9467273b6d74e21b8d81aca1f8533f6b"
|
||||||
|
dependencies = [
|
||||||
|
"typenum",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hyper"
|
||||||
|
version = "1.11.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "27b501faa50e7a26c3d3560ca625132f4078a17771f4810baf70475ae48cbe43"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atomic-waker",
|
"atomic-waker",
|
||||||
"bytes",
|
"bytes",
|
||||||
@@ -1998,7 +1972,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "iced"
|
name = "iced"
|
||||||
version = "0.15.0-dev"
|
version = "0.15.0-dev"
|
||||||
source = "git+https://github.com/iced-rs/iced.git?branch=master#3de451447bd28217bb535632867550908e29d5d0"
|
source = "git+https://github.com/iced-rs/iced.git?branch=master#f8127c84dddf0b9e32c5e7dbb822911652f72665"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"iced_core",
|
"iced_core",
|
||||||
"iced_debug",
|
"iced_debug",
|
||||||
@@ -2013,7 +1987,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "iced_core"
|
name = "iced_core"
|
||||||
version = "0.15.0-dev"
|
version = "0.15.0-dev"
|
||||||
source = "git+https://github.com/iced-rs/iced.git?branch=master#3de451447bd28217bb535632867550908e29d5d0"
|
source = "git+https://github.com/iced-rs/iced.git?branch=master#f8127c84dddf0b9e32c5e7dbb822911652f72665"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.13.1",
|
"bitflags 2.13.1",
|
||||||
"bytes",
|
"bytes",
|
||||||
@@ -2032,7 +2006,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "iced_debug"
|
name = "iced_debug"
|
||||||
version = "0.15.0-dev"
|
version = "0.15.0-dev"
|
||||||
source = "git+https://github.com/iced-rs/iced.git?branch=master#3de451447bd28217bb535632867550908e29d5d0"
|
source = "git+https://github.com/iced-rs/iced.git?branch=master#f8127c84dddf0b9e32c5e7dbb822911652f72665"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"iced_core",
|
"iced_core",
|
||||||
"iced_futures",
|
"iced_futures",
|
||||||
@@ -2042,7 +2016,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "iced_futures"
|
name = "iced_futures"
|
||||||
version = "0.15.0-dev"
|
version = "0.15.0-dev"
|
||||||
source = "git+https://github.com/iced-rs/iced.git?branch=master#3de451447bd28217bb535632867550908e29d5d0"
|
source = "git+https://github.com/iced-rs/iced.git?branch=master#f8127c84dddf0b9e32c5e7dbb822911652f72665"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures",
|
"futures",
|
||||||
"iced_core",
|
"iced_core",
|
||||||
@@ -2056,7 +2030,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "iced_graphics"
|
name = "iced_graphics"
|
||||||
version = "0.15.0-dev"
|
version = "0.15.0-dev"
|
||||||
source = "git+https://github.com/iced-rs/iced.git?branch=master#3de451447bd28217bb535632867550908e29d5d0"
|
source = "git+https://github.com/iced-rs/iced.git?branch=master#f8127c84dddf0b9e32c5e7dbb822911652f72665"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.13.1",
|
"bitflags 2.13.1",
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
@@ -2073,7 +2047,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "iced_program"
|
name = "iced_program"
|
||||||
version = "0.15.0-dev"
|
version = "0.15.0-dev"
|
||||||
source = "git+https://github.com/iced-rs/iced.git?branch=master#3de451447bd28217bb535632867550908e29d5d0"
|
source = "git+https://github.com/iced-rs/iced.git?branch=master#f8127c84dddf0b9e32c5e7dbb822911652f72665"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"iced_graphics",
|
"iced_graphics",
|
||||||
"iced_runtime",
|
"iced_runtime",
|
||||||
@@ -2082,7 +2056,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "iced_renderer"
|
name = "iced_renderer"
|
||||||
version = "0.15.0-dev"
|
version = "0.15.0-dev"
|
||||||
source = "git+https://github.com/iced-rs/iced.git?branch=master#3de451447bd28217bb535632867550908e29d5d0"
|
source = "git+https://github.com/iced-rs/iced.git?branch=master#f8127c84dddf0b9e32c5e7dbb822911652f72665"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"iced_graphics",
|
"iced_graphics",
|
||||||
"iced_tiny_skia",
|
"iced_tiny_skia",
|
||||||
@@ -2094,18 +2068,19 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "iced_runtime"
|
name = "iced_runtime"
|
||||||
version = "0.15.0-dev"
|
version = "0.15.0-dev"
|
||||||
source = "git+https://github.com/iced-rs/iced.git?branch=master#3de451447bd28217bb535632867550908e29d5d0"
|
source = "git+https://github.com/iced-rs/iced.git?branch=master#f8127c84dddf0b9e32c5e7dbb822911652f72665"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"iced_core",
|
"iced_core",
|
||||||
"iced_futures",
|
"iced_futures",
|
||||||
|
"sipper",
|
||||||
"thiserror 2.0.20",
|
"thiserror 2.0.20",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "iced_tiny_skia"
|
name = "iced_tiny_skia"
|
||||||
version = "0.15.0-dev"
|
version = "0.15.0-dev"
|
||||||
source = "git+https://github.com/iced-rs/iced.git?branch=master#3de451447bd28217bb535632867550908e29d5d0"
|
source = "git+https://github.com/iced-rs/iced.git?branch=master#f8127c84dddf0b9e32c5e7dbb822911652f72665"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
"cosmic-text",
|
"cosmic-text",
|
||||||
@@ -2121,7 +2096,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "iced_wgpu"
|
name = "iced_wgpu"
|
||||||
version = "0.15.0-dev"
|
version = "0.15.0-dev"
|
||||||
source = "git+https://github.com/iced-rs/iced.git?branch=master#3de451447bd28217bb535632867550908e29d5d0"
|
source = "git+https://github.com/iced-rs/iced.git?branch=master#f8127c84dddf0b9e32c5e7dbb822911652f72665"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.13.1",
|
"bitflags 2.13.1",
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
@@ -2138,7 +2113,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "iced_widget"
|
name = "iced_widget"
|
||||||
version = "0.15.0-dev"
|
version = "0.15.0-dev"
|
||||||
source = "git+https://github.com/iced-rs/iced.git?branch=master#3de451447bd28217bb535632867550908e29d5d0"
|
source = "git+https://github.com/iced-rs/iced.git?branch=master#f8127c84dddf0b9e32c5e7dbb822911652f72665"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"iced_renderer",
|
"iced_renderer",
|
||||||
"iced_runtime",
|
"iced_runtime",
|
||||||
@@ -2152,7 +2127,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "iced_winit"
|
name = "iced_winit"
|
||||||
version = "0.15.0-dev"
|
version = "0.15.0-dev"
|
||||||
source = "git+https://github.com/iced-rs/iced.git?branch=master#3de451447bd28217bb535632867550908e29d5d0"
|
source = "git+https://github.com/iced-rs/iced.git?branch=master#f8127c84dddf0b9e32c5e7dbb822911652f72665"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arboard",
|
"arboard",
|
||||||
"iced_debug",
|
"iced_debug",
|
||||||
@@ -2287,9 +2262,9 @@ checksum = "964de6e86d545b246d84badc0fef527924ace5134f30641c203ef52ba83f58d5"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "2.14.0"
|
version = "2.14.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
|
checksum = "07aa2048142242915a31d35844fb311e0e53fcca590c3a0a40dcf1b841fa09eb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"equivalent",
|
"equivalent",
|
||||||
"hashbrown 0.17.1",
|
"hashbrown 0.17.1",
|
||||||
@@ -2459,7 +2434,7 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ldp"
|
name = "ldp"
|
||||||
version = "0.0.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"base64 0.23.1",
|
"base64 0.23.1",
|
||||||
@@ -2469,6 +2444,7 @@ dependencies = [
|
|||||||
"oxigraph",
|
"oxigraph",
|
||||||
"parse_link_header",
|
"parse_link_header",
|
||||||
"reqwest-middleware",
|
"reqwest-middleware",
|
||||||
|
"sfv",
|
||||||
"slotmap",
|
"slotmap",
|
||||||
"thiserror 2.0.20",
|
"thiserror 2.0.20",
|
||||||
"tracing",
|
"tracing",
|
||||||
@@ -2504,9 +2480,9 @@ checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libredox"
|
name = "libredox"
|
||||||
version = "0.1.20"
|
version = "0.1.23"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "28d0a00925a9f930d679b6789b721e3a7f9ed110f41b86d2497caa780c3a070a"
|
checksum = "8d8f1ea3f21fd3405dcaf6c9b5c1630af9afc422d9073ea39c5f6d6c772e08ed"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.13.1",
|
"bitflags 2.13.1",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -2606,9 +2582,9 @@ checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "md-5"
|
name = "md-5"
|
||||||
version = "0.10.6"
|
version = "0.11.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf"
|
checksum = "69b6441f590336821bb897fb28fc622898ccceb1d6cea3fde5ea86b090c4de98"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"digest",
|
"digest",
|
||||||
@@ -2670,9 +2646,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mio"
|
name = "mio"
|
||||||
version = "1.2.2"
|
version = "1.2.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "30d65c71f1ce40ab09135ce117d742b9f8a19ff91a41a8b57ed50bc2de59c427"
|
checksum = "4b18443e9c262bfe8fa82f51666e2642c53393f7e5c27b3e1aeab922cff5b9d8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"wasi",
|
"wasi",
|
||||||
@@ -3293,15 +3269,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "owo-colors"
|
name = "owo-colors"
|
||||||
version = "4.3.0"
|
version = "4.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d211803b9b6b570f68772237e415a029d5a50c65d382910b879fb19d3271f94d"
|
checksum = "13c45bb4a6ae1280ec0803b1ef9d3455eb50f01efbbe1447ab020f1d54fba9d8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxigraph"
|
name = "oxigraph"
|
||||||
version = "0.5.9"
|
version = "0.5.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6d945cbe78640ab719a73697b9bd250054ea82c60470754efea79c21d5fc1cd1"
|
checksum = "7f6632dd080bd07676f06e70254ff5862c9943e9483d700fa7258df73a3f9a6a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dashmap",
|
"dashmap",
|
||||||
"getrandom 0.3.4",
|
"getrandom 0.3.4",
|
||||||
@@ -3337,9 +3313,9 @@ checksum = "54b4ed3a7192fa19f5f48f99871f2755047fabefd7f222f12a1df1773796a102"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxjsonld"
|
name = "oxjsonld"
|
||||||
version = "0.2.5"
|
version = "0.2.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f6e1380a504a8571763f13b8bcad629ff90d0300d47d8a519f3c6c599625840e"
|
checksum = "86a3e89e005662e60327027f45ec7cefd0472404e01831b5d83a3ac522cfabe0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"json-event-parser",
|
"json-event-parser",
|
||||||
"oxiri",
|
"oxiri",
|
||||||
@@ -3350,9 +3326,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxrdf"
|
name = "oxrdf"
|
||||||
version = "0.3.3"
|
version = "0.3.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0afd5c28e4a399c57ee2bc3accd40c7b671fdc7b6537499f14e95b265af7d7e0"
|
checksum = "4be15186205eb60ddbdc2fb47cb25df472c7f399bbe119b68c0972b6b6dd46ea"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hex",
|
"hex",
|
||||||
"oxilangtag",
|
"oxilangtag",
|
||||||
@@ -3365,9 +3341,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxrdfio"
|
name = "oxrdfio"
|
||||||
version = "0.2.5"
|
version = "0.2.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "696223589ecbcab06b1a5df9b527dc25b0c656160cca38752fdb3878a5d3dd03"
|
checksum = "17b3fe3bb34179c376ab04f2a1b32616b0babab574b3b7eef64d587e60d5e1db"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"oxjsonld",
|
"oxjsonld",
|
||||||
"oxrdf",
|
"oxrdf",
|
||||||
@@ -3378,9 +3354,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxrdfxml"
|
name = "oxrdfxml"
|
||||||
version = "0.2.3"
|
version = "0.2.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cd5516ae083d09bc57ec65ed5ee97701481725de6ffaa83d968ab42a96157ba1"
|
checksum = "71853d12051879f3e424c6864e978f5f5cbecd8e86a9817adbccaefccac9d61d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"oxilangtag",
|
"oxilangtag",
|
||||||
"oxiri",
|
"oxiri",
|
||||||
@@ -3391,9 +3367,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxrocksdb-sys"
|
name = "oxrocksdb-sys"
|
||||||
version = "0.5.9"
|
version = "0.5.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6977c1d1827fcbf14480e768e4dede0b39c2961f6028497d012f9c04bcda91c6"
|
checksum = "01fcf5ae1e1295a612bef72fc64cd81e1ac3d1bd3243ef84d330f2962a8335e1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bindgen",
|
"bindgen",
|
||||||
"cc",
|
"cc",
|
||||||
@@ -3401,18 +3377,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxsdatatypes"
|
name = "oxsdatatypes"
|
||||||
version = "0.2.2"
|
version = "0.2.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "06fa874d87eae638daae9b4e3198864fe2cce68589f227c0b2cf5b62b1530516"
|
checksum = "c17c2ae62ac34fda465f6331105906c0e17b4e088dac3249e1f229b962062503"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"thiserror 2.0.20",
|
"thiserror 2.0.20",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "oxttl"
|
name = "oxttl"
|
||||||
version = "0.2.3"
|
version = "0.2.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f03fd471bd54c23d76631c0a2677aa4bb308d905f6e491ee35dcb0732b7c5c6c"
|
checksum = "b1d0fe19fa62a6a102f85b052bbd86e3cdc3360cd6a338d01bab1a6743bf1d8e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
"oxilangtag",
|
"oxilangtag",
|
||||||
@@ -3992,6 +3968,26 @@ dependencies = [
|
|||||||
"bitflags 2.13.1",
|
"bitflags 2.13.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ref-cast"
|
||||||
|
version = "1.0.27"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7e440fb4e4b4147295338efb76001ab9e4efc0e5839df2c47fc5ac2381d365c3"
|
||||||
|
dependencies = [
|
||||||
|
"ref-cast-impl",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ref-cast-impl"
|
||||||
|
version = "1.0.27"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "92ecd8964f8453721699a1ed72037b0db49ce2f5a5138486ee89bed6f67cdf3a"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 3.0.4",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex"
|
name = "regex"
|
||||||
version = "1.13.1"
|
version = "1.13.1"
|
||||||
@@ -4270,12 +4266,6 @@ version = "1.0.23"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f"
|
checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ryu"
|
|
||||||
version = "1.0.23"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu-js"
|
name = "ryu-js"
|
||||||
version = "1.0.3"
|
version = "1.0.3"
|
||||||
@@ -4426,24 +4416,35 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sha1"
|
name = "sfv"
|
||||||
version = "0.10.7"
|
version = "0.15.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a978451301f4db1d02937a4ab3ccce137717b81826e79b7d49ffe3244a13c3b8"
|
checksum = "890ef0e5532daf21fdaa3dbaf991417187f3a87ab69231fe69be942495746480"
|
||||||
|
dependencies = [
|
||||||
|
"base64 0.22.1",
|
||||||
|
"indexmap",
|
||||||
|
"ref-cast",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sha1"
|
||||||
|
version = "0.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "aacc4cc499359472b4abe1bf11d0b12e688af9a805fa5e3016f9a386dc2d0214"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"cpufeatures 0.2.17",
|
"cpufeatures",
|
||||||
"digest",
|
"digest",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sha2"
|
name = "sha2"
|
||||||
version = "0.10.9"
|
version = "0.11.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
|
checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"cpufeatures 0.2.17",
|
"cpufeatures",
|
||||||
"digest",
|
"digest",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -4500,6 +4501,16 @@ version = "1.0.3"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649"
|
checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sipper"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1bccb4192828b3d9a08e0b5a73f17795080dfb278b50190216e3ae2132cf4f95"
|
||||||
|
dependencies = [
|
||||||
|
"futures",
|
||||||
|
"pin-project-lite",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sketches-ddsketch"
|
name = "sketches-ddsketch"
|
||||||
version = "0.4.1"
|
version = "0.4.1"
|
||||||
@@ -4546,9 +4557,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smallvec"
|
name = "smallvec"
|
||||||
version = "1.15.2"
|
version = "1.16.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90"
|
checksum = "b9be42f50aa861c555654aa3a37f52f4b1074bacf4e48fe0ef7fa584e80f1f0f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
@@ -4636,9 +4647,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sparesults"
|
name = "sparesults"
|
||||||
version = "0.3.3"
|
version = "0.3.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7e13362decdcbeb3fefadff1631238c835c112027221e83d217cc5779f5a81c2"
|
checksum = "5dfa99dba6f5155ef4fdd75b78f794ea0c729e17b07d84eb88ae3c1278d1758d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"json-event-parser",
|
"json-event-parser",
|
||||||
"memchr",
|
"memchr",
|
||||||
@@ -4649,9 +4660,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "spareval"
|
name = "spareval"
|
||||||
version = "0.2.6"
|
version = "0.2.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c8eab80b96dc836e4cf8fda72daa67ccc0244dc5303be5d4566e8fd04adbdde5"
|
checksum = "85b51144836ff9ca2f792b7a2422c4170ff04460d86cd8f2f764cf53e339cbec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hex",
|
"hex",
|
||||||
"json-event-parser",
|
"json-event-parser",
|
||||||
@@ -4672,9 +4683,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "spargebra"
|
name = "spargebra"
|
||||||
version = "0.4.6"
|
version = "0.4.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "46715eb957d1fe960cbbc0b713da8f78e2cb19df315b48fb09c9467a1c84f656"
|
checksum = "bef3c186ffb9bf2dde7c5edd5528583f309fcb819b5773cf0e313194a990304f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"oxilangtag",
|
"oxilangtag",
|
||||||
"oxiri",
|
"oxiri",
|
||||||
@@ -4686,9 +4697,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sparopt"
|
name = "sparopt"
|
||||||
version = "0.3.6"
|
version = "0.3.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "aed7a854b8ea67618f8ce69aabb0e904d7704226060e9d5a2930eb3136c3fa3b"
|
checksum = "973ee503ab3d6c3de66b4b459233cd5b22b44dad0fb7b8d0931daf73d2ede935"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"oxrdf",
|
"oxrdf",
|
||||||
"rand 0.9.5",
|
"rand 0.9.5",
|
||||||
@@ -5602,9 +5613,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uuid"
|
name = "uuid"
|
||||||
version = "1.25.0"
|
version = "1.26.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f053576934f05a761a402421fbbe3d425d9366f75f978806a037b3ca481abecc"
|
checksum = "b5772d71c9be8a8a6ac2117d949c5b224c1b72241bb611d9a3012edcf8af7812"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom 0.4.3",
|
"getrandom 0.4.3",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
|
|||||||
+1
-1
@@ -20,7 +20,7 @@ clap = { version = "4.6", features = ["derive"] }
|
|||||||
color-eyre = "0.6"
|
color-eyre = "0.6"
|
||||||
futures = "0.3"
|
futures = "0.3"
|
||||||
http = "1.5"
|
http = "1.5"
|
||||||
iced = { git = "https://github.com/iced-rs/iced.git", branch = "master", features = ["advanced", "tokio"] }
|
iced = { git = "https://github.com/iced-rs/iced.git", branch = "master", features = ["advanced", "sipper", "tokio"] }
|
||||||
num-traits = "0.2"
|
num-traits = "0.2"
|
||||||
oxigraph = { version = "0.5", features = ["rdf-12"] }
|
oxigraph = { version = "0.5", features = ["rdf-12"] }
|
||||||
oxilangtag = "0.1"
|
oxilangtag = "0.1"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use oxigraph::model::NamedNodeRef;
|
|
||||||
use crate::vocab;
|
use crate::vocab;
|
||||||
|
use oxigraph::model::NamedNodeRef;
|
||||||
|
|
||||||
pub enum Category {
|
pub enum Category {
|
||||||
AudioBook = 0,
|
AudioBook = 0,
|
||||||
@@ -19,4 +19,4 @@ impl Category {
|
|||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+120
-41
@@ -1,9 +1,9 @@
|
|||||||
use std::fmt::Display;
|
|
||||||
use oxigraph::model::{Graph, Literal, LiteralRef, NamedNode, NamedNodeRef, NamedOrBlankNode, Term, TermRef, Triple};
|
|
||||||
use oxilangtag::LanguageTag;
|
|
||||||
use url::Url;
|
|
||||||
use gl_search::Schema;
|
|
||||||
use crate::vocab;
|
use crate::vocab;
|
||||||
|
use gl_search::Schema;
|
||||||
|
use oxigraph::model::{Graph, LiteralRef, NamedNode, NamedNodeRef, Triple};
|
||||||
|
use oxilangtag::LanguageTag;
|
||||||
|
use std::fmt::Display;
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub enum Class {
|
pub enum Class {
|
||||||
@@ -83,33 +83,61 @@ impl Class {
|
|||||||
pub fn fields(&self, language: LanguageTag<String>) -> Vec<(gl_search::Field, String)> {
|
pub fn fields(&self, language: LanguageTag<String>) -> Vec<(gl_search::Field, String)> {
|
||||||
match self {
|
match self {
|
||||||
Class::RdfProperty => vec![
|
Class::RdfProperty => vec![
|
||||||
(Schema::field("label", Some(language.primary_language())), String::from("Label")),
|
(
|
||||||
(Schema::field("definition", Some(language.primary_language())), String::from("Definition")),
|
Schema::field("label", Some(language.primary_language())),
|
||||||
|
String::from("Label"),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
Schema::field("definition", Some(language.primary_language())),
|
||||||
|
String::from("Definition"),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
Class::RdfsClass => vec![
|
Class::RdfsClass => vec![
|
||||||
(Schema::field("label", Some(language.primary_language())), String::from("Label")),
|
(
|
||||||
(Schema::field("definition", Some(language.primary_language())), String::from("Definition")),
|
Schema::field("label", Some(language.primary_language())),
|
||||||
|
String::from("Label"),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
Schema::field("definition", Some(language.primary_language())),
|
||||||
|
String::from("Definition"),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
Class::SkosConcept => vec![
|
Class::SkosConcept => vec![
|
||||||
(Schema::field("label", Some(language.primary_language())), String::from("Label")),
|
(
|
||||||
(Schema::field("definition", Some(language.primary_language())), String::from("Definition")),
|
Schema::field("label", Some(language.primary_language())),
|
||||||
],
|
String::from("Label"),
|
||||||
Class::Work => vec![
|
),
|
||||||
(Schema::field("title", Some(language.primary_language())), String::from("Title")),
|
(
|
||||||
|
Schema::field("definition", Some(language.primary_language())),
|
||||||
|
String::from("Definition"),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
|
Class::Work => vec![(
|
||||||
|
Schema::field("title", Some(language.primary_language())),
|
||||||
|
String::from("Title"),
|
||||||
|
)],
|
||||||
Class::Person => vec![
|
Class::Person => vec![
|
||||||
(Schema::field("given_name", Some(language.primary_language())), String::from("Given Name")),
|
(
|
||||||
(Schema::field("surname", Some(language.primary_language())), String::from("Surname")),
|
Schema::field("given_name", Some(language.primary_language())),
|
||||||
],
|
String::from("Given Name"),
|
||||||
Class::CorporateBody => vec![
|
),
|
||||||
(Schema::field("corporate_body", Some(language.primary_language())), String::from("Corporate Body")),
|
(
|
||||||
],
|
Schema::field("surname", Some(language.primary_language())),
|
||||||
Class::Expression => vec![
|
String::from("Surname"),
|
||||||
(Schema::field("title", Some(language.primary_language())), String::from("Title")),
|
),
|
||||||
],
|
|
||||||
Class::Manifestation => vec![
|
|
||||||
(Schema::field("title", Some(language.primary_language())), String::from("Title")),
|
|
||||||
],
|
],
|
||||||
|
Class::CorporateBody => vec![(
|
||||||
|
Schema::field("corporate_body", Some(language.primary_language())),
|
||||||
|
String::from("Corporate Body"),
|
||||||
|
)],
|
||||||
|
Class::Expression => vec![(
|
||||||
|
Schema::field("title", Some(language.primary_language())),
|
||||||
|
String::from("Title"),
|
||||||
|
)],
|
||||||
|
Class::Manifestation => vec![(
|
||||||
|
Schema::field("title", Some(language.primary_language())),
|
||||||
|
String::from("Title"),
|
||||||
|
)],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,16 +145,23 @@ impl Class {
|
|||||||
match self {
|
match self {
|
||||||
Class::Work => Some(Url::parse("http://fedora.quill.lan/rest/#Work").unwrap()),
|
Class::Work => Some(Url::parse("http://fedora.quill.lan/rest/#Work").unwrap()),
|
||||||
Class::Person => Some(Url::parse("http://fedora.quill.lan/rest/#Agent").unwrap()),
|
Class::Person => Some(Url::parse("http://fedora.quill.lan/rest/#Agent").unwrap()),
|
||||||
Class::CorporateBody => Some(Url::parse("http://fedora.quill.lan/rest/#Agent").unwrap()),
|
Class::CorporateBody => {
|
||||||
Class::Expression => Some(Url::parse("http://fedora.quill.lan/rest/#Expression").unwrap()),
|
Some(Url::parse("http://fedora.quill.lan/rest/#Agent").unwrap())
|
||||||
Class::Manifestation => Some(Url::parse("http://fedora.quill.lan/rest/#Manifestation").unwrap()),
|
}
|
||||||
|
Class::Expression => {
|
||||||
|
Some(Url::parse("http://fedora.quill.lan/rest/#Expression").unwrap())
|
||||||
|
}
|
||||||
|
Class::Manifestation => {
|
||||||
|
Some(Url::parse("http://fedora.quill.lan/rest/#Manifestation").unwrap())
|
||||||
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn template(&self, subject: NamedNode) -> Graph {
|
pub fn template(&self, subject: NamedNode) -> Graph {
|
||||||
let subject = subject.as_ref();
|
let subject = subject.as_ref();
|
||||||
let empty_english_string_literal = LiteralRef::new_language_tagged_literal_unchecked("", "en");
|
let empty_english_string_literal =
|
||||||
|
LiteralRef::new_language_tagged_literal_unchecked("", "en");
|
||||||
let empty_string_literal = LiteralRef::new_simple_literal("");
|
let empty_string_literal = LiteralRef::new_simple_literal("");
|
||||||
let empty_node = NamedNodeRef::new_unchecked("");
|
let empty_node = NamedNodeRef::new_unchecked("");
|
||||||
let hash_node = NamedNodeRef::new_unchecked("#");
|
let hash_node = NamedNodeRef::new_unchecked("#");
|
||||||
@@ -136,42 +171,86 @@ impl Class {
|
|||||||
Class::RdfsClass => Graph::new(),
|
Class::RdfsClass => Graph::new(),
|
||||||
Class::SkosConcept => Graph::new(),
|
Class::SkosConcept => Graph::new(),
|
||||||
Class::Work => Graph::from_iter([
|
Class::Work => Graph::from_iter([
|
||||||
Triple::new(subject, vocab::rdawd::TITLE_OF_WORK, empty_english_string_literal),
|
Triple::new(
|
||||||
|
subject,
|
||||||
|
vocab::rdawd::TITLE_OF_WORK,
|
||||||
|
empty_english_string_literal,
|
||||||
|
),
|
||||||
Triple::new(subject, vocab::rdawo::IDENTIFIER_FOR_WORK, empty_node),
|
Triple::new(subject, vocab::rdawo::IDENTIFIER_FOR_WORK, empty_node),
|
||||||
Triple::new(subject, vocab::rdawo::EXPRESSION_OF_WORK, empty_node),
|
Triple::new(subject, vocab::rdawo::EXPRESSION_OF_WORK, empty_node),
|
||||||
]),
|
]),
|
||||||
Class::Person => Graph::from_iter([
|
Class::Person => Graph::from_iter([
|
||||||
Triple::new(subject, vocab::rdaad::GIVEN_NAME, empty_english_string_literal),
|
Triple::new(
|
||||||
|
subject,
|
||||||
|
vocab::rdaad::GIVEN_NAME,
|
||||||
|
empty_english_string_literal,
|
||||||
|
),
|
||||||
Triple::new(subject, vocab::rdaad::SURNAME, empty_english_string_literal),
|
Triple::new(subject, vocab::rdaad::SURNAME, empty_english_string_literal),
|
||||||
Triple::new(subject, vocab::rdaao::IDENTIFIER_FOR_PERSON, hash_node),
|
Triple::new(subject, vocab::rdaao::IDENTIFIER_FOR_PERSON, hash_node),
|
||||||
Triple::new(hash_node, vocab::rdano::SCHEME_OF_NOMEN, empty_node),
|
Triple::new(hash_node, vocab::rdano::SCHEME_OF_NOMEN, empty_node),
|
||||||
Triple::new(hash_node, vocab::rdand::NOMEN_STRING, empty_string_literal),
|
Triple::new(hash_node, vocab::rdand::NOMEN_STRING, empty_string_literal),
|
||||||
]),
|
]),
|
||||||
Class::CorporateBody => Graph::from_iter([
|
Class::CorporateBody => Graph::from_iter([
|
||||||
Triple::new(subject, vocab::rdaao::IDENTIFIER_FOR_CORPORATE_BODY, hash_node),
|
Triple::new(
|
||||||
Triple::new(subject, vocab::rdaad::NAME_OF_CORPORATE_BODY, empty_english_string_literal),
|
subject,
|
||||||
|
vocab::rdaao::IDENTIFIER_FOR_CORPORATE_BODY,
|
||||||
|
hash_node,
|
||||||
|
),
|
||||||
|
Triple::new(
|
||||||
|
subject,
|
||||||
|
vocab::rdaad::NAME_OF_CORPORATE_BODY,
|
||||||
|
empty_english_string_literal,
|
||||||
|
),
|
||||||
Triple::new(hash_node, vocab::rdano::SCHEME_OF_NOMEN, empty_node),
|
Triple::new(hash_node, vocab::rdano::SCHEME_OF_NOMEN, empty_node),
|
||||||
Triple::new(hash_node, vocab::rdand::NOMEN_STRING, empty_string_literal),
|
Triple::new(hash_node, vocab::rdand::NOMEN_STRING, empty_string_literal),
|
||||||
]),
|
]),
|
||||||
Class::Expression => Graph::from_iter([
|
Class::Expression => Graph::from_iter([
|
||||||
Triple::new(subject, vocab::rdaeo::WORK_EXPRESSED, empty_node),
|
Triple::new(subject, vocab::rdaeo::WORK_EXPRESSED, empty_node),
|
||||||
Triple::new(subject, vocab::rdaeo::LANGUAGE_OF_EXPRESSION, vocab::lclang::ENGLISH),
|
Triple::new(
|
||||||
Triple::new(subject, vocab::rdaeo::TITLE_OF_EXPRESSION, empty_english_string_literal),
|
subject,
|
||||||
|
vocab::rdaeo::LANGUAGE_OF_EXPRESSION,
|
||||||
|
vocab::lclang::ENGLISH,
|
||||||
|
),
|
||||||
|
Triple::new(
|
||||||
|
subject,
|
||||||
|
vocab::rdaeo::TITLE_OF_EXPRESSION,
|
||||||
|
empty_english_string_literal,
|
||||||
|
),
|
||||||
Triple::new(subject, vocab::rdaeo::CONTENT_TYPE, empty_node),
|
Triple::new(subject, vocab::rdaeo::CONTENT_TYPE, empty_node),
|
||||||
Triple::new(subject, vocab::rdaeo::MANIFESTATION_OF_EXPRESSION, empty_node),
|
Triple::new(
|
||||||
|
subject,
|
||||||
|
vocab::rdaeo::MANIFESTATION_OF_EXPRESSION,
|
||||||
|
empty_node,
|
||||||
|
),
|
||||||
]),
|
]),
|
||||||
Class::Manifestation => Graph::from_iter([
|
Class::Manifestation => Graph::from_iter([
|
||||||
Triple::new(subject, vocab::rdamd::TITLE_OF_MANIFESTATION, empty_english_string_literal),
|
Triple::new(
|
||||||
Triple::new(subject, vocab::rdamd::UNIFORM_RESOURCE_LOCATOR, empty_string_literal),
|
subject,
|
||||||
Triple::new(subject, vocab::rdamo::CARRIER_TYPE, vocab::rdact::ONLINE_RESOURCE),
|
vocab::rdamd::TITLE_OF_MANIFESTATION,
|
||||||
|
empty_english_string_literal,
|
||||||
|
),
|
||||||
|
Triple::new(
|
||||||
|
subject,
|
||||||
|
vocab::rdamd::UNIFORM_RESOURCE_LOCATOR,
|
||||||
|
empty_string_literal,
|
||||||
|
),
|
||||||
|
Triple::new(
|
||||||
|
subject,
|
||||||
|
vocab::rdamo::CARRIER_TYPE,
|
||||||
|
vocab::rdact::ONLINE_RESOURCE,
|
||||||
|
),
|
||||||
Triple::new(subject, vocab::rdamo::MEDIA_TYPE, empty_node),
|
Triple::new(subject, vocab::rdamo::MEDIA_TYPE, empty_node),
|
||||||
Triple::new(subject, vocab::rdamo::FILE_TYPE, empty_node),
|
Triple::new(subject, vocab::rdamo::FILE_TYPE, empty_node),
|
||||||
Triple::new(subject, vocab::rdamo::CATEGORY_OF_MANIFESTATION, empty_node),
|
Triple::new(subject, vocab::rdamo::CATEGORY_OF_MANIFESTATION, empty_node),
|
||||||
Triple::new(subject, vocab::rdamo::EXPRESSION_MANIFESTED, empty_node),
|
Triple::new(subject, vocab::rdamo::EXPRESSION_MANIFESTED, empty_node),
|
||||||
Triple::new(subject, vocab::rdamo::IDENTIFIER_FOR_MANIFESTATION, hash_node),
|
Triple::new(
|
||||||
|
subject,
|
||||||
|
vocab::rdamo::IDENTIFIER_FOR_MANIFESTATION,
|
||||||
|
hash_node,
|
||||||
|
),
|
||||||
Triple::new(hash_node, vocab::rdano::SCHEME_OF_NOMEN, empty_node),
|
Triple::new(hash_node, vocab::rdano::SCHEME_OF_NOMEN, empty_node),
|
||||||
Triple::new(hash_node, vocab::rdand::NOMEN_STRING, empty_string_literal),
|
Triple::new(hash_node, vocab::rdand::NOMEN_STRING, empty_string_literal),
|
||||||
]),
|
]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-13
@@ -81,19 +81,24 @@ impl CurieHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn expand(&self, base: Option<&Url>, abbreviated_iri: &str) -> Option<String> {
|
pub fn expand(&self, base: Option<&Url>, abbreviated_iri: &str) -> Option<String> {
|
||||||
let absolute_iri = base.and_then(|base| {
|
let absolute_iri = base
|
||||||
base.join(abbreviated_iri).ok().map(|absolute| absolute.as_str().to_string())
|
.and_then(|base| {
|
||||||
}).unwrap_or_else(|| abbreviated_iri.to_string());
|
base.join(abbreviated_iri)
|
||||||
|
.ok()
|
||||||
absolute_iri.split_once(':')
|
.map(|absolute| absolute.as_str().to_string())
|
||||||
.and_then(|(prefix, name)| {
|
|
||||||
if prefix.is_empty() && let Some(base) = base {
|
|
||||||
Some(format!("{base}{name}"))
|
|
||||||
} else {
|
|
||||||
self.prefixes
|
|
||||||
.get(prefix)
|
|
||||||
.map(|base| format!("{base}{name}"))
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
.unwrap_or_else(|| abbreviated_iri.to_string());
|
||||||
|
|
||||||
|
absolute_iri.split_once(':').and_then(|(prefix, name)| {
|
||||||
|
if prefix.is_empty()
|
||||||
|
&& let Some(base) = base
|
||||||
|
{
|
||||||
|
Some(format!("{base}{name}"))
|
||||||
|
} else {
|
||||||
|
self.prefixes
|
||||||
|
.get(prefix)
|
||||||
|
.map(|base| format!("{base}{name}"))
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -24,10 +24,10 @@ pub enum Error {
|
|||||||
|
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
UpdateEvaluation(#[from] oxigraph::sparql::UpdateEvaluationError),
|
UpdateEvaluation(#[from] oxigraph::sparql::UpdateEvaluationError),
|
||||||
|
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
TonicTransport(#[from] gl_inference::tonic::transport::Error),
|
TonicTransport(#[from] gl_inference::tonic::transport::Error),
|
||||||
|
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
TonicStatus(#[from] gl_inference::tonic::Status),
|
TonicStatus(#[from] gl_inference::tonic::Status),
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use oxigraph::model::{NamedNode, Term, TermRef};
|
|
||||||
use oxigraph::model::vocab::xsd;
|
|
||||||
use crate::vocab::rdf;
|
use crate::vocab::rdf;
|
||||||
|
use oxigraph::model::vocab::xsd;
|
||||||
|
use oxigraph::model::{NamedNode, Term, TermRef};
|
||||||
|
|
||||||
pub(crate) fn term_to_named_node(term: &Term) -> Option<&NamedNode> {
|
pub(crate) fn term_to_named_node(term: &Term) -> Option<&NamedNode> {
|
||||||
if let Term::NamedNode(node) = term {
|
if let Term::NamedNode(node) = term {
|
||||||
@@ -34,4 +34,4 @@ pub(crate) fn term_ref_as_str(term: TermRef<'_>) -> Option<&str> {
|
|||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+68
-48
@@ -1,12 +1,12 @@
|
|||||||
use rayon::iter::ParallelIterator;
|
|
||||||
use std::collections::{HashMap, HashSet};
|
|
||||||
use oxigraph::model::{Graph, NamedNode, TermRef, NamedOrBlankNodeRef, NamedNodeRef};
|
|
||||||
use rayon::iter::IntoParallelRefIterator;
|
|
||||||
use gl_search::{Field, OwnedValue, Schema};
|
|
||||||
use crate::class::Class;
|
use crate::class::Class;
|
||||||
use crate::{helpers, vocab, CurieHelper};
|
|
||||||
use crate::language::LanguageCondition;
|
use crate::language::LanguageCondition;
|
||||||
use crate::ontology::ResourceDescription;
|
use crate::ontology::ResourceDescription;
|
||||||
|
use crate::{CurieHelper, helpers, vocab};
|
||||||
|
use gl_search::{Field, OwnedValue, Schema};
|
||||||
|
use oxigraph::model::{Graph, NamedNode, NamedNodeRef, NamedOrBlankNodeRef, TermRef};
|
||||||
|
use rayon::iter::IntoParallelRefIterator;
|
||||||
|
use rayon::iter::ParallelIterator;
|
||||||
|
use std::collections::{HashMap, HashSet};
|
||||||
|
|
||||||
pub struct Indexer<'a> {
|
pub struct Indexer<'a> {
|
||||||
language: LanguageCondition,
|
language: LanguageCondition,
|
||||||
@@ -21,8 +21,14 @@ impl<'a> Indexer<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn extract_string(&self, graph: &Graph, subject: NamedNodeRef, predicate: NamedNodeRef) -> OwnedValue {
|
fn extract_string(
|
||||||
graph.object_for_subject_predicate(subject, predicate)
|
&self,
|
||||||
|
graph: &Graph,
|
||||||
|
subject: NamedNodeRef,
|
||||||
|
predicate: NamedNodeRef,
|
||||||
|
) -> OwnedValue {
|
||||||
|
graph
|
||||||
|
.object_for_subject_predicate(subject, predicate)
|
||||||
.filter(|term| self.language.primary_matches_term(*term))
|
.filter(|term| self.language.primary_matches_term(*term))
|
||||||
.and_then(helpers::term_ref_as_str)
|
.and_then(helpers::term_ref_as_str)
|
||||||
.map(String::from)
|
.map(String::from)
|
||||||
@@ -44,52 +50,46 @@ impl<'a> Indexer<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn corporate_body(&self, graph: &Graph, subject: NamedNodeRef) -> HashMap<Field, OwnedValue> {
|
fn corporate_body(&self, graph: &Graph, subject: NamedNodeRef) -> HashMap<Field, OwnedValue> {
|
||||||
HashMap::from_iter([
|
HashMap::from_iter([(
|
||||||
(
|
Schema::field("corporate_name", self.language.primary_language()),
|
||||||
Schema::field("corporate_name", self.language.primary_language()),
|
self.extract_string(graph, subject, vocab::rdaad::NAME_OF_CORPORATE_BODY),
|
||||||
self.extract_string(graph, subject, vocab::rdaad::NAME_OF_CORPORATE_BODY),
|
)])
|
||||||
),
|
|
||||||
])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn work(&self, graph: &Graph, subject: NamedNodeRef) -> HashMap<Field, OwnedValue> {
|
fn work(&self, graph: &Graph, subject: NamedNodeRef) -> HashMap<Field, OwnedValue> {
|
||||||
HashMap::from_iter([
|
HashMap::from_iter([(
|
||||||
(
|
Schema::field("title", self.language.primary_language()),
|
||||||
Schema::field("title", self.language.primary_language()),
|
self.extract_string(graph, subject, vocab::rdawd::TITLE_OF_WORK),
|
||||||
self.extract_string(graph, subject, vocab::rdawd::TITLE_OF_WORK),
|
)])
|
||||||
),
|
|
||||||
])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expression(&self, graph: &Graph, subject: NamedNodeRef) -> HashMap<Field, OwnedValue> {
|
fn expression(&self, graph: &Graph, subject: NamedNodeRef) -> HashMap<Field, OwnedValue> {
|
||||||
HashMap::from_iter([
|
HashMap::from_iter([(
|
||||||
(
|
Schema::field("title", self.language.primary_language()),
|
||||||
Schema::field("title", self.language.primary_language()),
|
self.extract_string(graph, subject, vocab::rdaed::TITLE_OF_EXPRESSION),
|
||||||
self.extract_string(graph, subject, vocab::rdaed::TITLE_OF_EXPRESSION),
|
)])
|
||||||
),
|
|
||||||
])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn manifestation(&self, graph: &Graph, subject: NamedNodeRef) -> HashMap<Field, OwnedValue> {
|
fn manifestation(&self, graph: &Graph, subject: NamedNodeRef) -> HashMap<Field, OwnedValue> {
|
||||||
HashMap::from_iter([
|
HashMap::from_iter([(
|
||||||
(
|
Schema::field("title", self.language.primary_language()),
|
||||||
Schema::field("title", self.language.primary_language()),
|
self.extract_string(graph, subject, vocab::rdamd::TITLE_OF_MANIFESTATION),
|
||||||
self.extract_string(graph, subject, vocab::rdamd::TITLE_OF_MANIFESTATION),
|
)])
|
||||||
),
|
|
||||||
])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn graph(&self, graph: &Graph) -> Vec<HashMap<Field, OwnedValue>> {
|
pub fn graph(&self, graph: &Graph) -> Vec<HashMap<Field, OwnedValue>> {
|
||||||
let mut entities_and_types = HashSet::new();
|
let mut entities_and_types = HashSet::new();
|
||||||
let triples = graph.triples_for_predicate(vocab::rdf::TYPE);
|
let triples = graph.triples_for_predicate(vocab::rdf::TYPE);
|
||||||
for triple in triples {
|
for triple in triples {
|
||||||
if let NamedOrBlankNodeRef::NamedNode(subject) = triple.subject &&
|
if let NamedOrBlankNodeRef::NamedNode(subject) = triple.subject
|
||||||
let TermRef::NamedNode(class) = triple.object {
|
&& let TermRef::NamedNode(class) = triple.object
|
||||||
|
{
|
||||||
entities_and_types.insert((subject, class));
|
entities_and_types.insert((subject, class));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
entities_and_types.par_iter()
|
entities_and_types
|
||||||
|
.par_iter()
|
||||||
.filter_map(|(subject, class)| {
|
.filter_map(|(subject, class)| {
|
||||||
Class::try_from_named_node(*class).and_then(|class| {
|
Class::try_from_named_node(*class).and_then(|class| {
|
||||||
match class {
|
match class {
|
||||||
@@ -101,11 +101,18 @@ impl<'a> Indexer<'a> {
|
|||||||
Class::CorporateBody => Some(self.corporate_body(graph, *subject)),
|
Class::CorporateBody => Some(self.corporate_body(graph, *subject)),
|
||||||
Class::Expression => Some(self.expression(graph, *subject)),
|
Class::Expression => Some(self.expression(graph, *subject)),
|
||||||
Class::Manifestation => Some(self.manifestation(graph, *subject)),
|
Class::Manifestation => Some(self.manifestation(graph, *subject)),
|
||||||
}.map(|mut document| {
|
}
|
||||||
document.insert(Schema::discriminant_field(), OwnedValue::from(class as u64));
|
.map(|mut document| {
|
||||||
document.insert(Schema::iri_field(), OwnedValue::Str(subject.as_str().to_string()));
|
document
|
||||||
|
.insert(Schema::discriminant_field(), OwnedValue::from(class as u64));
|
||||||
|
document.insert(
|
||||||
|
Schema::iri_field(),
|
||||||
|
OwnedValue::Str(subject.as_str().to_string()),
|
||||||
|
);
|
||||||
|
|
||||||
let curie = self.curie_helper.abbreviate(None, subject.as_str())
|
let curie = self
|
||||||
|
.curie_helper
|
||||||
|
.abbreviate(None, subject.as_str())
|
||||||
.map(OwnedValue::Str)
|
.map(OwnedValue::Str)
|
||||||
.unwrap_or(OwnedValue::Null);
|
.unwrap_or(OwnedValue::Null);
|
||||||
document.insert(Schema::curie_field(), curie);
|
document.insert(Schema::curie_field(), curie);
|
||||||
@@ -113,18 +120,24 @@ impl<'a> Indexer<'a> {
|
|||||||
document
|
document
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}).collect()
|
})
|
||||||
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ontology(&self, entities: HashMap<NamedNode, ResourceDescription>) -> Vec<HashMap<Field, OwnedValue>> {
|
pub fn ontology(
|
||||||
|
&self,
|
||||||
|
entities: HashMap<NamedNode, ResourceDescription>,
|
||||||
|
) -> Vec<HashMap<Field, OwnedValue>> {
|
||||||
let label_field = Schema::field("label", self.language.primary_language());
|
let label_field = Schema::field("label", self.language.primary_language());
|
||||||
let definition_field = Schema::field("definition", self.language.primary_language());
|
let definition_field = Schema::field("definition", self.language.primary_language());
|
||||||
|
|
||||||
entities.iter()
|
entities
|
||||||
|
.iter()
|
||||||
.map(|(subject, description)| {
|
.map(|(subject, description)| {
|
||||||
let mut document = HashMap::with_capacity(4);
|
let mut document = HashMap::with_capacity(4);
|
||||||
|
|
||||||
let discriminant = description.class
|
let discriminant = description
|
||||||
|
.class
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.and_then(|node| Class::try_from_named_node(node.as_ref()))
|
.and_then(|node| Class::try_from_named_node(node.as_ref()))
|
||||||
.map(|doc_type| doc_type as u64)
|
.map(|doc_type| doc_type as u64)
|
||||||
@@ -132,7 +145,9 @@ impl<'a> Indexer<'a> {
|
|||||||
.unwrap_or(OwnedValue::Null);
|
.unwrap_or(OwnedValue::Null);
|
||||||
document.insert(Schema::discriminant_field(), discriminant);
|
document.insert(Schema::discriminant_field(), discriminant);
|
||||||
|
|
||||||
let curie = self.curie_helper.abbreviate(None, subject.as_str())
|
let curie = self
|
||||||
|
.curie_helper
|
||||||
|
.abbreviate(None, subject.as_str())
|
||||||
.map(OwnedValue::Str)
|
.map(OwnedValue::Str)
|
||||||
.unwrap_or(OwnedValue::Null);
|
.unwrap_or(OwnedValue::Null);
|
||||||
document.insert(Schema::curie_field(), curie);
|
document.insert(Schema::curie_field(), curie);
|
||||||
@@ -140,17 +155,22 @@ impl<'a> Indexer<'a> {
|
|||||||
let subject = OwnedValue::from(subject.as_str());
|
let subject = OwnedValue::from(subject.as_str());
|
||||||
document.insert(Schema::iri_field(), subject);
|
document.insert(Schema::iri_field(), subject);
|
||||||
|
|
||||||
let label = description.label.clone()
|
let label = description
|
||||||
|
.label
|
||||||
|
.clone()
|
||||||
.map(OwnedValue::from)
|
.map(OwnedValue::from)
|
||||||
.unwrap_or(OwnedValue::Null);
|
.unwrap_or(OwnedValue::Null);
|
||||||
document.insert(label_field, label);
|
document.insert(label_field, label);
|
||||||
|
|
||||||
let definition = description.description.clone()
|
let definition = description
|
||||||
|
.description
|
||||||
|
.clone()
|
||||||
.map(OwnedValue::from)
|
.map(OwnedValue::from)
|
||||||
.unwrap_or(OwnedValue::Null);
|
.unwrap_or(OwnedValue::Null);
|
||||||
document.insert(definition_field, definition);
|
document.insert(definition_field, definition);
|
||||||
|
|
||||||
document
|
document
|
||||||
}).collect()
|
})
|
||||||
|
.collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+31
-25
@@ -1,16 +1,14 @@
|
|||||||
use oxigraph::model::{Literal, TermRef};
|
use oxigraph::model::{Literal, TermRef};
|
||||||
use oxilangtag::LanguageTag;
|
use oxilangtag::LanguageTag;
|
||||||
use std::sync::LazyLock;
|
|
||||||
use spargebra::algebra::{Expression, Function, GraphPattern};
|
use spargebra::algebra::{Expression, Function, GraphPattern};
|
||||||
use spargebra::term::Variable;
|
use spargebra::term::Variable;
|
||||||
|
use std::sync::LazyLock;
|
||||||
|
|
||||||
pub static ENGLISH_TAG: LazyLock<LanguageTag<String>> = LazyLock::new(|| {
|
pub static ENGLISH_TAG: LazyLock<LanguageTag<String>> =
|
||||||
LanguageTag::parse("en".to_string()).unwrap()
|
LazyLock::new(|| LanguageTag::parse("en".to_string()).unwrap());
|
||||||
});
|
|
||||||
|
|
||||||
pub static ENGLISH_OR_UNTAGGED: LazyLock<LanguageCondition> = LazyLock::new(|| {
|
pub static ENGLISH_OR_UNTAGGED: LazyLock<LanguageCondition> =
|
||||||
LanguageCondition::ExactMatchOrUntagged(ENGLISH_TAG.clone())
|
LazyLock::new(|| LanguageCondition::ExactMatchOrUntagged(ENGLISH_TAG.clone()));
|
||||||
});
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum LanguageCondition {
|
pub enum LanguageCondition {
|
||||||
@@ -54,20 +52,23 @@ impl LanguageCondition {
|
|||||||
pub fn filter(&self, variable: impl Into<String>) -> String {
|
pub fn filter(&self, variable: impl Into<String>) -> String {
|
||||||
let variable = variable.into();
|
let variable = variable.into();
|
||||||
|
|
||||||
let exact = |language: &LanguageTag<String>| Expression::FunctionCall(
|
let exact = |language: &LanguageTag<String>| {
|
||||||
Function::LangMatches, vec![
|
Expression::FunctionCall(
|
||||||
Expression::FunctionCall(Function::Lang, vec![
|
Function::LangMatches,
|
||||||
Expression::Variable(Variable::new_unchecked(&variable))
|
vec![
|
||||||
]),
|
Expression::FunctionCall(
|
||||||
Expression::Literal(Literal::new_simple_literal(language.to_string()))
|
Function::Lang,
|
||||||
],
|
vec![Expression::Variable(Variable::new_unchecked(&variable))],
|
||||||
);
|
),
|
||||||
|
Expression::Literal(Literal::new_simple_literal(language.to_string())),
|
||||||
let untagged = Expression::Not(
|
],
|
||||||
Box::new(Expression::FunctionCall(Function::HasLang, vec![
|
)
|
||||||
Expression::Variable(Variable::new_unchecked(&variable))
|
};
|
||||||
]))
|
|
||||||
);
|
let untagged = Expression::Not(Box::new(Expression::FunctionCall(
|
||||||
|
Function::HasLang,
|
||||||
|
vec![Expression::Variable(Variable::new_unchecked(&variable))],
|
||||||
|
)));
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
Self::ExactMatchOnly(language) => Some(exact(language)),
|
Self::ExactMatchOnly(language) => Some(exact(language)),
|
||||||
@@ -77,9 +78,14 @@ impl LanguageCondition {
|
|||||||
)),
|
)),
|
||||||
Self::UntaggedOnly => Some(untagged),
|
Self::UntaggedOnly => Some(untagged),
|
||||||
Self::AnyOrNone => None,
|
Self::AnyOrNone => None,
|
||||||
}.map(|expr| GraphPattern::Filter {
|
}
|
||||||
expr,
|
.map(|expr| {
|
||||||
inner: Box::new(GraphPattern::Bgp { patterns: vec![] }),
|
GraphPattern::Filter {
|
||||||
}.to_string()).unwrap_or_default()
|
expr,
|
||||||
|
inner: Box::new(GraphPattern::Bgp { patterns: vec![] }),
|
||||||
|
}
|
||||||
|
.to_string()
|
||||||
|
})
|
||||||
|
.unwrap_or_default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -1,13 +1,13 @@
|
|||||||
mod curie;
|
mod curie;
|
||||||
mod error;
|
mod error;
|
||||||
|
|
||||||
pub mod vocab;
|
|
||||||
pub mod class;
|
|
||||||
pub mod category;
|
pub mod category;
|
||||||
pub mod language;
|
pub mod class;
|
||||||
mod helpers;
|
mod helpers;
|
||||||
pub mod indexer;
|
pub mod indexer;
|
||||||
|
pub mod language;
|
||||||
pub mod ontology;
|
pub mod ontology;
|
||||||
|
pub mod vocab;
|
||||||
|
|
||||||
pub use curie::{CurieHelper, PREFIXES};
|
pub use curie::{CurieHelper, PREFIXES};
|
||||||
pub use error::{Error, Result};
|
pub use error::{Error, Result};
|
||||||
|
|||||||
+49
-40
@@ -1,17 +1,19 @@
|
|||||||
use std::collections::{HashMap, HashSet};
|
|
||||||
use std::fmt::Debug;
|
|
||||||
use std::str::FromStr;
|
|
||||||
use oxigraph::io::{RdfFormat, RdfParser, RdfSerializer};
|
|
||||||
use oxigraph::model::{Graph, NamedNode, Triple};
|
|
||||||
use oxigraph::sparql::results::{QueryResultsFormat, QueryResultsParser, SliceQueryResultsParserOutput};
|
|
||||||
use spargebra::algebra::GraphPattern;
|
|
||||||
use spargebra::term::{GroundTerm, NamedNodePattern, TermPattern, TriplePattern, Variable};
|
|
||||||
use gl_inference::proto::ontology_client::OntologyClient;
|
|
||||||
use gl_inference::proto::OntologyQueryRequest;
|
|
||||||
use gl_inference::tonic::transport::{Channel, Endpoint};
|
|
||||||
use crate::helpers::{term_as_str, term_to_named_node};
|
use crate::helpers::{term_as_str, term_to_named_node};
|
||||||
use crate::language::LanguageCondition;
|
use crate::language::LanguageCondition;
|
||||||
use crate::vocab;
|
use crate::vocab;
|
||||||
|
use gl_inference::proto::OntologyQueryRequest;
|
||||||
|
use gl_inference::proto::ontology_client::OntologyClient;
|
||||||
|
use gl_inference::tonic::transport::{Channel, Endpoint};
|
||||||
|
use oxigraph::io::{RdfFormat, RdfParser, RdfSerializer};
|
||||||
|
use oxigraph::model::{Graph, NamedNode, Triple};
|
||||||
|
use oxigraph::sparql::results::{
|
||||||
|
QueryResultsFormat, QueryResultsParser, SliceQueryResultsParserOutput,
|
||||||
|
};
|
||||||
|
use spargebra::algebra::GraphPattern;
|
||||||
|
use spargebra::term::{GroundTerm, NamedNodePattern, TermPattern, TriplePattern, Variable};
|
||||||
|
use std::collections::{HashMap, HashSet};
|
||||||
|
use std::fmt::Debug;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
pub struct ResourceDescription {
|
pub struct ResourceDescription {
|
||||||
@@ -45,10 +47,7 @@ impl OntologyBuilder {
|
|||||||
.keep_alive_timeout(std::time::Duration::from_secs(20))
|
.keep_alive_timeout(std::time::Duration::from_secs(20))
|
||||||
.keep_alive_while_idle(true);
|
.keep_alive_while_idle(true);
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self { endpoint, language })
|
||||||
endpoint,
|
|
||||||
language,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn connect(self) -> crate::Result<ConnectedOntology> {
|
pub async fn connect(self) -> crate::Result<ConnectedOntology> {
|
||||||
@@ -78,8 +77,8 @@ impl Debug for ConnectedOntology {
|
|||||||
impl ConnectedOntology {
|
impl ConnectedOntology {
|
||||||
pub async fn run_inference(&mut self, graph: &Graph) -> crate::Result<Graph> {
|
pub async fn run_inference(&mut self, graph: &Graph) -> crate::Result<Graph> {
|
||||||
let mut output_buffer = Vec::new();
|
let mut output_buffer = Vec::new();
|
||||||
let mut serializer = RdfSerializer::from_format(RdfFormat::Turtle)
|
let mut serializer =
|
||||||
.for_writer(output_buffer);
|
RdfSerializer::from_format(RdfFormat::Turtle).for_writer(output_buffer);
|
||||||
for triple in graph {
|
for triple in graph {
|
||||||
serializer.serialize_triple(triple)?;
|
serializer.serialize_triple(triple)?;
|
||||||
}
|
}
|
||||||
@@ -110,7 +109,8 @@ SELECT ?subject ?class WHERE {
|
|||||||
VALUES ?class { rdf:Property rdfs:Class }
|
VALUES ?class { rdf:Property rdfs:Class }
|
||||||
?subject a ?class ;
|
?subject a ?class ;
|
||||||
gl:readOnly "true"^^xsd:boolean .
|
gl:readOnly "true"^^xsd:boolean .
|
||||||
}"#.to_owned();
|
}"#
|
||||||
|
.to_owned();
|
||||||
|
|
||||||
let request = OntologyQueryRequest {
|
let request = OntologyQueryRequest {
|
||||||
sparql_query: Some(sparql_query),
|
sparql_query: Some(sparql_query),
|
||||||
@@ -129,13 +129,11 @@ SELECT ?subject ?class WHERE {
|
|||||||
.and_then(term_to_named_node)
|
.and_then(term_to_named_node)
|
||||||
.cloned();
|
.cloned();
|
||||||
|
|
||||||
let class = solution
|
let class = solution.get("class").and_then(term_to_named_node).cloned();
|
||||||
.get("class")
|
|
||||||
.and_then(term_to_named_node)
|
|
||||||
.cloned();
|
|
||||||
|
|
||||||
if let Some(subject) = subject &&
|
if let Some(subject) = subject
|
||||||
let Some(class) = class {
|
&& let Some(class) = class
|
||||||
|
{
|
||||||
let entry = match class.as_ref() {
|
let entry = match class.as_ref() {
|
||||||
vocab::rdf::PROPERTY => ReadOnlyEntity::Property(subject),
|
vocab::rdf::PROPERTY => ReadOnlyEntity::Property(subject),
|
||||||
vocab::rdfs::CLASS => ReadOnlyEntity::Class(subject),
|
vocab::rdfs::CLASS => ReadOnlyEntity::Class(subject),
|
||||||
@@ -148,8 +146,12 @@ SELECT ?subject ?class WHERE {
|
|||||||
Ok(results)
|
Ok(results)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn selector_to_sparql_pattern(selector: ResourceSelector, nodes: impl IntoIterator<Item = NamedNode>) -> String {
|
fn selector_to_sparql_pattern(
|
||||||
let bindings = nodes.into_iter()
|
selector: ResourceSelector,
|
||||||
|
nodes: impl IntoIterator<Item = NamedNode>,
|
||||||
|
) -> String {
|
||||||
|
let bindings = nodes
|
||||||
|
.into_iter()
|
||||||
.map(GroundTerm::NamedNode)
|
.map(GroundTerm::NamedNode)
|
||||||
.map(Some)
|
.map(Some)
|
||||||
.map(|item| vec![item])
|
.map(|item| vec![item])
|
||||||
@@ -181,16 +183,22 @@ SELECT ?subject ?class WHERE {
|
|||||||
GraphPattern::Join {
|
GraphPattern::Join {
|
||||||
left: Box::new(basic_pattern),
|
left: Box::new(basic_pattern),
|
||||||
right: Box::new(values_pattern),
|
right: Box::new(values_pattern),
|
||||||
}.to_string()
|
}
|
||||||
|
.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn resource_descriptions(&mut self, selector: ResourceSelector, nodes: impl IntoIterator<Item = NamedNode>) -> crate::Result<HashMap<NamedNode, ResourceDescription>> {
|
pub async fn resource_descriptions(
|
||||||
|
&mut self,
|
||||||
|
selector: ResourceSelector,
|
||||||
|
nodes: impl IntoIterator<Item = NamedNode>,
|
||||||
|
) -> crate::Result<HashMap<NamedNode, ResourceDescription>> {
|
||||||
let pattern = Self::selector_to_sparql_pattern(selector, nodes);
|
let pattern = Self::selector_to_sparql_pattern(selector, nodes);
|
||||||
let label_filter = self.language.filter("label");
|
let label_filter = self.language.filter("label");
|
||||||
let comment_filter = self.language.filter("comment");
|
let comment_filter = self.language.filter("comment");
|
||||||
let definition_filter = self.language.filter("definition");
|
let definition_filter = self.language.filter("definition");
|
||||||
|
|
||||||
let sparql_query = format!(r#"PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
|
let sparql_query = format!(
|
||||||
|
r#"PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
|
||||||
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
|
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
|
||||||
PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
|
PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
|
||||||
|
|
||||||
@@ -207,7 +215,8 @@ SELECT ?subject ?label ?description ?class WHERE {{
|
|||||||
{definition_filter}
|
{definition_filter}
|
||||||
}}
|
}}
|
||||||
BIND(COALESCE(?definition, ?comment) AS ?description)
|
BIND(COALESCE(?definition, ?comment) AS ?description)
|
||||||
}}"#);
|
}}"#
|
||||||
|
);
|
||||||
|
|
||||||
let request = OntologyQueryRequest {
|
let request = OntologyQueryRequest {
|
||||||
sparql_query: Some(sparql_query),
|
sparql_query: Some(sparql_query),
|
||||||
@@ -221,10 +230,7 @@ SELECT ?subject ?label ?description ?class WHERE {{
|
|||||||
let mut results = HashMap::new();
|
let mut results = HashMap::new();
|
||||||
if let SliceQueryResultsParserOutput::Solutions(solutions) = parser_output {
|
if let SliceQueryResultsParserOutput::Solutions(solutions) = parser_output {
|
||||||
for solution in solutions.filter_map(Result::ok) {
|
for solution in solutions.filter_map(Result::ok) {
|
||||||
let class = solution
|
let class = solution.get("class").and_then(term_to_named_node).cloned();
|
||||||
.get("class")
|
|
||||||
.and_then(term_to_named_node)
|
|
||||||
.cloned();
|
|
||||||
|
|
||||||
let subject = solution
|
let subject = solution
|
||||||
.get("subject")
|
.get("subject")
|
||||||
@@ -242,14 +248,17 @@ SELECT ?subject ?label ?description ?class WHERE {{
|
|||||||
.and_then(term_as_str)
|
.and_then(term_as_str)
|
||||||
.map(String::from);
|
.map(String::from);
|
||||||
|
|
||||||
results.insert(subject, ResourceDescription {
|
results.insert(
|
||||||
label,
|
subject,
|
||||||
description,
|
ResourceDescription {
|
||||||
class,
|
label,
|
||||||
});
|
description,
|
||||||
|
class,
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(results)
|
Ok(results)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -171,4 +171,4 @@ pub mod skos {
|
|||||||
|
|
||||||
pub const CONCEPT: NamedNodeRef =
|
pub const CONCEPT: NamedNodeRef =
|
||||||
NamedNodeRef::new_unchecked("http://www.w3.org/2004/02/skos/core#Concept");
|
NamedNodeRef::new_unchecked("http://www.w3.org/2004/02/skos/core#Concept");
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -4,4 +4,4 @@ fn main() {
|
|||||||
|
|
||||||
println!("cargo::rerun-if-changed=build.rs");
|
println!("cargo::rerun-if-changed=build.rs");
|
||||||
println!("cargo::rerun-if-changed=proto/inference.proto");
|
println!("cargo::rerun-if-changed=proto/inference.proto");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,13 +9,13 @@ pub enum Error {
|
|||||||
|
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
SparqlSyntax(#[from] oxigraph::sparql::SparqlSyntaxError),
|
SparqlSyntax(#[from] oxigraph::sparql::SparqlSyntaxError),
|
||||||
|
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
QueryEvaluation(#[from] oxigraph::sparql::QueryEvaluationError),
|
QueryEvaluation(#[from] oxigraph::sparql::QueryEvaluationError),
|
||||||
|
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
UpdateEvaluation(#[from] oxigraph::sparql::UpdateEvaluationError),
|
UpdateEvaluation(#[from] oxigraph::sparql::UpdateEvaluationError),
|
||||||
|
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Storage(#[from] oxigraph::store::StorageError),
|
Storage(#[from] oxigraph::store::StorageError),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,4 +2,4 @@ pub mod proto {
|
|||||||
tonic::include_proto!("org.graphofliberty.inference");
|
tonic::include_proto!("org.graphofliberty.inference");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub use tonic;
|
pub use tonic;
|
||||||
|
|||||||
+27
-8
@@ -1,5 +1,5 @@
|
|||||||
use oxigraph::model::GraphNameRef;
|
use oxigraph::model::GraphNameRef;
|
||||||
use oxigraph::sparql::{SparqlEvaluator};
|
use oxigraph::sparql::SparqlEvaluator;
|
||||||
use oxigraph::store::Store;
|
use oxigraph::store::Store;
|
||||||
use tracing::debug_span;
|
use tracing::debug_span;
|
||||||
|
|
||||||
@@ -30,24 +30,43 @@ const DOMAIN_UPDATE: &str = r#"INSERT {
|
|||||||
?x ?p ?y .
|
?x ?p ?y .
|
||||||
}"#;
|
}"#;
|
||||||
|
|
||||||
fn run_update(query_name: &str, query: &str, store: &Store, graph_name: GraphNameRef<'_>) -> crate::error::Result<()> {
|
fn run_update(
|
||||||
|
query_name: &str,
|
||||||
|
query: &str,
|
||||||
|
store: &Store,
|
||||||
|
graph_name: GraphNameRef<'_>,
|
||||||
|
) -> crate::error::Result<()> {
|
||||||
let _span = debug_span!("Update", name = query_name).entered();
|
let _span = debug_span!("Update", name = query_name).entered();
|
||||||
|
|
||||||
SparqlEvaluator::new()
|
SparqlEvaluator::new()
|
||||||
.with_prefix("rdfs", RDF_SCHEMA_PREFIX)?
|
.with_prefix("rdfs", RDF_SCHEMA_PREFIX)?
|
||||||
.with_prefix("gl", GL_PREFIX)?
|
.with_prefix("gl", GL_PREFIX)?
|
||||||
.parse_update(&format!("WITH {graph_name} {query}"))?
|
.parse_update(&format!("WITH {graph_name} {query}"))?
|
||||||
.on_store(store).execute()?;
|
.on_store(store)
|
||||||
|
.execute()?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn infer(inferences: usize, store: &Store, graph_name: GraphNameRef<'_>) -> crate::error::Result<usize> {
|
pub(crate) fn infer(
|
||||||
let old_count = store.quads_for_pattern(None, None, None, Some(graph_name)).count();
|
inferences: usize,
|
||||||
run_update("rdfs:subPropertyOf", SUB_PROPERTY_OF_UPDATE, store, graph_name)?;
|
store: &Store,
|
||||||
|
graph_name: GraphNameRef<'_>,
|
||||||
|
) -> crate::error::Result<usize> {
|
||||||
|
let old_count = store
|
||||||
|
.quads_for_pattern(None, None, None, Some(graph_name))
|
||||||
|
.count();
|
||||||
|
run_update(
|
||||||
|
"rdfs:subPropertyOf",
|
||||||
|
SUB_PROPERTY_OF_UPDATE,
|
||||||
|
store,
|
||||||
|
graph_name,
|
||||||
|
)?;
|
||||||
run_update("rdfs:subClassOf", SUB_CLASS_OF_UPDATE, store, graph_name)?;
|
run_update("rdfs:subClassOf", SUB_CLASS_OF_UPDATE, store, graph_name)?;
|
||||||
run_update("rdfs:domain", DOMAIN_UPDATE, store, graph_name)?;
|
run_update("rdfs:domain", DOMAIN_UPDATE, store, graph_name)?;
|
||||||
let new_count = store.quads_for_pattern(None, None, None, Some(graph_name)).count();
|
let new_count = store
|
||||||
|
.quads_for_pattern(None, None, None, Some(graph_name))
|
||||||
|
.count();
|
||||||
|
|
||||||
let new_inferences_total = inferences + (new_count - old_count);
|
let new_inferences_total = inferences + (new_count - old_count);
|
||||||
if new_count > old_count {
|
if new_count > old_count {
|
||||||
@@ -55,4 +74,4 @@ pub(crate) fn infer(inferences: usize, store: &Store, graph_name: GraphNameRef<'
|
|||||||
} else {
|
} else {
|
||||||
Ok(new_inferences_total)
|
Ok(new_inferences_total)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
|
use crate::service::OntologyService;
|
||||||
|
use gl_inference::proto::ontology_server::OntologyServer;
|
||||||
use tonic::transport::Server;
|
use tonic::transport::Server;
|
||||||
use tracing_subscriber::{fmt, EnvFilter};
|
|
||||||
use tracing_subscriber::fmt::format::FmtSpan;
|
use tracing_subscriber::fmt::format::FmtSpan;
|
||||||
use tracing_subscriber::layer::SubscriberExt;
|
use tracing_subscriber::layer::SubscriberExt;
|
||||||
use tracing_subscriber::util::SubscriberInitExt;
|
use tracing_subscriber::util::SubscriberInitExt;
|
||||||
use gl_inference::proto::ontology_server::OntologyServer;
|
use tracing_subscriber::{EnvFilter, fmt};
|
||||||
use crate::service::OntologyService;
|
|
||||||
|
|
||||||
mod service;
|
|
||||||
mod logic;
|
|
||||||
mod error;
|
mod error;
|
||||||
|
mod logic;
|
||||||
|
mod service;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> color_eyre::Result<()> {
|
async fn main() -> color_eyre::Result<()> {
|
||||||
@@ -35,4 +35,4 @@ async fn main() -> color_eyre::Result<()> {
|
|||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
+83
-39
@@ -1,13 +1,16 @@
|
|||||||
|
use gl_inference::proto::ontology_server::Ontology;
|
||||||
|
use gl_inference::proto::{
|
||||||
|
OntologyClearResponse, OntologyLoadRequest, OntologyLoadResponse, OntologyQueryRequest,
|
||||||
|
OntologyQueryResponse,
|
||||||
|
};
|
||||||
use num_traits::ToPrimitive;
|
use num_traits::ToPrimitive;
|
||||||
use oxigraph::io::{RdfFormat, RdfParser, RdfSerializer};
|
use oxigraph::io::{RdfFormat, RdfParser, RdfSerializer};
|
||||||
use oxigraph::model::{BlankNode, Dataset, GraphName, GraphNameRef, NamedNode, NamedNodeRef};
|
use oxigraph::model::{BlankNode, Dataset, GraphName, GraphNameRef, NamedNode, NamedNodeRef};
|
||||||
use oxigraph::sparql::{QueryResults, SparqlEvaluator};
|
|
||||||
use oxigraph::sparql::results::{QueryResultsFormat, QueryResultsSerializer};
|
use oxigraph::sparql::results::{QueryResultsFormat, QueryResultsSerializer};
|
||||||
|
use oxigraph::sparql::{QueryResults, SparqlEvaluator};
|
||||||
use oxigraph::store::Store;
|
use oxigraph::store::Store;
|
||||||
use tonic::{Request, Response, Status};
|
use tonic::{Request, Response, Status};
|
||||||
use tracing::{debug, debug_span, field};
|
use tracing::{debug, debug_span, field};
|
||||||
use gl_inference::proto::ontology_server::Ontology;
|
|
||||||
use gl_inference::proto::{OntologyClearResponse, OntologyLoadRequest, OntologyLoadResponse, OntologyQueryRequest, OntologyQueryResponse};
|
|
||||||
|
|
||||||
const ONTOLOGY_GRAPH: GraphNameRef = GraphNameRef::NamedNode(NamedNodeRef::new_unchecked(
|
const ONTOLOGY_GRAPH: GraphNameRef = GraphNameRef::NamedNode(NamedNodeRef::new_unchecked(
|
||||||
"https://graphofliberty.org/ontology",
|
"https://graphofliberty.org/ontology",
|
||||||
@@ -27,29 +30,40 @@ impl OntologyService {
|
|||||||
|
|
||||||
#[tonic::async_trait]
|
#[tonic::async_trait]
|
||||||
impl Ontology for OntologyService {
|
impl Ontology for OntologyService {
|
||||||
async fn load(&self, request: Request<OntologyLoadRequest>) -> Result<Response<OntologyLoadResponse>, Status> {
|
async fn load(
|
||||||
let span = debug_span!("Load Ontology", old_size = field::Empty, input_size = field::Empty, inferences = field::Empty, new_size = field::Empty).entered();
|
&self,
|
||||||
|
request: Request<OntologyLoadRequest>,
|
||||||
|
) -> Result<Response<OntologyLoadResponse>, Status> {
|
||||||
|
let span = debug_span!(
|
||||||
|
"Load Ontology",
|
||||||
|
old_size = field::Empty,
|
||||||
|
input_size = field::Empty,
|
||||||
|
inferences = field::Empty,
|
||||||
|
new_size = field::Empty
|
||||||
|
)
|
||||||
|
.entered();
|
||||||
|
|
||||||
let request = request.get_ref();
|
let request = request.get_ref();
|
||||||
|
|
||||||
let old_size = self.ontology.len()
|
let old_size = self
|
||||||
|
.ontology
|
||||||
|
.len()
|
||||||
.map_err(|err| Status::internal(err.to_string()))?
|
.map_err(|err| Status::internal(err.to_string()))?
|
||||||
.to_u64()
|
.to_u64()
|
||||||
.unwrap_or(u64::MAX);
|
.unwrap_or(u64::MAX);
|
||||||
|
|
||||||
let path = std::path::Path::new(&request.path);
|
let path = std::path::Path::new(&request.path);
|
||||||
let store = Store::open_read_only(path).unwrap();
|
let store = Store::open_read_only(path).unwrap();
|
||||||
let input_size = store.len()
|
let input_size = store
|
||||||
|
.len()
|
||||||
.map_err(|err| Status::internal(err.to_string()))?
|
.map_err(|err| Status::internal(err.to_string()))?
|
||||||
.to_u64()
|
.to_u64()
|
||||||
.unwrap_or(u64::MAX);
|
.unwrap_or(u64::MAX);
|
||||||
|
|
||||||
let quads = store.iter()
|
let quads = store.iter().filter_map(Result::ok).map(|mut quad| {
|
||||||
.filter_map(Result::ok)
|
quad.graph_name = ONTOLOGY_GRAPH.into_owned();
|
||||||
.map(|mut quad| {
|
quad
|
||||||
quad.graph_name = ONTOLOGY_GRAPH.into_owned();
|
});
|
||||||
quad
|
|
||||||
});
|
|
||||||
self.ontology.extend(quads).unwrap();
|
self.ontology.extend(quads).unwrap();
|
||||||
|
|
||||||
let inferences = if request.infer {
|
let inferences = if request.infer {
|
||||||
@@ -57,9 +71,13 @@ impl Ontology for OntologyService {
|
|||||||
.map_err(|err| Status::internal(err.to_string()))?
|
.map_err(|err| Status::internal(err.to_string()))?
|
||||||
.to_u64()
|
.to_u64()
|
||||||
.unwrap_or(u64::MAX)
|
.unwrap_or(u64::MAX)
|
||||||
} else { 0 };
|
} else {
|
||||||
|
0
|
||||||
|
};
|
||||||
|
|
||||||
let new_size = self.ontology.len()
|
let new_size = self
|
||||||
|
.ontology
|
||||||
|
.len()
|
||||||
.map_err(|err| Status::internal(err.to_string()))?
|
.map_err(|err| Status::internal(err.to_string()))?
|
||||||
.to_u64()
|
.to_u64()
|
||||||
.unwrap_or(u64::MAX);
|
.unwrap_or(u64::MAX);
|
||||||
@@ -79,27 +97,34 @@ impl Ontology for OntologyService {
|
|||||||
Ok(Response::new(response))
|
Ok(Response::new(response))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn clear(&self, _request: Request<()>) -> Result<Response<OntologyClearResponse>, Status> {
|
async fn clear(
|
||||||
|
&self,
|
||||||
|
_request: Request<()>,
|
||||||
|
) -> Result<Response<OntologyClearResponse>, Status> {
|
||||||
let span = debug_span!("Clear Ontology", size = field::Empty).entered();
|
let span = debug_span!("Clear Ontology", size = field::Empty).entered();
|
||||||
|
|
||||||
let size = self.ontology.len()
|
let size = self
|
||||||
|
.ontology
|
||||||
|
.len()
|
||||||
.map_err(|err| Status::internal(err.to_string()))?
|
.map_err(|err| Status::internal(err.to_string()))?
|
||||||
.to_u64()
|
.to_u64()
|
||||||
.unwrap_or(u64::MAX);
|
.unwrap_or(u64::MAX);
|
||||||
|
|
||||||
self.ontology.clear()
|
self.ontology
|
||||||
|
.clear()
|
||||||
.map_err(|err| Status::internal(err.to_string()))?;
|
.map_err(|err| Status::internal(err.to_string()))?;
|
||||||
|
|
||||||
let response = OntologyClearResponse {
|
let response = OntologyClearResponse { size };
|
||||||
size,
|
|
||||||
};
|
|
||||||
|
|
||||||
span.record("size", response.size);
|
span.record("size", response.size);
|
||||||
|
|
||||||
Ok(Response::new(response))
|
Ok(Response::new(response))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn query(&self, request: Request<OntologyQueryRequest>) -> Result<Response<OntologyQueryResponse>, Status> {
|
async fn query(
|
||||||
|
&self,
|
||||||
|
request: Request<OntologyQueryRequest>,
|
||||||
|
) -> Result<Response<OntologyQueryResponse>, Status> {
|
||||||
let span = debug_span!("Query", inferences = field::Empty).entered();
|
let span = debug_span!("Query", inferences = field::Empty).entered();
|
||||||
|
|
||||||
let request = request.get_ref();
|
let request = request.get_ref();
|
||||||
@@ -108,16 +133,21 @@ impl Ontology for OntologyService {
|
|||||||
let provided_dataset;
|
let provided_dataset;
|
||||||
let graph_name = if let Some(turtle) = &request.turtle {
|
let graph_name = if let Some(turtle) = &request.turtle {
|
||||||
let random_graph_identifier = BlankNode::default();
|
let random_graph_identifier = BlankNode::default();
|
||||||
let graph_name = GraphName::NamedNode(NamedNode::new_unchecked(format!("https://graphofliberty.org/inference/{}", random_graph_identifier.as_str())));
|
let graph_name = GraphName::NamedNode(NamedNode::new_unchecked(format!(
|
||||||
|
"https://graphofliberty.org/inference/{}",
|
||||||
|
random_graph_identifier.as_str()
|
||||||
|
)));
|
||||||
provided_dataset = RdfParser::from_format(RdfFormat::Turtle)
|
provided_dataset = RdfParser::from_format(RdfFormat::Turtle)
|
||||||
.for_slice(&turtle)
|
.for_slice(&turtle)
|
||||||
.filter_map(Result::ok)
|
.filter_map(Result::ok)
|
||||||
.map(|mut quad| {
|
.map(|mut quad| {
|
||||||
quad.graph_name = graph_name.clone();
|
quad.graph_name = graph_name.clone();
|
||||||
quad
|
quad
|
||||||
}).collect::<Dataset>();
|
})
|
||||||
|
.collect::<Dataset>();
|
||||||
|
|
||||||
self.ontology.extend(&provided_dataset)
|
self.ontology
|
||||||
|
.extend(&provided_dataset)
|
||||||
.map_err(|err| Status::internal(err.to_string()))?;
|
.map_err(|err| Status::internal(err.to_string()))?;
|
||||||
|
|
||||||
let inferences = crate::logic::infer(0, &self.ontology, graph_name.as_ref())
|
let inferences = crate::logic::infer(0, &self.ontology, graph_name.as_ref())
|
||||||
@@ -135,34 +165,42 @@ impl Ontology for OntologyService {
|
|||||||
|
|
||||||
let mut evaluator = SparqlEvaluator::new();
|
let mut evaluator = SparqlEvaluator::new();
|
||||||
for (name, iri) in &request.prefixes {
|
for (name, iri) in &request.prefixes {
|
||||||
evaluator = evaluator.with_prefix(name, iri)
|
evaluator = evaluator
|
||||||
|
.with_prefix(name, iri)
|
||||||
.map_err(|err| Status::internal(err.to_string()))?;
|
.map_err(|err| Status::internal(err.to_string()))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(base) = &request.base {
|
if let Some(base) = &request.base {
|
||||||
evaluator = evaluator.with_base_iri(base)
|
evaluator = evaluator
|
||||||
|
.with_base_iri(base)
|
||||||
.map_err(|err| Status::internal(err.to_string()))?;
|
.map_err(|err| Status::internal(err.to_string()))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut query = evaluator.parse_query(sparql_query)
|
let mut query = evaluator
|
||||||
|
.parse_query(sparql_query)
|
||||||
.map_err(|err| Status::internal(err.to_string()))?;
|
.map_err(|err| Status::internal(err.to_string()))?;
|
||||||
|
|
||||||
query.dataset_mut().set_default_graph(vec![graph_name.clone()]);
|
query
|
||||||
|
.dataset_mut()
|
||||||
|
.set_default_graph(vec![graph_name.clone()]);
|
||||||
|
|
||||||
let results = query.on_store(&self.ontology)
|
let results = query
|
||||||
|
.on_store(&self.ontology)
|
||||||
.execute()
|
.execute()
|
||||||
.map_err(|err| Status::internal(err.to_string()))?;
|
.map_err(|err| Status::internal(err.to_string()))?;
|
||||||
|
|
||||||
match results {
|
match results {
|
||||||
QueryResults::Boolean(result) => {
|
QueryResults::Boolean(result) => {
|
||||||
let serializer = QueryResultsSerializer::from_format(QueryResultsFormat::Json);
|
let serializer = QueryResultsSerializer::from_format(QueryResultsFormat::Json);
|
||||||
output_buffer = serializer.serialize_boolean_to_writer(output_buffer, result)
|
output_buffer = serializer
|
||||||
|
.serialize_boolean_to_writer(output_buffer, result)
|
||||||
.map_err(|err| Status::internal(err.to_string()))?;
|
.map_err(|err| Status::internal(err.to_string()))?;
|
||||||
}
|
}
|
||||||
QueryResults::Solutions(solutions) => {
|
QueryResults::Solutions(solutions) => {
|
||||||
let serializer = QueryResultsSerializer::from_format(QueryResultsFormat::Json);
|
let serializer = QueryResultsSerializer::from_format(QueryResultsFormat::Json);
|
||||||
let variables = Vec::from_iter(solutions.variables().iter().cloned());
|
let variables = Vec::from_iter(solutions.variables().iter().cloned());
|
||||||
let mut writer = serializer.serialize_solutions_to_writer(output_buffer, variables)?;
|
let mut writer =
|
||||||
|
serializer.serialize_solutions_to_writer(output_buffer, variables)?;
|
||||||
for solution in solutions.filter_map(Result::ok) {
|
for solution in solutions.filter_map(Result::ok) {
|
||||||
writer.serialize(&solution)?;
|
writer.serialize(&solution)?;
|
||||||
}
|
}
|
||||||
@@ -171,11 +209,13 @@ impl Ontology for OntologyService {
|
|||||||
QueryResults::Graph(graph) => {
|
QueryResults::Graph(graph) => {
|
||||||
let mut serializer = RdfSerializer::from_format(RdfFormat::Turtle);
|
let mut serializer = RdfSerializer::from_format(RdfFormat::Turtle);
|
||||||
for (name, iri) in &request.prefixes {
|
for (name, iri) in &request.prefixes {
|
||||||
serializer = serializer.with_prefix(name, iri)
|
serializer = serializer
|
||||||
|
.with_prefix(name, iri)
|
||||||
.map_err(|err| Status::internal(err.to_string()))?;
|
.map_err(|err| Status::internal(err.to_string()))?;
|
||||||
}
|
}
|
||||||
if let Some(base) = &request.base {
|
if let Some(base) = &request.base {
|
||||||
serializer = serializer.with_base_iri(base)
|
serializer = serializer
|
||||||
|
.with_base_iri(base)
|
||||||
.map_err(|err| Status::internal(err.to_string()))?;
|
.map_err(|err| Status::internal(err.to_string()))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,16 +229,19 @@ impl Ontology for OntologyService {
|
|||||||
} else {
|
} else {
|
||||||
let mut serializer = RdfSerializer::from_format(RdfFormat::Turtle);
|
let mut serializer = RdfSerializer::from_format(RdfFormat::Turtle);
|
||||||
for (name, iri) in &request.prefixes {
|
for (name, iri) in &request.prefixes {
|
||||||
serializer = serializer.with_prefix(name, iri)
|
serializer = serializer
|
||||||
|
.with_prefix(name, iri)
|
||||||
.map_err(|err| Status::internal(err.to_string()))?;
|
.map_err(|err| Status::internal(err.to_string()))?;
|
||||||
}
|
}
|
||||||
if let Some(base) = &request.base {
|
if let Some(base) = &request.base {
|
||||||
serializer = serializer.with_base_iri(base)
|
serializer = serializer
|
||||||
|
.with_base_iri(base)
|
||||||
.map_err(|err| Status::internal(err.to_string()))?;
|
.map_err(|err| Status::internal(err.to_string()))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut serializer = serializer.for_writer(output_buffer);
|
let mut serializer = serializer.for_writer(output_buffer);
|
||||||
let resulting_dataset = self.ontology
|
let resulting_dataset = self
|
||||||
|
.ontology
|
||||||
.quads_for_pattern(None, None, None, Some(graph_name.as_ref()))
|
.quads_for_pattern(None, None, None, Some(graph_name.as_ref()))
|
||||||
.filter_map(Result::ok);
|
.filter_map(Result::ok);
|
||||||
for quad in resulting_dataset {
|
for quad in resulting_dataset {
|
||||||
@@ -212,10 +255,11 @@ impl Ontology for OntologyService {
|
|||||||
response.results = String::from_utf8_lossy(&output_buffer).to_string();
|
response.results = String::from_utf8_lossy(&output_buffer).to_string();
|
||||||
|
|
||||||
if request.turtle.is_some() {
|
if request.turtle.is_some() {
|
||||||
self.ontology.clear_graph(graph_name.as_ref())
|
self.ontology
|
||||||
|
.clear_graph(graph_name.as_ref())
|
||||||
.map_err(|err| Status::internal(err.to_string()))?;
|
.map_err(|err| Status::internal(err.to_string()))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Response::new(response))
|
Ok(Response::new(response))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ gl-search.workspace = true
|
|||||||
|
|
||||||
clap.workspace = true
|
clap.workspace = true
|
||||||
color-eyre.workspace = true
|
color-eyre.workspace = true
|
||||||
csv = "1.4"
|
|
||||||
http.workspace = true
|
http.workspace = true
|
||||||
iced.workspace = true
|
iced.workspace = true
|
||||||
ldp.workspace = true
|
ldp.workspace = true
|
||||||
|
|||||||
+371
-201
@@ -1,33 +1,46 @@
|
|||||||
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
|
|
||||||
use std::ops::Sub;
|
|
||||||
use crate::navigator::Navigator;
|
use crate::navigator::Navigator;
|
||||||
|
use crate::rdf::conversion::term_to_named_node;
|
||||||
use crate::rdf::term_helper::{TermHelper, TermHelperMut};
|
use crate::rdf::term_helper::{TermHelper, TermHelperMut};
|
||||||
|
use crate::tasks;
|
||||||
use crate::widget::iri_input::iri_input;
|
use crate::widget::iri_input::iri_input;
|
||||||
use crate::widget::navigation_area::navigation_area;
|
use crate::widget::navigation_area::navigation_area;
|
||||||
use gl_graph::{language, CurieHelper, vocab};
|
use gl_graph::class::Class;
|
||||||
|
use gl_graph::ontology::{ConnectedOntology, OntologyBuilder, ReadOnlyEntity, ResourceDescription};
|
||||||
|
use gl_graph::{CurieHelper, language, vocab};
|
||||||
|
use gl_search::tantivy::schema::Value;
|
||||||
use gl_search::{Schema, SearchIndex};
|
use gl_search::{Schema, SearchIndex};
|
||||||
use http::StatusCode;
|
use http::StatusCode;
|
||||||
|
use iced::advanced::text::Wrapping;
|
||||||
use iced::alignment::Horizontal;
|
use iced::alignment::Horizontal;
|
||||||
use iced::keyboard::{Event, key};
|
use iced::keyboard::{Event, key};
|
||||||
|
use iced::task::sipper;
|
||||||
use iced::widget::button::Style;
|
use iced::widget::button::Style;
|
||||||
use iced::widget::{button, center, column, combo_box, container, grid, mouse_area, opaque, operation, pick_list, row, scrollable, space, stack, table, text, text_input, toggler};
|
|
||||||
use iced::window::Settings;
|
|
||||||
use iced::{color, keyboard, window, Background, Color, Element, Font, Length, Subscription, Task, font};
|
|
||||||
use iced::advanced::text::Wrapping;
|
|
||||||
use iced::widget::grid::Sizing;
|
use iced::widget::grid::Sizing;
|
||||||
|
use iced::widget::{
|
||||||
|
button, center, column, combo_box, container, grid, mouse_area, opaque, operation, pick_list,
|
||||||
|
row, scrollable, space, stack, table, text, text_input, toggler,
|
||||||
|
};
|
||||||
|
use iced::window::Settings;
|
||||||
|
use iced::{
|
||||||
|
Background, Color, Element, Font, Length, Subscription, Task, color, font, keyboard, window,
|
||||||
|
};
|
||||||
use ldp::middleware::BasicAuthMiddleware;
|
use ldp::middleware::BasicAuthMiddleware;
|
||||||
use ldp::model::{KeyedDataset, QuadKey};
|
use ldp::model::{KeyedDataset, QuadKey};
|
||||||
use ldp::reqwest::{Client, Url};
|
use ldp::reqwest::{Client, Url};
|
||||||
use ldp::reqwest_middleware::{ClientBuilder, ClientWithMiddleware};
|
use ldp::reqwest_middleware::{ClientBuilder, ClientWithMiddleware};
|
||||||
use ldp::{RdfSource, RdfSourceUpdateResponse, ResourceRequestBuilder, SerializationOptions};
|
use ldp::{RdfSource, RdfSourceUpdateResponse, ResourceRequestBuilder, SerializationOptions};
|
||||||
use oxigraph::io::RdfFormat;
|
use oxigraph::io::RdfFormat;
|
||||||
use oxigraph::model::{BaseDirection, Graph, NamedNode, NamedNodeRef, NamedOrBlankNode, NamedOrBlankNodeRef, Quad, Term, TermRef, Triple, TripleRef};
|
use oxigraph::model::{
|
||||||
|
BaseDirection, Graph, NamedNode, NamedNodeRef, NamedOrBlankNode, NamedOrBlankNodeRef, Quad,
|
||||||
|
Term, TermRef, Triple, TripleRef,
|
||||||
|
};
|
||||||
|
use rfd::FileHandle;
|
||||||
|
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
|
||||||
|
use std::ops::Sub;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use tokio::io::AsyncWriteExt;
|
||||||
|
use tonic::codegen::tokio_stream::StreamExt;
|
||||||
use tracing::{debug, error, trace};
|
use tracing::{debug, error, trace};
|
||||||
use gl_graph::class::Class;
|
|
||||||
use gl_graph::ontology::{ConnectedOntology, OntologyBuilder, ReadOnlyEntity, ResourceDescription};
|
|
||||||
use gl_search::tantivy::schema::Value;
|
|
||||||
use crate::rdf::conversion::term_to_named_node;
|
|
||||||
use crate::tasks;
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub(crate) enum Message {
|
pub(crate) enum Message {
|
||||||
@@ -68,6 +81,9 @@ pub(crate) enum Message {
|
|||||||
ShowOverwriteConfirmationModal,
|
ShowOverwriteConfirmationModal,
|
||||||
HideOverwriteConfirmationModal,
|
HideOverwriteConfirmationModal,
|
||||||
ConfirmOverwrite,
|
ConfirmOverwrite,
|
||||||
|
DownloadResource,
|
||||||
|
DownloadLocationSelected(Option<PathBuf>),
|
||||||
|
DownloadProgress((usize, Option<usize>)),
|
||||||
NewDocument(Class, Option<Url>),
|
NewDocument(Class, Option<Url>),
|
||||||
NavigateToPredicate(QuadKey),
|
NavigateToPredicate(QuadKey),
|
||||||
NavigateToObject(QuadKey),
|
NavigateToObject(QuadKey),
|
||||||
@@ -102,6 +118,11 @@ struct SearchState {
|
|||||||
results: Vec<HashMap<gl_search::Field, gl_search::OwnedValue>>,
|
results: Vec<HashMap<gl_search::Field, gl_search::OwnedValue>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum DownloadState {
|
||||||
|
Idle,
|
||||||
|
InProgress(FileHandle, usize),
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) struct Publisher {
|
pub(crate) struct Publisher {
|
||||||
http_client: ClientWithMiddleware,
|
http_client: ClientWithMiddleware,
|
||||||
curie_helper: CurieHelper,
|
curie_helper: CurieHelper,
|
||||||
@@ -116,6 +137,7 @@ pub(crate) struct Publisher {
|
|||||||
url_input_valid: bool,
|
url_input_valid: bool,
|
||||||
navigator: Navigator<Url>,
|
navigator: Navigator<Url>,
|
||||||
document: RdfSource<KeyedDataset<RowState>>,
|
document: RdfSource<KeyedDataset<RowState>>,
|
||||||
|
download_state: DownloadState,
|
||||||
inferred_triples: Graph,
|
inferred_triples: Graph,
|
||||||
hovered_row: Option<QuadKey>,
|
hovered_row: Option<QuadKey>,
|
||||||
search_state: Option<SearchState>,
|
search_state: Option<SearchState>,
|
||||||
@@ -129,11 +151,14 @@ pub(crate) struct Publisher {
|
|||||||
impl Publisher {
|
impl Publisher {
|
||||||
fn is_read_only<'a>(&'a self, triple: impl Into<TripleRef<'a>>) -> bool {
|
fn is_read_only<'a>(&'a self, triple: impl Into<TripleRef<'a>>) -> bool {
|
||||||
let triple = triple.into();
|
let triple = triple.into();
|
||||||
if triple.predicate == vocab::rdf::TYPE &&
|
if triple.predicate == vocab::rdf::TYPE
|
||||||
let TermRef::NamedNode(node) = triple.object {
|
&& let TermRef::NamedNode(node) = triple.object
|
||||||
self.read_only_entities.contains(&ReadOnlyEntity::Class(node.into_owned()))
|
{
|
||||||
|
self.read_only_entities
|
||||||
|
.contains(&ReadOnlyEntity::Class(node.into_owned()))
|
||||||
} else {
|
} else {
|
||||||
self.read_only_entities.contains(&ReadOnlyEntity::Property(triple.predicate.into_owned()))
|
self.read_only_entities
|
||||||
|
.contains(&ReadOnlyEntity::Property(triple.predicate.into_owned()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,6 +199,7 @@ impl Publisher {
|
|||||||
url_input_valid: true,
|
url_input_valid: true,
|
||||||
navigator,
|
navigator,
|
||||||
document,
|
document,
|
||||||
|
download_state: DownloadState::Idle,
|
||||||
inferred_triples: Graph::new(),
|
inferred_triples: Graph::new(),
|
||||||
hovered_row: None,
|
hovered_row: None,
|
||||||
search_state: None,
|
search_state: None,
|
||||||
@@ -193,8 +219,9 @@ impl Publisher {
|
|||||||
|
|
||||||
match message {
|
match message {
|
||||||
Message::ConnectToOntologyService(endpoint) => {
|
Message::ConnectToOntologyService(endpoint) => {
|
||||||
let builder = OntologyBuilder::from_string(&endpoint, language::ENGLISH_OR_UNTAGGED.clone())
|
let builder =
|
||||||
.expect("Unable to parse endpoint of ontology service");
|
OntologyBuilder::from_string(&endpoint, language::ENGLISH_OR_UNTAGGED.clone())
|
||||||
|
.expect("Unable to parse endpoint of ontology service");
|
||||||
|
|
||||||
task = tasks::connect_to_ontology_service(builder)
|
task = tasks::connect_to_ontology_service(builder)
|
||||||
.chain(Task::done(Message::PopulateCaches));
|
.chain(Task::done(Message::PopulateCaches));
|
||||||
@@ -204,9 +231,9 @@ impl Publisher {
|
|||||||
}
|
}
|
||||||
Message::PopulateCaches => {
|
Message::PopulateCaches => {
|
||||||
if let Some(ontology) = &mut self.ontology {
|
if let Some(ontology) = &mut self.ontology {
|
||||||
let classes = Class::ALL.iter().map(|class| {
|
let classes = Class::ALL
|
||||||
class.to_named_node().into_owned()
|
.iter()
|
||||||
});
|
.map(|class| class.to_named_node().into_owned());
|
||||||
|
|
||||||
task = Task::batch([
|
task = Task::batch([
|
||||||
tasks::list_datatypes(ontology.clone()),
|
tasks::list_datatypes(ontology.clone()),
|
||||||
@@ -216,18 +243,22 @@ impl Publisher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Message::CacheDatatypes(datatypes) => {
|
Message::CacheDatatypes(datatypes) => {
|
||||||
self.abbreviated_datatypes = datatypes.keys()
|
self.abbreviated_datatypes = datatypes
|
||||||
|
.keys()
|
||||||
.map(|node| {
|
.map(|node| {
|
||||||
self.curie_helper.abbreviate(None, node.as_str())
|
self.curie_helper
|
||||||
|
.abbreviate(None, node.as_str())
|
||||||
.unwrap_or(node.as_str().to_string())
|
.unwrap_or(node.as_str().to_string())
|
||||||
}).collect();
|
})
|
||||||
|
.collect();
|
||||||
}
|
}
|
||||||
Message::CacheReadOnlyEntities(entities) => {
|
Message::CacheReadOnlyEntities(entities) => {
|
||||||
self.read_only_entities = entities;
|
self.read_only_entities = entities;
|
||||||
}
|
}
|
||||||
Message::LookupResourceDescriptions(nodes) => {
|
Message::LookupResourceDescriptions(nodes) => {
|
||||||
let provided_nodes: HashSet<NamedNode> = HashSet::from_iter(nodes);
|
let provided_nodes: HashSet<NamedNode> = HashSet::from_iter(nodes);
|
||||||
let nodes_with_known_descriptions = HashSet::from_iter(self.resource_descriptions.keys().cloned());
|
let nodes_with_known_descriptions =
|
||||||
|
HashSet::from_iter(self.resource_descriptions.keys().cloned());
|
||||||
let nodes_to_look_up = provided_nodes.sub(&nodes_with_known_descriptions);
|
let nodes_to_look_up = provided_nodes.sub(&nodes_with_known_descriptions);
|
||||||
|
|
||||||
if let Some(ontology) = &mut self.ontology {
|
if let Some(ontology) = &mut self.ontology {
|
||||||
@@ -240,10 +271,18 @@ impl Publisher {
|
|||||||
Message::WindowClosed(id) => {
|
Message::WindowClosed(id) => {
|
||||||
if self.window_id == id {
|
if self.window_id == id {
|
||||||
task = iced::exit();
|
task = iced::exit();
|
||||||
} else if let Some(search_state) = &self.search_state && search_state.window_id == id {
|
} else if let Some(search_state) = &self.search_state
|
||||||
|
&& search_state.window_id == id
|
||||||
|
{
|
||||||
self.search_state = None;
|
self.search_state = None;
|
||||||
} else if let Some(infrence_window_id) = self.inference_window_id && infrence_window_id == id {
|
} else if let Some(infrence_window_id) = self.inference_window_id
|
||||||
|
&& infrence_window_id == id
|
||||||
|
{
|
||||||
self.inference_window_id = None;
|
self.inference_window_id = None;
|
||||||
|
} else if let Some(read_only_window_id) = self.read_only_window_id
|
||||||
|
&& read_only_window_id == id
|
||||||
|
{
|
||||||
|
self.read_only_window_id = None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Message::URLInputChanged(value) => {
|
Message::URLInputChanged(value) => {
|
||||||
@@ -259,47 +298,49 @@ impl Publisher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Message::NavigateTo(url) => {
|
Message::NavigateTo(url) => {
|
||||||
task = Task::done(Message::ResetState)
|
task =
|
||||||
.chain(Task::done(Message::FetchDocument(url)));
|
Task::done(Message::ResetState).chain(Task::done(Message::FetchDocument(url)));
|
||||||
}
|
}
|
||||||
Message::FetchDocument(url) => {
|
Message::FetchDocument(url) => {
|
||||||
let client = self.http_client.clone();
|
let client = self.http_client.clone();
|
||||||
task = Task::future(async {
|
task = Task::perform(
|
||||||
let request = ResourceRequestBuilder::with_client_and_url(client, url)
|
async {
|
||||||
.accept_rdf_format(RdfFormat::Turtle)
|
let request = ResourceRequestBuilder::with_client_and_url(client, url)
|
||||||
.follow_described_by(true)
|
.accept_rdf_format(RdfFormat::Turtle)
|
||||||
.build();
|
.follow_described_by(true)
|
||||||
|
.build();
|
||||||
|
|
||||||
match request.send().await {
|
let response = request.send().await?;
|
||||||
Ok(resource) => match resource.into_rdf_source().await {
|
response.into_rdf_source().await
|
||||||
Ok(rdf_source) => Message::LoadDocument(rdf_source),
|
},
|
||||||
Err(err) => {
|
|result| match result {
|
||||||
Message::ShowError(format!("Unable to parse response: {err}"))
|
Ok(document) => Message::LoadDocument(document),
|
||||||
}
|
Err(ldp::Error::Reqwest(err))
|
||||||
},
|
if err.status() == Some(StatusCode::NOT_FOUND) =>
|
||||||
Err(ldp::Error::Reqwest(err)) => {
|
{
|
||||||
if err.status() == Some(StatusCode::NOT_FOUND) {
|
Message::ResourceNotFound
|
||||||
Message::ResourceNotFound
|
|
||||||
} else {
|
|
||||||
Message::ShowError(err.to_string())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Err(err) => Message::ShowError(format!("Request failed: {err}")),
|
Err(err) => Message::ShowError(err.to_string()),
|
||||||
}
|
},
|
||||||
});
|
);
|
||||||
}
|
}
|
||||||
Message::ResourceNotFound => {
|
Message::ResourceNotFound => {
|
||||||
self.resource_not_found = true;
|
|
||||||
task = Task::done(Message::ShowNewDocumentButtons);
|
task = Task::done(Message::ShowNewDocumentButtons);
|
||||||
|
self.resource_not_found = true;
|
||||||
}
|
}
|
||||||
Message::LoadDocument(document) => {
|
Message::LoadDocument(document) => {
|
||||||
let nodes_to_look_up = document.dataset().quads.iter().flat_map(|(_, quad)| {
|
let nodes_to_look_up = document
|
||||||
let mut nodes = vec![ quad.predicate.clone() ];
|
.dataset()
|
||||||
if let Some(object) = term_to_named_node(&quad.object) {
|
.quads
|
||||||
nodes.push(object.clone());
|
.iter()
|
||||||
}
|
.flat_map(|(_, quad)| {
|
||||||
nodes
|
let mut nodes = vec![quad.predicate.clone()];
|
||||||
}).collect();
|
if let Some(object) = term_to_named_node(&quad.object) {
|
||||||
|
nodes.push(object.clone());
|
||||||
|
}
|
||||||
|
nodes
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
let add_row_tasks = document.dataset().quads.iter().map(|(key, quad)| {
|
let add_row_tasks = document.dataset().quads.iter().map(|(key, quad)| {
|
||||||
let datatype_state = combo_box::State::new(self.abbreviated_datatypes.clone());
|
let datatype_state = combo_box::State::new(self.abbreviated_datatypes.clone());
|
||||||
@@ -374,9 +415,10 @@ impl Publisher {
|
|||||||
task = window_task.then(|_| operation::focus("query"));
|
task = window_task.then(|_| operation::focus("query"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(selected_entity_class) = selected_entity_class &&
|
if let Some(selected_entity_class) = selected_entity_class
|
||||||
let Some(class) = Class::try_from_named_node(selected_entity_class) {
|
&& let Some(class) = Class::try_from_named_node(selected_entity_class)
|
||||||
task = task.chain(Task::done(Message::UpdateQueryClass(class)))
|
{
|
||||||
|
task = task.chain(Task::done(Message::UpdateQueryClass(class)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Message::UpdateQueryClass(type_) => {
|
Message::UpdateQueryClass(type_) => {
|
||||||
@@ -387,7 +429,8 @@ impl Publisher {
|
|||||||
}
|
}
|
||||||
Message::QueryUpdated(new_query) => {
|
Message::QueryUpdated(new_query) => {
|
||||||
if let Some(search_state) = &mut self.search_state {
|
if let Some(search_state) = &mut self.search_state {
|
||||||
let category_id = search_state.entity_class_selection
|
let category_id = search_state
|
||||||
|
.entity_class_selection
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|selection| selection.to_owned() as u64);
|
.map(|selection| selection.to_owned() as u64);
|
||||||
|
|
||||||
@@ -407,7 +450,9 @@ impl Publisher {
|
|||||||
}
|
}
|
||||||
Message::SearchResultClicked(node) => {
|
Message::SearchResultClicked(node) => {
|
||||||
if let Some(search_state) = &self.search_state {
|
if let Some(search_state) = &self.search_state {
|
||||||
task = task.chain(Task::done(Message::LookupResourceDescriptions(HashSet::from_iter([node.clone()]))));
|
task = task.chain(Task::done(Message::LookupResourceDescriptions(
|
||||||
|
HashSet::from_iter([node.clone()]),
|
||||||
|
)));
|
||||||
|
|
||||||
match search_state.action {
|
match search_state.action {
|
||||||
SearchResultClickAction::URLInput => {
|
SearchResultClickAction::URLInput => {
|
||||||
@@ -497,15 +542,18 @@ impl Publisher {
|
|||||||
Message::SaveGraph(overwrite) => {
|
Message::SaveGraph(overwrite) => {
|
||||||
let client = self.http_client.clone();
|
let client = self.http_client.clone();
|
||||||
let read_only_entities = self.read_only_entities.clone();
|
let read_only_entities = self.read_only_entities.clone();
|
||||||
let options = SerializationOptions::from_format(RdfFormat::Turtle)
|
let options = SerializationOptions::from_format(RdfFormat::Turtle).with_filter(
|
||||||
.with_filter(move |triple| {
|
move |triple| {
|
||||||
if triple.predicate == vocab::rdf::TYPE &&
|
if triple.predicate == vocab::rdf::TYPE
|
||||||
let TermRef::NamedNode(node) = triple.object {
|
&& let TermRef::NamedNode(node) = triple.object
|
||||||
|
{
|
||||||
!read_only_entities.contains(&ReadOnlyEntity::Class(node.into_owned()))
|
!read_only_entities.contains(&ReadOnlyEntity::Class(node.into_owned()))
|
||||||
} else {
|
} else {
|
||||||
!read_only_entities.contains(&ReadOnlyEntity::Property(triple.predicate.into_owned()))
|
!read_only_entities
|
||||||
|
.contains(&ReadOnlyEntity::Property(triple.predicate.into_owned()))
|
||||||
}
|
}
|
||||||
});
|
},
|
||||||
|
);
|
||||||
let request = self
|
let request = self
|
||||||
.document
|
.document
|
||||||
.to_update(options)
|
.to_update(options)
|
||||||
@@ -531,6 +579,58 @@ impl Publisher {
|
|||||||
task = Task::done(Message::SaveGraph(true))
|
task = Task::done(Message::SaveGraph(true))
|
||||||
.chain(Task::done(Message::HideOverwriteConfirmationModal));
|
.chain(Task::done(Message::HideOverwriteConfirmationModal));
|
||||||
}
|
}
|
||||||
|
Message::DownloadResource => {
|
||||||
|
let suggested_file_name = self.document.origin_file_name().unwrap_or_default();
|
||||||
|
|
||||||
|
let destination_selector =
|
||||||
|
rfd::AsyncFileDialog::new().set_file_name(suggested_file_name);
|
||||||
|
|
||||||
|
task = Task::perform(destination_selector.save_file(), |result| {
|
||||||
|
Message::DownloadLocationSelected(result.map(|fh| fh.path().to_owned()))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Message::DownloadLocationSelected(None) => {
|
||||||
|
debug!("canceled");
|
||||||
|
}
|
||||||
|
Message::DownloadLocationSelected(Some(path)) => {
|
||||||
|
if let Ok(url) = Url::parse(&self.url_input) {
|
||||||
|
let client = self.http_client.clone();
|
||||||
|
task = Task::sip(
|
||||||
|
sipper(async move |mut sender| {
|
||||||
|
let request = ResourceRequestBuilder::with_client_and_url(client, url)
|
||||||
|
.follow_described_by(false)
|
||||||
|
.build();
|
||||||
|
let resource = request.send().await?;
|
||||||
|
|
||||||
|
let mut handle = tokio::fs::File::create(path).await?;
|
||||||
|
let mut progress = 0usize;
|
||||||
|
let total_size = resource.size();
|
||||||
|
|
||||||
|
let mut stream = resource.into_stream();
|
||||||
|
while let Some(chunk_result) = stream.next().await {
|
||||||
|
let chunk = chunk_result?;
|
||||||
|
handle.write_all(&chunk).await?;
|
||||||
|
progress += chunk.len();
|
||||||
|
sender.send((progress, total_size)).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}),
|
||||||
|
Message::DownloadProgress,
|
||||||
|
|result: crate::error::Result<()>| {
|
||||||
|
if let Err(err) = result {
|
||||||
|
Message::ShowError(err.to_string())
|
||||||
|
} else {
|
||||||
|
Message::None
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Message::DownloadProgress((bytes_written, Some(bytes_total))) => {
|
||||||
|
let percentage = bytes_written as f32 / bytes_total as f32;
|
||||||
|
debug!(bytes_written, bytes_total, percentage);
|
||||||
|
}
|
||||||
Message::ShowNewDocumentButtons => {
|
Message::ShowNewDocumentButtons => {
|
||||||
self.show_new_document_buttons = true;
|
self.show_new_document_buttons = true;
|
||||||
}
|
}
|
||||||
@@ -549,8 +649,9 @@ impl Publisher {
|
|||||||
let quad = document.quad_from_triple(triple.into_owned());
|
let quad = document.quad_from_triple(triple.into_owned());
|
||||||
document.dataset_mut().quads.insert(quad);
|
document.dataset_mut().quads.insert(quad);
|
||||||
|
|
||||||
if triple.predicate == vocab::rdf::TYPE &&
|
if triple.predicate == vocab::rdf::TYPE
|
||||||
let TermRef::NamedNode(node) = triple.object {
|
&& let TermRef::NamedNode(node) = triple.object
|
||||||
|
{
|
||||||
nodes_to_look_up.insert(node.into_owned());
|
nodes_to_look_up.insert(node.into_owned());
|
||||||
} else {
|
} else {
|
||||||
nodes_to_look_up.insert(triple.predicate.into_owned());
|
nodes_to_look_up.insert(triple.predicate.into_owned());
|
||||||
@@ -581,7 +682,9 @@ impl Publisher {
|
|||||||
Url::parse(node.as_str()).ok()
|
Url::parse(node.as_str()).ok()
|
||||||
} else if let Term::Literal(literal) = &quad.object {
|
} else if let Term::Literal(literal) = &quad.object {
|
||||||
Url::parse(literal.value()).ok()
|
Url::parse(literal.value()).ok()
|
||||||
} else { None };
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
if let Some(url) = url {
|
if let Some(url) = url {
|
||||||
task = Task::done(Message::URLInputChanged(url.to_string()))
|
task = Task::done(Message::URLInputChanged(url.to_string()))
|
||||||
@@ -601,7 +704,8 @@ impl Publisher {
|
|||||||
}
|
}
|
||||||
Message::RunInference => {
|
Message::RunInference => {
|
||||||
if let Some(ontology) = &mut self.ontology {
|
if let Some(ontology) = &mut self.ontology {
|
||||||
let graph = self.document
|
let graph = self
|
||||||
|
.document
|
||||||
.dataset()
|
.dataset()
|
||||||
.quads
|
.quads
|
||||||
.iter()
|
.iter()
|
||||||
@@ -613,14 +717,12 @@ impl Publisher {
|
|||||||
}
|
}
|
||||||
Message::SetInferredTriples(graph) => {
|
Message::SetInferredTriples(graph) => {
|
||||||
if let Some(ontology) = &mut self.ontology {
|
if let Some(ontology) = &mut self.ontology {
|
||||||
let predicates = graph.iter()
|
let predicates = graph.iter().map(|triple| triple.predicate.into_owned());
|
||||||
.map(|triple| triple.predicate.into_owned());
|
|
||||||
|
|
||||||
let objects = graph.iter()
|
let objects = graph.iter().filter_map(|triple| match triple.object {
|
||||||
.filter_map(|triple| match triple.object {
|
TermRef::NamedNode(node) => Some(node.into_owned()),
|
||||||
TermRef::NamedNode(node) => Some(node.into_owned()),
|
_ => None,
|
||||||
_ => None,
|
});
|
||||||
});
|
|
||||||
|
|
||||||
let mut nodes_to_look_up: HashSet<NamedNode> = HashSet::from_iter(predicates);
|
let mut nodes_to_look_up: HashSet<NamedNode> = HashSet::from_iter(predicates);
|
||||||
nodes_to_look_up.extend(objects);
|
nodes_to_look_up.extend(objects);
|
||||||
@@ -664,11 +766,17 @@ impl Publisher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn title(&self, window: window::Id) -> String {
|
pub(crate) fn title(&self, window: window::Id) -> String {
|
||||||
if let Some(inference_window_id) = self.inference_window_id && window == inference_window_id {
|
if let Some(inference_window_id) = self.inference_window_id
|
||||||
|
&& window == inference_window_id
|
||||||
|
{
|
||||||
"Graph of Liberty Publisher - Inferences".to_string()
|
"Graph of Liberty Publisher - Inferences".to_string()
|
||||||
} else if let Some(search_state) = &self.search_state && window == search_state.window_id {
|
} else if let Some(search_state) = &self.search_state
|
||||||
|
&& window == search_state.window_id
|
||||||
|
{
|
||||||
"Graph of Liberty Publisher - Search".to_string()
|
"Graph of Liberty Publisher - Search".to_string()
|
||||||
} else if let Some(read_only_window_id) = &self.read_only_window_id {
|
} else if let Some(read_only_window_id) = self.read_only_window_id
|
||||||
|
&& window == read_only_window_id
|
||||||
|
{
|
||||||
"Graph of Liberty Publisher - Read Only Triples".to_string()
|
"Graph of Liberty Publisher - Read Only Triples".to_string()
|
||||||
} else {
|
} else {
|
||||||
"Graph of Liberty Publisher".to_string()
|
"Graph of Liberty Publisher".to_string()
|
||||||
@@ -682,43 +790,64 @@ impl Publisher {
|
|||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
fn view_inferred_class_table<'a>(&'a self, triples: impl IntoIterator<Item = TripleRef<'a>>) -> Element<'a, Message> {
|
fn view_inferred_class_table<'a>(
|
||||||
let bold = |t| text(t).font(Font { weight: font::Weight::Bold, ..Font::default() });
|
&'a self,
|
||||||
|
triples: impl IntoIterator<Item = TripleRef<'a>>,
|
||||||
|
) -> Element<'a, Message> {
|
||||||
|
let bold = |t| {
|
||||||
|
text(t).font(Font {
|
||||||
|
weight: font::Weight::Bold,
|
||||||
|
..Font::default()
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
let subject_column = table::column(bold("Subject"), |(subject, _): (NamedNodeRef, _)| {
|
let subject_column = table::column(bold("Subject"), |(subject, _): (NamedNodeRef, _)| {
|
||||||
text(self.curie_helper
|
text(
|
||||||
.abbreviate(Some(self.document.origin()), subject.as_str())
|
self.curie_helper
|
||||||
.unwrap_or_else(|| subject.as_str().to_string()))
|
.abbreviate(Some(self.document.origin()), subject.as_str())
|
||||||
|
.unwrap_or_else(|| subject.as_str().to_string()),
|
||||||
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
let class_column = table::column(bold("Classes"), |(_, classes): (_, BTreeSet<NamedNodeRef>)| {
|
let class_column = table::column(
|
||||||
let textual_classes = classes.iter()
|
bold("Classes"),
|
||||||
.map(|class| {
|
|(_, classes): (_, BTreeSet<NamedNodeRef>)| {
|
||||||
let curie = self.curie_helper
|
let textual_classes = classes
|
||||||
.abbreviate(Some(self.document.origin()), class.as_str())
|
.iter()
|
||||||
.unwrap_or_else(|| class.as_str().to_string());
|
.map(|class| {
|
||||||
|
let curie = self
|
||||||
|
.curie_helper
|
||||||
|
.abbreviate(Some(self.document.origin()), class.as_str())
|
||||||
|
.unwrap_or_else(|| class.as_str().to_string());
|
||||||
|
|
||||||
let label = self.resource_descriptions
|
let label = self
|
||||||
.get(&class.into_owned())
|
.resource_descriptions
|
||||||
.and_then(|description| description.label.clone());
|
.get(&class.into_owned())
|
||||||
|
.and_then(|description| description.label.clone());
|
||||||
|
|
||||||
if let Some(label) = label {
|
if let Some(label) = label {
|
||||||
format!("{curie} ({label})")
|
format!("{curie} ({label})")
|
||||||
} else {
|
} else {
|
||||||
curie
|
curie
|
||||||
}
|
}
|
||||||
}).collect::<Vec<_>>()
|
})
|
||||||
.join("\n");
|
.collect::<Vec<_>>()
|
||||||
|
.join("\n");
|
||||||
|
|
||||||
text(textual_classes)
|
text(textual_classes)
|
||||||
});
|
},
|
||||||
|
);
|
||||||
|
|
||||||
let mut inferred_classes: BTreeMap<NamedNodeRef, BTreeSet<NamedNodeRef>> = BTreeMap::new();
|
let mut inferred_classes: BTreeMap<NamedNodeRef, BTreeSet<NamedNodeRef>> = BTreeMap::new();
|
||||||
for triple in triples {
|
for triple in triples {
|
||||||
if let NamedOrBlankNodeRef::NamedNode(subject) = triple.subject &&
|
if let NamedOrBlankNodeRef::NamedNode(subject) = triple.subject
|
||||||
let TermRef::NamedNode(class) = triple.object {
|
&& let TermRef::NamedNode(class) = triple.object
|
||||||
inferred_classes.entry(subject)
|
{
|
||||||
.and_modify(|classes| { classes.insert(class); })
|
inferred_classes
|
||||||
|
.entry(subject)
|
||||||
|
.and_modify(|classes| {
|
||||||
|
classes.insert(class);
|
||||||
|
})
|
||||||
.or_insert(BTreeSet::from_iter([class]));
|
.or_insert(BTreeSet::from_iter([class]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -726,14 +855,24 @@ impl Publisher {
|
|||||||
table([subject_column, class_column], inferred_classes).into()
|
table([subject_column, class_column], inferred_classes).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn view_triple_table<'a>(&'a self, triples: impl IntoIterator<Item = TripleRef<'a>>) -> Element<'a, Message> {
|
fn view_triple_table<'a>(
|
||||||
let bold = |t| text(t).font(Font { weight: font::Weight::Bold, ..Font::default() });
|
&'a self,
|
||||||
|
triples: impl IntoIterator<Item = TripleRef<'a>>,
|
||||||
|
) -> Element<'a, Message> {
|
||||||
|
let bold = |t| {
|
||||||
|
text(t).font(Font {
|
||||||
|
weight: font::Weight::Bold,
|
||||||
|
..Font::default()
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
let subject_column = table::column(bold("Subject"), |triple: TripleRef| {
|
let subject_column = table::column(bold("Subject"), |triple: TripleRef| {
|
||||||
let curie = if let NamedOrBlankNodeRef::NamedNode(subject) = triple.subject {
|
let curie = if let NamedOrBlankNodeRef::NamedNode(subject) = triple.subject {
|
||||||
Some(self.curie_helper
|
Some(
|
||||||
.abbreviate(Some(self.document.origin()), subject.as_str())
|
self.curie_helper
|
||||||
.unwrap_or_else(|| subject.as_str().to_string()))
|
.abbreviate(Some(self.document.origin()), subject.as_str())
|
||||||
|
.unwrap_or_else(|| subject.as_str().to_string()),
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
@@ -742,11 +881,13 @@ impl Publisher {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let predicate_column = table::column(bold("Predicate"), |triple: TripleRef| {
|
let predicate_column = table::column(bold("Predicate"), |triple: TripleRef| {
|
||||||
let curie = self.curie_helper
|
let curie = self
|
||||||
|
.curie_helper
|
||||||
.abbreviate(None, triple.predicate.as_str())
|
.abbreviate(None, triple.predicate.as_str())
|
||||||
.unwrap_or_else(|| triple.predicate.as_str().to_string());
|
.unwrap_or_else(|| triple.predicate.as_str().to_string());
|
||||||
|
|
||||||
let label = self.resource_descriptions
|
let label = self
|
||||||
|
.resource_descriptions
|
||||||
.get(&triple.predicate.into_owned())
|
.get(&triple.predicate.into_owned())
|
||||||
.and_then(|description| description.label.clone());
|
.and_then(|description| description.label.clone());
|
||||||
|
|
||||||
@@ -757,14 +898,16 @@ impl Publisher {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let object_column = table::column(bold("Object"), |triple: TripleRef| {
|
let object_column =
|
||||||
match triple.object {
|
table::column(bold("Object"), |triple: TripleRef| match triple.object {
|
||||||
TermRef::NamedNode(node) => {
|
TermRef::NamedNode(node) => {
|
||||||
let curie = self.curie_helper
|
let curie = self
|
||||||
|
.curie_helper
|
||||||
.abbreviate(Some(self.document.origin()), node.as_str())
|
.abbreviate(Some(self.document.origin()), node.as_str())
|
||||||
.unwrap_or_else(|| node.as_str().to_string());
|
.unwrap_or_else(|| node.as_str().to_string());
|
||||||
|
|
||||||
let label = self.resource_descriptions
|
let label = self
|
||||||
|
.resource_descriptions
|
||||||
.get(&node.into_owned())
|
.get(&node.into_owned())
|
||||||
.and_then(|description| description.label.clone());
|
.and_then(|description| description.label.clone());
|
||||||
|
|
||||||
@@ -775,8 +918,7 @@ impl Publisher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => text(triple.object.to_string()),
|
_ => text(triple.object.to_string()),
|
||||||
}
|
});
|
||||||
});
|
|
||||||
|
|
||||||
table([subject_column, predicate_column, object_column], triples).into()
|
table([subject_column, predicate_column, object_column], triples).into()
|
||||||
}
|
}
|
||||||
@@ -790,45 +932,55 @@ impl Publisher {
|
|||||||
search_state.entity_class_selection.as_ref(),
|
search_state.entity_class_selection.as_ref(),
|
||||||
Class::ALL,
|
Class::ALL,
|
||||||
ToString::to_string,
|
ToString::to_string,
|
||||||
).on_select(Message::UpdateQueryClass);
|
)
|
||||||
|
.on_select(Message::UpdateQueryClass);
|
||||||
|
|
||||||
let mut columns = vec![table::column(text("CURIE"), |document: &HashMap<gl_search::Field, gl_search::OwnedValue>| {
|
let mut columns = vec![table::column(
|
||||||
let iri = document.get(&Schema::iri_field())
|
text("CURIE"),
|
||||||
.and_then(|value| value.as_str())
|
|document: &HashMap<gl_search::Field, gl_search::OwnedValue>| {
|
||||||
.unwrap_or_default();
|
let iri = document
|
||||||
|
.get(&Schema::iri_field())
|
||||||
|
.and_then(|value| value.as_str())
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
let abbreviated_iri = document.get(&Schema::curie_field())
|
let abbreviated_iri = document
|
||||||
.and_then(|value| value.as_str())
|
.get(&Schema::curie_field())
|
||||||
.unwrap_or_default();
|
.and_then(|value| value.as_str())
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
button(text(abbreviated_iri).wrapping(Wrapping::Word))
|
button(text(abbreviated_iri).wrapping(Wrapping::Word))
|
||||||
.on_press(Message::SearchResultClicked(NamedNode::new_unchecked(iri)))
|
.on_press(Message::SearchResultClicked(NamedNode::new_unchecked(iri)))
|
||||||
.style(button::text)
|
.style(button::text)
|
||||||
})];
|
},
|
||||||
|
)];
|
||||||
|
|
||||||
let fields = search_state.entity_class_selection
|
let fields = search_state
|
||||||
|
.entity_class_selection
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|class| {
|
.map(|class| class.fields(language::ENGLISH_TAG.clone()))
|
||||||
class.fields(language::ENGLISH_TAG.clone())
|
.unwrap_or_default();
|
||||||
}).unwrap_or_default();
|
|
||||||
|
|
||||||
for (field, label) in fields {
|
for (field, label) in fields {
|
||||||
columns.push(
|
columns.push(
|
||||||
table::column(text(label), move |document: &HashMap<gl_search::Field, gl_search::OwnedValue>| {
|
table::column(
|
||||||
let iri = document.get(&Schema::iri_field())
|
text(label),
|
||||||
.and_then(|value| value.as_str())
|
move |document: &HashMap<gl_search::Field, gl_search::OwnedValue>| {
|
||||||
.unwrap_or_default();
|
let iri = document
|
||||||
|
.get(&Schema::iri_field())
|
||||||
|
.and_then(|value| value.as_str())
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
let value = document
|
let value = document
|
||||||
.get(&field)
|
.get(&field)
|
||||||
.and_then(|value| value.as_str())
|
.and_then(|value| value.as_str())
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
button(text(value).wrapping(Wrapping::Word))
|
button(text(value).wrapping(Wrapping::Word))
|
||||||
.on_press(Message::SearchResultClicked(NamedNode::new_unchecked(iri)))
|
.on_press(Message::SearchResultClicked(NamedNode::new_unchecked(iri)))
|
||||||
.style(button::text)
|
.style(button::text)
|
||||||
})
|
},
|
||||||
.width(Length::Fixed(256.0)),
|
)
|
||||||
|
.width(Length::Fixed(256.0)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -842,24 +994,26 @@ impl Publisher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn view_inference_window(&self) -> Element<'_, Message> {
|
fn view_inference_window(&self) -> Element<'_, Message> {
|
||||||
let classes = self.inferred_triples.triples_for_predicate(vocab::rdf::TYPE);
|
let classes = self
|
||||||
|
.inferred_triples
|
||||||
|
.triples_for_predicate(vocab::rdf::TYPE);
|
||||||
|
|
||||||
column![
|
column![
|
||||||
self.view_inferred_class_table(classes),
|
self.view_inferred_class_table(classes),
|
||||||
scrollable(self.view_triple_table(&self.inferred_triples)),
|
scrollable(self.view_triple_table(&self.inferred_triples)),
|
||||||
].into()
|
]
|
||||||
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn view_read_only_window(&self) -> Element<'_, Message> {
|
fn view_read_only_window(&self) -> Element<'_, Message> {
|
||||||
let read_only_triples = self.document
|
let read_only_triples = self
|
||||||
|
.document
|
||||||
.dataset()
|
.dataset()
|
||||||
.iter_both()
|
.iter_both()
|
||||||
.filter_map(|(_, quad, state)| if state.read_only { Some(quad) } else { None })
|
.filter_map(|(_, quad, state)| if state.read_only { Some(quad) } else { None })
|
||||||
.map(|quad| TripleRef::from(quad.as_ref()));
|
.map(|quad| TripleRef::from(quad.as_ref()));
|
||||||
|
|
||||||
column![
|
column![scrollable(self.view_triple_table(read_only_triples)),].into()
|
||||||
scrollable(self.view_triple_table(read_only_triples)),
|
|
||||||
].into()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn view_row<'a>(
|
fn view_row<'a>(
|
||||||
@@ -910,14 +1064,16 @@ impl Publisher {
|
|||||||
.on_shift_click(Message::NavigateToPredicate(key))
|
.on_shift_click(Message::NavigateToPredicate(key))
|
||||||
};
|
};
|
||||||
|
|
||||||
let predicate_label = self.resource_descriptions
|
let predicate_label = self
|
||||||
|
.resource_descriptions
|
||||||
.get(&quad.predicate)
|
.get(&quad.predicate)
|
||||||
.and_then(|description| description.label.clone())
|
.and_then(|description| description.label.clone())
|
||||||
.map(|label| container(text(label)));
|
.map(|label| container(text(label)));
|
||||||
|
|
||||||
let term = TermHelper::new(&quad.object);
|
let term = TermHelper::new(&quad.object);
|
||||||
|
|
||||||
let value_label = term.value_as_named_node()
|
let value_label = term
|
||||||
|
.value_as_named_node()
|
||||||
.and_then(|node| self.resource_descriptions.get(&node.into_owned()))
|
.and_then(|node| self.resource_descriptions.get(&node.into_owned()))
|
||||||
.and_then(|description| description.label.clone())
|
.and_then(|description| description.label.clone())
|
||||||
.map(|label| container(text(label)));
|
.map(|label| container(text(label)));
|
||||||
@@ -938,28 +1094,29 @@ impl Publisher {
|
|||||||
/* If the object is not a valid URL (either as a literal string or as a named node), then
|
/* If the object is not a valid URL (either as a literal string or as a named node), then
|
||||||
* use a normal text input instead of an iri_input.
|
* use a normal text input instead of an iri_input.
|
||||||
*/
|
*/
|
||||||
let object_input: Element<Message> = if term.is_named_node() || Url::parse(term.value()).is_ok() {
|
let object_input: Element<Message> =
|
||||||
let base = iri_input(&self.curie_helper, "Object", Some(base), value.as_str())
|
if term.is_named_node() || Url::parse(term.value()).is_ok() {
|
||||||
.on_shift_click(Message::NavigateToObject(key));
|
let base = iri_input(&self.curie_helper, "Object", Some(base), value.as_str())
|
||||||
if state.read_only {
|
.on_shift_click(Message::NavigateToObject(key));
|
||||||
base.into()
|
if state.read_only {
|
||||||
|
base.into()
|
||||||
|
} else {
|
||||||
|
base.align_x(value_alignment)
|
||||||
|
.on_input(move |value| Message::ObjectUpdated(key, value))
|
||||||
|
.on_control_click(Message::OpenQueryWindow(
|
||||||
|
SearchResultClickAction::Object(key),
|
||||||
|
))
|
||||||
|
.into()
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
base.align_x(value_alignment)
|
let base = text_input("Object", value.clone());
|
||||||
.on_input(move |value| Message::ObjectUpdated(key, value))
|
if state.read_only {
|
||||||
.on_control_click(Message::OpenQueryWindow(SearchResultClickAction::Object(
|
base.into()
|
||||||
key,
|
} else {
|
||||||
)))
|
base.on_input(move |value| Message::ObjectUpdated(key, value))
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
} else {
|
};
|
||||||
let base = text_input("Object", value.clone());
|
|
||||||
if state.read_only {
|
|
||||||
base.into()
|
|
||||||
} else {
|
|
||||||
base.on_input(move |value| Message::ObjectUpdated(key, value))
|
|
||||||
.into()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let selected_datatype = term
|
let selected_datatype = term
|
||||||
.datatype()
|
.datatype()
|
||||||
@@ -1032,16 +1189,21 @@ impl Publisher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn view(&self, window: window::Id) -> Element<'_, Message> {
|
pub(crate) fn view(&self, window: window::Id) -> Element<'_, Message> {
|
||||||
if let Some(search_state) = &self.search_state &&
|
if let Some(search_state) = &self.search_state
|
||||||
search_state.window_id == window {
|
&& search_state.window_id == window
|
||||||
|
{
|
||||||
return self.view_search_window(search_state);
|
return self.view_search_window(search_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(inference_window_id) = self.inference_window_id && window == inference_window_id {
|
if let Some(inference_window_id) = self.inference_window_id
|
||||||
|
&& window == inference_window_id
|
||||||
|
{
|
||||||
return self.view_inference_window();
|
return self.view_inference_window();
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(read_only_window_id) = self.read_only_window_id && window == read_only_window_id {
|
if let Some(read_only_window_id) = self.read_only_window_id
|
||||||
|
&& window == read_only_window_id
|
||||||
|
{
|
||||||
return self.view_read_only_window();
|
return self.view_read_only_window();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1060,8 +1222,8 @@ impl Publisher {
|
|||||||
!self.url_input_valid,
|
!self.url_input_valid,
|
||||||
));
|
));
|
||||||
|
|
||||||
let mut rows: Vec<Element<Message>> = vec![];
|
let rows: Vec<Element<Message>> = self
|
||||||
rows = self.document
|
.document
|
||||||
.dataset()
|
.dataset()
|
||||||
.iter_both()
|
.iter_both()
|
||||||
.filter(|(_, _, state)| !state.read_only)
|
.filter(|(_, _, state)| !state.read_only)
|
||||||
@@ -1069,24 +1231,31 @@ impl Publisher {
|
|||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let body: Element<Message> = if self.show_new_document_buttons {
|
let body: Element<Message> = if self.show_new_document_buttons {
|
||||||
let buttons = Class::CREATABLE.iter()
|
let buttons = Class::CREATABLE.iter().map(|class| {
|
||||||
.map(|class| {
|
let url = if self.resource_not_found {
|
||||||
let url = if self.resource_not_found {
|
Url::parse(&self.url_input).ok()
|
||||||
Url::parse(&self.url_input).ok()
|
} else {
|
||||||
} else { None };
|
None
|
||||||
|
};
|
||||||
|
|
||||||
button(text(class.to_string()))
|
button(text(class.to_string()))
|
||||||
.on_press(Message::NewDocument(class.clone(), url))
|
.on_press(Message::NewDocument(class.clone(), url))
|
||||||
.into()
|
.into()
|
||||||
});
|
});
|
||||||
|
|
||||||
column![
|
column![grid(buttons).height(Sizing::EvenlyDistribute(Length::Shrink))].into()
|
||||||
grid(buttons).height(Sizing::EvenlyDistribute(Length::Shrink))
|
|
||||||
].into()
|
|
||||||
} else {
|
} else {
|
||||||
column(rows).into()
|
column(rows).into()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let download_button_base = button("\u{2b73}");
|
||||||
|
let download_button =
|
||||||
|
if self.document.origin_type() == Some(&ldp::ResourceType::NonRdfSource) {
|
||||||
|
download_button_base.on_press(Message::DownloadResource)
|
||||||
|
} else {
|
||||||
|
download_button_base
|
||||||
|
};
|
||||||
|
|
||||||
let save_button_base = button(text("\u{1f4be}"));
|
let save_button_base = button(text("\u{1f4be}"));
|
||||||
let save_button = if self.modified {
|
let save_button = if self.modified {
|
||||||
save_button_base.on_press(Message::SaveGraph(false))
|
save_button_base.on_press(Message::SaveGraph(false))
|
||||||
@@ -1103,6 +1272,7 @@ impl Publisher {
|
|||||||
back_button,
|
back_button,
|
||||||
forward_button,
|
forward_button,
|
||||||
address_input,
|
address_input,
|
||||||
|
download_button,
|
||||||
save_button,
|
save_button,
|
||||||
],
|
],
|
||||||
scrollable(body),
|
scrollable(body),
|
||||||
@@ -1157,4 +1327,4 @@ where
|
|||||||
)
|
)
|
||||||
]
|
]
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -22,7 +22,7 @@ pub(crate) struct SearchArgs {
|
|||||||
pub(crate) discriminant: Option<u64>,
|
pub(crate) discriminant: Option<u64>,
|
||||||
|
|
||||||
#[arg(short, long, value_name = "LIMIT")]
|
#[arg(short, long, value_name = "LIMIT")]
|
||||||
pub(crate) limit: Option<usize>,
|
pub(crate) limit: Option<usize>,
|
||||||
|
|
||||||
#[arg(value_name = "QUERY")]
|
#[arg(value_name = "QUERY")]
|
||||||
pub(crate) query: String,
|
pub(crate) query: String,
|
||||||
|
|||||||
@@ -42,10 +42,16 @@ pub(crate) enum Error {
|
|||||||
|
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
TonicTransport(#[from] tonic::transport::Error),
|
TonicTransport(#[from] tonic::transport::Error),
|
||||||
|
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
TonicStatus(#[from] tonic::Status),
|
TonicStatus(#[from] tonic::Status),
|
||||||
|
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Tantivy(#[from] gl_search::tantivy::TantivyError),
|
Tantivy(#[from] gl_search::tantivy::TantivyError),
|
||||||
}
|
|
||||||
|
#[error(transparent)]
|
||||||
|
Reqwest(#[from] ldp::reqwest::Error),
|
||||||
|
|
||||||
|
#[error(transparent)]
|
||||||
|
Ldp(#[from] ldp::Error),
|
||||||
|
}
|
||||||
|
|||||||
+57
-30
@@ -3,32 +3,32 @@ mod args;
|
|||||||
mod error;
|
mod error;
|
||||||
mod navigator;
|
mod navigator;
|
||||||
mod rdf;
|
mod rdf;
|
||||||
|
mod tasks;
|
||||||
mod theme;
|
mod theme;
|
||||||
mod widget;
|
mod widget;
|
||||||
mod tasks;
|
|
||||||
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use crate::app::Publisher;
|
use crate::app::Publisher;
|
||||||
use crate::args::{AppArgs, Command};
|
use crate::args::{AppArgs, Command};
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
use gl_graph::indexer::Indexer;
|
||||||
|
use gl_graph::ontology::{OntologyBuilder, ResourceSelector};
|
||||||
|
use gl_graph::{CurieHelper, language, vocab};
|
||||||
|
use gl_inference::proto::OntologyQueryRequest;
|
||||||
|
use gl_inference::proto::ontology_client::OntologyClient;
|
||||||
use gl_search::{Schema, SearchIndex};
|
use gl_search::{Schema, SearchIndex};
|
||||||
use iced::futures::StreamExt;
|
use iced::futures::StreamExt;
|
||||||
|
use ldp::Traverse;
|
||||||
use ldp::middleware::BasicAuthMiddleware;
|
use ldp::middleware::BasicAuthMiddleware;
|
||||||
use ldp::reqwest::Client;
|
use ldp::reqwest::Client;
|
||||||
use ldp::reqwest_middleware::ClientBuilder;
|
use ldp::reqwest_middleware::ClientBuilder;
|
||||||
use ldp::traverse::Traverse;
|
|
||||||
use oxigraph::model::{Graph, TripleRef};
|
use oxigraph::model::{Graph, TripleRef};
|
||||||
use tracing::{debug_span, error, field, Instrument};
|
use std::collections::HashMap;
|
||||||
|
use tracing::{Instrument, debug_span, error, field};
|
||||||
use tracing_subscriber::fmt::format::FmtSpan;
|
use tracing_subscriber::fmt::format::FmtSpan;
|
||||||
use tracing_subscriber::layer::SubscriberExt;
|
use tracing_subscriber::layer::SubscriberExt;
|
||||||
use tracing_subscriber::util::SubscriberInitExt;
|
use tracing_subscriber::util::SubscriberInitExt;
|
||||||
use tracing_subscriber::{EnvFilter, fmt};
|
use tracing_subscriber::{EnvFilter, fmt};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
use gl_graph::indexer::Indexer;
|
|
||||||
use gl_graph::{language, CurieHelper, vocab};
|
|
||||||
use gl_graph::ontology::{OntologyBuilder, ResourceSelector};
|
|
||||||
use gl_inference::proto::ontology_client::OntologyClient;
|
|
||||||
use gl_inference::proto::OntologyQueryRequest;
|
|
||||||
|
|
||||||
fn main() -> color_eyre::Result<()> {
|
fn main() -> color_eyre::Result<()> {
|
||||||
let appender = tracing_appender::rolling::never("/tmp", "publisher-log");
|
let appender = tracing_appender::rolling::never("/tmp", "publisher-log");
|
||||||
@@ -47,16 +47,24 @@ fn main() -> color_eyre::Result<()> {
|
|||||||
Some(Command::Query(args)) => {
|
Some(Command::Query(args)) => {
|
||||||
let raw_query = if let Some(query) = &args.query_path {
|
let raw_query = if let Some(query) = &args.query_path {
|
||||||
Some(String::from_utf8(std::fs::read(query)?)?)
|
Some(String::from_utf8(std::fs::read(query)?)?)
|
||||||
} else { None };
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
let graph = if let Some(dataset_path) = &args.dataset_path {
|
let graph = if let Some(dataset_path) = &args.dataset_path {
|
||||||
Some(String::from_utf8(std::fs::read(dataset_path)?)?)
|
Some(String::from_utf8(std::fs::read(dataset_path)?)?)
|
||||||
} else { None };
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
let request = OntologyQueryRequest {
|
let request = OntologyQueryRequest {
|
||||||
sparql_query: raw_query,
|
sparql_query: raw_query,
|
||||||
turtle: graph,
|
turtle: graph,
|
||||||
prefixes: HashMap::from_iter(gl_graph::PREFIXES.iter().map( | (name, iri) | (name.clone(), iri.clone()))),
|
prefixes: HashMap::from_iter(
|
||||||
|
gl_graph::PREFIXES
|
||||||
|
.iter()
|
||||||
|
.map(|(name, iri)| (name.clone(), iri.clone())),
|
||||||
|
),
|
||||||
base: args.base.clone(),
|
base: args.base.clone(),
|
||||||
inferences_only: args.inferences_only,
|
inferences_only: args.inferences_only,
|
||||||
};
|
};
|
||||||
@@ -83,7 +91,9 @@ fn main() -> color_eyre::Result<()> {
|
|||||||
.expect("Failed to build search index");
|
.expect("Failed to build search index");
|
||||||
|
|
||||||
let limit = args.limit.unwrap_or(5);
|
let limit = args.limit.unwrap_or(5);
|
||||||
for document in index.query(args.discriminant, &args.query, Schema::all_fields(), limit)? {
|
for document in
|
||||||
|
index.query(args.discriminant, &args.query, Schema::all_fields(), limit)?
|
||||||
|
{
|
||||||
println!("{}", gl_search::to_json(document));
|
println!("{}", gl_search::to_json(document));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -108,14 +118,22 @@ fn main() -> color_eyre::Result<()> {
|
|||||||
let curie_helper = CurieHelper::new(gl_graph::PREFIXES.clone());
|
let curie_helper = CurieHelper::new(gl_graph::PREFIXES.clone());
|
||||||
let indexer = Indexer::new(language::ENGLISH_OR_UNTAGGED.clone(), &curie_helper);
|
let indexer = Indexer::new(language::ENGLISH_OR_UNTAGGED.clone(), &curie_helper);
|
||||||
|
|
||||||
let mut client = OntologyBuilder::from_string("http://[::1]:3000", language::ENGLISH_OR_UNTAGGED.clone())?
|
let mut client = OntologyBuilder::from_string(
|
||||||
.connect()
|
"http://[::1]:3000",
|
||||||
|
language::ENGLISH_OR_UNTAGGED.clone(),
|
||||||
|
)?
|
||||||
|
.connect()
|
||||||
|
.await?;
|
||||||
|
let resource_descriptions = client
|
||||||
|
.resource_descriptions(
|
||||||
|
ResourceSelector::Classes,
|
||||||
|
[
|
||||||
|
vocab::rdf::PROPERTY.into_owned(),
|
||||||
|
vocab::rdfs::CLASS.into_owned(),
|
||||||
|
vocab::skos::CONCEPT.into_owned(),
|
||||||
|
],
|
||||||
|
)
|
||||||
.await?;
|
.await?;
|
||||||
let resource_descriptions = client.resource_descriptions(ResourceSelector::Classes, [
|
|
||||||
vocab::rdf::PROPERTY.into_owned(),
|
|
||||||
vocab::rdfs::CLASS.into_owned(),
|
|
||||||
vocab::skos::CONCEPT.into_owned(),
|
|
||||||
]).await?;
|
|
||||||
let documents = indexer.ontology(resource_descriptions);
|
let documents = indexer.ontology(resource_descriptions);
|
||||||
debug_span!("Index Ontology", documents = field::Empty).in_scope(|| {
|
debug_span!("Index Ontology", documents = field::Empty).in_scope(|| {
|
||||||
for document in documents {
|
for document in documents {
|
||||||
@@ -140,24 +158,31 @@ fn main() -> color_eyre::Result<()> {
|
|||||||
while let Some(result) = traversal.next().await {
|
while let Some(result) = traversal.next().await {
|
||||||
match result {
|
match result {
|
||||||
Ok(rdf_source) => {
|
Ok(rdf_source) => {
|
||||||
let triples = rdf_source.dataset()
|
let triples = rdf_source.dataset().iter().map(TripleRef::from);
|
||||||
.iter()
|
|
||||||
.map(TripleRef::from);
|
|
||||||
graph.extend(triples);
|
graph.extend(triples);
|
||||||
rdf_source_count += 1;
|
rdf_source_count += 1;
|
||||||
},
|
}
|
||||||
Err(err) => error!(?err),
|
Err(err) => error!(?err),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let span = debug_span!("Index Repository", rdf_sources = rdf_source_count, triples = field::Empty, documents = field::Empty);
|
let span = debug_span!(
|
||||||
|
"Index Repository",
|
||||||
|
rdf_sources = rdf_source_count,
|
||||||
|
triples = field::Empty,
|
||||||
|
documents = field::Empty
|
||||||
|
);
|
||||||
let triple_count = async {
|
let triple_count = async {
|
||||||
let curie_helper = CurieHelper::new(gl_graph::PREFIXES.clone());
|
let curie_helper = CurieHelper::new(gl_graph::PREFIXES.clone());
|
||||||
let indexer = Indexer::new(language::ENGLISH_OR_UNTAGGED.clone(), &curie_helper);
|
let indexer =
|
||||||
|
Indexer::new(language::ENGLISH_OR_UNTAGGED.clone(), &curie_helper);
|
||||||
|
|
||||||
let mut client = OntologyBuilder::from_string("http://[::1]:3000", language::ENGLISH_OR_UNTAGGED.clone())?
|
let mut client = OntologyBuilder::from_string(
|
||||||
.connect()
|
"http://[::1]:3000",
|
||||||
.await?;
|
language::ENGLISH_OR_UNTAGGED.clone(),
|
||||||
|
)?
|
||||||
|
.connect()
|
||||||
|
.await?;
|
||||||
|
|
||||||
let graph_with_inferences = client.run_inference(&graph).await?;
|
let graph_with_inferences = client.run_inference(&graph).await?;
|
||||||
for document in indexer.graph(&graph_with_inferences) {
|
for document in indexer.graph(&graph_with_inferences) {
|
||||||
@@ -165,7 +190,9 @@ fn main() -> color_eyre::Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Ok::<usize, crate::error::Error>(graph_with_inferences.len())
|
Ok::<usize, crate::error::Error>(graph_with_inferences.len())
|
||||||
}.instrument(span.clone()).await?;
|
}
|
||||||
|
.instrument(span.clone())
|
||||||
|
.await?;
|
||||||
span.record("triples", triple_count);
|
span.record("triples", triple_count);
|
||||||
|
|
||||||
Ok::<_, crate::error::Error>(writer)
|
Ok::<_, crate::error::Error>(writer)
|
||||||
|
|||||||
@@ -33,4 +33,4 @@ impl<T> Navigator<T> {
|
|||||||
}
|
}
|
||||||
self.current()
|
self.current()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+66
-38
@@ -1,57 +1,73 @@
|
|||||||
use iced::Task;
|
use crate::app::Message;
|
||||||
use ldp::reqwest_middleware::ClientWithMiddleware;
|
|
||||||
use ldp::ResourceRequestBuilder;
|
|
||||||
use oxigraph::io::RdfFormat;
|
|
||||||
use oxigraph::model::{Dataset, Graph, NamedNode, NamedNodeRef, NamedOrBlankNodeRef, TermRef};
|
|
||||||
use url::Url;
|
|
||||||
use gl_graph::class::Class;
|
use gl_graph::class::Class;
|
||||||
use gl_graph::ontology::{ConnectedOntology, OntologyBuilder, ResourceSelector};
|
use gl_graph::ontology::{ConnectedOntology, OntologyBuilder, ResourceSelector};
|
||||||
use gl_graph::vocab;
|
use gl_graph::vocab;
|
||||||
use crate::app::Message;
|
use iced::Task;
|
||||||
|
use ldp::ResourceRequestBuilder;
|
||||||
|
use ldp::reqwest_middleware::ClientWithMiddleware;
|
||||||
|
use oxigraph::io::RdfFormat;
|
||||||
|
use oxigraph::model::{Dataset, Graph, NamedNode, NamedNodeRef, NamedOrBlankNodeRef, TermRef};
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
pub(crate) fn connect_to_ontology_service(builder: OntologyBuilder) -> Task<Message> {
|
pub(crate) fn connect_to_ontology_service(builder: OntologyBuilder) -> Task<Message> {
|
||||||
Task::perform(builder.connect(), |result| {
|
Task::perform(builder.connect(), |result| match result {
|
||||||
match result {
|
Ok(ontology) => Message::ConnectedToOntologyService(ontology),
|
||||||
Ok(ontology) => Message::ConnectedToOntologyService(ontology),
|
Err(err) => Message::ShowError(err.to_string()),
|
||||||
Err(err) => Message::ShowError(err.to_string())
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn lookup_resource_descriptions(mut ontology: ConnectedOntology, subjects: impl IntoIterator<Item = NamedNode> + Send + 'static) -> Task<Message> {
|
pub(crate) fn lookup_resource_descriptions(
|
||||||
Task::perform(async move { ontology.resource_descriptions(ResourceSelector::Subjects, subjects).await }, |result| {
|
mut ontology: ConnectedOntology,
|
||||||
match result {
|
subjects: impl IntoIterator<Item = NamedNode> + Send + 'static,
|
||||||
|
) -> Task<Message> {
|
||||||
|
Task::perform(
|
||||||
|
async move {
|
||||||
|
ontology
|
||||||
|
.resource_descriptions(ResourceSelector::Subjects, subjects)
|
||||||
|
.await
|
||||||
|
},
|
||||||
|
|result| match result {
|
||||||
Ok(descriptions) => Message::CacheResourceDescriptions(descriptions),
|
Ok(descriptions) => Message::CacheResourceDescriptions(descriptions),
|
||||||
Err(err) => Message::ShowError(err.to_string()),
|
Err(err) => Message::ShowError(err.to_string()),
|
||||||
}
|
},
|
||||||
})
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn list_datatypes(mut ontology: ConnectedOntology) -> Task<Message> {
|
pub(crate) fn list_datatypes(mut ontology: ConnectedOntology) -> Task<Message> {
|
||||||
Task::perform(async move { ontology.resource_descriptions(ResourceSelector::Classes, vec![vocab::rdfs::DATATYPE.into_owned()]).await }, |result| {
|
Task::perform(
|
||||||
match result {
|
async move {
|
||||||
|
ontology
|
||||||
|
.resource_descriptions(
|
||||||
|
ResourceSelector::Classes,
|
||||||
|
vec![vocab::rdfs::DATATYPE.into_owned()],
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
},
|
||||||
|
|result| match result {
|
||||||
Ok(datatypes) => Message::CacheDatatypes(datatypes),
|
Ok(datatypes) => Message::CacheDatatypes(datatypes),
|
||||||
Err(err) => Message::ShowError(err.to_string()),
|
Err(err) => Message::ShowError(err.to_string()),
|
||||||
}
|
},
|
||||||
})
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn list_read_only_entities(mut ontology: ConnectedOntology) -> Task<Message> {
|
pub(crate) fn list_read_only_entities(mut ontology: ConnectedOntology) -> Task<Message> {
|
||||||
Task::perform(async move { ontology.list_read_only().await }, |result| {
|
Task::perform(
|
||||||
match result {
|
async move { ontology.list_read_only().await },
|
||||||
|
|result| match result {
|
||||||
Ok(entities) => Message::CacheReadOnlyEntities(entities),
|
Ok(entities) => Message::CacheReadOnlyEntities(entities),
|
||||||
Err(err) => Message::ShowError(err.to_string()),
|
Err(err) => Message::ShowError(err.to_string()),
|
||||||
}
|
},
|
||||||
})
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn run_inference(mut ontology: ConnectedOntology, graph: Graph) -> Task<Message> {
|
pub(crate) fn run_inference(mut ontology: ConnectedOntology, graph: Graph) -> Task<Message> {
|
||||||
Task::perform(async move { ontology.run_inference(&graph).await }, |result| {
|
Task::perform(
|
||||||
match result {
|
async move { ontology.run_inference(&graph).await },
|
||||||
|
|result| match result {
|
||||||
Ok(inferences) => Message::SetInferredTriples(inferences),
|
Ok(inferences) => Message::SetInferredTriples(inferences),
|
||||||
Err(err) => Message::ShowError(err.to_string()),
|
Err(err) => Message::ShowError(err.to_string()),
|
||||||
}
|
},
|
||||||
})
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn navigate_to_next_url(client: ClientWithMiddleware, class: Class) -> Task<Message> {
|
pub(crate) fn navigate_to_next_url(client: ClientWithMiddleware, class: Class) -> Task<Message> {
|
||||||
@@ -66,20 +82,32 @@ pub(crate) fn navigate_to_next_url(client: ClientWithMiddleware, class: Class) -
|
|||||||
Ok(resource) => match resource.into_rdf_source::<Dataset>().await {
|
Ok(resource) => match resource.into_rdf_source::<Dataset>().await {
|
||||||
Ok(document) => {
|
Ok(document) => {
|
||||||
let node = NamedNodeRef::new_unchecked(lookup_url.as_str());
|
let node = NamedNodeRef::new_unchecked(lookup_url.as_str());
|
||||||
let result = document.dataset()
|
let result = document
|
||||||
.quads_for_pattern(Some(NamedOrBlankNodeRef::NamedNode(node)), Some(vocab::glo::NEXT_URL), None, None)
|
.dataset()
|
||||||
|
.quads_for_pattern(
|
||||||
|
Some(NamedOrBlankNodeRef::NamedNode(node)),
|
||||||
|
Some(vocab::glo::NEXT_URL),
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
)
|
||||||
.next();
|
.next();
|
||||||
if let Some(next_url_quad) = result {
|
if let Some(next_url_quad) = result {
|
||||||
if let TermRef::NamedNode(next_url) = next_url_quad.object {
|
if let TermRef::NamedNode(next_url) = next_url_quad.object {
|
||||||
let url = Url::parse(next_url.as_str()).unwrap();
|
let url = Url::parse(next_url.as_str()).unwrap();
|
||||||
Message::NewDocument(class, Some(url))
|
Message::NewDocument(class, Some(url))
|
||||||
} else { Message::None }
|
} else {
|
||||||
} else { Message::None }
|
Message::None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Message::None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => Message::None
|
_ => Message::None,
|
||||||
}
|
},
|
||||||
_ => Message::None
|
_ => Message::None,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} else { Task::none() }
|
} else {
|
||||||
}
|
Task::none()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -214,7 +214,8 @@ where
|
|||||||
state.shift = modifiers.shift();
|
state.shift = modifiers.shift();
|
||||||
}
|
}
|
||||||
Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left))
|
Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left))
|
||||||
if cursor.is_over(layout.bounds()) => {
|
if cursor.is_over(layout.bounds()) =>
|
||||||
|
{
|
||||||
if state.control
|
if state.control
|
||||||
&& let Some(on_control_click) = &self.on_control_click
|
&& let Some(on_control_click) = &self.on_control_click
|
||||||
{
|
{
|
||||||
@@ -244,8 +245,9 @@ where
|
|||||||
);
|
);
|
||||||
|
|
||||||
let clipboard = shell.clipboard_mut();
|
let clipboard = shell.clipboard_mut();
|
||||||
if let Some(Content::Text(content)) = &clipboard.write &&
|
if let Some(Content::Text(content)) = &clipboard.write
|
||||||
let Some(expanded) = self.curie_helper.expand(self.base, content) {
|
&& let Some(expanded) = self.curie_helper.expand(self.base, content)
|
||||||
|
{
|
||||||
clipboard.write = Some(Content::Text(expanded));
|
clipboard.write = Some(Content::Text(expanded));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -99,4 +99,4 @@ impl SearchIndex {
|
|||||||
|
|
||||||
pub fn to_json(document: HashMap<Field, OwnedValue>) -> String {
|
pub fn to_json(document: HashMap<Field, OwnedValue>) -> String {
|
||||||
document.to_json(Schema::schema())
|
document.to_json(Schema::schema())
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -9,4 +9,4 @@ pub use tantivy::schema::document::OwnedValue;
|
|||||||
|
|
||||||
pub use error::{Result, SearchError};
|
pub use error::{Result, SearchError};
|
||||||
pub use index::{SearchIndex, SearchIndexBuilder, to_json};
|
pub use index::{SearchIndex, SearchIndexBuilder, to_json};
|
||||||
pub use schema::Schema;
|
pub use schema::Schema;
|
||||||
|
|||||||
@@ -76,4 +76,4 @@ impl Schema {
|
|||||||
pub fn all_fields() -> Vec<Field> {
|
pub fn all_fields() -> Vec<Field> {
|
||||||
Self::schema().fields().map(|(field, _)| field).collect()
|
Self::schema().fields().map(|(field, _)| field).collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,4 +20,4 @@ pub fn bytes_to_documents(data: &[u8]) -> crate::Result<Vec<SearchDocument>> {
|
|||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
Ok(documents)
|
Ok(documents)
|
||||||
}*/
|
}*/
|
||||||
|
|||||||
Reference in New Issue
Block a user