Skip to content

Commit

Permalink
removed unnecessary files. readonly properties are no longer necessar…
Browse files Browse the repository at this point in the history
…ily required properties. Removed str2num which was bottlenecking generation.
  • Loading branch information
Lancewiu committed Apr 19, 2018
1 parent a70b4d5 commit c7c5cce
Show file tree
Hide file tree
Showing 11 changed files with 126 additions and 183 deletions.
5 changes: 4 additions & 1 deletion +file/Attribute.m
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
classdef Attribute < handle
properties(SetAccess=private)
properties
name; %attribute key
doc; %doc string
required; %bool regarding whether or not this Attribute is required for class
value; %Value
readonly; %determines whether value can be changed or not
dtype; %type of value
dependent; %set externally. If the attribute is actually dependent on an untyped dataset/group
end

methods
Expand All @@ -17,10 +18,12 @@
obj.value = [];
obj.readonly = false;
obj.dtype = [];
obj.dependent = '';

if nargin < 1
return;
end

%source is a java.util.HashMap
obj.name = source.get('name');
obj.doc = source.get('doc');
Expand Down
11 changes: 6 additions & 5 deletions +file/Dataset.m
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
classdef Dataset < handle
properties(SetAccess=private)
properties
name;
doc;
type;
Expand Down Expand Up @@ -82,6 +82,9 @@
attriter = attributes.iterator();
for i=1:len
nextattr = file.Attribute(attriter.next());
if isempty(obj.type)
nextattr.dependent = obj.name;
end
obj.attributes.(nextattr.name) = nextattr;
end
end
Expand All @@ -100,12 +103,10 @@
return;
end

if isempty(obj.name)
propname = obj.type;
else
if ~isempty(obj.name)
propname = obj.name;
props(propname) = obj;
end
props(propname) = obj;

%there are only two classes that do this and they're all under
%ecephys: ElectrodeTable and ElectrodeTableRegion.
Expand Down
21 changes: 12 additions & 9 deletions +file/Group.m
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
classdef Group < handle
properties(SetAccess=private)
properties
doc;
name;
canRename;
Expand Down Expand Up @@ -88,6 +88,9 @@
attriter = attributes.iterator();
for i=1:len
nextattr = file.Attribute(attriter.next());
if isempty(obj.type)
nextattr.dependent = obj.name;
end
obj.attributes.(nextattr.name) = nextattr;
end
end
Expand All @@ -100,10 +103,11 @@
datasetiter = datasets.iterator();
obj.datasets = repmat(file.Dataset, len, 1);
for i=1:len
obj.datasets(i) = file.Dataset(datasetiter.next());
if isempty(obj.datasets(i).name)
ds = file.Dataset(datasetiter.next());
if isempty(ds.name)
anonDataCnt = anonDataCnt + 1;
end
obj.datasets(i) = ds;
end
end

Expand All @@ -115,10 +119,11 @@
subgroupiter = subgroups.iterator();
obj.subgroups = repmat(file.Group, len, 1);
for i=1:len
obj.subgroups(i) = file.Group(subgroupiter.next());
if isempty(obj.subgroups(i).name)
sg = file.Group(subgroupiter.next());
if isempty(sg.name)
anonGroupCnt = anonGroupCnt + 1;
end
obj.subgroups(i) = sg;
end
end

Expand Down Expand Up @@ -149,16 +154,14 @@
props = containers.Map;
varargs = {};

if ~isempty(obj.type)
propertyname = obj.type;
else
if ~isempty(obj.name)
propertyname = obj.name;
end

if ~obj.elide
if obj.isConstrainedSet
varargs = {obj};
else
elseif ~isempty(propertyname)
props(propertyname) = obj;
end
end
Expand Down
104 changes: 55 additions & 49 deletions +file/fillClass.m
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,35 @@
%% PROCESSING
[processed, classprops, inherited] = processClass(name, namespace, pregen);
class = processed(1);
validationlist = setdiff(keys(classprops.named), {name});
propertylist = setdiff(validationlist, inherited);

