diff --git a/+file/fillClass.m b/+file/fillClass.m index 21a10f95..8a8bec85 100644 --- a/+file/fillClass.m +++ b/+file/fillClass.m @@ -122,7 +122,7 @@ classprops,... namespace); setterFcns = file.fillSetters(setdiff(nonInherited, union(readonly, hiddenAndReadonly))); - validatorFcns = file.fillValidators(allProperties, classprops, namespace); + validatorFcns = file.fillValidators(allProperties, classprops, namespace, namespace.getFullClassName(name), inherited); exporterFcns = file.fillExport(nonInherited, class, depnm); methodBody = strjoin({constructorBody... '%% SETTERS' setterFcns... diff --git a/+file/fillValidators.m b/+file/fillValidators.m index 214cb93d..caacadb2 100644 --- a/+file/fillValidators.m +++ b/+file/fillValidators.m @@ -1,18 +1,27 @@ -function validationStr = fillValidators(propnames, props, namespacereg) +function validationStr = fillValidators(propnames, props, namespacereg, className, inherited) validationStr = ''; for i=1:length(propnames) nm = propnames{i}; prop = props(nm); - % if readonly and value exists then ignore + if isa(prop, 'file.Attribute') && prop.readonly && ~isempty(prop.value) - continue; - end - if startsWith(class(prop), 'file.') - validationBody = fillUnitValidation(nm, prop, namespacereg); - else % primitive type - validationBody = fillDtypeValidation(nm, prop); + % Need to add a validator for inherited and readonly properties. In + % the superclass these properties might not be read only and due to + % inheritance its not possible to change property attributes + if any(strcmp(nm, inherited)) + validationBody = fillReadOnlyValidator(nm, prop.value, className); + else + continue + end + else + if startsWith(class(prop), 'file.') + validationBody = fillUnitValidation(nm, prop, namespacereg); + else % primitive type + validationBody = fillDtypeValidation(nm, prop); + end end + headerStr = ['function val = validate_' nm '(obj, val)']; if isempty(validationBody) funcstionStr = [headerStr newline 'end']; @@ -279,4 +288,34 @@ fdvstr = [fdvstr ... 'val = types.util.checkDtype(''' name ''', ''' ts ''', val);']; end +end + +function fdvstr = fillReadOnlyValidator(name, value, className) + + classNameSplit = strsplit(className, '.'); + shortName = classNameSplit{end}; + + errorStr = sprintf( 'error(''Unable to set the ''''%s'''' property of class ''''%s'''' because it is read-only.'')', name, className, shortName); + + if ischar(value) + condition = strjoin({ ... + sprintf('if isequal(val, ''%s'')', value), ... + sprintf(' val = ''%s'';', value ), ... + 'else' }, newline); + elseif isnumeric(value) || islogical(value) + condition = strjoin({ ... + sprintf('if isequal(val, %d)', value), ... + sprintf(' val = %d;', value ), ... + 'else' }, newline); + else + % Note: According to the documentation for Attribute specification keys + % (https://schema-language.readthedocs.io/en/latest/description.html#sec-attributes-spec), + % the above cases should be sufficient. + error('Unhandled case') + end + + fdvstr = strjoin({... + condition, ... + sprintf(' %s', errorStr), ... + 'end' }, newline ); end \ No newline at end of file diff --git a/+io/timestamp2datetime.m b/+io/timestamp2datetime.m index a736f7cc..1869d633 100644 --- a/+io/timestamp2datetime.m +++ b/+io/timestamp2datetime.m @@ -48,9 +48,9 @@ , 'Day', ymdStamp(7:8) ... ); end - Datetime.Year = str2double(YmdToken.Year); - Datetime.Month = str2double(YmdToken.Month); Datetime.Day = str2double(YmdToken.Day); + Datetime.Month = str2double(YmdToken.Month); + Datetime.Year = str2double(YmdToken.Year); assert(~isnat(Datetime), errorId, sprintf(errorTemplate, 'non-numeric YMD values detected')); %% HMiS TZ diff --git a/+tests/+unit/linkTest.m b/+tests/+unit/linkTest.m index f3d22f83..1b74a569 100644 --- a/+tests/+unit/linkTest.m +++ b/+tests/+unit/linkTest.m @@ -67,7 +67,7 @@ function testExternalResolution(testCase) 'table', types.untyped.ObjectView('/acquisition/es1'),... 'description', 'dtr stub that points to electrical series illegally'); % do not do this at home. expected = types.core.ElectricalSeries('data', expectedData,... - 'data_unit', 'unit',... + 'data_unit', 'volts', ... 'electrodes', stubDtr); nwb.acquisition.set('es1', expected); nwb.export('test1.nwb');