Skip to content

Commit

Permalink
Merge pull request #495 from NeurodataWithoutBorders/494-check-for-mu…
Browse files Browse the repository at this point in the history
…ltiple-constrained

494 check for multiple constrained
  • Loading branch information
lawrence-mbf authored Feb 28, 2023
2 parents 16a5411 + 9382c12 commit 5492118
Show file tree
Hide file tree
Showing 13 changed files with 420 additions and 273 deletions.
6 changes: 6 additions & 0 deletions +file/+interface/HasProps.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
classdef HasProps < matlab.mixin.Heterogeneous
methods (Abstract)
props = getProps(obj);
end
end

3 changes: 2 additions & 1 deletion +file/Dataset.m
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
classdef Dataset
classdef Dataset < file.interface.HasProps
properties
name;
doc;
Expand Down Expand Up @@ -108,6 +108,7 @@
obj.linkable = ~isempty(obj.name) && hasNoAttributes;
end

%% HasProps
function props = getProps(obj)
props = containers.Map;

Expand Down
66 changes: 32 additions & 34 deletions +file/Group.m
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
classdef Group
classdef Group < file.interface.HasProps
properties
doc;
name;
Expand Down Expand Up @@ -139,8 +139,9 @@
isempty(obj.attributes);
end

function Prop_Map = getProps(obj)
Prop_Map = containers.Map;
%% HasProps
function PropertyMap = getProps(obj)
PropertyMap = containers.Map;
%typed + constrained
%should never happen

Expand All @@ -161,27 +162,27 @@
attr_names = strcat(SubData.name, '_', attr_names);
Sub_Attribute_Map =...
containers.Map(attr_names, num2cell(SubData.attributes));
Prop_Map = [Prop_Map; Sub_Attribute_Map];
PropertyMap = [PropertyMap; Sub_Attribute_Map];
end
Prop_Map(SubData.name) = SubData;
PropertyMap(SubData.name) = SubData;
else
if isempty(SubData.name)
Prop_Map(lower(SubData.type)) = SubData;
PropertyMap(lower(SubData.type)) = SubData;
else
Prop_Map(SubData.name) = SubData;
PropertyMap(SubData.name) = SubData;
end
end
end

