diff options
Diffstat (limited to 'src/core/model/Domain.hpp')
-rw-r--r-- | src/core/model/Domain.hpp | 1203 |
1 files changed, 0 insertions, 1203 deletions
diff --git a/src/core/model/Domain.hpp b/src/core/model/Domain.hpp deleted file mode 100644 index 7e10d91..0000000 --- a/src/core/model/Domain.hpp +++ /dev/null @@ -1,1203 +0,0 @@ -/* - 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 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} - * <domain name="book"> - * <struct name="book" cardinality="1" isRoot="true"> - * <field> - * <childRef ref="book.chapter"/> - * <childRef ref="book.paragraph"/> - * </field> - * </struct> - * <struct name="chapter"> - * <field> - * <childRef ref="book.section"/> - * <childRef ref="book.paragraph"/> - * </field> - * </struct> - * <struct name="section"> - * <field> - * <childRef ref="book.subsection"/> - * <childRef ref="book.paragraph"/> - * </field> - * </struct> - * <struct name="subsection"> - * <field> - * <childRef ref="book.paragraph"/> - * </field> - * </struct> - * <struct name="paragraph" transparent="true"> - * <field> - * <childRef ref="book.text"/> - * </field> - * </struct> - * <struct name="text" transparent="true"> - * <primitive type="string"/> - * </struct> - * </domain> - * \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". - * - * The translation to a context free grammar is as follows: - * - * \code{.txt} - * BOOK := <book> BOOK_TREE </book> - * BOOK_TREE := CHAPTER BOOK_TREE | PARAGRAPH BOOK_TREE | epsilon - * CHAPTER := <chapter> CHAPTER_TREE </chapter> - * CHAPTER_TREE := SECTION CHAPTER_TREE | PARAGRAPH CHAPTER_TREE | epsilon - * SECTION := <section> SECTION_TREE </section> - * SECTION_TREE := SUBSECTION SECTION_TREE | PARAGRAPH SECTION_TREE | - * epsilon - * SUBSECTION := <subsection> SUBSECTION_TREE </subsection> - * SUBSECTION_TREE := PARAGRAPH SUBSECTION_TREE | epsilon - * PARAGRAPH := <paragraph> PARAGRAPH_CONTENT </paragraph> - * 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} - * <domain name="headings"> - * <import rel="domain" src="./book_domain.osxml"/> - * <struct name="heading" cardinality="1" transparent="true"> - * <parentRef ref="book.book"> - * <field name="heading" isSubtree="true" optional="true"/> - * </parentRef> - * ... - * <fieldRef name="book.paragraph."> - * </struct> - * </domain> - * \endcode - * - * This would change the context free grammar as follows: - * - * \code{.txt} - * BOOK := <book> HEADING BOOK_TREE </book> - * HEADING := <heading> PARAGRAPH </heading> - * \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} - * <domain name="comments"> - * <import rel="domain" src="./book_domain.osxml"/> - * - * <annotation name="comment"> - * <field name="content" isSubtree="true"> - * <childRef ref="book.paragraph"/> - * </field> - * <field name="replies" isSubtree="true"> - * <childRef ref="reply"/> - * </field> - * </annotation> - * - * <struct name="comment"> - * <field name="content"> - * <childRef ref="book.paragraph"/> - * </field> - * <field name="replies" isSubtree="true"> - * <childRef ref="reply"/> - * </field> - * <parentRef ref="book.paragraph"> - * <fieldRef ref="$default"/> - * </parentRef> - * </struct> - * <struct name="reply"> - * <field name="content" isSubtree="true"> - * <childRef ref="book.paragraph"/> - * </field> - * <field name="replies" isSubtree="true"> - * <childRef ref="reply"/> - * </field> - * </struct> - * </domain> - * \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 <core/managed/ManagedContainer.hpp> -#include <core/RangeSet.hpp> - -#include "Node.hpp" -#include "RootNode.hpp" -#include "Typesystem.hpp" - -namespace ousia { - -// Forward declarations -class Rtti; -class Descriptor; -class StructuredClass; -class Domain; - -/** - * Magic field name used to identify the default field. The default field is - * either the tree field or the only subtree field. - */ -static const std::string DEFAULT_FIELD_NAME = "$default"; - -/** - * 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 "text" StructuredClass, which might allow - * the actual text content. Here is the according XML: - * - * \code{.xml} - * <struct name="text" transparent="true"> - * <primitive type="string"/> - * </struct> - * \endcode - * - */ -class FieldDescriptor : public Node { - friend Descriptor; - -public: - /** - * This enum class contains all possible FieldTypes, meaning either the - * main structure beneath this Descriptor (TREE) or supporting structure - * (SUBTREE) - * - * Note that there may be only one TREE field in a descriptor. - */ - enum class FieldType { TREE, SUBTREE }; - -private: - NodeVector<StructuredClass> children; - FieldType fieldType; - Owned<Type> primitiveType; - bool optional; - bool primitive; - -protected: - bool doValidate(Logger &logger) const override; - -public: - /** - * This is the constructor for primitive fields. - * - * @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<Type> primitiveType, - Handle<Descriptor> parent, - FieldType fieldType = FieldType::TREE, - 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<Descriptor> 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<StructuredClass> &getChildren() const { return children; } - - /** - * Returns all StructuredClasses whose instances are allowed as children in - * the Structure Tree of instances of this field including subclasses of - * children, which are allowed directly. - * - * @return all StructuredClasses whose instances are allowed as children in - * the Structure Tree of instances of this field including subclasses of - * children, which are allowed directly. - */ - NodeVector<StructuredClass> getChildrenWithSubclasses() const; - - /** - * Adds a StructuredClass whose instances shall be allowed as children in - * the StructureTree of instances of this field. - */ - void addChild(Handle<StructuredClass> 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<Handle<StructuredClass>> &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<StructuredClass> 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 if this field is primitive. - * - * @return true if and only if this field is primitive. - */ - bool isPrimitive() const { return 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<Type> 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<Type> 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 tries to construct the shortest possible path of this Descriptor - * to the given child Descriptor. Note that this method has the problem that - * an empty return path does NOT strictly imply that no such path could - * be constructed: We also return an empty vector if the given - * Descriptor is a direct child. Therefore we also return a bool value - * indicating that the path is valid or not. - * - * Implicitly this does a breadth-first search on the graph of - * StructuredClasses that are transparent. It also takes care of cycles. - * - * @param childDescriptor is a supposedly valid child Descriptor of this - * Descriptor. - * @return a tuple containing a path of FieldDescriptors and - * StructuredClasses between this Descriptor and the - * input Descriptor and a bool value indicating if - * the construction was successful. - * - */ - std::pair<NodeVector<Node>, bool> pathTo( - Handle<StructuredClass> childDescriptor, Logger &logger) const; - /** - * This tries to construct the shortest possible path of this Descriptor - * to the given FieldDescriptor. Note that this method has the problem that - * an empty return path does NOT strictly imply that no such path could - * be constructed: We also return an empty vector if the given - * FieldDescriptor is a direct child. Therefore we also return a bool value - * indicating that the path is valid or not. - * - * - * Implicitly this does a breadth-first search on the graph of - * StructuredClasses that are transparent. It also takes care of cycles. - * - * @param field is a FieldDescriptor that may be allowed as child of this - * Descriptor. - * @return a path of FieldDescriptors and StructuredClasses between - * this Descriptor and the input FieldDescriptor or an empty - * vector if no such path could be constructed. - */ - NodeVector<Node> pathTo(Handle<FieldDescriptor> field, - Logger &logger) const; - - /** - * Returns a vector of all TREE fields that are allowed as structure tree - * children of an instance of this Descriptor. This also makes use of - * transparency. - * The list is sorted by the number of transparent elements that have to be - * constructed to arrive at the respective FieldDescriptor. - * - * @return a vector of all TREE fields that are allowed as structure tree - * children of an instance of this Descriptor. - */ - NodeVector<FieldDescriptor> getDefaultFields() const; -}; - -/** - * 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} - * <A key="value"> - * <key>value</key> - * </A> - * \endcode - * - * key="value" inside the A-node would be an attribute, while <key>value</key> - * 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<StructType> attributesDescriptor; - NodeVector<FieldDescriptor> fieldDescriptors; - - bool addAndSortFieldDescriptor(Handle<FieldDescriptor> fd, Logger &logger); - -protected: - void doResolve(ResolutionState &state) override; - - bool doValidate(Logger &logger) const override; - -public: - Descriptor(Manager &mgr, std::string name, Handle<Domain> domain) - : Node(mgr, std::move(name), domain), - attributesDescriptor(acquire(new StructType(mgr, "", nullptr))), - 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<StructType> getAttributesDescriptor() const - { - return attributesDescriptor; - } - - /** - * Returns the NodeVector of all FieldDescriptors of this Descriptor. - * - * @return the NodeVector of all FieldDescriptors of this Descriptor. - */ - virtual NodeVector<FieldDescriptor> getFieldDescriptors() const - { - return fieldDescriptors; - } - - /** - * Returns the index of the FieldDescriptor with the given name or -1 if no - * such FieldDescriptor was found. - * - * @param name the name of a FieldDescriptor. - - * @return the index of the FieldDescriptor with the given name or -1 if - * no such FieldDescriptor was found. - */ - ssize_t getFieldDescriptorIndex( - const std::string &name = DEFAULT_FIELD_NAME) const; - /** - * Returns the index of the given FieldDescriptor or -1 of the given - * FieldDescriptor is not registered at this Descriptor. - * - * @param fd a FieldDescriptor. - - * @return the index of the given FieldDescriptor or -1 of the given - * FieldDescriptor is not registered at this Descriptor. - */ - ssize_t getFieldDescriptorIndex(Handle<FieldDescriptor> fd) const; - /** - * Returns the FieldDescriptor with the given name. - * - * @param name the name of a FieldDescriptor. - - * @return the FieldDescriptor with the given name or a nullptr if no - * such FieldDescriptor was found. - */ - Rooted<FieldDescriptor> getFieldDescriptor( - const std::string &name = DEFAULT_FIELD_NAME) const; - - /** - * This returns true if this Descriptor has a FieldDescriptor with the - * given name. - * - * @param name the name of a FieldDescriptor. - - * @return true if this Descriptor has a FieldDescriptor with the given - * name - */ - bool hasField(const std::string &fieldName = DEFAULT_FIELD_NAME) const - { - return getFieldDescriptorIndex(fieldName) != -1; - } - - /** - * Adds the given FieldDescriptor to this Descriptor. This also sets the - * parent of the given FieldDescriptor if it is not set yet. - * - * @param fd is a FieldDescriptor. - * @return returns true if the given FieldDescriptor was not added at the - * end one place before because a TREE field already existed and - * the TREE field has to be at the end. - */ - bool addFieldDescriptor(Handle<FieldDescriptor> fd, Logger &logger); - - /** - * 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. - * @return returns true if the given FieldDescriptor was not added at the - * end one place before because a TREE field already existed and - * the TREE field has to be at the end. - */ - bool moveFieldDescriptor(Handle<FieldDescriptor> fd, Logger &logger); - - /** - * Copies a FieldDescriptor that belongs to another Descriptor to this - * Descriptor. - * - * @param fd some FieldDescriptor belonging to another Descriptor. - * @return returns true if the given FieldDescriptor was not added at the - * end one place before because a TREE field already existed and - * the TREE field has to be at the end. - */ - bool copyFieldDescriptor(Handle<FieldDescriptor> fd, Logger &logger); - - /** - * 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<FieldDescriptor> 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 and a bool - * indicating whether the order of FieldDescriptors had - * to be changed for the TREE field to be in the last - * spot. - */ - std::pair<Rooted<FieldDescriptor>, bool> createPrimitiveFieldDescriptor( - Handle<Type> primitiveType, Logger &logger, - FieldDescriptor::FieldType fieldType = FieldDescriptor::FieldType::TREE, - 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 and a bool - * indicating whether the order of FieldDescriptors had - * to be changed for the TREE field to be in the last - * spot. - */ - std::pair<Rooted<FieldDescriptor>, bool> createFieldDescriptor( - Logger &logger, - 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. - * - * Implicitly this does a breadth-first search on the graph of - * StructuredClasses that are transparent. It also takes care of cycles. - * - * @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. - * - */ - NodeVector<Node> pathTo(Handle<StructuredClass> childDescriptor, - Logger &logger) const; - /** - * This tries to construct the shortest possible path of this Descriptor - * to the given FieldDescriptor. Note that this method has the problem that - * an empty return path does NOT strictly imply that no such path could - * be constructed: We also return an empty vector if the given - * FieldDescriptor is a direct child. Therefore we also return a bool value - * indicating that the path is valid or not. - * - * - * Implicitly this does a breadth-first search on the graph of - * StructuredClasses that are transparent. It also takes care of cycles. - * - * @param field is a FieldDescriptor that may be allowed as child of this - * Descriptor. - * @return returns a tuple containing a path of FieldDescriptors and - * StructuredClasses between this Descriptor and the input - * FieldDescriptor and a bool value indicating if the - * construction was successful. - */ - std::pair<NodeVector<Node>, bool> pathTo(Handle<FieldDescriptor> field, - Logger &logger) const; - - /** - * Returns a vector of all TREE fields that are allowed as structure tree - * children of an instance of this Descriptor. This also makes use of - * transparency. - * The list is sorted by the number of transparent elements that have to be - * constructed to arrive at the respective FieldDescriptor. - * - * @return a vector of all TREE fields that are allowed as structure tree - * children of an instance of this Descriptor. - */ - NodeVector<FieldDescriptor> getDefaultFields() const; - - /** - * Returns a vector of all StructuredClasses that are allowed as children - * of an instance of this Descriptor in the structure tree. This also makes - * use of transparency. - * The list is sorted by the number of transparent elements that have to be - * constructed to arrive at the respective FieldDescriptor. - * - * @return a vector of all StructuredClasses that are allowed as children - * of an instance of this Descriptor in the structure tree. - */ - NodeVector<StructuredClass> getPermittedChildren() 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? - */ - -/** - * 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} - * <domain name="headings"> - * <head> - * <import rel="domain" src="book.oxm"/> - * </head> - * <structs> - * <struct name="heading" cardinality="0-1" transparent="true"> - * <parents> - * <parent name="book.book"> - * <field name="heading" type="SUBTREE"/> - * </parent> - * ... - * </parents> - * <fields> - * <fieldRef name="book.paragraph."> - * </fields> - * </structs> - * </domain> - * \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} - * <book> - * <section> - * <paragraph>Text.</paragraph> - * </section> - * </book> - * \endcode - * - * But in our mind the document - * - * \code{.xml} - * <book> - * <section> - * Text. - * </section> - * </book> - * \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. - */ -class StructuredClass : public Descriptor { - friend Domain; - -private: - const Variant cardinality; - Owned<StructuredClass> superclass; - NodeVector<StructuredClass> subclasses; - bool transparent; - bool root; - - /** - * Helper method for getFieldDescriptors. - */ - Rooted<FieldDescriptor> gatherFieldDescriptors( - NodeVector<FieldDescriptor> ¤t, - std::unordered_set<const StructuredClass *> &visited, - std::set<std::string> &overriddenFields, bool hasTREE) 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 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> domain = nullptr, - Variant cardinality = Cardinality::any(), - Handle<StructuredClass> 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<StructuredClass> 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. - * - * It will also set the parent for this Descriptors AttributesDescriptor. - * - * @param sup some StructuredClass that shall be the new superclass of - * this StructuredClass. - * @param logger is some logger. Errors during setting the parent for this - * Descriptors AttributesDescriptor will be written into this - * logger. - */ - void setSuperclass(Handle<StructuredClass> sup, Logger &logger); - - /** - * 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<StructuredClass> 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<StructuredClass> &getSubclasses() const - { - return subclasses; - } - - /** - * Adds a subclass to this StructuredClass. This also calls setSuperclass - * on the given subclass. - * - * @param sc is some StructuredClass. - * @param logger is some logger. Errors during setting the parent for the - * new subclasses AttributesDescriptor will be written into - * this logger. - */ - void addSubclass(Handle<StructuredClass> sc, Logger &logger); - - /** - * Removes a subclass from this StructuredClass. This also calls - * setSuperclass(nullptr) on the given subclass. - * - * @param sc is some StructuredClass. - * @param logger is some logger. Errors during setting the parent for the - * removed subclasses AttributesDescriptor will be written - * into this logger. - */ - void removeSubclass(Handle<StructuredClass> sc, Logger &logger); - - /** - * Returns a NodeVector of all FieldDescriptors of - * this StructuredClass. This also merges the FieldDescriptors directly - * belonging to this StructuredClass with all FieldDescritptors of its - * Superclass (and so on recurvively). The order of field descriptors is - * as follows: - * 1.) non-overridden SUBTREE FieldDescriptors of super classes. - * 2.) SUBTREE FieldDescriptors of this class. - * 3.) TREE FieldDescriptor (either inherited from super class or direct) - * - * @return a NodeVector of all FieldDescriptors of this StructuredClass. - */ - NodeVector<FieldDescriptor> getFieldDescriptors() const override; - - 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. - */ - AnnotationClass(Manager &mgr, std::string name, Handle<Domain> domain); -}; - -/** - * 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 RootNode { - friend StructuredClass; - friend AnnotationClass; - -private: - NodeVector<StructuredClass> structuredClasses; - NodeVector<AnnotationClass> annotationClasses; - NodeVector<Typesystem> typesystems; - NodeVector<Domain> domains; - -protected: - void doResolve(ResolutionState &state) override; - bool doValidate(Logger &logger) const override; - void doReference(Handle<Node> node) override; - RttiSet doGetReferenceTypes() 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 = "") - : RootNode(mgr, std::move(name), nullptr), - structuredClasses(this), - annotationClasses(this), - typesystems(this), - domains(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<SystemTypesystem> sys, std::string name = "") - : Domain(mgr, std::move(name)) - { - referenceTypesystem(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<Domain> createEmptyDomain(Manager &mgr, std::string name) - { - return Rooted<Domain>{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<StructuredClass> &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<StructuredClass> 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<StructuredClass> 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 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<StructuredClass> createStructuredClass( - std::string name, Variant cardinality = Cardinality::any(), - Handle<StructuredClass> 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<AnnotationClass> &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<AnnotationClass> 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<AnnotationClass> 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. - */ - Rooted<AnnotationClass> createAnnotationClass(std::string name); - - /** - * 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<Typesystem> &getTypesystems() const { return typesystems; } - - /** - * Adds a Typesystem reference to this Domain. - */ - void referenceTypesystem(Handle<Typesystem> t) { typesystems.push_back(t); } - - /** - * Adds multiple Typesystem references to this Domain. - */ - void referenceTypesystems(const std::vector<Handle<Typesystem>> &ts) - { - typesystems.insert(typesystems.end(), ts.begin(), ts.end()); - } - - /** - * Adds a Domain reference to this Domain. - */ - void referenceDomain(Handle<Domain> d) { domains.push_back(d); } - - /** - * Adds multiple Domain references to this Domain. - */ - void referenceDomains(const std::vector<Handle<Domain>> &ds) - { - domains.insert(domains.end(), ds.begin(), ds.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_ */ |