packages feed

rdf4h 1.2.7 → 1.3.0

raw patch · 9 files changed

+160/−83 lines, 9 filesdep +ghc-primdep +networkdep ~network-uriPVP ok

version bump matches the API change (PVP)

Dependencies added: ghc-prim, network

Dependency ranges changed: network-uri

API changes (from Hackage documentation)

- Data.RDF.Query: removeDupes :: Triples -> Triples
- Data.RDF.Query: sortTriples :: Triples -> Triples
+ Data.RDF: uniqTriplesOf :: RDF rdf => rdf -> Triples
+ Data.RDF.MGraph: uniqTriplesOf :: RDF rdf => rdf -> Triples
+ Data.RDF.Query: expandNode :: PrefixMappings -> Node -> Node
+ Data.RDF.Query: expandTriple :: PrefixMappings -> Triple -> Triple
+ Data.RDF.Query: expandURI :: PrefixMappings -> Text -> Text
+ Data.RDF.TriplesGraph: uniqTriplesOf :: RDF rdf => rdf -> Triples
+ Data.RDF.Types: absolutizeUrl :: Maybe BaseUrl -> Maybe Text -> Text -> Text
+ Data.RDF.Types: isAbsoluteUri :: Text -> Bool
+ Data.RDF.Types: mkAbsoluteUrl :: Text -> Text -> Text
+ Data.RDF.Types: resolveQName :: Maybe BaseUrl -> Text -> PrefixMappings -> Maybe Text
+ Data.RDF.Types: uniqTriplesOf :: RDF rdf => rdf -> Triples

Files

