diff --git a/CHANGELOG.md b/CHANGELOG.md index c0be7c0da9095f4876f5aeb2c5dcc34f287544fd..4d2da167de45ebdfa408b05bb3d0b676003b100f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,9 +16,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Minimal error handling * Queries * Retrieval by id(s) +* Enums for CaosDB datatypes, importances, roles, and collections ### Changed +* Structs for value and datatype are now used internally to set and get values + of entities and properties. +* `get_datatype` now returns a tuple with the datatype name and the collection + type (or nothing in case of scalar datatypes) + ### Deprecated ### Removed diff --git a/Project.toml b/Project.toml index c62a453e14cf635f708a9b60c85da966b1d9cddc..59d0c2fb56947680b63b3c11c5b5e479eecf8e0e 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "CaosDB" uuid = "091fdcf5-a163-4d8f-97f4-9adce40cd04e" authors = ["florian <f.spreckelsen@inidscale.com>"] -version = "0.0.3" +version = "0.0.4" [deps] Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb" diff --git a/src/CaosDB.jl b/src/CaosDB.jl index e15b46db7c84354f7c72d818ce83fc57dee117b6..376fa3a1299b232d2db2cb4e7fa6f1466d66a6d9 100644 --- a/src/CaosDB.jl +++ b/src/CaosDB.jl @@ -29,7 +29,16 @@ export evaluate_return_code, CaosDBException, ClientException, GenericCaosDBException, CaosDBMessage # Exports from module Constants -export MIN_CCAOSDB_VERSION +# ...from Constants namespace +export COLLECTION, DATATYPE, IMPORTANCE, MIN_CCAOSDB_VERSION, ROLE +# ...from CaosDB datatypes +export BOOLEAN, DATETIME, DOUBLE, INTEGER, TEXT +# ...from CaosDB collections +export LIST +# ...from CaosDB entity roles +export FILE, PROPERTY, RECORD, RECORD_TYPE +# ...from CaosDB importances +export FIX, OBLIGATORY, RECOMMENDED, SUGGESTED # Exports from module Utility export get_ccaosdb_version, get_env_fallback @@ -55,7 +64,6 @@ export get_id, get_datatype, get_unit, get_value, - get_property_list_length, get_version_id, get_property, get_properties, diff --git a/src/Constants.jl b/src/Constants.jl index b1e5db73dc4672aa719861d5cf58e5fc918d9939..67327b08b6c1bc55d171feea575b13dba2e8d2d1 100644 --- a/src/Constants.jl +++ b/src/Constants.jl @@ -23,12 +23,81 @@ module Constants -export MIN_CCAOSDB_VERSION +# exports from this module +export COLLECTION, DATATYPE, IMPORTANCE, MIN_CCAOSDB_VERSION, ROLE + +# exports from the enum submodules +export BOOLEAN, DATETIME, DOUBLE, INTEGER, TEXT + +export LIST + +export FILE, PROPERTY, RECORD, RECORD_TYPE + +export FIX, OBLIGATORY, RECOMMENDED, SUGGESTED """ The minimum version of CaosDB's cpplib and C interface that is supported by this version of CaosDB.jl. """ -const MIN_CCAOSDB_VERSION = v"0.0.16" +const MIN_CCAOSDB_VERSION = v"0.0.17" + +# enums have to be encapsulated in modules to prevent namespce conflicts, see +# https://bleepcoder.com/julia/413856244/feature-request-getproperty-on-enum-type-to-access-instances +module DATATYPE + +export BOOLEAN, DATETIME, DOUBLE, INTEGER, TEXT + +@enum _DATATYPE begin + UNSPECIFIED + BOOLEAN + INTEGER + DOUBLE + DATETIME + TEXT +end +end + +module COLLECTION + +export LIST + +@enum _COLLECTION begin + LIST +end +end + +module ROLE + +export FILE, PROPERTY, RECORD, RECORD_TYPE + +@enum _ROLE begin + UNSPECIFIED + RECORD + RECORD_TYPE + PROPERTY + FILE +end +end + +module IMPORTANCE + +export FIX, OBLIGATORY, RECOMMENDED, SUGGESTED + +@enum _IMPORTANCE begin + UNSPECIFIED + OBLIGATORY + RECOMMENDED + SUGGESTED + FIX +end +end + +using .COLLECTION + +using .DATATYPE + +using .IMPORTANCE + +using .ROLE end diff --git a/src/Entity.jl b/src/Entity.jl index 9c23a8ee1794bbd5710b829b8f29d6b7124bfb3c..6a9007d0e57d8af55483abf9cf99b6d3d2fd84ee 100644 --- a/src/Entity.jl +++ b/src/Entity.jl @@ -39,7 +39,6 @@ export get_id, get_datatype, get_unit, get_value, - get_property_list_length, get_version_id, get_property, get_properties, @@ -83,11 +82,6 @@ using CaosDB # especially in case of a property which I might want to specify by # name, add a value, append it to a Record, and then insert it and # might expect the server to care for the datatype. -# -# Also, how much do we want to support them with typos. Currently, C -# and C++ only understand all-capital strings for datatypes, -# importances, roles. What about user input like "record_type", -# "RecordType", "recordtype"? """ Struct containing a pointer to the wrapped cpp entity object. Meant for internal use; use `CaosDB.Entity.create_entity` to @@ -195,6 +189,66 @@ mutable struct _Message end end +""" +Struct containing a pointer to the wrapped cpp DataType object. Meant for +internal use only; use `CaosDB.Entity.create_<type>_datatype` to create a +valid _DataType object or use the `set/get_datatype` functions. +""" +mutable struct _DataType + wrapped_datatype::Ptr{Cvoid} + _deletable::Bool + + function _DataType(managed_by_julia::Bool = false) + + datatype = new() + datatype._deletable = false + + if managed_by_julia + function f(t) + ccall( + (:caosdb_entity_delete_datatype, CaosDB.library_name), + Cint, + (Ref{_DataType},), + Ref{_DataType}(t), + ) + end + finalizer(f, datatype) + end + + return datatype + end +end + +""" +Struct containing a pointer to the wrapped cpp AbstractValue object. Meant for +internal use only; use `CaosDB.Entity.create_value` to create a _Value object or +use the `set/get_value` functions`. +""" +mutable struct _Value + wrapped_value::Ptr{Cvoid} + _deletable::Bool + + function _Value(managed_by_julia::Bool = false) + + value = new() + value._deletable = false + + if managed_by_julia + function f(t) + ccall( + (:caosdb_entity_delete_value, CaosDB.library_name), + Cint, + (Ref{_Value},), + Ref{_Value}(t), + ) + end + finalizer(f, value) + end + + return value + end +end + """ function create_entity(name::AbstractString = "") @@ -232,7 +286,7 @@ function create_recordtype(name::AbstractString = "") record_type = create_entity(name) - set_role(record_type, "RECORD_TYPE") + set_role(record_type, CaosDB.Constants.ROLE.RECORD_TYPE) return record_type @@ -248,7 +302,7 @@ function create_record(name::AbstractString = "") record = create_entity(name) - set_role(record, "RECORD") + set_role(record, CaosDB.Constants.ROLE.RECORD) return record @@ -257,30 +311,28 @@ end """ function create_property_entity(; name::AbstractString = "", - datatype::AbstractString = "", + datatype::Union{AbstractString,CaosDB.Constants.DATATYPE._DATATYPE} = "", + collection::Union{CaosDB.Constants.COLLECTION._COLLECTION,Nothing} = nothing, unit::AbstractString = "", - is_reference::Bool = false, - is_list::Bool = false, ) -Return a new entity object with role Record. If `name`, `datatype`, or -`unit` were provided, its name, datatype (including whether it is a -reference or a list), or unit are set accordingly. +Return a new entity object with role Record. If `name`, `datatype`, or `unit` +were provided, its name, datatype (including whether its `collection` type), or +unit are set accordingly. """ function create_property_entity(; name::AbstractString = "", - datatype::AbstractString = "", + datatype::Union{AbstractString,CaosDB.Constants.DATATYPE._DATATYPE} = "", + collection::Union{CaosDB.Constants.COLLECTION._COLLECTION,Nothing} = nothing, unit::AbstractString = "", - is_reference::Bool = false, - is_list::Bool = false, ) property = create_entity(name) - set_role(property, "PROPERTY") + set_role(property, CaosDB.Constants.ROLE.PROPERTY) if datatype != "" - set_datatype(property, datatype, is_list = is_list, is_reference = is_reference) + set_datatype(property, datatype, collection) end if unit != "" @@ -295,16 +347,14 @@ end name::AbstractString = "", id::AbstractString = "", value::Union{AbstractString, Number, Bool} = "", - datatype::AbstractString = "", - is_reference::Bool = false, - is_list::Bool = false, + datatype::Union{AbstractString,CaosDB.Constants.DATATYPE._DATATYPE} = "", + collection::Union{CaosDB.Constants.COLLECTION._COLLECTION, Nothing} = nothing, ) -Create a property object that can be appended to another `_Entity`. If -`name`, `id`, or `value` are given, the property's name, id, or value -are set accordingly. The datatype and whether it is a list or a -reference can be specified with `datatype`, `is_reference`, and -`is_list`, respectively. +Create a property object that can be appended to another `_Entity`. If `name`, +`id`, or `value` are given, the property's name, id, or value are set +accordingly. The datatype and its collection type can be specified with +`datatype` and `collection`, respectively. !!! info @@ -315,9 +365,8 @@ function create_property(; name::AbstractString = "", id::AbstractString = "", value::Union{AbstractString,Number,Bool} = "", - datatype::AbstractString = "", - is_reference::Bool = false, - is_list::Bool = false, + datatype::Union{AbstractString,CaosDB.Constants.DATATYPE._DATATYPE} = "", + collection::Union{CaosDB.Constants.COLLECTION._COLLECTION,Nothing} = nothing, ) property = Ref{_Property}(_Property(true)) @@ -339,7 +388,7 @@ function create_property(; end if datatype != "" - set_datatype(property, datatype, is_reference = is_reference, is_list = is_list) + set_datatype(property, datatype, collection) end if value != "" @@ -373,7 +422,7 @@ function create_file_entity(; end file_entity = create_entity(name) - set_role(file_entity, "FILE") + set_role(file_entity, CaosDB.Constants.ROLE.FILE) set_local_path(file_entity, local_path) set_remote_path(file_entity, remote_path) @@ -415,6 +464,186 @@ function create_parent(; name::AbstractString = "", id::AbstractString = "") return parent end +""" + function create_atomic_datatype(name::CaosDB.Constants.DATATYPE._DATATYPE) + +Create and return a DataType object with an atomic datatype specified by the +`name`. +""" +function create_atomic_datatype(name::CaosDB.Constants.DATATYPE._DATATYPE) + + datatype = Ref{_DataType}(_DataType(true)) + + err_code = ccall( + (:caosdb_entity_create_atomic_datatype, CaosDB.library_name), + Cint, + (Ref{_DataType}, Cstring), + datatype, + string(name), + ) + + CaosDB.Exceptions.evaluate_return_code(err_code) + + return datatype +end + +""" + function create_reference_datatype(name::AbstractString) + +Create and return a DataType object with a reference datatype specified by +`name`. +""" +function create_reference_datatype(name::AbstractString) + + datatype = Ref{_DataType}(_DataType(true)) + + err_code = ccall( + (:caosdb_entity_create_reference_datatype, CaosDB.library_name), + Cint, + (Ref{_DataType}, Cstring), + datatype, + name, + ) + + CaosDB.Exceptions.evaluate_return_code(err_code) + + return datatype +end + +""" + function create_atomic_list_datatype(name::CaosDB.Constants.DATATYPE._DATATYPE) + +Create and return a DataType object which is a list of atomics specified by +`name`. +""" +function create_atomic_list_datatype(name::CaosDB.Constants.DATATYPE._DATATYPE) + + datatype = Ref{_DataType}(_DataType(true)) + + err_code = ccall( + (:caosdb_entity_create_atomic_list_datatype, CaosDB.library_name), + Cint, + (Ref{_DataType}, Cstring), + datatype, + string(name), + ) + + CaosDB.Exceptions.evaluate_return_code(err_code) + + return datatype +end + +""" + function create_reference_list_datatype(name::AbstractString) + +Create and return a DataType object which is a list of references specified by +`name`. +""" +function create_reference_list_datatype(name::AbstractString) + + datatype = Ref{_DataType}(_DataType(true)) + + err_code = ccall( + (:caosdb_entity_create_reference_list_datatype, CaosDB.library_name), + Cint, + (Ref{_DataType}, Cstring), + datatype, + name, + ) + + CaosDB.Exceptions.evaluate_return_code(err_code) + + return datatype +end + +function create_value( + value::Union{AbstractString,Number,Bool,Vector{T}}, +) where {T<:Union{AbstractString,Number,Bool}} + + in_type = typeof(value) + out = Ref{_Value}(_Value(true)) + if in_type <: AbstractString + err_code = ccall( + (:caosdb_entity_create_string_value, CaosDB.library_name), + Cint, + (Ref{_Value}, Cstring), + out, + value, + ) + elseif in_type <: Bool + err_code = ccall( + (:caosdb_entity_create_bool_value, CaosDB.library_name), + Cint, + (Ref{_Value}, Bool), + out, + value, + ) + elseif in_type <: Integer + err_code = ccall( + (:caosdb_entity_create_int_value, CaosDB.library_name), + Cint, + (Ref{_Value}, Clong), + out, + Clong(value), + ) + elseif in_type <: Number + err_code = ccall( + (:caosdb_entity_create_double_value, CaosDB.library_name), + Cint, + (Ref{_Value}, Cdouble), + out, + Cdouble(value), + ) + elseif in_type <: Vector{T} where {T<:AbstractString} + err_code = ccall( + (:caosdb_entity_create_string_vector_value, CaosDB.library_name), + Cint, + (Ref{_Value}, Ptr{Ptr{Cchar}}, Cint), + out, + value, + Cint(length(value)), + ) + elseif in_type <: Vector{T} where {T<:Bool} + err_code = ccall( + (:caosdb_entity_create_bool_vector_value, CaosDB.library_name), + Cint, + (Ref{_Value}, Ptr{Bool}, Cint), + out, + value, + Cint(length(value)), + ) + elseif in_type <: Vector{T} where {T<:Integer} + err_code = ccall( + (:caosdb_entity_create_int_vector_value, CaosDB.library_name), + Cint, + (Ref{_Value}, Ptr{Clong}, Cint), + out, + Vector{Clong}(value), + Cint(length(value)), + ) + elseif in_type <: Vector{T} where {T<:Number} + err_code = ccall( + (:caosdb_entity_create_double_vector_value, CaosDB.library_name), + Cint, + (Ref{_Value}, Ptr{Cdouble}, Cint), + out, + Vector{Cdouble}(value), + Cint(length(value)), + ) + else + # Should never enter here but treat it just in case + throw( + ArgumentError( + "The argument of type $in_type couldn't be converted into a valid CaosDB value object.", + ), + ) + end + + CaosDB.Exceptions.evaluate_return_code(err_code) + + return out +end + """ function get_id(entity::Ref{_Entity}) @@ -500,7 +729,9 @@ function get_role(entity::Ref{_Entity}) CaosDB.Exceptions.evaluate_return_code(err_code) - return unsafe_string(out[]) + rolename = unsafe_string(out[]) + role = getproperty(CaosDB.Constants.ROLE, Symbol(rolename)) + return role end """ @@ -657,33 +888,99 @@ function get_description(message::Ref{_Message}) return unsafe_string(out[]) end -# TODO(henrik, daniel) Is this the best way to return name, is_ref, -# and is_list to the users? Should we split it up? +""" + function _get_datatype(datatype::Ref{_DataType}) + +Return a tuple that contains the name of the `datatype`, and its collection type +(`nothing` in case of a scalar datatype). +""" +function _get_datatype(datatype::Ref{_DataType}) + + name = Ref{Ptr{UInt8}}(Ptr{UInt8}()) + err_code = ccall( + (:caosdb_entity_datatype_get_datatype_name, CaosDB.library_name), + Cint, + (Ref{_DataType}, Ref{Ptr{UInt8}}), + datatype, + name, + ) + CaosDB.Exceptions.evaluate_return_code(err_code) + name = unsafe_string(name[]) + + is_a = Ref{Bool}(false) + err_code = ccall( + (:caosdb_entity_datatype_is_atomic, CaosDB.library_name), + Cint, + (Ref{_DataType}, Ref{Bool}), + datatype, + is_a, + ) + CaosDB.Exceptions.evaluate_return_code(err_code) + if is_a[] + return getproperty(CaosDB.Constants.DATATYPE, Symbol(name)), nothing + end + + err_code = ccall( + (:caosdb_entity_datatype_is_reference, CaosDB.library_name), + Cint, + (Ref{_DataType}, Ref{Bool}), + datatype, + is_a, + ) + CaosDB.Exceptions.evaluate_return_code(err_code) + if is_a[] + return name, nothing + end + + err_code = ccall( + (:caosdb_entity_datatype_is_list_of_atomic, CaosDB.library_name), + Cint, + (Ref{_DataType}, Ref{Bool}), + datatype, + is_a, + ) + CaosDB.Exceptions.evaluate_return_code(err_code) + if is_a[] + return getproperty(CaosDB.Constants.DATATYPE, Symbol(name)), + CaosDB.Constants.COLLECTION.LIST + end + + err_code = ccall( + (:caosdb_entity_datatype_is_list_of_reference, CaosDB.library_name), + Cint, + (Ref{_DataType}, Ref{Bool}), + datatype, + is_a, + ) + CaosDB.Exceptions.evaluate_return_code(err_code) + if is_a[] + return name, CaosDB.Constants.COLLECTION.LIST + end + + throw(CaosDB.Exceptions.ClientException("Unkown datatype")) + +end + """ function get_datatype(entity::Ref{_Entity}) -Return a tuple that contains the name of the datatype of the given -`entity`, whether it is a reference, and whether it is a list. +Return a tuple that contains the name of the datatype of the given `entity`, and +its collection type (`nothing` in case of a scalar datatype). """ function get_datatype(entity::Ref{_Entity}) - out = Ref{Ptr{UInt8}}(Ptr{UInt8}()) - is_ref = Ref{Bool}(false) - is_list = Ref{Bool}(false) - + out = Ref{_DataType}(_DataType()) err_code = ccall( (:caosdb_entity_entity_get_datatype, CaosDB.library_name), Cint, - (Ref{_Entity}, Ref{Ptr{UInt8}}, Ref{Bool}, Ref{Bool}), + (Ref{_Entity}, Ref{_DataType}), entity, out, - is_ref, - is_list, ) CaosDB.Exceptions.evaluate_return_code(err_code) - return unsafe_string(out[]), is_ref[], is_list[] + return _get_datatype(out) end """ @@ -694,23 +991,18 @@ Return a tuple that contains the name of the datatype of the given """ function get_datatype(property::Ref{_Property}) - out = Ref{Ptr{UInt8}}(Ptr{UInt8}()) - is_ref = Ref{Bool}(false) - is_list = Ref{Bool}(false) - + out = Ref{_DataType}(_DataType()) err_code = ccall( (:caosdb_entity_property_get_datatype, CaosDB.library_name), Cint, - (Ref{_Property}, Ref{Ptr{UInt8}}, Ref{Bool}, Ref{Bool}), + (Ref{_Property}, Ref{_DataType}), property, out, - is_ref, - is_list, ) CaosDB.Exceptions.evaluate_return_code(err_code) - return unsafe_string(out[]), is_ref[], is_list[] + return _get_datatype(out) end """ @@ -758,428 +1050,229 @@ function get_unit(property::Ref{_Property}) end """ - function get_value(entity::Ref{_Entity}) - -Return the value of the given `entity` -""" -function get_value(entity::Ref{_Entity}) - - _caosdb_dtypes = ("INTEGER", "DOUBLE", "BOOLEAN", "TEXT") - - ent_datatype = get_datatype(entity) - is_list = ent_datatype[3] - if ent_datatype[1] in _caosdb_dtypes - if !is_list - if ent_datatype[1] == "INTEGER" - out = Ref{Clong}(0) - err_code = ccall( - (:caosdb_entity_entity_get_int_value, CaosDB.library_name), - Cint, - (Ref{_Entity}, Ref{Clong}), - entity, - out, - ) - - out = out[] - elseif ent_datatype[1] == "DOUBLE" - out = Ref{Cdouble}(0) - err_code = ccall( - (:caosdb_entity_entity_get_double_value, CaosDB.library_name), - Cint, - (Ref{_Entity}, Ref{Cdouble}), - entity, - out, - ) - out = out[] - elseif ent_datatype[1] == "BOOLEAN" - out = Ref{Cint}(0) - err_code = ccall( - (:caosdb_entity_entity_get_boolean_value, CaosDB.library_name), - Cint, - (Ref{_Entity}, Ref{Cint}), - entity, - out, - ) - out = convert(Bool, out[]) - elseif ent_datatype[1] == "TEXT" - out = Ref{Ptr{UInt8}}(Ptr{UInt8}()) - err_code = ccall( - (:caosdb_entity_entity_get_string_value, CaosDB.library_name), - Cint, - (Ref{_Entity}, Ref{Ptr{UInt8}}), - entity, - out, - ) - out = unsafe_string(out[]) - end - else - list_length = get_property_list_length(entity) - if ent_datatype[1] == "INTEGER" - out = Vector{Clong}() - for i::Cint = 1:list_length - temp = get_int_list_value_at(entity, i) - append!(out, temp) - end - elseif ent_datatype[1] == "DOUBLE" - out = Vector{Cdouble}() - for i::Cint = 1:list_length - temp = get_double_list_value_at(entity, i) - append!(out, temp) - end - elseif ent_datatype[1] == "BOOLEAN" - out = Vector{Bool}() - for i::Cint = 1:list_length - temp = get_bool_list_value_at(entity, i) - append!(out, temp) - end - elseif ent_datatype[1] == "TEXT" - out = Vector{String}() - for i::Cint = 1:list_length - temp = get_string_list_value_at(entity, i) - append!(out, [temp]) - end - end - end - elseif ent_datatype[2] - # is reference - if !is_list - out = Ref{Ptr{UInt8}}(Ptr{UInt8}()) - err_code = ccall( - (:caosdb_entity_entity_get_string_value, CaosDB.library_name), - Cint, - (Ref{_Entity}, Ref{Ptr{UInt8}}), - entity, - out, - ) - out = unsafe_string(out[]) - else - # is list of references - list_length = get_property_list_length(entity) - out = [get_string_list_value_at(entity, Cint(ii)) for ii = 1:list_length] - end - end - - if @isdefined err_code - CaosDB.Exceptions.evaluate_return_code(err_code) - end - - return out -end - -""" - function get_value(property::Ref{_Property}) + function _get_value(value::Ref{_Value}) -Return the value of the given `property` +Return the value of the given CaosDB value object. """ -function get_value(property::Ref{_Property}) +function _get_value(value::Ref{_Value}) - _caosdb_dtypes = ("INTEGER", "DOUBLE", "BOOLEAN", "TEXT") - - prop_datatype = get_datatype(property) - is_list = prop_datatype[3] - if prop_datatype[1] in _caosdb_dtypes - if !is_list - if prop_datatype[1] == "INTEGER" - out = Ref{Clong}(0) - err_code = ccall( - (:caosdb_entity_property_get_int_value, CaosDB.library_name), - Cint, - (Ref{_Property}, Ref{Clong}), - property, - out, - ) - - out = out[] - elseif prop_datatype[1] == "DOUBLE" - out = Ref{Cdouble}(0) - err_code = ccall( - (:caosdb_entity_property_get_double_value, CaosDB.library_name), - Cint, - (Ref{_Property}, Ref{Cdouble}), - property, - out, - ) - out = out[] - elseif prop_datatype[1] == "BOOLEAN" - out = Ref{Cint}(0) - err_code = ccall( - (:caosdb_entity_property_get_boolean_value, CaosDB.library_name), - Cint, - (Ref{_Property}, Ref{Cint}), - property, - out, - ) - out = convert(Bool, out[]) - elseif prop_datatype[1] == "TEXT" - out = Ref{Ptr{UInt8}}(Ptr{UInt8}()) - err_code = ccall( - (:caosdb_entity_property_get_string_value, CaosDB.library_name), - Cint, - (Ref{_Property}, Ref{Ptr{UInt8}}), - property, - out, - ) - out = unsafe_string(out[]) - end - else - list_length = get_property_list_length(property) - if prop_datatype[1] == "INTEGER" - out = Vector{Clong}() - for i::Cint = 1:list_length - temp = get_int_list_value_at(property, i) - append!(out, temp) - end - elseif prop_datatype[1] == "DOUBLE" - out = Vector{Cdouble}() - for i::Cint = 1:list_length - temp = get_double_list_value_at(property, i) - append!(out, temp) - end - elseif prop_datatype[1] == "BOOLEAN" - out = Vector{Bool}() - for i::Cint = 1:list_length - temp = get_bool_list_value_at(property, i) - append!(out, temp) - end - elseif prop_datatype[1] == "TEXT" - out = Vector{String}() - for i::Cint = 1:list_length - temp = get_string_list_value_at(property, i) - append!(out, [temp]) - end - end - end - elseif prop_datatype[2] - # is reference - if !is_list - out = Ref{Ptr{UInt8}}(Ptr{UInt8}()) - err_code = ccall( - (:caosdb_entity_property_get_string_value, CaosDB.library_name), - Cint, - (Ref{_Property}, Ref{Ptr{UInt8}}), - property, - out, - ) - out = unsafe_string(out[]) - else - # is list of references - list_length = get_property_list_length(property) - out = [get_string_list_value_at(property, Cint(ii)) for ii = 1:list_length] - end - end - if @isdefined err_code - CaosDB.Exceptions.evaluate_return_code(err_code) - end - - return out -end - -""" - function get_property_list_length(property::Ref{_Property}) - -Return the length of the list of the given `property` -""" -function get_property_list_length(property::Ref{_Property}) - - length = Ref{Cint}(0) + is_a = Ref{Bool}(false) + # value may be null err_code = ccall( - (:caosdb_entity_property_get_value_list_length, CaosDB.library_name), + (:caosdb_entity_value_is_null, CaosDB.library_name), Cint, - (Ref{_Property}, Ref{Cint}), - property, - length, + (Ref{_Value}, Ref{Bool}), + value, + is_a, ) CaosDB.Exceptions.evaluate_return_code(err_code) - return length[] -end - -""" - function get_property_list_length(entity::Ref{_Entity}) - -Return the length of the list of the given `entity` -""" -function get_property_list_length(entity::Ref{_Entity}) - - length = Ref{Cint}(0) - - err_code = ccall( - (:caosdb_entity_entity_get_value_list_length, CaosDB.library_name), - Cint, - (Ref{_Entity}, Ref{Cint}), - entity, - length, - ) - - CaosDB.Exceptions.evaluate_return_code(err_code) - - return length[] -end - -""" - function get_int_list_value_at(property::Ref{_Property}, index::Cint) + if is_a[] + return nothing + end -Return the value of the INTEGER list of the given `property` at the position `index`. -""" -function get_int_list_value_at(property::Ref{_Property}, index::Cint) - out = Ref{Clong}(0) + # scalar string err_code = ccall( - (:caosdb_entity_property_get_int_list_value_at, CaosDB.library_name), + (:caosdb_entity_value_is_string, CaosDB.library_name), Cint, - (Ref{_Property}, Ref{Clong}, Cint), - property, - out, - index - Cint(1), + (Ref{_Value}, Ref{Bool}), + value, + is_a, ) CaosDB.Exceptions.evaluate_return_code(err_code) - return out[] -end -""" - function get_int_list_value_at(entity::Ref{_Entity}, index::Cint) + if is_a[] + out = Ref{Ptr{UInt8}}(Ptr{UInt8}()) -Return the value of the INTEGER list of the given `entity` at the position `index`. -""" -function get_int_list_value_at(entity::Ref{_Entity}, index::Cint) - out = Ref{Clong}(0) - err_code = ccall( - (:caosdb_entity_entity_get_int_list_value_at, CaosDB.library_name), - Cint, - (Ref{_Entity}, Ref{Clong}, Cint), - entity, - out, - index - Cint(1), - ) + ccall( + (:caosdb_entity_value_get_as_string, CaosDB.library_name), + Cint, + (Ref{_Value}, Ref{Ptr{UInt8}}), + value, + out, + ) - CaosDB.Exceptions.evaluate_return_code(err_code) - return out[] -end + CaosDB.Exceptions.evaluate_return_code(err_code) -""" - function get_double_list_value_at(property::Ref{_Property}, index::Cint) + return unsafe_string(out[]) + end -Return the value of the DOUBLE list of the given `property` at the position `index`. -""" -function get_double_list_value_at(property::Ref{_Property}, index::Cint) - out = Ref{Cdouble}(0) + # integer err_code = ccall( - (:caosdb_entity_property_get_double_list_value_at, CaosDB.library_name), + (:caosdb_entity_value_is_integer, CaosDB.library_name), Cint, - (Ref{_Property}, Ref{Cdouble}, Cint), - property, - out, - index - Cint(1), + (Ref{_Value}, Ref{Bool}), + value, + is_a, ) CaosDB.Exceptions.evaluate_return_code(err_code) - return out[] -end -""" - function get_double_list_value_at(entity::Ref{_Entity}, index::Cint) + if is_a[] + out = Ref{Clong}(0) -Return the value of the DOUBLE list of the given `entity` at the position `index`. -""" -function get_double_list_value_at(entity::Ref{_Entity}, index::Cint) - out = Ref{Cdouble}(0) + ccall( + (:caosdb_entity_value_get_as_integer, CaosDB.library_name), + Cint, + (Ref{_Value}, Ref{Clong}), + value, + out, + ) + + CaosDB.Exceptions.evaluate_return_code(err_code) + + return out[] + end + + # double err_code = ccall( - (:caosdb_entity_entity_get_double_list_value_at, CaosDB.library_name), + (:caosdb_entity_value_is_double, CaosDB.library_name), Cint, - (Ref{_Entity}, Ref{Cdouble}, Cint), - entity, - out, - index - Cint(1), + (Ref{_Value}, Ref{Bool}), + value, + is_a, ) CaosDB.Exceptions.evaluate_return_code(err_code) - return out[] -end -""" - function get_bool_list_value_at(property::Ref{_Property}, index::Cint) + if is_a[] + out = Ref{Cdouble}(0) -Return the value of the BOOLEAN list of the given `property` at the position `index`. -""" -function get_bool_list_value_at(property::Ref{_Property}, index::Cint) - out = Ref{Cint}(0) + ccall( + (:caosdb_entity_value_get_as_double, CaosDB.library_name), + Cint, + (Ref{_Value}, Ref{Cdouble}), + value, + out, + ) + + CaosDB.Exceptions.evaluate_return_code(err_code) + + return out[] + end + + # bool err_code = ccall( - (:caosdb_entity_property_get_boolean_list_value_at, CaosDB.library_name), + (:caosdb_entity_value_is_bool, CaosDB.library_name), Cint, - (Ref{_Property}, Ref{Cint}, Cint), - property, - out, - index - Cint(1), + (Ref{_Value}, Ref{Bool}), + value, + is_a, ) CaosDB.Exceptions.evaluate_return_code(err_code) - out = convert(Bool, out[]) - return out -end -""" - function get_bool_list_value_at(entity::Ref{_Entity}, index::Cint) + if is_a[] + out = Ref{Bool}(false) -Return the value of the BOOLEAN list of the given `entity` at the position `index`. -""" -function get_bool_list_value_at(entity::Ref{_Entity}, index::Cint) - out = Ref{Cint}(0) + ccall( + (:caosdb_entity_value_get_as_bool, CaosDB.library_name), + Cint, + (Ref{_Value}, Ref{Bool}), + value, + out, + ) + + CaosDB.Exceptions.evaluate_return_code(err_code) + + return convert(Bool, out[]) + end + + # vector err_code = ccall( - (:caosdb_entity_entity_get_boolean_list_value_at, CaosDB.library_name), + (:caosdb_entity_value_is_vector, CaosDB.library_name), Cint, - (Ref{_Entity}, Ref{Cint}, Cint), - entity, - out, - index - Cint(1), + (Ref{_Value}, Ref{Bool}), + value, + is_a, ) CaosDB.Exceptions.evaluate_return_code(err_code) - out = convert(Bool, out[]) - return out + + if is_a[] + vector_size = Ref{Cint}(0) + + err_code = ccall( + (:caosdb_entity_value_get_as_vector_size, CaosDB.library_name), + Cint, + (Ref{_Value}, Ref{Cint}), + value, + vector_size, + ) + + CaosDB.Exceptions.evaluate_return_code(err_code) + + out = [] + value_elt = Ref{_Value}(_Value(false)) + for ii::Cint = 1:vector_size[] + err_code = ccall( + (:caosdb_entity_value_get_as_vector_at, CaosDB.library_name), + Cint, + (Ref{_Value}, Ref{_Value}, Cint), + value, + value_elt, + ii - Cint(1), + ) + CaosDB.Exceptions.evaluate_return_code(err_code) + push!(out, _get_value(value_elt)) + end + + if length(out) > 0 + # convert to vector of type of elements s.th. it can be re-used in a + # `set_value` function. + elt_type = typeof(out[1]) + return convert(Vector{elt_type}, out) + end + + return out + end + + throw(CaosDB.Exceptions.ClientException("Unkown value.")) end """ - function get_string_list_value_at(property::Ref{_Property}, index::Cint) + function get_value(entity::Ref{_Entity}) -Return the value of the TEXT list of the given `property` at the position `index`. +Return the value of the given `entity` """ -function get_string_list_value_at(property::Ref{_Property}, index::Cint) - out = Ref{Ptr{UInt8}}(Ptr{UInt8}()) +function get_value(entity::Ref{_Entity}) + + value = Ref{_Value}(_Value()) + err_code = ccall( - (:caosdb_entity_property_get_string_list_value_at, CaosDB.library_name), + (:caosdb_entity_entity_get_value, CaosDB.library_name), Cint, - (Ref{_Property}, Ref{Ptr{UInt8}}, Cint), - property, - out, - index - Cint(1), + (Ref{_Entity}, Ref{_Value}), + entity, + value, ) - CaosDB.Exceptions.evaluate_return_code(err_code) - out = unsafe_string(out[]) - return out + + return _get_value(value) end """ - function get_string_list_value_at(entity::Ref{_Entity}, index::Cint) + function get_value(property::Ref{_Property}) -Return the value of the TEXT list of the given `entity` at the position `index`. +Return the value of the given `property` """ -function get_string_list_value_at(entity::Ref{_Entity}, index::Cint) - out = Ref{Ptr{UInt8}}(Ptr{UInt8}()) +function get_value(property::Ref{_Property}) + + value = Ref{_Value}(_Value()) + err_code = ccall( - (:caosdb_entity_entity_get_string_list_value_at, CaosDB.library_name), + (:caosdb_entity_property_get_value, CaosDB.library_name), Cint, - (Ref{_Entity}, Ref{Ptr{UInt8}}, Cint), - entity, - out, - index - Cint(1), + (Ref{_Property}, Ref{_Value}), + property, + value, ) - CaosDB.Exceptions.evaluate_return_code(err_code) - out = unsafe_string(out[]) - return out + + return _get_value(value) end """ @@ -1239,14 +1332,16 @@ function get_importance(property::Ref{_Property}) err_code = ccall( (:caosdb_entity_property_get_importance, CaosDB.library_name), Cint, - (Ref{_Entity}, Ref{Ptr{UInt8}}), + (Ref{_Property}, Ref{Ptr{UInt8}}), property, out, ) CaosDB.Exceptions.evaluate_return_code(err_code) - return unsafe_string(out[]) + imp_name = unsafe_string(out[]) + imp = getproperty(CaosDB.Constants.IMPORTANCE, Symbol(imp_name)) + return imp end """ @@ -1736,17 +1831,17 @@ function set_id(property::Ref{_Property}, id::AbstractString) end """ - function set_role(entity::Ref{_Entity}, role::AbstractString) + function set_role(entity::Ref{_Entity}, role::CaosDB.Constants.ROLE._ROLE) Set the role of the given `entity` object. """ -function set_role(entity::Ref{_Entity}, role::AbstractString) +function set_role(entity::Ref{_Entity}, role::CaosDB.Constants.ROLE._ROLE) err_code = ccall( (:caosdb_entity_entity_set_role, CaosDB.library_name), Cint, (Ref{_Entity}, Cstring), entity, - role, + string(role), ) CaosDB.Exceptions.evaluate_return_code(err_code) @@ -1823,31 +1918,25 @@ function set_description(entity::Ref{_Entity}, description::AbstractString) CaosDB.Exceptions.evaluate_return_code(err_code) end -# TODO(henrik, daniel) Convenience functions for lists and references, -# too? """ function set_datatype( entity::Ref{_Entity}, - datatype::AbstractString; - is_list::Bool = false, - is_reference::Bool = false, + datatype::AbstractString, + collection::Union{CaosDB.Constants.COLLECTION._COLLECTION, Nothing} ) -Set the datatype of the given `entity` object to the given `datatype` -name. Only possible if the role of the entity is "PROPERTY". Specify -whether it is a reference or a list with the optional `is_list` and -`is_reference` keyword arguments. If the datatype is not a reference, -it is checked against the Atomic Datatypes known to CaosDB and an -exception is thrown if it is not known. +Set the datatype of the given `entity` object to a reference to the given +`datatype` name. Only possible if the role of the entity is "PROPERTY". Specify +whether the datatype is a list by specifying a `collection`. If none is given, a +scalar datatype is set. """ function set_datatype( entity::Ref{_Entity}, - datatype::AbstractString; - is_list::Bool = false, - is_reference::Bool = false, + datatype::AbstractString, + collection::Union{CaosDB.Constants.COLLECTION._COLLECTION,Nothing} = nothing, ) - if get_role(entity) != "PROPERTY" + if get_role(entity) != CaosDB.Constants.ROLE.PROPERTY throw( CaosDB.Exceptions.ClientException( "Only entities with role PROPERTY can be assigned a datatype.", @@ -1855,54 +1944,161 @@ function set_datatype( ) end + if collection == nothing + dtype_ref = create_reference_datatype(datatype) + elseif collection == CaosDB.Constants.COLLECTION.LIST + dtype_ref = create_reference_list_datatype(datatype) + else + throw(ArgumentError("Unkown datatype: $datatype")) + end + err_code = ccall( (:caosdb_entity_entity_set_datatype, CaosDB.library_name), Cint, - (Ref{_Entity}, Cstring, Bool, Bool), + (Ref{_Entity}, Ref{_DataType}), entity, - datatype, - is_reference, - is_list, + dtype_ref, + ) + + CaosDB.Exceptions.evaluate_return_code(err_code) +end + +""" + function set_datatype( + entity::Ref{_Entity}, + datatype::CaosDB.Constants.DATATYPE._DATATYPE, + collection::Union{CaosDB.Constants.COLLECTION._COLLECTION, Nothing} + ) + +Set the datatype of the given `entity` object to a reference to the given atomic +`datatype`. Only possible if the role of the entity is "PROPERTY". Specify +whether the datatype is a list by specifying a `collection`. If none is given, a +scalar datatype is set. +""" +function set_datatype( + entity::Ref{_Entity}, + datatype::CaosDB.Constants.DATATYPE._DATATYPE, + collection::Union{CaosDB.Constants.COLLECTION._COLLECTION,Nothing} = nothing, +) + + if get_role(entity) != CaosDB.Constants.ROLE.PROPERTY + throw( + CaosDB.Exceptions.ClientException( + "Only entities with role PROPERTY can be assigned a datatype.", + ), + ) + end + + if collection == nothing + dtype_ref = create_atomic_datatype(datatype) + elseif collection == CaosDB.Constants.COLLECTION.LIST + dtype_ref = create_atomic_list_datatype(datatype) + else + throw(ArgumentError("Unkown datatype: $datatype")) + end + + err_code = ccall( + (:caosdb_entity_entity_set_datatype, CaosDB.library_name), + Cint, + (Ref{_Entity}, Ref{_DataType}), + entity, + dtype_ref, ) CaosDB.Exceptions.evaluate_return_code(err_code) end +""" + function set_datatype(entity::Ref{_Entity}, datatype::Tuple{Any, Any}) + +Convenience wrapper for the `set_datatype` functions s.th. expressions like +`set_datatype(entity_a, get_datatype(entity_b))` work. +""" +function set_datatype(entity::Ref{_Entity}, datatype::Tuple{Any,Any}) + set_datatype(entity, datatype[1], datatype[2]) +end """ function set_datatype( property::Ref{_Property}, - datatype::AbstractString; - is_list::Bool = false, - is_reference::Bool = false, + datatype::AbstractString, + collection::Union{CaosDB.Constants.COLLECTION._COLLECTION, Nothing} ) -Set the datatype of the given `property` object to the given -`datatype` name. Specify whether it is a reference or a list with the -optional `is_list` and `is_reference` keyword arguments. If the -datatype is not a reference, it is checked against the Atomic -Datatypes known to CaosDB and an exception is thrown if it is not -known. +Set the datatype of the given `property` object to a reference to the given +`datatype` name. Specify whether the datatype is a list by specifying a +`collection`. If none is given, a scalar datatype is set. """ function set_datatype( property::Ref{_Property}, - datatype::AbstractString; - is_list::Bool = false, - is_reference::Bool = false, + datatype::AbstractString, + collection::Union{CaosDB.Constants.COLLECTION._COLLECTION,Nothing} = nothing, ) + if collection == nothing + dtype_ref = create_reference_datatype(datatype) + elseif collection == CaosDB.Constants.COLLECTION.LIST + dtype_ref = create_reference_list_datatype(datatype) + else + throw(ArgumentError("Unkown datatype: $datatype")) + end + err_code = ccall( (:caosdb_entity_property_set_datatype, CaosDB.library_name), Cint, - (Ref{_Property}, Cstring, Bool, Bool), + (Ref{_Property}, Ref{_DataType}), property, - datatype, - is_reference, - is_list, + dtype_ref, + ) + + CaosDB.Exceptions.evaluate_return_code(err_code) +end + +""" + function set_datatype( + property::Ref{_Property}, + datatype::CaosDB.Constants.DATATYPE._DATATYPE, + collection::Union{CaosDB.Constants.COLLECTION._COLLECTION, Nothing} + ) + +Set the datatype of the given `property` object to a reference to the given +atomic `datatype`. Specify whether the datatype is a list by specifying a +`collection`. If none is given, a scalar datatype is set. +""" +function set_datatype( + property::Ref{_Property}, + datatype::CaosDB.Constants.DATATYPE._DATATYPE, + collection::Union{CaosDB.Constants.COLLECTION._COLLECTION,Nothing} = nothing, +) + + if collection == nothing + dtype_ref = create_atomic_datatype(datatype) + elseif collection == CaosDB.Constants.COLLECTION.LIST + dtype_ref = create_atomic_list_datatype(datatype) + else + throw(ArgumentError("Unkown datatype: $datatype")) + end + + err_code = ccall( + (:caosdb_entity_property_set_datatype, CaosDB.library_name), + Cint, + (Ref{_Property}, Ref{_DataType}), + property, + dtype_ref, ) CaosDB.Exceptions.evaluate_return_code(err_code) end +""" + function set_datatype(property::Ref{_Property}, datatype::Tuple{Any, Any}) + +Convenience wrapper for the `set_datatype` functions s.th. expressions like +`set_datatype(property_a, get_datatype(property_b))` work. +""" +function set_datatype(property::Ref{_Property}, datatype::Tuple{Any,Any}) + set_datatype(property, datatype[1], datatype[2]) +end + """ function set_unit(entity::Ref{_Entity}, unit::AbstractString) @@ -1920,7 +2116,6 @@ function set_unit(entity::Ref{_Entity}, unit::AbstractString) CaosDB.Exceptions.evaluate_return_code(err_code) end - """ function set_unit(property::Ref{_Property}, unit::AbstractString) @@ -1938,8 +2133,6 @@ function set_unit(property::Ref{_Property}, unit::AbstractString) CaosDB.Exceptions.evaluate_return_code(err_code) end -# TODO(henrik, daniel) There is no check for the correct datatype -# here. Should we add this? """ function set_value( entity::Ref{_Entity}, @@ -1956,7 +2149,7 @@ function set_value( value::Union{AbstractString,Number,Bool,Vector{T}}, ) where {T<:Union{AbstractString,Number,Bool}} - if get_role(entity) != "PROPERTY" + if get_role(entity) != CaosDB.Constants.ROLE.PROPERTY throw( CaosDB.Exceptions.ClientException( "Only entites with role PROPERTY may be assigned a value.", @@ -1964,80 +2157,15 @@ function set_value( ) end - in_type = typeof(value) - if in_type <: AbstractString - err_code = ccall( - (:caosdb_entity_entity_set_string_value, CaosDB.library_name), - Cint, - (Ref{_Entity}, Cstring), - entity, - value, - ) - elseif in_type <: Bool - err_code = ccall( - (:caosdb_entity_entity_set_boolean_value, CaosDB.library_name), - Cint, - (Ref{_Entity}, Bool), - entity, - value, - ) - elseif in_type <: Integer - err_code = ccall( - (:caosdb_entity_entity_set_int_value, CaosDB.library_name), - Cint, - (Ref{_Entity}, Clong), - entity, - Clong(value), - ) - elseif in_type <: Number - err_code = ccall( - (:caosdb_entity_entity_set_double_value, CaosDB.library_name), - Cint, - (Ref{_Entity}, Cdouble), - entity, - Cdouble(value), - ) - else - # Type is a vector now - vec_length = Cint(length(value)) - if in_type <: Vector{T} where {T<:AbstractString} - err_code = ccall( - (:caosdb_entity_entity_set_string_list_value, CaosDB.library_name), - Cint, - (Ref{_Entity}, Ptr{Ptr{Cchar}}, Cint), - entity, - value, - vec_length, - ) - elseif in_type <: Vector{T} where {T<:Bool} - err_code = ccall( - (:caosdb_entity_entity_set_boolean_list_value, CaosDB.library_name), - Cint, - (Ref{_Entity}, Ptr{Bool}, Cint), - entity, - value, - vec_length, - ) - elseif in_type <: Vector{T} where {T<:Integer} - err_code = ccall( - (:caosdb_entity_entity_set_int_list_value, CaosDB.library_name), - Cint, - (Ref{_Entity}, Ptr{Clong}, Cint), - entity, - Vector{Clong}(value), - vec_length, - ) - elseif in_type <: Vector{T} where {T<:Number} - err_code = ccall( - (:caosdb_entity_entity_set_double_list_value, CaosDB.library_name), - Cint, - (Ref{_Entity}, Ptr{Cdouble}, Cint), - entity, - Vector{Cdouble}(value), - vec_length, - ) - end - end + value_ref = create_value(value) + + err_code = ccall( + (:caosdb_entity_entity_set_value, CaosDB.library_name), + Cint, + (Ref{_Entity}, Ref{_Value}), + entity, + value_ref, + ) CaosDB.Exceptions.evaluate_return_code(err_code) end @@ -2053,96 +2181,37 @@ function set_value( value::Union{AbstractString,Number,Bool,Vector{T}}, ) where {T<:Union{AbstractString,Number,Bool}} - in_type = typeof(value) - if in_type <: AbstractString - err_code = ccall( - (:caosdb_entity_property_set_string_value, CaosDB.library_name), - Cint, - (Ref{_Property}, Cstring), - property, - value, - ) - elseif in_type <: Bool - err_code = ccall( - (:caosdb_entity_property_set_boolean_value, CaosDB.library_name), - Cint, - (Ref{_Property}, Bool), - property, - value, - ) - elseif in_type <: Integer - err_code = ccall( - (:caosdb_entity_property_set_int_value, CaosDB.library_name), - Cint, - (Ref{_Property}, Clong), - property, - Clong(value), - ) - elseif in_type <: Number - err_code = ccall( - (:caosdb_entity_property_set_double_value, CaosDB.library_name), - Cint, - (Ref{_Property}, Cdouble), - property, - Cdouble(value), - ) - else - # Type is a vector now - vec_length = Cint(length(value)) - if in_type <: Vector{T} where {T<:AbstractString} - err_code = ccall( - (:caosdb_entity_property_set_string_list_value, CaosDB.library_name), - Cint, - (Ref{_Property}, Ptr{Ptr{Cchar}}, Cint), - property, - value, - vec_length, - ) - elseif in_type <: Vector{T} where {T<:Bool} - err_code = ccall( - (:caosdb_entity_property_set_boolean_list_value, CaosDB.library_name), - Cint, - (Ref{_Property}, Ptr{Bool}, Cint), - property, - value, - vec_length, - ) - elseif in_type <: Vector{T} where {T<:Integer} - err_code = ccall( - (:caosdb_entity_property_set_int_list_value, CaosDB.library_name), - Cint, - (Ref{_Property}, Ptr{Clong}, Cint), - property, - Vector{Clong}(value), - vec_length, - ) - elseif in_type <: Vector{T} where {T<:Number} - err_code = ccall( - (:caosdb_entity_property_set_double_list_value, CaosDB.library_name), - Cint, - (Ref{_Property}, Ptr{Cdouble}, Cint), - property, - Vector{Cdouble}(value), - vec_length, - ) - end - end + value_ref = create_value(value) + + err_code = ccall( + (:caosdb_entity_property_set_value, CaosDB.library_name), + Cint, + (Ref{_Property}, Ref{_Value}), + property, + value_ref, + ) CaosDB.Exceptions.evaluate_return_code(err_code) end """ - function set_importance(property::Ref{_Property}, importance::AbstractString) + function set_importance( + property::Ref{_Property}, + importance::CaosDB.Constants.IMPORTANCE._IMPORTANCE + ) Set the importance of the given `property` object. """ -function set_importance(property::Ref{_Property}, importance::AbstractString) +function set_importance( + property::Ref{_Property}, + importance::CaosDB.Constants.IMPORTANCE._IMPORTANCE, +) err_code = ccall( (:caosdb_entity_property_set_importance, CaosDB.library_name), Cint, (Ref{_Property}, Cstring), property, - importance, + string(importance), ) CaosDB.Exceptions.evaluate_return_code(err_code) diff --git a/test/runtests.jl b/test/runtests.jl index c2ae2face7fdc82805eab16055069ae4a33c5b04..e0d445d9d08367a7f9978ec02a0a9225bed6ea44 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -102,12 +102,13 @@ using CaosDB rt_with_name = CaosDB.Entity.create_recordtype("TestRT") @test CaosDB.Entity.get_name(rt_with_name) == "TestRT" - @test CaosDB.Entity.get_role(rt_with_name) == "RECORD_TYPE" + @test CaosDB.Entity.get_role(rt_with_name) == CaosDB.Constants.ROLE.RECORD_TYPE prop_with_name_and_unit = CaosDB.Entity.create_property_entity(name = "TestProp", unit = "m") @test CaosDB.Entity.get_name(prop_with_name_and_unit) == "TestProp" - @test CaosDB.Entity.get_role(prop_with_name_and_unit) == "PROPERTY" + @test CaosDB.Entity.get_role(prop_with_name_and_unit) == + CaosDB.Constants.ROLE.PROPERTY @test CaosDB.Entity.get_unit(prop_with_name_and_unit) == "m" rec_with_parent_and_props = CaosDB.Entity.create_record("TestRec") @@ -119,7 +120,7 @@ using CaosDB # cannot set the datatype of a record @test_throws CaosDB.Exceptions.ClientException CaosDB.Entity.set_datatype( rec_with_parent_and_props, - "INTEGER", + CaosDB.Constants.DATATYPE.INTEGER, ) par1 = CaosDB.Entity.create_parent(name = "Parent1") @@ -145,22 +146,20 @@ using CaosDB prop1 = CaosDB.Entity.create_property(name = "Property1", value = "2") prop2 = CaosDB.Entity.create_property(id = "id_of_property_2") - CaosDB.Entity.set_datatype(prop2, "TEXT") + CaosDB.Entity.set_datatype(prop2, CaosDB.Constants.DATATYPE.TEXT) prop3 = CaosDB.Entity.create_property(name = "Property3") CaosDB.Entity.append_properties(rec_with_parent_and_props, [prop1, prop2, prop3]) @test length(CaosDB.Entity.get_properties(rec_with_parent_and_props)) == 3 - # properties can be accessed as a list - # TODO(florian) Fix this once we have a reasonable treatment of value objects in Extern C. - @test_broken CaosDB.Entity.get_value( + # properties can be accessed as a list + @test CaosDB.Entity.get_value( CaosDB.Entity.get_properties(rec_with_parent_and_props)[1], ) == "2" - type, is_ref, is_list = CaosDB.Entity.get_datatype( + type, collection = CaosDB.Entity.get_datatype( CaosDB.Entity.get_properties(rec_with_parent_and_props)[2], ) - @test type == "TEXT" - @test is_ref == false - @test is_list == false + @test type == CaosDB.Constants.DATATYPE.TEXT + @test collection == nothing @test CaosDB.Entity.get_id( CaosDB.Entity.get_properties(rec_with_parent_and_props)[2], ) == "id_of_property_2" @@ -177,7 +176,7 @@ using CaosDB local_path = string(pwd(), "/", "caosdbfilefortests.txt"), remote_path = "/remote_path/file.txt", ) - @test CaosDB.Entity.get_role(file_ent) == "FILE" + @test CaosDB.Entity.get_role(file_ent) == CaosDB.Constants.ROLE.FILE @test CaosDB.Entity.get_name(file_ent) == "TestFile" # local file not found rm(string(pwd(), "/", "caosdbfilefortests.txt")) @@ -191,21 +190,16 @@ using CaosDB @testset "Property values and datatypes" begin @testset "Entity properties" begin int_prop = - CaosDB.Entity.create_property_entity(name = "IntProp", datatype = "INTEGER") - double_prop = CaosDB.Entity.create_property_entity( - name = "DoubleProp", - datatype = "DOUBLE", - ) - bool_prop = CaosDB.Entity.create_property_entity( - name = "BoolProp", - datatype = "BOOLEAN", - ) + CaosDB.Entity.create_property_entity(name = "IntProp", datatype = INTEGER) + double_prop = + CaosDB.Entity.create_property_entity(name = "DoubleProp", datatype = DOUBLE) + bool_prop = + CaosDB.Entity.create_property_entity(name = "BoolProp", datatype = BOOLEAN) string_prop = - CaosDB.Entity.create_property_entity(name = "StringProp", datatype = "TEXT") + CaosDB.Entity.create_property_entity(name = "StringProp", datatype = TEXT) ref_prop = CaosDB.Entity.create_property_entity( name = "RefProp", datatype = "MyRefType", - is_reference = true, ) CaosDB.Entity.set_value(int_prop, 123) CaosDB.Entity.set_value(double_prop, 10.246) @@ -222,38 +216,37 @@ using CaosDB @test isa(CaosDB.Entity.get_value(bool_prop), Bool) @test isa(CaosDB.Entity.get_value(string_prop), String) @test isa(CaosDB.Entity.get_value(ref_prop), String) - @test CaosDB.Entity.get_datatype(int_prop) == ("INTEGER", false, false) - @test CaosDB.Entity.get_datatype(double_prop) == ("DOUBLE", false, false) - @test CaosDB.Entity.get_datatype(bool_prop) == ("BOOLEAN", false, false) - @test CaosDB.Entity.get_datatype(string_prop) == ("TEXT", false, false) - @test CaosDB.Entity.get_datatype(ref_prop) == ("MyRefType", true, false) + @test CaosDB.Entity.get_datatype(int_prop) == (INTEGER, nothing) + @test CaosDB.Entity.get_datatype(double_prop) == (DOUBLE, nothing) + @test CaosDB.Entity.get_datatype(bool_prop) == (BOOLEAN, nothing) + @test CaosDB.Entity.get_datatype(string_prop) == (TEXT, nothing) + @test CaosDB.Entity.get_datatype(ref_prop) == ("MyRefType", nothing) """ Test lists """ int_list_prop = CaosDB.Entity.create_property_entity( name = "IntProp", - datatype = "INTEGER", - is_list = true, + datatype = INTEGER, + collection = LIST, ) double_list_prop = CaosDB.Entity.create_property_entity( name = "DoubleProp", - datatype = "DOUBLE", - is_list = true, + datatype = DOUBLE, + collection = LIST, ) bool_list_prop = CaosDB.Entity.create_property_entity( name = "BoolProp", - datatype = "BOOLEAN", - is_list = true, + datatype = BOOLEAN, + collection = LIST, ) string_list_prop = CaosDB.Entity.create_property_entity( name = "StringProp", - datatype = "TEXT", - is_list = true, + datatype = TEXT, + collection = LIST, ) ref_list_prop = CaosDB.Entity.create_property_entity( name = "RefListProp", datatype = "MyRefType", - is_list = true, - is_reference = true, + collection = LIST, ) CaosDB.Entity.set_value(int_list_prop, [123, 456]) CaosDB.Entity.set_value(double_list_prop, [10.246, 3.14]) @@ -270,25 +263,41 @@ using CaosDB @test isa(CaosDB.Entity.get_value(bool_list_prop), Vector{Bool}) @test isa(CaosDB.Entity.get_value(string_list_prop), Vector{String}) @test isa(CaosDB.Entity.get_value(ref_list_prop), Vector{String}) - @test CaosDB.Entity.get_datatype(int_list_prop) == ("INTEGER", false, true) - @test CaosDB.Entity.get_datatype(double_list_prop) == ("DOUBLE", false, true) - @test CaosDB.Entity.get_datatype(bool_list_prop) == ("BOOLEAN", false, true) - @test CaosDB.Entity.get_datatype(string_list_prop) == ("TEXT", false, true) - @test CaosDB.Entity.get_datatype(ref_list_prop) == ("MyRefType", true, true) + @test CaosDB.Entity.get_datatype(int_list_prop) == (INTEGER, LIST) + @test CaosDB.Entity.get_datatype(double_list_prop) == (DOUBLE, LIST) + @test CaosDB.Entity.get_datatype(bool_list_prop) == (BOOLEAN, LIST) + @test CaosDB.Entity.get_datatype(string_list_prop) == (TEXT, LIST) + @test CaosDB.Entity.get_datatype(ref_list_prop) == ("MyRefType", LIST) + + # Check copying of values and datatypes + copied_prop = CaosDB.Entity.create_property_entity(name = "CopiedProp") + set_datatype(copied_prop, get_datatype(int_list_prop)) + set_value(copied_prop, get_value(int_list_prop)) + @test get_datatype(copied_prop) == get_datatype(int_list_prop) + @test get_value(copied_prop) == get_value(int_list_prop) + set_datatype(copied_prop, get_datatype(double_prop)) + set_value(copied_prop, get_value(double_prop)) + @test get_datatype(copied_prop) == get_datatype(double_prop) + @test get_value(copied_prop) == get_value(double_prop) + set_datatype(copied_prop, get_datatype(ref_list_prop)) + set_value(copied_prop, get_value(ref_list_prop)) + @test get_datatype(copied_prop) == get_datatype(ref_list_prop) + # TODO(fspreck) Re-try once + # https://gitlab.indiscale.com/caosdb/src/caosdb-cpplib/-/issues/24 + # has been fixed. + @test_broken get_value(copied_prop) == get_value(ref_list_prop) + end + @testset "Property properties" begin - int_prop = CaosDB.Entity.create_property(name = "IntProp", datatype = "INTEGER") + int_prop = CaosDB.Entity.create_property(name = "IntProp", datatype = INTEGER) double_prop = - CaosDB.Entity.create_property(name = "DoubleProp", datatype = "DOUBLE") - bool_prop = - CaosDB.Entity.create_property(name = "BoolProp", datatype = "BOOLEAN") + CaosDB.Entity.create_property(name = "DoubleProp", datatype = DOUBLE) + bool_prop = CaosDB.Entity.create_property(name = "BoolProp", datatype = BOOLEAN) string_prop = - CaosDB.Entity.create_property(name = "StringProp", datatype = "TEXT") - ref_prop = CaosDB.Entity.create_property( - name = "RefProp", - datatype = "MyRefType", - is_reference = true, - ) + CaosDB.Entity.create_property(name = "StringProp", datatype = TEXT) + ref_prop = + CaosDB.Entity.create_property(name = "RefProp", datatype = "MyRefType") CaosDB.Entity.set_value(int_prop, 123) CaosDB.Entity.set_value(double_prop, 10.246) CaosDB.Entity.set_value(bool_prop, true) @@ -304,38 +313,37 @@ using CaosDB @test isa(CaosDB.Entity.get_value(bool_prop), Bool) @test isa(CaosDB.Entity.get_value(string_prop), String) @test isa(CaosDB.Entity.get_value(ref_prop), String) - @test CaosDB.Entity.get_datatype(int_prop) == ("INTEGER", false, false) - @test CaosDB.Entity.get_datatype(double_prop) == ("DOUBLE", false, false) - @test CaosDB.Entity.get_datatype(bool_prop) == ("BOOLEAN", false, false) - @test CaosDB.Entity.get_datatype(string_prop) == ("TEXT", false, false) - @test CaosDB.Entity.get_datatype(ref_prop) == ("MyRefType", true, false) + @test CaosDB.Entity.get_datatype(int_prop) == (INTEGER, nothing) + @test CaosDB.Entity.get_datatype(double_prop) == (DOUBLE, nothing) + @test CaosDB.Entity.get_datatype(bool_prop) == (BOOLEAN, nothing) + @test CaosDB.Entity.get_datatype(string_prop) == (TEXT, nothing) + @test CaosDB.Entity.get_datatype(ref_prop) == ("MyRefType", nothing) """ Test lists """ int_list_prop = CaosDB.Entity.create_property( name = "IntProp", - datatype = "INTEGER", - is_list = true, + datatype = INTEGER, + collection = LIST, ) double_list_prop = CaosDB.Entity.create_property( name = "DoubleProp", - datatype = "DOUBLE", - is_list = true, + datatype = DOUBLE, + collection = LIST, ) bool_list_prop = CaosDB.Entity.create_property( name = "BoolProp", - datatype = "BOOLEAN", - is_list = true, + datatype = BOOLEAN, + collection = LIST, ) string_list_prop = CaosDB.Entity.create_property( name = "StringProp", - datatype = "TEXT", - is_list = true, + datatype = TEXT, + collection = LIST, ) ref_list_prop = CaosDB.Entity.create_property( name = "RefListProp", datatype = "MyRefType", - is_list = true, - is_reference = true, + collection = LIST, ) CaosDB.Entity.set_value(int_list_prop, [123, 456]) CaosDB.Entity.set_value(double_list_prop, [10.246, 3.14]) @@ -352,11 +360,11 @@ using CaosDB @test isa(CaosDB.Entity.get_value(bool_list_prop), Vector{Bool}) @test isa(CaosDB.Entity.get_value(string_list_prop), Vector{String}) @test isa(CaosDB.Entity.get_value(ref_list_prop), Vector{String}) - @test CaosDB.Entity.get_datatype(int_list_prop) == ("INTEGER", false, true) - @test CaosDB.Entity.get_datatype(double_list_prop) == ("DOUBLE", false, true) - @test CaosDB.Entity.get_datatype(bool_list_prop) == ("BOOLEAN", false, true) - @test CaosDB.Entity.get_datatype(string_list_prop) == ("TEXT", false, true) - @test CaosDB.Entity.get_datatype(ref_list_prop) == ("MyRefType", true, true) + @test CaosDB.Entity.get_datatype(int_list_prop) == (INTEGER, LIST) + @test CaosDB.Entity.get_datatype(double_list_prop) == (DOUBLE, LIST) + @test CaosDB.Entity.get_datatype(bool_list_prop) == (BOOLEAN, LIST) + @test CaosDB.Entity.get_datatype(string_list_prop) == (TEXT, LIST) + @test CaosDB.Entity.get_datatype(ref_list_prop) == ("MyRefType", LIST) end end end