bes  Updated for version 3.20.6
BindNameFunction.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) 2013 OPeNDAP, Inc.
7 // Authors: 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 
25 #include "config.h"
26 
27 //#define DODS_DEBUG
28 
29 #include <cassert>
30 
31 #include <sstream>
32 #include <vector>
33 
34 #include <BaseType.h>
35 #include <Str.h>
36 
37 #include <Error.h>
38 #include <DDS.h>
39 #include <DMR.h>
40 #include <D4Group.h>
41 #include <D4RValue.h>
42 
43 #include <debug.h>
44 #include <util.h>
45 
46 #include <BESDebug.h>
47 
48 #include "BindNameFunction.h"
49 
50 using namespace libdap;
51 
52 namespace functions {
53 
54 string bind_name_info =
55  string("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
56  + "<function name=\"make_array\" version=\"1.0\" href=\"http://docs.opendap.org/index.php/Server_Side_Processing_Functions#bind_name\">\n"
57  + "</function>";
58 
72 void function_bind_name_dap2(int argc, BaseType * argv[], DDS &dds, BaseType **btpp)
73 {
74  DBG(cerr << "function_bind_name_dap2() - BEGIN" << endl);
75 
76  if (argc == 0) {
77  Str *response = new Str("info");
78  response->set_value(bind_name_info);
79  *btpp = response;
80  return;
81  }
82 
83  // Check for two args or more. The first two must be strings.
84  if (argc != 2) throw Error(malformed_expr, "bind_name(name,variable) requires two arguments.");
85 
86  DBG(cerr << "function_bind_name_dap2() - Processing argv[0]" << endl);
87 
88  string name = extract_string_argument(argv[0]);
89  DBG(cerr << "function_bind_name_dap2() - New name: " << name << endl);
90 
91  DBG(cerr << "function_bind_name_dap2() - Processing argv[1]" << endl);
92  BaseType *sourceVar = argv[1];
93  DBG(cerr << "function_bind_name_dap2() - Source variable: " <<
94  sourceVar->type_name() << " " << sourceVar->name() << endl);
95 
96  // Don't allow renaming that will introduce namespace collisions.
97  //
98  // Check the DDS to see if a variable with name given as argv[0] already exists. If
99  // so, return an error. This is complicated somewhat because the CE Evaluator will
100  // have already looked and, if the string passed into the function matches a variable,
101  // replaced that string with a BaseType* to the (already existing) variable. If not,
102  // the CE Evaluator will make a DAP String variable with a value that is the string
103  // passed into the function. So, either way argv[0] is a BaseType*. However, if it's
104  // a variable in the dataset, its name() will be found by DDS::var().
105  if (dds.var(/*argv[0]->name()*/name)) throw Error(malformed_expr, "The name '" + name + "' is already in use.");
106 
107  // If the variable is the return value of a function, just pass it back. If it is
108  // a variable in the dataset (i.e., present in the DDS), copy it because DDS deletes
109  // all its variables and the function processing code also deletes all it's variables.
110  // NB: Could use reference counting pointers to eliminate this copy... jhrg 6/24/13
111  if (dds.var(sourceVar->name())) {
112  DBG(cerr << "function_bind_name_dap2() - Copying existing variable in DDS: " << sourceVar->name() << endl);
113  *btpp = sourceVar->ptr_duplicate();
114  if (!(*btpp)->read_p()) {
115  (*btpp)->read();
116  (*btpp)->set_read_p(true);
117  }
118  (*btpp)->set_send_p(true);
119  (*btpp)->set_name(name);
120  }
121  else {
122  DBG(cerr << "function_bind_name_dap2 - Using passed variable: " << sourceVar->name() << endl);
123  sourceVar->set_name(name);
124  *btpp = sourceVar;
125  } DBG(cerr << "function_bind_name_dap2() - END" << endl);
126 
127  return;
128 }
129 
130 BaseType *function_bind_name_dap4(D4RValueList *args, DMR &dmr)
131 {
132  // DAP4 function porting information: in place of 'argc' use 'args.size()'
133  if (args == 0 || args->size() == 0) {
134  Str *response = new Str("info");
135  response->set_value(bind_name_info);
136  // DAP4 function porting: return a BaseType* instead of using the value-result parameter
137  return response;
138  }
139 
140  // Check for 2 arguments
141  DBG(cerr << "args->size() = " << args->size() << endl);
142  if (args->size() != 2) throw Error(malformed_expr, "bind_shape(shape,variable) requires two arguments.");
143 
144  string name = extract_string_argument(args->get_rvalue(0)->value(dmr));
145 
146  DBG(cerr << "function_bind_name_dap4() - New name: " << name << endl);
147 
148  BaseType *sourceVar = args->get_rvalue(1)->value(dmr);
149  DBG(cerr << "function_bind_name_dap4() - Source variable: " << sourceVar->type_name() << " " << sourceVar->name() << endl);
150 
151  BaseType *resultVar;
152 
153  // Don't allow renaming that will introduce namespace collisions.
154  //
155  // Check the DMR to see if a variable with name given as args[0] already exists. If
156  // so, return an error. This is complicated somewhat because the CE Evaluator will
157  // have already looked and, if the string passed into the function matches a variable,
158  // replaced that string with a BaseType* to the (already existing) variable. If not,
159  // the CE Evaluator will make a DAP String variable with a value that is the string
160  // passed into the function. So, either way args[0] is a BaseType*. However, if it's
161  // a variable in the dataset, its name() will be found by DMR::root()->var().
162  if (dmr.root()->var(/*arg0->name()*/name))
163  throw Error(malformed_expr, "The name '" + /*arg0->name()*/name + "' is already in use.");
164 
165  // If the variable is the return value of a function, just pass it back. If it is
166  // a variable in the dataset (i.e., present in the DDS), copy it because DDS deletes
167  // all its variables and the function processing code also deletes all it's variables.
168  // NB: Could use reference counting pointers to eliminate this copy... jhrg 6/24/13
169  if (dmr.root()->var(sourceVar->name())) {
170  DBG(cerr << "function_bind_name_dap4() - Copying existing variable in DMR: " << sourceVar->name() << endl);
171  resultVar = sourceVar->ptr_duplicate();
172  if (!resultVar->read_p()) {
173  resultVar->read();
174  resultVar->set_read_p(true);
175  }
176  resultVar->set_send_p(true);
177  resultVar->set_name(name);
178  }
179  else {
180  DBG(cerr << "function_bind_name_dap4 - Using passed variable: " << sourceVar->name() << endl);
181  resultVar = sourceVar;
182  resultVar->set_name(name);
183 
184  }
185  return resultVar;
186 
187 }
188 
189 } // namesspace functions
libdap
Definition: BESDapFunctionResponseCache.h:35
Error