packages feed

multifocal-0.0.1: src/UI/LensMenu.hs

-----------------------------------------------------------------------------
-- |
-- Module      :  UI.LensMenu
-- Copyright   :  (c) 2011 University of Minho
-- License     :  BSD3
--
-- Maintainer  :  hpacheco@di.uminho.pt
-- Stability   :  experimental
-- Portability :  non-portable
--
-- Multifocal:
-- Bidirectional Two-level Transformation of XML Schemas
-- 
-- Menu functions for generated lens executables.
--
-----------------------------------------------------------------------------

module UI.LensMenu where

import Data.Type
import Data.Spine
import Data.Equal
import Generics.Pointless.Lenses
import Language.XML.HaXmlAliases
import Language.XML.Type2Xml
import Language.XML.Xml2Type
import System.IO
import System.Environment
import System.Console.GetOpt
import UI.Menu

data Options = Options
	{
		  optInputSourceFile	:: Maybe FilePath
		, optInputTargetFile    :: Maybe FilePath
		, optOutputFile	        :: Maybe FilePath
		, optDirection          :: Bool
	}

startOpt :: Options
startOpt = Options
	{ optInputSourceFile	= Nothing
	, optInputTargetFile	= Nothing
	, optOutputFile		= Nothing
	, optDirection		= False
	}

options :: Opts Options
options =
   [ Option "h" ["help"]
        (NoArg (\opt -> exitHelp options))
        "Show usage info"
   , Option "s" ["source"]
        (ReqArg (\arg opt -> return opt { optInputSourceFile = Just arg }) "FILE")
        "Input XML Source File"
   , Option "t" ["target"]
        (ReqArg (\arg opt -> return opt { optInputTargetFile = Just arg }) "FILE")
        "Input XML Target File"
   , Option "o" ["output"]
        (ReqArg (\arg opt -> return opt { optOutputFile = Just arg }) "FILE")
        "Output XML File (default: stdout)"
   , Option "f" ["forward"]
        (NoArg (\opt -> return opt { optDirection = True }))
        "Run the bidirectional transformation in the forward direction (requires an source file)"
   , Option "b" ["backward"]
	(NoArg (\opt -> return opt { optDirection = False }))
	"Run the bidirectional transformation in the backward direction (requires a source file and a modified target file)"
   ]

lensmenu :: FilePath -> FilePath -> Type a -> Type b -> Lens a b -> IO ()
lensmenu srcSchema tgtSchema srcType tgtType lns = do
	argv <- getArgs
	opts <- parseOptions startOpt options argv
	if optDirection opts
		then forward opts srcSchema tgtSchema srcType tgtType lns
		else backward opts srcSchema tgtSchema srcType tgtType lns

forward :: Options -> FilePath -> FilePath -> Type a -> Type b -> Lens a b -> IO ()
forward opts srcSchema tgtSchema srcType tgtType lns = do
	putStrLn "Running forward transformation..."
	-- parse XML Source File
	s <- run "input XML source file missing" $ optInputSourceFile opts
	srcFile <- readFile s
	let srcDoc = parseXml s srcFile
	-- translate XML source into an Haskell value
	src <- run "Error translating XML source file" $ xml2value srcType srcDoc
	-- run forward transformation
	let tgt = get lns src
	-- print output XML target
	outputHandle <- maybe (return stdout) (\f -> openFile f WriteMode) (optOutputFile opts)
	tgtDoc <- run "Error printing XML target file" $ value2xml tgtSchema tgtType tgt
	hPutStrLn outputHandle $ renderXml tgtDoc
	hClose outputHandle

backward :: Options -> FilePath -> FilePath -> Type a -> Type b -> Lens a b -> IO ()
backward opts srcSchema tgtSchema srcType tgtType lns = do
	putStrLn "Running backward transformation..."
	-- parse XML Source File
	s <- run "input XML source file missing" $ optInputSourceFile opts
	srcFile <- readFile s
	let srcDoc = parseXml s srcFile
	-- translate XML source into an Haskell value
	src <- run "Error translating XML source file" $ xml2value srcType srcDoc
	-- parse XML Target File
	t <- run "input XML target file missing" $ optInputTargetFile opts
	tgtFile <- readFile t
	let tgtDoc = parseXml t tgtFile
	-- translate XML target into an Haskell value
	tgt <- run "Error translating XML target file" $ xml2value tgtType tgtDoc
	-- run backward transformation
	let src' = put lns (tgt,src)
	-- print output XML target
	outputHandle <- maybe (return stdout) (\f -> openFile f WriteMode) (optOutputFile opts)
	srcDoc' <- run "Error printing XML modified source file" $ value2xml srcSchema srcType src'
	hPutStrLn outputHandle $ renderXml srcDoc'
	hClose outputHandle