bes  Updated for version 3.20.13
GridAggregateOnOuterDimension.cc
1 // This file is part of the "NcML Module" project, a BES module designed
3 // to allow NcML files to be used to be used as a wrapper to add
4 // AIS to existing datasets of any format.
5 //
6 // Copyright (c) 2009 OPeNDAP, Inc.
7 // Author: Michael Johnson <m.johnson@opendap.org>
8 //
9 // For more information, please also see the main website: http://opendap.org/
10 //
11 // This library is free software; you can redistribute it and/or
12 // modify it under the terms of the GNU Lesser General Public
13 // License as published by the Free Software Foundation; either
14 // version 2.1 of the License, or (at your option) any later version.
15 //
16 // This library is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 // Lesser General Public License for more details.
20 //
21 // You should have received a copy of the GNU Lesser General Public
22 // License along with this library; if not, write to the Free Software
23 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 //
25 // Please see the files COPYING and COPYRIGHT for more information on the GLPL.
26 //
27 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
29 
30 #include <sstream>
31 #include <memory> // unique_ptr
32 
33 
34 #include <libdap/DataDDS.h> // libdap
35 #include <libdap/DDS.h> // libdap
36 #include <libdap/Grid.h> // libdap
37 
38 #include "DDSLoader.h" // agg_util
39 #include "Dimension.h" // agg_util
40 #include "NCMLDebug.h" // ncml_module
41 #include "NCMLUtil.h" // ncml_module
42 
43 #include "GridAggregateOnOuterDimension.h"
44 
45 #include "AggregationException.h"
46 #include "AggregationUtil.h" // agg_util
47 #include <libdap/Array.h> // libdap
48 #include "ArrayAggregateOnOuterDimension.h" // agg_util
49 
50 using libdap::Array;
51 using libdap::DataDDS;
52 using libdap::DDS;
53 using libdap::Grid;
54 
55 namespace agg_util {
56 
57 #define DEBUG_CHANNEL "ncml:2"
58 
59 // Copy local data
60 void GridAggregateOnOuterDimension::duplicate(const GridAggregateOnOuterDimension& rhs)
61 {
62  _newDim = rhs._newDim;
63 }
64 
66  const AMDList& memberDatasets, const DDSLoader& loaderProto)
67 // this should give us map vectors and the member array rank (without new dim).
68 :
69  GridAggregationBase(proto, memberDatasets, loaderProto), _newDim(newDim)
70 {
71  BESDEBUG(DEBUG_CHANNEL, "GridAggregateOnOuterDimension() ctor called!" << endl);
72 
73  createRep(memberDatasets);
74 }
75 
77  GridAggregationBase(proto), _newDim()
78 {
79  BESDEBUG(DEBUG_CHANNEL, "GridAggregateOnOuterDimension() copy ctor called!" << endl);
80  duplicate(proto);
81 }
82 
83 GridAggregateOnOuterDimension*
84 GridAggregateOnOuterDimension::ptr_duplicate()
85 {
86  return new GridAggregateOnOuterDimension(*this);
87 }
88 
89 GridAggregateOnOuterDimension&
90 GridAggregateOnOuterDimension::operator=(const GridAggregateOnOuterDimension& rhs)
91 {
92  if (this != &rhs) {
93  cleanup();
94  GridAggregationBase::operator=(rhs);
95  duplicate(rhs);
96  }
97  return *this;
98 }
99 
100 GridAggregateOnOuterDimension::~GridAggregateOnOuterDimension()
101 {
102  BESDEBUG(DEBUG_CHANNEL, "~GridAggregateOnOuterDimension() dtor called!" << endl);
103  cleanup();
104 }
105 
107 // Helpers
108 
109 void GridAggregateOnOuterDimension::createRep(const AMDList& memberDatasets)
110 {
111  BESDEBUG_FUNC(DEBUG_CHANNEL, "Replacing the Grid's data Array with an ArrayAggregateOnOuterDimension..." << endl);
112 
113  // This is the prototype we need. It will have been set in the ctor.
114  const auto pArr = dynamic_cast<Array*>(array_var());
115  NCML_ASSERT_MSG(pArr, "Expected to find a contained data Array but we did not!");
116 
117  // Create the Grid version of the read getter and make a new AAOOD from our state.
118  unique_ptr<ArrayGetterInterface> arrayGetter(new TopLevelGridDataArrayGetter());
119 
120  // Create the subclass that does the work and replace our data array with it.
121  // Note this ctor will prepend the new dimension itself, so we do not.
122  //
123  // pArr is a prototype, already should be setup properly _without_ the new dim
124  unique_ptr<ArrayAggregateOnOuterDimension> aggDataArray(new ArrayAggregateOnOuterDimension(*pArr,
125  memberDatasets, std::move(arrayGetter), _newDim));
126 
127  // Make sure null since sink function
128  // called on the unique_ptr
129  NCML_ASSERT(!(arrayGetter.get()));
130 
131  // Replace our data Array with this one. Will delete old one and may throw.
132  set_array(aggDataArray.get());
133 
134  // Release here on successful set since set_array uses raw ptr only.
135  // In case we threw then unique_ptr cleans up itself.
136  aggDataArray.release();
137 }
138 
139 void GridAggregateOnOuterDimension::cleanup() const noexcept
140 {
141 }
142 
143 /* virtual */
145 {
146  VALID_PTR(pSubGrid);
147  transferConstraintsToSubGridMaps(pSubGrid);
148  transferConstraintsToSubGridArray(pSubGrid);
149 }
150 
151 /* virtual */
152 const Dimension&
154 {
155  return _newDim;
156 }
157 
158 void GridAggregateOnOuterDimension::transferConstraintsToSubGridMaps(Grid* pSubGrid)
159 {
160  BESDEBUG(DEBUG_CHANNEL, "Transferring constraints to the subgrid maps..." << endl);
161  Map_iter subGridMapIt = pSubGrid->map_begin();
162  for (Map_iter it = map_begin(); it != map_end(); ++it) {
163  // Skip the new outer dimension
164  if (it == map_begin()) {
165  continue;
166  }
167 
168  Array* subGridMap = static_cast<Array*>(*subGridMapIt);
169  Array* superGridMap = static_cast<Array*>(*it);
170  agg_util::AggregationUtil::transferArrayConstraints(subGridMap, *superGridMap, false, // skipFirstDim = false since map sizes consistent
171  false, // same rank, dont skip this one either
172  true, // printDebug
173  DEBUG_CHANNEL); // debugChannel
174  ++subGridMapIt; // keep iterators in sync
175  }
176 }
177 
178 void GridAggregateOnOuterDimension::transferConstraintsToSubGridArray(Grid* pSubGrid)
179 {
180  BESDEBUG(DEBUG_CHANNEL, "Transferring constraints to the subgrid array..." << endl);
181 
182  Array* pSubGridArray = static_cast<Array*>(pSubGrid->get_array());
183  VALID_PTR(pSubGridArray);
184  Array* pThisArray = static_cast<Array*>(array_var());
185  VALID_PTR(pThisArray);
186 
187  // transfer, skipping first dim which is the new one.
188  agg_util::AggregationUtil::transferArrayConstraints(pSubGridArray, // into the prototype
189  *pThisArray, // from the output array (with valid constraints)
190  true, // skipFirstDim: need to skip since the ranks differ
191  false, // but not into the to array
192  true, // printDebug
193  DEBUG_CHANNEL);
194 }
195 
196 } // namespace agg_util
static void transferArrayConstraints(libdap::Array *pToArray, const libdap::Array &fromArray, bool skipFirstFromDim, bool skipFirstToDim, bool printDebug=false, const std::string &debugChannel="agg_util")
virtual void transferConstraintsToSubGridHook(Grid *pSubGrid)
virtual const Dimension & getAggregationDimension() const
GridAggregateOnOuterDimension(const Grid &proto, const Dimension &newDim, const AMDList &memberDatasets, const DDSLoader &loaderProto)
Helper class for temporarily hijacking an existing dhi to load a DDX response for one particular file...