OPeNDAP Hyrax Back End Server (BES)  Updated for version 3.8.3
GridJoinExistingAggregation.cc
Go to the documentation of this file.
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.
30 
31 #include "AggregationUtil.h" // agg_util
32 #include "ArrayJoinExistingAggregation.h" // agg_util
33 #include <Array.h> // libdap
34 #include "DDSLoader.h"
35 #include "NCMLDebug.h"
36 
37 using libdap::Array;
38 using libdap::Grid;
39 
40 // unused jhrg 4/16/14 static const bool PRINT_CONSTRAINTS = true;
41 static const string DEBUG_CHANNEL("ncml:2");
42 
43 namespace agg_util
44 {
45 
47  const libdap::Grid& proto,
48  const AMDList& memberDatasets,
49  const DDSLoader& loaderProto,
50  const Dimension& joinDim)
51  // init WITHOUT a template. We need to do maps specially.
52  : GridAggregationBase(proto.name(), memberDatasets, loaderProto)
53  , _joinDim(joinDim)
54  {
55  createRep(proto, memberDatasets);
56  }
57 
59  const GridJoinExistingAggregation& proto)
60  : GridAggregationBase(proto)
61  , _joinDim(proto._joinDim)
62  {
63  duplicate(proto);
64  }
65 
66  /* virtual */
68  {
69  cleanup();
70  }
71 
72  /* virtual */
75  {
76  return new GridJoinExistingAggregation(*this);
77  }
78 
81  {
82  if (this != &rhs)
83  {
84  cleanup();
86  duplicate(rhs);
87  }
88  return *this;
89  }
90 
91  auto_ptr<ArrayJoinExistingAggregation>
93  {
94  BESDEBUG_FUNC(DEBUG_CHANNEL,
95  "Making an aggregated map " <<
96  "as a coordinate variable..." << endl);
97  Grid* pGridGranuleTemplate = const_cast<GridJoinExistingAggregation*>(this)->getSubGridTemplate();
98  NCML_ASSERT_MSG(pGridGranuleTemplate, "Expected grid granule template but got null.");
99 
100  const Array* pMapTemplate = AggregationUtil::findMapByName(*pGridGranuleTemplate, _joinDim.name);
101  NCML_ASSERT_MSG(pMapTemplate, "Expected to find a dim map for the joinExisting agg but failed!");
102 
103  // Make an array getter that pulls out the map array we are interested in.
104  // Use the basic array getter to read and get from top level DDS.
105  // N.B. Must use this->name() ie the gridname since that's what it will search!
106  auto_ptr<agg_util::ArrayGetterInterface> mapArrayGetter(
108 
109  auto_ptr<ArrayJoinExistingAggregation> pNewMap =
110  auto_ptr<ArrayJoinExistingAggregation>(
112  *pMapTemplate,
113  getDatasetList(),
114  mapArrayGetter,
115  _joinDim));
116 
117  return pNewMap;
118  }
119 
121  // Subclass Impl (Protected)
122 
123  /* virtual */
124  void
126  {
127  VALID_PTR(pSubGrid);
128  transferConstraintsToSubGridMaps(pSubGrid);
129  transferConstraintsToSubGridArray(pSubGrid);
130  }
131 
132  /* virtual */
133  const Dimension&
135  {
136  return _joinDim;
137  }
138 
139 
141  // Private Impl
142 
143  void
144  GridJoinExistingAggregation::duplicate(const GridJoinExistingAggregation& rhs)
145  {
146  _joinDim = rhs._joinDim;
147  }
148 
149  void
150  GridJoinExistingAggregation::cleanup() throw()
151  {
152  }
153 
154  void
155  GridJoinExistingAggregation::createRep(
156  const libdap::Grid& constProtoSubGrid,
157  const AMDList& memberDatasets)
158  {
159  // Semantically const calls below
160  Grid& protoSubGrid = const_cast<Grid&>(constProtoSubGrid);
161 
162  // Set up the shape, don't add maps
163  setShapeFrom(protoSubGrid, false);
164 
165  // Add the maps by hand, leaving out the first (outer dim) one
166  // since we need to make add that specially.
167  Grid::Map_iter firstIt = protoSubGrid.map_begin();
168  Grid::Map_iter endIt = protoSubGrid.map_end();
169  for (Grid::Map_iter it = firstIt;
170  it != endIt;
171  ++it)
172  {
173  // Skip the first one, assuming it's the join dim
174  if (it == firstIt)
175  {
176  NCML_ASSERT_MSG( (*it)->name() == _joinDim.name,
177  "Expected the first map to be the outer dimension "
178  "named " + _joinDim.name +
179  " but it was not! Logic problem.");
180  continue;
181  }
182 
183  // Add the others.
184  Array* pMap = dynamic_cast<Array*>(*it);
185  VALID_PTR(pMap);
186  add_map(pMap, true); // add as a copy
187  }
188 
189  BESDEBUG_FUNC(DEBUG_CHANNEL,
190  "Replacing the Grid's data Array with an ArrayAggregateOnOuterDimension..." << endl);
191 
192  // This is the prototype we need. It will have been set in the ctor.
193  Array* pArr = static_cast<Array*>(array_var());
194  NCML_ASSERT_MSG(pArr,
195  "Expected to find a contained data Array but we did not!");
196 
197  // Create the Grid version of the read getter and make a new AAOOD from our state.
198  std::auto_ptr<ArrayGetterInterface> arrayGetter(new TopLevelGridDataArrayGetter());
199 
200  // Create the subclass that does the work and replace our data array with it.
201  // Note this ctor will prepend the new dimension itself, so we do not.
202  std::auto_ptr<ArrayJoinExistingAggregation> aggDataArray(
203  new ArrayJoinExistingAggregation(
204  *pArr, // prototype, already should be setup properly _without_ the new dim
205  memberDatasets,
206  arrayGetter,
207  _joinDim
208  ));
209 
210  // Make sure null since sink function
211  // called on the auto_ptr
212  NCML_ASSERT(!(arrayGetter.get()));
213 
214  // Replace our data Array with this one. Will delete old one and may throw.
215  set_array(aggDataArray.get());
216 
217  // Release here on successful set since set_array uses raw ptr only.
218  // In case we threw then auto_ptr cleans up itself.
219  aggDataArray.release();
220  }
221 
222  void
223  GridJoinExistingAggregation::transferConstraintsToSubGridMaps(Grid* pSubGrid)
224  {
225  BESDEBUG(DEBUG_CHANNEL, "Transferring constraints to the subgrid maps..." << endl);
226  Map_iter subGridMapIt = pSubGrid->map_begin();
227  for (Map_iter it = map_begin(); it != map_end(); ++it)
228  {
229  // Skip the aggregated outer dimension since handled specially
230  if (it != map_begin())
231  {
232  Array* subGridMap = static_cast<Array*>(*subGridMapIt);
233  Array* superGridMap = static_cast<Array*>(*it);
235  *superGridMap,
236  false, // skipFirstDim = false since inner dim map sizes consistent
237  false, // same rank, don't skip this one either
238  true, // printDebug
239  DEBUG_CHANNEL);
240  }
241  ++subGridMapIt; // keep them in sync
242  }
243  }
244 
245  void
246  GridJoinExistingAggregation::transferConstraintsToSubGridArray(Grid* /* pSubGrid */)
247  {
248  // Data array gets the constraints set on it directly since we replaced
249  // the map with an aggregated array variable. Thus it handles its own
250  // constraints.
251  // Leaving the stub here in case this changes in the future.
252  }
253 
254 
255 } // namespace agg_util
virtual const AMDList & getDatasetList() const
Accessor for the dataset description list that describes this aggregation.
#define BESDEBUG_FUNC(channel, info)
Definition: NCMLDebug.h:58
std::string name
Definition: Dimension.h:61
GridJoinExistingAggregation(const libdap::Grid &proto, const AMDList &memberDatasets, const DDSLoader &loaderProto, const Dimension &joinDim)
virtual const Dimension & getAggregationDimension() const
Get the contained aggregation dimension info.
#define NCML_ASSERT(cond)
Definition: NCMLDebug.h:80
void setShapeFrom(const libdap::Grid &protoSubGrid, bool addMaps)
Use the data array and maps from protoSubGrid as the initial point for the shape of the Grid...
static const libdap::Array * findMapByName(const libdap::Grid &inGrid, const std::string &findName)
Find the given map name in the given Grid and return it if found, else NULL.
Helper class for temporarily hijacking an existing dhi to load a DDX response for one particular file...
#define NCML_ASSERT_MSG(cond, msg)
Definition: NCMLDebug.h:83
virtual void transferConstraintsToSubGridHook(Grid *pSubGrid)
Required specialization for the read() call stack.
Struct for holding information about a dimension of data, minimally a name and a cardinality (size)...
Definition: Dimension.h:50
virtual GridJoinExistingAggregation * ptr_duplicate()
GridJoinExistingAggregation & operator=(const GridJoinExistingAggregation &rhs)
std::vector< RCPtr< AggMemberDataset > > AMDList
static void transferArrayConstraints(libdap::Array *pToArray, const libdap::Array &fromArray, bool skipFirstFromDim, bool skipFirstToDim, bool printDebug=false, const std::string &debugChannel="agg_util")
Copy the constraints from the from Array into the pToArray in Dim_iter order.
Grid * getSubGridTemplate()
Reveals the raw ptr, but only to subclasses.
auto_ptr< ArrayJoinExistingAggregation > makeAggregatedOuterMapVector() const
Create a new map aggregated map vector for this aggregation, using its data templates, granule list, and outer dimension.
#define VALID_PTR(ptr)
Definition: NCMLDebug.h:88
#define BESDEBUG(x, y)
macro used to send debug information to the debug stream
Definition: BESDebug.h:64
GridAggregationBase & operator=(const GridAggregationBase &rhs)