diff --git a/+spec/generate.m b/+spec/generate.m index b452f38d..f44ec8c1 100644 --- a/+spec/generate.m +++ b/+spec/generate.m @@ -3,6 +3,9 @@ % optionally, include schema mapping as second argument OR path of specs % schemaSource is either a path to a directory where the source is % OR a containers.Map of filenames +namespaceText = convertStringsToChars(namespaceText); +schemaSource = convertStringsToChars(schemaSource); + Schema = spec.loadSchemaObject(); namespace = spec.schema2matlab(Schema.read(namespaceText)); Namespaces = spec.getNamespaceInfo(namespace); diff --git a/generateCore.m b/generateCore.m index fac0a5c6..a9d6c08e 100644 --- a/generateCore.m +++ b/generateCore.m @@ -7,16 +7,16 @@ function generateCore(varargin) % GENERATECORE(version) Generate classes for the % core namespace of the listed version. % - % A cache of schema data is generated in the 'namespaces' subdirectory in - % the current working directory. This is for allowing cross-referencing - % classes between multiple namespaces. - % - % Output files are generated placed in a '+types' subdirectory in the - % current working directory. - % % GENERATECORE(__, 'savedir', saveDirectory) Generates the core class % files in the specified directory. % + % GENERATECORE(__, 'savedirtemp') Generates the core class files in the MATLAB temp directory. + % + % A cache of schema data is generated in the 'namespaces' subdirectory in + % the installation directory. + % + % Output files are generated placed in a '+types' subdirectory in the installation directory. + % % Example: % generateCore(); % generateCore('2.2.3'); @@ -24,8 +24,11 @@ function generateCore(varargin) % See also GENERATEEXTENSION latestVersion = '2.6.0'; - - if nargin == 0 || strcmp(varargin{1}, 'savedir') + + if isempty(varargin) ... + || "savedir" == lower(varargin{1}) ... + || "savedirtemp" == lower(varargin{1}) ... + || "latest" == lower(varargin{1}) version = latestVersion; else version = varargin{1}; @@ -34,20 +37,12 @@ function generateCore(varargin) varargin = varargin(2:end); end - if strcmp(version, 'latest') - version = latestVersion; - end - schemaPath = fullfile(misc.getMatnwbDir(), 'nwb-schema', version); corePath = fullfile(schemaPath, 'core', 'nwb.namespace.yaml'); - commonPath = fullfile(schemaPath,... - 'hdmf-common-schema', ... - 'common',... - 'namespace.yaml'); + commonPath = fullfile(schemaPath, 'hdmf-common-schema', 'common', 'namespace.yaml'); assert(2 == exist(corePath, 'file'),... 'NWB:GenerateCore:MissingCoreSchema',... - 'Cannot find suitable core namespace for schema version `%s`',... - version); + 'Cannot find suitable core namespace for schema version `%s`', version); if 2 == exist(commonPath, 'file') generateExtension(commonPath, varargin{:}); end diff --git a/generateExtension.m b/generateExtension.m index 75eb51cb..418b75d8 100644 --- a/generateExtension.m +++ b/generateExtension.m @@ -1,62 +1,76 @@ function generateExtension(varargin) % GENERATEEXTENSION Generate Matlab classes from NWB extension schema file - % GENERATEEXTENSION(extension_path...) Generate classes + % GENERATEEXTENSION(ext1, ext2, ..., extn) Generate classes % (Matlab m-files) from one or more NWB:N schema extension namespace - % files. A registry of already generated core types is used to resolve - % dependent types. + % files. + % + % GENERATEEXTENSION(__, 'savedir', location) Generates classes in a custom directory specified + % by file location. + % + % GENERATEEXTENSION(__, 'savedirtemp') Generates classes in the default MATLAB temp directory. + % This option will override any previously defined 'savedir' location. % % A cache of schema data is generated in the 'namespaces' subdirectory in - % the current working directory. This is for allowing cross-referencing - % classes between multiple namespaces. + % the installation directory (unless otherwise specified). % - % Output files are generated placed in a '+types' subdirectory in the - % current working directory. + % By default, output files are generated placed in a '+types' subdirectory in the + % installation directory. % % Example: % generateExtension('schema\myext\myextension.namespace.yaml', 'schema\myext2\myext2.namespace.yaml'); % % See also GENERATECORE - - for iOption = 1:length(varargin) - option = varargin{iOption}; - validateattributes(option, {'char', 'string'}, {'scalartext'} ... - , 'generateExtension', 'extension name', iOption); - if isstring(option) - varargin{iOption} = char(option); - end + + invalidArgumentErrorCode = 'NWB:GenerateExtension:InvalidArguments'; + + iOptionLocation = find(strcmp(varargin, 'savedir') | strcmp(varargin, 'savedirtemp'), 1); + if isempty(iOptionLocation) + iOptionLocation = length(varargin) + 1; end - - saveDirMask = strcmp(varargin, 'savedir'); - if any(saveDirMask) - assert(~saveDirMask(end),... - 'NWB:GenerateExtenion:InvalidParameter',... - 'savedir must be paired with the desired save directory.'); - saveDir = varargin{find(saveDirMask, 1, 'last') + 1}; - saveDirParametersMask = saveDirMask | circshift(saveDirMask, 1); - sourceList = varargin(~saveDirParametersMask); + + assert(0 < min(iOptionLocation, length(varargin)), invalidArgumentErrorCode ... + , 'generateExtension requires at least one extension to generate from.'); + + options = varargin(iOptionLocation:end); + extensions = varargin(1:(iOptionLocation-1)); + + hasSaveDirTemp = any(strcmpi(varargin, 'savedirtemp')); + if hasSaveDirTemp + saveDir = fullfile(tempdir(), 'MatNWB'); else - saveDir = misc.getMatnwbDir(); - sourceList = varargin; + iSaveDir = find(strcmpi(options, 'savedir')); + if isempty(iSaveDir) + saveDir = misc.getMatnwbDir(); + elseif iSaveDir(end) < length(options) + saveDir = options{iSaveDir(end) + 1}; + assert(1 ~= isfile(saveDir) ... + , invalidArgumentErrorCode ... + , 'provided save directory "%s" must be a valid directory path.', saveDir); + else + error(invalidArgumentErrorCode ... + , 'incomplete or erroneous savedir argument order.'); + end end - - for iNamespaceFiles = 1:length(sourceList) - source = sourceList{iNamespaceFiles}; - validateattributes(source, {'char', 'string'}, {'scalartext'}); - - [localpath, ~, ~] = fileparts(source); - assert(2 == exist(source, 'file'),... - 'NWB:GenerateExtension:FileNotFound', 'Path to file `%s` could not be found.', source); + + assert(all(cellfun('isclass', extensions, 'char') | cellfun('isclass', extensions, 'string')) ... + , invalidArgumentErrorCode ... + , 'extensions must be character arrays or strings.'); + + for iExtension = 1:length(extensions) + source = string(extensions{iExtension}); + assert(1 == isfile(source) ... + , invalidArgumentErrorCode ... + , 'extension file "%s" not found.', source); fid = fopen(source); namespaceText = fread(fid, '*char') .'; fclose(fid); - - Namespaces = spec.generate(namespaceText, localpath); - + Namespaces = spec.generate(namespaceText, fileparts(source)); for iNamespace = 1:length(Namespaces) - Namespace = Namespaces(iNamespace); - spec.saveCache(Namespace, saveDir); - file.writeNamespace(Namespace.name, saveDir); + N = Namespaces(iNamespace); + spec.saveCache(N, saveDir); + file.writeNamespace(N.name, saveDir); rehash(); end end + addpath(saveDir); end