packages feed

hxt-7.1: doc/cookbook/SPARQLFunctions.hs

{- |
   Module     : SPARQLFunctions 
   Author     : Manuel Ohlendorf  

   Maintainer : Manuel Ohlendorf
   Stability  : experimental
   Portability: portable
   Version    :

Several functions used for query processing.
-}
module SPARQLFunctions
    (
    normalizeQuery
    ,showResult
    ,getSPARQLQuery
    )
where

import SPARQLDataTypes
import RDFDataTypes
import SPARQLParser
import Text.ParserCombinators.Parsec (parse)
import Text.XML.HXT.Arrow

-- | normalises the Triple Patterns
normalizeTripleP :: TriplePattern -> [TriplePattern]
normalizeTripleP (TriplePatN s p o ) = [TriplePatN s p o]
normalizeTripleP (TriplePat _ [])          = []
normalizeTripleP (TriplePat _ ((_,[]):_)) = []
normalizeTripleP (TriplePat s ((p,[o]):xs)) =  (TriplePatN s p o) : normalizeTripleP(TriplePat s xs)
normalizeTripleP (TriplePat s ((p,(x:xs)):ys)) = (TriplePatN s p x) : normalizeTripleP (TriplePat s [(p,xs)]) 
                                                ++ normalizeTripleP (TriplePat s ys)

-- | normalises the Pattern elements
normalizePatternElement :: PatternElement -> [TriplePattern]
normalizePatternElement (PET t) = normalizeTripleP t
normalizePatternElement (PEG []) = []
normalizePatternElement (PEG (x:xs)) = normalizePatternElement x ++ normalizePatternElement' xs
                                        
normalizePatternElement' :: [PatternElement] -> [TriplePattern]
normalizePatternElement' [] = []
normalizePatternElement' (x:xs) = normalizePatternElement x  ++ normalizePatternElement' xs

-- | normalises the graph patterns
normalizeGraphPattern :: GraphPattern -> [TriplePattern]
normalizeGraphPattern (GraphPattern []) = []
normalizeGraphPattern (GraphPattern (x:xs)) = normalizePatternElement x ++ normalizePatternElement' xs 

-- | normalises a 'Query' by removing all abbreviations. 
-- The result is a 'Query' containing a list of simple triple patterns.
-- This function has to be called be for query evaluation.
normalizeQuery :: Query -> Query
normalizeQuery Empty = Empty
normalizeQuery (QueryN _ [])  = Empty
normalizeQuery (QueryN v (x:xs)) = QueryN v (x:xs)
normalizeQuery (Query v gp) = QueryN v (normalizeGraphPattern gp)

showIt :: [(Either RDFTerm URI)] -> String
showIt [] = ""
showIt ((Right u) :xs) = '|' : "<" ++ u ++">|\n" ++ showIt xs
showIt ((Left r) :xs)  = '|' : show r ++"|\n" ++ showIt xs

-- | The show function for printing out the result of the query evaluation
showResult :: [(Var,[(Either RDFTerm URI)])] -> String
showResult [] = ""
showResult ((var, xs):ys) 
    = if (xs /=[]) 
      then '\t' : '?':var ++ "\n" ++ (showIt xs) ++"\n"++ (showResult ys) 
      else ""


-- | The main entry point, when combining the SPARQL parser with a arrow based programme.
-- Executes the SPARQL parser and returns a 'Query'.
--
-- Raises an error if the parsing fails and returns a empty 'Query'.
--
-- The extra parameter is the query string which will be parsed.
-- The arrow input is ignored, the output is the parsed query.
getSPARQLQuery :: String -> IOSArrow a Query 
getSPARQLQuery queryStr
    = case (parse parseSPARQL "" queryStr) of
      Left parseError
       -> (issueFatal ("Syntax error in SPARQL query " 
                        ++ show queryStr 
                        ++ ": " ++ show parseError) >>> constA (Empty))
      Right theQuery
       -> constA (theQuery)