0001 function model = dsPropagateNamespaces(model,map, varargin)
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027 options = dsCheckOptions(varargin,{'auto_gen_test_data_flag',0,{0,1}},false);
0028 if options.auto_gen_test_data_flag
0029 varargs = varargin;
0030 varargs{find(strcmp(varargs, 'auto_gen_test_data_flag'))+1} = 0;
0031 varargs(end+1:end+2) = {'unit_test_flag',1};
0032 argin = [{model}, {map}, varargs];
0033 end
0034
0035
0036 model=dsCheckModel(model, varargin{:});
0037
0038 if ~iscell(map) || size(map,2)~=4
0039 error('map must be a cell array with four columns for (name, namespace_name, namespace, type)');
0040 end
0041 names_in_namespace=cellfun(@(x,y)strncmp(y,x,length(y)),map(:,2),map(:,3));
0042 [name_,name__]=dsGetNamespaces(model);
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054 allowed_insert_types.fixed_variables=...
0055 {'parameters','fixed_variables','reserved'};
0056 allowed_insert_types.functions=...
0057 {'parameters','fixed_variables','functions','state_variables','reserved'};
0058 allowed_insert_types.monitors=...
0059 {'parameters','fixed_variables','functions','state_variables','reserved'};
0060 allowed_insert_types.ODEs=...
0061 {'parameters','fixed_variables','functions','state_variables','reserved'};
0062 allowed_insert_types.ICs=...
0063 {'parameters','fixed_variables','functions','state_variables','reserved'};
0064 allowed_insert_types.linkers=...
0065 {'parameters','fixed_variables','functions','state_variables','reserved'};
0066 allowed_insert_types.conditionals=...
0067 {'parameters','fixed_variables','functions','state_variables','reserved'};
0068
0069
0070
0071 if ~isempty(model.linkers)
0072 namespaces={model.linkers.namespace};
0073 expressions=propagate_namespaces({model.linkers.expression},namespaces,map,allowed_insert_types.linkers);
0074 [model.linkers(1:length(model.linkers)).expression]=deal(expressions{:});
0075 end
0076
0077
0078 if ~isempty(model.conditionals)
0079 namespaces={model.conditionals.namespace};
0080 target_types={'condition','action','else'};
0081 for type_index=1:length(target_types)
0082 type=target_types{type_index};
0083 tmp=propagate_namespaces({model.conditionals.(type)},namespaces,map,allowed_insert_types.conditionals);
0084 [model.conditionals(1:length(model.conditionals)).(type)]=deal(tmp{:});
0085 end
0086 end
0087
0088
0089 target_types={'fixed_variables','functions','monitors','ODEs','ICs'};
0090
0091
0092 for type_index=1:length(target_types)
0093 type=target_types{type_index};
0094
0095 s=model.(type);
0096 if isstruct(s)
0097 fields=fieldnames(s);
0098 expressions=struct2cell(s);
0099 namespaces={};
0100 for i=1:length(expressions)
0101 idx=strcmp(fields{i},map(:,2));
0102 if numel(find(idx))>1
0103
0104 tmp=map(idx&names_in_namespace,3);
0105
0106
0107 l=cellfun(@length,tmp);
0108 tmp=tmp{l==max(l)};
0109 else
0110 tmp=map{idx,3};
0111 end
0112 namespaces{end+1}=tmp;
0113 end
0114
0115 expressions=propagate_namespaces(expressions,namespaces,map,allowed_insert_types.(type));
0116
0117
0118 model.(type)=cell2struct(expressions,fields,1);
0119 end
0120 end
0121
0122
0123
0124 function expressions=propagate_namespaces(expressions,namespaces,map,insert_types)
0125
0126 for i=1:length(expressions)
0127 if isempty(expressions{i})
0128 continue;
0129 end
0130
0131 this_namespace=namespaces{i};
0132
0133
0134 this_namespace__ = name__{strcmp(this_namespace,name_)};
0135
0136
0137 parent_namespace = dsGetParentNamespace(this_namespace__, varargin{:});
0138
0139
0140 insert_type_constraint = ismember(map(:,4),insert_types);
0141 this_namespace_map_inds = find(strcmp(this_namespace,map(:,3)) & insert_type_constraint);
0142 parent_namespace_map_inds = find(strcmp(parent_namespace,map(:,3)) & insert_type_constraint);
0143
0144
0145 words=unique(regexp(expressions{i},'[a-zA-Z]+\w*','match'));
0146
0147
0148 for j=1:length(words)
0149
0150 if any(strcmp(words{j},map(parent_namespace_map_inds,1)))
0151
0152 ind=parent_namespace_map_inds(strcmp(words{j},map(parent_namespace_map_inds,1)));
0153 new_word=map{ind,2};
0154
0155
0156 if exist('type','var') && strcmp(type, 'ICs') && strcmp(words{j}, 'X')
0157 new_word = [new_word '_last'];
0158 end
0159
0160
0161
0162 expressions{i}=dsStrrep(expressions{i},words{j},new_word, '', '', varargin{:});
0163
0164
0165
0166 new_word_type=map{ind,4};
0167
0168 if ~isfield(model.(new_word_type),new_word)
0169
0170 if isfield(model.(new_word_type),words{j})
0171 model.(new_word_type).(new_word)=model.(new_word_type).(words{j});
0172 model.(new_word_type) = rmfield(model.(new_word_type),words{j});
0173 else
0174 tmpi=find(strcmp(words{j},map(:,1))&strcmp(new_word_type,map(:,4))&strcmp(this_namespace,map(:,3)));
0175 if ~isempty(tmpi)
0176 old_field = map{tmpi,2};
0177 if ~isempty(tmpi) && isfield(model.(new_word_type),old_field)
0178 model.(new_word_type).(new_word)=model.(new_word_type).(old_field);
0179
0180 end
0181 end
0182 end
0183 end
0184
0185 elseif any(strcmp(words{j},map(this_namespace_map_inds,1)))
0186
0187 ind=this_namespace_map_inds(strcmp(words{j},map(this_namespace_map_inds,1)));
0188 new_word=map{ind,2};
0189
0190
0191 expressions{i}=dsStrrep(expressions{i},words{j},new_word, '', '', varargin{:});
0192 end
0193 end
0194 end
0195 end
0196
0197
0198 if options.auto_gen_test_data_flag
0199 argout = {model};
0200
0201 dsUnitSaveAutoGenTestData(argin, argout);
0202 end
0203
0204 end
0205
0206
0207
0208 function parent = dsGetParentNamespace(namespace)
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224 if isempty(namespace) && isnumeric(namespace)
0225 namespace='';
0226 end
0227 if ~isempty(namespace) && namespace(end)=='_'
0228 namespace=namespace(1:end-1);
0229 end
0230 if ~isempty(namespace)
0231 parts=regexp(namespace,'__','split');
0232 else
0233 parts=[];
0234 end
0235
0236 switch length(parts)
0237 case 0
0238 parent='global';
0239 case 1
0240 parent='';
0241 case 2
0242 if isequal(parts{1},parts{2})
0243 parent='global';
0244 else
0245 parent=[parts{1} '_'];
0246 end
0247 case 3
0248 parent=[parts{1} '_' parts{2} '_'];
0249 otherwise
0250 parent='';
0251 for i=1:length(parts)-1
0252 parent=[parent parts{i} '_'];
0253 end
0254 end
0255
0256 end