/*
Ousía
Copyright (C) 2014, 2015 Benjamin Paaßen, Andreas Stöckel
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
/**
* @file Cardinality.hpp
*
* A Cardinality in this term here is some arbitrary subset of natural numbers
* (including zero), that specifies the permits size of some other set.
*
* We define Cardinalities in a constructive process, meaning constructive
* operators on elementary sets (either single numbers or ranges of numbers).
*
* Examples for such constructions are:
*
* {1}
* {1,...,4}
* {1,...,4} union {9,...,12} union {16}
* {0,...,infinity}
*
* Note that the only construction operator needed is union (or +).
*
* @author Benjamin Paaßen (bpaassen@techfak.uni-bielefeld.de)
*/
#ifndef _OUSIA_MODEL_CARDINALITY_HPP_
#define _OUSIA_MODEL_CARDINALITY_HPP_
namespace ousia {
namespace model {
/**
* This class is an abstract interface for Cardinality implementations, meaning
* either a Union of two other Cardinalities or elementary Cardinalities.
*/
class Cardinality {
public:
/**
* Returns true if and only if the given size is permits according to this
* Cardinality.
*
* @param is some natural number (size).
* @return true if and only if that size is permits.
*/
virtual bool permits(const size_t &size) const = 0;
virtual bool operator==(const Cardinality &rhs) const = 0;
};
/**
* A UnionCardinality is in fact just the binary or applied to the
* permits-criteria of two other cardinalities.
*/
class UnionCardinality : public Cardinality {
private:
const Cardinality &left;
const Cardinality &right;
public:
UnionCardinality(const Cardinality &left, const Cardinality &right)
: left(left), right(right)
{
}
bool permits(const size_t &size) const override
{
return left.permits(size) || right.permits(size);
}
bool operator==(const Cardinality &obj) const override
{
const UnionCardinality *o =
dynamic_cast(&obj);
if (o == NULL)
return false;
return left == o->left && right == o->right;
}
};
/**
* The unite function is basically just a wrapper for constructing a
* UnionCardinality.
*/
inline UnionCardinality unite(const Cardinality &lhs, const Cardinality &rhs)
{
return std::move(UnionCardinality(lhs, rhs));
}
/**
* A SingleCardinality permits exactly one number.
*/
class SingleCardinality : public Cardinality {
private:
size_t num;
public:
SingleCardinality(size_t num) : num(std::move(num)) {}
bool permits(const size_t &size) const override { return size == num; }
bool operator==(const Cardinality &obj) const override
{
const SingleCardinality *o =
dynamic_cast(&obj);
if (o == NULL)
return false;
return num == o->num;
}
};
/**
* A RangeCardinality permits all numbers between the two bounds (lo and hi),
* inclusively.
*/
class RangeCardinality : public Cardinality {
private:
size_t lo;
size_t hi;
public:
RangeCardinality(size_t lo, size_t hi)
: lo(std::move(lo)), hi(std::move(hi))
{
}
bool permits(const size_t &size) const override
{
return size >= lo && size <= hi;
}
bool operator==(const Cardinality &obj) const override
{
const RangeCardinality *o =
dynamic_cast(&obj);
if (o == NULL)
return false;
return lo == o->lo && hi == o->hi;
}
};
/**
* An OpenRangeCardinality permits all numbers higher or equal than the lower
* bound.
*/
class OpenRangeCardinality : public Cardinality {
private:
size_t lo;
public:
OpenRangeCardinality(size_t lo) : lo(std::move(lo)) {}
bool permits(const size_t &size) const override { return size >= lo; }
bool operator==(const Cardinality &obj) const override
{
const OpenRangeCardinality *o =
dynamic_cast(&obj);
if (o == NULL)
return false;
return lo == o->lo;
}
};
}
}
#endif /* _OUSIA_MODEL_CARDINALITY_HPP_ */