MatrixBerryCore
AHashMap.m
Go to the documentation of this file.
2 
3  properties (Constant,Abstract,GetAccess=protected)
4  IGNORE_EXTENSIONS
5  ALLOWED_EXTENSIONS
6 
7  end
8  properties (Access=protected,Hidden)
9  storageLocation
10  storageLocationRoot
11  isPutErrorIgnored=false
12  isBrokenStoredValuesIgnored=false
13  fileExtension
14  isHashedPath=true
15  isHashedKeys=false
16  saveFunc=@(x,y,z)1
17  loadKeyFunc=@(x)1
18  loadValueFunc=@(x)1
19  storageFormat='none'
20  isMissingKeyBlamed=false
21  isStorageContentChecked=true;
22  storageBranchKey
23  end
24  methods
25  function isHashedPath=getIsHashedPath(self)
26  isHashedPath=self.isHashedPath;
27  end
28  function isHashedKeys=getIsHashedKeys(self)
29  isHashedKeys=self.isHashedKeys;
30  end
31  function self=AHashMap(varargin)
32  import mxberry.core.parseparext;
33  import mxberry.core.cont.DiskBasedHashMap;
34  %
35  [~,~,isStorageBranchKeySkipped,storageLocationRoot,...
36  storageBranchKey,self.isPutErrorIgnored,...
37  self.isBrokenStoredValuesIgnored,self.storageFormat,...
38  self.isHashedPath,self.isHashedKeys,...
39  self.isStorageContentChecked,...
40  ~,isStorageLocSpec,isStorageBranchKeySpec]=...
41  mxberry.core.parseparext(varargin,...
42  {'skipStorageBranchKey','storageLocationRoot',...
43  'storagebranchkey','ignoreputerrors',...
44  'ignorebrokenstoredvalues','storageformat',...
45  'usehashedpath','usehashedkeys',...
46  'checkstoragecontent';...
47  false,char(1,0),'default',self.isPutErrorIgnored,...
48  self.isBrokenStoredValuesIgnored,self.storageFormat,...
49  self.isHashedPath,self.isHashedKeys,...
50  self.isStorageContentChecked;...
51  'islogscalar(x)','isstring(x)',...
52  'isstring(x)','islogscalar(x)',...
53  'islogscalar(x)','isstring(x)',...
54  'islogscalar(x)','islogscalar(x)',...
55  'islogscalar(x)'},[0 1]);
56  %
57  if ~isStorageBranchKeySpec
58  storageBranchKey='default';
59  end
60  %
61  if self.isHashedPath
62  storageBranchKey=mxberry.core.hash(storageBranchKey);
63  end
64  %
65  if ~isStorageLocSpec
66  metaClass=metaclass(self);
67  storageLocationRoot=fileparts(which(metaClass.Name));
68  end
69  %
70  %
71  if isStorageBranchKeySkipped
72  self.storageLocation=storageLocationRoot;
73  storageBranchKey='';
74  else
75  self.storageLocation=[storageLocationRoot,filesep,...
76  storageBranchKey];
77  end
78  %
79  self.storageLocationRoot=storageLocationRoot;
80  %
81  self.storageBranchKey=storageBranchKey;
82  %
83  if ~strcmpi(self.storageFormat,'none')
84  if ~mxberry.io.isdir(self.storageLocation)
85  %check that a directory if exists, containts only mat files
86  mxberry.io.mkdir(self.storageLocation);
87  else
88  self.checkStorageDir(self.storageLocation);
89  end
90  end
91  %
92  end
93  %
94  function fullFileName=getFileNameByKey(self,keyStr,varargin)
95  import mxberry.core.throwerror;
96  import mxberry.core.parseparext;
97  [~,~,isPresenceChecked]=parseparext(varargin,...
98  {'checkForPresence';true;'islogical(x)&&isscalar(x)'},0);
99  fullFileName=self.genfullfilename(keyStr);
100  if isPresenceChecked&&...
101  (~self.isKey(keyStr)&&self.isMissingKeyBlamed)
102  throwerror('noRecord',...
103  ['The specified key %s is not present ',...
104  'in this container, dirName: %s'],keyStr,...
105  fileparts(fullFileName));
106  end
107  end
108  %
109  function [isKeyVec,fullFileNameCVec]=isKey(self,keyList)
110  import mxberry.core.throwwarn;
111  if isa(keyList,'char')
112  keyList={keyList};
113  end
114  fullFileNameCVec=cellfun(@self.genfullfilename,keyList,...
115  'UniformOutput',false);
116  isKeyVec=false(1,length(fullFileNameCVec));
117  nKeys=length(isKeyVec);
118  for iKey=1:nKeys
119  try
120  isKeyVec(iKey)=self.checkKey(fullFileNameCVec{iKey});
121  catch meObj
122  if self.isBrokenStoredValuesIgnored
123  throwarn('brokenKeyValue',...
124  'a value stored for a specified is broken: %s',...
125  meObj.message);
126  else
127  rethrow(meObj);
128  end
129  end
130  end
131 
132  end
133  %
134  function branchKey=getStorageBranchKey(self)
135  branchKey=self.storageBranchKey;
136  end
137  %
138  function storageLocationRoot=getStorageLocationRoot(self)
139 
140  storageLocationRoot=self.storageLocationRoot;
141  end
142  %
143  function storageLocation=getStorageLocation(self)
144 
145  storageLocation=self.storageLocation;
146  end
147  function put(self,keyList,valueObjList,varargin)
148  import mxberry.core.throwerror;
149  if ~iscell(valueObjList)
150  valueObjList={valueObjList};
151  end
152  if ~iscell(keyList)
153  keyList={keyList};
154  end
155  %
156  isnCellVec=~cellfun(@iscell,varargin);
157  varargin(isnCellVec)=cellfun(@(x){x},varargin(isnCellVec),...
158  'UniformOutput',false);
159  %
160  if ~mxberry.core.checksize(keyList,size(valueObjList))
161  throwerror('wrongInput',...
162  'keyList and valueObjList should be of the same size');
163  end
164  %
165  cellfun(@self.putOne,keyList,valueObjList,varargin{:});
166  end
167  function [valueList,varargout]=get(self,keyList,varargin)
168  import mxberry.core.parseparext;
169  [~,~,isUniformOutput]=parseparext(varargin,...
170  {'uniformOutput';true;@(x)islogical(x)&&isscalar(x)},0);
171  %
172  if ~iscell(keyList)
173  keyList={keyList};
174  end
175  %
176  varargout=cell(1,nargout-1);
177  %
178  if isUniformOutput&&length(keyList)==1
179  [valueList,varargout{:}]=self.getOne(keyList{1});
180  else
181  [valueList,varargout{:}]=cellfun(...
182  @self.getOne,keyList,...
183  'UniformOutput',isUniformOutput);
184  end
185  end
186  function keyList=getKeyList(self)
187  SFileProp=dir([self.storageLocation,filesep,...
188  ['*.',self.fileExtension]]);
189  isDirVec=[SFileProp.isdir];
190  fileNameList={SFileProp(~isDirVec).name};
191  fileNameList=cellfun(@(x)([self.storageLocation,filesep,x]),...
192  fileNameList,'UniformOutput',false);
193  %
194  [~,keyList]=cellfun(@(x)self.checkKey(x),fileNameList,...
195  'UniformOutput',false);
196  end
197  function remove(self,keyList)
198  if ~iscell(keyList)
199  keyList={keyList};
200  end
201  cellfun(@self.removeOne,keyList,'UniformOutput',false);
202  end
203  function removeAll(self)
204  storageLocation=self.getStorageLocation(); %#ok<*PROP>
205  delete([storageLocation,filesep,['*.',self.fileExtension]]);
206  end
207  %
208  end
209  methods (Access=protected)
210  function [isPositive,keyStr]=checkKey(self,fileName)
211  import mxberry.core.throwerror;
212  import mxberry.core.throwwarn;
213  isPositive=mxberry.io.isfile(fileName);
214  if isPositive
215  warnState=warning('off','MATLAB:load:variableNotFound');
216  try
217  S=self.loadKeyFunc(fileName);
218  catch meObj
219  meCauseObj=throwerror('unknownFailure',...
220  'failed to load file %s',fileName);
221  meObj=meObj.addCause(meCauseObj);
222  rethrow(meObj);
223  end
224  warning(warnState.state,'MATLAB:load:variableNotFound');
225  isPositive=isfield(S,'keyStr');
226  if isPositive
227  keyStr=S.keyStr;
228  else
229  keyStr='';
230  throwwarn('incorrectKeyValueFile',...
231  'key value file is invalid and will be updated');
232  end
233  supposedFileName=self.genfilename(keyStr);
234  [~,actualFileName]=fileparts(fileName);
235  if ~strcmp(supposedFileName,actualFileName)
236  throwerror('badKeyValuePair',...
237  ['key %s assumes the key value file name to be %s ',...
238  'while the actual file name is %s'],...
239  keyStr,supposedFileName,fileName);
240  end
241  end
242  end
243  function removeOne(self,keyStr)
244  fullFileName=self.genfullfilename(keyStr);
245  if mxberry.io.isfile(fullFileName)
246  delete(fullFileName);
247  end
248  end
249  function fullFileName=genfullfilename(self,keyStr)
250  import mxberry.core.throwerror;
251  if ~mxberry.core.isrow(keyStr)
252  throwerror('wrongInput',...
253  'keyStr is expected to be a row-string');
254  end
255  fullFileName=[self.storageLocation,filesep,...
256  self.genfilename(keyStr),['.',self.fileExtension]];
257  end
258  function putOne(self,keyStr,valueObj)
259  import mxberry.core.throwwarn;
260  fullFileName=self.genfullfilename(keyStr);
261  try
262  self.saveFunc(fullFileName,'valueObj','keyStr');
263  catch meObj
264  if mxberry.io.isfile(fullFileName)
265  delete(fullFileName);
266  end
267  %
268  if self.isPutErrorIgnored
269  throwwarn('saveFailure',...
270  'cannot save the key value: %s',...
271  meObj.message);
272  return;
273  else
274  rethrow(meObj);
275  end
276  end
277  end
278  %
279  function valueObj=getOne(self,keyStr)
280  import mxberry.core.throwerror;
281  [isKey,fullFileNameCVec]=self.isKey(keyStr);
282  if ~isKey
283  throwerror('noRecord',...
284  'The specified key is not present in this container');
285  end
286  valueObj=getfield(self.loadValueFunc(fullFileNameCVec{1}),...
287  'valueObj'); %#ok<GFLD>
288  end
289  function isPositive=isStorageDir(self,dirName)
290  SFileList=dir(dirName);
291  isDirVec=[SFileList.isdir];
292  isIgnoredOrAllowedExtVec=self.isFileExt({SFileList.name},...
293  [self.IGNORE_EXTENSIONS,self.ALLOWED_EXTENSIONS]);
294  isPositive=all(isDirVec|isIgnoredOrAllowedExtVec|...
295  ~self.isStorageContentChecked);
296  end
297  function checkStorageDir(self,dirName)
299  import mxberry.core.throwerror;
300  if ~self.isStorageDir(dirName)
301  throwerror('wrongLocation',...
302  ['cannot create a storage at the specified location %s ',...
303  'as it contains some foreign files'],dirName);
304  end
305  end
306  end
307  methods (Access=protected,Static)
308  function isPositiveVec=isFileExt(fileNameList,extList)
309  regExpStr=strcat(extList,'|');
310  regExpStr=[regExpStr{:}];
311  regExpStr=['\.(',regExpStr(1:end-1),')$'];
312  isPositiveVec=cellfun(@(x)~isempty(x),regexp(fileNameList,regExpStr));
313  end
314  end
315  methods (Access=protected)
316  function fileName=genfilename(self,inpStr)
317  if self.isHashedKeys
318  inpStr=mxberry.core.hash(inpStr);
319  end
320  %
321  if ~isempty(inpStr)
322  nChars=length(inpStr);
323  nBlocks=fix(nChars/namelengthmax);
324  blockSizeVec=[repmat(namelengthmax,1,nBlocks),rem(nChars,namelengthmax)];
325  inpCutStrCVec=mat2cell(inpStr,1,blockSizeVec);
326  %
327  inpCutStrCVec=cellfun(@genvarname,inpCutStrCVec,'UniformOutput',false);
328  fileName=[inpCutStrCVec{:}];
329  else
330  fileName=inpStr;
331  end
332  %
333  end
334  end
335 
336 end
function filesep()
function throwerror(in msgTag, in varargin)
THROWERROR works similarly to built-in ERROR function in case when there is no output arguments but s...
function mkdir(in dirName)
MKDIR creates a directory recursively.
function hash(in inpArr, in methodName)
OBJECTHASH counts the hash of input object/array.
function parseparext(in args, in propNameValMat, in varargin)
PARSEPAREXT behaves in the same way as mxberry.core.parseparams but returns property values in a more...
function repmat(in inpArray, in varargin)
function throwwarn(in msgTag, in varargin)
THROWWARN works similarly to built-in WARNING function in case when there is no output arguments but ...
function isdir(in dirName, in isJavaBased)
ISDIR returns true if a specified name corresponds to an existing directory.
DISKBASEDHASHMAP represents a hash map for the arbitrary objects on disk with a high level of persist...
Definition: AHashMap.m:6
function isfile(in fileName, in isJavaBased)
ISFILE returns true if a specified name corresponds to an existing file.
function genfilename(in inpStr)
GENFILENAME generates a valid file name based on a given string.
function isrow(in inpArray)