Logo ROOT  
Reference Guide
RBrowserData.cxx
Go to the documentation of this file.
1// Author: Sergey Linev <S.Linev@gsi.de>
2// Date: 2019-10-14
3// Warning: This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback is welcome!
4
5/*************************************************************************
6 * Copyright (C) 1995-2020, Rene Brun and Fons Rademakers. *
7 * All rights reserved. *
8 * *
9 * For the licensing terms see $ROOTSYS/LICENSE. *
10 * For the list of contributors see $ROOTSYS/README/CREDITS. *
11 *************************************************************************/
12
13#include <ROOT/RBrowserData.hxx>
14
21
22#include <ROOT/RLogger.hxx>
23
24#include "TFolder.h"
25#include "TROOT.h"
26#include "TBufferJSON.h"
27
28#include <algorithm>
29#include <regex>
30
31using namespace ROOT::Experimental;
32using namespace std::string_literals;
33
35 static RLogChannel sLog("ROOT.Browser");
36 return sLog;
37}
38
39
40/** \class ROOT::Experimental::RBrowserData
41\ingroup rbrowser
42\brief Way to browse (hopefully) everything in %ROOT
43*/
44
45/////////////////////////////////////////////////////////////////////
46/// set top element for browsing
47
48void RBrowserData::SetTopElement(std::shared_ptr<Browsable::RElement> elem)
49{
50 fTopElement = elem;
51
53}
54
55/////////////////////////////////////////////////////////////////////
56/// set working directory relative to top element
57
59{
60 fWorkingPath = path;
61
63}
64
65/////////////////////////////////////////////////////////////////////
66/// Create default elements shown in the RBrowser
67
69{
70 auto comp = std::make_shared<Browsable::RGroup>("top","Root browser");
71
73
74 std::unique_ptr<Browsable::RHolder> rootfold = std::make_unique<Browsable::TObjectHolder>(gROOT->GetRootFolder(), kFALSE);
75 auto elem_root = Browsable::RProvider::Browse(rootfold);
76 if (elem_root)
77 comp->Add(std::make_shared<Browsable::RWrapper>("root", elem_root));
78
79 std::unique_ptr<Browsable::RHolder> rootfiles = std::make_unique<Browsable::TObjectHolder>(gROOT->GetListOfFiles(), kFALSE);
80 auto elem_files = Browsable::RProvider::Browse(rootfiles);
81 if (elem_files) {
82 auto files = std::make_shared<Browsable::RWrapper>("ROOT Files", elem_files);
83 files->SetExpandByDefault(true);
84 comp->Add(files);
85 // if there are any open files, make them visible by default
86 if (elem_files->GetNumChilds() > 0)
87 seldir = {};
88 }
89
90 SetTopElement(comp);
91
92 SetWorkingPath(seldir);
93}
94
95/////////////////////////////////////////////////////////////////////
96/// Reset all data correspondent to last request
97
99{
100 fLastAllChilds = false;
101 fLastSortedItems.clear();
102 fLastSortMethod.clear();
103 fLastItems.clear();
104 if (with_element) {
105 fLastPath.clear();
106 fLastElement.reset();
107 }
108}
109
110/////////////////////////////////////////////////////////////////////////
111/// Decompose path to elements
112/// Returns array of names for each element in the path, first element either "/" or "."
113/// If returned array empty - it is error
114
115Browsable::RElementPath_t RBrowserData::DecomposePath(const std::string &strpath, bool relative_to_work_element)
116{
118 if (relative_to_work_element) arr = fWorkingPath;
119
120 if (strpath.empty())
121 return arr;
122
123 auto arr2 = Browsable::RElement::ParsePath(strpath);
124 arr.insert(arr.end(), arr2.begin(), arr2.end());
125 return arr;
126}
127
128/////////////////////////////////////////////////////////////////////////
129/// Process browser request
130
132{
133 auto path = fWorkingPath;
134 path.insert(path.end(), request.path.begin(), request.path.end());
135
136 if ((path != fLastPath) || !fLastElement) {
137
138 auto elem = GetSubElement(path);
139 if (!elem) return false;
140
142
143 fLastPath = path;
144 fLastElement = std::move(elem);
145 } else if (request.reload) {
146 // only reload items from element, not need to reset element itself
148 }
149
150 // when request childs, always try to make elements
151 if (fLastItems.empty()) {
152
153 auto iter = fLastElement->GetChildsIter();
154
155 if (!iter) return false;
156 int id = 0;
157 fLastAllChilds = true;
158
159 while (iter->Next() && fLastAllChilds) {
160 fLastItems.emplace_back(iter->CreateItem());
161 if (id++ > 10000)
162 fLastAllChilds = false;
163 }
164
165 fLastSortedItems.clear();
166 fLastSortMethod.clear();
167 }
168
169 // create sorted array
170 if ((fLastSortedItems.size() != fLastItems.size()) ||
171 (fLastSortMethod != request.sort) ||
172 (fLastSortReverse != request.reverse)) {
173 fLastSortedItems.resize(fLastItems.size(), nullptr);
174 int id = 0;
175 if (request.sort.empty()) {
176 // no sorting, just move all folders up
177 for (auto &item : fLastItems)
178 if (item->IsFolder())
179 fLastSortedItems[id++] = item.get();
180 for (auto &item : fLastItems)
181 if (!item->IsFolder())
182 fLastSortedItems[id++] = item.get();
183 } else {
184 // copy items
185 for (auto &item : fLastItems)
186 fLastSortedItems[id++] = item.get();
187
188 if (request.sort != "unsorted")
189 std::sort(fLastSortedItems.begin(), fLastSortedItems.end(),
190 [request](const Browsable::RItem *a, const Browsable::RItem *b) { return a->Compare(b, request.sort); });
191 }
192
193 if (request.reverse)
194 std::reverse(fLastSortedItems.begin(), fLastSortedItems.end());
195
196 fLastSortMethod = request.sort;
197 fLastSortReverse = request.reverse;
198 }
199
200 const std::regex expr(request.regex);
201
202 int id = 0;
203 for (auto &item : fLastSortedItems) {
204
205 // check if element is hidden
206 if (!request.hidden && item->IsHidden())
207 continue;
208
209 if (!request.regex.empty() && !item->IsFolder() && !std::regex_match(item->GetName(), expr))
210 continue;
211
212 if ((id >= request.first) && ((request.number == 0) || (id < request.first + request.number)))
213 reply.nodes.emplace_back(item);
214
215 id++;
216 }
217
218 reply.first = request.first;
219 reply.nchilds = id; // total number of childs
220
221 return true;
222}
223
224/////////////////////////////////////////////////////////////////////////
225/// Process browser request, returns string with JSON of RBrowserReply data
226
228{
229 RBrowserReply reply;
230
231 reply.path = request.path;
232 reply.first = 0;
233 reply.nchilds = 0;
234
235 ProcessBrowserRequest(request, reply);
236
238}
239
240/////////////////////////////////////////////////////////////////////////
241/// Returns element with path, specified as string
242
243std::shared_ptr<Browsable::RElement> RBrowserData::GetElement(const std::string &str)
244{
245 auto path = DecomposePath(str, true);
246
247 return GetSubElement(path);
248}
249
250/////////////////////////////////////////////////////////////////////////
251/// Returns element with path, specified as Browsable::RElementPath_t
252
253std::shared_ptr<Browsable::RElement> RBrowserData::GetElementFromTop(const Browsable::RElementPath_t &path)
254{
255 return GetSubElement(path);
256}
257
258/////////////////////////////////////////////////////////////////////////
259/// Returns sub-element starting from top, using cached data
260
261std::shared_ptr<Browsable::RElement> RBrowserData::GetSubElement(const Browsable::RElementPath_t &path)
262{
263 if (path.empty())
264 return fTopElement;
265
266 // first check direct match in cache
267 for (auto &entry : fCache)
268 if (entry.first == path)
269 return entry.second;
270
271 // find best possible entry in cache
272 int pos = 0;
273 auto elem = fTopElement;
274
275 for (auto &entry : fCache) {
276 if (entry.first.size() >= path.size())
277 continue;
278
279 auto comp = Browsable::RElement::ComparePaths(path, entry.first);
280
281 if ((comp > pos) && (comp == (int) entry.first.size())) {
282 pos = comp;
283 elem = entry.second;
284 }
285 }
286
287 while (pos < (int) path.size()) {
288 std::string subname = path[pos];
289 int indx = Browsable::RElement::ExtractItemIndex(subname);
290
291 auto iter = elem->GetChildsIter();
292 if (!iter)
293 return nullptr;
294
295 if (!iter->Find(subname, indx)) {
296 if (indx < 0)
297 return nullptr;
298 iter = elem->GetChildsIter();
299 if (!iter || !iter->Find(subname))
300 return nullptr;
301 }
302
303 elem = iter->GetElement();
304
305 if (!elem)
306 return nullptr;
307
308 auto subpath = path;
309 subpath.resize(pos+1);
310 fCache.emplace_back(subpath, elem);
311 pos++; // switch to next element
312 }
313
314 return elem;
315}
316
317/////////////////////////////////////////////////////////////////////////
318/// Clear internal objects cache
319
321{
322 fCache.clear();
323}
#define b(i)
Definition: RSha256.hxx:100
const Bool_t kFALSE
Definition: RtypesCore.h:101
XFontStruct * id
Definition: TGX11.cxx:109
#define gROOT
Definition: TROOT.h:404
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:164
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:131
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:102
Representation of single item in the browser.
Definition: RItem.hxx:24
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.
Definition: RProvider.cxx:268
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 "Files ...
Definition: RSysFile.cxx:529
void SetTopElement(std::shared_ptr< Browsable::RElement > elem)
set top element for browsing
std::string fLastSortMethod
! last sort method
std::shared_ptr< Browsable::RElement > GetSubElement(const Browsable::RElementPath_t &path)
Returns sub-element starting from top, using cached data.
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 ProcessBrowserRequest(const RBrowserRequest &request, RBrowserReply &reply)
Process browser request.
std::vector< std::pair< Browsable::RElementPath_t, std::shared_ptr< Browsable::RElement > > > fCache
! already requested elements
std::shared_ptr< Browsable::RElement > GetElementFromTop(const Browsable::RElementPath_t &path)
Returns element with path, specified as Browsable::RElementPath_t.
void ClearCache()
Clear internal objects cache.
std::vector< const Browsable::RItem * > fLastSortedItems
! sorted child items, used in requests
bool fLastAllChilds
! if all chlds were extracted
std::string ProcessRequest(const RBrowserRequest &request)
Process browser request, returns string with JSON of RBrowserReply data.
Browsable::RElementPath_t fWorkingPath
! path showed in Breadcrumb
bool fLastSortReverse
! last request reverse order
Browsable::RElementPath_t fLastPath
! path to last used element
std::shared_ptr< Browsable::RElement > fTopElement
! top element
void SetWorkingPath(const Browsable::RElementPath_t &path)
set working directory relative to top element
std::shared_ptr< Browsable::RElement > fLastElement
! last element used in request
std::shared_ptr< Browsable::RElement > GetElement(const std::string &str)
Returns element with path, specified as string.
std::vector< std::unique_ptr< Browsable::RItem > > fLastItems
! created browser items - used in requests
void ResetLastRequestData(bool with_element)
Reset all data correspondent to last request.
void CreateDefaultElements()
Create default elements shown in the RBrowser.
Reply on browser request.
std::vector< const Browsable::RItem * > nodes
list of pointers, no ownership!
std::vector< std::string > path
reply path
int nchilds
total number of childs in the node
int first
first node in returned list
Request send from client to get content of path element.
std::vector< std::string > path
requested path
int first
first child to request
int number
number of childs to request, 0 - all childs
std::string sort
kind of sorting
A log configuration for a channel, e.g.
Definition: RLogger.hxx:101
static TString ToJSON(const T *obj, Int_t compact=0, const char *member_name=nullptr)
Definition: TBufferJSON.h:75
@ 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
const char * Data() const
Definition: TString.h:369
std::vector< std::string > RElementPath_t
Definition: RElement.hxx:21
RLogChannel & BrowserLog()
Log channel for Browser diagnostics.
auto * a
Definition: textangle.C:12