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