packages feed

conferer-1.0.0.0: src/Conferer/Source/PropertiesFile.hs

-- |
-- Copyright: (c) 2019 Lucas David Traverso
-- License: MPL-2.0
-- Maintainer: Lucas David Traverso <lucas6246@gmail.com>
-- Stability: stable
-- Portability: portable
--
-- Properties file source
module Conferer.Source.PropertiesFile where

import Data.Text (Text)
import Data.Function ((&))
import System.Directory (doesFileExist)
import Data.Maybe (catMaybes)
import qualified Data.Text as Text
import qualified Data.Text.IO as Text

import Conferer.Source
import Conferer.Source.Files
import qualified Conferer.Source.Null as Null
import qualified Conferer.Source.InMemory as InMemory

-- | 'Source' that uses a config file in @config/{env}.properties@ and
-- parses it as a properties file with @some.key=a value@ lines
data PropertiesFileSource =
  PropertiesFileSource
  { originalFilePath :: FilePath
  , innerSource :: Source
  } deriving (Show)

instance IsSource PropertiesFileSource where
  getKeyInSource PropertiesFileSource{..} key = do
    getKeyInSource innerSource key
  getSubkeysInSource PropertiesFileSource{..} key = do
    getSubkeysInSource innerSource key

-- | Create a 'SourceCreator' using 'getFilePathFromEnv' to get the path to file
-- and 'fromFilePath'
fromConfig :: Key -> SourceCreator
fromConfig key config = do
  filePath <- getFilePathFromEnv key "properties" config
  fromFilePath filePath

-- | Create a 'Source' reading the file and using that as a properties file, but
-- if the file doesn't exist do nothing.
fromFilePath :: FilePath -> IO Source
fromFilePath filePath = do
  fileExists <- doesFileExist filePath
  if fileExists
    then do
      fileContent <- Text.readFile filePath
      return $ fromFileContent filePath fileContent
    else
      return Null.empty

-- | Create a 'Source' using some content as a properties file
fromFileContent :: FilePath -> Text -> Source
fromFileContent originalFilePath fileContent =
  let keyValues =
        fileContent
        & Text.lines
        & fmap lineToKeyValue
        & catMaybes
      innerSource = InMemory.fromAssociations keyValues
  in Source $ PropertiesFileSource {..}

-- | Transform a line into a key/value pair (or not)
lineToKeyValue :: Text -> Maybe (Key, Text)
lineToKeyValue line =
  Text.breakOn "=" line
  & (\(rawKey, rawValue) ->
      case Text.stripPrefix "=" rawValue of
        Just value ->
          Just (fromText rawKey, value)
        Nothing ->
          Nothing
    )