/* 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 Domain.hpp * * This header contains the class hierarchy of descriptor classes for domains. * Properly connected instances of these classes with a Domain node as root * describe a semantic Domain in a formal way. It specifies the allowed (tree) * structure of a document by means of StructuredClasses as well as the allowed * Annotations by means of AnnotationClasses. * * The Structure Description contained in the hierarchy of StructuredClasses is * equivalent to a context free grammar of a special form. We introduce the * terms "StructuredClass" and "FieldDescriptor". * On the top level you would start with a StructuredClass, say "book", which * in turn might contain two FieldDescriptors, one for the meta data of ones * book and one for the actual structure. Consider the following XML: * * \code{.xml} * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * \endcode * * Note that we define one field as the TREE (meaning the main or default * document structure) and one mearly as SUBTREE, relating to supporting * information. You are not allowed to define more than one field of type * "TREE". Accordingly for each StructuredClass in the main TREE there must be * at least one possible primitive child or one TREE field. Otherwise the * grammar would be nonterminal. For SUBTREE fields no children may define a * TREE field and at least one permitted child must exist, either primitive or * as another StructuredClass. * * The translation to context free grammars is as follows: * * \code{.txt} * BOOK := BOOK_TREE * BOOK_TREE := CHAPTER BOOK_TREE | PARAGRAPH BOOK_TREE | epsilon * CHAPTER := CHAPTER_TREE * CHAPTER_TREE := SECTION CHAPTER_TREE | PARAGRAPH CHAPTER_TREE | epsilon * SECTION :=
SECTION_TREE
* SECTION_TREE := SUBSECTION SECTION_TREE | PARAGRAPH SECTION_TREE | * epsilon * SUBSECTION := SUBSECTION_TREE * SUBSECTION_TREE := PARAGRAPH SUBSECTION_TREE | epsilon * PARAGRAPH := PARAGRAPH_CONTENT * PARAGRAPH_CONTENT := string * \endcode * * Note that this translation recurs to further nonterminals like SECTION but * necessarily produces one "book" terminal. Also note that, in principle, * this grammar translation allows for arbitrarily many children instances of * the proper StructuredClass. This can be regulated by the "cardinality" * property of a StructuredClass. * * It is possible to add further fields, like we would in the "headings" domain * to add titles to our structure. * * \code{.xml} * * * * * * * * * * * ... * * * * * * * \endcode * * This would change the context free grammar as follows: * * \code{.txt} * BOOK := HEADING BOOK_TREE * HEADING := PARAGRAPH * \endcode * * AnnotationClasses on the other hand do not specify a context free grammar. * They merely specify what kinds of Annotations are allowed within this domain * and which fields or attributes they have. Note that Annotations are allowed * to define structured children that manifest e.g. meta information of that * Annotation. An example for that would be the "comment" domain: * * \code{.xml} * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * \endcode * * Here we have comment annotations, which have a reply tree as sub structure. * * @author Benjamin Paaßen (bpaassen@techfak.uni-bielefeld.de) */ #ifndef _OUSIA_MODEL_DOMAIN_HPP_ #define _OUSIA_MODEL_DOMAIN_HPP_ #include #include #include "Node.hpp" #include "Typesystem.hpp" namespace ousia { // Forward declarations class Rtti; class Descriptor; class StructuredClass; class Domain; /** * As mentioned in the description above a FieldDescriptor specifies the * StructuredClasses that are allowed as children of a StructuredClass or * AnnotationClass. A field may also be primitive, which means that a proper * instance of the respective StructuredClass or AnnotationClass must provide * accordingly typed content without further descending in the Structure * Hierarchy. * * As an example consider the "paragraph" StructuredClass, which might allow * the actual text content. Here is the according XML: * * \code{.xml} * * * * * * * * * * \endcode * * Accordingly the primitiveType field of a FieldDescriptor may only be * defined if the type is set to "PRIMITIVE". If the type is something else * at least one child must be defined and the primitiveType remains in an * undefined state. */ class FieldDescriptor : public Node { friend Descriptor; public: /** * This enum class contains all possible FieldTypes, meaning either the * main structure beneath this Descritor (TREE), supporting structure * (SUBTREE) or a primitive terminal (PRIMITIVE). * * Note the following rules (which are also mentioned above): * 1.) There may be only one TREE field in a Descriptor. * 2.) Each TREE field must allow for at least one child, which in turn has * either a TREE field or a PRIMITIVE field. * 3.) SUBTREE fields may not allow for children with TREE fields. * 4.) SUBTREE fields must allow for at least one child with another SUBTREE * or PRIMITIVE field. */ enum class FieldType { TREE, SUBTREE, PRIMITIVE }; private: NodeVector children; FieldType fieldType; Owned primitiveType; bool optional; protected: bool doValidate(Logger &logger) const override; public: /** * This is the constructor for primitive fields. The type is automatically * set to "PRIMITIVE". * * @param mgr is the global Manager instance. * @param parent is a handle of the Descriptor node that has this * FieldDescriptor. * @param primitiveType is a handle to some Type in some Typesystem of which * one instance is allowed to fill this field. * @param name is the name of this field. * @param optional should be set to 'false' is this field needs to be * filled in order for an instance of the parent * Descriptor to be valid. */ FieldDescriptor(Manager &mgr, Handle parent, Handle primitiveType, std::string name = "", bool optional = false); /** * This is the constructor for non-primitive fields. You have to provide * children here later on. * * @param mgr is the global Manager instance. * @param parent is a handle of the Descriptor node that has this * FieldDescriptor. * @param fieldType is the FieldType of this FieldDescriptor, either * TREE for the main or default structure or SUBTREE * for supporting structures. * @param name is the name of this field. * @param optional should be set to 'false' is this field needs to be * filled in order for an instance of the parent * Descriptor to be valid. */ FieldDescriptor(Manager &mgr, Handle parent = nullptr, FieldType fieldType = FieldType::TREE, std::string name = "", bool optional = false); /** * Returns a const reference to the NodeVector of StructuredClasses whose * instances are allowed as children in the StructureTree of instances of * this field. * * @return a const reference to the NodeVector of StructuredClasses whose * instances are allowed as children in the StructureTree of instances of * this field. */ const NodeVector &getChildren() const { return children; } /** * Adds a StructuredClass whose instances shall be allowed as children in * the StructureTree of instances of this field. */ void addChild(Handle c) { invalidate(); children.push_back(c); } /** * Adds multiple StructuredClasses whose instances shall be allowed as * children in the StructureTree of instances of this field. */ void addChildren(const std::vector> &cs) { invalidate(); children.insert(children.end(), cs.begin(), cs.end()); } /** * Removes the given StructuredClass from the list of children of this * FieldDescriptor. * * @param c some StructuredClass that shan't be a child of this * FieldDescriptor anymore. * @return true if the FieldDescriptor contained this child and false if it * did not. */ bool removeChild(Handle c); /** * Returns the type of this field (not to be confused with the primitive * type of this field). * * @return the type of this field. */ FieldType getFieldType() const { return fieldType; } /** * Sets the type of this field (not to be confused with the primitive type * of this field). * * @param ft is the new type of this field. */ void setFieldType(const FieldType &ft) { invalidate(); fieldType = ft; } /** * Returns true if and only if the type of this field is PRIMITIVE. * * @return true if and only if the type of this field is PRIMITIVE. */ bool isPrimitive() const { return fieldType == FieldType::PRIMITIVE; } /** * Returns the primitive type of this field, which is only allowed to be * set if the type of this field is PRIMITIVE. * * @return the primitive type of this field. */ Rooted getPrimitiveType() const { return primitiveType; } /** * Sets the primitive type of this field, which is only allowed to be * set if the type of this field is PRIMITIVE. * * @param t is the new primitive type of this field- */ void setPrimitiveType(Handle t) { invalidate(); primitiveType = acquire(t); } /** * Returns true if and only if this field is optional. * * @return true if and only if this field is optional. */ bool isOptional() const { return optional; } /** * Specifies whether this field shall be optional. * * @param o should be true if and only if this field should be optional. */ void setOptional(bool o) { invalidate(); optional = std::move(o); } }; /** * This is a super class for StructuredClasses and AnnotationClasses and is, * in itself, not supposed to be instantiated. It defines that both, Annotations * and StructuredEntities, may have attributes and fields. For more information * on fields please have a look at the header documentation as well as the * documentation of the FieldDescriptor class. * * Attributes are primitive content stored in a key-value fashion. Therefore * the attribute specification of a descriptor is done by referencing an * appropriate StructType that contains all permitted keys and value types. * * In XML terms the difference between primitive fields and attributes can be * explained as the difference between node attributes and node children. * Consider the XML * * \code{.xml} * * value * * \endcode * * key="value" inside the A-node would be an attribute, while value * would be a primitive field. While equivalent in XML the semantics are * different: An attribute describes indeed attributes, features of one single * node whereas a primitive field describes the _content_ of a node. * */ class Descriptor : public Node { friend FieldDescriptor; private: Owned attributesDescriptor; NodeVector fieldDescriptors; bool continuePath(Handle target, std::vector> &path) const; protected: void doResolve(ResolutionState &state) override; bool doValidate(Logger &logger) const override; public: Descriptor(Manager &mgr, std::string name, Handle domain, Handle attributesDescriptor) : Node(mgr, std::move(name), domain), attributesDescriptor(acquire(attributesDescriptor)), fieldDescriptors(this) { } /** * Returns a reference to the StructType that specifies the attribute keys * as well as value domains for this Descriptor. * * @return a reference to the StructType that specifies the attribute keys * as well as value domains for this Descriptor. */ Rooted getAttributesDescriptor() const { return attributesDescriptor; } /** * Sets the StructType that specifies the attributes of this Descriptor. * * @param t some StructType. */ void setAttributesDescriptor(Handle t) { invalidate(); attributesDescriptor = acquire(t); } /** * Returns a const reference to the NodeVector of all FieldDescriptors of * this Descriptor. * * @return a const reference to the NodeVector of all FieldDescriptors of * this Descriptor. */ const NodeVector &getFieldDescriptors() const { return fieldDescriptors; } /** * Adds the given FieldDescriptor to this Descriptor. This also sets the * parent of the given FieldDescriptor if it is not set to this Descriptor * already and removes it from the old parent Descriptor. * * @param fd is a FieldDescriptor. */ void addFieldDescriptor(Handle fd); /** * Adds the given FieldDescriptors to this Descriptor. This also sets the * parent of each given FieldDescriptor if it is not set to this Descriptor * already and removes it from the old parent Descriptor. * * @param fds are FieldDescriptors. */ void addFieldDescriptors(const std::vector> &fds) { for (Handle fd : fds) { addFieldDescriptor(fd); } } /** * Copies a FieldDescriptor that belongs to another Descriptor to this * Descriptor. * * @param fd some FieldDescriptor belonging to another Descriptor. */ void copyFieldDescriptor(Handle fd); /** * Removes the given FieldDescriptor from this Descriptor. This also sets * the parent of the given FieldDescriptor to null. * * @param fd is a FieldDescriptor. * @return true if the FieldDescriptor was removed and false if this * Descriptor did not have the given FieldDescriptor as child. */ bool removeFieldDescriptor(Handle fd); /** * This creates a new primitive FieldDescriptor and adds it to this * Descriptor. * * @param primitiveType is a handle to some Type in some Typesystem of which * one instance is allowed to fill this field. * @param name is the name of this field. * @param optional should be set to 'false' is this field needs to be * filled in order for an instance of the parent * Descriptor to be valid. * * @return the newly created FieldDescriptor. */ Rooted createPrimitiveFieldDescriptor( Handle primitiveType, std::string name = "", bool optional = false); /** * This creates a new primitive FieldDescriptor and adds it to this * Descriptor. * * @param fieldType is the FieldType of this FieldDescriptor, either * TREE for the main or default structure or SUBTREE * for supporting structures. * @param name is the name of this field. * @param optional should be set to 'false' is this field needs to be * filled in order for an instance of the parent * Descriptor to be valid. * * @return the newly created FieldDescriptor. */ Rooted createFieldDescriptor( FieldDescriptor::FieldType fieldType = FieldDescriptor::FieldType::TREE, std::string name = "", bool optional = false); /** * This tries to construct the shortest possible path of this Descriptor * to the given child Descriptor. As an example consider the book domain * from above. * * First consider the call book->pathTo(chapter). This is an easy example: * Our path just contains a reference to the default field of book, because * a chapter may be directly added to the main field of book. * * Second consider the call book->pathTo(text). This is somewhat more * complicated, but it is still a valid request, because we can construct * the path: {book_main_field, paragraph, paragraph_main_field}. * This is only valid because paragraph is transparent. * * What about the call book->pathTo(section)? This will lead to an empty * return path (= invalid). We could, of course, in principle construct * a path between book and section (via chapter), but chapter is not * transparent. Therefore that path is not allowed. * * @param childDescriptor is a supposedly valid child Descriptor of this * Descriptor. * @return either a path of FieldDescriptors and * StructuredClasses between this Descriptor and * the input StructuredClass or an empty vector if * no such path can be constructed. * */ std::vector> pathTo( Handle childDescriptor) const; }; /* * TODO: We should discuss Cardinalities one more time. Is it smart to define * cardinalities independent of context? Should we not have at least have the * possibility to define it context-dependently? */ /** * This is the default cardinality. */ static Variant::cardinalityType createAny() { Variant::cardinalityType any; any.merge(Range::typeRangeFrom(0)); return std::move(any); } static const Variant AnyCardinality = createAny(); /** * A StructuredClass specifies nodes in the StructureTree of a document that * implements this domain. For more information on the StructureTree please * consult the Header documentation above. * * Note that a StructuredClass may "invade" an existing Domain description by * defining itself as a viable child in one existing field. Consider the * example of the "heading" domain from the header documentation again: * * \code{.xml} * * * * * * * * * * * ... * * * * * * * \endcode * * The "parent" construct allows to "invade" another domain. * * This does indeed interfere with an existing domain and one must carefully * craft such parent references to not create undesired side effects. However * they provide the most convenient mechanism to extend existing domains * without having to rewrite them. * * Another important factor is the 'transparent' flag. Transparent * StructureClasses may be implicitly constructed in the document graph. * If we go back to our example a user would (without transparency) have to * explicitly declare: * * \code{.xml} * *
* Text. *
*
* \endcode * * But in our mind the document * * \code{.xml} * *
* Text. *
*
* \endcode * * Is already sufficiently specific. We can infer that a paragraph should be * wrapped around "Text.". Therefore we set the 'transparent' flag of the * "paragraph" StructuredClass to true. Please note that such inferences * become increasingly complicated when children of transparent * StructuredClasses are allowed to be transparent as well. So use with care. * * Finally we allow StructuredClasses to inherit attributes of other * StructuredClasses. Inheritance also implies that instance of the inheriting * class can be used wherever an instance of the inherited class is allowed. * Inheritance therefore also goes for fields. TODO: What is the specification * for field inheritance? Is the child allowed to specify children at all? * Is that interpreted as overriding the parent fields or constructing a union? * What about the cardinality? */ class StructuredClass : public Descriptor { friend Domain; private: const Variant cardinality; Owned superclass; NodeVector subclasses; bool transparent; bool root; /** * Helper method for getFieldDescriptors. */ const void gatherFieldDescriptors( NodeVector ¤t, std::set &overriddenFields) const; protected: bool doValidate(Logger &logger) const override; public: /** * The constructor for a StructuredClass. * * @param mgr is the current Manager. * @param name is the name of the StructuredClass. * @param domain is the Domain this StructuredClass belongs * to. * @param cardinality specifies how often an element of this type * may occur at a specific point in the * StructureTree. For example: A document should * have at least one author. This is set to * * per default, meaning that any number of * of instances is valid, including zero. * @param attributesDescriptor is a StructType that specifies the attribute * keys as well as value domains for this * Descriptor. * @param superclass references a parent StructuredClass. Please * look for more information on inheritance in * the class documentation above. The default is * a null reference, meaning no super class. * The constructor automatically registers this * class as a subclass at the super class. * @param transparent specifies whether this StructuredClass is * transparent. For more information on * transparency please refer to the class * documentation above. The default is false. * @param root specifies whether this StructuredClass is * allowed to be at the root of a Document. */ StructuredClass(Manager &mgr, std::string name = "", Handle domain = nullptr, Variant cardinality = AnyCardinality, Handle attributesDescriptor = nullptr, Handle superclass = nullptr, bool transparent = false, bool root = false); /** * Returns the Cardinality of this StructuredClass (as a RangeSet). * * @return the Cardinality of this StructuredClass (as a RangeSet). */ const Variant &getCardinality() const { return cardinality; } /** * Returns the superclass of this StructuredClass. This is not the same as * the parents in the Structure Tree! * * @return the superclass of this StructuredClass. */ Rooted getSuperclass() const { return superclass; } /** * Sets the superclass of this StructuredClass. This is not the same as * the parents in the Structure Tree! * * This will also register this class as a subclass at the given superclass * and unregister it at the previous superclass. * * @parem sup some StructuredClass that shall be the new superclass of this * StructuredClass. */ void setSuperclass(Handle sup); /** * Returns true if this class is a subclass of the given class. It does not * return true if the other class is equal to the given class. * * @param c is another class that might or might not be a superclass of this * one * @return true if this class is a subclass of the given class. * */ bool isSubclassOf(Handle c) const; /** * Returns the StructuredClasses that are subclasses of this class. This * is the inverted version of isa, meaning: each class c that has a isa * relationship to this class is part of the returned vector. * * Note that the order of subclasses is not strictly defined. * * You are not allowed to add subclasses directly to the vector. When you * construct a new StructuredClass with a non-empty isa-handle it will * automatically register as subclass at the super class. * * @return the StructuredClasses that are subclasses of this class. */ const NodeVector &getSubclasses() const { return subclasses; } /** * Adds a subclass to this StructuredClass. This also calls setSuperclass * on the given subclass. * * @param sc is some StructuredClass. */ void addSubclass(Handle sc); /** * Removes a subclass from this StructuredClass. This also calls * setSuperclass(nullptr) on the given subclass. * * @param sc is some StructuredClass. */ void removeSubclass(Handle sc); /** * Returns a const reference to the NodeVector of all FieldDescriptors of * this StructuredClass. This does more than the getter for FieldDescriptor, * because in this method we gather the FieldDescriptors of all superclasses * as well that have not been overridden in child classes. * * @return a const reference to the NodeVector of all FieldDescriptors of * this StructuredClass. */ NodeVector getEffectiveFieldDescriptors() const; bool isTransparent() const { return transparent; } void setTransparent(bool t) { invalidate(); transparent = std::move(t); } bool hasRootPermission() const { return root; } void setRootPermission(bool r) { invalidate(); root = std::move(r); } }; /** * An AnnotationClass defines allowed Annotations. For more information on * Annotations please refer to the Document.hpp. * * This class has no special properties and is in essence just a Descriptor. */ class AnnotationClass : public Descriptor { friend Domain; public: /** * The constructor for a new AnnotationClass. Note that you have to add * the FieldDescriptors to it later on. * * @param mgr is the Manager instance. * @param name is a name for this AnnotationClass that will * be used for later references to this * AnnotationClass. * @param domain is the Domain this AnnotationClass belongs * to. * @param attributesDescriptor is a StructType that specifies the attribute * keys as well as value domains for this * Descriptor. */ AnnotationClass(Manager &mgr, std::string name, Handle domain, // TODO: What would be a wise default value for attributes? Handle attributesDescriptor = nullptr); }; /** * A Domain node specifies which StructuredClasses and which AnnotationClasses * are part of this domain. TODO: Do we want to be able to restrict Annotations * to certain Structures? */ class Domain : public Node { friend StructuredClass; friend AnnotationClass; private: NodeVector structuredClasses; NodeVector annotationClasses; // TODO: Is it wise to attach the type systems here? If not: What would be // a good alternative. NodeVector typesystems; protected: void doResolve(ResolutionState &state) override; bool doValidate(Logger &logger) const override; public: /** * The constructor for a new domain. Note that this is an empty Domain and * still has to be filled with StructuredClasses and AnnotationClasses. * * @param mgr is the Manager instance. * @param name is a name for this domain which will be used for later * references to this Domain. */ Domain(Manager &mgr, std::string name = "") : Node(mgr, std::move(name), nullptr), structuredClasses(this), annotationClasses(this), typesystems(this) { } /** * The constructor for a new domain. Note that this is an empty Domain and * still has to be filled with StructuredClasses and AnnotationClasses. * * @param mgr is the Manager instance. * @param sys is the SystemTypesystem instance. * @param name is a name for this domain which will be used for later * references to this Domain. */ Domain(Manager &mgr, Handle sys, std::string name = "") : Domain(mgr, std::move(name)) { includeTypesystem(sys); } /** * Creates a new Domain and returns it. * * @param mgr is the Manager instance. * @param name is a name for this domain which will be used for later * references to this Domain. */ static Rooted createEmptyDomain(Manager &mgr, std::string name) { return Rooted{new Domain(mgr, std::move(name))}; } /** * Returns a const reference to the NodeVector of StructuredClasses that are * part of this Domain. * * @return a const reference to the NodeVector of StructuredClasses that are * part of this Domain. */ const NodeVector &getStructureClasses() const { return structuredClasses; } /** * Adds a StructuredClass to this domain. This also sets the parent of the * given StructuredClass if it is not set to this Domain already and removes * it from the old Domain. * * @param s is some StructuredClass. */ void addStructuredClass(Handle s); /** * Removes a StructuredClass from this domain. This also sets the parent of * the given StructuredClass to null. * * @param s is some StructuredClass. * @return true if the given StructuredClass was removed and false if this * Domain did not have the given StructuredClass as child. */ bool removeStructuredClass(Handle s); /** * This creates a new StructuredClass and appends it to this Domain. * * @param name is the name of the StructuredClass. * @param cardinality specifies how often an element of this type * may occur at a specific point in the * StructureTree. For example: A document should * have at least one author. This is set to * * per default, meaning that any number of * of instances is valid, including zero. * @param attributesDescriptor is a StructType that specifies the attribute * keys as well as value domains for this * Descriptor. * @param superclass references a parent StructuredClass. Please * look for more information on inheritance in * the class documentation above. The default is * a null reference, meaning no super class. * The constructor automatically registers this * class as a subclass at the super class. * @param transparent specifies whether this StructuredClass is * transparent. For more information on * transparency please refer to the class * documentation above. The default is false. * @param root specifies whether this StructuredClass is * allowed to be at the root of a Document. * * @return the newly created StructuredClass. */ Rooted createStructuredClass( std::string name, Variant cardinality = AnyCardinality, Handle attributesDescriptor = nullptr, Handle superclass = nullptr, bool transparent = false, bool root = false); /** * Returns a const reference to the NodeVector of AnnotationClasses that are * part of this Domain. * * @return a const reference to the NodeVector of AnnotationClasses that are * part of this Domain. */ const NodeVector &getAnnotationClasses() const { return annotationClasses; } /** * Adds an AnnotationClass to this domain. This also sets the parent of the * given AnnotationClass if it is not set to this Domain already and removes * it from the old Domain. * * @param a is some AnnotationClass. */ void addAnnotationClass(Handle a); /** * Removes a AnnotationClass from this domain. This also sets the parent of * the given AnnotationClass to null. * * @param a is some AnnotationClass. * @return true if the given AnnotationClass was removed and false if this * Domain did not have the given AnnotationClass as child. */ bool removeAnnotationClass(Handle a); /** * This creates a new AnnotationClass and appends it to this Domain. * * @param name is a name for this AnnotationClass that will * be used for later references to this * AnnotationClass. * @param attributesDescriptor is a StructType that specifies the attribute * keys as well as value domains for this * Descriptor. */ Rooted createAnnotationClass( std::string name, Handle attributesDescriptor = nullptr); /** * Returns a const reference to the NodeVector of TypeSystems that are * references in this Domain. * * @return a const reference to the NodeVector of TypeSystems that are * references in this Domain. */ const NodeVector &getTypesystems() const { return typesystems; } /** * Adds a Typesystem reference to this Domain. */ void includeTypesystem(Handle t) { typesystems.push_back(t); } /** * Adds multiple Typesystem references to this Domain. */ void includeTypesystems(const std::vector> &ts) { typesystems.insert(typesystems.end(), ts.begin(), ts.end()); } }; namespace RttiTypes { extern const Rtti FieldDescriptor; extern const Rtti Descriptor; extern const Rtti StructuredClass; extern const Rtti AnnotationClass; extern const Rtti Domain; } } #endif /* _OUSIA_MODEL_DOMAIN_HPP_ */