bes  Updated for version 3.20.10
CSV_Obj.cc
1 // CSV_Obj.cc
2 
3 // This file is part of bes, A C++ back-end server implementation framework
4 // for the OPeNDAP Data Access Protocol.
5 
6 // Copyright (c) 2004-2009 University Corporation for Atmospheric Research
7 // Author: Stephan Zednik <zednik@ucar.edu> and Patrick West <pwest@ucar.edu>
8 // and Jose Garcia <jgarcia@ucar.edu>
9 //
10 // This library is free software; you can redistribute it and/or
11 // modify it under the terms of the GNU Lesser General Public
12 // License as published by the Free Software Foundation; either
13 // version 2.1 of the License, or (at your option) any later version.
14 //
15 // This library is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 // Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public
21 // License along with this library; if not, write to the Free Software
22 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 //
24 // You can contact University Corporation for Atmospheric Research at
25 // 3080 Center Green Drive, Boulder, CO 80301
26 
27 // (c) COPYRIGHT University Corporation for Atmospheric Research 2004-2005
28 // Please read the full copyright statement in the file COPYRIGHT_UCAR.
29 //
30 // Authors:
31 // zednik Stephan Zednik <zednik@ucar.edu>
32 // pwest Patrick West <pwest@ucar.edu>
33 // jgarcia Jose Garcia <jgarcia@ucar.edu>
34 
35 #include <iostream>
36 #include <sstream>
37 #include <iomanip>
38 
39 #include "CSV_Obj.h"
40 #include "CSV_Utils.h"
41 
42 #include <BESInternalError.h>
43 #include <BESNotFoundError.h>
44 #include <BESSyntaxUserError.h>
45 
46 #include <BESLog.h>
47 
48 using std::string;
49 using std::ostream;
50 using std::endl;
51 using std::vector;
52 using std::ostringstream;
53 
54 CSV_Obj::CSV_Obj()
55 {
56  _reader = new CSV_Reader();
57  _header = new CSV_Header();
58  _data = new vector<CSV_Data*>();
59 }
60 
61 CSV_Obj::~CSV_Obj()
62 {
63  if (_reader) {
64  _reader->close();
65  delete _reader;
66  _reader = 0;
67  }
68  if (_header) {
69  delete _header;
70  _header = 0;
71  }
72  if (_data) {
73  CSV_Data *d = 0;
74  vector<CSV_Data*>::iterator i = _data->begin();
75  vector<CSV_Data*>::iterator e = _data->end();
76  while (i != e) {
77  d = (*i);
78  delete d;
79  _data->erase(i);
80  i = _data->begin();
81  e = _data->end();
82  }
83  delete _data;
84  _data = 0;
85  }
86 }
87 
88 bool CSV_Obj::open(const string& filepath)
89 {
90  return _reader->open(filepath);
91 }
92 
93 void CSV_Obj::load()
94 {
95  vector<string> txtLine;
96  bool OnHeader = true;
97  _reader->reset();
98  while (!_reader->eof()) {
99  _reader->get(txtLine);
100 
101  if (OnHeader) {
102  if (_header->populate(&txtLine)) {
103  for (unsigned int i = 0; i < txtLine.size(); i++) {
104  _data->push_back(new CSV_Data());
105  }
106  }
107  OnHeader = false;
108  }
109  else if (!txtLine.empty()) {
110  int index = 0;
111  vector<CSV_Data *>::iterator it = _data->begin();
112  vector<CSV_Data *>::iterator et = _data->end();
113  for (; it != et; it++) {
114  CSV_Data *d = (*it);
115  try {
116  string token = txtLine.at(index);
117  CSV_Utils::slim(token);
118  CSV_Field *f = _header->getField(index);
119  if (!f) {
120  ostringstream err;
121  err << " Attempting to add value " << token << " to field " << index << ", field does not exist";
122  ERROR_LOG(err.str());
123  throw BESInternalError(err.str(), __FILE__, __LINE__);
124  }
125  d->insert(f, &token);
126  }
127  catch (const std::out_of_range &/*e*/) {
128  ostringstream err;
129  err << "Error in CSV dataset, too few data elements on line " << _reader->get_row_number();
130  // FIXME: Different on OSX and Linux << " (C++ Error: " << e.what() << ")";
131  ERROR_LOG(err.str());
132  throw BESSyntaxUserError(err.str(), __FILE__, __LINE__);
133  }
134  index++;
135  }
136  }
137  txtLine.clear();
138  }
139 }
140 
141 void CSV_Obj::getFieldList(vector<string> &list)
142 {
143  _header->getFieldList(list);
144 }
145 
146 string CSV_Obj::getFieldType(const string& fieldName)
147 {
148  return _header->getFieldType(fieldName);
149 }
150 
151 int CSV_Obj::getRecordCount()
152 {
153  CSV_Data* alphaField = _data->at(0);
154  string type = alphaField->getType();
155 
156  if (type.compare(string(STRING)) == 0) {
157  return ((vector<string>*) alphaField->getData())->size();
158  }
159  else if (type.compare(string(FLOAT32)) == 0) {
160  return ((vector<float>*) alphaField->getData())->size();
161  }
162  else if (type.compare(string(FLOAT64)) == 0) {
163  return ((vector<double>*) alphaField->getData())->size();
164  }
165  else if (type.compare(string(INT16)) == 0) {
166  return ((vector<short>*) alphaField->getData())->size();
167  }
168  else if (type.compare(string(INT32)) == 0) {
169  return ((vector<int>*) alphaField->getData())->size();
170  }
171  else {
172  return -1;
173  }
174 }
175 
176 void *
177 CSV_Obj::getFieldData(const string& field)
178 {
179  void *ret = 0;
180  CSV_Field *f = _header->getField(field);
181  if (f) {
182  int index = f->getIndex();
183  CSV_Data *d = _data->at(index);
184  if (d) {
185  ret = d->getData();
186  }
187  else {
188  string err = (string) "Unable to get data for field " + field;
189  throw BESInternalError(err, __FILE__, __LINE__);
190  }
191  }
192  else {
193  string err = (string) "Unable to get data for field " + field + ", no such field exists";
194  throw BESInternalError(err, __FILE__, __LINE__);
195  }
196  return ret;
197 }
198 
199 vector<string> CSV_Obj::getRecord(const int rowNum)
200 {
201  vector<string> record;
202  void* fieldData;
203  string type;
204 
205  int maxRows = getRecordCount();
206  if (rowNum > maxRows) {
207  ostringstream err;
208  err << "Attempting to retrieve row " << rowNum << " of " << maxRows;
209  throw BESInternalError(err.str(), __FILE__, __LINE__);
210  }
211 
212  vector<string> fieldList;
213  getFieldList(fieldList);
214  vector<string>::iterator it = fieldList.begin();
215  vector<string>::iterator et = fieldList.end();
216  for (; it != et; it++) {
217  string fieldName = (*it);
218  ostringstream oss;
219  fieldData = getFieldData(fieldName);
220  CSV_Field *f = _header->getField(fieldName);
221  if (!f) {
222  ostringstream err;
223  err << "Unable to retrieve data for field " << fieldName << " on row " << rowNum;
224  throw BESInternalError(err.str(), __FILE__, __LINE__);
225  }
226  type = f->getType();
227 
228  if (type.compare(string(STRING)) == 0) {
229  record.push_back(((vector<string>*) fieldData)->at(rowNum));
230  }
231  else if (type.compare(string(FLOAT32)) == 0) {
232  oss << ((vector<float>*) fieldData)->at(rowNum);
233  record.push_back(oss.str());
234  }
235  else if (type.compare(string(FLOAT64)) == 0) {
236  oss << ((vector<double>*) fieldData)->at(rowNum);
237  record.push_back(oss.str());
238  }
239  else if (type.compare(string(INT16)) == 0) {
240  oss << ((vector<short>*) fieldData)->at(rowNum);
241  record.push_back(oss.str());
242  }
243  else if (type.compare(string(INT32)) == 0) {
244  oss << ((vector<int>*) fieldData)->at(rowNum);
245  record.push_back(oss.str());
246  }
247  }
248 
249  return record;
250 }
251 
252 void CSV_Obj::dump(ostream &strm) const
253 {
254  strm << BESIndent::LMarg << "CSV_Obj::dump - (" << (void *) this << ")" << endl;
255  BESIndent::Indent();
256  if (_reader) {
257  strm << BESIndent::LMarg << "reader:" << endl;
258  BESIndent::Indent();
259  _reader->dump(strm);
260  BESIndent::UnIndent();
261  }
262  if (_header) {
263  strm << BESIndent::LMarg << "header:" << endl;
264  BESIndent::Indent();
265  _header->dump(strm);
266  BESIndent::UnIndent();
267  }
268  if (_data) {
269  strm << BESIndent::LMarg << "data:" << endl;
270  }
271  BESIndent::UnIndent();
272 }
273 
exception thrown if internal error encountered
error thrown if there is a user syntax error in the request or any other user error
virtual void dump(std::ostream &strm) const
dump the contents of this object to the specified ostream
Definition: CSV_Header.cc:166
virtual void dump(std::ostream &strm) const
dump the contents of this object to the specified ostream
Definition: CSV_Obj.cc:252
virtual void dump(std::ostream &strm) const
dump the contents of this object to the specified ostream
Definition: CSV_Reader.cc:115
static void slim(std::string &str)
Strips leading and trailing double quotes from string.
Definition: CSV_Utils.cc:72