Gaia
parsertypes.h
1 /*
2  * Copyright (C) 2006-2013 Music Technology Group - Universitat Pompeu Fabra
3  *
4  * This file is part of Gaia
5  *
6  * Gaia is free software: you can redistribute it and/or modify it under
7  * the terms of the GNU Affero General Public License as published by the Free
8  * Software Foundation (FSF), either version 3 of the License, or (at your
9  * option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14  * details.
15  *
16  * You should have received a copy of the Affero GNU General Public License
17  * version 3 along with this program. If not, see http://www.gnu.org/licenses/
18  */
19 
20 #ifndef GAIA_PARSER_PARSERTYPES_H
21 #define GAIA_PARSER_PARSERTYPES_H
22 
23 #include <QList>
24 #include "../point.h"
25 #include "grammar.h"
26 
27 namespace gaia2 {
28 
29  template <typename SearchPointType, typename DataSetType>
31 
32  class Filter;
33 
34  namespace parser {
35 
36 
38  // ----[ Base types ]-------------------------------------------------------//
39 
40  class Predicate {
41  public:
42  virtual ~Predicate() {}
43  virtual bool value() const = 0;
44  inline bool isTrue() const { return value(); }
45  virtual QString toString() const = 0;
46 
47  virtual Predicate* copy() const = 0;
48  };
49 
50  class Value {
51  public:
52  virtual ~Value() {}
53  virtual Real value() const = 0;
54  virtual QString toString() const = 0;
55 
56  virtual Value* copy() const = 0;
57  };
58 
59  class Label {
60  public:
61  virtual ~Label() {}
62  virtual QString value() const = 0;
63  virtual QString toString() const = 0;
64 
65  virtual Label* copy() const = 0;
66  };
67 
68 
69 
71  // ----[ Predicate types ]--------------------------------------------------//
72 
73  class PredValueComparison : public Predicate {
74  // note: access here should be protected, but since the SearchSpacePool has
75  // been templated, we can't forward-declare here it anymore
76  public:
77  Value *_lhs, *_rhs;
78  int _type;
79  friend class gaia2::Filter;
80 
81  public:
82  PredValueComparison(Value* lhs, int type, Value* rhs)
83  : _lhs(lhs), _rhs(rhs), _type(type) {}
84 
86  : Predicate(), _lhs(other._lhs->copy()), _rhs(other._rhs->copy()), _type(other._type) {}
87 
89  delete _lhs;
90  delete _rhs;
91  }
92 
93  virtual Predicate* copy() const {
94  return new PredValueComparison(*this);
95  }
96 
97  virtual bool value() const {
98  switch (_type) {
99  case EQ: return _lhs->value() == _rhs->value();
100  case NEQ: return _lhs->value() != _rhs->value();
101  case LT: return _lhs->value() < _rhs->value();
102  case GT: return _lhs->value() > _rhs->value();
103  case LTE: return _lhs->value() <= _rhs->value();
104  case GTE: return _lhs->value() >= _rhs->value();
105  default:
106  throw gaia2::GaiaException("Invalid type in PredValueComparison");
107  }
108  // should never get here
109  return false;
110  }
111 
112 
113  virtual QString toString() const {
114  QString result;
115  switch (_type) {
116  case EQ: result = "%1 == %2"; break;
117  case NEQ: result = "%1 != %2"; break;
118  case LT: result = "%1 < %2"; break;
119  case GT: result = "%1 > %2"; break;
120  case LTE: result = "%1 <= %2"; break;
121  case GTE: result = "%1 >= %2"; break;
122  }
123 
124  return result.arg(_lhs->toString()).arg(_rhs->toString());
125  }
126  };
127 
128  class PredValueRange : public Predicate {
129  // note: access here should be protected, but since the SearchSpacePool has
130  // been templated, we can't forward-declare here it anymore
131  public:
132  Value* _var;
133  Real _min, _max;
134  friend class gaia2::Filter;
135 
136  public:
137  PredValueRange(Value* var, Real minv, Real maxv)
138  : _var(var), _min(minv), _max(maxv) {
139  if (minv > maxv) {
140  _min = maxv;
141  _max = minv;
142  }
143  }
144 
145  PredValueRange(const PredValueRange& other)
146  : Predicate(), _var(other._var->copy()), _min(other._min), _max(other._max) {}
147 
148  ~PredValueRange() { delete _var; }
149 
150  virtual Predicate* copy() const {
151  return new PredValueRange(*this);
152  }
153 
154  virtual bool value() const {
155  Real v = _var->value();
156  return (v >= _min) && (v <= _max);
157  }
158 
159  virtual QString toString() const {
160  return QString("%1 BETWEEN %2 AND %3").arg(_var->toString()).arg(_min).arg(_max);
161  }
162  };
163 
165  // note: access here should be protected, but since the SearchSpacePool has
166  // been templated, we can't forward-declare here it anymore
167  public:
168  Label *_lhs, *_rhs;
169  int _type;
170  friend class gaia2::Filter;
171 
172  public:
173  PredLabelComparison(Label* lhs, int type, Label* rhs)
174  : _lhs(lhs), _rhs(rhs), _type(type) {}
175 
177  : Predicate(), _lhs(other._lhs->copy()), _rhs(other._rhs->copy()), _type(other._type) {}
178 
180  delete _lhs;
181  delete _rhs;
182  }
183 
184  virtual Predicate* copy() const {
185  return new PredLabelComparison(*this);
186  }
187 
188  virtual bool value() const {
189  switch (_type) {
190  case EQ: return _lhs->value() == _rhs->value();
191  case NEQ: return _lhs->value() != _rhs->value();
192  default:
193  throw gaia2::GaiaException("Invalid type in PredLabelComparison");
194  }
195  // should never get here
196  return false;
197  }
198 
199  virtual QString toString() const {
200  QString result;
201  switch (_type) {
202  case EQ: result = "%1 == %2"; break;
203  case NEQ: result = "%1 != %2"; break;
204  }
205 
206  return result.arg(_lhs->toString()).arg(_rhs->toString());
207  }
208  };
209 
210  class PredLogicalOp : public Predicate {
211  protected:
212  Predicate *_lhs, *_rhs;
213  int _op;
214  template <typename SearchPointType, typename DataSetType>
215  friend class gaia2::BaseQueryOptimizer;
216  friend class gaia2::Filter;
217 
218  public:
219  PredLogicalOp(Predicate* lhs, int op, Predicate* rhs)
220  : _lhs(lhs), _rhs(rhs), _op(op) {}
221 
222  PredLogicalOp(const PredLogicalOp& other)
223  : Predicate(), _lhs(other._lhs->copy()), _rhs(other._rhs->copy()), _op(other._op) {}
224 
225  ~PredLogicalOp() {
226  delete _lhs;
227  delete _rhs;
228  }
229 
230  virtual Predicate* copy() const {
231  return new PredLogicalOp(*this);
232  }
233 
234  virtual bool value() const {
235  switch (_op) {
236  case AND: return _lhs->value() && _rhs->value();
237  case OR: return _lhs->value() || _rhs->value();
238  default:
239  throw gaia2::GaiaException("Invalid type in PredLogicalOp");
240  }
241  // should never get here
242  return false;
243  }
244 
245  virtual QString toString() const {
246  QString result;
247  switch (_op) {
248  case AND: result = "(%1) AND (%2)"; break;
249  case OR: result = "(%1) OR (%2)"; break;
250  }
251 
252  return result.arg(_lhs->toString()).arg(_rhs->toString());
253  }
254  };
255 
256  class PredNegate : public Predicate {
257  protected:
258  Predicate* _pred;
259  template <typename SearchPointType, typename DataSetType>
260  friend class gaia2::BaseQueryOptimizer;
261  friend class gaia2::Filter;
262 
263  public:
264  PredNegate(Predicate* pred) : _pred(pred) {}
265  PredNegate(const PredNegate& other) : Predicate(), _pred(other._pred->copy()) {}
266  ~PredNegate() { delete _pred; }
267 
268  virtual Predicate* copy() const {
269  return new PredNegate(*this);
270  }
271 
272  virtual bool value() const {
273  return !_pred->value();
274  }
275 
276  virtual QString toString() const {
277  return QString("NOT (%1)").arg(_pred->toString());
278  }
279  };
280 
281  class BooleanConstant : public Predicate {
282  protected:
283  bool _value;
284 
285  public:
286  BooleanConstant(bool value) : _value(value) {}
287  virtual Predicate* copy() const { return new BooleanConstant(*this); }
288 
289  inline virtual bool value() const { return _value; }
290 
291  virtual QString toString() const {
292  return _value ? "True" : "False";
293  }
294  };
295 
296  class PredValueIsIn : public Predicate {
297  protected:
298  Value* _var;
299  QList<Real> _vlist;
300  friend class gaia2::Filter;
301 
302  public:
303  PredValueIsIn(Value* var, const QList<Real>& vlist)
304  : _var(var), _vlist(vlist) {}
305 
306  PredValueIsIn(const PredValueIsIn& other)
307  : Predicate(), _var(other._var->copy()), _vlist(other._vlist) {}
308 
309  ~PredValueIsIn() {
310  delete _var;
311  }
312 
313  virtual Predicate* copy() const {
314  return new PredValueIsIn(*this);
315  }
316 
317  virtual bool value() const {
318  return _vlist.contains(_var->value());
319  }
320 
321  virtual QString toString() const {
322  QString result = QString("%1 IN (").arg(_var->toString());
323  if (!_vlist.empty()) result += QString::number(_vlist[0]);
324  for (int i=1; i<_vlist.size(); i++) result += QString(", %1").arg(_vlist[i]);
325  return result + ")";
326  }
327  };
328 
329  class PredLabelIsIn : public Predicate {
330  protected:
331  Label* _var;
332  QStringList _slist;
333  template <typename SearchPointType, typename DataSetType>
334  friend class gaia2::BaseQueryOptimizer;
335  friend class gaia2::Filter;
336 
337  public:
338  PredLabelIsIn(Label* var, const QStringList& slist)
339  : _var(var), _slist(slist) {}
340 
341  PredLabelIsIn(const PredLabelIsIn& other)
342  : Predicate(), _var(other._var->copy()), _slist(other._slist) {}
343 
344  ~PredLabelIsIn() {
345  delete _var;
346  }
347 
348  virtual Predicate* copy() const {
349  return new PredLabelIsIn(*this);
350  }
351 
352  virtual bool value() const {
353  return _slist.contains(_var->value());
354  }
355 
356  virtual QString toString() const {
357  QString result = QString("%1 IN (").arg(_var->toString());
358  if (!_slist.empty()) result += QString("\"%1\"").arg(_slist[0]);
359  for (int i=1; i<_slist.size(); i++) result += QString(", \"%1\"").arg(_slist[i]);
360  return result + ")";
361  }
362  };
363 
364 
366  // ----[ Label types ]------------------------------------------------------//
367 
368  class LabelConstant : public Label {
369  protected:
370  QString _value;
371 
372  public:
373  LabelConstant(const QString& value) : _value(value) {}
374  virtual Label* copy() const { return new LabelConstant(*this); }
375  inline virtual QString value() const { return _value; }
376  virtual QString toString() const { return QString("%1").arg(_value); }
377  };
378 
379  class LabelVariable : public Label {
380  protected:
381  const gaia2::Point** _point;
382  DescriptorType _type;
383  DescriptorLengthType _ltype;
384  int _idx;
385  QString _varname; // name used by the user in the filter query
386  QString _fullname; // fully qualified name, used for getting values when label is of EnumType
387 
388  public:
389  LabelVariable(const QString& name) : _point(0), _ltype(FixedLength),
390  _idx(-1), _varname(name) {}
391 
392  QString name() const { return _varname; }
393 
394  virtual Label* copy() const { return new LabelVariable(*this); }
395 
396  virtual QString value() const {
397  if (_idx == -1) throw GaiaException("variable ", _varname, " is not bound...");
398  if (!_point) throw GaiaException("no currently set point");
399 
400  switch (_type) {
401  case StringType:
402  switch (_ltype) {
403  case FixedLength: return (*_point)->fstringData()[_idx];
404  case VariableLength: return (*_point)->vstringData()[_idx].toSingleValue();
405  }
406  throw GaiaException("Internal error at LabelVariable::value()");
407  case EnumType:
408  switch (_ltype) {
409  case FixedLength: return (*_point)->layout().enumToString(_fullname, (*_point)->fenumData()[_idx]);
410  case VariableLength: return (*_point)->layout().enumToString(_fullname, (*_point)->venumData()[_idx].toSingleValue());
411  }
412  // no need to have a throw here, as we'll fall back on the outer one anyway
413  default:
414  ;
415  }
416  throw GaiaException("Internal error at LabelVariable::value()");
417  }
418 
419  void bind(const PointLayout& layout, const Point** pointLocation) {
420  _point = pointLocation;
421  _fullname = layout.descriptorNames(layout.descriptorLocation(_varname))[0];
422 
423  Region location = layout.descriptorLocation(name());
424  _type = location.type();
425  _ltype = location.lengthType();
426  _idx = location.index();
427  }
428 
429  virtual QString toString() const { return _varname; }
430  };
431 
432  class LabelPointID : public Label {
433  protected:
434  const Point** _point;
435 
436  public:
437  LabelPointID() : _point(0) {}
438 
439  virtual Label* copy() const { return new LabelPointID(*this); }
440 
441  virtual QString value() const {
442  if (!_point) throw GaiaException("no currently set point");
443  return (*_point)->name();
444  }
445 
446  void bind(const Point** pointLocation) {
447  _point = pointLocation;
448  }
449 
450  virtual QString toString() const { return "point.id"; }
451  };
452 
453 
455  // ----[ Value types ]------------------------------------------------------//
456 
457  class ValueConstant : public Value {
458  protected:
459  Real _value;
460 
461  public:
462  ValueConstant(Real value) : _value(value) {}
463  virtual Value* copy() const { return new ValueConstant(*this); }
464  virtual Real value() const { return _value; }
465  virtual QString toString() const { return QString::number(_value); }
466  };
467 
468  class ValueVariable : public Value {
469  protected:
470  const gaia2::Point** _point;
471  DescriptorLengthType _ltype;
472  int _idx;
473  QString _varname;
474  int _dimension_number;
475 
476  public:
477 
478  ValueVariable(const QString& name) {
479  _point = 0;
480  _ltype = FixedLength;
481  _idx = -1;
482  _dimension_number = -1;
483 
484  /* check if name contains dimension number in the form n.a.m.e.[#], where # is the number.
485  * in case it contains the dimension number strip it from the name and save it to _dimension_number */
486 
487  if (name.lastIndexOf("[") != -1 && name.lastIndexOf("]") != -1){
488  _varname = name.left(name.lastIndexOf("["));
489 
490  QString dimension_number_str = name.section('[', 1);
491  dimension_number_str.chop(1);
492  bool ok;
493  int dimension_number = dimension_number_str.toInt(&ok, 10);
494  if (ok) {
495  // conversion succeeded
496  _dimension_number = dimension_number;
497  }else{
498  throw GaiaException("dimension number malformated for descriptor ", _varname, "...");
499  }
500  }else{
501  _varname = name;
502  }
503  }
504 
505  QString name() const {
506  return _varname;
507  }
508 
509  virtual Value* copy() const { return new ValueVariable(*this); }
510 
511  virtual Real value() const {
512  if (_idx == -1) throw GaiaException("variable ", _varname, " is not bound...");
513  if (!_point) throw GaiaException("no currently set point");
514 
515  switch (_ltype) {
516  case FixedLength: return (*_point)->frealData()[_idx];
517  case VariableLength: return (*_point)->vrealData()[_idx].toSingleValue();
518  }
519  throw GaiaException("Internal error at ValueVariable::value()");
520  }
521 
522  void bind(const PointLayout& layout, const Point** pointLocation) {
523  _point = pointLocation;
524  _ltype = layout.descriptorLocation(name()).lengthType();
525 
526  // Detect if the descriptor is multidimensional by checking the length of listIndices (NOTE: requires fix length transformation)
527  QVector< int > listIndices = layout.descriptorLocation(name()).listIndices(layout.descriptorLocation(name()).type(), layout.descriptorLocation(name()).lengthType());
528  if (listIndices.size() == 1){
529  // If descriptor is not multidimensional, we get the first index
530  _idx = layout.descriptorLocation(name()).index();
531  }else{
532  // If descriptor is multidimensional, get the value indicated by _dimension_number
533  if (_dimension_number < 0){
534  throw GaiaException("dimension number was not indicated for multidimensional descriptor ", _varname, "...");
535  }else{
536  if (_dimension_number < listIndices.size()){
537  _idx = listIndices[_dimension_number];
538  }else{
539  throw GaiaException("dimension number out of range for multidimensional descriptor ", _varname, "...");
540  }
541  }
542  }
543  }
544 
545  virtual QString toString() const { return _varname; }
546  };
547 
548  } // namespace parser
549 } // namespace gaia2
550 
551 
552 // useful define to trick lemon to generate code inside our namespace
553 #define OPEN_GAIA_PARSER_NS namespace gaia2 { namespace parser {
554 #define CLOSE_GAIA_PARSER_NS } } // namespace parser / namespace gaia2
555 
556 #endif // GAIA_PARSER_PARSERTYPES_H
Definition: parsertypes.h:59
Definition: parsertypes.h:128
Definition: parsertypes.h:210
int index() const
Returns the index corresponding to the descriptor contained in this region if and only if this region...
Definition: region.cpp:117
A region is a physical location in the point layout which consists in a list of segments.
Definition: region.h:125
QStringList descriptorNames() const
Returns all descriptor names from this layout.
Definition: pointlayout.cpp:77
Definition: parsertypes.h:40
The QueryOptimizer class tries to optimize a query by reducing the SearchSpace on which it is suppose...
Definition: parsertypes.h:30
Definition: parsertypes.h:468
Definition: parsertypes.h:432
This class describes the layout of a point.
Definition: pointlayout.h:60
Definition: parsertypes.h:296
The Filter class allows to check whether a predicate is true for a given Point.
Definition: filter.h:73
DescriptorLengthType
Either fixed-length or variable-length.
Definition: region.h:46
Definition: parsertypes.h:379
Definition: parsertypes.h:256
Main Gaia namespace, which contains all the library functions.
Definition: addfield.cpp:22
Definition: parsertypes.h:164
Definition: parsertypes.h:368
Definition: parsertypes.h:73
DescriptorLengthType lengthType() const
Returns the descriptor length type if all segments within this region are of the same type...
Definition: region.cpp:90
Definition: parsertypes.h:457
Definition: parsertypes.h:50
Definition: parsertypes.h:281
Definition: parsertypes.h:329
DescriptorType
The possible types of descriptors accepted.
Definition: region.h:36
Exception class that can take up to 3 arguments of any type, which will be serialized into a QString ...
Definition: gaiaexception.h:46
Definition: point.h:106
DescriptorType type() const
Returns the descriptor type if all segments within this region are of the same type.
Definition: region.cpp:74
Region descriptorLocation(const QString &name) const
Returns the region corresponding to the location of the specified descriptor or group of descriptors...
Definition: pointlayout.cpp:60