1 // -*- mode: c++; c-basic-offset:4 -*- 2 3 // This file is part of libdap, A C++ implementation of the OPeNDAP Data 4 // Access Protocol. 5 6 // Copyright (c) 2013 OPeNDAP, Inc. 7 // Author: James Gallagher <jgallagher@opendap.org> 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 #ifndef D4MAPS_H_ 26 #define D4MAPS_H_ 27 28 #include <string> 29 #include <vector> 30 31 using namespace std; 32 33 namespace libdap { 34 35 class Array; 36 class XMLWriter; 37 38 /** 39 * A 'Map' in DAP4 is an Array in the dataset that is used to provide the 40 * domain values for a Coverage (aka a Grid). These Maps are a more 41 * general case of the DAP2 'Map vectors' because a DAP4 Map can have N 42 * dimensions. 43 * 44 * Because the Maps can be shared by any or all of the Arrays in a dataset, 45 * they also correspond to the NetCDF/CF notion of a Shared Dimension. 46 * 47 * In this implementation of the D4Map, each Map has a name and two weak 48 * pointers, one to the Array that holds the domain values and one to the 49 * Array that uses the Map. Note that while Maps can be shared by Arrays, 50 * each Array has it's own collection of these D4Map objects. This makes 51 * processing constraints possible (because it is possible to write 52 * different constraints for two arrays that share Maps). 53 */ 54 class D4Map { 55 std::string d_name; 56 Array *d_array; // the actual map data; weak pointer 57 Array *d_parent; // what array holds this map; weak pointer 58 59 public: D4Map()60 D4Map() : d_name(""), d_array(0), d_parent(0) { } d_name(name)61 D4Map(const string &name, Array *array, Array *parent = 0) : d_name(name), d_array(array), d_parent(parent) { } 62 ~D4Map()63 virtual ~D4Map() { } 64 name()65 const string& name() const { return d_name; } set_name(const string & name)66 void set_name(const string& name) { d_name = name; } 67 array()68 const Array* array() const { return d_array; } set_array(Array * array)69 void set_array(Array* array) { d_array = array; } 70 71 /** 72 * @brief The Array that holds this Map 73 */ parent()74 const Array* parent() const { return d_parent; } set_parent(Array * parent)75 void set_parent(Array* parent) { d_parent = parent; } 76 77 virtual void print_dap4(XMLWriter &xml); 78 }; 79 80 /** 81 * The D4Maps object holds pointers to all of the Maps used by 82 * a given Array. 83 */ 84 class D4Maps { 85 public: 86 typedef vector<D4Map*>::iterator D4MapsIter; 87 typedef vector<D4Map*>::const_iterator D4MapsCIter; 88 89 private: 90 vector<D4Map*> d_maps; 91 Array *d_parent; // Array these Maps belong to; weak pointer 92 m_duplicate(const D4Maps & maps)93 void m_duplicate(const D4Maps &maps) { 94 d_parent = maps.d_parent; 95 for (D4MapsCIter ci = maps.d_maps.begin(), ce = maps.d_maps.end(); ci != ce; ++ci) { 96 d_maps.push_back(new D4Map(**ci)); 97 } 98 } 99 100 public: D4Maps()101 D4Maps() {} D4Maps(Array * parent)102 D4Maps(Array* parent) : d_parent(parent) { } D4Maps(const D4Maps & maps)103 D4Maps(const D4Maps &maps) { m_duplicate(maps); } ~D4Maps()104 virtual ~D4Maps() { 105 for (D4MapsIter i = d_maps.begin(), e = d_maps.end(); i != e; ++i) 106 delete *i; 107 } 108 109 D4Maps &operator=(const D4Maps &rhs); 110 111 /** 112 * Add a map. This does not test for duplicate names or Array pointers; 113 * It assumes that the caller has done that! 114 */ add_map(D4Map * map)115 void add_map(D4Map *map) { 116 d_maps.push_back(map); 117 // if the Map parent is not set, do so now 118 if (!d_maps.back()->parent()) 119 d_maps.back()->set_parent(d_parent); 120 } 121 remove_map(D4Map * map)122 void remove_map(D4Map *map) { 123 for (D4MapsIter i = d_maps.begin(), e = d_maps.end(); i != e; ++i) { 124 /* && (*i)->parent() == map->parent() */ 125 // Don't test if the map->parent() matches - we only care about the name and array. 126 // This method is intended for processing CE array slices that are edge cases and 127 // is only called from code where we know map->parent() matches *i->parent(). 128 // jhrg 4/12/16 129 if ((*i)->name() == map->name() && (*i)->array() == map->array()) { 130 d_maps.erase(i); 131 break; 132 } 133 } 134 } 135 get_map(int i)136 D4Map* get_map(int i) { return d_maps.at(i); } 137 map_begin()138 D4MapsIter map_begin() { return d_maps.begin(); } map_end()139 D4MapsIter map_end() { return d_maps.end(); } 140 size()141 int size() const { return d_maps.size(); } empty()142 bool empty() const { return d_maps.empty(); } 143 print_dap4(XMLWriter & xml)144 virtual void print_dap4(XMLWriter &xml) { 145 for (D4MapsIter i = d_maps.begin(), e = d_maps.end(); i != e; ++i) 146 (*i)->print_dap4(xml); 147 } 148 }; 149 150 } /* namespace libdap */ 151 #endif /* D4MAPS_H_ */ 152