import models/SimpleClassDiagrams as SimpleClassDiagrams
include "primitives.alh"

SimpleClassDiagrams CoreFormalism {
    SimpleAttribute String {
        name = "String"
        constraint = $
            String function constraint(model : Element, name : String):
                if (bool_not(is_physical_string(model["model"][name]))):
                    return "String has no string value"!
                else:
                    return "OK"!
            $
    }

    SimpleAttribute Permissions {
        name = "Permissions"
        constraint = $
            String function constraint(model : Element, name : String):
                Element self
                self = model["model"][name]
                if (bool_not(is_physical_string(self))):
                    return "Permissions has no string value"!
                if (bool_not(string_len(self) == 3)):
                    return "Permissions string is not of correct length"!
                if (bool_or(cast_integer(string_get(self, 0)) < 0, cast_integer(string_get(self, 0)) > 2)):
                    return "Owner permission is not in range [0, 2]"!
                if (bool_or(cast_integer(string_get(self, 1)) < 0, cast_integer(string_get(self, 1)) > 2)):
                    return "Group permission is not in range [0, 2]"!
                if (bool_or(cast_integer(string_get(self, 2)) < 0, cast_integer(string_get(self, 2)) > 2)):
                    return "Other permission is not in range [0, 2]"!
                return "OK"!
            $
    }

    SimpleAttribute Boolean {
        name = "Boolean"
        constraint = $
            String function constraint(model : Element, name : String):
                if (bool_not(is_physical_boolean(model["model"][name]))):
                    return "Boolean has no bool value"!
                else:
                    return "OK"!
            $
    }

    SimpleAttribute Natural {
        name = "Natural"
        constraint = $
            String function constraint(model : Element, name : String):
                if (bool_not(is_physical_int(model["model"][name]))):
                    return "Natural has no integer value"!
                elif (integer_lt(model["model"][name], 0)):
                    return "Natural has negative value"!
                else:
                    return "OK"!
            $
    }

    Class User {
        name = "User"
        name : String
        password : String
        admin : Boolean
    }

    Class Group {
        name = "Group"
        name : String
    }

    Association ownedBy (Group, User) {
        name = "ownedBy"
    }
    Association belongsTo (User, Group) {
        name = "belongsTo"
    }

    Class Entry {
        name = "Entry"
        name : String
        permissions : Permissions
    }

    Class Folder : Entry {
        name = "Folder"
    }

    Association contains (Folder, Entry) {
        name = "contains"
    }

    Class Model : Entry {
        name = "Model"
        location : String
    }

    Class TypeMapping : Model {
        name = "TypeMapping"
    }

    Association instanceOf (Model, Model) {
        name = "instanceOf"
    }

    Association owner (Model, User) {
        name = "owner"
        target_lower_cardinality = 1
        target_upper_cardinality = 1
    }

    Association group (Model, Group) {
        name = "group"
        target_lower_cardinality = 1
        target_upper_cardinality = 1
    }

    Class Transformation : Model {
        name = "Transformation"
    }

    Class ModelTransformation : Transformation {
        name = "ModelTransformation"
    }

    Class ActionLanguage : Transformation {
        name = "ActionLanguage"
    }

    Class ManualOperation : Transformation {
        name = "ManualOperation"
    }

    Association transformInput (Model, Transformation) {
        name = "transformInput"
        name : String
    }

    Association transformOutput (Transformation, Model) {
        name = "transformOutput"
        name : String
    }

    Association tracability (Model, Model) {
        name = "tracability"
        type : String
    }

    Association semantics (instanceOf, ActionLanguage) {
        name = "semantics"
        target_lower_cardinality = 1
        target_upper_cardinality = 1
    }
    Association typing (instanceOf, TypeMapping) {
        name = "typing"
        target_lower_cardinality = 1
        target_upper_cardinality = 1
    }

    Class Service {
        name = "Service"
        name : String
        port : String
    }
}

export CoreFormalism to models/CoreFormalism
