{-# LANGUAGE DeriveDataTypeable #-} {- Copyright (C) 2018 Dr. Alistair Ward This file is part of BishBosh. BishBosh is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. BishBosh is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with BishBosh. If not, see . -} {- | [@AUTHOR@] Dr. Alistair Ward [@DESCRIPTION@] * Exceptions customised for this application. * N.B.: IO-functions can merely forward any exceptions thrown by the underlying calls, so these exceptions are typically thrown from pure functions. * CAVEAT: though intended to be orthogonal, there's some inevitable overlap. -} module BishBosh.Data.Exception( -- * Types -- ** Data-types BadData(), BadRequest(), Exception( -- MkException, getType -- getDetails ), -- * Functions -- ** Constructors mkDuplicateData, mkIncompatibleData, mkInsufficientData, mkInvalidDatum, mkNullDatum, mkOutOfBounds, mkRedundantData, mkParseFailure, mkRequestFailure, mkResultUndefined, mkSearchFailure, -- ** Predicates isBadData, isBadRequest ) where import qualified Control.Exception import qualified Data.Typeable -- | These types of exception may be thrown by any function which checks its parameters; typically either constructors or mutators. data BadData = DuplicateData -- ^ Some data is duplicated. | IncompatibleData -- ^ Two or more data with valid values, are incompatible. cf. InvalidDatum. | InsufficientData -- ^ More data is required to fulfill the request. cf. 'NullDatum'. | InvalidDatum -- ^ A datum's value is invalid. | NullDatum -- ^ An empty collection was unexpectedly received; a specialisation of either 'InsufficientData' or 'InvalidDatum'. | OutOfBounds -- ^ Either underflow or overflow of numeric data; a specialisation of 'InvalidDatum'. | RedundantData -- ^ Data superflous to requirements was provided; a specialisation of 'InvalidDatum'. deriving Show -- | These types of exception may be thrown by any function which is unable to comply with a correctly formed request. data BadRequest = ParseFailure -- ^ An attempt to parse data failed. | RequestFailure -- ^ A well-formed request couldn't be completed. | ResultUndefined -- ^ More than one correct result is possible. | SearchFailure -- ^ An attempt to find data failed. deriving Show -- | Each type of exception includes a type & a details. data Exception = MkException { getType :: Either BadData BadRequest, getDetails :: String } deriving Data.Typeable.Typeable instance Control.Exception.Exception Exception instance Show Exception where showsPrec _ MkException { getType = eitherBadDataOrBadRequest, getDetails = details } = either shows shows eitherBadDataOrBadRequest . showString "; " . showString details -- | Constructor. mkDuplicateData :: String -> Exception mkDuplicateData = MkException $ Left DuplicateData -- | Constructor. mkIncompatibleData :: String -> Exception mkIncompatibleData = MkException $ Left IncompatibleData -- | Constructor. mkInsufficientData :: String -> Exception mkInsufficientData = MkException $ Left InsufficientData -- | Constructor. mkInvalidDatum :: String -> Exception mkInvalidDatum = MkException $ Left InvalidDatum -- | Constructor. mkNullDatum :: String -> Exception mkNullDatum = MkException $ Left NullDatum -- | Constructor. mkOutOfBounds :: String -> Exception mkOutOfBounds = MkException $ Left OutOfBounds -- | Constructor. mkRedundantData :: String -> Exception mkRedundantData = MkException $ Left RedundantData -- | Constructor. mkParseFailure :: String -> Exception mkParseFailure = MkException $ Right ParseFailure -- | Constructor. mkRequestFailure :: String -> Exception mkRequestFailure = MkException $ Right RequestFailure -- | Constructor. mkResultUndefined :: String -> Exception mkResultUndefined = MkException $ Right ResultUndefined -- | Constructor. mkSearchFailure :: String -> Exception mkSearchFailure = MkException $ Right SearchFailure -- | Predicate. isBadData :: Exception -> Bool isBadData MkException { getType = Left _ } = True isBadData _ = False -- | Predicate. isBadRequest :: Exception -> Bool isBadRequest MkException { getType = Right _ } = True isBadRequest _ = False