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