bes  Updated for version 3.20.10
BESDMRResponseHandler.cc
1 // BESDMRResponseHandler.cc
2 
3 // This file is part of bes, A C++ back-end server implementation framework
4 // for the OPeNDAP Data Access Protocol.
5 
6 // Copyright (c) 2013 OPeNDAP, Inc.
7 // Author: Patrick West <pwest@rpi.edu>
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 #include <sstream>
28 #include <memory>
29 
30 #include <libdap/DMR.h>
31 #include <libdap/D4Group.h>
32 #include <libdap/D4Attributes.h>
33 #include <libdap/D4BaseTypeFactory.h>
34 
35 #include "BESDMRResponseHandler.h"
36 #include "BESDMRResponse.h"
37 #include "BESRequestHandlerList.h"
38 #include "BESDapNames.h"
39 #include "BESDapTransmit.h"
40 #include "BESContextManager.h"
41 #include "GlobalMetadataStore.h"
42 
43 #include "BESLog.h"
44 #include "BESDebug.h"
45 
46 using namespace bes;
47 using namespace std;
48 
49 #define MODULE "dap"
50 #define prolog std::string("BESDMRResponseHandler::").append(__func__).append("() - ")
51 
52 BESDMRResponseHandler::BESDMRResponseHandler(const string &name) :
53  BESResponseHandler(name)
54 {
55 }
56 
57 BESDMRResponseHandler::~BESDMRResponseHandler()
58 {
59 }
60 
79 {
80  dhi.action_name = DMR_RESPONSE_STR;
81 
82  // Look in the MDS for dhi.container.get_real_name().
83  // if found, use that response, else build it.
84  // If the MDS is disabled, don't use it.
85  GlobalMetadataStore *mds = GlobalMetadataStore::get_instance();
86 
88 
89  dhi.first_container();
90  if (mds) lock = mds->is_dmr_available(*(dhi.container));
91 
92  if (mds && lock() && dhi.container->get_dap4_constraint().empty() && dhi.container->get_dap4_function().empty()) { // no CE
93  // send the response
94  mds->write_dmr_response(dhi.container->get_relative_name(), dhi.get_output_stream());
95  // suppress transmitting a ResponseObject in transmit()
96  d_response_object = 0;
97  }
98  else {
99  DMR *dmr = 0;
100  if (mds && lock() && dhi.container->get_dap4_function().empty()) {
101  // If mds and lock(), the DDS is in the cache, get the _object_
102  dmr = mds->get_dmr_object(dhi.container->get_relative_name());
103 
104  BESDMRResponse *bdmr = new BESDMRResponse(dmr);
105  BESDEBUG(MODULE, prolog << "dmr->request_xml_base(): '"<< dmr->request_xml_base() <<
106  "' (dmr: "<< (void *) dmr << ")" << endl);
107 
108  // This method sets the constraint for the current container. It does nothing
109  // if there is no 'current container.'
110  bdmr->set_dap4_constraint(dhi);
111  bdmr->clear_container();
112 
113  d_response_object = bdmr;
114  BESDEBUG(MODULE, prolog << "d_response_object: "<< (void *) d_response_object << endl);
115  }
116  else {
117  dmr = new DMR();
118 
119  // if (xml_base_found && !xml_base.empty()) dmr->set_request_xml_base(xml_base);
120  BESDMRResponse *bdmr = new BESDMRResponse(dmr);
121  BESDEBUG(MODULE, prolog << "dmr->request_xml_base(): '"<< dmr->request_xml_base()
122  << "' (dmr: "<< (void *)dmr << ")" << endl);
123 
124  d_response_object = bdmr;
125 
126  BESDEBUG(MODULE, prolog << "d_response_object: "<< (void *) d_response_object << endl);
127 
128  // The RequestHandlers set the constraint and reset the container(s)
129  BESRequestHandlerList::TheList()->execute_each(dhi);
130 
131  dhi.first_container(); // must reset container; execute_each() iterates over all of them
132 
133 #if ANNOTATION_SYSTEM
134  // Support for the experimental Dataset Annotation system. jhrg 12/19/18
135  if (!d_annotation_service_url.empty()) {
136  unique_ptr<D4Attribute> annotation_url(new D4Attribute(DODS_EXTRA_ANNOTATION_ATTR, attr_str_c));
137  annotation_url->add_value(d_annotation_service_url);
138 
139  // If there is already a DODS_EXTRA container, use it
140  if (dmr->root() && dmr->root()->attributes()->get(DODS_EXTRA_ATTR_TABLE)) {
141  dmr->root()->attributes()->get(DODS_EXTRA_ATTR_TABLE)->attributes()->add_attribute_nocopy(annotation_url.release());
142  }
143  else {
144  // Make DODS_EXTRA and load the attribute into it.
145  unique_ptr<D4Attribute> dods_extra(new D4Attribute(DODS_EXTRA_ATTR_TABLE, attr_container_c));
146  dods_extra->attributes()->add_attribute_nocopy(annotation_url.release());
147 
148  // If the root group is null, set the factory (this is an edge case!)
149  if (!dmr->root()) {
150  unique_ptr<D4BaseTypeFactory> factory(new D4BaseTypeFactory);
151  dmr->set_factory(factory.get());
152  dmr->root()->attributes()->add_attribute_nocopy(dods_extra.release());
153  dmr->set_factory(0);
154  }
155  else {
156  dmr->root()->attributes()->add_attribute_nocopy(dods_extra.release());
157  }
158  }
159  }
160 #endif
161  // Cache the DMR if the MDS is not null but the response was not present, and..
162  // This request does not contain a server function call.
163  if (mds && !lock() && dhi.container->get_dap4_function().empty()) {
164  mds->add_responses(static_cast<BESDMRResponse*>(d_response_object)->get_dmr(), dhi.container->get_relative_name());
165  }
166  }
167  }
168 }
169 
183 {
184  if (d_response_object) {
185  transmitter->send_response(DMR_SERVICE, d_response_object, dhi);
186  }
187 }
188 
195 void BESDMRResponseHandler::dump(ostream &strm) const
196 {
197  strm << BESIndent::LMarg << "BESDMRResponseHandler::dump - (" << (void *) this << ")" << endl;
198  BESIndent::Indent();
200  BESIndent::UnIndent();
201 }
202 
204 BESDMRResponseHandler::DMRResponseBuilder(const string &name)
205 {
206  return new BESDMRResponseHandler(name);
207 }
208 
std::string get_relative_name() const
Get the relative name of the object in this container.
Definition: BESContainer.h:186
std::string get_dap4_constraint() const
retrieve the constraint expression for this container
Definition: BESContainer.h:203
std::string get_dap4_function() const
retrieve the constraint expression for this container
Definition: BESContainer.h:212
response handler that builds an OPeNDAP DMR response object
virtual void transmit(BESTransmitter *transmitter, BESDataHandlerInterface &dhi)
transmit the response object built by the execute command using the specified transmitter object
virtual void dump(std::ostream &strm) const
dumps information about this object
virtual void execute(BESDataHandlerInterface &dhi)
executes the command <get type-"dmr" definition="..">
Represents an OPeNDAP DMR DAP4 data object within the BES.
virtual void clear_container()
clear the container in the DAP response object
virtual void set_dap4_constraint(BESDataHandlerInterface &dhi)
set the constraint depending on the context
Structure storing information used by the BES to handle the request.
void first_container()
set the container pointer to the first container in the containers list
BESContainer * container
pointer to current container in this interface
virtual void execute_each(BESDataHandlerInterface &dhi)
for each container in the given data handler interface, execute the given request
handler object that knows how to create a specific response object
virtual void dump(std::ostream &strm) const
dumps information about this object
Store the DAP metadata responses.
virtual void write_dmr_response(const std::string &name, std::ostream &os)
Write the stored DMR response to a stream.
virtual libdap::DMR * get_dmr_object(const std::string &name)
Build a DMR object from the cached Response.
virtual MDSReadLock is_dmr_available(const std::string &name)
Is the DMR response for.
virtual bool add_responses(libdap::DDS *dds, const std::string &name)
Add the DAP2 metadata responses using a DDS.
Unlock and close the MDS item when the ReadLock goes out of scope.