allprops = keys(classprops.named);
required = {};
optional = {};
readonly = {};
defaults = {};
%separate into readonly, required, and optional properties
for i=1:length(allprops)
pnm = allprops{i};
prop = classprops.named(pnm);

if ischar(prop) || isa(prop, 'java.util.HashMap') || isstruct(prop) || prop.required
required = [required {pnm}];
else
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}];
end
end
non_inherited = setdiff(allprops, inherited);
ro_unique = intersect(readonly, non_inherited);
req_unique = intersect(required, non_inherited);
opt_unique = intersect(optional, non_inherited);

%% CLASSDEF
if length(processed) <= 1
Expand All @@ -17,59 +44,38 @@
depnm = ['types.' pnamespace.name '.' parentname]; %WRITE
end

%% PROPERTIES
%in format <name> -> <docstring>
ro_props = struct();
req_props = struct();
opt_props = struct();
for i=1:length(propertylist)
propname = propertylist{i};
prop = classprops.named(propname);

if isa(prop, 'file.Attribute') && prop.readonly
ro_props.(propname) = prop.doc;
elseif ischar(prop)
req_props.(propname) = ['property of type ' prop];
elseif isa(prop, 'java.util.HashMap')
req_props.(propname) = ['reference to type ' prop.get('target_type')];
elseif isstruct(prop)
req_props.(propname) = ['table with properties {' strtrim(evalc('disp(fieldnames(prop)'')')) '}'];
elseif prop.required
req_props.(propname) = prop.doc;
else
opt_props.(propname) = prop.doc;
end
end

%find all properties that contain hardcoded values or defaults
vals_with_prop = {};
for i=1:length(validationlist)
vlname = validationlist{i};
vprop = classprops.named(vlname);
if isa(vprop, 'file.Attribute') && ~isempty(vprop.value)
vals_with_prop = [vals_with_prop {vlname}];
end
end

%% return classfile string
classDef = [...
'classdef ' name ' < ' depnm newline... %header, dependencies
'% ' name ' ' class.doc]; %name, docstr
propsDef = strjoin({...
file.fillProps(ro_props, 'READONLY', 'SetAccess=private')...%readonly properties
file.fillProps(req_props, 'REQUIRED')... %required properties
file.fillProps(opt_props, 'OPTIONAL')... %optional properties
}, newline);
propgroups = {...
@()file.fillProps(classprops.named, ro_unique, 'SetAccess=protected')...
@()file.fillProps(classprops.named, req_unique)...
@()file.fillProps(classprops.named, opt_unique)...
};
docsep = {...
'% READONLY'...
'% REQUIRED'...
'% OPTIONAL'...
};
propsDef = '';
for i=1:length(propgroups)
pg = propgroups{i};
pdef = pg();
if ~isempty(pdef)
propsDef = [propsDef newline docsep{i} newline pdef];
end
end

constructorBody = file.fillConstructor(name,...
namespace.name,...
depnm,...
vals_with_prop,... %we need these values to determine if we can hardcode or not
[fieldnames(ro_props); fieldnames(req_props)]',...
fieldnames(opt_props)',...
defaults,... %all defaults, regardless of inheritance
req_unique,...
opt_unique,...
classprops);
setterFcns = file.fillSetters(propertylist);
validatorFcns = file.fillValidators(validationlist, classprops, namespace);
exporterFcns = file.fillExport(name, propertylist, classprops);
setterFcns = file.fillSetters(setdiff(non_inherited, ro_unique));
validatorFcns = file.fillValidators(allprops, classprops, namespace);
exporterFcns = file.fillExport(name, [req_unique opt_unique], classprops);
methodBody = strjoin({constructorBody...
'%% SETTERS' setterFcns...
'%% VALIDATORS' validatorFcns...
Expand All @@ -91,7 +97,7 @@
for i=length(branch):-1:1
node = branch(i);
nodename = node.get('neurodata_type_def');

if ~isKey(pregen, nodename)
if isgroup
class = file.Group(node);
Expand Down
71 changes: 20 additions & 51 deletions +file/fillConstructor.m
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
function fcstr = fillConstructor(name, namespacename, parentname, pwithval, req_names, opt_names, props)
function fcstr = fillConstructor(name, parentname, defaults, 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', req_names, props.named)...
@() fillParamDocs('OPTIONAL', opt_names, props.named)...
@() fillSetDocs(name, props.varargs, namespacename)...
@() fillBody(parentname, pwithval, req_names, opt_names, props)...
@()fillParamDocs('REQUIRED', required, props.named)...
@()fillParamDocs('OPTIONAL', optional, props.named)...
@()fillBody(parentname, defaults, required, optional, props)...
};
for i=1:length(fcns)
fcn = fcns{i};
Expand All @@ -22,17 +21,6 @@
'end'}, newline);
end