%attributes
if ~isempty(obj.attributes)
Prop_Map = [Prop_Map;...
PropertyMap = [PropertyMap;...
containers.Map({obj.attributes.name}, num2cell(obj.attributes))];
end

%links
if ~isempty(obj.links)
Prop_Map = [Prop_Map;...
PropertyMap = [PropertyMap;...
containers.Map({obj.links.name}, num2cell(obj.links))];
end

Expand All @@ -200,49 +201,46 @@
%if untyped, check if elided
% if elided, add to prefix and check all subgroups, attributes and datasets.
% otherwise, call getprops and assign to its name.
Sub_Group = obj.subgroups(i);
groupName = Sub_Group.name;
groupType = Sub_Group.type;
SubGroup = obj.subgroups(i);
groupName = SubGroup.name;
groupType = SubGroup.type;
if ~isempty(groupType)
if isempty(groupName)
Prop_Map(lower(groupType)) = Sub_Group;
PropertyMap(lower(groupType)) = SubGroup;
else
Prop_Map(groupName) = Sub_Group;
PropertyMap(groupName) = SubGroup;
end
continue;
end

if ~Sub_Group.elide
Prop_Map(groupName) = Sub_Group;
if ~SubGroup.elide
PropertyMap(groupName) = SubGroup;
continue;
end
Descendant_Map = Sub_Group.getProps;
descendant_names = keys(Descendant_Map);
for iSubGroup = 1:length(descendant_names)
descendantName = descendant_names{iSubGroup};
Descendant = Descendant_Map(descendantName);

DescendantMap = SubGroup.getProps();
descendantNames = keys(DescendantMap);
for iSubGroup = 1:length(descendantNames)
descendantName = descendantNames{iSubGroup};
Descendant = DescendantMap(descendantName);
% hoist constrained sets to the current
% subname.
isPossiblyConstrained =...
isa(Descendant, 'file.Group')...
|| isa(Descendant, 'file.Dataset');
isConstrained = isPossiblyConstrained...
&& strcmpi(descendantName, Descendant.type)...
&& Descendant.isConstrainedSet;
&& all(strcmpi(descendantName, {Descendant.type}))...
&& all(Descendant.isConstrainedSet);
if isConstrained
propName = groupName;
if isKey(PropertyMap, groupName)
SetType = PropertyMap(groupName);
else
SetType = [];
end
PropertyMap(groupName) = [SetType, Descendant];
else
propName = [groupName '_' descendantName];
end

if isKey(Prop_Map, propName) && ~isConstrained
warning(['Generic group `%s` is currently unsupported '...
'in MatNwb and is ignored.'], propName);
continue;
PropertyMap([groupName, '_', descendantName]) = Descendant;
end

Prop_Map(propName) = Descendant_Map(descendantName);
end
end
end
Expand Down
12 changes: 11 additions & 1 deletion +file/fillClass.m
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,18 @@
for i=1:length(allprops)
pnm = allprops{i};
prop = classprops(pnm);

isRequired = ischar(prop) || isa(prop, 'containers.Map') || isstruct(prop);
iIsPropertyRequired = false;
if isa(prop, 'file.interface.HasProps')
iIsPropertyRequired = false(size(prop));
for iProp = 1:length(prop)
p = prop(iProp);
iIsPropertyRequired(iProp) = p.required;
end
end

if ischar(prop) || isa(prop, 'containers.Map') || isstruct(prop) || prop.required
if isRequired || all(iIsPropertyRequired)
required = [required {pnm}];
else
optional = [optional {pnm}];
Expand Down
43 changes: 33 additions & 10 deletions +file/fillConstructor.m
Original file line number Diff line number Diff line change
Expand Up @@ -62,22 +62,40 @@
nm = names{i};
prop = props(nm);

if isa(prop, 'file.Group') || isa(prop, 'file.Dataset')
dynamicConstrained(i) = prop.isConstrainedSet && strcmpi(nm, prop.type);
anon(i) = ~prop.isConstrainedSet && isempty(prop.name);
if isa(prop, 'file.Attribute')
isattr(i) = true;
continue;
end

if isa(prop, 'file.interface.HasProps')
isDynamicConstrained = false(size(prop));
isAnon = false(size(prop));
hasType = false(size(prop));
typeNames = cell(size(prop));
for iProp = 1:length(prop)
p = prop(iProp);
isDynamicConstrained(iProp) = p.isConstrainedSet && strcmpi(nm, p.type);
isAnon(iProp) = ~p.isConstrainedSet && isempty(p.name);
hasType(iProp) = ~isempty(p.type);
typeNames{iProp} = p.type;
end
dynamicConstrained(i) = all(isDynamicConstrained);
anon(i) = all(isAnon);

if ~isempty(prop.type)
if all(hasType)
varnames{i} = nm;
typeNameCell = cell(size(prop));
try
typenames{i} = namespace.getFullClassName(prop.type);
for iProp = 1:length(prop)
typeNameCell{iProp} = namespace.getFullClassName(prop(iProp).type);
end
catch ME
if ~strcmp(ME.identifier, 'NWB:Scheme:Namespace:NotFound')
rethrow(ME);
end
end
typenames{i} = misc.cellPrettyPrint(typeNameCell);
end
elseif isa(prop, 'file.Attribute')
isattr(i) = true;
end
end

Expand Down Expand Up @@ -132,9 +150,14 @@
defaults = cell(size(names));
for i=1:length(names)
prop = props(names{i});
if (isa(prop, 'file.Group') &&...
(prop.hasAnonData || prop.hasAnonGroups || prop.isConstrainedSet)) ||...
(isa(prop, 'file.Dataset') && prop.isConstrainedSet)
isPluralSet = isa(prop, 'file.interface.HasProps') && ~isscalar(prop);
isGroupSet = ~isPluralSet ...
&& isa(prop, 'file.Group') ...
&& (prop.hasAnonData || prop.hasAnonGroups || prop.isConstrainedSet);
isDataSet = ~isPluralSet ...
&& isa(prop, 'file.Dataset')...
&& prop.isConstrainedSet;
if isPluralSet || isGroupSet || isDataSet
defaults{i} = 'types.untyped.Set()';
else
defaults{i} = '[]';
Expand Down
25 changes: 20 additions & 5 deletions +file/fillProps.m
Original file line number Diff line number Diff line change
Expand Up @@ -71,15 +71,30 @@
error('Invalid reftype found whilst filling Constructor prop docs.');
end
typeStr = sprintf('%s Reference to %s', refTypeName, prop('target_type'));
elseif isa(prop, 'file.Dataset') && isempty(prop.type)
typeStr = getPropStr(prop.dtype);
elseif isempty(prop.type)
typeStr = 'types.untyped.Set';
elseif isa(prop, 'file.interface.HasProps')
typeStrCell = cell(size(prop));
for iProp = 1:length(typeStrCell)
anonProp = prop(iProp);
if isa(anonProp, 'file.Dataset') && isempty(anonProp.type)
typeStrCell{iProp} = getPropStr(anonProp.dtype);
elseif isempty(anonProp.type)
typeStrCell{iProp} = 'types.untyped.Set';
else
typeStrCell{iProp} = anonProp.type;
end
end
typeStr = strjoin(typeStrCell, '|');
else
typeStr = prop.type;
end

if isa(prop, 'file.Dataset') || isa(prop, 'file.Attribute') || isa(prop, 'file.Group')
if isa(prop, 'file.interface.HasProps')
propStrCell = cell(size(prop));
for iProp = 1:length(prop)
propStrCell{iProp} = prop(iProp).doc;
end
propStr = sprintf('(%s) %s', typeStr, strjoin(propStrCell, ' | '));
elseif isa(prop, 'file.Attribute')
propStr = sprintf('(%s) %s', typeStr, prop.doc);
else
propStr = typeStr;
Expand Down
Loading

0 comments on commit 5492118

Please sign in to comment.