OPeNDAP Hyrax Back End Server (BES)  Updated for version 3.8.3
BindNameFunction.cc
Go to the documentation of this file.
1 
2 // -*- mode: c++; c-basic-offset:4 -*-
3 
4 // This file is part of libdap, A C++ implementation of the OPeNDAP Data
5 // Access Protocol.
6 
7 // Copyright (c) 2013 OPeNDAP, Inc.
8 // Authors: James Gallagher <jgallagher@opendap.org>
9 //
10 // This library is free software; you can redistribute it and/or
11 // modify it under the terms of the GNU Lesser General Public
12 // License as published by the Free Software Foundation; either
13 // version 2.1 of the License, or (at your option) any later version.
14 //
15 // This library is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 // Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public
21 // License along with this library; if not, write to the Free Software
22 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 //
24 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
25 
26 #include "config.h"
27 
28 //#define DODS_DEBUG
29 
30 #include <cassert>
31 
32 #include <sstream>
33 #include <vector>
34 
35 #include <BaseType.h>
36 #include <Str.h>
37 
38 #include <Error.h>
39 #include <DDS.h>
40 #include <DMR.h>
41 #include <D4Group.h>
42 #include <D4RValue.h>
43 
44 #include <debug.h>
45 #include <util.h>
46 
47 #include <BESDebug.h>
48 
49 #include "BindNameFunction.h"
50 
51 namespace libdap {
52 
54 string("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n") +
55 "<function name=\"make_array\" version=\"1.0\" href=\"http://docs.opendap.org/index.php/Server_Side_Processing_Functions#bind_name\">\n" +
56 "</function>";
57 
71 void
72 function_bind_name_dap2(int argc, BaseType * argv[], DDS &dds, BaseType **btpp)
73 {
74 
75  DBG(cerr << "function_bind_name_dap2() - BEGIN" << endl);
76 
77  if (argc == 0) {
78  Str *response = new Str("info");
79  response->set_value(bind_name_info);
80  *btpp = response;
81  return;
82  }
83 
84  // Check for two args or more. The first two must be strings.
85  if (argc != 2)
86  throw Error(malformed_expr, "bind_name(name,variable) requires two arguments.");
87 
88  DBG(cerr << "function_bind_name_dap2() - Processing argv[0]" << endl);
89 
90  string name = extract_string_argument(argv[0]);
91  DBG(cerr << "function_bind_name_dap2() - New name: " << name << endl);
92 
93  DBG(cerr << "function_bind_name_dap2() - Processing argv[1]" << endl);
94  BaseType *sourceVar = argv[1];
95  DBG(cerr << "function_bind_name_dap2() - Source variable: " <<
96  sourceVar->type_name() << " " << sourceVar->name() << endl);
97 
98  // Don't allow renaming that will introduce namespace collisions.
99  //
100  // Check the DDS to see if a variable with name given as argv[0] already exists. If
101  // so, return an error. This is complicated somewhat because the CE Evaluator will
102  // have already looked and, if the string passed into the function matches a variable,
103  // replaced that string with a BaseType* to the (already existing) variable. If not,
104  // the CE Evaluator will make a DAP String variable with a value that is the string
105  // passed into the function. So, either way argv[0] is a BaseType*. However, if it's
106  // a variable in the dataset, its name() will be found by DDS::var().
107  if (dds.var(/*argv[0]->name()*/ name))
108  throw Error(malformed_expr, "The name '" + name + "' is already in use.");
109 
110 
111  // If the variable is the return value of a function, just pass it back. If it is
112  // a variable in the dataset (i.e., present in the DDS), copy it because DDS deletes
113  // all its variables and the function processing code also deletes all it's variables.
114  // NB: Could use reference counting pointers to eliminate this copy... jhrg 6/24/13
115  if (dds.var(sourceVar->name())) {
116  DBG(cerr << "function_bind_name_dap2() - Copying existing variable in DDS: " << sourceVar->name() << endl);
117  *btpp = sourceVar->ptr_duplicate();
118  if (!(*btpp)->read_p()) {
119  (*btpp)->read();
120  (*btpp)->set_read_p(true);
121  }
122  (*btpp)->set_send_p(true);
123  (*btpp)->set_name(name);
124  }
125  else {
126  DBG(cerr << "function_bind_name_dap2 - Using passed variable: " << sourceVar->name() << endl);
127  sourceVar->set_name(name);
128  *btpp = sourceVar;
129  }
130  DBG(cerr << "function_bind_name_dap2() - END" << endl);
131 
132  return;
133 }
134 
135 BaseType *function_bind_name_dap4(D4RValueList *args, DMR &dmr){
136  // DAP4 function porting information: in place of 'argc' use 'args.size()'
137  if (args == 0 || args->size() == 0) {
138  Str *response = new Str("info");
139  response->set_value(bind_name_info);
140  // DAP4 function porting: return a BaseType* instead of using the value-result parameter
141  return response;
142  }
143 
144  // Check for 2 arguments
145  DBG(cerr << "args->size() = " << args->size() << endl);
146  if (args->size() != 2)
147  throw Error(malformed_expr,"bind_shape(shape,variable) requires two arguments.");
148 
149  string name = extract_string_argument(args->get_rvalue(0)->value(dmr));
150 
151  DBG(cerr << "function_bind_name_dap4() - New name: " << name << endl);
152 
153  BaseType *sourceVar = args->get_rvalue(1)->value(dmr);
154  DBG(cerr << "function_bind_name_dap4() - Source variable: " << sourceVar->type_name() << " " << sourceVar->name() << endl);
155 
156  BaseType *resultVar;
157 
158  // Don't allow renaming that will introduce namespace collisions.
159  //
160  // Check the DMR to see if a variable with name given as args[0] already exists. If
161  // so, return an error. This is complicated somewhat because the CE Evaluator will
162  // have already looked and, if the string passed into the function matches a variable,
163  // replaced that string with a BaseType* to the (already existing) variable. If not,
164  // the CE Evaluator will make a DAP String variable with a value that is the string
165  // passed into the function. So, either way args[0] is a BaseType*. However, if it's
166  // a variable in the dataset, its name() will be found by DMR::root()->var().
167  if (dmr.root()->var(/*arg0->name()*/ name))
168  throw Error(malformed_expr, "The name '" + /*arg0->name()*/ name + "' is already in use.");
169 
170 
171  // If the variable is the return value of a function, just pass it back. If it is
172  // a variable in the dataset (i.e., present in the DDS), copy it because DDS deletes
173  // all its variables and the function processing code also deletes all it's variables.
174  // NB: Could use reference counting pointers to eliminate this copy... jhrg 6/24/13
175  if (dmr.root()->var(sourceVar->name())) {
176  DBG(cerr << "function_bind_name_dap4() - Copying existing variable in DMR: " << sourceVar->name() << endl);
177  resultVar = sourceVar->ptr_duplicate();
178  if (!resultVar->read_p()) {
179  resultVar->read();
180  resultVar->set_read_p(true);
181  }
182  resultVar->set_send_p(true);
183  resultVar->set_name(name);
184  }
185  else {
186  DBG(cerr << "function_bind_name_dap4 - Using passed variable: " << sourceVar->name() << endl);
187  resultVar = sourceVar;
188  resultVar->set_name(name);
189 
190  }
191  return resultVar;
192 
193 
194 }
195 
196 
197 } // namesspace libdap
BaseType * function_bind_name_dap4(D4RValueList *args, DMR &dmr)
static class NCMLUtil overview
void function_bind_name_dap2(int argc, BaseType *argv[], DDS &dds, BaseType **btpp)
Bind a new name to a variable.
string bind_name_info