On Fri, Sep 20, 2013 at 3:14 PM, Spyros Trigazis <[email protected]> wrote:
> Implement readJSON functions for DCCategory, DCVersion and > DCKind in Data Collectors's Types to be parsable from a JSON > formatted file. Also, implement a utility function to > capitalize the first character of a string. > > Signed-off-by: Spyros Trigazis <[email protected]> > --- > src/Ganeti/DataCollectors/Types.hs | 24 ++++++++++++++++++------ > src/Ganeti/Utils.hs | 6 ++++++ > 2 files changed, 24 insertions(+), 6 deletions(-) > > diff --git a/src/Ganeti/DataCollectors/Types.hs > b/src/Ganeti/DataCollectors/Types.hs > index da2c793..81d8313 100644 > --- a/src/Ganeti/DataCollectors/Types.hs > +++ b/src/Ganeti/DataCollectors/Types.hs > @@ -40,23 +40,24 @@ module Ganeti.DataCollectors.Types > ) where > > import Data.Char > +import Data.Ratio > import qualified Data.Map as Map > import qualified Data.Sequence as Seq > import Text.JSON > > import Ganeti.Constants as C > import Ganeti.THH > -import Ganeti.Utils (getCurrentTime) > +import Ganeti.Utils (getCurrentTime, capitalize) > > -- | The possible classes a data collector can belong to. > data DCCategory = DCInstance | DCStorage | DCDaemon | DCHypervisor > - deriving (Show, Eq) > + deriving (Show, Eq, Read) > > -- | The JSON instance for DCCategory. > instance JSON DCCategory where > showJSON = showJSON . map toLower . drop 2 . show > - readJSON = > - error "JSON read instance not implemented for type DCCategory" > + readJSON (JSString s) = Ok (read ("DC" ++ capitalize (fromJSString s))) > + readJSON v = fail $ "Invalid JSON value " ++ show v ++ " for type > DCCategory" > Using "read" is always quite dangerous, on input which is not validated. What happens when the result of ("DC" ++ capitalize (fromJSString s))) is not a string corresponding to an actual element of DCCategory? I think the whole program will just crash throwing an exception, which is not nice. Therefore, I'm afraid you'll have to list the valid strings and fail in case you receive a string which is none of them. Otherwise, have a look at the valFromObj function, which might help you do something similar to what you are doing now (I'm not 100% sure, though, I never used it). > -- | The possible status codes of a data collector. > data DCStatusCode = DCSCOk -- ^ Everything is OK > @@ -88,7 +89,15 @@ data DCKind = DCKPerf -- ^ Performance reporting > collector > instance JSON DCKind where > showJSON DCKPerf = showJSON (0 :: Int) > showJSON DCKStatus = showJSON (1 :: Int) > - readJSON = error "JSON read instance not implemented for type DCKind" > + readJSON (JSRational _ x) = > + if denominator x /= 1 > + then fail $ "Invalid JSON value " ++ show x ++ " for type DCKind" > + else > + let x' = (fromIntegral . numerator $ x) :: Int > + in if x' == 0 then Ok DCKPerf > + else if x' == 1 then Ok DCKStatus > + else fail $ "Invalid JSON value " ++ show x' ++ " for type > DCKind" > + readJSON v = fail $ "Invalid JSON value " ++ show v ++ " for type > DCKind" > > -- | Type representing the version number of a data collector. > data DCVersion = DCVerBuiltin | DCVersion String deriving (Show, Eq) > @@ -97,7 +106,10 @@ data DCVersion = DCVerBuiltin | DCVersion String > deriving (Show, Eq) > instance JSON DCVersion where > showJSON DCVerBuiltin = showJSON C.builtinDataCollectorVersion > showJSON (DCVersion v) = showJSON v > - readJSON = error "JSON read instance not implemented for type DCVersion" > + readJSON (JSString s) = > + if fromJSString s == C.builtinDataCollectorVersion > + then Ok DCVerBuiltin else Ok . DCVersion $ fromJSString s > + readJSON v = fail $ "Invalid JSON value " ++ show v ++ " for type > DCVersion" > > -- | Type for the value field of the above map. > data CollectorData = CPULoadData (Seq.Seq (Integer, [Int])) > diff --git a/src/Ganeti/Utils.hs b/src/Ganeti/Utils.hs > index 4f67006..839794f 100644 > --- a/src/Ganeti/Utils.hs > +++ b/src/Ganeti/Utils.hs > @@ -53,6 +53,7 @@ module Ganeti.Utils > , warn > , wrap > , trim > + , capitalize > , defaultHead > , exitIfEmpty > , splitEithers > @@ -396,6 +397,11 @@ wrap maxWidth = filter (not . null) . map trim . wrap0 > trim :: String -> String > trim = reverse . dropWhile isSpace . reverse . dropWhile isSpace > > +-- | Capitalizes the first character of a string. > +capitalize :: String -> String > +capitalize [] = [] > +capitalize (x:xs) = toUpper x : xs > + > -- | A safer head version, with a default value. > defaultHead :: a -> [a] -> a > defaultHead def [] = def > -- > 1.7.10.4 > > Rest LGTM. Thanks, Michele -- Google Germany GmbH Dienerstr. 12 80331 München Registergericht und -nummer: Hamburg, HRB 86891 Sitz der Gesellschaft: Hamburg Geschäftsführer: Graham Law, Christine Elizabeth Flores
