diff --git a/src/Entity.jl b/src/Entity.jl index 419187468566f37e8403d452dd04425311677b82..a507886ecab1a358f19286ffda9c6a7d0cd855a0 100644 --- a/src/Entity.jl +++ b/src/Entity.jl @@ -198,7 +198,7 @@ mutable struct _DataType wrapped_datatype::Ptr{Cvoid} _deletable::Bool - function _DatatType(managed_by_julia::Bool = false) + function _DataType(managed_by_julia::Bool = false) datatype = new() datatype._deletable = false @@ -470,12 +470,12 @@ function create_parent(; name::AbstractString = "", id::AbstractString = "") end """ - function create_atomic_datatype(name::AbstractString) + 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::AbstractString) +function create_atomic_datatype(name::CaosDB.Constants.DATATYPE._DATATYPE) datatype = Ref{_DataType}(_DataType(true)) @@ -484,7 +484,7 @@ function create_atomic_datatype(name::AbstractString) Cint, (Ref{_DataType}, Cstring), datatype, - name, + string(name), ) CaosDB.Exceptions.evaluate_return_code(err_code) @@ -516,12 +516,12 @@ function create_reference_datatype(name::AbstractString) end """ - function create_atomic_list_datatype(name::AbstractString) + 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::AbstractString) +function create_atomic_list_datatype(name::CaosDB.Constants.DATATYPE._DATATYPE) datatype = Ref{_DataType}(_DataType(true)) @@ -530,7 +530,7 @@ function create_atomic_list_datatype(name::AbstractString) Cint, (Ref{_DataType}, Cstring), datatype, - name, + string(name), ) CaosDB.Exceptions.evaluate_return_code(err_code) @@ -539,12 +539,12 @@ function create_atomic_list_datatype(name::AbstractString) end """ - function create_list_of_reference_datatype(name::AbstractString) + function create_reference_list_datatype(name::AbstractString) Create and return a DataType object which is a list of references specified by `name`. """ -function create_list_of_reference_datatype(name::AbstractString) +function create_reference_list_datatype(name::AbstractString) datatype = Ref{_DataType}(_DataType(true)) @@ -893,33 +893,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 """ @@ -930,23 +996,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 """ @@ -1862,28 +1923,22 @@ 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) != CaosDB.Constants.ROLE.PROPERTY @@ -1894,54 +1949,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) @@ -1959,7 +2121,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)