bes  Updated for version 3.20.6
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 <DMR.h>
31 #include <D4Group.h>
32 #include <D4Attributes.h>
33 #include <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 BESDMRResponseHandler::BESDMRResponseHandler(const string &name) :
50  BESResponseHandler(name)
51 {
52 }
53 
54 BESDMRResponseHandler::~BESDMRResponseHandler()
55 {
56 }
57 
76 {
77  dhi.action_name = DMR_RESPONSE_STR;
78 
79  bool xml_base_found = false;
80  string xml_base = BESContextManager::TheManager()->get_context("xml:base", xml_base_found);
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  if (xml_base_found && !xml_base.empty()) dmr->set_request_xml_base(xml_base);
105 
106  BESDMRResponse *bdmr = new BESDMRResponse(dmr);
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  }
115  else {
116  dmr = new DMR();
117 
118  if (xml_base_found && !xml_base.empty()) dmr->set_request_xml_base(xml_base);
119 
120  d_response_object = new BESDMRResponse(dmr);
121 
122  // The RequestHandlers set the constraint and reset the container(s)
123  BESRequestHandlerList::TheList()->execute_each(dhi);
124 
125  dhi.first_container(); // must reset container; execute_each() iterates over all of them
126 
127 #if ANNOTATION_SYSTEM
128  // Support for the experimental Dataset Annotation system. jhrg 12/19/18
129  if (!d_annotation_service_url.empty()) {
130  unique_ptr<D4Attribute> annotation_url(new D4Attribute(DODS_EXTRA_ANNOTATION_ATTR, attr_str_c));
131  annotation_url->add_value(d_annotation_service_url);
132 
133  // If there is already a DODS_EXTRA container, use it
134  if (dmr->root() && dmr->root()->attributes()->get(DODS_EXTRA_ATTR_TABLE)) {
135  dmr->root()->attributes()->get(DODS_EXTRA_ATTR_TABLE)->attributes()->add_attribute_nocopy(annotation_url.release());
136  }
137  else {
138  // Make DODS_EXTRA and load the attribute into it.
139  unique_ptr<D4Attribute> dods_extra(new D4Attribute(DODS_EXTRA_ATTR_TABLE, attr_container_c));
140  dods_extra->attributes()->add_attribute_nocopy(annotation_url.release());
141 
142  // If the root group is null, set the factory (this is an edge case!)
143  if (!dmr->root()) {
144  unique_ptr<D4BaseTypeFactory> factory(new D4BaseTypeFactory);
145  dmr->set_factory(factory.get());
146  dmr->root()->attributes()->add_attribute_nocopy(dods_extra.release());
147  dmr->set_factory(0);
148  }
149  else {
150  dmr->root()->attributes()->add_attribute_nocopy(dods_extra.release());
151  }
152  }
153  }
154 #endif
155  // Cache the DMR if the MDS is not null but the response was not present, and..
156  // This request does not contain a server function call.
157  if (mds && !lock() && dhi.container->get_dap4_function().empty()) {
158  mds->add_responses(static_cast<BESDMRResponse*>(d_response_object)->get_dmr(), dhi.container->get_relative_name());
159  }
160  }
161  }
162 }
163 
177 {
178  if (d_response_object) {
179  transmitter->send_response(DMR_SERVICE, d_response_object, dhi);
180  }
181 }
182 
189 void BESDMRResponseHandler::dump(ostream &strm) const
190 {
191  strm << BESIndent::LMarg << "BESDMRResponseHandler::dump - (" << (void *) this << ")" << endl;
192  BESIndent::Indent();
194  BESIndent::UnIndent();
195 }
196 
198 BESDMRResponseHandler::DMRResponseBuilder(const string &name)
199 {
200  return new BESDMRResponseHandler(name);
201 }
202 
BESDataHandlerInterface::container
BESContainer * container
pointer to current container in this interface
Definition: BESDataHandlerInterface.h:75
BESDapResponse::set_dap4_constraint
virtual void set_dap4_constraint(BESDataHandlerInterface &dhi)
set the constraint depending on the context
Definition: BESDapResponse.cc:137
bes::GlobalMetadataStore::MDSReadLock
Unlock and close the MDS item when the ReadLock goes out of scope.
Definition: GlobalMetadataStore.h:193
bes::GlobalMetadataStore::get_dmr_object
virtual libdap::DMR * get_dmr_object(const std::string &name)
Build a DMR object from the cached Response.
Definition: GlobalMetadataStore.cc:1210
BESDMRResponseHandler::dump
virtual void dump(std::ostream &strm) const
dumps information about this object
Definition: BESDMRResponseHandler.cc:189
bes::GlobalMetadataStore::write_dmr_response
virtual void write_dmr_response(const std::string &name, std::ostream &os)
Write the stored DMR response to a stream.
Definition: GlobalMetadataStore.cc:1106
BESContainer::get_dap4_function
std::string get_dap4_function() const
retrieve the constraint expression for this container
Definition: BESContainer.h:212
BESResponseHandler::dump
virtual void dump(std::ostream &strm) const
dumps information about this object
Definition: BESResponseHandler.cc:102
BESContainer::get_relative_name
std::string get_relative_name() const
Get the relative name of the object in this container.
Definition: BESContainer.h:186
BESRequestHandlerList::execute_each
virtual void execute_each(BESDataHandlerInterface &dhi)
for each container in the given data handler interface, execute the given request
Definition: BESRequestHandlerList.cc:167
bes::GlobalMetadataStore
Store the DAP metadata responses.
Definition: GlobalMetadataStore.h:89
BESDMRResponseHandler
response handler that builds an OPeNDAP DMR response object
Definition: BESDMRResponseHandler.h:50
bes::GlobalMetadataStore::add_responses
virtual bool add_responses(libdap::DDS *dds, const std::string &name)
Add the DAP2 metadata responses using a DDS.
Definition: GlobalMetadataStore.cc:645
BESDMRResponseHandler::execute
virtual void execute(BESDataHandlerInterface &dhi)
executes the command <get type-"dmr" definition="..">
Definition: BESDMRResponseHandler.cc:75
BESResponseHandler
handler object that knows how to create a specific response object
Definition: BESResponseHandler.h:77
BESTransmitter
Definition: BESTransmitter.h:47
BESDMRResponse::clear_container
virtual void clear_container()
clear the container in the DAP response object
Definition: BESDMRResponse.cc:48
BESDataHandlerInterface::first_container
void first_container()
set the container pointer to the first container in the containers list
Definition: BESDataHandlerInterface.h:135
BESContextManager::get_context
virtual std::string get_context(const std::string &name, bool &found)
retrieve the value of the specified context from the BES
Definition: BESContextManager.cc:77
BESDataHandlerInterface
Structure storing information used by the BES to handle the request.
Definition: BESDataHandlerInterface.h:56
BESDMRResponseHandler::transmit
virtual void transmit(BESTransmitter *transmitter, BESDataHandlerInterface &dhi)
transmit the response object built by the execute command using the specified transmitter object
Definition: BESDMRResponseHandler.cc:176
bes::GlobalMetadataStore::is_dmr_available
virtual MDSReadLock is_dmr_available(const std::string &name)
Is the DMR response for.
Definition: GlobalMetadataStore.cc:771
BESContainer::get_dap4_constraint
std::string get_dap4_constraint() const
retrieve the constraint expression for this container
Definition: BESContainer.h:203
BESDMRResponse
Represents an OPeNDAP DMR DAP4 data object within the BES.
Definition: BESDMRResponse.h:39