function fcstr = fillSetDocs(name, varprops, namespace)
fcstr = '';
for i=1:length(varprops)
nm = varprops{i}.type;
if strcmp(nm, name)
continue;
end
fcstr = [fcstr '% ' nm ' = list of types.' namespace '.' nm newline];
end
end

function fdfp = fillDocFromProp(prop, propnm)
if ischar(prop)
fdfp = prop;
Expand Down Expand Up @@ -86,59 +74,40 @@
end
end

function bodystr = fillBody(pname, propwithvals, req_vars, opt_vars, props)
all_vars = [req_vars opt_vars];

upstream = {}; %kwargs to be sent to parent
hardcoded = {}; %hardcoded defaults that should be instantiated now.
for i=1:length(propwithvals)
pnm = propwithvals{i};
prop = props.named(pnm);
if any(strcmp(all_vars, pnm)) %that is, it's noninherited
[~, status] = str2num(prop.value);
if status
wrapped_assgn = prop.value;
else
wrapped_assgn = ['''' prop.value ''''];
end

hardcoded = [hardcoded {['obj.' pnm ' = ' wrapped_assgn ';']}];
else
upstream = [upstream {pnm} {prop.value}];
end
end
if isempty(upstream)
function bodystr = fillBody(pname, defaults, required, optional, props)
if isempty(defaults)
bodystr = '';
else
bodystr = ['varargin = [' util.cellPrettyPrint(upstream) ' varargin];' newline];
usmap = containers.Map;
for i=1:length(defaults)
nm = defaults{i};
usmap(nm) = props.named(nm).value;
end
kwargs = io.map2kwargs(usmap);
bodystr = ['varargin = [' util.cellPrettyPrint(kwargs) ' varargin];' newline];
end
bodystr = [bodystr 'obj = obj@' pname '(varargin{:});'];

if ~isempty(hardcoded)
bodystr = [bodystr newline strjoin(hardcoded, newline)];
end
bodystr = strjoin({bodystr...
'p = inputParser;'...
'p.KeepUnmatched = true;'... %suppress subclass/parent props
'p.PartialMatching = false;'...
'p.StructExpand = false;'}, newline);

for i=1:length(all_vars)
var = all_vars{i};
params = [required optional];
for i=1:length(params)
var = params{i};
bodystr = [bodystr newline 'addParameter(p, ''' var ''', []);'];
end
req_empty_vars = setdiff(req_vars, propwithvals); %check required values that don't have a set value
req_vars_str = util.cellPrettyPrint(req_empty_vars);
req_unset = setdiff(required, defaults); %check required values that don't have a set value
req_body = strjoin({...
'parse(p, varargin{:});'...
['required = ' req_vars_str ';']...
['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];
for i=1:length(all_vars)
var = all_vars{i};
for i=1:length(params)
var = params{i};
bodystr = [bodystr newline 'obj.' var ' = p.Results.' var ';'];
end
end
Loading

0 comments on commit c7c5cce

Please sign in to comment.