+ Nothing
+
+-- | Perform query and return error string or parsed domain object
+queryNmcDom ::
+ (String -> IO (Either String ByteString)) -- ^ query operation action
+ -> String -- ^ key
+ -> IO (Either String NmcDom) -- ^ error string or domain
+queryNmcDom queryOp key = do
+ l <- queryOp key
+ case l of
+ Left estr -> return $ Left estr
+ Right str -> case decode str :: Maybe NmcDom of
+ Nothing -> return $ Left $ "Unparseable value: " ++ (show str)
+ Just dom -> return $ Right dom
+
+-- | Try to fetch "import" object and merge it into the base domain
+-- Original "import" element is removed, but new imports from the
+-- imported objects are processed recursively until there are none.
+mergeImport ::
+ (String -> IO (Either String ByteString)) -- ^ query operation action
+ -> Int -- ^ recursion counter
+ -> NmcDom -- ^ base domain
+ -> IO (Either String NmcDom) -- ^ result with merged import
+mergeImport queryOp depth base = do
+ let
+ mbase = mergeSelf base
+ base' = mbase {domImport = Nothing}
+ -- print base
+ if depth <= 0 then return $ Left "Nesting of imports is too deep"
+ else case domImport mbase of
+ Nothing -> return $ Right base'
+ Just key -> do
+ sub <- queryNmcDom queryOp key
+ case sub of
+ Left e -> return $ Left e
+ Right sub' -> mergeImport queryOp (depth - 1) $ sub' `merge` base'
+
+-- | If there is an element in the map with key "", merge the contents
+-- and remove this element. Do this recursively.
+mergeSelf :: NmcDom -> NmcDom
+mergeSelf base =
+ let
+ map = domMap base
+ base' = base {domMap = removeSelf map}
+ removeSelf Nothing = Nothing
+ removeSelf (Just map) = if size map' == 0 then Nothing else Just map'
+ where map' = M.delete "" map
+ in
+ case map of
+ Nothing -> base'
+ Just map' ->
+ case M.lookup "" map' of
+ Nothing -> base'
+ Just sub -> (mergeSelf sub) `merge` base'
+ -- recursion depth limited by the size of the record