Skip to content
Snippets Groups Projects
Commit 2a80158e authored by Christian Gutsche's avatar Christian Gutsche
Browse files

initial

parents
No related branches found
No related tags found
No related merge requests found
module context
export addContext, addRole, getContexts, getRoles, getRole, @newContext, @newRole, @context, assignRole, disassignRole, Context, Role
using Parameters
abstract type Role end
abstract type Context end
@with_kw mutable struct ContextManagement
contexts::Vector{Context} = []
roles::Dict{Context, Dict{Any, Vector{DataType}}} = Dict()
roleTypeDB::Dict{Any, Dict{Context, DataType}} = Dict()
roleDB::Dict{Any, Dict{Context, Any}} = Dict()
end
global contextManager = ContextManagement()
function getContexts()
contextManager.contexts
end
function addContext(context::T) where {T <: Context}
push!(contextManager.contexts, eval(context))
end
function addRole(context, contextualType, roleNameSymbol)
if (eval(context)) in keys(contextManager.roles)
if (eval(contextualType)) in keys(contextManager.roles[eval(context)])
push!(contextManager.roles[eval(context)][eval(contextualType)], eval(roleNameSymbol))
else
contextManager.roles[eval(context)][eval(contextualType)] = [eval(roleNameSymbol)]
end
else
contextManager.roles[eval(context)] = Dict((eval(contextualType))=>[eval(roleNameSymbol)])
end
end
function getRoles()
contextManager.roles
end
function getRoles(type)
contextManager.roleDB[type]
end
function getRole(type, context::T) where {T <: Context}
(contextManager.roleDB[type])[context]
end
macro newContext(contextName)
if typeof(contextName) == String || typeof(contextName) == Symbol
if typeof(contextName) == Symbol
contextName = repr(contextName)[2:end]
end
contextNameString = contextName*"ContextType"
contextTypeNameSymbol = Meta.parse(contextNameString)
contextName = Meta.parse(contextName)
structDefExpr = :(struct $(contextTypeNameSymbol) <: Context end;)
SingletonDefExpr = :($(contextName) = $contextTypeNameSymbol())
return esc(:($structDefExpr; $SingletonDefExpr; addContext($contextName)))
else
error("Argument of @newContext must be a String or a Symbol")
end
end
macro newRole(roleName, attributes, context, contextualType)
if endswith(repr(attributes), "))") || endswith(repr(attributes), "])")
attrString = "(" * replace(replace(repr(attributes)[4:end-2], ","=>";"), " => "=>"::") * ")"
else
attrString = "(" * replace(replace(repr(attributes)[3:end-1], ","=>";"), " => "=>"::") * ")"
end
roleNameSymbol = Symbol(roleName)
attrString = attrString
attrExpr = @eval(Meta.parse($attrString))
newStructExpr = :(struct $roleNameSymbol <: Role
$attrExpr
end)
return esc(:($newStructExpr; addRole($context, $contextualType, $roleNameSymbol)))
end
function assignRole(pair::Pair, context::T) where {T<:Context}
type = pair[1]
role = pair[2]
if type in keys(contextManager.roleDB)
if context in keys(contextManager.roleDB[type])
@warn(repr(type)*" already has Role in context "*repr(context)*". Previous Role will be overwritten!")
end
contextManager.roleDB[type][context] = role
else
contextManager.roleDB[type] = Dict(context => role)
end
if type in keys(contextManager.roleTypeDB)
contextManager.roleTypeDB[type][context] = typeof(role)
else
contextManager.roleTypeDB[type] = Dict(context => typeof(role))
end
end
function disassignRole(pair::Pair, context::T) where {T<:Context}
type = pair[1]
role = pair[2]
if type in keys(contextManager.roleDB)
delete!(contextManager.roleDB[type], context)
else
error("Role is not assigned to type "*repr(type))
end
if type in keys(contextManager.roleTypeDB)
delete!(contextManager.roleTypeDB[type], context)
else
error("Role is not assigned to type "*repr(type))
end
end
macro context(cname, expr)
if typeof(expr) != Expr
error("Second argument of @context must be a function or function definition")
else
if expr.head == :function
functionHeaderString = repr(expr.args[1])
if endswith(repr(expr.args[1]), "())")
functionHeaderString = functionHeaderString[1:end-2] * "context::" * repr(cname)[2:end] * "ContextType))"
else
functionHeaderString = functionHeaderString[1:end-2] * ", " * "context::" * repr(cname)[2:end] * "ContextType))"
end
expr.args[1] = eval(Meta.parse(functionHeaderString))
return esc(expr)
elseif expr.head == :call
callString = repr(expr)
contextString = repr(cname)
if endswith(callString, "())")
callString = callString[1:end-2] * contextString[2:end] * "))"
else
callString = callString[1:end-2] * ", " * contextString[2:end] * "))"
end
callExpr = Meta.parse(callString)
return esc(eval(callExpr))
else
error("Second argument of @context must be a function or function definition")
end
end
end
end
\ No newline at end of file
include("./context.jl")
using .context
struct Person
name::String
age::Int
end
@newContext "Business"
@newContext("Volunteering")
@newContext(Family)
@newContext University
println("Contexts: ", getContexts())
println("First element is Business: ", getContexts()[1] == Business)
@newRole(Husband, [partner=>Person, dayOfMariage=>String], Family, Person)
@newRole(Wife, [partner=>Person, dayOfMariage=>String], Family, Person)
@newRole(Student, [UniversityName=>String, MatrNr=>Int], University, Person)
@newRole Professor [UniversityName::String, Chair::String] University Person
@newRole AcademicStaff UniversityName=>String, Chair=>String, id=>Int University Person
@newRole Employee (CompanyName=>String, partner=>Person) Business Person
@newRole Employer (CompanyName=>String) Business Person
@newRole Chairperson OrganizationName=>String Volunteering Person
println(" ")
println("Husband attributes:", fieldnames(Husband))
println("Wife attributes:", fieldnames(Wife))
println("Employee attributes:", fieldnames(Employee))
println("Chairperson attributes:", fieldnames(Chairperson))
println(" ")
println(getRoles())
println(" ")
John = Person("John", 34)
Jane = Person("Jane", 42)
Jake = Person("Jake", 24)
assignRole(John=>Employee("Test Inc.", Jake), Business)
function marry(p1::Person, p2::Person, dayOfMariage::String)
assignRole(p1=>Husband(p2, dayOfMariage), Family)
@context Family assignRole(p2=>Wife(p1, dayOfMariage))
end
marry(John, Jane, "10.10.2020")
println(" ")
println("Roles of John: ", getRoles(John))
println(" ")
@context University assignRole(Jane => Professor("TU Dresden", "Chair of Context Oriented Programming"))
println(getRoles())
println(" ")
println("Roles of Jane: ", getRoles(Jane))
println(" ")
@context Family function getPartner(person::Person)
(@context context getRole(person)).partner
end
@context Business function getPartner(person::Person)
getRole(person, context).partner
end
println("John's Family Partner: ", @context Family getPartner(John))
println("John's Business Partner: ", @context Business getPartner(John))
println("Janes's Family Partner: ", getPartner(Jane, Family))
function divorce(p1::Person, p2::Person)
disassignRole(p1=>Husband, Family)
disassignRole(p2=>Wife, Family)
end
divorce(John, Jane)
println(" ")
println("Roles of John: ", getRoles(John))
println(" ")
assignRole(John=>Employer("Test Inc."), Business)
marry(Jane, Jake, "01.01.2023")
## Context.jl -- A simple Library for Context-Oriented Programming
### How to Start
To load the Module, add
'include("<<location of context.jl file>>")'
to your script.
If your script is located just in this dir, use the following (in Windows):
'include("./context.jl")'
'using .context'
Will then add all the function listed below to the namespace.
With
'import .context'
e.g. you have to write context.getRoles().
### Some Background Structures
'Context'
An abstract type. Will be super type of concrete context types.
'Role'
An abstract type. Will be super type of concrete role types.
'ContextManagement'
A data base for all contexts and roles that are defined and active.
### Available Functions and Macros
'@newContext <<Context Name>>'
Creates a new Type '<<Context Name>>ContextType' and an Object '<<Context Name>>' of this type
'@newRole <<Role Name>> <<List of Attributes>> <<Context, role lives in>> <<Type, role can be assigned to>>'
Creates a new Struct '<<Role Name>>' with the Attributes defined in '<<List of Attributes>>'
'@context <<Context Name>> <<function Definition>>'
Creates a function, specifically defined for the context <<Context Name>>. Note that, the variable 'context' will be available inside the function by default.
'@context <<Context Name>> <<function call>>'
Calls a function, that was defined via '@context <<Context Name>> <<function Definition>>'. Note that, the variable 'context' will be available inside the function by default.
'assignRole(<<Type>> => <<Role Name>>(<<Role Attributes>>), <<Context Name>>)'
'@context <<Context Name>> assignRole(<<Type>> => <<Role Name>>(<<Role Attributes>>))'
Assigns a Role <<Role Name>> to a <<Type>> in the context <<Context Name>>
'disassignRole(<<Type>> => <<Role Name>>(<<Role Attributes>>), <<Context Name>>)'
'@context <<Context Name>> disassignRole(<<Type>> => <<Role Name>>(<<Role Attributes>>))'
Disassigns a Role <<Role Name>> to a <<Type>> in the context <<Context Name>>
getContexts()
Returns a list of all defined Contexts.
getRoles()
Returns a 'Dict{Context, Dict{Any, Vector{DataType}}}' of all defined Roles. E.g.: {<<Context Name 1>> => {<<Class Name 1>> => [<<Role 1>>], <<Class Name 2>> => [<<Role 2>>]}, <<Context Name 2>>=>{<<Class Name 1>> => [<<Role 3>>, <<Role 4>>]}}
getRoles(<<Object Name>>)
Returns a 'Dict{Context, DataType}' for a specific object <<Object Name>>.
getRole(<<Object Name>>, <<Context Name>>)
Returns the Role, that <<Object Name>> is playing in the context <<Context Name>>.
### Example
For an Example, look into 'contextExample.jl'
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment