libdap++ Updated for version 3.8.2
|
00001 00002 // -*- mode: c++; c-basic-offset:4 -*- 00003 00004 // This file is part of libdap, A C++ implementation of the OPeNDAP Data 00005 // Access Protocol. 00006 00007 // Copyright (c) 2003 OPeNDAP, Inc. 00008 // Author: James Gallagher <jgallagher@opendap.org> 00009 // 00010 // This library is free software; you can redistribute it and/or 00011 // modify it under the terms of the GNU Lesser General Public 00012 // License as published by the Free Software Foundation; either 00013 // version 2.1 of the License, or (at your option) any later version. 00014 // 00015 // This library is distributed in the hope that it will be useful, 00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00018 // Lesser General Public License for more details. 00019 // 00020 // You should have received a copy of the GNU Lesser General Public 00021 // License along with this library; if not, write to the Free Software 00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00023 // 00024 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112. 00025 00026 #include "config.h" 00027 00028 #include <iostream> 00029 #include <fstream> 00030 #include <algorithm> 00031 #include <functional> 00032 00033 #include "AISResources.h" 00034 #include "AISDatabaseParser.h" 00035 00036 using namespace std; 00037 00038 namespace libdap { 00039 00045 ostream & 00046 operator<<(ostream &os, const Resource &r) 00047 { 00048 os << "<ancillary"; 00049 if (r.d_rule != Resource::overwrite) { 00050 os << " rule=\""; 00051 (r.d_rule == Resource::fallback) ? os << "fallback\"" : os << "replace\""; 00052 } 00053 os << " url=\"" << r.d_url << "\"/>"; 00054 00055 return os; 00056 } 00057 00061 ostream & 00062 operator<<(ostream &os, const AISResources &ais_res) 00063 { 00064 os << "<?xml version=\"1.0\" encoding=\"US-ASCII\" standalone=\"yes\"?>" 00065 << endl; 00066 os << "<!DOCTYPE ais SYSTEM \"http://xml.opendap.org/ais/ais_database.dtd\">" << endl; 00067 os << "<ais xmlns=\"http://xml.opendap.org/ais\">" << endl; 00068 00069 for (AISResources::ResourceRegexpsCIter pos = ais_res.d_re.begin(); 00070 pos != ais_res.d_re.end(); ++pos) { 00071 os << "<entry>" << endl; 00072 // write primary 00073 os << "<primary regexp=\"" << pos->first << "\"/>" << endl; 00074 // write the vector of Resource objects 00075 for (ResourceVectorCIter i = pos->second.begin(); 00076 i != pos->second.end(); ++i) { 00077 os << *i << endl; 00078 } 00079 os << "</entry>" << endl; 00080 } 00081 00082 // Under VC++ 6.x, 'pos' is twice tagged as twice in the 00083 // same scope (this method - not just within for blocks), so 00084 // I gave it another name. ROM - 6/14/03 00085 for (AISResources::ResourceMapCIter pos2 = ais_res.d_db.begin(); 00086 pos2 != ais_res.d_db.end(); ++pos2) { 00087 os << "<entry>" << endl; 00088 // write primary 00089 os << "<primary url=\"" << pos2->first << "\"/>" << endl; 00090 // write the vector of Resource objects 00091 for (ResourceVectorCIter i = pos2->second.begin(); 00092 i != pos2->second.end(); ++i) { 00093 os << *i << endl; 00094 } 00095 os << "</entry>" << endl; 00096 } 00097 00098 os << "</ais>" << endl; 00099 00100 return os; 00101 } 00102 00105 AISResources::AISResources(const string &database) throw(AISDatabaseReadFailed) 00106 { 00107 read_database(database); 00108 } 00109 00116 void 00117 AISResources::add_url_resource(const string &url, const Resource &ancillary) 00118 { 00119 add_url_resource(url, ResourceVector(1, ancillary)); 00120 } 00121 00127 void 00128 AISResources::add_url_resource(const string &url, const ResourceVector &rv) 00129 { 00130 ResourceMapIter pos = d_db.find(url); 00131 if (pos == d_db.end()) { 00132 d_db.insert(std::make_pair(url, rv)); 00133 } 00134 else { 00135 // There's already a ResourceVector, append to it. 00136 for (ResourceVectorCIter i = rv.begin(); i != rv.end(); ++i) 00137 pos->second.push_back(*i); 00138 } 00139 } 00140 00145 void 00146 AISResources::add_regexp_resource(const string &re, const Resource &ancillary) 00147 { 00148 add_regexp_resource(re, ResourceVector(1, ancillary)); 00149 } 00150 00157 void 00158 AISResources::add_regexp_resource(const string &re, const ResourceVector &rv) 00159 { 00160 ResourceRegexpsIter pos = find_if(d_re.begin(), d_re.end(), 00161 FindRegexp(re)); 00162 if (pos == d_re.end()) { 00163 d_re.push_back(std::make_pair(re, rv)); 00164 } 00165 else { 00166 // There's already a ResourceVector, append to it. 00167 for (ResourceVectorCIter i = rv.begin(); i != rv.end(); ++i) 00168 pos->second.push_back(*i); 00169 } 00170 } 00171 00180 bool 00181 AISResources::has_resource(const string &primary) const 00182 { 00183 // This code looks for the 'primary' in the AIS database (which is a STL 00184 // map<> of strings and AIS stuff. As an optimization, it first uses the 00185 // map<> class' find() method to see if the 'primary' is in there as a 00186 // literal. If not, then it tries to match each regular expression in the 00187 // database. 00188 return ((d_db.find(primary) != d_db.end()) 00189 || (find_if(d_re.begin(), d_re.end(), MatchRegexp(primary)) 00190 != d_re.end())); 00191 00192 } 00193 00212 ResourceVector 00213 AISResources::get_resource(const string &primary) 00214 { 00215 ResourceVector rv; 00216 const ResourceMapIter &i = d_db.find(primary); 00217 00218 if (i != d_db.end()) 00219 rv = i->second; 00220 00221 // Finds the first matching regular expression and returns a vector of 00222 // AIS resources. 00223 const ResourceRegexpsIter &j = find_if(d_re.begin(), d_re.end(), 00224 MatchRegexp(primary)); 00225 if (j != d_re.end()) 00226 copy(j->second.begin(), j->second.end(), inserter(rv, rv.begin())); 00227 00228 if (rv.size() == 0) 00229 throw NoSuchPrimaryResource(); 00230 00231 return rv; 00232 } 00233 00241 void 00242 AISResources::read_database(const string &database) 00243 { 00244 AISDatabaseParser parser; 00245 00246 parser.intern(database, this); 00247 } 00248 00257 void 00258 AISResources::write_database(const string &filename) 00259 { 00260 ofstream fos; 00261 fos.open(filename.c_str()); 00262 00263 if (!fos) 00264 throw AISDatabaseWriteFailed("Could not open file :" + filename); 00265 00266 fos << *this << endl; 00267 00268 if (!fos) 00269 throw AISDatabaseWriteFailed(); 00270 } 00271 00272 } // namespace libdap