Commit 8c402d01 authored by Michael Hanus 's avatar Michael Hanus
Browse files

Directories of ER tools restructured

parent ab90a7c0
......@@ -18,8 +18,8 @@ currycheck/CurryCheck
currydoc/CurryDoc
currytest/CurryTest
cusage/CheckUsage
erd2cdbi/ERD2CDBI
erd2curry/erd2curry
ertools/ERD2CDBI
ertools/erd2curry
genint/GenInt
importcalls/ImportCalls
optimize/bindingopt
......
------------------------------------------------------------------------------
--- This module contains the definition of data types to represent
--- entity/relationship diagrams and an I/O operation to read them
--- from a term file.
---
--- @author Michael Hanus, Marion Mueller
--- @version September 2015
------------------------------------------------------------------------------
module ERD(ERD(..),ERDName,Entity(..),EName,Entity(..),
Attribute(..),AName,Key(..),Null,Domain(..),
Relationship(..),REnd(..),RName,Role,Cardinality(..),MaxValue(..),
readERDTermFile) where
import Time
import ReadShowTerm(readUnqualifiedTerm)
--- Data type to represent entity/relationship diagrams.
data ERD = ERD ERDName [Entity] [Relationship]
type ERDName = String -- used as the name of the generated module
data Entity = Entity EName [Attribute]
type EName = String
data Attribute = Attribute AName Domain Key Null
type AName = String
data Key = NoKey
| PKey
| Unique
type Null = Bool
data Domain = IntDom (Maybe Int)
| FloatDom (Maybe Float)
| CharDom (Maybe Char)
| StringDom (Maybe String)
| BoolDom (Maybe Bool)
| DateDom (Maybe CalendarTime)
| UserDefined String (Maybe String)
| KeyDom String -- later used for foreign keys
data Relationship = Relationship RName [REnd]
type RName = String
data REnd = REnd EName Role Cardinality
type Role = String
--- Cardinality of a relationship w.r.t. some entity.
--- The cardinality is either a fixed number (e.g., (Exactly 1)
--- representing the cardinality (1,1))
--- or an interval (e.g., (Between 1 (Max 4)) representing the
--- cardinality (1,4), or (Between 0 Infinite) representing the
--- cardinality (0,n)).
data Cardinality = Exactly Int
| Between Int MaxValue
--- The upper bound of a cardinality which is either a finite number
--- or infinite.
data MaxValue = Max Int | Infinite
--- Read an ERD specification from a file containing a single ERD term.
readERDTermFile :: String -> IO ERD
readERDTermFile termfilename = do
putStrLn $ "Reading ERD term from file " ++ termfilename ++ "..."
termstring <- readFile termfilename
return (updateERDTerm (readUnqualifiedTerm ["ERD","Prelude"] termstring))
--- Transforms an ERD term possible containing old, outdated, information.
--- In particular, translate (Range ...) into (Between ...).
updateERDTerm :: ERD -> ERD
updateERDTerm (ERD name es rs) = ERD name es (map updateRel rs)
where
updateRel (Relationship r ends) = Relationship r (map updateEnd ends)
updateEnd (REnd n r c) = REnd n r (updateCard c)
updateCard (Exactly n) = Exactly n
updateCard (Between min (Max m)) =
if min<=m
then Between min (Max m)
else error ("ERD: Illegal cardinality " ++ show (Between min (Max m)))
updateCard (Between min Infinite) = Between min Infinite
{-
-- Example ERD term:
(ERD "Uni"
[Entity "Student" [Attribute "MatNum" (IntDom Nothing) PKey False,
Attribute "Name" (StringDom Nothing) NoKey False,
Attribute "Firstname" (StringDom Nothing) NoKey False,
Attribute "Email" (UserDefined "MyModule.Email" Nothing)
NoKey True],
Entity "Lecture" [Attribute "Id" (IntDom Nothing) PKey False,
Attribute "Title" (StringDom Nothing) Unique False,
Attribute "Hours" (IntDom (Just 4)) NoKey False],
Entity "Lecturer" [Attribute "Id" (IntDom Nothing) PKey False,
Attribute "Name" (StringDom Nothing) NoKey False,
Attribute "Firstname" (StringDom Nothing) NoKey False],
Entity "Group" [Attribute "Time" (StringDom Nothing) NoKey False]]
[Relationship "Teaching"
[REnd "Lecturer" "taught_by" (Exactly 1),
REnd "Lecture" "teaches" (Between 0 Infinite)],
Relationship "Participation"
[REnd "Student" "participated_by" (Between 0 Infinite),
REnd "Lecture" "participates" (Between 0 Infinite)],
Relationship "Membership"
[REnd "Student" "consists_of" (Exactly 3),
REnd "Group" "member_of" (Between 0 Infinite)]])
-}
------------------------------------------------------------------------------
--- This module contains some useful operations on the data types representing
--- entity/relationship diagrams
---
--- @author Michael Hanus
--- @version August 2007
------------------------------------------------------------------------------
module ERDGoodies(erdName,entityName,isEntityNamed,entityAttributes,
hasForeignKey,foreignKeyAttributes,
attributeName,attributeDomain,hasDefault,
isForeignKey,isNullAttribute,
cardMinimum,cardMaximum,
showERD,combineIds) where
import ERD
import List(intersperse)
import Char(isUpper)
import Maybe
--- The name of an ERD.
erdName :: ERD -> String
erdName (ERD name _ _) = name
--- The name of an entity.
entityName :: Entity -> String
entityName (Entity n _) = n
--- Is this an entity with a given name?
isEntityNamed :: String -> Entity -> Bool
isEntityNamed n e = entityName e == n
--- Has the entity an attribute with a foreign key for a given entity name?
hasForeignKey :: String -> Entity -> Bool
hasForeignKey ename (Entity _ attrs) = any isForeignKeyWithName attrs
where
isForeignKeyWithName (Attribute _ d _ _) = case d of KeyDom n -> n==ename
_ -> False
--- Returns the attributes that are a foreign key of a given entity name.
foreignKeyAttributes :: String -> [Attribute] -> [Attribute]
foreignKeyAttributes ename attrs = filter isForeignKeyWithName attrs
where
isForeignKeyWithName (Attribute _ d _ _) = case d of KeyDom n -> n==ename
_ -> False
--- Returns the names of the foreign key attributes for a given entity name.
foreignKeyAttrNames :: String -> [Attribute] -> [String]
foreignKeyAttrNames ename attrs =
map attributeName (filter isForeignKeyWithName attrs)
where
isForeignKeyWithName (Attribute _ d _ _) = case d of KeyDom n -> n==ename
_ -> False
--- The attributes of an entity
entityAttributes :: Entity -> [Attribute]
entityAttributes (Entity _ attrs) = attrs
--- The name of an attribute.
attributeName :: Attribute -> String
attributeName (Attribute name _ _ _) = name
--- The domain of an attribute.
attributeDomain :: Attribute -> Domain
attributeDomain (Attribute _ d _ _) = d
--- Has an attribute domain a default value?
hasDefault :: Domain -> Bool
hasDefault (IntDom d) = isJust d
hasDefault (FloatDom d) = isJust d
hasDefault (StringDom d) = isJust d
hasDefault (BoolDom d) = isJust d
hasDefault (DateDom d) = isJust d
hasDefault (UserDefined _ d) = isJust d
---- Is an attribute a (generated) foreign key?
isForeignKey :: Attribute -> Bool
isForeignKey (Attribute _ d _ _) = case d of KeyDom _ -> True
_ -> False
--- Has an attribute a null value?
isNullAttribute :: Attribute -> Bool
isNullAttribute (Attribute _ _ _ isnull) = isnull
--- The minimum value of a cardinality.
cardMinimum :: Cardinality -> Int
cardMinimum (Exactly i) = i
cardMinimum (Between i _) = i
--- The maximum value of a cardinality (provided that it is not infinite).
cardMaximum :: Cardinality -> Int
cardMaximum (Exactly i) = i
cardMaximum (Between _ (Max i)) = i
--- A simple pretty printer for ERDs.
showERD :: Int -> ERD -> String
showERD n (ERD en es rs) = "ERD " ++ showString en ++ lb n ++
" [" ++ concat (intersperse ("," ++ lb (n+2)) (map (showEs (n+2)) es)) ++ "]"
++ lb n ++
" [" ++ concat (intersperse ("," ++ lb (n+2)) (map (showRs (n+2)) rs)) ++ "]"
showEs n (Entity en attrs) = "Entity " ++ showString en ++ lb (n+7) ++
"[" ++ concat (intersperse ("," ++ lb (n+8)) (map showWOBrackets attrs)) ++"]"
showRs n (Relationship rn ends) =
"Relationship " ++ showString rn ++ lb (n+13) ++
"[" ++ concat (intersperse ("," ++ lb (n+14)) (map showWOBrackets ends)) ++"]"
showWOBrackets t = stripBrackets (show t)
where
stripBrackets (c:cs) = if c=='(' then reverse (tail (reverse cs)) else c:cs
showString s = "\""++s++"\""
lb n = "\n" ++ take n (repeat ' ')
--- Combines a non-empty list of identifiers into a single identifier.
--- Used in ERD transformation and code generation to create
--- names for combined objects, e.g., relationships and foreign keys.
combineIds :: [String] -> String
combineIds (name:names) = name ++ concatMap maybeAddUnderscore names
where
maybeAddUnderscore [] = "_"
maybeAddUnderscore s@(c:_) = if isUpper c then s else '_' : s
# Makefile for ERD->Curry compiler
#
# Required:
# - installed Curry System (PAKCS or KiCS2) specified by variable REPL
# - bin directory of the Curry System specified by variable BINDIR
# binaries
TOOL = $(BINDIR)/erd2curry
# Some modules required by the erd2curry implementation:
DEPS = ERD2Curry.curry CodeGeneration.curry Transformation.curry \
XML2ERD.curry ERDGoodies.curry ERD2Graph.curry \
ERD.curry $(LIBDIR)/AbstractCurry/*.curry
.PHONY: all compile install clean uninstall
all: install
compile: erd2curry
install: compile
rm -f $(TOOL)
ln -s $(CURDIR)/erd2curry $(TOOL)
clean:
$(CLEANCURRY)
rm -f erd2curry
uninstall: clean
rm -f $(TOOL)
erd2curry: $(DEPS)
# create saved state for top-level function "main":
$(REPL) $(REPL_OPTS) :load ERD2Curry :save "main \"$(CURDIR)\"" :q
mv ERD2Curry $@
......@@ -9,10 +9,10 @@
module CodeGeneration(Option,Storage(..),ConsistencyTest(..),
isSQLite,erd2code) where
import ERD
import ERDGoodies
import AbstractCurry.Types
import AbstractCurry.Build
import Database.ERD
import Database.ERDGoodies
import List
import Char
import FiniteMap
......
......@@ -12,6 +12,7 @@ import AbstractCurry.Pretty
import AbstractCurry.Build
import Char ( toLower, toUpper )
import Database.ERD
import IO
import IOExts ( connectToCommand )
import List
......@@ -21,30 +22,6 @@ import SetFunctions (selectValue, set2)
import System
import Time
-- The ERDDatatype that everything is based on
data ERD = ERD String [Entity] [Relationship]
data Entity = Entity String [Attribute]
data Attribute = Attribute String Domain Key Null
data Key = NoKey | PKey | Unique
type Null = Bool
data Domain = IntDom (Maybe Int)
| FloatDom (Maybe Float)
| CharDom (Maybe Char)
| StringDom (Maybe String)
| BoolDom (Maybe Bool)
| DateDom (Maybe ClockTime)
| KeyDom String
| UserDefined String (Maybe String)
data Relationship = Relationship String [REnd]
data REnd = REnd String String Cardinality
data Cardinality = Exactly Int
| Between Int MaxValue
data MaxValue = Max Int | Infinite
-- Takes a x_ERDT.term (An ER-Model that was translated by erd2curry)
-- and the absolute path to the database.
-- Creates a SQLite database (optional), a .curry program with all datatypes
......
......@@ -3,6 +3,8 @@ module ERD2Curry where
import AbstractCurry.Files (readCurry)
import AbstractCurry.Select (imports)
import AbstractCurry.Pretty
import Database.ERD
import Database.ERDGoodies
import Directory
import Distribution(curryCompiler)
import System(exitWith, getArgs,system)
......@@ -10,15 +12,13 @@ import Time
import XML
import XML2ERD
import ERD
import ERDGoodies
import Transformation
import CodeGeneration
import ERD2Graph
systemBanner :: String
systemBanner =
let bannerText = "ERD->Curry Compiler (Version of 21/12/15)"
let bannerText = "ERD->Curry Compiler (Version of 07/06/16)"
bannerLine = take (length bannerText) (repeat '-')
in bannerLine ++ "\n" ++ bannerText ++ "\n" ++ bannerLine
......
......@@ -8,7 +8,7 @@ import IO
import IOExts
import Char(isAlphaNum)
import List(intersperse)
import ERD
import Database.ERD
import Distribution(getRcVar)
-- Should a relation represented as an explicit node?
......
......@@ -6,29 +6,40 @@
#
#****************************************************************************
# Tool binary
TOOL = $(BINDIR)/erd2cdbi
# installation binaries
ERD2CURRY = $(BINDIR)/erd2curry
ERD2CDBI = $(BINDIR)/erd2cdbi
# Some modules required by the erd2curry tool:
DEPSERD2CURRY = ERD2Curry.curry CodeGeneration.curry Transformation.curry \
XML2ERD.curry ERD2Graph.curry \
$(ROOT)/lib/Database/ERD*.curry $(LIBDIR)/AbstractCurry/*.curry
# Some modules required by the erd2cdbi tool:
DEPS = $(ROOT)/lib/Database/CDBI/*.curry ERD2CDBI.curry
DEPSERD2CDBI = ERD2CDBI.curry $(ROOT)/lib/Database/ERD*.curry \
$(ROOT)/lib/Database/CDBI/*.curry
.PHONY: all compile install clean uninstall
all: install
compile: ERD2CDBI
compile: erd2curry ERD2CDBI
install: compile
rm -f $(TOOL)
ln -s $(CURDIR)/ERD2CDBI $(TOOL)
rm -f $(ERD2CURRY) $(ERD2CDBI)
ln -s $(CURDIR)/erd2curry $(ERD2CURRY)
ln -s $(CURDIR)/ERD2CDBI $(ERD2CDBI)
clean:
$(CLEANCURRY)
rm -f ERD2CDBI
rm -f erd2curry ERD2CDBI
uninstall: clean
rm -f $(TOOL)
rm -f $(ERD2CURRY) $(ERD2CDBI)
erd2curry: $(DEPSERD2CURRY)
$(REPL) $(REPL_OPTS) :load ERD2Curry :save "main \"$(CURDIR)\"" :q
mv ERD2Curry $@
ERD2CDBI: $(DEPS)
@echo Compiling ERD2CDBI-Tool
ERD2CDBI: $(DEPSERD2CDBI)
$(REPL) $(REPL_OPTS) :load ERD2CDBI :save :quit
ERD2Curry compiler
ER Tools for Curry
==================
This directory contains a compiler for database applications
This directory contains tools for dealing with database applications
specified by entity-relationship diagrams (ERDs) in Curry programs.
----------------------------------------------------------------------
ERD2CDBI compiler
-----------------
This tool transforms an ERD term into datatypes used in the
Database.CDBI. libraries. It also creates an information file
for the currypp SQL-Parser.
If the tool is invoked with the option -db, it creates a
corresponding sqlite database.
----------------------------------------------------------------------
ERD2Curry compiler
------------------
This is a compiler for database applications
specified by entity-relationship diagrams (ERDs) into Curry programs.
The basic ideas and details about this approach are described in
......@@ -11,7 +30,8 @@ In Proc. of the Tenth International Symposium on
Practical Aspects of Declarative Languages (PADL 2008), pp. 316-332,
Springer LNCS 4902, 2008
----------------------------------------------------------------------
Usage information:
------------------
Default use without Umbrello UML Modeller but ERD term descriptions:
......
......@@ -6,8 +6,8 @@
module Transformation(transform) where
import ERD
import ERDGoodies
import Database.ERD
import Database.ERDGoodies
---------------------------------------------------
-- The main transformation which adds
......
......@@ -4,14 +4,14 @@
module XML2ERD(convert) where
import XML
import ERD
import Read
import Char
import Database.ERD
import List
import Maybe
import Char
import Read
import ReadShowTerm
import Time
import XML
......@@ -275,7 +275,7 @@ convertDomain (Just t) (Just d) =
| elem typ bool = if dom == "true"
then BoolDom (Just True)
else BoolDom (Just False)
| elem t date = DateDom (Just (parseDate dom))
| elem t date = DateDom (Just (toClockTime (parseDate dom)))
| otherwise = UserDefined t (Just d)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment