bes  Updated for version 3.20.6
ff_ce_functions.cc
1 
2 // -*- mode: c++; c-basic-offset:4 -*-
3 
4 // This file is part of ff_handler a FreeForm API handler for the OPeNDAP
5 // DAP2 data server.
6 
7 // Copyright (c) 2005 OPeNDAP, Inc.
8 // Author: James Gallagher <jgallagher@opendap.org>
9 //
10 // This is free software; you can redistribute it and/or modify it under the
11 // terms of the GNU Lesser General Public License as published by the Free
12 // Software Foundation; either version 2.1 of the License, or (at your
13 // option) any later version.
14 //
15 // This software is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
17 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
18 // License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public
21 // License along with this library; if not, write to the Free Software
22 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 //
24 // You can contact OPeNDAP, Inc. at PO Box 112, Saunderstown, RI. 02874-0112.
25 
26 // (c) COPYRIGHT URI/MIT 1998-1999
27 // Please read the full copyright statement in the file COPYRIGHT.
28 //
29 // Authors:
30 // jhrg,jimg James Gallagher (jgallagher@gso.uri.edu)
31 
32 // This file contains various functions for use with/in constraint
33 // expressions.
34 
35 #include <iostream>
36 #include <string>
37 #include <algorithm>
38 
39 //#define DODS_DEBUG
40 
41 #include <BaseType.h>
42 #include <Str.h>
43 #include <Structure.h>
44 #include <Sequence.h>
45 #include <DDS.h>
46 #include <ConstraintEvaluator.h>
47 #include <ServerFunctionsList.h>
48 #include <Error.h>
49 #include <util.h>
50 #include <debug.h>
51 
52 #include "date_proc.h"
53 #include "DODS_Date.h"
54 #include "DODS_Date_Factory.h"
55 #include "DODS_StartDate_Factory.h"
56 #include "DODS_EndDate_Factory.h"
57 #include "DODS_Time.h"
58 #include "DODS_Time_Factory.h"
59 #include "DODS_StartTime_Factory.h"
60 #include "DODS_EndTime_Factory.h"
61 #include "DODS_Date_Time.h"
62 #include "DODS_Date_Time_Factory.h"
63 #include "DODS_StartDate_Time_Factory.h"
64 #include "DODS_EndDate_Time_Factory.h"
65 
66 #include "ff_ce_functions.h"
67 #include "FFStr.h"
68 
74 template < class T, class T_Factory >
75 inline static T get_instance(DDS & dds)
76 {
77  return T_Factory(dds).get();
78 }
79 
93 template < class T, class T_Factory >
94 static bool comparison(int argc, BaseType * argv[], DDS & dds)
95 {
96  if (argc < 1 || argc > 2)
97  throw Error(malformed_expr,
98  "Wrong number of arguments to a constraint expression function.");
99 
100  DBG(cerr << "comparision: argc: " << argc << endl);
101 
102  T t1(argv[0]);
103  T t2;
104  if (argc == 2)
105  t2.set(argv[1]);
106 
107  T current = get_instance < T, T_Factory > (dds);
108 
109  DBG(cerr << "t1: " << t1.get(iso8601) << endl);
110  if (argc == 2) {
111  DBG(cerr << "t2 (1): " << t2.get(iso8601) << endl);
112  }
113  DBG(cerr << "current: " << current.get(iso8601) << endl);
114 
115  if (argc == 2)
116  return ((t1 <= current) && (t2 >= current));
117  else
118  return (t1 == current);
119 }
120 
134 template < class T1, class T1_Factory, class T2, class T2_Factory >
135  static bool range_comparison(int argc, BaseType * argv[], DDS & dds)
136 {
137  if (argc != 2)
138  throw Error(malformed_expr,
139  "Wrong number of arguments to a constraint expression function.");
140 
141  T1 t1(argv[0]);
142  T2 t2(argv[1]);
143 
144  T1 current_start = get_instance < T1, T1_Factory > (dds);
145  T2 current_end = get_instance < T2, T2_Factory > (dds);
146 
147  return (((current_start >= t1) && (current_start <= t2)) ||
148  ((current_end >= t1) && (current_end <= t2)) ||
149  ((current_start <= t1) && (current_end >= t2)));
150 }
151 
160 static void
161 new_string_variable(const string & name, DDS & dds, BaseType * position = 0)
162 {
163  // Create the new variable
164 
165  Str *new_variable = new FFStr(name, "");
166  new_variable->set_read_p(true); // You must call this before ...
167  new_variable->set_synthesized_p(true); // this! Look at BaseType.cc.
168 
169  // Add it to the DDS in the right place
170 
171  if (position) {
172  switch (position->type()) {
173  case dods_structure_c:{
174  Structure *sp = (Structure *) position;
175  sp->add_var((BaseType *) new_variable);
176  break;
177  }
178 
179  case dods_sequence_c:{
180  Sequence *sp = (Sequence *) position;
181  sp->add_var((BaseType *) new_variable);
182  break;
183  }
184 
185  default:
186  delete new_variable;
187  throw Error(malformed_expr,
188  "You asked me to insert the synthesized variable in \n\
189 something that did not exist or was not a constructor \n\
190 type (e.g., a structure, sequence, ...).");
191  break;
192  }
193  }
194  else {
195  dds.add_var(new_variable);
196  }
197 
198  // Mark the variable as part of the current projection.
199 
200  dds.mark(name, true); // Don't just call set_send_p()!
201 
202  delete new_variable;
203 }
204 
205 static void func_date(int argc, BaseType * argv[], DDS & dds, bool *result)
206 {
207  DBG(cerr << "calling func_date" << endl);
208  *result = comparison < DODS_Date, DODS_Date_Factory > (argc, argv, dds);
209  DBG(cerr << "result: " << *result << endl << endl);
210 }
211 
212 static void func_startdate(int argc, BaseType * argv[], DDS & dds, bool *result)
213 {
214  DBG(cerr << "calling func_startdate" << endl);
215  *result = comparison < DODS_Date, DODS_StartDate_Factory > (argc, argv,
216  dds);
217 }
218 
219 static void func_enddate(int argc, BaseType * argv[], DDS & dds, bool *result)
220 {
221  DBG(cerr << "calling func_enddate" << endl);
222  *result = comparison < DODS_Date, DODS_EndDate_Factory > (argc, argv,
223  dds);
224 }
225 
226 static void func_date_range(int argc, BaseType * argv[], DDS & dds, bool *result)
227 {
228  *result = range_comparison < DODS_Date, DODS_StartDate_Factory, DODS_Date,
229  DODS_EndDate_Factory > (argc, argv, dds);
230 }
231 
232 static void func_time(int argc, BaseType * argv[], DDS & dds, bool *result)
233 {
234  *result = comparison < DODS_Time, DODS_Time_Factory > (argc, argv, dds);
235 }
236 
237 static void func_starttime(int argc, BaseType * argv[], DDS & dds, bool *result)
238 {
239  *result = comparison < DODS_Time, DODS_StartTime_Factory > (argc, argv,
240  dds);
241 }
242 
243 static void func_endtime(int argc, BaseType * argv[], DDS & dds, bool *result)
244 {
245  *result = comparison < DODS_Time, DODS_EndTime_Factory > (argc, argv,
246  dds);
247 }
248 
249 // This comparision function should be used for decimal dates. 5/29/99 jhrg
250 
251 static void func_date_time(int argc, BaseType * argv[], DDS & dds, bool *result)
252 {
253  *result = comparison < DODS_Date_Time, DODS_Date_Time_Factory > (argc,
254  argv,
255  dds);
256 }
257 
258 static void func_startdate_time(int argc, BaseType * argv[], DDS & dds, bool *result)
259 {
260  *result = comparison < DODS_Date_Time,
261  DODS_StartDate_Time_Factory > (argc, argv, dds);
262 }
263 
264 static void func_enddate_time(int argc, BaseType * argv[], DDS & dds, bool *result)
265 {
266  *result = comparison < DODS_Date_Time, DODS_EndDate_Time_Factory > (argc,
267  argv,
268  dds);
269 }
270 
271 // This function is added to the selection part of the CE when the matching
272 // `projection function' is run.
273 
274 // The date and date_time functions should now recognize decimal format years
275 // and date-times. 5/30/99 jhrg
276 
277 static void sel_dods_jdate(int argc, BaseType *[], DDS & dds, bool *result)
278 {
279  if (argc != 0)
280  throw Error(malformed_expr,
281  "Wrong number of arguments to internal selection function.\n\
282 Please report this error.");
283 
284  DODS_Date current =
285  get_instance < DODS_Date, DODS_Date_Factory > (dds);
286 
287  // Stuff the yyyy/ddd string into DODS_JDate.
288  Str *dods_jdate = (Str *) dds.var("DODS_JDate");
289  // By calling DODS_Date::get with the token `yd' I'm explicitly asking
290  // for the year/day (pseudo juilian) date format. 5/27/99 jhrg
291  string s = current.get(yd).c_str();
292  dods_jdate->val2buf(&s);
293 
294  *result = true;
295 }
296 
297 // A projection function: This adds a new variable to the DDS and arranges
298 // for the matching selection function (above) to be called.
299 
300 static void
301 proj_dods_jdate(int argc, BaseType * argv[], DDS & dds,
302  ConstraintEvaluator & ce)
303 {
304  if (argc < 0 || argc > 1)
305  throw Error(malformed_expr,
306  "Wrong number of arguments to projection function.\n\
307 Expected zero or one arguments.");
308 
309  new_string_variable("DODS_JDate", dds, (argc == 1) ? argv[0] : 0);
310 
311  // Add the selection function to the CE
312 
313  ce.append_clause(sel_dods_jdate, 0); // 0 == no BaseType args
314 }
315 
316 // Same as the above function, but for ymd dates.
317 
318 static void sel_dods_date(int argc, BaseType *[], DDS & dds, bool *result)
319 {
320  if (argc != 0)
321  throw Error(malformed_expr,
322  "Wrong number of arguments to internal selection function.\n\
323 Please report this error.");
324 
325  DODS_Date current =
326  get_instance < DODS_Date, DODS_Date_Factory > (dds);
327 
328  // Stuff the yyyy/ddd string into DODS_Date.
329  Str *dods_date = (Str *) dds.var("DODS_Date");
330  // Calling the regular form of DODS_Date::get() returns the data in y/m/d
331  // format. 5/27/99 jhrg
332  string s = current.get().c_str();
333  dods_date->val2buf(&s);
334 
335  *result = true;
336 }
337 
338 static void
339 proj_dods_date(int argc, BaseType * argv[], DDS & dds,
340  ConstraintEvaluator & ce)
341 {
342  if (argc < 0 || argc > 1)
343  throw Error(malformed_expr,
344  "Wrong number of arguments to projection function.\n\
345 Expected zero or one arguments.");
346 
347  new_string_variable("DODS_Date", dds, (argc == 1) ? argv[0] : 0);
348 
349  // Add the selection function to the CE
350 
351  ce.append_clause(sel_dods_date, 0); // 0 == no BaseType args
352 }
353 
354 /************************ DODS_Time functions *************************/
355 
356 
357 static void sel_dods_time(int argc, BaseType *[], DDS & dds, bool *result)
358 {
359  if (argc != 0)
360  throw Error(malformed_expr,
361  "Wrong number of arguments to internal selection function.\n\
362 Please report this error.");
363 
364  DODS_Time current =
365  get_instance < DODS_Time, DODS_Time_Factory > (dds);
366 
367  // Stuff the "hh:mm:ss" string into `DODS_Time'
368  Str *dods_time = (Str *) dds.var("DODS_Time");
369  string s = current.get().c_str();
370  dods_time->val2buf(&s);
371 
372  *result = true;
373 }
374 
375 static void
376 proj_dods_time(int argc, BaseType * argv[], DDS & dds,
377  ConstraintEvaluator & ce)
378 {
379  if (argc < 0 || argc > 1)
380  throw Error(malformed_expr,
381  "Wrong number of arguments to projection function.\n\
382 Expected zero or one arguments.");
383 
384  // Create the new variable
385 
386  new_string_variable("DODS_Time", dds, (argc == 1) ? argv[0] : 0);
387 
388  // Add the selection function to the CE
389 
390  ce.append_clause(sel_dods_time, 0); // 0 == no BaseType args
391 }
392 
393 /*************************** Date/Time functions *************************/
394 
395 // This function is added to the selection part of the CE when the matching
396 // `projection function' is run.
397 
398 static void sel_dods_date_time(int argc, BaseType *[], DDS & dds, bool *result)
399 {
400  if (argc != 0)
401  throw Error(malformed_expr,
402  "Wrong number of arguments to internal selection function.\n\
403 Please report this error.");
404 
405  DODS_Date_Time current
406  = get_instance < DODS_Date_Time, DODS_Date_Time_Factory > (dds);
407 
408  Str *dods_date_time = (Str *) dds.var("DODS_Date_Time");
409  string s = current.get().c_str();
410  dods_date_time->val2buf(&s);
411 
412  *result = true;
413 }
414 
415 // A projection function: This adds a new variable to the DDS and arranges
416 // for the matching selection function (above) to be called.
417 
418 static void
419 proj_dods_date_time(int argc, BaseType * argv[], DDS & dds,
420  ConstraintEvaluator & ce)
421 {
422  if (argc < 0 || argc > 1)
423  throw Error(malformed_expr,
424  "Wrong number of arguments to projection function.\n\
425 Expected zero or one arguments.");
426 
427  // Create the new variable
428 
429  new_string_variable("DODS_Date_Time", dds, (argc == 1) ? argv[0] : 0);
430 
431  // Add the selection function to the CE
432 
433  ce.append_clause(sel_dods_date_time, 0); // 0 == no BaseType args
434 }
435 
436 /*************************** Decimal/Year functions *************************/
437 
438 // This function is added to the selection part of the CE when the matching
439 // `projection function' is run.
440 
441 static void sel_dods_decimal_year(int argc, BaseType *[], DDS & dds, bool *result)
442 {
443  if (argc != 0)
444  throw Error(malformed_expr,
445  "Wrong number of arguments to internal selection function.\n\
446 Please report this error.");
447 
448  DODS_Date_Time current
449  = get_instance < DODS_Date_Time, DODS_Date_Time_Factory > (dds);
450 
451  // Stuff the yyyy/ddd string into DODS_JDate.
452  Str *dods_decimal_year = (Str *) dds.var("DODS_Decimal_Year");
453  string s = current.get(decimal);
454  dods_decimal_year->val2buf(&s);
455 
456  *result = true;
457 }
458 
459 // A projection function: This adds a new variable to the DDS and arranges
460 // for the matching selection function (above) to be called.
461 
462 static void
463 proj_dods_decimal_year(int argc, BaseType * argv[], DDS & dds,
464  ConstraintEvaluator & ce)
465 {
466  if (argc < 0 || argc > 1)
467  throw Error(malformed_expr,
468  "Wrong number of arguments to projection function.\n\
469 Expected zero or one arguments.");
470 
471  // Create the new variable
472 
473  new_string_variable("DODS_Decimal_Year", dds,
474  (argc == 1) ? argv[0] : 0);
475 
476  // Add the selection function to the CE
477 
478  ce.append_clause(sel_dods_decimal_year, 0); // 0 == no BaseType args
479 }
480 
481 /*************************** Decimal/Year functions *************************/
482 
483 // This function is added to the selection part of the CE when the matching
484 // `projection function' is run.
485 
486 static void sel_dods_startdecimal_year(int argc, BaseType *[], DDS & dds, bool *result)
487 {
488  if (argc != 0)
489  throw Error(malformed_expr,
490  "Wrong number of arguments to internal selection function.\n\
491 Please report this error.");
492 
493  DODS_Date_Time current
494  =
495  get_instance < DODS_Date_Time, DODS_StartDate_Time_Factory > (dds);
496 
497  // Stuff the yyyy/ddd string into DODS_JDate.
498  Str *dods_decimal_year = (Str *) dds.var("DODS_StartDecimal_Year");
499  string s = current.get(decimal);
500  dods_decimal_year->val2buf(&s);
501 
502  *result = true;
503 }
504 
505 // A projection function: This adds a new variable to the DDS and arranges
506 // for the matching selection function (above) to be called.
507 
508 static void
509 proj_dods_startdecimal_year(int argc, BaseType * argv[], DDS & dds,
510  ConstraintEvaluator & ce)
511 {
512  if (argc < 0 || argc > 1)
513  throw Error(malformed_expr,
514  "Wrong number of arguments to projection function.\n\
515 Expected zero or one arguments.");
516 
517  // Create the new variable
518 
519  new_string_variable("DODS_StartDecimal_Year", dds,
520  (argc == 1) ? argv[0] : 0);
521 
522  // Add the selection function to the CE
523 
524  ce.append_clause(sel_dods_startdecimal_year, 0); // 0 == no BaseType args
525 }
526 
527 /*************************** Decimal/Year functions *************************/
528 
529 // This function is added to the selection part of the CE when the matching
530 // `projection function' is run.
531 
532 static void sel_dods_enddecimal_year(int argc, BaseType *[], DDS & dds, bool *result)
533 {
534  if (argc != 0)
535  throw Error(malformed_expr,
536  "Wrong number of arguments to internal selection function.\n\
537 Please report this error.");
538 
539  DODS_Date_Time current
540  = get_instance < DODS_Date_Time, DODS_EndDate_Time_Factory > (dds);
541 
542  // Stuff the yyyy/ddd string into DODS_JDate.
543  Str *dods_decimal_year = (Str *) dds.var("DODS_EndDecimal_Year");
544  string s = current.get(decimal);
545  dods_decimal_year->val2buf(&s);
546 
547  *result = true;
548 }
549 
550 // A projection function: This adds a new variable to the DDS and arranges
551 // for the matching selection function (above) to be called.
552 
553 static void
554 proj_dods_enddecimal_year(int argc, BaseType * argv[], DDS & dds,
555  ConstraintEvaluator & ce)
556 {
557  if (argc < 0 || argc > 1)
558  throw Error(malformed_expr,
559  "Wrong number of arguments to projection function.\n\
560 Expected zero or one arguments.");
561 
562  // Create the new variable
563 
564  new_string_variable("DODS_EndDecimal_Year", dds,
565  (argc == 1) ? argv[0] : 0);
566 
567  // Add the selection function to the CE
568 
569  ce.append_clause(sel_dods_enddecimal_year, 0); // 0 == no BaseType args
570 }
571 
572 /************************ DODS_StartDate functions *************************/
573 
574 static void sel_dods_startdate(int argc, BaseType *[], DDS & dds, bool *result)
575 {
576  if (argc != 0)
577  throw Error(malformed_expr,
578  "Wrong number of arguments to internal selection function.\n\
579 Please report this error.");
580 
581  DODS_Date current =
582  get_instance < DODS_Date, DODS_StartDate_Factory > (dds);
583 
584  // Stuff the yyyy/ddd string into DODS_StartDate.
585  Str *dods_date = (Str *) dds.var("DODS_StartDate");
586  // Calling the regular form of DODS_Date::get() returns the data in y/m/d
587  // format. 5/27/99 jhrg
588  string s = current.get().c_str();
589  dods_date->val2buf(&s);
590 
591  *result = true;
592 }
593 
594 static void
595 proj_dods_startdate(int argc, BaseType * argv[], DDS & dds,
596  ConstraintEvaluator & ce)
597 {
598  if (argc < 0 || argc > 1)
599  throw Error(malformed_expr,
600  "Wrong number of arguments to projection function.\n\
601 Expected zero or one arguments.");
602 
603  new_string_variable("DODS_StartDate", dds, (argc == 1) ? argv[0] : 0);
604 
605  // Add the selection function to the CE
606 
607  ce.append_clause(sel_dods_startdate, 0); // 0 == no BaseType args
608 }
609 
610 /************************ DODS_StartTime functions *************************/
611 
612 static void sel_dods_starttime(int argc, BaseType *[], DDS & dds, bool *result)
613 {
614  if (argc != 0)
615  throw Error(malformed_expr,
616  "Wrong number of arguments to internal selection function.\n\
617 Please report this error.");
618 
619  DODS_Time current =
620  get_instance < DODS_Time, DODS_StartTime_Factory > (dds);
621 
622  // Stuff the "hh:mm:ss" string into `DODS_Time'
623  Str *dods_time = (Str *) dds.var("DODS_StartTime");
624  string s = current.get().c_str();
625  dods_time->val2buf(&s);
626 
627  *result = true;
628 }
629 
630 static void
631 proj_dods_starttime(int argc, BaseType * argv[], DDS & dds,
632  ConstraintEvaluator & ce)
633 {
634  if (argc < 0 || argc > 1)
635  throw Error(malformed_expr,
636  "Wrong number of arguments to projection function.\n\
637 Expected zero or one arguments.");
638 
639  // Create the new variable
640 
641  new_string_variable("DODS_StartTime", dds, (argc == 1) ? argv[0] : 0);
642 
643  // Add the selection function to the CE
644 
645  ce.append_clause(sel_dods_starttime, 0); // 0 == no BaseType args
646 }
647 
648 /*************************** StartDate/Time functions *************************/
649 
650 // This function is added to the selection part of the CE when the matching
651 // `projection function' is run.
652 
653 static void sel_dods_startdate_time(int argc, BaseType *[], DDS & dds, bool *result)
654 {
655  if (argc != 0)
656  throw Error(malformed_expr,
657  "Wrong number of arguments to internal selection function.\n\
658 Please report this error.");
659 
660  DODS_Date_Time current
661  =
662  get_instance < DODS_Date_Time, DODS_StartDate_Time_Factory > (dds);
663 
664  Str *dods_date_time = (Str *) dds.var("DODS_StartDate_Time");
665  string s = current.get().c_str();
666  dods_date_time->val2buf(&s);
667 
668  *result = true;
669 }
670 
671 // A projection function: This adds a new variable to the DDS and arranges
672 // for the matching selection function (above) to be called.
673 
674 static void
675 proj_dods_startdate_time(int argc, BaseType * argv[], DDS & dds,
676  ConstraintEvaluator & ce)
677 {
678  if (argc < 0 || argc > 1)
679  throw Error(malformed_expr,
680  "Wrong number of arguments to projection function.\n\
681 Expected zero or one arguments.");
682 
683  // Create the new variable
684 
685  new_string_variable("DODS_StartDate_Time", dds,
686  (argc == 1) ? argv[0] : 0);
687 
688  // Add the selection function to the CE
689 
690  ce.append_clause(sel_dods_startdate_time, 0); // 0 == no BaseType args
691 }
692 
693 /************************ DODS_EndDate functions *************************/
694 
695 static void sel_dods_enddate(int argc, BaseType *[], DDS & dds, bool *result)
696 {
697  if (argc != 0)
698  throw Error(malformed_expr,
699  "Wrong number of arguments to internal selection function.\n\
700 Please report this error.");
701 
702  DODS_Date current =
703  get_instance < DODS_Date, DODS_EndDate_Factory > (dds);
704 
705  // Stuff the yyyy/ddd string into DODS_EndDate.
706  Str *dods_date = (Str *) dds.var("DODS_EndDate");
707  // Calling the regular form of DODS_Date::get() returns the data in y/m/d
708  // format. 5/27/99 jhrg
709  string s = current.get().c_str();
710  dods_date->val2buf(&s);
711 
712  *result = true;
713 }
714 
715 static void
716 proj_dods_enddate(int argc, BaseType * argv[], DDS & dds,
717  ConstraintEvaluator & ce)
718 {
719  if (argc < 0 || argc > 1)
720  throw Error(malformed_expr,
721  "Wrong number of arguments to projection function.\n\
722 Expected zero or one arguments.");
723 
724  new_string_variable("DODS_EndDate", dds, (argc == 1) ? argv[0] : 0);
725 
726  // Add the selection function to the CE
727 
728  ce.append_clause(sel_dods_enddate, 0); // 0 == no BaseType args
729 }
730 
731 /************************ DODS_EndTime functions *************************/
732 
733 static void sel_dods_endtime(int argc, BaseType *[], DDS & dds, bool *result)
734 {
735  if (argc != 0)
736  throw Error(malformed_expr,
737  "Wrong number of arguments to internal selection function.\n\
738 Please report this error.");
739 
740  DODS_Time current =
741  get_instance < DODS_Time, DODS_EndTime_Factory > (dds);
742 
743  // Stuff the "hh:mm:ss" string into `DODS_Time'
744  Str *dods_time = (Str *) dds.var("DODS_EndTime");
745  string s = current.get().c_str();
746  dods_time->val2buf(&s);
747 
748  *result = true;
749 }
750 
751 static void
752 proj_dods_endtime(int argc, BaseType * argv[], DDS & dds,
753  ConstraintEvaluator & ce)
754 {
755  if (argc < 0 || argc > 1)
756  throw Error(malformed_expr,
757  "Wrong number of arguments to projection function.\n\
758 Expected zero or one arguments.");
759 
760  // Create the new variable
761 
762  new_string_variable("DODS_EndTime", dds, (argc == 1) ? argv[0] : 0);
763 
764  // Add the selection function to the CE
765 
766  ce.append_clause(sel_dods_endtime, 0); // 0 == no BaseType args
767 }
768 
769 /*************************** EndDate/Time functions *************************/
770 
771 // This function is added to the selection part of the CE when the matching
772 // `projection function' is run.
773 
774 static void sel_dods_enddate_time(int argc, BaseType *[], DDS & dds, bool *result)
775 {
776  if (argc != 0)
777  throw Error(malformed_expr,
778  "Wrong number of arguments to internal selection function.\n\
779 Please report this error.");
780 
781  DODS_Date_Time current
782  = get_instance < DODS_Date_Time, DODS_EndDate_Time_Factory > (dds);
783 
784  Str *dods_date_time = (Str *) dds.var("DODS_EndDate_Time");
785  string s = current.get().c_str();
786  dods_date_time->val2buf(&s);
787 
788  *result = true;
789 }
790 
791 // A projection function: This adds a new variable to the DDS and arranges
792 // for the matching selection function (above) to be called.
793 
794 static void
795 proj_dods_enddate_time(int argc, BaseType * argv[], DDS & dds,
796  ConstraintEvaluator & ce)
797 {
798  if (argc < 0 || argc > 1)
799  throw Error(malformed_expr,
800  "Wrong number of arguments to projection function.\n\
801 Expected zero or one arguments.");
802 
803  // Create the new variable
804 
805  new_string_variable("DODS_EndDate_Time", dds,
806  (argc == 1) ? argv[0] : 0);
807 
808  // Add the selection function to the CE
809 
810  ce.append_clause(sel_dods_enddate_time, 0); // 0 == no BaseType args
811 }
812 
813 void ff_register_functions()
814 {
815  libdap::ServerFunction *ff_dap_function;
816 
817  // The first set of functions all are 'Selection functions.' They are used
818  // in the selection part of a CE to choose which instances of a sequence
819  // will be sent. Each of these particular functions compare a given date,
820  // or range of dates, to the date information in the sequence instance.
821  // These function are very specific to sequences that contain date/time
822  // information.
823 
824  ff_dap_function = new libdap::ServerFunction(
825  // The name of the function as it will appear in a constraint expression
826  "date",
827  // The version of the function
828  "1.0",
829  // A brief description of the function
830  string("Compares the current variable to the date parameters. If only one parameter is passed then ") +
831  "this returns true if they're the same date. If two parameters are passed they are considered to be the beginning "+
832  "and end of a date range and the function returns true if the current variable falls in the range.",
833  // A usage/syntax statement
834  "date(date_1[, date_2])",
835  // A URL that points two a web page describing the function
836  "http://docs.opendap.org/index.php/Server_Side_Processing_Functions#FreeForm_Functions",
837  // A URI that defines the role of the function
838  "http://services.opendap.org/dap4/freeform-function/date",
839  // A pointer to the helloWorld() function
840  func_date
841  );
842  libdap::ServerFunctionsList::TheList()->add_function(ff_dap_function);
843 
844  ff_dap_function = new libdap::ServerFunction(
845  "date_range",
846  "1.0",
847  string("Compares the current sequence instance with the passed date range. Return true if the instance is within the range. ")+
848  "If only single date parameter is used as a start date to now.",
849  "date_range(startDate, endDate)",
850  "http://docs.opendap.org/index.php/Server_Side_Processing_Functions#FreeForm_Functions",
851  "http://services.opendap.org/dap4/freeform-function/date_range",
852  func_date_range
853  );
854  libdap::ServerFunctionsList::TheList()->add_function(ff_dap_function);
855 
856  ff_dap_function = new libdap::ServerFunction(
857  "start_date",
858  "1.0",
859  string("The current sequence instance is compared, as a start date, to the single passed parameter. Returns true if they're the same date. ")+
860  "If two parameters are passed they are considered a date range. True is returned if the current variable falls into the range.",
861  "start_date(date[, endDate])",
862  "http://docs.opendap.org/index.php/Server_Side_Processing_Functions#FreeForm_Functions",
863  "http://services.opendap.org/dap4/freeform-function/start_date",
864  func_startdate
865  );
866  libdap::ServerFunctionsList::TheList()->add_function(ff_dap_function);
867 
868  ff_dap_function = new libdap::ServerFunction(
869  "end_date",
870  "1.0",
871  string("The current sequence instance is compared, as an end date, to the single passed parameter. Returns true if they're the same date. ") +
872  "If two parameters are passed they are considered a date range. True is returned if the current variable falls into the range.",
873  "end_date(date[, endDate])",
874  "http://docs.opendap.org/index.php/Server_Side_Processing_Functions#FreeForm_Functions",
875  "http://services.opendap.org/dap4/freeform-function/end_date",
876  func_enddate
877  );
878  libdap::ServerFunctionsList::TheList()->add_function(ff_dap_function);
879 
880  ff_dap_function = new libdap::ServerFunction(
881  "time",
882  "1.0",
883  "Compares the current variable with the passed time range. Return true if the sequence instance is within the range.",
884  "time( time[, endTime] )",
885  "http://docs.opendap.org/index.php/Server_Side_Processing_Functions#FreeForm_Functions",
886  "http://services.opendap.org/dap4/freeform-function/time",
887  func_time
888  );
889  libdap::ServerFunctionsList::TheList()->add_function(ff_dap_function);
890 
891  ff_dap_function = new libdap::ServerFunction(
892  "start_time",
893  "1.0",
894  "Compares the current variable with the passed time range. Return true if the sequence instance is within the range.",
895  "start_time( time[, endTime] )",
896  "http://docs.opendap.org/index.php/Server_Side_Processing_Functions#FreeForm_Functions",
897  "http://services.opendap.org/dap4/freeform-function/start_time",
898  func_starttime
899  );
900  libdap::ServerFunctionsList::TheList()->add_function(ff_dap_function);
901 
902  ff_dap_function = new libdap::ServerFunction(
903  "end_time",
904  "1.0",
905  "Compares the current variable with the passed time range. Return true if the sequence instance is within the range.",
906  "end_time( time[, endTime] )",
907  "http://docs.opendap.org/index.php/Server_Side_Processing_Functions#FreeForm_Functions",
908  "http://services.opendap.org/dap4/freeform-function/end_time",
909  func_endtime
910  );
911  libdap::ServerFunctionsList::TheList()->add_function(ff_dap_function);
912 
913  ff_dap_function = new libdap::ServerFunction(
914  "date_time",
915  "1.0",
916  "Compares the current sequence instance with the passed date/time range. Return true if the instance is within the range.",
917  "date_time( date/time [, end date/time] )",
918  "http://docs.opendap.org/index.php/Server_Side_Processing_Functions#FreeForm_Functions",
919  "http://services.opendap.org/dap4/freeform-function/date_time",
920  func_date_time
921  );
922  libdap::ServerFunctionsList::TheList()->add_function(ff_dap_function);
923 
924  ff_dap_function = new libdap::ServerFunction(
925  "start_date_time",
926  "1.0",
927  "Compares the current sequence instance with the passed date/time range. Return true if the instance is within the range.",
928  "start_date_time( date/time [, end date/time] )",
929  "http://docs.opendap.org/index.php/Server_Side_Processing_Functions#FreeForm_Functions",
930  "http://services.opendap.org/dap4/freeform-function/start_date_time",
931  func_startdate_time
932  );
933  libdap::ServerFunctionsList::TheList()->add_function(ff_dap_function);
934 
935  ff_dap_function = new libdap::ServerFunction(
936  "end_date_time",
937  "1.0",
938  "Compares the current sequence instance with the passed date/time range. Return true if the instance is within the range.",
939  "end_date_time(date/time [, end date/time] )",
940  "http://docs.opendap.org/index.php/Server_Side_Processing_Functions#FreeForm_Functions",
941  "http://services.opendap.org/dap4/freeform-function/end_date_time",
942  func_enddate_time
943  );
944  libdap::ServerFunctionsList::TheList()->add_function(ff_dap_function);
945 
946  // These are 'Projection Functions' that add new variables to a dataset.
947  // Their operation might be superceeded by NCML (except that NCML doesn't
948  // do exactly what they do, but it could be extended...). The function
949  // is used in the projection part of a URL.
950 
951  ff_dap_function = new libdap::ServerFunction(
952  "DODS_Time",
953  "1.0",
954  "Adds a variable named DODS_Time that is an ISO 8601 time string to the dataset.",
955  "DODS_Time( [Sequence or Structure] )",
956  "http://docs.opendap.org/index.php/Server_Side_Processing_Functions#FreeForm_Functions",
957  "http://services.opendap.org/dap4/freeform-function/DODS_Time",
958  proj_dods_time
959  );
960  libdap::ServerFunctionsList::TheList()->add_function(ff_dap_function);
961 
962  ff_dap_function = new libdap::ServerFunction(
963  "DODS_StartTime",
964  "1.0",
965  "Adds a variable named DODS_StartTime that is an ISO 8601 time string to the dataset.",
966  "DODS_StartTime( [Sequence or Structure] )",
967  "http://docs.opendap.org/index.php/Server_Side_Processing_Functions#FreeForm_Functions",
968  "http://services.opendap.org/dap4/freeform-function/DODS_StartTime",
969  proj_dods_starttime
970  );
971  libdap::ServerFunctionsList::TheList()->add_function(ff_dap_function);
972 
973  ff_dap_function = new libdap::ServerFunction(
974  "DODS_EndTime",
975  "1.0",
976  "Adds a variable named DODS_EndTime that is an ISO 8601 time string to the dataset.",
977  "DODS_EndTime( [Sequence or Structure] )",
978  "http://docs.opendap.org/index.php/Server_Side_Processing_Functions#FreeForm_Functions",
979  "http://services.opendap.org/dap4/freeform-function/DODS_EndTime",
980  proj_dods_endtime
981  );
982  libdap::ServerFunctionsList::TheList()->add_function(ff_dap_function);
983 
984  ff_dap_function = new libdap::ServerFunction(
985  "DODS_JDate",
986  "1.0",
987  "Adds a variable named DODS_JDate that is the Julian day number to the dataset.",
988  "DODS_JDate( [Sequence or Structure variable] )",
989  "http://docs.opendap.org/index.php/Server_Side_Processing_Functions#FreeForm_Functions",
990  "http://services.opendap.org/dap4/freeform-function/DODS_JDATE",
991  proj_dods_jdate
992  );
993  libdap::ServerFunctionsList::TheList()->add_function(ff_dap_function);
994 
995  ff_dap_function = new libdap::ServerFunction(
996  "DODS_Date",
997  "1.0",
998  string("Adds a variable named DODS_Date that is an ISO 8601 date string to the dataset."),
999  "DODS_Date( [Sequence or Structure] )",
1000  "http://docs.opendap.org/index.php/Server_Side_Processing_Functions#FreeForm_Functions",
1001  "http://services.opendap.org/dap4/freeform-function/DODS_Date",
1002  proj_dods_date
1003  );
1004  libdap::ServerFunctionsList::TheList()->add_function(ff_dap_function);
1005 
1006  ff_dap_function = new libdap::ServerFunction(
1007  "DODS_StartDate",
1008  "1.0",
1009  string("Adds a variable named DODS_StartDate that is an ISO 8601 date string to the dataset."),
1010  "DODS_StartDate( [Sequence or Structure] )",
1011  "http://docs.opendap.org/index.php/Server_Side_Processing_Functions#FreeForm_Functions",
1012  "http://services.opendap.org/dap4/freeform-function/DODS_StartDate",
1013  proj_dods_startdate
1014  );
1015  libdap::ServerFunctionsList::TheList()->add_function(ff_dap_function);
1016 
1017  ff_dap_function = new libdap::ServerFunction(
1018  "DODS_EndDate",
1019  "1.0",
1020  string("Adds a variable named DODS_EndDate that is an ISO 8601 date string to the dataset."),
1021  "DODS_EndDate( [Sequence or Structure] )",
1022  "http://docs.opendap.org/index.php/Server_Side_Processing_Functions#FreeForm_Functions",
1023  "http://services.opendap.org/dap4/freeform-function/DODS_EndDate",
1024  proj_dods_enddate
1025  );
1026  libdap::ServerFunctionsList::TheList()->add_function(ff_dap_function);
1027  ff_dap_function = new libdap::ServerFunction(
1028  "DODS_Date_Time",
1029  "1.0",
1030  "Adds a variable named DODS_Date_Time that is an ISO 8601 date/time string to the dataset.",
1031  "DODS_Date_Time( [Sequence or Structure] )",
1032  "http://docs.opendap.org/index.php/Server_Side_Processing_Functions#FreeForm_Functions",
1033  "http://services.opendap.org/dap4/freeform-function/DODS_Date_Time",
1034  proj_dods_date_time
1035  );
1036  libdap::ServerFunctionsList::TheList()->add_function(ff_dap_function);
1037 
1038  ff_dap_function = new libdap::ServerFunction(
1039  "DODS_StartDate_Time",
1040  "1.0",
1041  "Adds a variable named DODS_StartDate_Time that is an ISO 8601 date/time string to the dataset.",
1042  "DODS_StartDate_Time( [Sequence or Structure] )",
1043  "http://docs.opendap.org/index.php/Server_Side_Processing_Functions#FreeForm_Functions",
1044  "http://services.opendap.org/dap4/freeform-function/DODS_StartDate_Time",
1045  proj_dods_startdate_time
1046  );
1047  libdap::ServerFunctionsList::TheList()->add_function(ff_dap_function);
1048 
1049  ff_dap_function = new libdap::ServerFunction(
1050  "DODS_EndDate_Time",
1051  "1.0",
1052  "Adds a variable named DODS_EndDate_Time that is an ISO 8601 date/time string to the dataset.",
1053  "DODS_EndDate_Time( [Sequence or Structure] )",
1054  "http://docs.opendap.org/index.php/Server_Side_Processing_Functions#FreeForm_Functions",
1055  "http://services.opendap.org/dap4/freeform-function/DODS_EndDate_Time",
1056  proj_dods_enddate_time
1057  );
1058  libdap::ServerFunctionsList::TheList()->add_function(ff_dap_function);
1059 
1060  ff_dap_function = new libdap::ServerFunction(
1061  "DODS_Decimal_Year",
1062  "1.0",
1063  "Adds a variable named DODS_Decimal_Year that is date as a decimal year/day value string to the dataset.",
1064  "DODS_Decimal_Year( [Sequence or Structure] )",
1065  "http://docs.opendap.org/index.php/Server_Side_Processing_Functions#FreeForm_Functions",
1066  "http://services.opendap.org/dap4/freeform-function/DODS_Decimal_Year",
1067  proj_dods_decimal_year
1068  );
1069  libdap::ServerFunctionsList::TheList()->add_function(ff_dap_function);
1070 
1071  ff_dap_function = new libdap::ServerFunction(
1072  "DODS_StartDecimal_Year",
1073  "1.0",
1074  "Adds a variable named DODS_StartDecimal_Year that is date as a decimal year/day value string to the dataset.",
1075  "DODS_StartDecimal_Year( [Sequence or Structure] )",
1076  "http://docs.opendap.org/index.php/Server_Side_Processing_Functions#FreeForm_Functions",
1077  "http://services.opendap.org/dap4/freeform-function/DODS_StartDecimal_Year",
1078  proj_dods_startdecimal_year
1079  );
1080  libdap::ServerFunctionsList::TheList()->add_function(ff_dap_function);
1081 
1082  ff_dap_function = new libdap::ServerFunction(
1083  "DODS_EndDecimal_Year",
1084  "1.0",
1085  "Adds a variable named DODS_EndDecimal_Year that is date as a decimal year/day value string to the dataset.",
1086  "DODS_EndDecimal_Year( [Sequence or Structure] )",
1087  "http://docs.opendap.org/index.php/Server_Side_Processing_Functions#FreeForm_Functions",
1088  "http://services.opendap.org/dap4/freeform-function/DODS_EndDecimal_Year",
1089  proj_dods_enddecimal_year
1090  );
1091  libdap::ServerFunctionsList::TheList()->add_function(ff_dap_function);
1092 }
DODS_Time
Definition: DODS_Time.h:63
DODS_StartDate_Factory
Definition: DODS_StartDate_Factory.h:72
DODS_Date
Definition: DODS_Date.h:108
DODS_EndDate_Factory
Definition: DODS_EndDate_Factory.h:50
Error
DODS_StartDate_Time_Factory
Definition: DODS_StartDate_Time_Factory.h:60
DODS_Date::get
string get(date_format format=ymd) const
Definition: DODS_Date.cc:429
DODS_Date_Time::get
string get(date_format format=ymd, bool gmt=true) const
Definition: DODS_Date_Time.cc:295
DODS_Date_Time
Definition: DODS_Date_Time.h:47
DODS_Time::get
string get(bool gmt=true) const
Definition: DODS_Time.cc:294
FFStr
Definition: FFStr.h:47