bes  Updated for version 3.20.5
CmdTranslation.cc
1 // CmdTranslation.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: Patrick West <pwest@ucar.edu> and Jose Garcia <jgarcia@ucar.edu>
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 University Corporation for Atmospheric Research at
24 // 3080 Center Green Drive, Boulder, CO 80301
25 
26 // (c) COPYRIGHT University Corporation for Atmospheric Research 2004-2005
27 // Please read the full copyright statement in the file COPYRIGHT_UCAR.
28 //
29 // Authors:
30 // pwest Patrick West <pwest@ucar.edu>
31 // jgarcia Jose Garcia <jgarcia@ucar.edu>
32 
33 #include <iostream>
34 #include <list>
35 #include <map>
36 
37 using std::cerr;
38 using std::cout;
39 using std::list;
40 using std::map;
41 
42 #include "CmdTranslation.h"
43 #include "BESTokenizer.h"
44 #include "BESSyntaxUserError.h"
45 
46 #define MY_ENCODING "ISO-8859-1"
47 
48 map<string, CmdTranslation::p_cmd_translator> CmdTranslation::_translations;
49 bool CmdTranslation::_is_show = false;
50 
51 int CmdTranslation::initialize(int, char**)
52 {
53  _translations["show"] = CmdTranslation::translate_show;
54  _translations["show.catalog"] = CmdTranslation::translate_catalog;
55  _translations["show.info"] = CmdTranslation::translate_catalog;
56  _translations["show.error"] = CmdTranslation::translate_show_error;
57  _translations["set"] = CmdTranslation::translate_set;
58  _translations["set.context"] = CmdTranslation::translate_context;
59  _translations["set.container"] = CmdTranslation::translate_container;
60  _translations["define"] = CmdTranslation::translate_define;
61  _translations["delete"] = CmdTranslation::translate_delete;
62  _translations["get"] = CmdTranslation::translate_get;
63  return 0;
64 }
65 
66 int CmdTranslation::terminate(void)
67 {
68  return 0;
69 }
70 
71 void CmdTranslation::add_translation(const string &name, p_cmd_translator func)
72 {
73  CmdTranslation::_translations[name] = func;
74 }
75 
76 void CmdTranslation::remove_translation(const string &name)
77 {
78  map<string, p_cmd_translator>::iterator i = CmdTranslation::_translations.find(name);
79  if (i != CmdTranslation::_translations.end()) {
80  CmdTranslation::_translations.erase(i);
81  }
82 }
83 
84 string CmdTranslation::translate(const string &commands)
85 {
86  BESTokenizer t;
87  try {
88  t.tokenize(commands.c_str());
89 
90  string token = t.get_first_token();
91  if (token.empty()) {
92  return "";
93  }
94  }
95  catch (BESSyntaxUserError &e) {
96  cerr << "failed to build tokenizer for translation" << endl;
97  cerr << e.get_message() << endl;
98  return "";
99  }
100 
101  LIBXML_TEST_VERSION;
102 
103  int rc;
104  xmlTextWriterPtr writer = 0;
105  xmlBufferPtr buf = 0;
106  // Unused xmlChar *tmp = 0;
107 
108  /* Create a new XML buffer, to which the XML document will be
109  * written */
110  buf = xmlBufferCreate();
111  if (buf == NULL) {
112  cerr << "testXmlwriterMemory: Error creating the xml buffer" << endl;
113  return "";
114  }
115 
116  /* Create a new XmlWriter for memory, with no compression.
117  * Remark: there is no compression for this kind of xmlTextWriter */
118  writer = xmlNewTextWriterMemory(buf, 0);
119  if (writer == NULL) {
120  cerr << "testXmlwriterMemory: Error creating the xml writer" << endl;
121  return "";
122  }
123 
124  /* Start the document with the xml default for the version,
125  * encoding ISO 8859-1 and the default for the standalone
126  * declaration. MY_ENCODING defined at top of this file*/
127  rc = xmlTextWriterStartDocument(writer, NULL, MY_ENCODING, NULL);
128  if (rc < 0) {
129  cerr << "testXmlwriterMemory: Error at xmlTextWriterStartDocument" << endl;
130  xmlFreeTextWriter(writer);
131  return "";
132  }
133 
134  /* Start an element named "request". Since thist is the first
135  * element, this will be the root element of the document. */
136  rc = xmlTextWriterStartElement(writer, BAD_CAST "request");
137  if (rc < 0) {
138  cerr << "testXmlwriterMemory: Error at xmlTextWriterStartElement" << endl;
139  xmlFreeTextWriter(writer);
140  return "";
141  }
142 
143  /* Add the request id attribute */
144  rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "reqID",
145  BAD_CAST "some_unique_value");
146  if (rc < 0) {
147  cerr << "failed to add the request id attribute" << endl;
148  return "";
149  }
150 
151  bool status = do_translate(t, writer);
152  if (!status) {
153  xmlFreeTextWriter(writer);
154  return "";
155  }
156 
157  // this should end the request element
158  rc = xmlTextWriterEndElement(writer);
159  if (rc < 0) {
160  cerr << "failed to close request element" << endl;
161  xmlFreeTextWriter(writer);
162  return "";
163  }
164 
165  rc = xmlTextWriterEndDocument(writer);
166  if (rc < 0) {
167  cerr << "failed to end the document" << endl;
168  return "";
169  }
170 
171  xmlFreeTextWriter(writer);
172 
173  // get the xml document as a string and return
174  string doc;
175  if (!buf->content) {
176  cerr << "failed to retrieve document as string" << endl;
177  }
178  else {
179  doc = (char *) buf->content;
180  }
181 
182  xmlBufferFree(buf);
183 
184  xmlCleanupParser();
185 
186  return doc;
187 }
188 
189 bool CmdTranslation::do_translate(BESTokenizer &t, xmlTextWriterPtr writer)
190 {
191  string token = t.get_current_token();
192  CmdTranslation::p_cmd_translator p = _translations[token];
193  if (!p) {
194  cerr << endl << "Invalid command " << token << endl << endl;
195  return false;
196  }
197 
198  try {
199  bool status = p(t, writer);
200  if (!status) {
201  return status;
202  }
203  }
204  catch (BESSyntaxUserError &e) {
205  cerr << e.get_message() << endl;
206  return false;
207  }
208 
209  // if this throws an exception then there are no more tokens. Catch it
210  // and ignore the exception. This means we're done.
211  try {
212  token = t.get_next_token();
213  }
214  catch (BESSyntaxUserError &e) {
215  token.clear();
216  }
217 
218  if (token.empty()) {
219  // we are done.
220  return true;
221  }
222 
223  // more translation to do, so call do_translate again. It will grab the
224  // current token which we just got.
225  return do_translate(t, writer);
226 }
227 
228 bool CmdTranslation::translate_show(BESTokenizer &t, xmlTextWriterPtr writer)
229 {
230  CmdTranslation::set_show(true);
231 
232  string show_what = t.get_next_token();
233  if (show_what.empty()) {
234  t.parse_error("show command must be followed by target");
235  }
236 
237  string new_cmd = "show." + show_what;
238  CmdTranslation::p_cmd_translator p = _translations[new_cmd];
239  if (p) {
240  return p(t, writer);
241  }
242 
243  string semi = t.get_next_token();
244  if (semi != ";") {
245  string err = (string) "show " + show_what + " commands must end with a semicolon";
246  t.parse_error(err);
247  }
248  show_what[0] = toupper(show_what[0]);
249  string tag = "show" + show_what;
250 
251  // start the show element
252  int rc = xmlTextWriterStartElement(writer, BAD_CAST tag.c_str());
253  if (rc < 0) {
254  cerr << "failed to start " << tag << " element" << endl;
255  return false;
256  }
257 
258  // end the show element
259  rc = xmlTextWriterEndElement(writer);
260  if (rc < 0) {
261  cerr << "failed to close " << tag << " element" << endl;
262  return false;
263  }
264 
265  return true;
266 }
267 
268 bool CmdTranslation::translate_show_error(BESTokenizer &t, xmlTextWriterPtr writer)
269 {
270  string show_what = t.get_current_token();
271  if (show_what.empty() || show_what != "error") {
272  t.parse_error("show command must be error");
273  }
274 
275  string etype = t.get_next_token();
276  if (etype == ";") {
277  string err = (string) "show " + show_what + " command must include the error type to show";
278  t.parse_error(err);
279  }
280 
281  string semi = t.get_next_token();
282  if (semi != ";") {
283  string err = (string) "show " + show_what + " commands must end with a semicolon";
284  t.parse_error(err);
285  }
286  show_what[0] = toupper(show_what[0]);
287  string tag = "show" + show_what;
288 
289  // start the show element
290  int rc = xmlTextWriterStartElement(writer, BAD_CAST tag.c_str());
291  if (rc < 0) {
292  cerr << "failed to start " << tag << " element" << endl;
293  return false;
294  }
295 
296  /* Add the error type attribute */
297  rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "type",
298  BAD_CAST etype.c_str());
299  if (rc < 0) {
300  cerr << "failed to add the get type attribute" << endl;
301  return false;
302  }
303 
304  // end the show element
305  rc = xmlTextWriterEndElement(writer);
306  if (rc < 0) {
307  cerr << "failed to close " << tag << " element" << endl;
308  return false;
309  }
310 
311  return true;
312 }
313 
314 bool CmdTranslation::translate_catalog(BESTokenizer &t, xmlTextWriterPtr writer)
315 {
316  // show catalog|info [in catalog] [for node]
317  // <showCatalog node="" />
318  string show_what = t.get_current_token();
319  if (show_what.empty() || (show_what != "info" && show_what != "catalog")) {
320  t.parse_error("show command must be info or catalog");
321  }
322 
323  show_what[0] = toupper(show_what[0]);
324  string tag = "show" + show_what;
325 
326  string token = t.get_next_token();
327  string node;
328  if (token == "for") {
329  node = t.get_next_token();
330  if (node == ";") {
331  t.parse_error("show catalog command expecting node");
332  }
333  node = t.remove_quotes(node);
334  token = t.get_next_token();
335  }
336  if (token != ";") {
337  t.parse_error("show command must be terminated by a semicolon");
338  }
339 
340  // start the show element
341  int rc = xmlTextWriterStartElement(writer, BAD_CAST tag.c_str());
342  if (rc < 0) {
343  cerr << "failed to start " << tag << " element" << endl;
344  return false;
345  }
346 
347  /* Add the catalog node */
348  if (!node.empty()) {
349  rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "node",
350  BAD_CAST node.c_str());
351  if (rc < 0) {
352  cerr << "failed to add the catalog node attribute" << endl;
353  return false;
354  }
355  }
356 
357  // end the show element
358  rc = xmlTextWriterEndElement(writer);
359  if (rc < 0) {
360  cerr << "failed to close " << tag << " element" << endl;
361  return false;
362  }
363 
364  return true;
365 }
366 
367 bool CmdTranslation::translate_set(BESTokenizer &t, xmlTextWriterPtr writer)
368 {
369  string set_what = t.get_next_token();
370  if (set_what.empty()) {
371  t.parse_error("set command must be followed by target");
372  }
373 
374  string new_cmd = "set." + set_what;
375  CmdTranslation::p_cmd_translator p = _translations[new_cmd];
376  if (!p) {
377  cerr << "no such command: set " << set_what << endl;
378  return false;
379  }
380 
381  return p(t, writer);
382 }
383 
384 bool CmdTranslation::translate_context(BESTokenizer &t, xmlTextWriterPtr writer)
385 {
386  // set context blee to blah ;
387  // <setContext name="dap_format">dap2</setContext>
388  string name = t.get_next_token();
389  if (name == ";") {
390  t.parse_error("missing context name");
391  }
392  string to = t.get_next_token();
393  if (to != "to") {
394  t.parse_error("missing word \"to\" in set context");
395  }
396  string value = t.get_next_token();
397  if (value == ";") {
398  t.parse_error("missing context value");
399  }
400  string semi = t.get_next_token();
401  if (semi != ";") {
402  t.parse_error("set context command must end with semicolon");
403  }
404 
405  // start the setContext element
406  int rc = xmlTextWriterStartElement(writer, BAD_CAST "setContext");
407  if (rc < 0) {
408  cerr << "failed to start setContext element" << endl;
409  return false;
410  }
411 
412  /* Add the context name attribute */
413  rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "name",
414  BAD_CAST name.c_str());
415  if (rc < 0) {
416  cerr << "failed to add the context name attribute" << endl;
417  return false;
418  }
419 
420  /* Write the value of the context */
421  rc = xmlTextWriterWriteString(writer, BAD_CAST value.c_str());
422  if (rc < 0) {
423  cerr << "failed to write the value of the context" << endl;
424  return false;
425  }
426 
427  // end the setContext element
428  rc = xmlTextWriterEndElement(writer);
429  if (rc < 0) {
430  cerr << "failed to close setContext element" << endl;
431  return false;
432  }
433 
434  return true;
435 }
436 
437 bool CmdTranslation::translate_container(BESTokenizer &t, xmlTextWriterPtr writer)
438 {
439  // set container in space values name,value,type;
440  // <setContainer name="c" space="catalog">/data/fnoc1.nc</setContainer>
441  string token = t.get_next_token();
442  string space;
443  if (token == "in") {
444  space = t.get_next_token();
445  if (space == "values" || space == ";") {
446  t.parse_error("expecting name of container storage");
447  }
448  token = t.get_next_token();
449  }
450  if (token != "values") {
451  t.parse_error("missing values for set container");
452  }
453 
454  string name = t.get_next_token();
455  if (name == ";" || name == ",") {
456  t.parse_error("expecting name of the container");
457  }
458 
459  token = t.get_next_token();
460  if (token != ",") {
461  t.parse_error("missing comma in set container after name");
462  }
463 
464  string value = t.get_next_token();
465  if (value == "," || value == ";") {
466  t.parse_error("expecting location of the container");
467  }
468 
469  token = t.get_next_token();
470  string type;
471  if (token == ",") {
472  type = t.get_next_token();
473  if (type == ";") {
474  t.parse_error("expecting container type");
475  }
476  token = t.get_next_token();
477  }
478 
479  if (token != ";") {
480  t.parse_error("set container command must end with semicolon");
481  }
482 
483  // start the setContainer element
484  int rc = xmlTextWriterStartElement(writer, BAD_CAST "setContainer");
485  if (rc < 0) {
486  cerr << "failed to start setContext element" << endl;
487  return false;
488  }
489 
490  /* Add the container name attribute */
491  rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "name",
492  BAD_CAST name.c_str());
493  if (rc < 0) {
494  cerr << "failed to add the context name attribute" << endl;
495  return false;
496  }
497 
498  if (!space.empty()) {
499  /* Add the container space attribute */
500  rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "space",
501  BAD_CAST space.c_str());
502  if (rc < 0) {
503  cerr << "failed to add the container space attribute" << endl;
504  return false;
505  }
506  }
507 
508  if (!type.empty()) {
509  /* Add the container space attribute */
510  rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "type",
511  BAD_CAST type.c_str());
512  if (rc < 0) {
513  cerr << "failed to add the container type attribute" << endl;
514  return false;
515  }
516  }
517 
518  /* Write the value of the container */
519  rc = xmlTextWriterWriteString(writer, BAD_CAST value.c_str());
520  if (rc < 0) {
521  cerr << "failed to write the location of the container" << endl;
522  return false;
523  }
524 
525  // end the setContainer element
526  rc = xmlTextWriterEndElement(writer);
527  if (rc < 0) {
528  cerr << "failed to close setContext element" << endl;
529  return false;
530  }
531 
532  return true;
533 }
534 
535 bool CmdTranslation::translate_define(BESTokenizer &t, xmlTextWriterPtr writer)
536 {
537  // define <def_name> [in <storage_name>] as <container_list> [where // <container_x>.constraint="<constraint>",<container_x>.attributes="<attribute_list>"] // [aggregate by "<aggregation_command>"];
538 
539  // <define name="definition_name" space="store_name">
540  // <container name="container_name">
541  // <constraint>legal_constraint</constraint>
542  // <attributes>attribute_list</attributes>
543  // </container>
544  // <aggregate handler="someHandler" cmd="someCommand" />
545  // </define>
546  string name = t.get_next_token();
547  string space;
548  string token = t.get_next_token();
549  if (token == "in") {
550  space = t.get_next_token();
551  token = t.get_next_token();
552  }
553 
554  if (token != "as") {
555  t.parse_error("Looking for keyword as in define command");
556  }
557 
558  list<string> containers;
559  map<string, string> clist;
560  bool done = false;
561  while (!done) {
562  token = t.get_next_token();
563  containers.push_back(token);
564  clist[token] = token;
565  token = t.get_next_token();
566  if (token != ",") {
567  done = true;
568  }
569  }
570 
571  // constraints and attributes
572  map<string, string> constraints;
573  string default_constraint;
574  map<string, string> attrs;
575  if (token == "with") {
576  token = t.get_next_token();
577  unsigned int type;
578  while (token != "aggregate" && token != ";") {
579  // see if we have a default constraint for all containers
580  if (token == "constraint") {
581  default_constraint = t.remove_quotes(t.get_next_token());
582  }
583  else {
584  string c = t.parse_container_name(token, type);
585  if (clist[c] != c) {
586  t.parse_error("constraint container does not exist");
587  }
588  if (type == 1) {
589  // constraint
590  constraints[c] = t.remove_quotes(t.get_next_token());
591  }
592  else if (type == 2) {
593  // attributed
594  attrs[c] = t.remove_quotes(t.get_next_token());
595  }
596  else {
597  t.parse_error("unknown constraint type");
598  }
599  token = t.get_next_token();
600  if (token == ",") {
601  token = t.get_next_token();
602  }
603  }
604  }
605  }
606 
607  string agg_handler;
608  string agg_cmd;
609  if (token == "aggregate") {
610  token = t.get_next_token();
611  if (token == "by") {
612  agg_cmd = t.remove_quotes(t.get_next_token());
613  token = t.get_next_token();
614  if (token != "using") {
615  t.parse_error("aggregation expecting keyword \"using\"");
616  }
617  agg_handler = t.get_next_token();
618  }
619  else if (token == "using") {
620  agg_handler = t.get_next_token();
621  token = t.get_next_token();
622  if (token != "by") {
623  t.parse_error("aggregation expecting keyword \"by\"");
624  }
625  agg_cmd = t.remove_quotes(t.get_next_token());
626  }
627  else {
628  t.parse_error("aggregation expecting keyword \"by\" or \"using\"");
629  }
630 
631  token = t.get_next_token();
632  }
633 
634  if (token != ";") {
635  t.parse_error("define command must end with semicolon");
636  }
637 
638  // start the define element
639  int rc = xmlTextWriterStartElement(writer, BAD_CAST "define");
640  if (rc < 0) {
641  cerr << "failed to start setContext element" << endl;
642  return false;
643  }
644 
645  /* Add the definition name attribute */
646  rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "name",
647  BAD_CAST name.c_str());
648  if (rc < 0) {
649  cerr << "failed to add the context name attribute" << endl;
650  return false;
651  }
652 
653  if (!space.empty()) {
654  /* Add the definition space attribute */
655  rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "space",
656  BAD_CAST space.c_str());
657  if (rc < 0) {
658  cerr << "failed to add the container space attribute" << endl;
659  return false;
660  }
661  }
662 
663  // write the default constraint if we have one
664  if (!default_constraint.empty()) {
665  // start the constraint element
666  int rc = xmlTextWriterStartElement(writer, BAD_CAST "constraint");
667  if (rc < 0) {
668  cerr << "failed to start container constraint element" << endl;
669  return false;
670  }
671 
672  /* Write the value of the constraint */
673  rc = xmlTextWriterWriteString(writer, BAD_CAST default_constraint.c_str());
674  if (rc < 0) {
675  cerr << "failed to write constraint for container" << endl;
676  return false;
677  }
678 
679  // end the container constraint element
680  rc = xmlTextWriterEndElement(writer);
681  if (rc < 0) {
682  cerr << "failed to close constraint element" << endl;
683  return false;
684  }
685  }
686 
687  list<string>::iterator i = containers.begin();
688  list<string>::iterator e = containers.end();
689  for (; i != e; i++) {
690  // start the container element
691  int rc = xmlTextWriterStartElement(writer, BAD_CAST "container");
692  if (rc < 0) {
693  cerr << "failed to start container element" << endl;
694  return false;
695  }
696 
697  /* Add the container name attribute */
698  rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "name",
699  BAD_CAST (*i).c_str());
700  if (rc < 0) {
701  cerr << "failed to add the context name attribute" << endl;
702  return false;
703  }
704 
705  // add constraints and attributes elements here
706  string constraint = constraints[(*i)];
707  if (!constraint.empty()) {
708  // start the constraint element
709  int rc = xmlTextWriterStartElement(writer, BAD_CAST "constraint");
710  if (rc < 0) {
711  cerr << "failed to start container constraint element" << endl;
712  return false;
713  }
714 
715  /* Write the value of the constraint */
716  rc = xmlTextWriterWriteString(writer, BAD_CAST constraint.c_str());
717  if (rc < 0) {
718  cerr << "failed to write constraint for container" << endl;
719  return false;
720  }
721 
722  // end the container constraint element
723  rc = xmlTextWriterEndElement(writer);
724  if (rc < 0) {
725  cerr << "failed to close constraint element" << endl;
726  return false;
727  }
728  }
729 
730  string attr = attrs[(*i)];
731  if (!attr.empty()) {
732  // start the attribute element
733  int rc = xmlTextWriterStartElement(writer, BAD_CAST "attributes");
734  if (rc < 0) {
735  cerr << "failed to start container attributes element" << endl;
736  return false;
737  }
738 
739  /* Write the value of the constraint */
740  rc = xmlTextWriterWriteString(writer, BAD_CAST attr.c_str());
741  if (rc < 0) {
742  cerr << "failed to write attributes for container" << endl;
743  return false;
744  }
745 
746  // end the container constraint element
747  rc = xmlTextWriterEndElement(writer);
748  if (rc < 0) {
749  cerr << "failed to close attributes element" << endl;
750  return false;
751  }
752  }
753 
754  // end the container element
755  rc = xmlTextWriterEndElement(writer);
756  if (rc < 0) {
757  cerr << "failed to close setContext element" << endl;
758  return false;
759  }
760  }
761 
762  if (!agg_cmd.empty()) {
763  // start the aggregation element
764  int rc = xmlTextWriterStartElement(writer, BAD_CAST "aggregate");
765  if (rc < 0) {
766  cerr << "failed to start aggregate element" << endl;
767  return false;
768  }
769 
770  if (!agg_handler.empty()) {
771  /* Add the aggregation handler attribute */
772  rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "handler",
773  BAD_CAST agg_handler.c_str());
774  if (rc < 0) {
775  cerr << "failed to add the context name attribute" << endl;
776  return false;
777  }
778  }
779 
780  /* Add the aggregation command attribute */
781  rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "cmd",
782  BAD_CAST agg_cmd.c_str());
783  if (rc < 0) {
784  cerr << "failed to add the context name attribute" << endl;
785  return false;
786  }
787 
788  // end the aggregation element
789  rc = xmlTextWriterEndElement(writer);
790  if (rc < 0) {
791  cerr << "failed to close setContext element" << endl;
792  return false;
793  }
794  }
795 
796  // end the define element
797  rc = xmlTextWriterEndElement(writer);
798  if (rc < 0) {
799  cerr << "failed to close setContext element" << endl;
800  return false;
801  }
802 
803  return true;
804 }
805 
806 bool CmdTranslation::translate_delete(BESTokenizer &t, xmlTextWriterPtr writer)
807 {
808  // delete container <container_name> [from <storage_name>];
809  // delete containers [from <storage_name>]
810  // delete definition <definition_name> [from <storage_name>];
811  // delete definitions [from <storage_name>];
812 
813  // <deleteContainer name="container_name" space="store_name" />
814  // <deleteContainers space="store_name" />
815  // <deleteDefinition name="definition_name" space="store_name" />
816  // <deleteDefinitions space="store_name" />
817 
818  string del_what = t.get_next_token();
819  string new_cmd = "delete." + del_what;
820 
821  CmdTranslation::p_cmd_translator p = _translations[new_cmd];
822  if (p) {
823  return p(t, writer);
824  }
825 
826  bool single = true;
827  if (del_what == "container" || del_what == "definition") {
828  single = true;
829  }
830  else if (del_what == "containers" || del_what == "definitions") {
831  single = false;
832  }
833  else {
834  t.parse_error("unknown delete command");
835  }
836 
837  del_what[0] = toupper(del_what[0]);
838  string tag = "delete" + del_what;
839 
840  string name;
841  if (single) {
842  name = t.get_next_token();
843  }
844 
845  string space;
846  string token = t.get_next_token();
847  if (token == "from") {
848  space = t.get_next_token();
849  token = t.get_next_token();
850  }
851 
852  if (token != ";") {
853  t.parse_error("delete command expected to end with semicolon");
854  }
855 
856  // start the delete element
857  int rc = xmlTextWriterStartElement(writer, BAD_CAST tag.c_str());
858  if (rc < 0) {
859  cerr << "failed to start aggregate element" << endl;
860  return false;
861  }
862 
863  if (!name.empty()) {
864  /* Add the container or definition name attribute */
865  rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "name",
866  BAD_CAST name.c_str());
867  if (rc < 0) {
868  cerr << "failed to add the context name attribute" << endl;
869  return false;
870  }
871  }
872 
873  if (!space.empty()) {
874  /* Add the container or definition storage space attribute */
875  rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "space",
876  BAD_CAST space.c_str());
877  if (rc < 0) {
878  cerr << "failed to add the context name attribute" << endl;
879  return false;
880  }
881  }
882 
883  // end the delete element
884  rc = xmlTextWriterEndElement(writer);
885  if (rc < 0) {
886  cerr << "failed to close setContext element" << endl;
887  return false;
888  }
889 
890  return true;
891 }
892 
893 bool CmdTranslation::translate_get(BESTokenizer &t, xmlTextWriterPtr writer)
894 {
895  // get das|dds|dods|ddx for <definition_name> [return as <return_name>];
896  // <get type="das|dds|dods|ddx" definition="def_name" returnAs="returnAs" />
897  // get html_form for <definition> using <url>;
898  // <get type="das|dds|dods|ddx" definition="def_name" url="url" returnAs="returnAs" />
899  string get_what = t.get_next_token();
900  string token = t.get_next_token();
901  if (token != "for") {
902  t.parse_error("get command expecting keyword \"for\"");
903  }
904 
905  string def_name = t.get_next_token();
906  string returnAs;
907  string url;
908  string starting;
909  string bounding;
910  token = t.get_next_token();
911  bool done = false;
912  while (!done) {
913  if (token == "return") {
914  token = t.get_next_token();
915  if (token != "as") {
916  t.parse_error("get command expecting keyword \"as\" for return");
917  }
918  returnAs = t.get_next_token();
919  token = t.get_next_token();
920  }
921  else if (token == "using") {
922  url = t.get_next_token();
923  token = t.get_next_token();
924  }
925  else if (token == "contentStartId") {
926  starting = t.get_next_token();
927  token = t.get_next_token();
928  }
929  else if (token == "mimeBoundary") {
930  bounding = t.get_next_token();
931  token = t.get_next_token();
932  }
933  else if (token == ";") {
934  done = true;
935  }
936  else {
937  t.parse_error("unexpected token in get command");
938  }
939  }
940 
941  // start the get element
942  int rc = xmlTextWriterStartElement(writer, BAD_CAST "get");
943  if (rc < 0) {
944  cerr << "failed to start aggregate element" << endl;
945  return false;
946  }
947 
948  /* Add the get type attribute */
949  rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "type",
950  BAD_CAST get_what.c_str());
951  if (rc < 0) {
952  cerr << "failed to add the get type attribute" << endl;
953  return false;
954  }
955 
956  /* Add the get definition attribute */
957  rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "definition",
958  BAD_CAST def_name.c_str());
959  if (rc < 0) {
960  cerr << "failed to add the get definition attribute" << endl;
961  return false;
962  }
963 
964  if (!url.empty()) {
965  /* Add the get type attribute */
966  rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "url",
967  BAD_CAST url.c_str());
968  if (rc < 0) {
969  cerr << "failed to add the url attribute" << endl;
970  return false;
971  }
972  }
973 
974  if (!returnAs.empty()) {
975  /* Add the get type attribute */
976  rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "returnAs",
977  BAD_CAST returnAs.c_str());
978  if (rc < 0) {
979  cerr << "failed to add the returnAs attribute" << endl;
980  return false;
981  }
982  }
983 
984  if (!starting.empty()) {
985  // start the constraint element
986  int rc = xmlTextWriterStartElement(writer, BAD_CAST "contentStartId");
987  if (rc < 0) {
988  cerr << "failed to start contentStartId element" << endl;
989  return false;
990  }
991 
992  /* Write the value of the contentStartId */
993  rc = xmlTextWriterWriteString(writer, BAD_CAST starting.c_str());
994  if (rc < 0) {
995  cerr << "failed to write contentStartId for get request" << endl;
996  return false;
997  }
998 
999  // end the contentStartId constraint element
1000  rc = xmlTextWriterEndElement(writer);
1001  if (rc < 0) {
1002  cerr << "failed to close constraint element" << endl;
1003  return false;
1004  }
1005  }
1006 
1007  if (!bounding.empty()) {
1008  // start the mimeBoundary element
1009  int rc = xmlTextWriterStartElement(writer, BAD_CAST "mimeBoundary");
1010  if (rc < 0) {
1011  cerr << "failed to start mimeBoundary element" << endl;
1012  return false;
1013  }
1014 
1015  /* Write the value of the constraint */
1016  rc = xmlTextWriterWriteString(writer, BAD_CAST bounding.c_str());
1017  if (rc < 0) {
1018  cerr << "failed to write mimeBoundary for get request" << endl;
1019  return false;
1020  }
1021 
1022  // end the mimeBoundary constraint element
1023  rc = xmlTextWriterEndElement(writer);
1024  if (rc < 0) {
1025  cerr << "failed to close mimeBoundary element" << endl;
1026  return false;
1027  }
1028  }
1029 
1030  // end the get element
1031  rc = xmlTextWriterEndElement(writer);
1032  if (rc < 0) {
1033  cerr << "failed to close get element" << endl;
1034  return false;
1035  }
1036 
1037  return true;
1038 }
1039 
1040 void CmdTranslation::dump(ostream &strm)
1041 {
1042  strm << BESIndent::LMarg << "CmdTranslation::dump" << endl;
1043  BESIndent::Indent();
1044  if (_translations.empty()) {
1045  strm << BESIndent::LMarg << "NO translations registered" << endl;
1046  }
1047  else {
1048  strm << BESIndent::LMarg << "translations registered" << endl;
1049  BESIndent::Indent();
1050  map<string, p_cmd_translator>::iterator i = _translations.begin();
1051  map<string, p_cmd_translator>::iterator e = _translations.end();
1052  for (; i != e; i++) {
1053  strm << BESIndent::LMarg << (*i).first << endl;
1054  }
1055  BESIndent::UnIndent();
1056  }
1057  BESIndent::UnIndent();
1058 }
1059 
virtual std::string get_message()
get the error message for this exception
Definition: BESError.h:99
tokenizer for the BES request command string
Definition: BESTokenizer.h:70
string & get_next_token()
returns the next token from the token list
error thrown if there is a user syntax error in the request or any other user error
string & get_first_token()
returns the first token from the token list
Definition: BESTokenizer.cc:86
string remove_quotes(const string &s)
removes quotes from a quoted token
string parse_container_name(const string &s, unsigned int &type)
parses a container name for constraint and attributes
void parse_error(const string &s="")
throws an exception giving the tokens up to the point of the problem
Definition: BESTokenizer.cc:63
void tokenize(const char *p)
tokenize the BES request/command string
string & get_current_token()
returns the current token from the token list