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