summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt3
-rw-r--r--src/core/model/Cardinality.hpp181
-rw-r--r--src/core/model/Domain.hpp55
-rw-r--r--test/core/model/CardinalityTest.cpp112
-rw-r--r--test/core/model/DocumentTest.cpp32
5 files changed, 358 insertions, 25 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 285abca..4469db2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -114,6 +114,7 @@ ADD_LIBRARY(ousia_core
src/core/managed/Managed
src/core/managed/ManagedType
src/core/managed/Manager
+ src/core/model/Cardinality
src/core/model/Document
src/core/model/Domain
src/core/model/Typesystem
@@ -184,6 +185,8 @@ IF(TEST)
test/core/managed/ManagedContainerTest
test/core/managed/ManagedTest
test/core/managed/ManagerTest
+ test/core/model/CardinalityTest
+ test/core/model/DocumentTest
test/core/parser/ParserStackTest
# test/core/script/FunctionTest
# test/core/script/ObjectTest
diff --git a/src/core/model/Cardinality.hpp b/src/core/model/Cardinality.hpp
new file mode 100644
index 0000000..aad5891
--- /dev/null
+++ b/src/core/model/Cardinality.hpp
@@ -0,0 +1,181 @@
+/*
+ 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 <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @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<const UnionCardinality *>(&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<const SingleCardinality *>(&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<const RangeCardinality *>(&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<const OpenRangeCardinality *>(&obj);
+ if (o == NULL)
+ return false;
+ return lo == o->lo;
+ }
+};
+}
+}
+
+#endif /* _OUSIA_MODEL_CARDINALITY_HPP_ */
+
diff --git a/src/core/model/Domain.hpp b/src/core/model/Domain.hpp
index 50c0bb1..65b9b1d 100644
--- a/src/core/model/Domain.hpp
+++ b/src/core/model/Domain.hpp
@@ -85,6 +85,7 @@
#include <core/managed/ManagedContainer.hpp>
#include <core/Node.hpp>
+#include "Cardinality.hpp"
#include "Typesystem.hpp"
namespace ousia {
@@ -181,10 +182,9 @@ public:
* Descriptor to be valid.
*/
FieldDescriptor(Manager &mgr, std::string name, Handle<Descriptor> parent,
- FieldType fieldType,
- ManagedVector<StructuredClass> children, bool optional)
+ FieldType fieldType, bool optional)
: Node(mgr, std::move(name), parent),
- children(children),
+ children(this),
fieldType(fieldType),
// TODO: What would be a wise initialization of the primitiveType?
optional(optional)
@@ -194,6 +194,11 @@ public:
// TODO: Is returning a ManagedVector alright?
ManagedVector<StructuredClass> &getChildren() { return children; }
+ const ManagedVector<StructuredClass> &getChildren() const
+ {
+ return children;
+ }
+
FieldType getFieldType() const { return fieldType; }
bool isPrimitive() const { return fieldType == FieldType::PRIMITIVE; }
@@ -236,11 +241,10 @@ private:
public:
Descriptor(Manager &mgr, std::string name, Handle<Node> parent,
// TODO: What would be a wise default value for attributes?
- Handle<StructType> attributesDescriptor,
- ManagedVector<FieldDescriptor> fieldDescriptors)
+ Handle<StructType> attributesDescriptor)
: Node(mgr, std::move(name), parent),
attributesDescriptor(acquire(attributesDescriptor)),
- fieldDescriptors(fieldDescriptors)
+ fieldDescriptors(this)
{
}
@@ -261,10 +265,6 @@ public:
}
};
-// TODO: Implement
-class Cardinality {
-};
-
/**
* A StructuredClass specifies nodes in the StructureTree of a document that
* implements this domain. For more information on the StructureTree please
@@ -342,7 +342,7 @@ class Cardinality {
*/
class StructuredClass : public Descriptor {
private:
- const Cardinality cardinality;
+ const Cardinality& cardinality;
Owned<StructuredClass> isa;
ManagedVector<FieldDescriptor> parents;
@@ -351,16 +351,13 @@ public:
StructuredClass(Manager &mgr, std::string name, Handle<Node> parent,
Handle<StructType> attributesDescriptor,
- ManagedVector<FieldDescriptor> fieldDescriptors,
const Cardinality &cardinality,
// TODO: What would be a wise default value for isa?
- Handle<StructuredClass> isa,
- ManagedVector<FieldDescriptor> parents, bool transparent)
- : Descriptor(mgr, std::move(name), parent, attributesDescriptor,
- fieldDescriptors),
+ Handle<StructuredClass> isa, bool transparent)
+ : Descriptor(mgr, std::move(name), parent, attributesDescriptor),
cardinality(cardinality),
isa(acquire(isa)),
- parents(parents),
+ parents(this),
transparent(transparent)
{
}
@@ -370,7 +367,7 @@ public:
Rooted<StructuredClass> getIsA() const { return isa; }
// TODO: Is returning a ManagedVector alright?
- ManagedVector<FieldDescriptor>& getParents() { return parents; }
+ ManagedVector<FieldDescriptor> &getParents() { return parents; }
const ManagedVector<FieldDescriptor> &getParents() const { return parents; }
};
@@ -396,23 +393,31 @@ private:
ManagedVector<AnnotationClass> annotationClasses;
public:
- Domain(Manager &mgr, std::string name,
- ManagedVector<StructuredClass> rootStructures,
- ManagedVector<AnnotationClass> annotationClasses)
+ Domain(Manager &mgr, std::string name)
// TODO: Can a domain have a parent?
: Node(mgr, std::move(name), nullptr),
- rootStructures(rootStructures),
- annotationClasses(annotationClasses)
+ rootStructures(this),
+ annotationClasses(this)
{
}
// TODO: Is returning a ManagedVector alright?
- ManagedVector<StructuredClass> getRootStructures()
+ ManagedVector<StructuredClass> &getRootStructures()
+ {
+ return rootStructures;
+ }
+
+ const ManagedVector<StructuredClass> &getRootStructures() const
{
return rootStructures;
}
- ManagedVector<AnnotationClass> getAnnotationClasses()
+ ManagedVector<AnnotationClass> &getAnnotationClasses()
+ {
+ return annotationClasses;
+ }
+
+ const ManagedVector<AnnotationClass> &getAnnotationClasses() const
{
return annotationClasses;
}
diff --git a/test/core/model/CardinalityTest.cpp b/test/core/model/CardinalityTest.cpp
new file mode 100644
index 0000000..34fa272
--- /dev/null
+++ b/test/core/model/CardinalityTest.cpp
@@ -0,0 +1,112 @@
+/*
+ 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 <http://www.gnu.org/licenses/>.
+*/
+
+#include <gtest/gtest.h>
+
+#include <core/model/Cardinality.hpp>
+
+namespace ousia {
+namespace model {
+TEST(Cardinality, testCardinalities)
+{
+ // Start with the elementary Cardinalities.
+ {
+ SingleCardinality c{1};
+ for (size_t s = 0; s < 100; s++) {
+ if (s != 1) {
+ ASSERT_FALSE(c.permits(s));
+ } else {
+ ASSERT_TRUE(c.permits(s));
+ }
+ }
+ }
+
+ {
+ OpenRangeCardinality c{4};
+ for (size_t s = 0; s < 100; s++) {
+ if (s < 4) {
+ ASSERT_FALSE(c.permits(s));
+ } else {
+ ASSERT_TRUE(c.permits(s));
+ }
+ }
+ }
+
+ {
+ RangeCardinality c{1, 10};
+ for (size_t s = 0; s < 100; s++) {
+ if (s < 1 || s > 10) {
+ ASSERT_FALSE(c.permits(s));
+ } else {
+ ASSERT_TRUE(c.permits(s));
+ }
+ }
+ }
+
+ // Then construct more complex ones as unions.
+
+ {
+ UnionCardinality c =
+ unite(SingleCardinality(1),
+ unite(RangeCardinality(4, 6), OpenRangeCardinality(16)));
+ for (size_t s = 0; s < 100; s++) {
+ if (s < 1 || (s > 1 && s < 4) || (s > 6 && s < 16)) {
+ ASSERT_FALSE(c.permits(s));
+ } else {
+ ASSERT_TRUE(c.permits(s));
+ }
+ }
+ }
+}
+
+TEST(Cardinality, testEquals)
+{
+ {
+ SingleCardinality a{1};
+ SingleCardinality b{2};
+ OpenRangeCardinality c{1};
+
+ ASSERT_EQ(a, a);
+ ASSERT_EQ(SingleCardinality(1), a);
+ ASSERT_EQ(b, b);
+ ASSERT_EQ(c, c);
+
+ ASSERT_FALSE(a == b);
+ ASSERT_FALSE(b == c);
+ ASSERT_FALSE(a == c);
+ }
+
+ {
+ RangeCardinality a{1, 1};
+ RangeCardinality b{1, 2};
+ RangeCardinality c{2, 2};
+
+ ASSERT_EQ(a, a);
+ ASSERT_EQ(RangeCardinality(1, 1), a);
+ ASSERT_EQ(b, b);
+ ASSERT_EQ(c, c);
+
+ ASSERT_FALSE(a == b);
+ // TODO: Here the semantics break down. It should be equal, in fact.
+ ASSERT_FALSE(a == SingleCardinality(1));
+ ASSERT_FALSE(b == c);
+ ASSERT_FALSE(a == c);
+ }
+}
+}
+}
diff --git a/test/core/model/DocumentTest.cpp b/test/core/model/DocumentTest.cpp
new file mode 100644
index 0000000..36e7c02
--- /dev/null
+++ b/test/core/model/DocumentTest.cpp
@@ -0,0 +1,32 @@
+/*
+ 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 <http://www.gnu.org/licenses/>.
+*/
+
+#include <gtest/gtest.h>
+
+#include <core/model/Document.hpp>
+
+namespace ousia {
+namespace model {
+TEST(Document, testDocumentConstruction)
+{
+ // Start by constructing the domain.
+ //TODO: IMPLEMENT
+ ASSERT_TRUE(true);
+}
+}
+}