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