{-|
Module      : Data.RDF.Encode.NQuads
Description : Representation and Incremental Processing of RDF Data
Copyright   : Travis Whitaker 2016
License     : MIT
Maintainer  : pi.boy.travis@gmail.com
Stability   : Provisional
Portability : Portable

An encoder for
<https://www.w3.org/TR/2014/REC-n-quads-20140225/ RDF 1.1 N-Quads>.
'B.Builder's are used to support efficient incremental output.
-}

{-# LANGUAGE OverloadedStrings #-}

module Data.RDF.Encoder.NQuads (
    -- * Graph Encoding
    encodeRDFGraph
  , encodeRDFGraphs
  , encodeTriple
  , encodeQuad
  ) where

import qualified Data.ByteString.Builder as B

import Data.RDF.Types
import Data.RDF.Encoder.Common

-- | Encodes a 'Triple' as a single line, i.e. with no graph label. Includes the
--   terminating period and newline.
encodeTriple :: Triple -> B.Builder
encodeTriple :: Triple -> Builder
encodeTriple (Triple Subject
s Predicate
p Object
o) = Subject -> Builder
encodeSubject Subject
s
                           forall a. Semigroup a => a -> a -> a
<> ByteString -> Builder
B.byteString ByteString
" "
                           forall a. Semigroup a => a -> a -> a
<> Predicate -> Builder
encodePredicate Predicate
p
                           forall a. Semigroup a => a -> a -> a
<> ByteString -> Builder
B.byteString ByteString
" "
                           forall a. Semigroup a => a -> a -> a
<> Object -> Builder
encodeObject Object
o
                           forall a. Semigroup a => a -> a -> a
<> ByteString -> Builder
B.byteString ByteString
" .\n"

-- | Encodes a 'Quad' as a single line. Includes the terminating period and
--   newline.
encodeQuad :: Quad -> B.Builder
encodeQuad :: Quad -> Builder
encodeQuad (Quad Triple
t Maybe IRI
Nothing)               = Triple -> Builder
encodeTriple Triple
t
encodeQuad (Quad (Triple Subject
s Predicate
p Object
o) (Just IRI
g)) = Subject -> Builder
encodeSubject Subject
s
                                         forall a. Semigroup a => a -> a -> a
<> ByteString -> Builder
B.byteString ByteString
" "
                                         forall a. Semigroup a => a -> a -> a
<> Predicate -> Builder
encodePredicate Predicate
p
                                         forall a. Semigroup a => a -> a -> a
<> ByteString -> Builder
B.byteString ByteString
" "
                                         forall a. Semigroup a => a -> a -> a
<> Object -> Builder
encodeObject Object
o
                                         forall a. Semigroup a => a -> a -> a
<> ByteString -> Builder
B.byteString ByteString
" "
                                         forall a. Semigroup a => a -> a -> a
<> IRI -> Builder
encodeEscapedIRI IRI
g
                                         forall a. Semigroup a => a -> a -> a
<> ByteString -> Builder
B.byteString ByteString
" .\n"

-- | Encode a single 'RDFGraph' as a 'B.Builder'.
encodeRDFGraph :: RDFGraph -> B.Builder
encodeRDFGraph :: RDFGraph -> Builder
encodeRDFGraph (RDFGraph Maybe IRI
Nothing [Triple]
ts)  = forall a. Monoid a => [a] -> a
mconcat forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map Triple -> Builder
encodeTriple [Triple]
ts
encodeRDFGraph (RDFGraph (Just IRI
g) [Triple]
ts) = let qs :: [Quad]
qs = forall a b. (a -> b) -> [a] -> [b]
map (\Triple
t -> Triple -> Maybe IRI -> Quad
Quad Triple
t (forall a. a -> Maybe a
Just IRI
g)) [Triple]
ts
                                        in forall a. Monoid a => [a] -> a
mconcat forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map Quad -> Builder
encodeQuad [Quad]
qs

-- | Encode multiple 'RDFGraph's as a 'B.Builder'.
encodeRDFGraphs :: Foldable f => f RDFGraph -> B.Builder
encodeRDFGraphs :: forall (f :: * -> *). Foldable f => f RDFGraph -> Builder
encodeRDFGraphs = forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap RDFGraph -> Builder
encodeRDFGraph