1- function fcstr = fillConstructor(name , parentname , defaults , propnames , props , namespace )
2- caps = upper(name );
3- fcnbody = [' % ' caps ' Constructor for ' name ];
1+ function fcstr = fillConstructor(name , parentname , defaults , props , namespace )
2+ caps = upper(name );
3+ fcnbody = [' % ' caps ' Constructor for ' name ];
44
5- txt = fillBody(parentname , defaults , propnames , props , namespace );
6- if ~isempty(txt )
7- fcnbody = [fcnbody newline txt ];
8- end
5+ txt = fillBody(parentname , defaults , props , namespace );
6+ if ~isempty(txt )
7+ fcnbody = [fcnbody newline txt ];
8+ end
99
10- fcnbody = strjoin({fcnbody ,...
11- sprintf(' if strcmp(class(obj), ''%s'' )' , namespace .getFullClassName(name )),...
12- ' types.util.checkUnset(obj, unique(varargin(1:2:end)));' ,...
13- ' end' }, newline );
10+ fcnbody = strjoin({fcnbody ,...
11+ sprintf(' if strcmp(class(obj), ''%s'' )' , namespace .getFullClassName(name )),...
12+ ' types.util.checkUnset(obj, unique(varargin(1:2:end)));' ,...
13+ ' end' }, newline );
1414
15- % insert check for DynamicTable class and child classes
16- txt = fillCheck(name , namespace );
17- if ~isempty(txt )
18- fcnbody = [fcnbody newline txt ];
19- end
15+ % insert check for DynamicTable class and child classes
16+ txt = fillCheck(name , namespace );
17+ if ~isempty(txt )
18+ fcnbody = [fcnbody newline txt ];
19+ end
2020
21- fcstr = strjoin({...
22- [' function obj = ' name ' (varargin)' ]...
23- file .addSpaces(fcnbody , 4 )...
24- ' end' }, newline );
21+ fcstr = strjoin({...
22+ [' function obj = ' name ' (varargin)' ]...
23+ file .addSpaces(fcnbody , 4 )...
24+ ' end' }, newline );
2525
2626end
2727
28- function bodystr = fillBody(pname , defaults , names , props , namespace )
29- if isempty(defaults )
30- bodystr = ' ' ;
31- else
32- overridemap = containers .Map ;
33- for i= 1 : length(defaults )
34- nm = defaults{i };
35- if strcmp(props(nm ).dtype, ' char' )
36- overridemap(nm ) = [' '' ' props(nm ).value ' '' ' ];
37- else
38- overridemap(nm ) = ...
39- sprintf(' types.util.correctType(%d , ''%s'' )' ,...
40- props(nm ).value,...
41- props(nm ).dtype);
28+ function bodystr = fillBody(pname , defaults , props , namespace )
29+ if isempty(defaults )
30+ bodystr = ' ' ;
31+ else
32+ overridemap = containers .Map ;
33+ for i= 1 : length(defaults )
34+ nm = defaults{i };
35+ if strcmp(props(nm ).dtype, ' char' )
36+ overridemap(nm ) = [' '' ' props(nm ).value ' '' ' ];
37+ else
38+ overridemap(nm ) = ...
39+ sprintf(' types.util.correctType(%d , ''%s'' )' ,...
40+ props(nm ).value,...
41+ props(nm ).dtype);
42+ end
4243 end
44+ kwargs = io .map2kwargs(overridemap );
45+ % add surrounding quotes to kwargs so misc.cellPrettyPrint can print them correctly
46+ kwargs(1 : 2 : end ) = strcat(' '' ' , kwargs(1 : 2 : end ), ' '' ' );
47+ bodystr = [' varargin = [{' misc .cellPrettyPrint(kwargs ) ' } varargin];' newline ];
4348 end
44- kwargs = io .map2kwargs(overridemap );
45- % add surrounding quotes to kwargs so misc.cellPrettyPrint can print them correctly
46- kwargs(1 : 2 : end ) = strcat(' '' ' , kwargs(1 : 2 : end ), ' '' ' );
47- bodystr = [' varargin = [{' misc .cellPrettyPrint(kwargs ) ' } varargin];' newline ];
48- end
49- bodystr = [bodystr ' obj = obj@' pname ' (varargin{:});' ];
49+ bodystr = [bodystr ' obj = obj@' pname ' (varargin{:});' ];
5050
51- if isempty(names )
52- return ;
53- end
54- % if there's a root object that is a constrained set, let it be hoistable from dynamic arguments
55- dynamicConstrained = false(size(names ));
56- anon = false(size(names ));
57- isattr = false(size(names ));
58- typenames = repmat({' ' }, size(names ));
59- varnames = repmat({' ' }, size(names ));
60- for i= 1 : length(names )
61- nm = names{i };
62- prop = props(nm );
63-
64- if isa(prop , ' file.Group' ) || isa(prop , ' file.Dataset' )
65- dynamicConstrained(i ) = prop .isConstrainedSet && strcmpi(nm , prop .type );
66- anon(i ) = ~prop .isConstrainedSet && isempty(prop .name );
67-
68- if ~isempty(prop .type )
69- varnames{i } = nm ;
70- try
71- typenames{i } = namespace .getFullClassName(prop .type );
72- catch ME
73- if ~strcmp(ME .identifier , ' NWB:Scheme:Namespace:NotFound' )
74- rethrow(ME );
51+ names = keys(props );
52+ if isempty(names )
53+ return ;
54+ end
55+ % if there's a root object that is a constrained set, let it be hoistable from dynamic arguments
56+ dynamicConstrained = false(size(names ));
57+ anon = false(size(names ));
58+ isattr = false(size(names ));
59+ typenames = repmat({' ' }, size(names ));
60+ varnames = repmat({' ' }, size(names ));
61+ for i= 1 : length(names )
62+ nm = names{i };
63+ prop = props(nm );
64+
65+ if isa(prop , ' file.Group' ) || isa(prop , ' file.Dataset' )
66+ dynamicConstrained(i ) = prop .isConstrainedSet && strcmpi(nm , prop .type );
67+ anon(i ) = ~prop .isConstrainedSet && isempty(prop .name );
68+
69+ if ~isempty(prop .type )
70+ varnames{i } = nm ;
71+ try
72+ typenames{i } = namespace .getFullClassName(prop .type );
73+ catch ME
74+ if ~strcmp(ME .identifier , ' NWB:Scheme:Namespace:NotFound' )
75+ rethrow(ME );
76+ end
7577 end
7678 end
79+ elseif isa(prop , ' file.Attribute' )
80+ isattr(i ) = true ;
7781 end
78- elseif isa(prop , ' file.Attribute' )
79- isattr(i ) = true ;
8082 end
81- end
8283
83- % warn for missing namespaces/property types
84- warnmsg = [' `' pname ' `'' s constructor is unable to check for type `%1$s` ' ...
85- ' because its namespace or type specifier could not be found. Try generating ' ...
86- ' the namespace or class definition for type `%1$s` or fix its schema.' ];
84+ % warn for missing namespaces/property types
85+ warnmsg = [' `' pname ' `'' s constructor is unable to check for type `%1$s` ' ...
86+ ' because its namespace or type specifier could not be found. Try generating ' ...
87+ ' the namespace or class definition for type `%1$s` or fix its schema.' ];
8788
88- invalid = cellfun(' isempty' , typenames );
89- invalidWarn = invalid & (dynamicConstrained | anon ) & ~isattr ;
90- invalidVars = varnames(invalidWarn );
91- for i= 1 : length(invalidVars )
92- warning(warnmsg , invalidVars{i });
93- end
94- varnames = lower(varnames );
95-
96- % we delete the entry in varargin such that any conflicts do not show up in inputParser
97- deleteFromVars = ' varargin(ivarargin) = [];' ;
98- % if constrained/anon sets exist, then check for nonstandard parameters and add as
99- % container.map
100- constrainedTypes = typenames(dynamicConstrained & ~invalid );
101- constrainedVars = varnames(dynamicConstrained & ~invalid );
102- methodCalls = strcat(' [obj.' , constrainedVars , ' , ivarargin] = ' ,...
103- ' types.util.parseConstrained(obj,'' ' , constrainedVars , ' '' , '' ' ,...
104- constrainedTypes , ' '' , varargin{:});' );
105- fullBody = cell(length(methodCalls ) * 2 ,1 );
106- fullBody(1 : 2 : end ) = methodCalls ;
107- fullBody(2 : 2 : end ) = {deleteFromVars };
108- fullBody = strjoin(fullBody , newline );
109- bodystr(end + 1 : end + length(fullBody )+1 ) = [newline fullBody ];
110-
111- % if anonymous values exist, then check for nonstandard parameters and add
112- % as Anon
113-
114- anonTypes = typenames(anon & ~invalid );
115- anonVars = varnames(anon & ~invalid );
116- methodCalls = strcat(' [obj.' , anonVars , ' ,ivarargin] = ' ,...
117- ' types.util.parseAnon('' ' , anonTypes , ' '' , varargin{:});' );
118- fullBody = cell(length(methodCalls ) * 2 ,1 );
119- fullBody(1 : 2 : end ) = methodCalls ;
120- fullBody(2 : 2 : end ) = {deleteFromVars };
121- fullBody = strjoin(fullBody , newline );
122- bodystr(end + 1 : end + length(fullBody )+1 ) = [newline fullBody ];
123-
124- parser = {...
125- ' p = inputParser;' ,...
126- ' p.KeepUnmatched = true;' ,...
127- ' p.PartialMatching = false;' ,...
128- ' p.StructExpand = false;' };
129-
130- names = names(~dynamicConstrained & ~anon );
131- defaults = cell(size(names ));
132- for i= 1 : length(names )
133- prop = props(names{i });
134- if (isa(prop , ' file.Group' ) && ...
135- (prop .hasAnonData || prop .hasAnonGroups || prop .isConstrainedSet )) || ...
136- (isa(prop , ' file.Dataset' ) && prop .isConstrainedSet )
137- defaults{i } = ' types.untyped.Set()' ;
138- else
139- defaults{i } = ' []' ;
89+ invalid = cellfun(' isempty' , typenames );
90+ invalidWarn = invalid & (dynamicConstrained | anon ) & ~isattr ;
91+ invalidVars = varnames(invalidWarn );
92+ for i= 1 : length(invalidVars )
93+ warning(warnmsg , invalidVars{i });
14094 end
141- end
142- % add parameters
143- parser = [parser , strcat(' addParameter(p, '' ' , names , ' '' , ' , defaults ,' );' )];
144- % parse
145- parser = [parser , {' misc.parseSkipInvalidName(p, varargin);' }];
146- % get results
147- parser = [parser , strcat(' obj.' , names , ' = p.Results.' , names , ' ;' )];
148- parser = strjoin(parser , newline );
149- bodystr(end + 1 : end + length(parser )+1 ) = [newline parser ];
95+ varnames = lower(varnames );
96+
97+ % we delete the entry in varargin such that any conflicts do not show up in inputParser
98+ deleteFromVars = ' varargin(ivarargin) = [];' ;
99+ % if constrained/anon sets exist, then check for nonstandard parameters and add as
100+ % container.map
101+ constrainedTypes = typenames(dynamicConstrained & ~invalid );
102+ constrainedVars = varnames(dynamicConstrained & ~invalid );
103+ methodCalls = strcat(' [obj.' , constrainedVars , ' , ivarargin] = ' ,...
104+ ' types.util.parseConstrained(obj,'' ' , constrainedVars , ' '' , '' ' ,...
105+ constrainedTypes , ' '' , varargin{:});' );
106+ fullBody = cell(length(methodCalls ) * 2 ,1 );
107+ fullBody(1 : 2 : end ) = methodCalls ;
108+ fullBody(2 : 2 : end ) = {deleteFromVars };
109+ fullBody = strjoin(fullBody , newline );
110+ bodystr(end + 1 : end + length(fullBody )+1 ) = [newline fullBody ];
111+
112+ % if anonymous values exist, then check for nonstandard parameters and add
113+ % as Anon
114+
115+ anonTypes = typenames(anon & ~invalid );
116+ anonVars = varnames(anon & ~invalid );
117+ methodCalls = strcat(' [obj.' , anonVars , ' ,ivarargin] = ' ,...
118+ ' types.util.parseAnon('' ' , anonTypes , ' '' , varargin{:});' );
119+ fullBody = cell(length(methodCalls ) * 2 ,1 );
120+ fullBody(1 : 2 : end ) = methodCalls ;
121+ fullBody(2 : 2 : end ) = {deleteFromVars };
122+ fullBody = strjoin(fullBody , newline );
123+ bodystr(end + 1 : end + length(fullBody )+1 ) = [newline fullBody ];
124+
125+ parser = {...
126+ ' p = inputParser;' ,...
127+ ' p.KeepUnmatched = true;' ,...
128+ ' p.PartialMatching = false;' ,...
129+ ' p.StructExpand = false;' };
130+
131+ names = names(~dynamicConstrained & ~anon );
132+ defaults = cell(size(names ));
133+ for i= 1 : length(names )
134+ prop = props(names{i });
135+ if (isa(prop , ' file.Group' ) && ...
136+ (prop .hasAnonData || prop .hasAnonGroups || prop .isConstrainedSet )) || ...
137+ (isa(prop , ' file.Dataset' ) && prop .isConstrainedSet )
138+ defaults{i } = ' types.untyped.Set()' ;
139+ else
140+ defaults{i } = ' []' ;
141+ end
142+ end
143+ % add parameters
144+ parser = [parser , strcat(' addParameter(p, '' ' , names , ' '' , ' , defaults ,' );' )];
145+ % parse
146+ parser = [parser , {' misc.parseSkipInvalidName(p, varargin);' }];
147+ % get results
148+ parser = [parser , strcat(' obj.' , names , ' = p.Results.' , names , ' ;' )];
149+ parser = strjoin(parser , newline );
150+ bodystr(end + 1 : end + length(parser )+1 ) = [newline parser ];
150151end
151152
152153function checkTxt = fillCheck(name , namespace )
153- checkTxt = [];
154-
155- % find if a dynamic table ancestry exists
156- ancestry = namespace .getRootBranch(name );
157- isDynamicTableDescendent = false ;
158- for iAncestor = 1 : length(ancestry )
159- ParentRaw = ancestry{iAncestor };
160- % this is always true, we just use the proper index as typedefs may vary.
161- typeDefInd = isKey(ParentRaw , namespace .TYPEDEF_KEYS );
162- isDynamicTableDescendent = isDynamicTableDescendent ...
163- || strcmp(' DynamicTable' , ParentRaw(namespace.TYPEDEF_KEYS{typeDefInd }));
164- end
154+ checkTxt = [];
155+
156+ % find if a dynamic table ancestry exists
157+ ancestry = namespace .getRootBranch(name );
158+ isDynamicTableDescendent = false ;
159+ for iAncestor = 1 : length(ancestry )
160+ ParentRaw = ancestry{iAncestor };
161+ % this is always true, we just use the proper index as typedefs may vary.
162+ typeDefInd = isKey(ParentRaw , namespace .TYPEDEF_KEYS );
163+ isDynamicTableDescendent = isDynamicTableDescendent ...
164+ || strcmp(' DynamicTable' , ParentRaw(namespace.TYPEDEF_KEYS{typeDefInd }));
165+ end
165166
166- if ~isDynamicTableDescendent
167- return ;
168- end
167+ if ~isDynamicTableDescendent
168+ return ;
169+ end
169170
170- checkTxt = strjoin({ ...
171- sprintf(' if strcmp(class(obj), ''%s'' )' , namespace .getFullClassName(name )), ...
172- ' types.util.dynamictable.checkConfig(obj);' , ...
173- ' end' ,...
174- }, newline );
171+ checkTxt = strjoin({ ...
172+ sprintf(' if strcmp(class(obj), ''%s'' )' , namespace .getFullClassName(name )), ...
173+ ' types.util.dynamictable.checkConfig(obj);' , ...
174+ ' end' ,...
175+ }, newline );
175176end
0 commit comments