Skip to content

Commit

Permalink
Add hasType method and change addNode method of openminds.Collection (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
ehennestad committed Sep 6, 2024
1 parent f4260f1 commit 739a641
Showing 1 changed file with 83 additions and 25 deletions.
108 changes: 83 additions & 25 deletions code/+openminds/@Collection/Collection.m
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
% For more details on how to create a new Collection:
% See also openminds.Collection/Collection

% Todo: Validation.
% Todo: Validation.
% - Linked subject states should have same subject


Expand All @@ -51,10 +51,14 @@
end

properties (SetAccess = protected)
% Nodes - Dictionary storing instances as values with identifiers
% as keys
Nodes (1,1) dictionary
end

properties (SetAccess = protected, Hidden)
% TypeMap - Keeps a map/dictionary of types and instance ids to
% efficiently extract instances of a specific type.
TypeMap (1,1) dictionary
end

Expand Down Expand Up @@ -97,7 +101,6 @@
options.Description (1,1) string = ""
end


% Initialize nodes
obj.Nodes = dictionary;
obj.TypeMap = dictionary;
Expand Down Expand Up @@ -183,21 +186,51 @@ function remove(obj, instance)
end

if isConfigured(obj.Nodes) && isKey(obj.Nodes, instanceId)
try
instanceType = class( obj.Nodes{instanceId} );
catch % < R2023a
instance = obj.Nodes(instanceId);
instanceType = class( instance{1} );
end
obj.Nodes(instanceId) = [];

allIds = obj.TypeMap(instanceType);
obj.TypeMap(instanceType) = { setdiff( allIds{1}, instanceId ) };
else
error('Instance with id %s is not found in collection')
end
end

function instance = get(obj, nodeKey)
instance = obj.Nodes{nodeKey};
if isMATLABReleaseOlderThan("R2023b")
instance = obj.Nodes(nodeKey);
instance = instance{1};
else
instance = obj.Nodes{nodeKey};
end
end

function instances = list(obj, type, propertyName, propertyValue)
function tf = hasType(obj, type)
arguments
obj
type (1,1) string
end

tf = false;

if ~isConfigured(obj.Nodes)
return
end

typeKeys = obj.TypeMap.keys;
tf = any( endsWith(typeKeys, "."+type) ); %i.e ".Person"
end

function instances = list(obj, type, propertyName, propertyValue)
arguments
obj
type (1,1) openminds.enum.Types
end
arguments (Repeating)
propertyName (1,1) string
propertyValue
Expand All @@ -209,20 +242,9 @@ function remove(obj, instance)
return
end

typeKeys = obj.TypeMap.keys;
isMatch = endsWith(typeKeys, "."+type); %i.e ".Person"
if any(isMatch)
if isMATLABReleaseOlderThan("R2023b")
keys = string( obj.TypeMap(typeKeys(isMatch)) );
else
keys = obj.TypeMap{typeKeys(isMatch)};
end
else
return
end

instances = obj.Nodes(keys);
instances = [instances{:}];
instanceKeys = obj.getInstanceKeysForType(type);
instances = obj.Nodes(instanceKeys);
instances = [instances{:}]; % Create non-cell array

% Filter by property values:
for i = 1:numel(propertyName)
Expand Down Expand Up @@ -332,28 +354,28 @@ function load(obj, filePath)%, options)
end
end
end

end

methods (Static) % Methods in separate files

outputPaths = saveInstances(instance, filePath, options)

instances = loadInstances(filePath)

end

methods (Access = protected)

%Add an instance to the Node container.
function addNode(obj, instance, options)
function wasAdded = addNode(obj, instance, options)

arguments
obj (1,1) openminds.Collection
instance (1,1) openminds.abstract.Schema
options.AddSubNodesOnly = false
options.AbortIfNodeExists = true;
end

wasAdded = false;

if isempty(instance.id)
instance.id = obj.getBlankNodeIdentifier();
Expand All @@ -375,8 +397,9 @@ function addNode(obj, instance, options)

if ~options.AddSubNodesOnly
obj.Nodes(instance.id) = {instance};

% Todo: Separate method
wasAdded = true;

% Add to TypeMap: Todo: Separate method
instanceType = class(instance);
if isConfigured(obj.TypeMap) && isKey(obj.TypeMap, instanceType)
if isMATLABReleaseOlderThan("R2023b")
Expand Down Expand Up @@ -409,12 +432,47 @@ function addSubNodes(obj, instance)
obj.addNode(embeddedTypes{i}, 'AddSubNodesOnly', true);
end
end

function identifier = getBlankNodeIdentifier(obj)
fmt = '_:%06d';
identifier = length(obj) + 1;
identifier = sprintf(fmt, identifier);
end
end

methods (Access = private)
function instanceKeys = getInstanceKeysForType(obj, instanceType)
% getInstanceKeysForType Get all ids for instances of a given type

typeKeys = obj.TypeMap.keys;

isMatch = strcmp(typeKeys, instanceType.ClassName);
if any(isMatch)
if isMATLABReleaseOlderThan("R2023b")
instanceKeys = string( obj.TypeMap(typeKeys(isMatch)) );
else
instanceKeys = obj.TypeMap{typeKeys(isMatch)};
end
else
instanceKeys = {};
return
end

existingKeys = obj.Nodes.keys();

% Sanity check, make sure all keys exist in Nodes dictionary
assert( all( ismember( instanceKeys, existingKeys ) ), ...
'TypeMap has too many keys' )
end

function refreshTypeKeys(obj, instanceType)
% Utility method during development. This should ultimately not be needed.

allIds = obj.TypeMap(instanceType.ClassName);
existingKeys = obj.Nodes.keys();

allIds = intersect( existingKeys, allIds{1} );
obj.TypeMap(instanceType.ClassName) = {allIds};
end
end
end

0 comments on commit 739a641

Please sign in to comment.