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 D4ENUMDEF_H_
26 #define D4ENUMDEF_H_
27 
28 #include <string>
29 #include <vector>
30 #include <algorithm>
31 #include <functional>
32 
33 #include "BaseType.h"
34 
35 using namespace std;
36 
37 namespace libdap {
38 
39 class D4EnumDefs;
40 class D4Group;
41 
42 class D4EnumDef {
43     string d_name;
44     Type d_type;
45     D4EnumDefs *d_parent; // a weak pointer, do not delete
46 
47     struct tuple {
48         string label;
49         long long value;
50 
tupletuple51         tuple(const string &l, long long v) : label(l), value(v) {}
52     };
53 
54     vector<tuple> d_tuples;
55 
m_duplicate(const D4EnumDef & rhs)56     void m_duplicate(const D4EnumDef &rhs)
57     {
58         d_name = rhs.d_name;
59         d_type = rhs.d_type;
60         d_parent = rhs.d_parent;
61         d_tuples = rhs.d_tuples;
62     }
63 
64     void print_value(XMLWriter &xml, const D4EnumDef::tuple &tuple) const;
65 
66 public:
67     typedef vector<tuple>::iterator D4EnumValueIter;
68 
D4EnumDef()69     D4EnumDef() : d_name(""), d_type(dods_null_c), d_parent(0) {}
d_name(n)70     D4EnumDef(const string &n, const Type &t, D4EnumDefs *e = 0) : d_name(n), d_type(t), d_parent(e) {}
D4EnumDef(const D4EnumDef & rhs)71     D4EnumDef(const D4EnumDef &rhs) {
72         m_duplicate(rhs);
73     }
74 
~D4EnumDef()75     virtual ~D4EnumDef() { }
76 
77     D4EnumDef &operator=(const D4EnumDef &rhs) {
78         if (this == &rhs) return *this;
79         m_duplicate(rhs);
80         return *this;
81     }
82 
name()83     string name() const { return d_name; }
set_name(const string & n)84     void set_name(const string &n) { d_name = n; }
85 
type()86     Type type() const { return d_type; }
set_type(Type t)87     void set_type(Type t) { d_type = t; }
88 
parent()89     D4EnumDefs *parent() const { return d_parent; }
set_parent(D4EnumDefs * e)90     void set_parent(D4EnumDefs *e) { d_parent = e; }
91 
empty()92     bool empty() const { return d_tuples.empty(); }
93 
add_value(const string & label,long long value)94     void add_value(const string &label, long long value) {
95         d_tuples.push_back(tuple(label, value));
96     }
97 
value_begin()98     D4EnumValueIter value_begin() { return d_tuples.begin(); }
value_end()99     D4EnumValueIter value_end() { return d_tuples.end(); }
label(D4EnumValueIter i)100     string &label(D4EnumValueIter i) { return (*i).label; }
value(D4EnumValueIter i)101     long long value(D4EnumValueIter i) { return (*i).value; }
102 
103     bool is_valid_enum_value(long long value);
104     void print_dap4(XMLWriter &xml) const;
105 };
106 
107 /** The Enumerations defined for a Group. */
108 class D4EnumDefs {
109     vector<D4EnumDef*> d_enums;
110 
111     D4Group *d_parent;		// the group that holds this set of D4EnumDefs; weak pointer, don't delete
112 
113     void m_print_enum(XMLWriter &xml, D4EnumDef *e) const;
114 
m_duplicate(const D4EnumDefs & rhs)115     void m_duplicate(const D4EnumDefs &rhs) {
116         D4EnumDefCIter i = rhs.d_enums.begin();
117         while (i != rhs.d_enums.end()) {
118             d_enums.push_back(new D4EnumDef(**i++));    // deep copy
119         }
120 
121         d_parent = rhs.d_parent;
122     }
123 
124 public:
125     typedef vector<D4EnumDef*>::iterator D4EnumDefIter;
126     typedef vector<D4EnumDef*>::const_iterator D4EnumDefCIter;
127 
D4EnumDefs()128     D4EnumDefs() : d_parent(0) {}
D4EnumDefs(const D4EnumDefs & rhs)129     D4EnumDefs(const D4EnumDefs &rhs) {
130         m_duplicate(rhs);
131     }
132 
~D4EnumDefs()133     virtual ~D4EnumDefs() {
134         D4EnumDefIter i = d_enums.begin();
135         while(i != d_enums.end()) {
136             delete *i++;
137         }
138     }
139 
140     D4EnumDefs &operator=(const D4EnumDefs &rhs) {
141         if (this == &rhs) return *this;
142         m_duplicate(rhs);
143         return *this;
144     }
145 
empty()146     bool empty() const { return d_enums.empty(); }
147 
parent()148     D4Group *parent() const { return d_parent; }
set_parent(D4Group * p)149     void set_parent(D4Group *p) { d_parent = p; }
150 
151     /** Append a new D4EnumDef.
152      *
153      * @param enum_def The enumeration.
154      */
add_enum(D4EnumDef * enum_def)155     void add_enum(D4EnumDef *enum_def) {
156     	add_enum_nocopy(new D4EnumDef(*enum_def));
157     }
add_enum_nocopy(D4EnumDef * enum_def)158     void add_enum_nocopy(D4EnumDef *enum_def) {
159     	enum_def->set_parent(this);
160         d_enums.push_back(enum_def);
161     }
162 
163     /// Get an iterator to the start of the enumerations
enum_begin()164     D4EnumDefIter enum_begin() { return d_enums.begin(); }
165 
166     /// Get an iterator to the end of the enumerations
enum_end()167     D4EnumDefIter enum_end() { return d_enums.end(); }
168 
169     D4EnumDef *find_enum_def(const string &name);
170 
171     /**
172      * @brief Insert a D4EnumDef.
173      * Insert a D4EnumDef before the position specified by the iterator.
174      * @note Calling this method invalidates all iterators that reference this
175      * D4EnumDef object.
176      * @param enum_def Make a deep copy and insert the enumeration definition
177      * @param i iterator
178      */
insert_enum(D4EnumDef * enum_def,D4EnumDefIter i)179     void insert_enum(D4EnumDef *enum_def, D4EnumDefIter i) {
180     	D4EnumDef *enum_def_copy = new D4EnumDef(*enum_def);
181     	enum_def_copy->set_parent(this);
182         d_enums.insert(i, enum_def_copy);
183     }
184 
185     void print_dap4(XMLWriter &xml, bool constrained = false) const;
186 };
187 
188 } /* namespace libdap */
189 #endif /* D4ENUMDEF_H_ */
190