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 | 114 | ||||
| -rw-r--r-- | src/Data/JLD/Compaction/InverseContext.hs | 22 | ||||
| -rw-r--r-- | src/Data/JLD/Model/InverseContext.hs | 30 |
3 files changed, 121 insertions, 45 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) | ||
| 291 | 331 | ||
| 292 | -- | 332 | -- 4.18. |
| 293 | pure Nothing | 333 | ciModifyPreferredValues <| V.cons (show KeywordAny) |
| 294 | 334 | ||
| 295 | compactIri' :: Monad m => Text -> CIT e m (Text, InverseContext) | 335 | -- 4.19. |
| 296 | compactIri' var = do | 336 | gets ciStatePreferredValues >>= mapM_ \preferredValue -> case T.findIndex (== ':') preferredValue of |
| 297 | CIEnv{..} <- ask | 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) | ||
| 298 | 347 | ||
| 299 | -- 2. 3. | 348 | -- 4.21. |
| 300 | let inverseContext = case activeContextInverseContext ciEnvActiveContext of | 349 | case maybeTerm of |
| 301 | Nothing -> buildInverseContext ciEnvActiveContext | 350 | Just term -> throwError <| Right term |
| 302 | Just ic -> ic | 351 | Nothing -> pure () |
| 303 | 352 | ||
| 304 | compactIri4 inverseContext var >>= \case | 353 | -- |
| 305 | Just var' -> pure (var', inverseContext) | 354 | pure var |
| 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) | ||
