libdap  Updated for version 3.17.0
Keywords2.cc
00001 // -*- mode: c++; c-basic-offset:4 -*-
00002 
00003 // This file is part of libdap, A C++ implementation of the OPeNDAP Data
00004 // Access Protocol.
00005 
00006 // Copyright (c) 2011 OPeNDAP, Inc.
00007 // Author: James Gallagher <jgallagher@opendap.org>
00008 //
00009 // This library is free software; you can redistribute it and/or
00010 // modify it under the terms of the GNU Lesser General Public
00011 // License as published by the Free Software Foundation; either
00012 // version 2.1 of the License, or (at your option) any later version.
00013 //
00014 // This library is distributed in the hope that it will be useful,
00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017 // Lesser General Public License for more details.
00018 //
00019 // You should have received a copy of the GNU Lesser General Public
00020 // License along with this library; if not, write to the Free Software
00021 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00022 //
00023 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
00024 #include "config.h"
00025 
00026 #include <iostream>
00027 #include <vector>
00028 
00029 //#define DODS_DEBUG
00030 
00031 #include "Keywords2.h"
00032 #include "Error.h"
00033 #include "escaping.h"
00034 #include "debug.h"
00035 
00036 using namespace std;
00037 
00038 namespace libdap {
00039 
00040 Keywords::Keywords()
00041 {
00042     // Load known keywords and their allowed values
00043     vector<string> v1(7);
00044     v1[0] = "2"; v1[1] = "2.0"; v1[2] = "3.2"; v1[3] = "3.3"; v1[4] = "3.4";
00045     v1[5] = "4"; v1[6] = "4.0";
00046     value_set_t vs = value_set_t(v1.begin(), v1.end());
00047     d_known_keywords["dap"] = vs;
00048 
00049     vector<string> v2(4);
00050     v2[0] = "md5"; v2[1] = "MD5"; v2[2] = "sha1"; v2[3] = "SHA1";
00051     value_set_t vs2 = value_set_t(v2.begin(), v2.end());
00052     d_known_keywords["checksum"] = vs2;
00053 }
00054 
00055 Keywords::~Keywords()
00056 {
00057 }
00058 
00066 static bool f_parse_keyword(const string &kw, string &word, string &value)
00067 {
00068     word = "";
00069     value = "";
00070     string::size_type i = kw.find('(');
00071     if (i == string::npos)
00072         return false;
00073     word = kw.substr(0, i);
00074     string::size_type j = kw.find(')');
00075     if (j == string::npos)
00076         return false;
00077     ++i; // Move past the opening paren
00078     value = kw.substr(i, j-i);
00079 
00080     return (!word.empty() && !value.empty());
00081 }
00082 
00089 void Keywords::m_add_keyword(const keyword &word, const keyword_value &value)
00090 {
00091     d_parsed_keywords[word] = value;
00092 }
00093 
00101 bool Keywords::m_is_valid_keyword(const keyword &word, const keyword_value &value) const
00102 {
00103     map<keyword, value_set_t>::const_iterator ci = d_known_keywords.find(word);
00104     if (ci == d_known_keywords.end())
00105         return false;
00106     else {
00107         value_set_t vs = ci->second;
00108 
00109         if (vs.find(value) == vs.end())
00110             throw Error("Bad value passed to the keyword/function: " + word);
00111     }
00112 
00113     return true;
00114 }
00115 
00121 bool Keywords::is_known_keyword(const string &word) const
00122 {
00123         return d_known_keywords.count(word) == 1;
00124 }
00125 
00131 list<Keywords::keyword> Keywords::get_keywords() const
00132 {
00133     list<keyword> kws;
00134     map<keyword, keyword_value>::const_iterator i;
00135     for (i = d_parsed_keywords.begin(); i != d_parsed_keywords.end(); ++i)
00136         kws.push_front((*i).first);
00137 
00138     return kws;
00139 }
00140 
00141 
00148 bool Keywords::has_keyword(const keyword &kw) const
00149 {
00150     return d_parsed_keywords.count(kw) == 1;
00151 }
00152 
00158 Keywords::keyword_value Keywords::get_keyword_value(const keyword &kw) const
00159 {
00160     if (d_known_keywords.find(kw) == d_known_keywords.end())
00161         throw Error("Keyword not known (" + kw + ")");
00162 
00163     return d_parsed_keywords.find(kw)->second;
00164 }
00165 
00171 string Keywords::parse_keywords(const string &ce)
00172 {
00173     // Get the whole CE
00174     string projection = www2id(ce, "%", "%20");
00175     string selection = "";
00176 
00177     // Separate the selection part (which follows/includes the first '&')
00178     string::size_type amp = projection.find('&');
00179     if (amp != string::npos) {
00180         selection = projection.substr(amp);
00181         projection = projection.substr(0, amp);
00182     }
00183 
00184     // Extract keywords; add to the Keywords keywords. For this, scan for
00185     // a known set of keywords and assume that anything else is part of the
00186     // projection and should be left alone. Keywords must come before variables
00187     // The 'projection' string will look like: '' or 'dap4.0' or 'dap4.0,u,v'
00188     while (!projection.empty()) {
00189         string::size_type i = projection.find(',');
00190         string next_word = projection.substr(0, i);
00191         string word, value;
00192         if (f_parse_keyword(next_word, word, value)
00193             && m_is_valid_keyword(word, value)) {
00194             m_add_keyword(word, value);
00195             if (i != string::npos)
00196                 projection = projection.substr(i + 1);
00197             else
00198                 projection = "";
00199         }
00200         else {
00201             break; // exit on first non-keyword
00202         }
00203     }
00204 
00205     // The CE is whatever is left after removing the keywords
00206     return projection + selection;
00207 }
00208 
00209 }