bes  Updated for version 3.20.13
GridJoinExistingAggregation.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) 2010 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 #include "GridJoinExistingAggregation.h"
30 
31 #include "AggregationUtil.h" // agg_util
32 #include "ArrayJoinExistingAggregation.h" // agg_util
33 #include <libdap/Array.h> // libdap
34 #include "DDSLoader.h"
35 #include "NCMLDebug.h"
36 
37 using libdap::Array;
38 using libdap::Grid;
39 
40 #define DEBUG_CHANNEL "ncml:2"
41 
42 namespace agg_util {
43 
44 GridJoinExistingAggregation::GridJoinExistingAggregation(const libdap::Grid& proto, const AMDList& memberDatasets,
45  const DDSLoader& loaderProto, const Dimension& joinDim)
46 // init WITHOUT a template. We need to do maps specially.
47 :
48  GridAggregationBase(proto.name(), memberDatasets, loaderProto), _joinDim(joinDim)
49 {
50  createRep(proto, memberDatasets);
51 }
52 
53 GridJoinExistingAggregation::GridJoinExistingAggregation(const GridJoinExistingAggregation& proto) :
54  GridAggregationBase(proto), _joinDim(proto._joinDim)
55 {
56  duplicate(proto);
57 }
58 
59 /* virtual */
60 GridJoinExistingAggregation::~GridJoinExistingAggregation()
61 {
62  cleanup();
63 }
64 
65 /* virtual */
66 GridJoinExistingAggregation*
67 GridJoinExistingAggregation::ptr_duplicate()
68 {
69  return new GridJoinExistingAggregation(*this);
70 }
71 
72 GridJoinExistingAggregation&
73 GridJoinExistingAggregation::operator=(const GridJoinExistingAggregation& rhs)
74 {
75  if (this != &rhs) {
76  cleanup();
77  GridAggregationBase::operator=(rhs);
78  duplicate(rhs);
79  }
80  return *this;
81 }
82 
83 unique_ptr<ArrayJoinExistingAggregation> GridJoinExistingAggregation::makeAggregatedOuterMapVector() const
84 {
85  BESDEBUG_FUNC(DEBUG_CHANNEL, "Making an aggregated map " << "as a coordinate variable..." << endl);
86  Grid* pGridGranuleTemplate = const_cast<GridJoinExistingAggregation*>(this)->getSubGridTemplate();
87  NCML_ASSERT_MSG(pGridGranuleTemplate, "Expected grid granule template but got null.");
88 
89  const Array* pMapTemplate = AggregationUtil::findMapByName(*pGridGranuleTemplate, _joinDim.name);
90  NCML_ASSERT_MSG(pMapTemplate, "Expected to find a dim map for the joinExisting agg but failed!");
91 
92  // Make an array getter that pulls out the map array we are interested in.
93  // Use the basic array getter to read and get from top level DDS.
94  // N.B. Must use this->name() ie the gridname since that's what it will search!
95  unique_ptr<agg_util::ArrayGetterInterface> mapArrayGetter(new agg_util::TopLevelGridMapArrayGetter(name()));
96 
97  auto pNewMap = unique_ptr<ArrayJoinExistingAggregation>(
98  new ArrayJoinExistingAggregation(*pMapTemplate, getDatasetList(), std::move(mapArrayGetter), _joinDim));
99 
100  return pNewMap;
101 }
102 
104 // Subclass Impl (Protected)
105 
106 /* virtual */
107 void GridJoinExistingAggregation::transferConstraintsToSubGridHook(Grid* pSubGrid)
108 {
109  VALID_PTR(pSubGrid);
110  transferConstraintsToSubGridMaps(pSubGrid);
111  transferConstraintsToSubGridArray(pSubGrid);
112 }
113 
114 /* virtual */
115 const Dimension&
116 GridJoinExistingAggregation::getAggregationDimension() const
117 {
118  return _joinDim;
119 }
120 
122 // Private Impl
123 
124 void GridJoinExistingAggregation::duplicate(const GridJoinExistingAggregation& rhs)
125 {
126  _joinDim = rhs._joinDim;
127 }
128 
129 void GridJoinExistingAggregation::cleanup() const noexcept
130 {
131 }
132 
133 void GridJoinExistingAggregation::createRep(const libdap::Grid& constProtoSubGrid, const AMDList& memberDatasets)
134 {
135  // Semantically const calls below
136  Grid& protoSubGrid = const_cast<Grid&>(constProtoSubGrid);
137 
138  // Set up the shape, don't add maps
139  setShapeFrom(protoSubGrid, false);
140 
141  // Add the maps by hand, leaving out the first (outer dim) one
142  // since we need to make add that specially.
143  Grid::Map_iter firstIt = protoSubGrid.map_begin();
144  Grid::Map_iter endIt = protoSubGrid.map_end();
145  for (Grid::Map_iter it = firstIt; it != endIt; ++it) {
146  // Skip the first one, assuming it's the join dim
147  if (it == firstIt) {
148  NCML_ASSERT_MSG((*it)->name() == _joinDim.name, "Expected the first map to be the outer dimension "
149  "named " + _joinDim.name + " but it was not! Logic problem.");
150  continue;
151  }
152 
153  // Add the others.
154  Array* pMap = dynamic_cast<Array*>(*it);
155  VALID_PTR(pMap);
156  add_map(pMap, true); // add as a copy
157  }
158 
159  BESDEBUG_FUNC(DEBUG_CHANNEL, "Replacing the Grid's data Array with an ArrayAggregateOnOuterDimension..." << endl);
160 
161  // This is the prototype we need. It will have been set in the ctor.
162  Array* pArr = static_cast<Array*>(array_var());
163  NCML_ASSERT_MSG(pArr, "Expected to find a contained data Array but we did not!");
164 
165  // Create the Grid version of the read getter and make a new AAOOD from our state.
166  std::unique_ptr<ArrayGetterInterface> arrayGetter(new TopLevelGridDataArrayGetter());
167 
168  // Create the subclass that does the work and replace our data array with it.
169  // Note this ctor will prepend the new dimension itself, so we do not.
170  std::unique_ptr<ArrayJoinExistingAggregation> aggDataArray(new ArrayJoinExistingAggregation(*pArr, // prototype, already should be setup properly _without_ the new dim
171  memberDatasets, std::move(arrayGetter), _joinDim));
172 
173  // Make sure null since sink function
174  // called on the unique_ptr
175  NCML_ASSERT(!(arrayGetter.get()));
176 
177  // Replace our data Array with this one. Will delete old one and may throw.
178  set_array(aggDataArray.get());
179 
180  // Release here on successful set since set_array uses raw ptr only.
181  // In case we threw then unique_ptr cleans up itself.
182  aggDataArray.release();
183 }
184 
185 void GridJoinExistingAggregation::transferConstraintsToSubGridMaps(Grid* pSubGrid)
186 {
187  BESDEBUG(DEBUG_CHANNEL, "Transferring constraints to the subgrid maps..." << endl);
188  Map_iter subGridMapIt = pSubGrid->map_begin();
189  for (Map_iter it = map_begin(); it != map_end(); ++it) {
190  // Skip the aggregated outer dimension since handled specially
191  if (it != map_begin()) {
192  Array* subGridMap = static_cast<Array*>(*subGridMapIt);
193  Array* superGridMap = static_cast<Array*>(*it);
194  agg_util::AggregationUtil::transferArrayConstraints(subGridMap, *superGridMap, false, // skipFirstDim = false since inner dim map sizes consistent
195  false, // same rank, don't skip this one either
196  true, // printDebug
197  DEBUG_CHANNEL);
198  }
199  ++subGridMapIt; // keep them in sync
200  }
201 }
202 
203 void GridJoinExistingAggregation::transferConstraintsToSubGridArray(Grid* /* pSubGrid */)
204 {
205  // Data array gets the constraints set on it directly since we replaced
206  // the map with an aggregated array variable. Thus it handles its own
207  // constraints.
208  // Leaving the stub here in case this changes in the future.
209 }
210 
211 } // 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")
Helper class for temporarily hijacking an existing dhi to load a DDX response for one particular file...