libdap++  Updated for version 3.8.2
Keywords2.cc
Go to the documentation of this file.
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00022 //
00023 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
00024 #include "config.h"
00025 
00026 static char rcsid[] not_used = { "$Id: ResponseBuilder.cc 23477 2010-09-02 21:02:59Z jimg $" };
00027 
00028 #include <iostream>
00029 #include <vector>
00030 
00031 //#define DODS_DEBUG
00032 
00033 #include "Keywords2.h"
00034 #include "Error.h"
00035 #include "escaping.h"
00036 #include "debug.h"
00037 
00038 using namespace std;
00039 
00040 namespace libdap {
00041 
00042 Keywords::Keywords()
00043 {
00044     // Load known keywords and their allowed values
00045     vector<string> v1(7);
00046     v1[0] = "2"; v1[1] = "2.0"; v1[2] = "3.2"; v1[3] = "3.3"; v1[4] = "3.4";
00047     v1[5] = "4"; v1[6] = "4.0";
00048     value_set_t vs = value_set_t(v1.begin(), v1.end());
00049     d_known_keywords["dap"] = vs;
00050 
00051     vector<string> v2(4);
00052     v2[0] = "md5"; v2[1] = "MD5"; v2[2] = "sha1"; v2[3] = "SHA1";
00053     value_set_t vs2 = value_set_t(v2.begin(), v2.end());
00054     d_known_keywords["checksum"] = vs2;
00055 }
00056 
00057 Keywords::~Keywords()
00058 {
00059 }
00060 
00068 static bool f_parse_keyword(const string &kw, string &word, string &value)
00069 {
00070     word = "";
00071     value = "";
00072     string::size_type i = kw.find('(');
00073     if (i == string::npos)
00074         return false;
00075     word = kw.substr(0, i);
00076     string::size_type j = kw.find(')');
00077     if (j == string::npos)
00078         return false;
00079     ++i; // Move past the opening brace
00080     value = kw.substr(i, j-i);
00081 
00082     return (!word.empty() && !value.empty());
00083 }
00084 
00091 void Keywords::m_add_keyword(const keyword &word, const keyword_value &value)
00092 {
00093     d_parsed_keywords[word] = value;
00094 }
00095 
00103 bool Keywords::m_is_valid_keyword(const keyword &word, const keyword_value &value) const
00104 {
00105     map<keyword, value_set_t>::const_iterator ci = d_known_keywords.find(word);
00106     if (ci == d_known_keywords.end())
00107         return false;
00108     else {
00109         value_set_t vs = ci->second;
00110 
00111         if (vs.find(value) == vs.end())
00112             throw Error("Bad value passed to the keyword/function: " + word);
00113     }
00114 
00115     return true;
00116 }
00117 
00123 bool Keywords::is_known_keyword(const string &word) const
00124 {
00125         return d_known_keywords.count(word) == 1;
00126 }
00127 
00133 list<Keywords::keyword> Keywords::get_keywords() const
00134 {
00135     list<keyword> kws;
00136     map<keyword, keyword_value>::const_iterator i;
00137     for (i = d_parsed_keywords.begin(); i != d_parsed_keywords.end(); ++i)
00138         kws.push_front((*i).first);
00139 
00140     return kws;
00141 }
00142 
00143 
00150 bool Keywords::has_keyword(const keyword &kw) const
00151 {
00152     return d_parsed_keywords.count(kw) == 1;
00153 }
00154 
00160 Keywords::keyword_value Keywords::get_keyword_value(const keyword &kw) const
00161 {
00162     if (d_known_keywords.find(kw) == d_known_keywords.end())
00163         throw Error("Keyword not known (" + kw + ")");
00164 
00165     return d_parsed_keywords.find(kw)->second;
00166 }
00167 
00173 string Keywords::parse_keywords(const string &ce)
00174 {
00175     // Get the whole CE
00176     string projection = www2id(ce, "%", "%20");
00177     string selection = "";
00178 
00179     // Separate the selection part (which follows/includes the first '&')
00180     string::size_type amp = projection.find('&');
00181     if (amp != string::npos) {
00182         selection = projection.substr(amp);
00183         projection = projection.substr(0, amp);
00184     }
00185 
00186     // Extract keywords; add to the Keywords keywords. For this, scan for
00187     // a known set of keywords and assume that anything else is part of the
00188     // projection and should be left alone. Keywords must come before variables
00189     // The 'projection' string will look like: '' or 'dap4.0' or 'dap4.0,u,v'
00190     while (!projection.empty()) {
00191         string::size_type i = projection.find(',');
00192         string next_word = projection.substr(0, i);
00193         string word, value;
00194         if (f_parse_keyword(next_word, word, value)
00195             && m_is_valid_keyword(word, value)) {
00196             m_add_keyword(word, value);
00197             if (i != string::npos)
00198                 projection = projection.substr(i + 1);
00199             else
00200                 projection = "";
00201         }
00202         else {
00203             break; // exit on first non-keyword
00204         }
00205     }
00206 
00207     // The CE is whatever is left after removing the keywords
00208     return projection + selection;
00209 }
00210 
00211 }