Mercurial > hg > ltpda
comparison m-toolbox/classes/+utils/@helper/callerIsMethod.m @ 0:f0afece42f48
Import.
author | Daniele Nicolodi <nicolodi@science.unitn.it> |
---|---|
date | Wed, 23 Nov 2011 19:22:13 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:f0afece42f48 |
---|---|
1 % CALLERISMETHOD(varargin) checks if a method was called by another LTPDA method. | |
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
3 % | |
4 % DESCRIPTION: CALLERISMETHOD(varargin) checks if the method it is inserted in, | |
5 % was called by another LTPDA method | |
6 % | |
7 % CALL: callerIsMethod = utils.helper.callerIsMethod() | |
8 % [callerIsMethod, className] = utils.helper.callerIsMethod() | |
9 % [callerIsMethod, className, methodName] = utils.helper.callerIsMethod() | |
10 % | |
11 % The name of the caller function is retrieved from a call to dbstack | |
12 % | |
13 % The name of the higher level caller function, if any is tested against the structure | |
14 % /../../classes/@class_name/method_name.m | |
15 % | |
16 % If the higher level caller is found to be a method of LTPDA classes, out is TRUE | |
17 % If the caller is found not to be a method of LTPDA classes, out is FALSE | |
18 % | |
19 % Optional outputs: | |
20 % className the name of the class the caller methods is associated | |
21 % methodName the name of the caller method is associated | |
22 % | |
23 % HISTORY: 09-02-11 M Hueller | |
24 % Creation | |
25 % | |
26 % VERSION: $Id: callerIsMethod.m,v 1.16 2011/04/09 06:58:47 hewitson Exp $ | |
27 % | |
28 % | |
29 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
30 | |
31 function varargout = callerIsMethod(varargin) | |
32 | |
33 % This is just some thinking about make a scheme that can override the | |
34 % behaviour of callerIsMethod. The idea is to create a variable called | |
35 % 'callerIsMethod' in the calling function and pass it in here. We would | |
36 % have to pass varargin and inputnames down the chain always. It almost | |
37 % works but will be too much work for the moment. | |
38 % if nargin == 2 | |
39 % | |
40 % inputs = varargin{1}; | |
41 % names = varargin{2}; | |
42 % | |
43 % idx = strcmpi('callerIsMethod', names); | |
44 % if any(idx) | |
45 % varargout{1} = inputs{idx}; | |
46 % return | |
47 % end | |
48 % end | |
49 | |
50 persistent exceptions; | |
51 | |
52 if isempty(exceptions) | |
53 exceptions = {'compute', 'rebuild', 'collect_values', 'generic_getInfo', 'executeCommands'}; | |
54 end | |
55 | |
56 stack = dbstack('-completenames'); | |
57 index = 2; | |
58 | |
59 if size (stack, 1) < index | |
60 error('### This utility can only be used inside other functions!'); | |
61 end | |
62 | |
63 if size (stack, 1) == index | |
64 | |
65 % This is the highest level function call. | |
66 % The caller is not a method | |
67 callerIsMethod = false; | |
68 className = []; | |
69 methodName = []; | |
70 | |
71 else | |
72 % This is not the highest level function call. | |
73 | |
74 % Serching for class methods assuming the folder/files structure is: | |
75 % /../../classes/@class_name/method_name.m | |
76 | |
77 % In the case that we are inside a nested function, we need to climb up | |
78 % until we get out of the calling file. | |
79 firstFile = stack(index).file; | |
80 firstName = stack(index).name; | |
81 | |
82 while index < length(stack) && strcmp(firstFile, stack(index).file) && ~strcmp(firstName, stack(index+1).name) | |
83 index = index+1; | |
84 end | |
85 | |
86 % capture method name | |
87 methodName = stack(index).name; | |
88 | |
89 if index == length(stack) && length(stack)>3 | |
90 callerIsMethod = false; | |
91 className = ''; | |
92 else | |
93 % filesep is quite slow, so we cache the value and use it three times. | |
94 % The \ character is also a command in regexp, so we need to go for a trick | |
95 if strncmp(computer, 'PC', 2) | |
96 fs = '\\'; | |
97 else | |
98 fs = '/'; | |
99 end | |
100 | |
101 % capture class name | |
102 tokenStr = regexp(stack(index).file, ['.*' fs '@(\w+)' fs '\w+.m$'], 'tokens'); | |
103 | |
104 % ********* | |
105 % At the moment this bit of code is a bad thing because models which | |
106 % create objects in their default plists (AOs for example) can't be | |
107 % rebuilt because the objects have no history. An example of this is | |
108 % smodel_model_psd_feeps. | |
109 % ********* | |
110 | |
111 % % If we are being called deep inside a built-in model constructor, | |
112 % % then the stack will contain fromModel and we are called from a | |
113 % % method. | |
114 % if utils.helper.ismember('fromModel', {stack(:).name}) | |
115 % callerIsMethod = true; | |
116 % className = 'ltpda_uo'; | |
117 % methodName = 'fromModel'; | |
118 % | |
119 % % If the method is a unit test (test_*) then we add history | |
120 % else | |
121 | |
122 | |
123 if strncmp(methodName, 'test_', 5) | |
124 callerIsMethod = false; | |
125 if ~isempty(tokenStr) | |
126 className = tokenStr{1}{1}; | |
127 end | |
128 | |
129 % if we get a match and if the caller is not in the exception list | |
130 % then we were called by a method. | |
131 elseif ~isempty(tokenStr) && ~any(strcmp(stack(index).name, exceptions)) | |
132 callerIsMethod = true; | |
133 className = tokenStr{1}{1}; | |
134 else | |
135 callerIsMethod = false; | |
136 className = ''; | |
137 end | |
138 end | |
139 | |
140 end | |
141 | |
142 % Assigning outputs | |
143 switch nargout | |
144 case 0 | |
145 case 1 | |
146 varargout{1} = callerIsMethod; | |
147 case 2 | |
148 varargout{1} = callerIsMethod; | |
149 varargout{2} = className; | |
150 case 3 | |
151 varargout{1} = callerIsMethod; | |
152 varargout{2} = className; | |
153 varargout{3} = methodName; | |
154 otherwise | |
155 error('### Incorrect number of outputs'); | |
156 end | |
157 end |