NCBI C++ ToolKit
track_info.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* $Id: track_info.cpp 47136 2022-09-08 13:55:49Z evgeniev $
2  * ===========================================================================
3  *
4  * PUBLIC DOMAIN NOTICE
5  * National Center for Biotechnology Information
6  *
7  * This software/database is a "United States Government Work" under the
8  * terms of the United States Copyright Act. It was written as part of
9  * the author's official duties as a United States Government employee and
10  * thus cannot be copyrighted. This software/database is freely available
11  * to the public for use. The National Library of Medicine and the U.S.
12  * Government have not placed any restriction on its use or reproduction.
13  *
14  * Although all reasonable efforts have been taken to ensure the accuracy
15  * and reliability of the software and data, the NLM and the U.S.
16  * Government do not and cannot warrant the performance or results that
17  * may be obtained by using this software or data. The NLM and the U.S.
18  * Government disclaim all warranties, express or implied, including
19  * warranties of performance, merchantability or fitness for any particular
20  * purpose.
21  *
22  * Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * Author: Dmitry Rudnev
27  *
28  * File Description:
29  * Implements the functions in track_info.hpp
30  */
31 
32 #include <ncbi_pch.hpp>
33 
34 #include <set>
35 #include <sstream>
36 
37 #include <gui/utils/track_info.hpp>
38 
39 
41 
42 const size_t TTrackErrorStatus::cShortErrorLength = 27;
43 
44 
45 
47 const string CTrackUtils::cTrackSettingKey_ErrorSeverity = "###severity";
48 const string CTrackUtils::cTrackSettingKey_ErrorCode = "###code";
49 const string CTrackUtils::cTrackSettingKey_ErrorShortMsg = "###short_msg";
50 const string CTrackUtils::cTrackSettingKey_ErrorMsg = "###msg";
51 
52 const string CTrackUtils::kStdTrackId = "STD";
53 const string CTrackUtils::kRStdTrackId = "R" + kStdTrackId;
54 
55 static
56 string s_SVURLDecode(const string& src)
57 {
58  string dst;
59 
60  SIZE_TYPE len = src.length();
61  if ( !len ) {
62  return dst;
63  }
64 
65  dst.resize(len);
66 
67  SIZE_TYPE pdst = 0;
68  for (SIZE_TYPE psrc = 0; psrc < len; pdst++) {
69  switch ( src[psrc] ) {
70  case '\\': {
71  if (psrc + 2 > len) {
72  dst[pdst] = src[psrc++];
73  } else {
74  int n1 = NStr::HexChar(src[psrc+1]);
75  int n2 = NStr::HexChar(src[psrc+2]);
76  if (n1 < 0 || n1 > 15 || n2 < 0 || n2 > 15) {
77  dst[pdst] = src[psrc++];
78  } else {
79  dst[pdst] = (n1 << 4) | n2;
80  psrc += 3;
81  }
82  }
83  break;
84  }
85  default:
86  dst[pdst] = src[psrc++];
87  }
88  }
89  if (pdst < len) {
90  dst.resize(pdst);
91  }
92 // cerr << "s_SVURLDecode(): src/dst/" << src << "/" << dst << "/" << endl;
93  return dst;
94 }
95 
96 
97 void CTrackUtils::ExtractTrackConfig(const string& track_str,
98  TTrackSettingsSet& settings_set,
99  list<string> *warning_messages)
100 {
101  settings_set.clear();
102  if (track_str.empty() ) return;
103 
104  set<string> track_names;
105  typedef vector<string> TTokens;
106  TTokens tracks;
107 
108  CTrackUtils::TokenizeWithEscape(track_str, ";][", tracks, true);
109  ITERATE (TTokens, t_iter, tracks) {
110  TTokens key_values;
111  TTrackSettings settings;
112  CTrackUtils::TokenizeWithEscape(*t_iter, ",", key_values, true);
113  ITERATE (TTokens, kv_iter, key_values) {
114  TTokens key_value_pair;
115  CTrackUtils::TokenizeWithEscape(*kv_iter, ":", key_value_pair, true);
116  if (key_value_pair.size() == 2) {
117  NStr::TruncateSpacesInPlace(key_value_pair[0]);
118  //NStr::TruncateSpacesInPlace(key_value_pair[1]);
119  if ( !key_value_pair[0].empty() &&
120  !key_value_pair[1].empty() ) {
121 
122  if (key_value_pair[0] == "name") { // Prevent tracks names duplication
123  string track_name = key_value_pair[1];
124  unsigned name_count = 1;
125  while (track_names.end() != track_names.find(track_name)) {
126  stringstream new_name;
127  new_name << key_value_pair[1] << " (" << ++name_count << ')';
128  track_name = new_name.str();
129  }
130  track_names.insert(track_name);
131  if (key_value_pair[1] != track_name) {
132  if (warning_messages) {
133  stringstream warning;
134  warning << "Track name \"" << key_value_pair[1] << "\" already exists. Using \"" << track_name << "\" instead.";
135  warning_messages->push_back(warning.str());
136  }
137  key_value_pair[1] = track_name;
138  }
139  }
140 
141  //!! temporary hack to preserve "is_scaled" to have the same meaning as "stored_scale" for some time (see SV-2703)
142  if(key_value_pair[0] == "is_scaled") {
143  settings[ "stored_scale" ] = s_SVURLDecode(NStr::URLDecode(key_value_pair[1]));
144  } else {
145  settings[ key_value_pair[0] ] = s_SVURLDecode(NStr::URLDecode(key_value_pair[1]));
146  }
147  }
148  }
149  }
150  if ( !settings.empty() ) {
151  // if the id of this track is not STD (i.e. TMS), check that a track with the same id has not yet been processed;
152  // if it has, merge/override settings from this one
153  if(isTMSId(settings)) {
154  string sTMSId;
155  GetKey(settings, "id", sTMSId);
156  TTrackSettingsSetSelection TracksWithTheSameId;
157  GetTrackSettingsSetSelection(settings_set, "id", sTMSId, TracksWithTheSameId);
158  if(!TracksWithTheSameId.empty()) {
159  TTrackSettings& duplicate_settings(*TracksWithTheSameId.front());
160  for(const auto& iSettings: settings) {
161  duplicate_settings[iSettings.first] = iSettings.second;
162  }
163  continue;
164  }
165  }
166  string annots;
167  GetKey(settings, "annots", annots);
168  if (NStr::StartsWith(annots, "http", NStr::eNocase) || NStr::StartsWith(annots, "ftp", NStr::eNocase)) {
169  if (0 == settings.count("remote_path")) {
170  settings["remote_path"] = annots;
171  }
172  }
173  settings_set.push_back(settings);
174  }
175  }
176 }
177 
178 
179 bool CTrackUtils::HasTrack(const string& track_key,
180  const TTrackSettingsSet& settings_set)
181 {
182  ITERATE (TTrackSettingsSet, iter, settings_set) {
183  TTrackSettings::const_iterator k_iter = iter->find("key");
184  if (k_iter != iter->end() &&
185  NStr::StartsWith(k_iter->second, track_key, NStr::eNocase)) {
186  return true;
187  }
188  }
189  return false;
190 }
191 
192 
193 bool CTrackUtils::HasTrack(const string& track_key,
194  const string& track_name,
195  const TTrackSettingsSet& settings_set)
196 {
197  ITERATE (TTrackSettingsSet, iter, settings_set) {
198  TTrackSettings::const_iterator k_iter = iter->find("key");
199  TTrackSettings::const_iterator n_iter = iter->find("name");
200  if (k_iter != iter->end() && n_iter != iter->end() &&
201  n_iter->second == track_name &&
202  NStr::StartsWith(k_iter->second, track_key, NStr::eNocase)) {
203  return true;
204  }
205  }
206  return false;
207 }
208 
209 /// returns true if the track id in settings looks like a TMS track id (i.e. is present, not empty and does not start with STD)
210 /// this does not guarantee nor check that it actually exists in TMS
211 bool CTrackUtils::isTMSId(const TTrackSettings& TrackSettings)
212 {
213  string sTrackID;
214  return CTrackUtils::GetKey(TrackSettings, "id", sTrackID) && sTrackID.find(kStdTrackId) != 0 && sTrackID.find(kRStdTrackId) != 0;
215 }
216 
217 /// Returns true if the track uses remote (non NCBI hosted) data
218 bool CTrackUtils::isRemoteData(const TTrackSettings& TrackSettings)
219 {
220  string track_id;
221  CTrackUtils::GetKey(TrackSettings, "id", track_id);
222  if (NStr::StartsWith(track_id, 'R') || NStr::StartsWith(track_id, 'U')) {
223  return true;
224  }
225 
226  string annots;
227  CTrackUtils::GetKey(TrackSettings, "annots", annots);
228  if (NStr::StartsWith(annots, "http", NStr::eNocase) || NStr::StartsWith(annots, "ftp", NStr::eNocase)) {
229  return true;
230  }
231 
232  return false;
233 }
234 
235 
236 
237 static const string& kBAM_DATA = "BAM";
238 
240 {
241  TDataKeys keys;
242  ITERATE (TTrackSettingsSet, iter, settings_set) {
243  TTrackSettings::const_iterator key_iter = iter->find("data_key");
244  if (key_iter != iter->end()) {
245  TTrackSettings::const_iterator db_iter = iter->find("dbname");
246  if (db_iter != iter->end() && db_iter->second == kBAM_DATA)
247  continue;
248  vector<string> mkeys;
249  NStr::Split(CTrackUtils::RemoveEscape(key_iter->second), "|", mkeys);
250  ITERATE (vector<string>, mkey_iter, mkeys) {
251  string key = NStr::TruncateSpaces(*mkey_iter);
252  if ( !key.empty() ) {
253  keys.push_back(key);
254  }
255  }
256  }
257  }
258  return keys;
259 }
260 
261 /// get all tracks that have a given value in a given key
262 /// the entries in TrackSettingsSetSelection are valid while the respective entries are not removed from TrackSettingsSet
263 void CTrackUtils::GetTrackSettingsSetSelection(TTrackSettingsSet& TrackSettingsSet, const string& key, const string& value,
264  TTrackSettingsSetSelection& TrackSettingsSetSelection)
265 {
266  TrackSettingsSetSelection.clear();
267  NON_CONST_ITERATE(TTrackSettingsSet, iTrackSettingsSet, TrackSettingsSet) {
268  TTrackSettings::const_iterator iTrackSettings = iTrackSettingsSet->find(key);
269  if (iTrackSettings != iTrackSettingsSet->end() &&
270  iTrackSettings->second == value) {
271  TrackSettingsSetSelection.push_back(iTrackSettingsSet);
272  }
273  }
274 }
275 
276 /// returns a specified key; if it does not exist, returns false
277 bool CTrackUtils::GetKey(const TTrackSettings& TrackSettings, const string& key, string& value)
278 {
279  value.clear();
280  TTrackSettings::const_iterator key_iter = TrackSettings.find(key);
281  if (key_iter == TrackSettings.end()) {
282  return false;
283  }
284  value = key_iter->second;
285  return true;
286 }
287 
288 void CTrackUtils::SetKey(TTrackSettings& TrackSettings, const string& key, const string& value)
289 {
290  TrackSettings[key] = value;
291 }
292 
293 
294 
295 /// set error information in the track configuration
296 /// error codes and such should correspond to ones in CHTMLActiveArea
300  const string& short_msg,
301  const string& msg)
302 {
303  TrackSettings[cTrackSettingKey_ErrorSeverity] = NStr::IntToString(severity);
305  TrackSettings[cTrackSettingKey_ErrorShortMsg] = short_msg.substr(0, TTrackErrorStatus::cShortErrorLength);
306  TrackSettings[cTrackSettingKey_ErrorMsg] = msg;
307  LOG_POST(Warning << "Track error detected, code: " << code << ", message: " << msg);
308 }
309 
310 /// check that the track is currently marked as having an error
312 {
313  string severity;
314  //!! should warnings be treated as errors?
316 }
317 
318 string CTrackUtils::RemoveEscape(const string &str)
319 {
320  // Special cases
321  if (str.empty()) {
322  return str;
323  }
324 
325  string::size_type len = str.length();
326  string out;
327  out.resize(len);
328 
329  string::size_type pdst = 0;
330  bool escape = false;
331  for (string::size_type psrc = 0; psrc < len; ++psrc) {
332  const char& curr_char = str[psrc];
333  if (curr_char == '\\' && !escape ) {
334  escape = true;
335  } else {
336  out[pdst++] = curr_char;
337  if (escape) {
338  escape = false;
339  }
340  }
341  }
342 
343  if (pdst < len) {
344  out[pdst] = '\0';
345  out.resize(pdst);
346  }
347 
348  return out;
349 }
350 
351 
353  const string &delim,
354  vector<string>& tokens,
355  bool remove_escape)
356 {
357  // Special cases
358  if (str.empty()) {
359  return;
360  } else if (delim.empty()) {
361  tokens.push_back(str);
362  return;
363  }
364 
365  // Tokenization
366  //
367  string::size_type pos = 0;
368  bool escape = false;
369  string curr_str = "";
370  while (pos < str.size()) {
371  const char& curr_char = str[pos];
372  if (curr_char == '\\') {
373  if ( !escape ) {
374  escape = true;
375  ++pos;
376  continue;
377  }
378  }
379 
380  bool match = delim.find(curr_char) != string::npos;
381  if (match) {
382  if (escape) {
383  if ( !remove_escape ) {
384  curr_str.append(1, '\\');
385  }
386  curr_str.append(1, curr_char);
387  escape = false;
388  } else if ( !curr_str.empty() ) {
389  tokens.push_back(curr_str);
390  curr_str.clear();
391  }
392  } else {
393  if (escape) {
394  curr_str.append(1, '\\');
395  curr_str.append(1, curr_char);
396  escape = false;
397  } else {
398  curr_str.append(1, curr_char);
399  }
400  }
401  ++pos;
402  }
403 
404  if ( !curr_str.empty() ) {
405  tokens.push_back(curr_str);
406  }
407 }
408 
409 
410 
412 
container_type::const_iterator const_iterator
Definition: map.hpp:53
const_iterator end() const
Definition: map.hpp:152
bool empty() const
Definition: map.hpp:149
const_iterator find(const key_type &key) const
Definition: map.hpp:153
iterator_bool insert(const value_type &val)
Definition: set.hpp:149
const_iterator find(const key_type &key) const
Definition: set.hpp:137
const_iterator end() const
Definition: set.hpp:136
std::ofstream out("events_result.xml")
main entry point for tests
static const char * str(char *buf, int n)
Definition: stats.c:84
#define ITERATE(Type, Var, Cont)
ITERATE macro to sequence through container elements.
Definition: ncbimisc.hpp:815
#define NON_CONST_ITERATE(Type, Var, Cont)
Non constant version of ITERATE macro.
Definition: ncbimisc.hpp:822
#define LOG_POST(message)
This macro is deprecated and it's strongly recomended to move in all projects (except tests) to macro...
Definition: ncbidiag.hpp:226
void Warning(CExceptionArgs_Base &args)
Definition: ncbiexpt.hpp:1191
static void SetError(TTrackSettings &TrackSettings, TTrackErrorStatus::TErrorSeverity severity, TTrackErrorStatus::TErrorCode code, const string &short_msg, const string &msg)
set error information in the track configuration error codes and such should correspond to ones in CH...
Definition: track_info.cpp:297
static const size_t cShortErrorLength
Definition: track_info.hpp:95
static void GetTrackSettingsSetSelection(TTrackSettingsSet &TrackSettingsSet, const string &key, const string &value, TTrackSettingsSetSelection &TrackSettingsSetSelection)
get all tracks that have a given value in a given key the entries in TrackSettingsSetSelection are va...
Definition: track_info.cpp:263
list< TTrackSettings > TTrackSettingsSet
Definition: track_info.hpp:123
static const string kStdTrackId
prefix for STD (as opposed to TMS) tracks
Definition: track_info.hpp:140
static const string cTrackSettingKey_ErrorShortMsg
if present contains the short error message
Definition: track_info.hpp:135
static void SetKey(TTrackSettings &TrackSettings, const string &key, const string &value)
Definition: track_info.cpp:288
static const string cTrackSettingKey_ErrorMsg
if present contains the error message
Definition: track_info.hpp:137
static const string cTrackSettingKey_ErrorSeverity
if present and set to anything, but CHTMLActiveArea::eErrorSeverity_NoError, do not attempt to load t...
Definition: track_info.hpp:131
static bool GetKey(const TTrackSettings &TrackSettings, const string &key, string &value)
returns a specified key; if it does not exist, returns false
Definition: track_info.cpp:277
static bool HasTrack(const string &track_key, const TTrackSettingsSet &settings_set)
Check if track settings contain the track of a given track key.
Definition: track_info.cpp:179
static bool isInErrorStatus(const TTrackSettings &TrackSettings)
check that the track is currently marked as having an error
Definition: track_info.cpp:311
static string RemoveEscape(const string &str)
remove escape characters ('\') used for escaping special characters in track settings values
Definition: track_info.cpp:318
static const string kRStdTrackId
prefix for Remote STD (as opposed to TMS) tracks
Definition: track_info.hpp:143
static const string cTrackSettingKey_PrivatePrefix
some internal reserved track setting keys that are used for internal communication always start with ...
Definition: track_info.hpp:129
static bool isRemoteData(const TTrackSettings &TrackSettings)
Returns true if the track uses remote (non NCBI hosted) data.
Definition: track_info.cpp:218
static bool isTMSId(const TTrackSettings &TrackSettings)
returns true if the track id in settings looks like a TMS track id (i.e.
Definition: track_info.cpp:211
static void TokenizeWithEscape(const string &str, const string &delim, vector< string > &tokens, bool remove_escape=false)
Tokenize a string using the delim.
Definition: track_info.cpp:352
vector< string > TDataKeys
Definition: track_info.hpp:119
static const string cTrackSettingKey_ErrorCode
if present contains the error code
Definition: track_info.hpp:133
list< TTrackSettingsSet::iterator > TTrackSettingsSetSelection
Definition: track_info.hpp:124
static TDataKeys GetAllDataKeys(const TTrackSettingsSet &settings_set)
Collect all data key values stored in 'data_key'.
Definition: track_info.cpp:239
static void ExtractTrackConfig(const string &track_str, TTrackSettingsSet &settings_set, list< string > *warning_messages=nullptr)
Extract the track settings from a setting string.
Definition: track_info.cpp:97
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
NCBI_NS_STD::string::size_type SIZE_TYPE
Definition: ncbistr.hpp:132
static list< string > & Split(const CTempString str, const CTempString delim, list< string > &arr, TSplitFlags flags=0, vector< SIZE_TYPE > *token_pos=NULL)
Split a string using specified delimiters.
Definition: ncbistr.cpp:3452
static string URLDecode(const CTempString str, EUrlDecode flag=eUrlDec_All)
URL-decode string.
Definition: ncbistr.cpp:6205
static void TruncateSpacesInPlace(string &str, ETrunc where=eTrunc_Both)
Truncate whitespace in a string (in-place)
Definition: ncbistr.cpp:3192
static string IntToString(int value, TNumToStringFlags flags=0, int base=10)
Convert int to string.
Definition: ncbistr.hpp:5086
static int HexChar(char ch)
Convert character to integer.
Definition: ncbistr.hpp:5198
static bool StartsWith(const CTempString str, const CTempString start, ECase use_case=eCase)
Check if a string starts with a specified prefix value.
Definition: ncbistr.hpp:5414
static string TruncateSpaces(const string &str, ETrunc where=eTrunc_Both)
Truncate whitespace in a string.
Definition: ncbistr.cpp:3177
@ eNocase
Case insensitive compare.
Definition: ncbistr.hpp:1206
int len
constexpr bool empty(list< Ts... >) noexcept
const struct ncbi::grid::netcache::search::fields::KEY key
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1227
static int match(register const pcre_uchar *eptr, register const pcre_uchar *ecode, const pcre_uchar *mstart, int offset_top, match_data *md, eptrblock *eptrb, unsigned int rdepth)
Definition: pcre_exec.c:513
Definition: inftrees.h:24
static string s_SVURLDecode(const string &src)
Definition: track_info.cpp:56
static const string & kBAM_DATA
Definition: track_info.cpp:237
list< STokenInfo > TTokens
Definition: xgbparint.cpp:88
Modified on Fri Jul 19 17:10:20 2024 by modify_doxy.py rev. 669887