Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RBrowserData.cxx
Go to the documentation of this file.
1// Author: Sergey Linev <S.Linev@gsi.de>
2// Date: 2019-10-14
3
4/*************************************************************************
5 * Copyright (C) 1995-2020, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12#include <ROOT/RBrowserData.hxx>
13
20
21#include <ROOT/RLogger.hxx>
22
23#include "TFolder.h"
24#include "TROOT.h"
25#include "TBufferJSON.h"
26#include "TEnv.h"
27
28#include <algorithm>
29#include <regex>
30
31using namespace ROOT;
32using namespace std::string_literals;
33
35{
36 static ROOT::RLogChannel sLog("ROOT.Browser");
37 return sLog;
38}
39
40namespace ROOT {
41
43
45
46public:
48
49 void RecursiveRemove(TObject *obj) override
50 {
52 }
53};
54
55} // namespace ROOT
56
57
58/** \class ROOT::RBrowserData
59\ingroup rbrowser
60\brief Way to browse (hopefully) everything in %ROOT
61*/
62
63
64/////////////////////////////////////////////////////////////////////
65/// Default constructor
66
68{
69 fCleanupHandle = std::make_unique<RBrowserDataCleanup>(*this);
71 gROOT->GetListOfCleanups()->Add(fCleanupHandle.get());
72}
73
74/////////////////////////////////////////////////////////////////////
75/// Destructor
76
78{
79 // should be here because of fCleanupHandle destructor
81 gROOT->GetListOfCleanups()->Remove(fCleanupHandle.get());
82}
83
84/////////////////////////////////////////////////////////////////////
85/// set top element for browsing
86
87void RBrowserData::SetTopElement(std::shared_ptr<Browsable::RElement> elem)
88{
90
92}
93
94/////////////////////////////////////////////////////////////////////
95/// set working directory relative to top element
96
103
104/////////////////////////////////////////////////////////////////////
105/// Create default elements shown in the RBrowser
106
108{
109 auto comp = std::make_shared<Browsable::RGroup>("top","Root browser");
110
112
113 std::unique_ptr<Browsable::RHolder> rootfold = std::make_unique<Browsable::TObjectHolder>(gROOT->GetRootFolder(), kFALSE);
115 if (elem_root)
116 comp->Add(std::make_shared<Browsable::RWrapper>("root", elem_root));
117
118 std::unique_ptr<Browsable::RHolder> rootfiles = std::make_unique<Browsable::TObjectHolder>(gROOT->GetListOfFiles(), kFALSE);
120 if (elem_files) {
121 auto files = std::make_shared<Browsable::RWrapper>("ROOT Files", elem_files);
122 files->SetExpandByDefault(true);
123 comp->Add(files);
124 // if there are any open files, make them visible by default
125 if (elem_files->GetNumChilds() > 0)
126 seldir = {};
127 }
128
130
132}
133
134/////////////////////////////////////////////////////////////////////
135/// Reset all data correspondent to last request
136
138{
139 fLastAllChilds = false;
140 fLastSortedItems.clear();
141 fLastSortMethod.clear();
142 fLastItems.clear();
143 if (with_element) {
144 fLastPath.clear();
145 fLastElement.reset();
146 }
147}
148
149/////////////////////////////////////////////////////////////////////////
150/// Decompose path to elements
151/// Returns array of names for each element in the path, first element either "/" or "."
152/// If returned array empty - it is error
153
155{
158
159 if (strpath.empty())
160 return arr;
161
163 arr.insert(arr.end(), arr2.begin(), arr2.end());
164 return arr;
165}
166
167/////////////////////////////////////////////////////////////////////////
168/// Process browser request
169
171{
172 auto path = fWorkingPath;
173 path.insert(path.end(), request.path.begin(), request.path.end());
174
175 if ((path != fLastPath) || !fLastElement) {
176
177 auto elem = GetSubElement(path);
178 if (!elem) return false;
179
181
182 fLastPath = path;
183 fLastElement = std::move(elem);
184
185 fLastElement->cd(); // set element active
186 } else if (request.reload) {
187 // only reload items from element, not need to reset element itself
189 }
190
191 // when request childs, always try to make elements
192 if (fLastItems.empty()) {
193
194 auto iter = fLastElement->GetChildsIter();
195
196 if (!iter) return false;
197 int id = 0;
198 fLastAllChilds = true;
199
200 while (iter->Next() && fLastAllChilds) {
201 fLastItems.emplace_back(iter->CreateItem());
202 if (id++ > 10000)
203 fLastAllChilds = false;
204 }
205
206 fLastSortedItems.clear();
207 fLastSortMethod.clear();
208 }
209
210 // create sorted array
211 if ((fLastSortedItems.size() != fLastItems.size()) ||
212 (fLastSortMethod != request.sort) ||
213 (fLastSortReverse != request.reverse)) {
214 fLastSortedItems.resize(fLastItems.size(), nullptr);
215 int id = 0;
216 if (request.sort.empty() || (request.sort == "none")) {
217 // no sorting, just move all folders up
218 for (auto &item : fLastItems)
219 if (item->IsFolder())
220 fLastSortedItems[id++] = item.get();
221 for (auto &item : fLastItems)
222 if (!item->IsFolder())
223 fLastSortedItems[id++] = item.get();
224 } else {
225 // copy items
226 for (auto &item : fLastItems)
227 fLastSortedItems[id++] = item.get();
228
229 if (request.sort != "unsorted")
230 std::sort(fLastSortedItems.begin(), fLastSortedItems.end(),
231 [request](const Browsable::RItem *a, const Browsable::RItem *b) { return a ? a->Compare(b, request.sort) : !b; });
232 }
233
234 if (request.reverse)
235 std::reverse(fLastSortedItems.begin(), fLastSortedItems.end());
236
237 fLastSortMethod = request.sort;
238 fLastSortReverse = request.reverse;
239 }
240
241 const std::regex expr(request.regex);
242
243 int id = 0;
244 for (auto &item : fLastSortedItems) {
245
246 // check if element is hidden
247 if (!request.hidden && item->IsHidden())
248 continue;
249
250 if (!request.regex.empty() && !item->IsFolder() && !std::regex_match(item->GetName(), expr))
251 continue;
252
253 if ((id >= request.first) && ((request.number == 0) || (id < request.first + request.number)))
254 reply.nodes.emplace_back(item);
255
256 id++;
257 }
258
259 reply.first = request.first;
260 reply.nchilds = id; // total number of childs
261
262 return true;
263}
264
265/////////////////////////////////////////////////////////////////////////
266/// Process browser request, returns string with JSON of RBrowserReply data
267
269{
271
272 reply.path = request.path;
273 reply.first = 0;
274 reply.nchilds = 0;
275
277
279}
280
281/////////////////////////////////////////////////////////////////////////
282/// Returns element with path, specified as string
283
284std::shared_ptr<Browsable::RElement> RBrowserData::GetElement(const std::string &str)
285{
286 auto path = DecomposePath(str, true);
287
288 return GetSubElement(path);
289}
290
291/////////////////////////////////////////////////////////////////////////
292/// Returns element with path, specified as Browsable::RElementPath_t
293
294std::shared_ptr<Browsable::RElement> RBrowserData::GetElementFromTop(const Browsable::RElementPath_t &path)
295{
296 return GetSubElement(path);
297}
298
299/////////////////////////////////////////////////////////////////////////
300/// Returns sub-element starting from top, using cached data
301
302std::shared_ptr<Browsable::RElement> RBrowserData::GetSubElement(const Browsable::RElementPath_t &path)
303{
304 if (path.empty())
305 return fTopElement;
306
307 // validate cache - removes no longer actual elements
308 RemoveFromCache(nullptr);
309
310 // first check direct match in cache
311 for (auto &entry : fCache)
312 if (entry.first == path)
313 return entry.second;
314
315 // find best possible entry in cache
316 int pos = 0;
317 auto elem = fTopElement;
318
319 for (auto &entry : fCache) {
320 if (entry.first.size() >= path.size())
321 continue;
322
323 auto comp = Browsable::RElement::ComparePaths(path, entry.first);
324
325 if ((comp > pos) && (comp == (int) entry.first.size())) {
326 pos = comp;
327 elem = entry.second;
328 }
329 }
330
331 while (pos < (int) path.size()) {
332 std::string subname = path[pos];
334
335 auto iter = elem->GetChildsIter();
336 if (!iter)
337 return nullptr;
338
339 if (!iter->Find(subname, indx)) {
340 if (indx < 0)
341 return nullptr;
342 iter = elem->GetChildsIter();
343 if (!iter || !iter->Find(subname))
344 return nullptr;
345 }
346
347 elem = iter->GetElement();
348
349 if (!elem)
350 return nullptr;
351
352 auto subpath = path;
353 subpath.resize(pos+1);
354 fCache.emplace_back(subpath, elem);
355 pos++; // switch to next element
356 }
357
358 return elem;
359}
360
361/////////////////////////////////////////////////////////////////////////
362/// Clear internal objects cache
363
365{
366 fCache.clear();
367}
368
369/////////////////////////////////////////////////////////////////////////
370/// Remove object from cache
371/// If nullptr specified - removes no-longer-valid elements
372/// Returns true if any element was removed
373
375{
376 unsigned pos = 0;
377
378 bool isany = false;
379
380 while (pos < fCache.size()) {
381 if (obj ? !fCache[pos].second->IsObject(obj) : fCache[pos].second->CheckValid()) {
382 pos++;
383 continue;
384 }
385
386 isany = true;
387 auto path = fCache[pos].first;
388 fCache.erase(fCache.begin() + pos);
389 if (RemoveFromCache(path))
390 pos = 0; // start scan from the beginning
391 }
392
393 return isany;
394}
395
396/////////////////////////////////////////////////////////////////////////
397/// Remove path (and all sub-paths) from cache
398/// Returns true if any element was removed
399
401{
402 if (path.size() == 0)
403 return false;
404
405 bool isany = false;
406 unsigned pos = 0;
407 while (pos < fCache.size()) {
408 if (Browsable::RElement::ComparePaths(path, fCache[pos].first) == (int) path.size()) {
409 fCache.erase(fCache.begin() + pos);
410 isany = true;
411 } else {
412 pos++;
413 }
414 }
415 return isany;
416}
#define b(i)
Definition RSha256.hxx:100
#define a(i)
Definition RSha256.hxx:99
constexpr Bool_t kFALSE
Definition RtypesCore.h:109
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize id
R__EXTERN TVirtualMutex * gROOTMutex
Definition TROOT.h:63
#define gROOT
Definition TROOT.h:417
#define R__LOCKGUARD(mutex)
static int ExtractItemIndex(std::string &name)
Extract index from name Index coded by client with ###<indx>$$$ suffix Such coding used by browser to...
Definition RElement.cxx:180
static int ComparePaths(const RElementPath_t &path1, const RElementPath_t &path2)
Compare two paths, Returns number of elements matches in both paths.
Definition RElement.cxx:147
static RElementPath_t ParsePath(const std::string &str)
Parse string path to produce RElementPath_t One should avoid to use string pathes as much as possible...
Definition RElement.cxx:118
Representation of single item in the browser.
Definition RItem.hxx:23
static std::shared_ptr< RElement > Browse(std::unique_ptr< RHolder > &obj)
Create browsable element for the object Created element may take ownership over the object.
static RElementPath_t ProvideTopEntries(std::shared_ptr< RGroup > &comp, const std::string &workdir="")
Provide top entries for file system On windows it is list of existing drivers, on Linux it is "File s...
Definition RSysFile.cxx:507
RBrowserDataCleanup(RBrowserData &_data)
void RecursiveRemove(TObject *obj) override
Recursively remove this object from a list.
Way to browse (hopefully) everything in ROOT.
void SetTopElement(std::shared_ptr< Browsable::RElement > elem)
set top element for browsing
std::vector< const Browsable::RItem * > fLastSortedItems
! sorted child items, used in requests
Browsable::RElementPath_t fWorkingPath
! path showed in Breadcrumb
bool RemoveFromCache(void *obj)
Remove object from cache If nullptr specified - removes no-longer-valid elements Returns true if any ...
std::shared_ptr< Browsable::RElement > GetSubElement(const Browsable::RElementPath_t &path)
Returns sub-element starting from top, using cached data.
std::vector< std::pair< Browsable::RElementPath_t, std::shared_ptr< Browsable::RElement > > > fCache
! already requested elements
Browsable::RElementPath_t DecomposePath(const std::string &path, bool relative_to_work_element)
Decompose path to elements Returns array of names for each element in the path, first element either ...
bool fLastAllChilds
! if all chlds were extracted
virtual ~RBrowserData()
Destructor.
bool ProcessBrowserRequest(const RBrowserRequest &request, RBrowserReply &reply)
Process browser request.
std::shared_ptr< Browsable::RElement > GetElementFromTop(const Browsable::RElementPath_t &path)
Returns element with path, specified as Browsable::RElementPath_t.
std::string fLastSortMethod
! last sort method
void ClearCache()
Clear internal objects cache.
std::string ProcessRequest(const RBrowserRequest &request)
Process browser request, returns string with JSON of RBrowserReply data.
std::vector< std::unique_ptr< Browsable::RItem > > fLastItems
! created browser items - used in requests
std::unique_ptr< RBrowserDataCleanup > fCleanupHandle
! cleanup handle for RecursiveRemove
Browsable::RElementPath_t fLastPath
! path to last used element
void SetWorkingPath(const Browsable::RElementPath_t &path)
set working directory relative to top element
std::shared_ptr< Browsable::RElement > fTopElement
! top element
std::shared_ptr< Browsable::RElement > GetElement(const std::string &str)
Returns element with path, specified as string.
bool fLastSortReverse
! last request reverse order
void ResetLastRequestData(bool with_element)
Reset all data correspondent to last request.
std::shared_ptr< Browsable::RElement > fLastElement
! last element used in request
void CreateDefaultElements()
Create default elements shown in the RBrowser.
RBrowserData()
Default constructor.
Reply on browser request.
Request send from client to get content of path element.
bool hidden
show hidden files
int number
number of childs to request, 0 - all childs
bool reverse
reverse item order
std::string sort
kind of sorting
std::vector< std::string > path
requested path
bool reload
force items reload
int first
first child to request
std::string regex
applied regex
A log configuration for a channel, e.g.
Definition RLogger.hxx:97
const_iterator begin() const
const_iterator end() const
static TString ToJSON(const T *obj, Int_t compact=0, const char *member_name=nullptr)
Definition TBufferJSON.h:77
@ kSkipTypeInfo
do not store typenames in JSON
Definition TBufferJSON.h:48
@ kNoSpaces
no new lines plus remove all spaces around "," and ":" symbols
Definition TBufferJSON.h:39
Mother of all ROOT objects.
Definition TObject.h:42
std::vector< std::string > RElementPath_t
Definition RElement.hxx:20
ROOT::RLogChannel & BrowserLog()
Log channel for Browser diagnostics.