libdap  Updated for version 3.20.6
libdap4 is an implementation of OPeNDAP's DAP protocol.
Keywords2.cc
1 // -*- mode: c++; c-basic-offset:4 -*-
2 
3 // This file is part of libdap, A C++ implementation of the OPeNDAP Data
4 // Access Protocol.
5 
6 // Copyright (c) 2011 OPeNDAP, Inc.
7 // Author: James Gallagher <jgallagher@opendap.org>
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2.1 of the License, or (at your option) any later version.
13 //
14 // This library is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 // Lesser General Public License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 //
23 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
24 #include "config.h"
25 
26 #include <iostream>
27 #include <vector>
28 
29 //#define DODS_DEBUG
30 
31 #include "Keywords2.h"
32 #include "Error.h"
33 #include "escaping.h"
34 #include "debug.h"
35 
36 using namespace std;
37 
38 namespace libdap {
39 
40 Keywords::Keywords()
41 {
42  // Load known keywords and their allowed values
43  vector<string> v1(7);
44  v1[0] = "2"; v1[1] = "2.0"; v1[2] = "3.2"; v1[3] = "3.3"; v1[4] = "3.4";
45  v1[5] = "4"; v1[6] = "4.0";
46  value_set_t vs = value_set_t(v1.begin(), v1.end());
47  d_known_keywords["dap"] = vs;
48 
49  vector<string> v2(4);
50  v2[0] = "md5"; v2[1] = "MD5"; v2[2] = "sha1"; v2[3] = "SHA1";
51  value_set_t vs2 = value_set_t(v2.begin(), v2.end());
52  d_known_keywords["checksum"] = vs2;
53 }
54 
55 Keywords::~Keywords()
56 {
57 }
58 
66 static bool f_parse_keyword(const string &kw, string &word, string &value)
67 {
68  word = "";
69  value = "";
70  string::size_type i = kw.find('(');
71  if (i == string::npos)
72  return false;
73  word = kw.substr(0, i);
74  string::size_type j = kw.find(')');
75  if (j == string::npos)
76  return false;
77  ++i; // Move past the opening paren
78  value = kw.substr(i, j-i);
79 
80  return (!word.empty() && !value.empty());
81 }
82 
89 void Keywords::m_add_keyword(const keyword &word, const keyword_value &value)
90 {
91  d_parsed_keywords[word] = value;
92 }
93 
101 bool Keywords::m_is_valid_keyword(const keyword &word, const keyword_value &value) const
102 {
103  map<keyword, value_set_t>::const_iterator ci = d_known_keywords.find(word);
104  if (ci == d_known_keywords.end())
105  return false;
106  else {
107  value_set_t vs = ci->second;
108 
109  if (vs.find(value) == vs.end())
110  throw Error("Bad value passed to the keyword/function: " + word);
111  }
112 
113  return true;
114 }
115 
121 bool Keywords::is_known_keyword(const string &word) const
122 {
123  return d_known_keywords.count(word) == 1;
124 }
125 
131 list<Keywords::keyword> Keywords::get_keywords() const
132 {
133  list<keyword> kws;
134  map<keyword, keyword_value>::const_iterator i;
135  for (i = d_parsed_keywords.begin(); i != d_parsed_keywords.end(); ++i)
136  kws.push_front((*i).first);
137 
138  return kws;
139 }
140 
141 
148 bool Keywords::has_keyword(const keyword &kw) const
149 {
150  return d_parsed_keywords.count(kw) == 1;
151 }
152 
158 Keywords::keyword_value Keywords::get_keyword_value(const keyword &kw) const
159 {
160  if (d_known_keywords.find(kw) == d_known_keywords.end())
161  throw Error("Keyword not known (" + kw + ")");
162 
163  return d_parsed_keywords.find(kw)->second;
164 }
165 
171 string Keywords::parse_keywords(const string &ce)
172 {
173  // Get the whole CE
174  string projection = www2id(ce, "%", "%20");
175  string selection = "";
176 
177  // Separate the selection part (which follows/includes the first '&')
178  string::size_type amp = projection.find('&');
179  if (amp != string::npos) {
180  selection = projection.substr(amp);
181  projection = projection.substr(0, amp);
182  }
183 
184  // Extract keywords; add to the Keywords keywords. For this, scan for
185  // a known set of keywords and assume that anything else is part of the
186  // projection and should be left alone. Keywords must come before variables
187  // The 'projection' string will look like: '' or 'dap4.0' or 'dap4.0,u,v'
188  while (!projection.empty()) {
189  string::size_type i = projection.find(',');
190  string next_word = projection.substr(0, i);
191  string word, value;
192  if (f_parse_keyword(next_word, word, value)
193  && m_is_valid_keyword(word, value)) {
194  m_add_keyword(word, value);
195  if (i != string::npos)
196  projection = projection.substr(i + 1);
197  else
198  projection = "";
199  }
200  else {
201  break; // exit on first non-keyword
202  }
203  }
204 
205  // The CE is whatever is left after removing the keywords
206  return projection + selection;
207 }
208 
209 }
STL namespace.
top level DAP object to house generic methods
Definition: AISConnect.cc:30
string www2id(const string &in, const string &escape, const string &except)
Definition: escaping.cc:220
A class for error processing.
Definition: Error.h:92