Skip to content

Commit

Permalink
basic read without links or refs now work.
Browse files Browse the repository at this point in the history
  • Loading branch information
Lancewiu committed Apr 20, 2018
1 parent c7c5cce commit 3222f33
Show file tree
Hide file tree
Showing 12 changed files with 221 additions and 109 deletions.
29 changes: 21 additions & 8 deletions +file/fillClass.m
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
optional = {};
readonly = {};
defaults = {};
dependent = {};
%separate into readonly, required, and optional properties
for i=1:length(allprops)
pnm = allprops{i};
Expand All @@ -22,12 +23,23 @@
optional = [optional {pnm}];
end

if isa(prop, 'file.Attribute') && prop.readonly
readonly = [readonly {pnm}];
end

if isa(prop, 'file.Attribute') && ~isempty(prop.value)
defaults = [defaults {pnm}];
if isa(prop, 'file.Attribute')
if prop.readonly
readonly = [readonly {pnm}];
end

if ~isempty(prop.value)
defaults = [defaults {pnm}];
end

if ~isempty(prop.dependent)
%extract prefix
parentname = strrep(pnm, ['_' prop.name], '');
parent = classprops.named(parentname);
if ~parent.required
dependent = [dependent {pnm}];
end
end
end
end
non_inherited = setdiff(allprops, inherited);
Expand All @@ -50,8 +62,8 @@
'% ' name ' ' class.doc]; %name, docstr
propgroups = {...
@()file.fillProps(classprops.named, ro_unique, 'SetAccess=protected')...
@()file.fillProps(classprops.named, req_unique)...
@()file.fillProps(classprops.named, opt_unique)...
@()file.fillProps(classprops.named, setdiff(req_unique, ro_unique))...
@()file.fillProps(classprops.named, setdiff(opt_unique, ro_unique))...
};
docsep = {...
'% READONLY'...
Expand All @@ -70,6 +82,7 @@
constructorBody = file.fillConstructor(name,...
depnm,...
defaults,... %all defaults, regardless of inheritance
dependent,...
req_unique,...
opt_unique,...
classprops);
Expand Down
59 changes: 45 additions & 14 deletions +file/fillConstructor.m
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
function fcstr = fillConstructor(name, parentname, defaults, required, optional, props)
function fcstr = fillConstructor(name, parentname, defaults, dependent, required, optional, props)
caps = upper(name);
fcnbody = strjoin({['% ' caps ' Constructor for ' name]...
['% obj = ' caps '(parentname1,parentvalue1,..,parentvalueN,parentargN,name1,value1,...,nameN,valueN)']...
}, newline);
fcns = {...
@()fillParamDocs('REQUIRED', required, props.named)...
@()fillParamDocs('OPTIONAL', optional, props.named)...
@()fillBody(parentname, defaults, required, optional, props)...
@()fillParamDocs('REQUIRED', setdiff(required, dependent), props.named)...
@()fillParamDocs('OPTIONAL', setdiff(optional, dependent), props.named)...
@()fillBody(parentname, defaults, dependent, required, optional, props)...
};
for i=1:length(fcns)
fcn = fcns{i};
Expand Down Expand Up @@ -74,7 +74,7 @@
end
end

function bodystr = fillBody(pname, defaults, required, optional, props)
function bodystr = fillBody(pname, defaults, dependent, required, optional, props)
if isempty(defaults)
bodystr = '';
else
Expand All @@ -97,15 +97,46 @@
var = params{i};
bodystr = [bodystr newline 'addParameter(p, ''' var ''', []);'];
end
req_unset = setdiff(required, defaults); %check required values that don't have a set value
req_body = strjoin({...
'parse(p, varargin{:});'...
['required = ' util.cellPrettyPrint(req_unset) ';']...
'missing = intersect(p.UsingDefaults, required);'...
'if ~isempty(missing)'...
' error(''Missing Required Argument(s) { %s }'', strjoin(missing, '', ''));'...
'end'}, newline);
bodystr = [bodystr newline req_body];

bodystr = [bodystr newline 'parse(p, varargin{:});'];

%check required values that don't have a set value and are independent
req_unset = setdiff(required, [defaults dependent]);
if ~isempty(req_unset)
req_body = strjoin({...
['required = ' util.cellPrettyPrint(req_unset) ';']...
'missing = intersect(p.UsingDefaults, required);'...
'if ~isempty(missing)'...
' error(''Missing Required Argument(s) { %s }'', strjoin(missing, '', ''));'...
'end'}, newline);
bodystr = [bodystr newline req_body];
end

%construct parent->dependent structure
dep_parents = struct();
for i=1:length(dependent)
dep = dependent{i};
dep_p = props.named(dep);
parent = dep_p.dependent;
if ~startsWith(dep, parent)
parent = strrep(dep, ['_' dep_p.name], '');
end
if isfield(dep_parents, parent)
deps = dep_parents.(parent);
dep_parents.(parent) = [deps {dep}];
else
dep_parents.(parent) = {dep};
end
end

%check each optional parent if they exist, then check their required dependents
dep_p_list = fieldnames(dep_parents);
for i=1:length(dep_p_list)
parent = dep_p_list{i};
children = util.cellPrettyPrint(dep_parents.(parent));
bodystr = [bodystr newline 'types.util.checkDependent(''' parent ''', ' children ', p.UsingDefaults);'];
end

for i=1:length(params)
var = params{i};
bodystr = [bodystr newline 'obj.' var ' = p.Results.' var ';'];
Expand Down
27 changes: 15 additions & 12 deletions +file/fillValidators.m
Original file line number Diff line number Diff line change
Expand Up @@ -39,26 +39,28 @@
constr = {};
for i=1:length(prop.datasets)
ds = prop.datasets(i);
if isempty(ds.type)
type = ds.dtype;
else
ds_namespace = namespacereg.getNamespace(ds.type).name;
type = ['types.' ds_namespace '.' ds.type];
end

if isempty(ds.name)
if isempty(ds.type)
typespec = ds.dtype;
else
typespec = ds.type;
end
constr = [constr {typespec}];
elseif isempty(ds.type)
namedprops.(ds.name) = ds.dtype;
constr = [constr {type}];
else
namedprops.(ds.name) = ds.type;
namedprops.(ds.name) = type;
end
end

for i=1:length(prop.subgroups)
sg = prop.subgroups(i);
sg_namespace = namespacereg.getNamespace(sg.type).name;
sgfullname = ['types.' sg_namespace '.' sg.type];
if isempty(sg.name)
constr = [constr sg.type];
constr = [constr {sgfullname}];
else
namedprops.(sg.name) = sg.type;
namedprops.(sg.name) = sgfullname;
end
end

Expand All @@ -81,7 +83,8 @@
elseif isa(prop, 'file.Attribute')
fuvstr = fillDtypeValidation(name, prop.dtype, namespacereg);
else %Link
fuvstr = fillDtypeValidation(name, prop.type, namespacereg);
namespace = namespacereg.getNamespace(prop.type).name;
fuvstr = fillDtypeValidation(name, ['types.' namespace '.' prop.type], namespacereg);
end
end

Expand Down
41 changes: 27 additions & 14 deletions +io/parseDataset.m
Original file line number Diff line number Diff line change
Expand Up @@ -36,33 +36,46 @@

datatype = info.Datatype;
if strcmp(datatype.Class, 'H5T_REFERENCE')
reftype = datatype.Type;
path = H5R.get_name(did, reftype, data);
props('ref') = [];
if strcmp(reftype, 'H5R_DATASET_REGION')
sid = H5R.get_region(did, reftype, data);
[start, finish] = H5S.get_select_bounds(sid);
H5S.close(sid);
reg = [start finish];
else
reg = [];
end
[path, reg] = parseReference(did, datatype.Type, data);
refs([fullpath '/ref']) = struct('path', path, 'region', reg);
props('ref') = [];
elseif strcmp(datatype.Class, 'H5T_COMPOUND')
t = table;
compound = datatype.Type.Member;
isref = logical(size(compound));
for j=1:length(compound)
comp = compound(j);
if strcmp(comp.Datatype.Class, 'H5T_REFERENCE')
isref(j) = true;
refnames = data.(comp.Name);
reflist = repmat(struct('path', [], 'region', []), size(refnames));
for k=1:size(refnames,2)
r = refnames(:,k);
[path, reg] = parseReference(did, comp.Datatype.Type, r);
reflist(k).path = path;
reflist(k).region = reg;
end
refs([fullpath '/' info.Name '.' comp.Name]) = reflist;
%for some reason, raw references are stored transposed.
data.(comp.Name) = cell(size(refnames, 2), 1);
end
end
props('table') = struct2table(data);
else
keyboard;
end
kwargs = io.map2kwargs(props);
parsed = eval([typename '(kwargs{:})']);

H5D.close(did);
H5F.close(fid);
end
end

function [target, region] = parseReference(did, type, data)
target = H5R.get_name(did, type, data);
region = [];
if strcmp(type, 'H5R_DATASET_REGION')
sid = H5R.get_region(did, type, data);
[start, finish] = H5S.get_select_bounds(sid);
H5S.close(sid);
region = [start finish];
end
end
53 changes: 41 additions & 12 deletions +io/parseGroup.m
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@
% NOTE, group name is in path format so we need to parse that out.
% parsed is either a containers.Map containing properties mapped to values OR a
% typed value
links = [];
links = containers.Map;
refs = containers.Map;
[~, root] = io.pathParts(info.Name);
[props, typename] = io.parseAttributes(info.Attributes);
hasTypes = false;

%parse datasets
for i=1:length(info.Datasets)
Expand All @@ -16,37 +17,65 @@
props = [props; ds];
else
props(ds_info.Name) = ds;
hasTypes = true;
end

refs = [refs; dsrefs];
end

%parse links if present
for i=1:length(info.Links)
links = [links io.parseLink(info.Links)];
end

%parse subgroups
for i=1:length(info.Groups)
g_info = info.Groups(i);
[~, gname] = io.pathParts(g_info.Name);
[subg, glinks, grefs] = io.parseGroup(filename, g_info);
props(gname) = subg;
links = [links glinks];
if isa(subg, 'containers.Map')
props = [props; subg];
else
props(gname) = subg;
hasTypes = true;
end

links = [links; glinks];
refs = [refs; grefs];
end

%parse links and add to map of links
for i=1:length(info.Links)
l = info.Links(i);
fpname = [info.Name '/' l.Name];
props(l.Name) = [];
links([info.Name '/' l.Name]) = l;
hasTypes = true;
end

if isempty(typename)
parsed = containers.Map;
keyboard;
%immediately elide prefix all property names with this but only if there are
%no typed objects in it.
propnames = keys(props);
if hasTypes
parsed = containers.Map({root}, {props});
else
parsed = containers.Map;
for i=1:length(propnames)
pnm = propnames{i};
p = props(pnm);
parsed([root '_' pnm]) = p;
end
end

if isempty(parsed)
%special case where a directory is simply empty. Return itself but
%empty
parsed(root) = [];
end
else
%construct as kwargs and instantiate object
kwargs = io.map2kwargs(props);
if isempty(root)
%we are root
parsed = types.core.NWBFile;
parsed = types.core.NWBFile(kwargs{:});
return;
end
kwargs = io.map2kwargs(props);
parsed = eval([typename '(kwargs{:})']);
end
end
4 changes: 0 additions & 4 deletions +io/parseLink.m

This file was deleted.

3 changes: 3 additions & 0 deletions +types/+util/checkConstrained.m
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
function checkConstrained(name, namedprops, constrained, val)
if isempty(val)
return;
end
if ~isa(val, 'containers.Map')
error('Property `%s` must be a containers.Map.', name);
end
Expand Down
10 changes: 10 additions & 0 deletions +types/+util/checkDependent.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
function checkDependent(parent, children, unconstructed)
if ~any(strcmp(parent, unconstructed))
for i=1:length(children)
child = children{i};
if any(strcmp(child, unconstructed))
error('Dependent type `%s` is required for parent property `%s`', child, parent);
end
end
end
end
7 changes: 6 additions & 1 deletion +types/+util/checkDims.m
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
function checkDims(valsize, validSizes)
if any(valsize == 0)
return; %ignore empty arrays
end
validSizesStrings = cell(size(validSizes));
for i=1:length(validSizes)
vs = validSizes{i};
if length(valsize) ~= length(vs)

if (length(vs) == 1 && (length(valsize) > 2 || ~any(valsize == 1))) ||...
(length(vs) > 1 && length(valsize) ~= length(vs))
continue;
end

Expand Down
Loading

0 comments on commit 3222f33

Please sign in to comment.