From 5eca67b6cab7031d8203b1403ba5cddaef833e76 Mon Sep 17 00:00:00 2001 From: Benjamin Paassen Date: Sun, 8 Feb 2015 19:37:51 +0100 Subject: restructured the FieldDescriptor mechanism. --- src/core/model/Document.cpp | 161 +++++++++++++++++----------------------- src/core/model/Document.hpp | 58 +++++++-------- src/core/model/Domain.cpp | 37 ++++++--- src/core/model/Domain.hpp | 64 +++++++++++----- src/plugins/html/DemoOutput.cpp | 18 ++--- src/plugins/xml/XmlParser.cpp | 4 +- 6 files changed, 181 insertions(+), 161 deletions(-) (limited to 'src') diff --git a/src/core/model/Document.cpp b/src/core/model/Document.cpp index de73bb8..4579383 100644 --- a/src/core/model/Document.cpp +++ b/src/core/model/Document.cpp @@ -28,53 +28,6 @@ namespace ousia { /* Class DocumentEntity */ -int DocumentEntity::getFieldDescriptorIndex(const std::string &fieldName, - bool enforce) const -{ - const NodeVector &fds = descriptor->getFieldDescriptors(); - unsigned int f = 0; - - // otherwise we return the FieldDescriptor with the correct name (if - // such a descriptor exists). - for (auto &fd : fds) { - if (fd->getName() == fieldName) { - return f; - } - f++; - } - - if (enforce) { - throw OusiaException(std::string("\"") + descriptor->getName() + - "\" has no field with name \"" + fieldName + "\""); - } else { - return -1; - } -} - -int DocumentEntity::getFieldDescriptorIndex( - Handle fieldDescriptor, bool enforce) const -{ - if (fieldDescriptor.isNull()) { - throw OusiaException("The given FieldDescriptor handle is null!"); - } - const NodeVector &fds = descriptor->getFieldDescriptors(); - int f = 0; - for (auto &fd : fds) { - if (fd->getName() == fieldDescriptor->getName() && - fd->getFieldType() == fieldDescriptor->getFieldType()) { - return f; - } - f++; - } - if (enforce) { - throw OusiaException(std::string("\"") + descriptor->getName() + - "\" has no field with name \"" + - fieldDescriptor->getName() + "\""); - } else { - return -1; - } -} - void DocumentEntity::invalidateSubInstance() { if (subInst->isa(&RttiTypes::StructuredEntity)) { @@ -105,18 +58,10 @@ void DocumentEntity::setDescriptor(Handle d) } invalidateSubInstance(); descriptor = subInst->acquire(d); - // get the effective field descriptors in the descriptor. - NodeVector fieldDescs; - if (descriptor->isa(&RttiTypes::StructuredClass)) { - fieldDescs = - descriptor.cast()->getEffectiveFieldDescriptors(); - } else { - fieldDescs = descriptor->getFieldDescriptors(); - } // clear the fields vector. fields.clear(); // fill it again. - for (size_t f = 0; f < fieldDescs.size(); f++) { + for (size_t f = 0; f < descriptor->getFieldDescriptors().size(); f++) { fields.push_back(NodeVector(subInst)); } } @@ -148,13 +93,7 @@ bool DocumentEntity::doValidate(Logger &logger) const * gather all fields of superclasses as well, that have not been * overridden in the subclasses. */ - NodeVector fieldDescs; - if (descriptor->isa(&RttiTypes::StructuredClass)) { - fieldDescs = - descriptor.cast()->getEffectiveFieldDescriptors(); - } else { - fieldDescs = descriptor->getFieldDescriptors(); - } + NodeVector fieldDescs = descriptor->getFieldDescriptors(); // iterate over every field for (unsigned int f = 0; f < fields.size(); f++) { // we have a special check for primitive fields. @@ -332,6 +271,43 @@ void DocumentEntity::setAttributes(const Variant &a) attributes = a; } +static int enforceGetFieldDescriptorIndex(Handle desc, + const std::string &fieldName) +{ + int idx = desc->getFieldDescriptorIndex(fieldName); + if (idx == -1) { + throw OusiaException( + std::string("Descriptor \"") + desc->getName() + + "\" has no field with the name \"" + fieldName + "\""); + } + return idx; +} + +static int enforceGetFieldDescriptorIndex( + Handle desc, Handle fieldDescriptor) +{ + int idx = desc->getFieldDescriptorIndex(fieldDescriptor); + if (idx == -1) { + throw OusiaException(std::string("Descriptor \"") + + desc->getName() + + "\" does not reference the given field \"" + + fieldDescriptor->getName() + "\""); + } + return idx; +} + +const NodeVector &DocumentEntity::getField( + const std::string &fieldName) const +{ + return fields[enforceGetFieldDescriptorIndex(descriptor, fieldName)]; +} + +const NodeVector &DocumentEntity::getField( + Handle fieldDescriptor) const +{ + return fields[enforceGetFieldDescriptorIndex(descriptor, fieldDescriptor)]; +} + void DocumentEntity::addStructureNode(Handle s, const int &i) { // only add the new node if we don't have it already. @@ -354,62 +330,63 @@ void DocumentEntity::addStructureNode(Handle s, const int &i) } } -bool DocumentEntity::removeStructureNodeFromField(Handle s, - const int &i) +void DocumentEntity::addStructureNode(Handle s, + Handle fieldDescriptor) { - auto it = fields[i].find(s); - if (it != fields[i].end()) { - invalidateSubInstance(); - fields[i].erase(it); - s->setParent(nullptr); - return true; + addStructureNode( + s, enforceGetFieldDescriptorIndex(descriptor, fieldDescriptor)); +} + +void DocumentEntity::addStructureNodes( + const std::vector> &ss, + Handle fieldDescriptor) +{ + const int i = enforceGetFieldDescriptorIndex(descriptor, fieldDescriptor); + for (Handle s : ss) { + addStructureNode(s, i); } - return false; } void DocumentEntity::addStructureNode(Handle s, const std::string &fieldName) { - addStructureNode(s, getFieldDescriptorIndex(fieldName, true)); + addStructureNode(s, enforceGetFieldDescriptorIndex(descriptor, fieldName)); } void DocumentEntity::addStructureNodes( const std::vector> &ss, const std::string &fieldName) { - const int i = getFieldDescriptorIndex(fieldName, true); + const int idx = enforceGetFieldDescriptorIndex(descriptor, fieldName); for (Handle s : ss) { - addStructureNode(s, i); + addStructureNode(s, idx); } } bool DocumentEntity::removeStructureNodeFromField(Handle s, - const std::string &fieldName) -{ - return removeStructureNodeFromField( - s, getFieldDescriptorIndex(fieldName, true)); -} - -void DocumentEntity::addStructureNode(Handle s, - Handle fieldDescriptor) + const int &i) { - addStructureNode(s, getFieldDescriptorIndex(fieldDescriptor, true)); + auto it = fields[i].find(s); + if (it != fields[i].end()) { + invalidateSubInstance(); + fields[i].erase(it); + s->setParent(nullptr); + return true; + } + return false; } -void DocumentEntity::addStructureNodes( - const std::vector> &ss, - Handle fieldDescriptor) +bool DocumentEntity::removeStructureNodeFromField(Handle s, + const std::string &fieldName) { - const int i = getFieldDescriptorIndex(fieldDescriptor, true); - for (Handle s : ss) { - addStructureNode(s, i); - } + return removeStructureNodeFromField( + s, enforceGetFieldDescriptorIndex(descriptor, fieldName)); } bool DocumentEntity::removeStructureNodeFromField( Handle s, Handle fieldDescriptor) { return removeStructureNodeFromField( - s, getFieldDescriptorIndex(fieldDescriptor, true)); + s, enforceGetFieldDescriptorIndex(descriptor, fieldDescriptor)); } bool DocumentEntity::removeStructureNode(Handle s) diff --git a/src/core/model/Document.hpp b/src/core/model/Document.hpp index 4be3494..b41393e 100644 --- a/src/core/model/Document.hpp +++ b/src/core/model/Document.hpp @@ -153,18 +153,8 @@ private: Variant attributes; std::vector> fields; - int getFieldDescriptorIndex(const std::string &fieldName, - bool enforce) const; - - int getFieldDescriptorIndex(Handle fieldDescriptor, - bool enforce) const; - void invalidateSubInstance(); - void addStructureNode(Handle s, const int &i); - - bool removeStructureNodeFromField(Handle s, const int &i); - protected: bool doValidate(Logger &logger) const; @@ -217,19 +207,6 @@ public: */ void setAttributes(const Variant &a); - /** - * This returns true if there is a FieldDescriptor in the Descriptor for - * this DocumentEntity which has the given name. - * - * @param fieldName is the name of a field as specified in the - * FieldDescriptor in the Domain description. - * @return true if this FieldDescriptor exists. - */ - bool hasField(const std::string &fieldName = DEFAULT_FIELD_NAME) const - { - return getFieldDescriptorIndex(fieldName, false) != -1; - } - /** * This returns the vector of entities containing all members of the field * with the given name. @@ -241,10 +218,7 @@ public: * @return a NodeVector of all StructuredEntities in that field. */ const NodeVector &getField( - const std::string &fieldName = DEFAULT_FIELD_NAME) const - { - return fields[getFieldDescriptorIndex(fieldName, true)]; - } + const std::string &fieldName = DEFAULT_FIELD_NAME) const; /** * This returns the vector of entities containing all members of the field @@ -259,11 +233,20 @@ public: * field. */ const NodeVector &getField( - Handle fieldDescriptor) const - { - return fields[getFieldDescriptorIndex(fieldDescriptor, true)]; - } + Handle fieldDescriptor) const; + /** + * This adds a StructureNode to the field with the given index. + * + * This method also changes the parent of the newly added StructureNode if + * it is not set to this DocumentEntity already and removes it from the + * old parent. + * + * @param s is the StructureNode that shall be added. + * @param fieldIdx is the index of a field as specified in the + * FieldDescriptor in the Domain description. + */ + void addStructureNode(Handle s, const int &fieldIdx); /** * This adds a StructureNode to the field with the given name. * @@ -295,6 +278,19 @@ public: */ void addStructureNodes(const std::vector> &ss, const std::string &fieldName = DEFAULT_FIELD_NAME); + /** + * This removes a StructureNode from the field with the given index. + * + * This method also changes the parent of the removed StructureNode to null. + * + * @param s is the StructureNode that shall be removed. + * @param fieldIdx is the index of a field as specified in the + * FieldDescriptor in the Domain description. + * @return true if this StructureNode was a child here and false if + * if was not found. + */ + bool removeStructureNodeFromField(Handle s, + const int &fieldIdx); /** * This removes a StructureNode from the field with the given name. * diff --git a/src/core/model/Domain.cpp b/src/core/model/Domain.cpp index 55f05b3..f45bd27 100644 --- a/src/core/model/Domain.cpp +++ b/src/core/model/Domain.cpp @@ -179,13 +179,7 @@ bool Descriptor::continuePath(Handle target, std::vector> optimum; // use recursive depth-first search from the top to reach the given child // get the list of effective FieldDescriptors. - NodeVector fields; - if (isa(&RttiTypes::StructuredClass)) { - const StructuredClass *tis = static_cast(this); - fields = tis->getEffectiveFieldDescriptors(); - } else { - fields = getFieldDescriptors(); - } + NodeVector fields = getFieldDescriptors(); for (auto &fd : fields) { for (auto &c : fd->getChildren()) { @@ -234,6 +228,30 @@ bool Descriptor::continuePath(Handle target, return found; } +int Descriptor::getFieldDescriptorIndex(const std::string &name) const +{ + int f = 0; + for (auto &fd : getFieldDescriptors()) { + if (fd->getName() == name) { + return f; + } + f++; + } + return -1; +} + +int Descriptor::getFieldDescriptorIndex(Handle fd) const +{ + int f = 0; + for (auto &fd2 : getFieldDescriptors()) { + if (fd == fd2) { + return f; + } + f++; + } + return -1; +} + void Descriptor::addFieldDescriptor(Handle fd) { // only add it if we need to. @@ -444,14 +462,13 @@ const void StructuredClass::gatherFieldDescriptors( } } -NodeVector StructuredClass::getEffectiveFieldDescriptors() - const +NodeVector StructuredClass::getFieldDescriptors() const { // in this case we return a NodeVector of Rooted entries without owner. NodeVector vec; std::set overriddenFields; gatherFieldDescriptors(vec, overriddenFields); - return std::move(vec); + return vec; } /* Class AnnotationClass */ diff --git a/src/core/model/Domain.hpp b/src/core/model/Domain.hpp index 53579bd..63f4c5d 100644 --- a/src/core/model/Domain.hpp +++ b/src/core/model/Domain.hpp @@ -485,17 +485,51 @@ public: } /** - * Returns a const reference to the NodeVector of all FieldDescriptors of - * this Descriptor. + * Returns the NodeVector of all FieldDescriptors of this Descriptor. * - * @return a const reference to the NodeVector of all FieldDescriptors of - * this Descriptor. + * @return the NodeVector of all FieldDescriptors of this Descriptor. */ - const NodeVector &getFieldDescriptors() const + virtual NodeVector 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. + */ + int 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. + */ + int getFieldDescriptorIndex(Handle fd) 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. @@ -697,10 +731,7 @@ public: * 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? + * Inheritance therefore also goes for fields. */ class StructuredClass : public Descriptor { friend Domain; @@ -825,7 +856,7 @@ public: * new subclasses AttributesDescriptor will be written into * this logger. */ - void addSubclass(Handle sc, Logger& logger); + void addSubclass(Handle sc, Logger &logger); /** * Removes a subclass from this StructuredClass. This also calls @@ -836,18 +867,17 @@ public: * removed subclasses AttributesDescriptor will be written * into this logger. */ - void removeSubclass(Handle sc, Logger& logger); + void removeSubclass(Handle sc, Logger &logger); /** * 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. + * this StructuredClass. This also merges the FieldDescriptors directly + * belonging to this StructuredClass with all FieldDescritptors of its + * Superclass (and so on recurvively). * - * @return a const reference to the NodeVector of all FieldDescriptors of - * this StructuredClass. + * @return a NodeVector of all FieldDescriptors of this StructuredClass. */ - NodeVector getEffectiveFieldDescriptors() const; + NodeVector getFieldDescriptors() const override; bool isTransparent() const { return transparent; } diff --git a/src/plugins/html/DemoOutput.cpp b/src/plugins/html/DemoOutput.cpp index d61e9b7..d041c1d 100644 --- a/src/plugins/html/DemoOutput.cpp +++ b/src/plugins/html/DemoOutput.cpp @@ -27,8 +27,8 @@ namespace ousia { namespace html { -void DemoHTMLTransformer::writeHTML(Handle doc, - std::ostream &out, bool pretty) +void DemoHTMLTransformer::writeHTML(Handle doc, std::ostream &out, + bool pretty) { Manager &mgr = doc->getManager(); // Create an XML object tree for the document first. @@ -115,7 +115,7 @@ Rooted DemoHTMLTransformer::transformSection( Rooted sec{ new xml::Element{mgr, parent, "section", {{"class", secclass}}}}; // check if we have a heading. - if (section->hasField("heading") && + if (section->getDescriptor()->hasField("heading") && section->getField("heading").size() > 0) { Handle heading = section->getField("heading")[0].cast(); @@ -188,8 +188,7 @@ Rooted DemoHTMLTransformer::transformList( Rooted l{new xml::Element{mgr, parent, listclass}}; // iterate through list items. for (auto &it : list->getField()) { - Handle item = - it.cast(); + Handle item = it.cast(); std::string itDescrName = item->getDescriptor()->getName(); if (itDescrName == "item") { // create the list item. @@ -210,9 +209,9 @@ Rooted DemoHTMLTransformer::transformList( typedef std::stack> AnnoStack; -static Rooted openAnnotation( - Manager &mgr, AnnoStack &opened, Handle entity, - Handle current) +static Rooted openAnnotation(Manager &mgr, AnnoStack &opened, + Handle entity, + Handle current) { // we push the newly opened entity on top of the stack. opened.push(entity); @@ -238,7 +237,8 @@ Rooted DemoHTMLTransformer::transformParagraph( Rooted p{new xml::Element{mgr, parent, "p"}}; // check if we have a heading. - if (par->hasField("heading") && par->getField("heading").size() > 0) { + if (par->getDescriptor()->hasField("heading") && + par->getField("heading").size() > 0) { Handle heading = par->getField("heading")[0].cast(); // put the heading in a strong xml::Element. diff --git a/src/plugins/xml/XmlParser.cpp b/src/plugins/xml/XmlParser.cpp index 4f956d5..6d77138 100644 --- a/src/plugins/xml/XmlParser.cpp +++ b/src/plugins/xml/XmlParser.cpp @@ -132,7 +132,8 @@ public: // try to find a FieldDescriptor for the given tag if we are not in a // field already. - if (!inField && parent != nullptr && parent->hasField(name())) { + if (!inField && parent != nullptr && + parent->getDescriptor()->hasField(name())) { Rooted field{new DocumentField( parentNode->getManager(), fieldName, parentNode)}; field->setLocation(location()); @@ -1315,7 +1316,6 @@ static void xmlStartElementHandler(void *p, const XML_Char *name, keyLoc.getStart()); args.emplace(key, value.second); } - // Call the start function std::string nameStr(name); -- cgit v1.2.3