rdf4h.cabal view
@@ -1,5 +1,5 @@ name:            rdf4h-version:         1.2.7+version:         1.3.0 synopsis:        A library for RDF processing in Haskell description:        'RDF for Haskell' is a library for working with RDF in Haskell.@@ -8,8 +8,8 @@   for triples  containing a particular subject, predicate, or object, or   selecting triples that satisfy an arbitrary predicate function. -author:          Calvin Smith-copyright:       (c) Calvin Smith, Rob Stewart+author:          Calvin Smith, Rob Stewart, Slava Kravchenko+copyright:       (c) Calvin Smith, Rob Stewart, Slava Kravchenko maintainer:      Rob Stewart <robstewart@gmail.com> homepage:        https://github.com/robstewart57/rdf4h bug-reports:     https://github.com/robstewart57/rdf4h/issues@@ -35,6 +35,10 @@   description: Use HPC for tests   default:     True +flag network-uri+   description: Get Network.URI from the network-uri package+   default: True+ library   exposed-modules: Data.RDF                  , Data.RDF.Namespace@@ -57,7 +61,15 @@                  , text                  , unordered-containers                  , hashable-                 , network-uri++  if impl(ghc < 7.6)+    build-depends: ghc-prim++  if flag(network-uri)+    build-depends: network-uri >= 2.6, network >= 2.6+  else+    build-depends: network-uri < 2.6, network < 2.6+   other-modules:   Text.RDF.RDF4H.ParserUtils                  , Text.RDF.RDF4H.Interact   hs-source-dirs:  src@@ -76,7 +88,15 @@                  , containers                  , text                  , hashable-                 , network-uri++  if impl(ghc < 7.6)+    build-depends: ghc-prim++  if flag(network-uri)+    build-depends: network-uri >= 2.6, network >= 2.6+  else+    build-depends: network-uri < 2.6, network < 2.6+   hs-source-dirs:  src   extensions:      BangPatterns RankNTypes ScopedTypeVariables MultiParamTypeClasses OverloadedStrings   ghc-options:     -Wall -fno-warn-unused-do-bind -funbox-strict-fields@@ -101,7 +121,15 @@                , knob                , unordered-containers                , hashable-               , network-uri++  if impl(ghc < 7.6)+    build-depends: ghc-prim++  if flag(network-uri)+    build-depends: network-uri >= 2.6, network >= 2.6+  else+    build-depends: network-uri < 2.6, network < 2.6+   other-modules: Data.RDF                , Data.RDF.Namespace                , Data.RDF.MGraph
src/Data/RDF/MGraph.hs view
@@ -1,7 +1,7 @@ {-# LANGUAGE TupleSections #-} -- |A simple graph implementation backed by 'Data.HashMap'. -module Data.RDF.MGraph(MGraph, empty, mkRdf, triplesOf, select, query)+module Data.RDF.MGraph(MGraph, empty, mkRdf, triplesOf, uniqTriplesOf, select, query)  where @@ -40,6 +40,7 @@   empty             = empty'   mkRdf             = mkRdf'   triplesOf         = triplesOf'+  uniqTriplesOf     = uniqTriplesOf'   select            = select'   query             = query' @@ -105,6 +106,10 @@ triplesOf' :: MGraph -> Triples triplesOf' (MGraph ((spoMap, _), _, _)) = concatMap (uncurry tripsSubj) subjPredMaps   where subjPredMaps = HashMap.toList spoMap++-- naive implementation for now+uniqTriplesOf' :: MGraph -> Triples+uniqTriplesOf' = nub . expandTriples  tripsSubj :: Subject -> AdjacencyMap -> Triples tripsSubj s adjMap = concatMap (uncurry (tfsp s)) (HashMap.toList adjMap)
src/Data/RDF/Namespace.hs view
@@ -12,8 +12,7 @@   -- * Predefined namespace values   rdf, rdfs, dc, dct, owl, xsd, skos, foaf, ex, ex2,   standard_ns_mappings, ns_mappings-)-where+) where  import qualified Data.Text as T import Data.RDF.Types
src/Data/RDF/Query.hs view
@@ -1,24 +1,25 @@- module Data.RDF.Query (    -- * Query functions-  sortTriples, equalSubjects, equalPredicates, equalObjects,+  equalSubjects, equalPredicates, equalObjects,   subjectOf, predicateOf, objectOf, isEmpty,-  rdfContainsNode, tripleContainsNode, removeDupes,+  rdfContainsNode, tripleContainsNode,   listSubjectsWithPredicate, listObjectsOfPredicate,    -- * RDF graph functions-  isIsomorphic, expandTriples, fromEither+  isIsomorphic, expandTriples, fromEither, +  -- * Miscellaneous functions+  expandTriple, expandNode, expandURI+ ) where  import Prelude hiding (pred) import Data.List import Data.RDF.Types---- |Answer the given list of triples in sorted order.-sortTriples :: Triples -> Triples-sortTriples = sort+import qualified Data.RDF.Namespace as NS (toPMList, uriOf, rdf)+import qualified Data.Text as T+import Data.Maybe (catMaybes)  -- |Answer the subject node of the triple. {-# INLINE subjectOf #-}@@ -43,21 +44,24 @@   in elem True xs  -- |Answer if triple contains node.+-- Note that it doesn't perform namespace expansion! tripleContainsNode :: Node -> Triple -> Bool {-# INLINE tripleContainsNode #-} tripleContainsNode node t =   subjectOf t == node || predicateOf t == node || objectOf t == node - -- |Determine whether two triples have equal subjects.+-- Note that it doesn't perform namespace expansion! equalSubjects :: Triple -> Triple -> Bool equalSubjects (Triple s1 _ _) (Triple s2 _ _) = s1 == s2  -- |Determine whether two triples have equal predicates.+-- Note that it doesn't perform namespace expansion! equalPredicates :: Triple -> Triple -> Bool equalPredicates (Triple _ p1 _) (Triple _ p2 _) = p1 == p2  -- |Determine whether two triples have equal objects.+-- Note that it doesn't perform namespace expansion! equalObjects :: Triple -> Triple -> Bool equalObjects (Triple _ _ o1) (Triple _ _ o2) = o1 == o2 @@ -91,12 +95,6 @@     (Left err) -> error (show err)     (Right rdf) -> rdf --- |Remove duplicate triples, returning unique triples. This --- function may return the triples in a different order than --- given.-removeDupes :: Triples -> Triples-removeDupes =  map head . group . sort- -- |This determines if two RDF representations are equal regardless of blank -- node names, triple order and prefixes.  In math terms, this is the \simeq -- latex operator, or ~=@@ -113,7 +111,34 @@ expandTriples' :: Triples -> Maybe BaseUrl -> PrefixMappings -> Triples -> Triples expandTriples' acc _ _ [] = acc expandTriples' acc baseURL prefixMaps (t:rest) = expandTriples' (normalize baseURL prefixMaps t : acc) baseURL prefixMaps rest-  where normalize baseURL' prefixMaps' = expandPrefixes prefixMaps' . expandBaseUrl baseURL'-        expandBaseUrl (Just _) triple' = triple'-        expandBaseUrl Nothing triple' = triple'-        expandPrefixes _ triple' = triple'+  where normalize baseURL' prefixMaps' = absolutizeTriple baseURL' . expandTriple prefixMaps'++-- |Expand the triple with the prefix map.+expandTriple :: PrefixMappings -> Triple -> Triple+expandTriple pms t = triple (expandNode pms $ subjectOf t) (expandNode pms $ predicateOf t) (expandNode pms $ objectOf t)++-- |Expand the node with the prefix map.+-- Only UNodes are expanded, other kinds of nodes are returned as-is.+expandNode :: PrefixMappings -> Node -> Node+expandNode pms (UNode n) = unode $ expandURI pms n+expandNode _ n'          = n'++-- |Expand the URI with the prefix map.+-- Also expands "a" to "http://www.w3.org/1999/02/22-rdf-syntax-ns#type".+expandURI :: PrefixMappings -> T.Text -> T.Text+expandURI _ "a"  = T.append (NS.uriOf NS.rdf) "type"+expandURI pms' x = firstExpandedOrOriginal x $ catMaybes $ map (resourceTail x) (NS.toPMList pms')+  where resourceTail :: T.Text -> (T.Text, T.Text) -> Maybe T.Text+        resourceTail x' (p', u') = T.stripPrefix (T.append p' ":") x' >>= Just . T.append u'+        firstExpandedOrOriginal :: a -> [a] -> a+        firstExpandedOrOriginal orig' [] = orig'+        firstExpandedOrOriginal _ (e:_)  = e++-- |Prefixes relative URIs in the triple with BaseUrl.+absolutizeTriple :: Maybe BaseUrl -> Triple -> Triple+absolutizeTriple base t = triple (absolutizeNode base $ subjectOf t) (absolutizeNode base $ predicateOf t) (absolutizeNode base $ objectOf t)++-- |Prepends BaseUrl to UNodes with relative URIs.+absolutizeNode :: Maybe BaseUrl -> Node -> Node+absolutizeNode (Just (BaseUrl b')) (UNode u') = unode $ mkAbsoluteUrl b' u'+absolutizeNode _ n                     = n
src/Data/RDF/TriplesGraph.hs view
@@ -8,7 +8,7 @@ -- functions of this graph (select, query) remove duplicates from their -- result triples (but triplesOf does not) since it is usually cheap -- to do so.-module Data.RDF.TriplesGraph(TriplesGraph, empty, mkRdf, triplesOf, select, query)+module Data.RDF.TriplesGraph(TriplesGraph, empty, mkRdf, triplesOf, uniqTriplesOf, select, query)  where @@ -17,6 +17,7 @@ import Data.RDF.Namespace import Data.RDF.Query import Data.RDF.Types+import Data.List (nub)  -- |A simple implementation of the 'RDF' type class that represents -- the graph internally as a list of triples.@@ -46,6 +47,7 @@   empty             = empty'   mkRdf             = mkRdf'   triplesOf         = triplesOf'+  uniqTriplesOf     = uniqTriplesOf'   select            = select'   query             = query' @@ -76,11 +78,14 @@ triplesOf' :: TriplesGraph -> Triples triplesOf' (TriplesGraph (ts, _, _)) = ts +uniqTriplesOf' :: TriplesGraph -> Triples+uniqTriplesOf' = nub . expandTriples+ select' :: TriplesGraph -> NodeSelector -> NodeSelector -> NodeSelector -> Triples-select' (TriplesGraph (ts, _, _)) s p o = removeDupes $ filter (matchSelect s p o) ts+select' g s p o = filter (matchSelect s p o) $ triplesOf g  query' :: TriplesGraph -> Maybe Subject -> Maybe Predicate -> Maybe Object -> Triples-query' (TriplesGraph (ts, _, _)) s p o = removeDupes $ filter (matchPattern s p o) ts+query' g s p o = filter (matchPattern s p o) $ triplesOf g  matchSelect :: NodeSelector -> NodeSelector -> NodeSelector -> Triple -> Bool matchSelect s p o t =
src/Data/RDF/Types.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveGeneric, OverloadedStrings #-}  module Data.RDF.Types ( @@ -14,8 +14,11 @@   -- * Node query function   isUNode,isLNode,isBNode, +  -- * Miscellaneous+  resolveQName, absolutizeUrl, isAbsoluteUri, mkAbsoluteUrl,+   -- * RDF Type-  RDF(baseUrl,prefixMappings,addPrefixMappings,empty,mkRdf,triplesOf,select,query),+  RDF(baseUrl,prefixMappings,addPrefixMappings,empty,mkRdf,triplesOf,uniqTriplesOf,select,query),    -- * Parsing RDF   RdfParser(parseString,parseFile,parseURL),@@ -41,6 +44,7 @@ import Data.Hashable(Hashable) import qualified Data.List as List import qualified Data.Map as Map+import qualified Network.URI as Network (isURI)  ------------------- -- LValue and constructor functions@@ -86,7 +90,7 @@ -- node ('BNode'), or a literal node ('LNode'). data Node = -  -- |An RDF URI reference. See+  -- |An RDF URI reference. URIs conform to the RFC3986 standard. See   -- <http://www.w3.org/TR/rdf-concepts/#section-Graph-URIref> for more   -- information.   UNode !T.Text@@ -172,6 +176,10 @@ isLNode (LNode _) = True isLNode _         = False +{-# INLINE isAbsoluteUri #-}+isAbsoluteUri :: T.Text -> Bool+isAbsoluteUri = Network.isURI . T.unpack+ -- |A type class for ADTs that expose views to clients. class View a b where   view :: a -> b@@ -206,8 +214,16 @@   mkRdf :: Triples -> Maybe BaseUrl -> PrefixMappings -> rdf    -- |Return all triples in the RDF, as a list.+  --+  -- Note that this function returns a list of triples in the RDF as they+  -- were added, without removing duplicates and without expanding namespaces.   triplesOf :: rdf -> Triples +  -- |Return unique triples in the RDF, as a list.+  --+  -- This function performs namespace expansion and removal of duplicates.+  uniqTriplesOf :: rdf -> Triples+   -- |Select the triples in the RDF that match the given selectors.   --   -- The three NodeSelector parameters are optional functions that match@@ -479,6 +495,42 @@   deriving (Eq, Ord) instance Show PrefixMapping where   show (PrefixMapping (prefix, uri)) = printf "PrefixMapping (%s, %s)" (show prefix) (show uri)++-----------------+-- Miscellaneous helper functions used throughout the project++-- Resolve a prefix using the given prefix mappings and base URL. If the prefix is+-- empty, then the base URL will be used if there is a base URL and if the map+-- does not contain an entry for the empty prefix.+resolveQName :: Maybe BaseUrl -> T.Text -> PrefixMappings -> Maybe T.Text+resolveQName mbaseUrl prefix (PrefixMappings pms') =+  case (mbaseUrl, T.null prefix) of+    (Just (BaseUrl base), True)  ->  Just $ Map.findWithDefault base T.empty pms'+    (Nothing,             True)  ->  Nothing+    (_,                   _   )  ->  Map.lookup prefix pms'++-- Resolve a URL fragment found on the right side of a prefix mapping+-- by converting it to an absolute URL if possible.+absolutizeUrl :: Maybe BaseUrl -> Maybe T.Text -> T.Text -> T.Text+absolutizeUrl mbUrl mdUrl urlFrag =+  if isAbsoluteUri urlFrag then urlFrag else+    (case (mbUrl, mdUrl) of+         (Nothing, Nothing) -> urlFrag+         (Just (BaseUrl bUrl), Nothing) -> bUrl `T.append` urlFrag+         (Nothing, Just dUrl) -> if isHash urlFrag then+                                     dUrl `T.append` urlFrag else urlFrag+         (Just (BaseUrl bUrl), Just dUrl) -> (if isHash urlFrag then dUrl+                                                  else bUrl)+                                                 `T.append` urlFrag)+  where+    isHash bs' = bs' == "#"++{-# INLINE mkAbsoluteUrl #-}+-- Make an absolute URL by returning as is if already an absolute URL and otherwise+-- appending the URL to the given base URL.+mkAbsoluteUrl :: T.Text -> T.Text -> T.Text+mkAbsoluteUrl base url =+  if isAbsoluteUri url then url else base `T.append` url   -----------------
src/Text/RDF/RDF4H/ParserUtils.hs view
@@ -6,7 +6,7 @@  import Network.URI import Network.HTTP-import Data.Char(intToDigit)+import Data.Char (intToDigit) import Data.Text.Encoding (decodeUtf8) import qualified Data.ByteString.Char8 as B import qualified Data.Text as T@@ -23,8 +23,8 @@ justTriples = map (fromMaybe (error "ParserUtils.justTriples")) .               filter (/= Nothing) --- | pars contents at URL in to and 'RDF'-_parseURL :: RDF rdf => (T.Text -> Either ParseFailure rdf)  -> String -> IO (Either ParseFailure rdf)+-- | Parse contents at URL into an 'RDF'.+_parseURL :: RDF rdf => (T.Text -> Either ParseFailure rdf) -> String -> IO (Either ParseFailure rdf) _parseURL parseFunc url =   maybe     (return (Left (ParseFailure $ "Unable to parse URL: " ++ url)))@@ -41,7 +41,7 @@                            (2, 0, 0) -> return $ parseFunc (decodeUtf8 (rspBody res))                            _         -> return (errResult $ "couldn't retrieve from URL: " ++ httpError res) --- | construct HTTP GET request.+-- | Construct HTTP GET request. request :: URI -> HTTPRequest B.ByteString request uri = Request { rqURI = uri,                         rqMethod = GET,
src/Text/RDF/RDF4H/TurtleParser.hs view
@@ -107,7 +107,9 @@      char ':'      name <- option T.empty t_name      (bUrl, _, _, pms, _, _, _, _) <- getState-     return $ resolveQName bUrl pre pms `T.append` name+     case resolveQName bUrl pre pms of+       Just n -> return $ n `T.append` name+       Nothing -> error ("Cannot resolve QName prefix: " ++ T.unpack pre)  t_subject :: GenParser ParseState () t_subject =@@ -398,48 +400,9 @@ in_range :: Char -> [(Char, Char)] -> Bool in_range c = any (\(c1, c2) -> c >= c1 && c <= c2) --- Resolve a prefix using the given prefix mappings and base URL. If the prefix is--- empty, then the base URL will be used if there is a base URL and if the map--- does not contain an entry for the empty prefix.-resolveQName :: Maybe BaseUrl -> T.Text -> PrefixMappings -> T.Text-resolveQName mbaseUrl prefix (PrefixMappings pms') =-  case (mbaseUrl, T.null prefix) of-    (Just (BaseUrl base), True)  ->  Map.findWithDefault base T.empty pms'-    (Nothing,             True)  ->  err1-    (_,                   _   )  ->  Map.findWithDefault err2 prefix pms'-  where-    err1 = error  "Cannot resolve empty QName prefix to a Base URL."-    err2 = error ("Cannot resolve QName prefix: " ++ T.unpack prefix)---- Resolve a URL fragment found on the right side of a prefix mapping by converting it to an absolute URL if possible.-absolutizeUrl :: Maybe BaseUrl -> Maybe T.Text -> T.Text -> T.Text-absolutizeUrl mbUrl mdUrl urlFrag =-  if isAbsoluteUri urlFrag then urlFrag else-    (case (mbUrl, mdUrl) of-         (Nothing, Nothing) -> urlFrag-         (Just (BaseUrl bUrl), Nothing) -> bUrl `T.append` urlFrag-         (Nothing, Just dUrl) -> if isHash urlFrag then-                                     dUrl `T.append` urlFrag else urlFrag-         (Just (BaseUrl bUrl), Just dUrl) -> (if isHash urlFrag then dUrl-                                                  else bUrl)-                                                 `T.append` urlFrag)-  where-    isHash bs' = T.length bs' == 1 && T.head bs' == '#'--{-# INLINE isAbsoluteUri #-}-isAbsoluteUri :: T.Text -> Bool-isAbsoluteUri = T.isInfixOf (T.pack [':'])- newBaseUrl :: Maybe BaseUrl -> T.Text -> BaseUrl-newBaseUrl Nothing                url = BaseUrl url+newBaseUrl Nothing               url = BaseUrl url newBaseUrl (Just (BaseUrl bUrl)) url = BaseUrl $! mkAbsoluteUrl bUrl url--{-# INLINE mkAbsoluteUrl #-}--- Make an absolute URL by returning as is if already an absolute URL and otherwise--- appending the URL to the given base URL.-mkAbsoluteUrl :: T.Text -> T.Text -> T.Text-mkAbsoluteUrl base url =-  if isAbsoluteUri url then url else base `T.append` url  currBaseUrl :: GenParser ParseState (Maybe BaseUrl) currBaseUrl = getState >>= \(bUrl, _, _, _, _, _, _, _) -> return bUrl
testsuite/tests/Test.hs view
@@ -6,11 +6,11 @@ import qualified Data.RDF.MGraph_Test as MGraph import qualified Text.RDF.RDF4H.XmlParser_Test as XmlParser import qualified Text.RDF.RDF4H.TurtleParser_ConformanceTest as TurtleParser+import Data.RDF.GraphTestUtils -main :: IO () -main = defaultMain (  TriplesGraph.tests-                   ++ MGraph.tests+main :: IO ()+main = defaultMain (  graphTests "TriplesGraph" TriplesGraph.triplesOf' TriplesGraph.uniqTriplesOf' TriplesGraph.empty' TriplesGraph.mkRdf'+                   ++ graphTests "MGraph" MGraph.triplesOf' MGraph.uniqTriplesOf' MGraph.empty' MGraph.mkRdf'                    ++ TurtleParser.tests                    ++ XmlParser.tests                    )-