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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22 //
23 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
24 
25 #include "config.h"
26 
27 #include <sstream>
28 
29 #include "XMLWriter.h"
30 #include "D4Dimensions.h"
31 #include "D4Group.h"
32 
33 #include "Error.h"
34 #include "InternalErr.h"
35 
36 namespace libdap {
37 
38 void
set_size(const string & size)39 D4Dimension::set_size(const string &size)
40 {
41 	unsigned long value = 0;
42 	istringstream iss(size);
43 	iss >> value;
44 
45 	// First test if the stream is OK, then look to see if we read all
46 	// of the chars.
47 	if (!iss || !iss.eof()) throw Error("Invalid value '" + size + "' passed to D4Dimension::set_size.");
48 	set_size(value);
49 }
50 
51 /**
52  * @brief Get the FQN for the dimension
53  * @return The D4Dimension as a fully qualified name.
54  */
55 string
fully_qualified_name() const56 D4Dimension::fully_qualified_name() const
57 {
58 	string name = d_name;
59 
60 	// d_parent is the D4Dimensions container and its parent is the Group where
61 	// this Dimension is defined.
62 	D4Group *grp = d_parent->parent();
63 	while (grp) {
64 		// The root group is named "/" (always); this avoids '//name'
65 		name = (grp->name() == "/") ? "/" + name : grp->name() + "/" + name;
66 
67 		if (grp->get_parent())
68 			grp = static_cast<D4Group*>(grp->get_parent());
69 		else
70 			grp = 0;
71 	}
72 
73 	return name;
74 }
75 
76 /**
77  * @brief Print the Dimension declaration.
78  * Print the Dimension in a form suitable for use in a Group definition/declaration.
79  * @see print_dap4(XMLWriter &xml, bool print_fqn)
80  * @param xml Print to this XMLWriter instance
81  */
82 void
print_dap4(XMLWriter & xml) const83 D4Dimension::print_dap4(XMLWriter &xml) const
84 {
85 	if (xmlTextWriterStartElement(xml.get_writer(), (const xmlChar*) "Dimension") < 0)
86 		throw InternalErr(__FILE__, __LINE__, "Could not write Dimension element");
87 
88 	if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "name", (const xmlChar*)d_name.c_str()) < 0)
89 		throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
90 #if 0
91 	// Use FQNs when things are referenced, not when they are defined
92 	if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "name", (const xmlChar*)fully_qualified_name().c_str()) < 0)
93 		throw InternalErr(__FILE__, __LINE__, "Could not write attribute for name");
94 #endif
95 	ostringstream oss;
96 	if (d_constrained)
97 	    oss << (d_c_stop - d_c_start) / d_c_stride + 1;
98 	else
99 	    oss << d_size;
100 	if (xmlTextWriterWriteAttribute(xml.get_writer(), (const xmlChar*) "size", (const xmlChar*) oss.str().c_str()) < 0)
101 		throw InternalErr(__FILE__, __LINE__, "Could not write attribute for size");
102 
103 	if (xmlTextWriterEndElement(xml.get_writer()) < 0)
104 		throw InternalErr(__FILE__, __LINE__, "Could not end Dimension element");
105 }
106 
107 // Note that in order for this to work the second argument must not be a reference.
108 // jhrg 8/20/13
109 static bool
dim_name_eq(D4Dimension * d,const string name)110 dim_name_eq(D4Dimension *d, const string name)
111 {
112 	return d->name() == name;
113 }
114 
115 D4Dimension *
find_dim(const string & name)116 D4Dimensions::find_dim(const string &name)
117 {
118 	D4DimensionsIter d = find_if(d_dims.begin(), d_dims.end(), bind2nd(ptr_fun(dim_name_eq), name));
119 	return (d != d_dims.end()) ? *d: 0;
120 }
121 
122 void
print_dap4(XMLWriter & xml,bool constrained) const123 D4Dimensions::print_dap4(XMLWriter &xml, bool constrained) const
124 {
125     D4DimensionsCIter i = d_dims.begin();
126     while (i != d_dims.end()) {
127 #if 0
128     	if (!constrained || parent()->find_first_var_that_uses_dimension(*i))
129             (*i)->print_dap4(xml);
130 #endif
131     	if (constrained) {
132     		if ((*i)->used_by_projected_var())
133     		    (*i)->print_dap4(xml);
134     	}
135     	else {
136     		(*i)->print_dap4(xml);
137     	}
138         ++i;
139     }
140 }
141 
142 } /* namespace libdap */
143