diff options
author | Volpeon <github@volpeon.ink> | 2023-06-24 10:32:18 +0200 |
---|---|---|
committer | Volpeon <github@volpeon.ink> | 2023-06-24 10:32:18 +0200 |
commit | 2479f89067408b8b9dc79abf09bbe6b1d3c0647d (patch) | |
tree | 6ca1262fe02bc89ac522b228565021e773e29b87 | |
parent | WIP: Compaction (diff) | |
download | hs-jsonld-2479f89067408b8b9dc79abf09bbe6b1d3c0647d.tar.gz hs-jsonld-2479f89067408b8b9dc79abf09bbe6b1d3c0647d.tar.bz2 hs-jsonld-2479f89067408b8b9dc79abf09bbe6b1d3c0647d.zip |
WIP: IRI compaction
-rw-r--r-- | src/Data/JLD/Compaction/IRI.hs | 118 | ||||
-rw-r--r-- | src/Data/JLD/Compaction/InverseContext.hs | 22 | ||||
-rw-r--r-- | src/Data/JLD/Model/InverseContext.hs | 30 |
3 files changed, 123 insertions, 47 deletions
diff --git a/src/Data/JLD/Compaction/IRI.hs b/src/Data/JLD/Compaction/IRI.hs index 34379d2..208643f 100644 --- a/src/Data/JLD/Compaction/IRI.hs +++ b/src/Data/JLD/Compaction/IRI.hs | |||
@@ -5,31 +5,33 @@ import Data.JLD.Prelude | |||
5 | import Data.JLD (JLDError (InvalidKeywordValue), JLDVersion (JLD1_0)) | 5 | import Data.JLD (JLDError (InvalidKeywordValue), JLDVersion (JLD1_0)) |
6 | import Data.JLD.Compaction.Global (JLDCompactionEnv (jldCompactionEnvProcessingMode), JLDCompactionT) | 6 | import Data.JLD.Compaction.Global (JLDCompactionEnv (jldCompactionEnvProcessingMode), JLDCompactionT) |
7 | import Data.JLD.Compaction.InverseContext (buildInverseContext) | 7 | import Data.JLD.Compaction.InverseContext (buildInverseContext) |
8 | import Data.JLD.Control.Monad.RES (REST, evalREST, runREST, withEnvRES, withStateRES) | 8 | import Data.JLD.Control.Monad.RES (REST, evalREST, withEnvRES, withErrorRES, withErrorRES') |
9 | import Data.JLD.Model.ActiveContext (ActiveContext (..)) | 9 | import Data.JLD.Model.ActiveContext (ActiveContext (..)) |
10 | import Data.JLD.Model.InverseContext (InverseContext) | 10 | import Data.JLD.Model.InverseContext (InverseContext, selectTerm) |
11 | 11 | ||
12 | import Control.Monad.Except (MonadError (..)) | 12 | import Control.Monad.Except (MonadError (..)) |
13 | import Data.Aeson (Value (..)) | 13 | import Data.Aeson (Value (..)) |
14 | import Data.Aeson.KeyMap qualified as KM (lookup, member, size) | 14 | import Data.Aeson.KeyMap qualified as KM (lookup, member, size) |
15 | import Data.JLD.Model.Direction (Direction (..)) | 15 | import Data.JLD.Model.GraphObject (isGraphObject', isNotGraphObject') |
16 | import Data.JLD.Model.GraphObject (isGraphObject', isNotGraphObject, isNotGraphObject') | ||
17 | import Data.JLD.Model.Keyword (Keyword (..)) | 16 | import Data.JLD.Model.Keyword (Keyword (..)) |
18 | import Data.JLD.Model.Language (Language (..)) | 17 | import Data.JLD.Model.Language (Language (..)) |
19 | import Data.JLD.Model.ListObject (isListObject') | 18 | import Data.JLD.Model.ListObject (isListObject') |
19 | import Data.JLD.Model.TermDefinition (TermDefinition (termDefinitionIriMapping)) | ||
20 | import Data.JLD.Model.ValueObject (isValueObject') | 20 | import Data.JLD.Model.ValueObject (isValueObject') |
21 | import Data.JLD.Util (valueToArray) | 21 | import Data.JLD.Util (valueToArray) |
22 | import Data.Set qualified as S | 22 | import Data.Map qualified as M (lookup) |
23 | import Data.Set qualified as S (insert) | ||
23 | import Data.Text (toLower) | 24 | import Data.Text (toLower) |
24 | import Data.Text qualified as T (drop, findIndex, isPrefixOf, take) | 25 | import Data.Text qualified as T (drop, findIndex) |
25 | import Data.Vector (Vector, (!?)) | 26 | import Data.Vector (Vector, (!?)) |
26 | import Data.Vector qualified as V (cons, snoc) | 27 | import Data.Vector qualified as V (cons) |
27 | 28 | ||
28 | type CIT e m = REST CIEnv (JLDError e) CIState m | 29 | type CIT e m = REST CIEnv (Either (JLDError e) Text) CIState m |
29 | 30 | ||
30 | data CIEnv = CIEnv | 31 | data CIEnv = CIEnv |
31 | { ciEnvGlobal :: JLDCompactionEnv | 32 | { ciEnvGlobal :: JLDCompactionEnv |
32 | , ciEnvActiveContext :: ActiveContext | 33 | , ciEnvActiveContext :: ActiveContext |
34 | , ciEnvInverseContext :: InverseContext | ||
33 | , ciEnvValue :: Maybe Value | 35 | , ciEnvValue :: Maybe Value |
34 | , ciEnvVocab :: Bool | 36 | , ciEnvVocab :: Bool |
35 | , ciEnvReverse :: Bool | 37 | , ciEnvReverse :: Bool |
@@ -45,7 +47,7 @@ data CIState = CIState | |||
45 | deriving (Show, Eq) | 47 | deriving (Show, Eq) |
46 | 48 | ||
47 | data CIParams = CIParams | 49 | data CIParams = CIParams |
48 | { ciParamsActiveContext :: ActiveContext | 50 | { ciParamsInverseContext :: Maybe InverseContext |
49 | , ciParamsValue :: Maybe Value | 51 | , ciParamsValue :: Maybe Value |
50 | , ciParamsVocab :: Bool | 52 | , ciParamsVocab :: Bool |
51 | , ciParamsReverse :: Bool | 53 | , ciParamsReverse :: Bool |
@@ -64,8 +66,22 @@ ciPutTypeLanguage v = modify \s -> s{ciStateTypeLanguage = v} | |||
64 | ciPutTypeLanguageValue :: Monad m => Text -> CIT e m () | 66 | ciPutTypeLanguageValue :: Monad m => Text -> CIT e m () |
65 | ciPutTypeLanguageValue v = modify \s -> s{ciStateTypeLanguageValue = v} | 67 | ciPutTypeLanguageValue v = modify \s -> s{ciStateTypeLanguageValue = v} |
66 | 68 | ||
67 | compactIri4 :: Monad m => InverseContext -> Text -> CIT e m (Maybe Text) | 69 | ciCompactIri :: Monad m => Text -> CIT e m Text |
68 | compactIri4 inverseContext var = do | 70 | ciCompactIri var = do |
71 | CIEnv{..} <- ask | ||
72 | let params p = | ||
73 | p | ||
74 | { ciParamsInverseContext = Just ciEnvInverseContext | ||
75 | , ciParamsVocab = True | ||
76 | } | ||
77 | (var', _) <- | ||
78 | compactIri ciEnvActiveContext var params | ||
79 | |> withEnvRES (const ciEnvGlobal) | ||
80 | .> withErrorRES Left | ||
81 | pure var' | ||
82 | |||
83 | compactIri' :: Monad m => Text -> CIT e m Text | ||
84 | compactIri' var = do | ||
69 | CIEnv{..} <- ask | 85 | CIEnv{..} <- ask |
70 | let ActiveContext{..} = ciEnvActiveContext | 86 | let ActiveContext{..} = ciEnvActiveContext |
71 | 87 | ||
@@ -284,41 +300,74 @@ compactIri4 inverseContext var = do | |||
284 | Just (Object o) | 300 | Just (Object o) |
285 | | typeLanguageValue == show KeywordReverse || typeLanguageValue == show KeywordId | 301 | | typeLanguageValue == show KeywordReverse || typeLanguageValue == show KeywordId |
286 | , Just idValue <- KM.lookup (show KeywordId) o -> case idValue of | 302 | , Just idValue <- KM.lookup (show KeywordId) o -> case idValue of |
287 | String idValue' -> pure () | 303 | -- 4.16.1. |
288 | _ -> throwError <| InvalidKeywordValue KeywordId idValue | 304 | String idValue' -> do |
289 | -- | 305 | compactedIdValue <- ciCompactIri idValue' |
290 | _ -> pure () | 306 | case M.lookup compactedIdValue activeContextTerms of |
307 | Just term | ||
308 | | termDefinitionIriMapping term == Just idValue' -> | ||
309 | ciModifyPreferredValues | ||
310 | <| V.cons (show KeywordVocab) | ||
311 | .> V.cons (show KeywordId) | ||
312 | -- 4.16.2. | ||
313 | _ -> | ||
314 | ciModifyPreferredValues | ||
315 | <| V.cons (show KeywordId) | ||
316 | .> V.cons (show KeywordVocab) | ||
317 | ciModifyPreferredValues <| V.cons (show KeywordNone) | ||
318 | -- | ||
319 | _ -> throwError <. Left <| InvalidKeywordValue KeywordId idValue | ||
320 | -- 4.17. | ||
321 | | Just (Array a) <- KM.lookup (show KeywordList) o | ||
322 | , null a -> do | ||
323 | ciModifyPreferredValues | ||
324 | <| V.cons typeLanguageValue | ||
325 | .> V.cons (show KeywordNone) | ||
326 | ciPutTypeLanguage KeywordAny | ||
327 | _ -> do | ||
328 | ciModifyPreferredValues | ||
329 | <| V.cons typeLanguageValue | ||
330 | .> V.cons (show KeywordNone) | ||
331 | |||
332 | -- 4.18. | ||
333 | ciModifyPreferredValues <| V.cons (show KeywordAny) | ||
334 | |||
335 | -- 4.19. | ||
336 | gets ciStatePreferredValues >>= mapM_ \preferredValue -> case T.findIndex (== ':') preferredValue of | ||
337 | Just idx -> ciModifyPreferredValues <| V.cons (T.drop idx preferredValue) | ||
338 | Nothing -> pure () | ||
339 | |||
340 | -- 4.20. | ||
341 | maybeTerm <- | ||
342 | liftA3 | ||
343 | (\containers typeLanguage preferredValues -> selectTerm var containers typeLanguage preferredValues ciEnvInverseContext) | ||
344 | (gets ciStateContainers) | ||
345 | (gets ciStateTypeLanguage) | ||
346 | (gets ciStatePreferredValues) | ||
347 | |||
348 | -- 4.21. | ||
349 | case maybeTerm of | ||
350 | Just term -> throwError <| Right term | ||
351 | Nothing -> pure () | ||
291 | 352 | ||
292 | -- | 353 | -- |
293 | pure Nothing | 354 | pure var |
294 | |||
295 | compactIri' :: Monad m => Text -> CIT e m (Text, InverseContext) | ||
296 | compactIri' var = do | ||
297 | CIEnv{..} <- ask | ||
298 | |||
299 | -- 2. 3. | ||
300 | let inverseContext = case activeContextInverseContext ciEnvActiveContext of | ||
301 | Nothing -> buildInverseContext ciEnvActiveContext | ||
302 | Just ic -> ic | ||
303 | |||
304 | compactIri4 inverseContext var >>= \case | ||
305 | Just var' -> pure (var', inverseContext) | ||
306 | Nothing -> pure (var, inverseContext) | ||
307 | 355 | ||
308 | compactIri :: Monad m => ActiveContext -> Text -> (CIParams -> CIParams) -> JLDCompactionT e m (Text, InverseContext) | 356 | compactIri :: Monad m => ActiveContext -> Text -> (CIParams -> CIParams) -> JLDCompactionT e m (Text, InverseContext) |
309 | compactIri activeContext var paramsFn = do | 357 | compactIri activeContext var paramsFn = do |
310 | envGlobal <- ask | 358 | env' <- asks env |
311 | result <- | 359 | result <- |
312 | compactIri' var | 360 | compactIri' var |
313 | |> evalREST (env envGlobal) st | 361 | |> withErrorRES' (either throwError pure) |
362 | .> evalREST env' st | ||
314 | case result of | 363 | case result of |
315 | Left err -> throwError err | 364 | Left err -> throwError err |
316 | Right res -> pure res | 365 | Right res -> pure (res, ciEnvInverseContext env') |
317 | where | 366 | where |
318 | CIParams{..} = | 367 | CIParams{..} = |
319 | paramsFn | 368 | paramsFn |
320 | CIParams | 369 | CIParams |
321 | { ciParamsActiveContext = activeContext | 370 | { ciParamsInverseContext = Nothing |
322 | , ciParamsValue = Nothing | 371 | , ciParamsValue = Nothing |
323 | , ciParamsVocab = False | 372 | , ciParamsVocab = False |
324 | , ciParamsReverse = False | 373 | , ciParamsReverse = False |
@@ -327,7 +376,8 @@ compactIri activeContext var paramsFn = do | |||
327 | env global = | 376 | env global = |
328 | CIEnv | 377 | CIEnv |
329 | { ciEnvGlobal = global | 378 | { ciEnvGlobal = global |
330 | , ciEnvActiveContext = ciParamsActiveContext | 379 | , ciEnvActiveContext = activeContext |
380 | , ciEnvInverseContext = fromMaybe (buildInverseContext activeContext) ciParamsInverseContext | ||
331 | , ciEnvValue = ciParamsValue | 381 | , ciEnvValue = ciParamsValue |
332 | , ciEnvVocab = ciParamsVocab | 382 | , ciEnvVocab = ciParamsVocab |
333 | , ciEnvReverse = ciParamsReverse | 383 | , ciEnvReverse = ciParamsReverse |
diff --git a/src/Data/JLD/Compaction/InverseContext.hs b/src/Data/JLD/Compaction/InverseContext.hs index b351e34..03a45f2 100644 --- a/src/Data/JLD/Compaction/InverseContext.hs +++ b/src/Data/JLD/Compaction/InverseContext.hs | |||
@@ -4,32 +4,32 @@ import Data.JLD.Prelude | |||
4 | 4 | ||
5 | import Data.JLD.Model.ActiveContext (ActiveContext (..)) | 5 | import Data.JLD.Model.ActiveContext (ActiveContext (..)) |
6 | import Data.JLD.Model.Direction (Direction (..)) | 6 | import Data.JLD.Model.Direction (Direction (..)) |
7 | import Data.JLD.Model.InverseContext (InverseContext) | 7 | import Data.JLD.Model.InverseContext (InverseContext, insert) |
8 | import Data.JLD.Model.Keyword (Keyword (..)) | 8 | import Data.JLD.Model.Keyword (Keyword (..)) |
9 | import Data.JLD.Model.Language (Language (Language)) | 9 | import Data.JLD.Model.Language (Language (Language)) |
10 | import Data.JLD.Model.TermDefinition (TermDefinition (..)) | 10 | import Data.JLD.Model.TermDefinition (TermDefinition (..)) |
11 | 11 | ||
12 | import Data.Map qualified as M | 12 | import Data.Map qualified as M (foldlWithKey) |
13 | 13 | ||
14 | processTerm :: Text -> InverseContext -> Text -> TermDefinition -> InverseContext | 14 | processTerm :: Text -> InverseContext -> Text -> TermDefinition -> InverseContext |
15 | processTerm defaultLangDir out termName TermDefinition{..} | 15 | processTerm defaultLangDir out termName TermDefinition{..} |
16 | | Just variableName <- termDefinitionIriMapping = | 16 | | Just variableName <- termDefinitionIriMapping = |
17 | out | 17 | out |
18 | |> M.insert (variableName, container, show KeywordAny, show KeywordNone) termName | 18 | |> insert variableName container KeywordAny (show KeywordNone) termName |
19 | .> if | 19 | .> if |
20 | | termDefinitionReversePropertyFlag -> | 20 | | termDefinitionReversePropertyFlag -> |
21 | M.insert (variableName, container, show KeywordType, show KeywordReverse) termName | 21 | insert variableName container KeywordType (show KeywordReverse) termName |
22 | | termDefinitionTypeMapping == Just (show KeywordNone) -> | 22 | | termDefinitionTypeMapping == Just (show KeywordNone) -> |
23 | M.insert (variableName, container, show KeywordLanguage, show KeywordAny) termName | 23 | insert variableName container KeywordLanguage (show KeywordAny) termName |
24 | .> M.insert (variableName, container, show KeywordType, show KeywordAny) termName | 24 | .> insert variableName container KeywordType (show KeywordAny) termName |
25 | | Just typeMapping <- termDefinitionTypeMapping -> | 25 | | Just typeMapping <- termDefinitionTypeMapping -> |
26 | M.insert (variableName, container, show KeywordType, typeMapping) termName | 26 | insert variableName container KeywordType typeMapping termName |
27 | | Just langDir <- maybeLangDir -> | 27 | | Just langDir <- maybeLangDir -> |
28 | M.insert (variableName, container, show KeywordLanguage, langDir) termName | 28 | insert variableName container KeywordLanguage langDir termName |
29 | | otherwise -> | 29 | | otherwise -> |
30 | M.insert (variableName, container, show KeywordLanguage, defaultLangDir) termName | 30 | insert variableName container KeywordLanguage defaultLangDir termName |
31 | .> M.insert (variableName, container, show KeywordLanguage, show KeywordNone) termName | 31 | .> insert variableName container KeywordLanguage (show KeywordNone) termName |
32 | .> M.insert (variableName, container, show KeywordType, show KeywordNone) termName | 32 | .> insert variableName container KeywordType (show KeywordNone) termName |
33 | | otherwise = out | 33 | | otherwise = out |
34 | where | 34 | where |
35 | container = if null termDefinitionContainerMapping then show KeywordNone else fold termDefinitionContainerMapping | 35 | container = if null termDefinitionContainerMapping then show KeywordNone else fold termDefinitionContainerMapping |
diff --git a/src/Data/JLD/Model/InverseContext.hs b/src/Data/JLD/Model/InverseContext.hs index fe4b516..ee85ce9 100644 --- a/src/Data/JLD/Model/InverseContext.hs +++ b/src/Data/JLD/Model/InverseContext.hs | |||
@@ -1,5 +1,31 @@ | |||
1 | module Data.JLD.Model.InverseContext (InverseContext) where | 1 | module Data.JLD.Model.InverseContext (InverseContext, hasKey3, insert, selectTerm) where |
2 | 2 | ||
3 | import Data.JLD.Prelude | 3 | import Data.JLD.Prelude |
4 | 4 | ||
5 | type InverseContext = Map (Text, Text, Text, Text) Text | 5 | import Data.JLD.Model.Keyword (Keyword) |
6 | import Data.Map qualified as M | ||
7 | import Data.Set qualified as S | ||
8 | import Data.Vector (Vector, (!?)) | ||
9 | import Data.Vector qualified as V (catMaybes) | ||
10 | |||
11 | type InverseContext = Map Text (Map Text (Map Keyword (Map Text Text))) | ||
12 | |||
13 | hasKey3 :: Text -> Text -> Keyword -> InverseContext -> Bool | ||
14 | hasKey3 var container type' inverseContext = | ||
15 | M.lookup var inverseContext >>= M.lookup container >>= M.lookup type' |> isJust | ||
16 | |||
17 | lookup4 :: Text -> Text -> Keyword -> Text -> InverseContext -> Maybe Text | ||
18 | lookup4 var container type' typeMapping inverseContext = | ||
19 | M.lookup var inverseContext >>= M.lookup container >>= M.lookup type' >>= M.lookup typeMapping | ||
20 | |||
21 | insert :: Text -> Text -> Keyword -> Text -> Text -> InverseContext -> InverseContext | ||
22 | insert var container type' typeMapping value = | ||
23 | M.alter (Just <. M.alter (Just <. M.alter (Just <. M.insert typeMapping value <. fromMaybe mempty) type' <. fromMaybe mempty) container <. fromMaybe mempty) var | ||
24 | |||
25 | selectTerm :: Text -> Set Text -> Keyword -> Vector Text -> InverseContext -> Maybe Text | ||
26 | selectTerm var containers typeLanguage preferredValues inverseContext = | ||
27 | containers | ||
28 | |> S.filter (\container -> hasKey3 var container typeLanguage inverseContext) | ||
29 | .> foldMap' (\container -> preferredValues <&> \item -> lookup4 var container typeLanguage item inverseContext) | ||
30 | .> V.catMaybes | ||
31 | .> (!? 0) | ||