summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/managed/Rtti.hpp43
-rw-r--r--src/core/model/Document.cpp19
-rw-r--r--src/core/model/Document.hpp34
-rw-r--r--src/core/model/Domain.cpp19
-rw-r--r--src/core/model/Domain.hpp27
-rw-r--r--src/core/model/Typesystem.cpp14
-rw-r--r--test/core/model/DomainTest.cpp14
7 files changed, 84 insertions, 86 deletions
diff --git a/src/core/managed/Rtti.hpp b/src/core/managed/Rtti.hpp
index f53fd9b..5bf4c46 100644
--- a/src/core/managed/Rtti.hpp
+++ b/src/core/managed/Rtti.hpp
@@ -20,9 +20,42 @@
* @file Rtti.hpp
*
* Classes used for storing runtime type information (RTTI). RTTI is used to
- * lookup objects in the object graph of a certain type and to attach
+ * resolve objects of a certain type in the object graph and to attach
* information that should be accessible to the script engine.
*
+ * <b>Why is this needed?</b> C++ provides the <tt>typeid</tt> operator to
+ * retrieve a reference at an internal table associated with type information
+ * for the given class. However, there is no native way for attaching additonal
+ * information to this type information table. Additional information we need to
+ * store is the inheritance graph (which cannot easily be extracted from C++)
+ * and information that is relevant for script engines (such as a list of
+ * methods and properties). One could of course store information about the type
+ * within each instance of this type, however when managing thousands of objects
+ * this would mean an additional overhead.
+ *
+ * <b>How to use:</b> The Rtti class allows to attach this information to a
+ * certain C++ file. To do so, create a global constant of the type
+ * Rtti<T> in the cpp file associated with the type declaration, where T
+ * is the type you want to register. As the type must only be registered once,
+ * you must not declare the variable as "static" in the header file (this would
+ * register it whever the header is included). If you want to access the global
+ * constant from other Rtti definitions (as parent), create a forward declaration
+ * in the header file. If you want to access the RTTI of a certain object or
+ * type, use the global typeOf() function (however, don't use it
+ * within global variable initializations).
+ *
+ * <b>Example:</b>
+ * In the header file:
+ * \code{.hpp}
+ * // Only needed if the type needs to be accessed
+ * // from other compilation units!
+ * const Rtti<MyType> MyType_Rtti;
+ * \endcode
+ * In the source file:
+ * \code{.cpp}
+ * const Rtti<MyType> MyType_Rtti{"MyType", {&MyOtherType_Rtti}, [...]};
+ * \endcode
+ *
* @author Andreas Stöckel (astoecke@techfak.uni-bielefeld.de)
*/
@@ -154,7 +187,9 @@ public:
/**
* Function that can be used to retrieve the RTTI information of a Managed
- * object.
+ * object. Do not use this function in the initialization of global Rtti
+ * variables, use pointers at the other global variable instead (as the
+ * initialization order is not well defined).
*
* @tparam T is the C++ type for which the type information should be returned.
*/
@@ -166,7 +201,9 @@ inline const RttiBase &typeOf()
/**
* Function that can be used to retrieve the RTTI information of a Managed
- * object.
+ * object. Do not use this function in the initialization of global Rtti
+ * variables, use pointers at the other global variable instead (as the
+ * initialization order is not well defined).
*
* @tparam T is the C++ type for which the type information should be returned.
* @param obj is a dummy object for which the type information should be
diff --git a/src/core/model/Document.cpp b/src/core/model/Document.cpp
index 497bb43..f6ed5de 100644
--- a/src/core/model/Document.cpp
+++ b/src/core/model/Document.cpp
@@ -25,8 +25,7 @@ namespace model {
int DocumentEntity::getFieldDescriptorIndex(const std::string &fieldName)
{
- const NodeVector<FieldDescriptor> &fds =
- descriptor->getFieldDescriptors();
+ const NodeVector<FieldDescriptor> &fds = descriptor->getFieldDescriptors();
unsigned int f = 0;
// look if we have an empty name.
@@ -71,8 +70,7 @@ void DocumentEntity::getField(NodeVector<StructuredEntity> &res,
NodeVector<StructuredEntity> &DocumentEntity::getField(
Rooted<FieldDescriptor> fieldDescriptor)
{
- const NodeVector<FieldDescriptor> &fds =
- descriptor->getFieldDescriptors();
+ const NodeVector<FieldDescriptor> &fds = descriptor->getFieldDescriptors();
int f = 0;
for (auto &fd : fds) {
if (fd->getName() == fieldDescriptor->getName() &&
@@ -187,6 +185,19 @@ Rooted<DocumentPrimitive> DocumentPrimitive::buildEntity(
// and return it.
return entity;
}
+
+/* Type registrations */
+
+const Rtti<Document> Document_Rtti{"Document"};
+const Rtti<DocumentEntity> DocumentEntity_Rtti{"DocumentEntity"};
+const Rtti<AnnotationEntity> AnnotationEntity_Rtti{"AnnotationEntity",
+ {&DocumentEntity_Rtti}};
+const Rtti<StructuredEntity> StructuredEntity_Rtti{"StructuredEntity",
+ {&DocumentEntity_Rtti}};
+const Rtti<DocumentPrimitive> DocumentPrimitive_Rtti{"DocumentPrimitive",
+ {&StructuredEntity_Rtti}};
+const Rtti<AnnotationEntity::Anchor> Anchor_Rtti{"Anchor",
+ {&StructuredEntity_Rtti}};
}
}
diff --git a/src/core/model/Document.hpp b/src/core/model/Document.hpp
index 0e0a416..5a293d3 100644
--- a/src/core/model/Document.hpp
+++ b/src/core/model/Document.hpp
@@ -188,11 +188,6 @@ public:
};
/**
- * A global variable for the ManagedType of a DocumentEntity.
- */
-static ManagedType DocumentEntityType{"DocumentEntity", typeid(DocumentEntity)};
-
-/**
* A StructuredEntity is a node in the Structure Tree of a document. For more
* information please refer to the header documentation above.
*/
@@ -265,12 +260,6 @@ public:
};
/**
- * A global variable for the ManagedType of a StructuredEntity.
- */
-static ManagedType StructuredEntityType{
- "StructuredEntity", typeid(StructuredEntity), {&DocumentEntityType}};
-
-/**
* This is a wrapper for primitive types (Variants) inside the document graph.
* The most straightforward example for this is the actual document text, e.g.
* inside a paragraph. In that case this would represent a mere string.
@@ -308,12 +297,6 @@ public:
};
/**
- * A global variable for the ManagedType of a DocumentPrimitive.
- */
-static ManagedType DocumentPrimitiveType{
- "DocumentPrimitive", typeid(DocumentPrimitive), {&StructuredEntityType}};
-
-/**
* An AnnotationEntity is a span-like instance that is not bound by the elements
* of the Structure Tree. An annotation may very well overlap and cross the
* limits of StructureEntities. A typical example for AnnotationEntities are
@@ -377,18 +360,6 @@ public:
};
/**
- * A global variable for the ManagedType of an Anchor.
- */
-static ManagedType AnchorType{
- "Anchor", typeid(AnnotationEntity::Anchor), {&StructuredEntityType}};
-
-/**
- * A global variable for the ManagedType of an AnnotationEntity.
- */
-static ManagedType AnnotationEntityType{
- "AnnotationEntity", typeid(AnnotationEntity), {&DocumentEntityType}};
-
-/**
* A Document is mainly a wrapper for the Root structure node of the Document
* Graph.
*/
@@ -407,11 +378,6 @@ public:
Rooted<StructuredEntity> getRoot() const { return root; }
};
-
-/**
- * A global variable for the ManagedType of a Document.
- */
-static ManagedType DocumentType{"Document", typeid(Document)};
}
}
diff --git a/src/core/model/Domain.cpp b/src/core/model/Domain.cpp
index 8eee86a..4901692 100644
--- a/src/core/model/Domain.cpp
+++ b/src/core/model/Domain.cpp
@@ -34,7 +34,7 @@ void FieldDescriptor::doResolve(std::vector<Rooted<Managed>> &res,
}
// TODO: better alias?
-static std::string DESCRIPTOR_ATTRIBUTES_ALIAS {"attributes"};
+static std::string DESCRIPTOR_ATTRIBUTES_ALIAS{"attributes"};
void Descriptor::doResolve(std::vector<Rooted<Managed>> &res,
const std::vector<std::string> &path, Filter filter,
@@ -46,8 +46,9 @@ void Descriptor::doResolve(std::vector<Rooted<Managed>> &res,
fd->resolve(res, path, filter, filterData, idx, visited, nullptr);
}
// TODO: This throws a SEGFAULT for some reason.
-// attributesDescriptor->resolve(res, path, filter, filterData, idx, visited,
-// &DESCRIPTOR_ATTRIBUTES_ALIAS);
+ // attributesDescriptor->resolve(res, path, filter, filterData, idx,
+ // visited,
+ // &DESCRIPTOR_ATTRIBUTES_ALIAS);
}
void StructuredClass::doResolve(std::vector<Rooted<Managed>> &res,
@@ -56,7 +57,7 @@ void StructuredClass::doResolve(std::vector<Rooted<Managed>> &res,
VisitorSet &visited)
{
Descriptor::doResolve(res, path, filter, filterData, idx, visited);
- if(!isa.isNull()){
+ if (!isa.isNull()) {
isa->doResolve(res, path, filter, filterData, idx, visited);
}
}
@@ -75,6 +76,16 @@ void Domain::doResolve(std::vector<Rooted<Managed>> &res,
t->resolve(res, path, filter, filterData, idx, visited, nullptr);
}
}
+
+/* Type registrations */
+
+const Rtti<FieldDescriptor> FieldDescriptor_Rtti{"FieldDescriptor"};
+const Rtti<Descriptor> Descriptor_Rtti{"Descriptor"};
+const Rtti<StructuredClass> StructuredClass_Rtti{"StructuredClass",
+ {&Descriptor_Rtti}};
+const Rtti<AnnotationClass> AnnotationClass_Rtti{"AnnotationClass",
+ {&Descriptor_Rtti}};
+const Rtti<Domain> Domain_Rtti{"Domain"};
}
}
diff --git a/src/core/model/Domain.hpp b/src/core/model/Domain.hpp
index d19558e..c0946bf 100644
--- a/src/core/model/Domain.hpp
+++ b/src/core/model/Domain.hpp
@@ -212,11 +212,6 @@ public:
Rooted<Type> getPrimitiveType() const { return primitiveType; }
};
-/**
- * A global variable for the ManagedType of a FieldDescriptor.
- */
-static ManagedType FieldDescriptorType{"FieldDescriptor",
- typeid(FieldDescriptor)};
/**
* This is a super class for StructuredClasses and AnnotationClasses and is,
@@ -283,11 +278,6 @@ public:
}
};
-/**
- * A global variable for the ManagedType of a Descriptor.
- */
-static ManagedType DescriptorType{"Descriptor", typeid(Descriptor)};
-
typedef RangeSet<size_t> Cardinality;
/**
@@ -405,12 +395,6 @@ public:
};
/**
- * A global variable for the ManagedType of a StructuredClass.
- */
-static ManagedType StructuredClassType{
- "StructuredClass", typeid(StructuredClass), {&DescriptorType}};
-
-/**
* An AnnotationClass defines allowed Annotations. For more information on
* Annotations please refer to the Document.hpp.
*
@@ -420,12 +404,6 @@ class AnnotationClass : public Descriptor {
};
/**
- * A global variable for the ManagedType of an AnnotationClass.
- */
-static ManagedType AnnotationClassType{
- "AnnotationClass", typeid(AnnotationClass), {&DescriptorType}};
-
-/**
* A Domain node specifies which StructuredClasses are allowed at the root
* level (or which Nonterminals are axioms of the grammar) and which Annotations
* are allowed globally. TODO: Do we want to be able to restrict Annotations to
@@ -475,11 +453,6 @@ public:
const NodeVector<Typesystem> &getTypesystems() const { return typesystems; }
};
-
-/**
- * A global variable for the ManagedType of a Domain.
- */
-static ManagedType DomainType{"Domain", typeid(Domain)};
}
}
diff --git a/src/core/model/Typesystem.cpp b/src/core/model/Typesystem.cpp
index 724bf0e..1da45ae 100644
--- a/src/core/model/Typesystem.cpp
+++ b/src/core/model/Typesystem.cpp
@@ -76,13 +76,13 @@ EnumType EnumType::createValidated(Manager &mgr, std::string name,
/* RTTI type registrations */
-const Rtti<Type> Type_T("Type");
-const Rtti<StringType> StringType_T("StringType", {&Type_T});
-const Rtti<IntType> IntType_T("IntType", {&Type_T});
-const Rtti<DoubleType> DoubleType_T("DoubleType", {&Type_T});
-const Rtti<BoolType> BoolType_T("BoolType", {&Type_T});
-const Rtti<EnumType> EnumType_T("EnumType", {&Type_T});
-const Rtti<StructType> StructType_T("StructType", {&Type_T});
+const Rtti<Type> Type_Rtti{"Type"};
+const Rtti<StringType> StringType_Rtti{"StringType", {&Type_Rtti}};
+const Rtti<IntType> IntType_Rtti{"IntType", {&Type_Rtti}};
+const Rtti<DoubleType> DoubleType_Rtti{"DoubleType", {&Type_Rtti}};
+const Rtti<BoolType> BoolType_Rtti{"BoolType", {&Type_Rtti}};
+const Rtti<EnumType> EnumType_Rtti{"EnumType", {&Type_Rtti}};
+const Rtti<StructType> StructType_Rtti{"StructType", {&Type_Rtti}};
}
}
diff --git a/test/core/model/DomainTest.cpp b/test/core/model/DomainTest.cpp
index 204a862..65954e7 100644
--- a/test/core/model/DomainTest.cpp
+++ b/test/core/model/DomainTest.cpp
@@ -28,7 +28,7 @@ namespace ousia {
namespace model {
void assert_path(std::vector<Rooted<Managed>> &result, size_t idx,
- const ManagedType &expected_type,
+ const RttiBase &expected_type,
std::vector<std::string> expected_path)
{
ASSERT_TRUE(result.size() > idx);
@@ -57,9 +57,9 @@ TEST(Domain, testDomainResolving)
std::vector<Rooted<Managed>> res =
domain->resolve(std::vector<std::string>{"book"});
// First we expect the book domain.
- assert_path(res, 0, DomainType, {"book"});
+ assert_path(res, 0, typeOf<Domain>(), {"book"});
// Then the book structure.
- assert_path(res, 1, StructuredClassType, {"book", "book"});
+ assert_path(res, 1, typeOf<StructuredClass>(), {"book", "book"});
ASSERT_EQ(2, res.size());
/*
@@ -67,7 +67,7 @@ TEST(Domain, testDomainResolving)
* StructuredClass should be returned.
*/
res = domain->resolve(std::vector<std::string>{"book", "book"});
- assert_path(res, 0, StructuredClassType, {"book", "book"});
+ assert_path(res, 0, typeOf<StructuredClass>(), {"book", "book"});
ASSERT_EQ(1, res.size());
/*
@@ -75,7 +75,7 @@ TEST(Domain, testDomainResolving)
*/
res = domain->resolve(std::vector<std::string>{"section"});
// TODO: Is that the path result we want?
- assert_path(res, 0, StructuredClassType, {"book", "section"});
+ assert_path(res, 0, typeOf<StructuredClass>(), {"book", "section"});
ASSERT_EQ(1, res.size());
/*
@@ -83,7 +83,7 @@ TEST(Domain, testDomainResolving)
* FieldDescriptor of the StructuredClass "book".
*/
res = domain->resolve(std::vector<std::string>{"book", "book", ""});
- assert_path(res, 0, FieldDescriptorType, {"book", "book", ""});
+ assert_path(res, 0, typeOf<FieldDescriptor>(), {"book", "book", ""});
ASSERT_EQ(1, res.size());
/*
@@ -91,7 +91,7 @@ TEST(Domain, testDomainResolving)
* but should be returned only once.
*/
res = domain->resolve("paragraph");
- assert_path(res, 0, StructuredClassType, {"book", "paragraph"});
+ assert_path(res, 0, typeOf<StructuredClass>(), {"book", "paragraph"});
ASSERT_EQ(1, res.size());
}
}