{-|
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
                           Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> ByteString -> Builder
B.byteString ByteString
" "
                           Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Predicate -> Builder
encodePredicate Predicate
p
                           Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> ByteString -> Builder
B.byteString ByteString
" "
                           Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Object -> Builder
encodeObject Object
o
                           Builder -> Builder -> Builder
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
                                         Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> ByteString -> Builder
B.byteString ByteString
" "
                                         Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Predicate -> Builder
encodePredicate Predicate
p
                                         Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> ByteString -> Builder
B.byteString ByteString
" "
                                         Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Object -> Builder
encodeObject Object
o
                                         Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> ByteString -> Builder
B.byteString ByteString
" "
                                         Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> IRI -> Builder
encodeEscapedIRI IRI
g
                                         Builder -> Builder -> Builder
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)  = [Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat ([Builder] -> Builder) -> [Builder] -> Builder
forall a b. (a -> b) -> a -> b
$ (Triple -> Builder) -> [Triple] -> [Builder]
forall a b. (a -> b) -> [a] -> [b]
map Triple -> Builder
encodeTriple [Triple]
ts
encodeRDFGraph (RDFGraph (Just IRI
g) [Triple]
ts) = let qs :: [Quad]
qs = (Triple -> Quad) -> [Triple] -> [Quad]
forall a b. (a -> b) -> [a] -> [b]
map (\Triple
t -> Triple -> Maybe IRI -> Quad
Quad Triple
t (IRI -> Maybe IRI
forall a. a -> Maybe a
Just IRI
g)) [Triple]
ts
                                        in [Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat ([Builder] -> Builder) -> [Builder] -> Builder
forall a b. (a -> b) -> a -> b
$ (Quad -> Builder) -> [Quad] -> [Builder]
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 :: f RDFGraph -> Builder
encodeRDFGraphs = (RDFGraph -> Builder) -> f RDFGraph -> Builder
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap RDFGraph -> Builder
encodeRDFGraph