From 2f75ac166594b6bc2ea30901669304eca23174ec Mon Sep 17 00:00:00 2001 From: Benjamin Paassen Date: Wed, 11 Feb 2015 17:54:48 +0100 Subject: changed semantics of default field, now referring to the only TREE field. --- src/core/model/Domain.cpp | 133 +++++++++++++++++----- src/core/model/Domain.hpp | 246 ++++++++++++++-------------------------- src/plugins/html/DemoOutput.cpp | 2 +- src/plugins/xml/XmlParser.cpp | 8 +- 4 files changed, 198 insertions(+), 191 deletions(-) (limited to 'src') diff --git a/src/core/model/Domain.cpp b/src/core/model/Domain.cpp index 787f1ff..3fb525f 100644 --- a/src/core/model/Domain.cpp +++ b/src/core/model/Domain.cpp @@ -173,20 +173,38 @@ bool Descriptor::doValidate(Logger &logger) const } // ensure that no attribute with the key "name" exists. if (attributesDescriptor == nullptr) { - logger.error("This Descriptor has no Attribute specification!"); + logger.error(std::string("Descriptor \"") + getName() + + "\" has no Attribute specification!"); valid = false; } else { if (attributesDescriptor->hasAttribute("name")) { logger.error( - "This Descriptor has an attribute \"name\" which is a reserved " - "word!"); + std::string("Descriptor \"") + getName() + + "\" has an attribute \"name\" which is a reserved word!"); valid = false; } valid = valid & attributesDescriptor->validate(logger); } + // check that only one FieldDescriptor is of type TREE. + auto fds = Descriptor::getFieldDescriptors(); + bool hasTREE = false; + for (auto fd : fds) { + if (fd->getFieldType() == FieldDescriptor::FieldType::TREE) { + if (!hasTREE) { + hasTREE = true; + } else { + logger.error( + std::string("Descriptor \"") + getName() + + "\" has multiple TREE fields, which is not permitted", + *fd); + valid = false; + break; + } + } + } // check attributes and the FieldDescriptors - return valid & continueValidationCheckDuplicates(fieldDescriptors, logger); + return valid & continueValidationCheckDuplicates(fds, logger); } std::vector> Descriptor::pathTo( @@ -259,18 +277,39 @@ bool Descriptor::continuePath(Handle target, return found; } -ssize_t Descriptor::getFieldDescriptorIndex(const std::string &name) const +static ssize_t getFieldDescriptorIndex(const NodeVector &fds, + const std::string &name) { - size_t f = 0; - for (auto &fd : getFieldDescriptors()) { - if (fd->getName() == name) { + if (fds.empty()) { + return -1; + } + + if (name == DEFAULT_FIELD_NAME) { + if (fds.back()->getFieldType() == FieldDescriptor::FieldType::TREE) { + return fds.size() - 1; + } else { + /* The last field has to be the TREE field. If the last field does + * not have the FieldType TREE no TREE-field exists at all. So we + * return -1. + */ + return -1; + } + } + + for (size_t f = 0; f < fds.size(); f++) { + if (fds[f]->getName() == name) { return f; } - f++; } return -1; } +ssize_t Descriptor::getFieldDescriptorIndex(const std::string &name) const +{ + NodeVector fds = getFieldDescriptors(); + return ousia::getFieldDescriptorIndex(fds, name); +} + ssize_t Descriptor::getFieldDescriptorIndex(Handle fd) const { size_t f = 0; @@ -286,33 +325,54 @@ ssize_t Descriptor::getFieldDescriptorIndex(Handle fd) const Rooted Descriptor::getFieldDescriptor( const std::string &name) const { - for (auto &fd : getFieldDescriptors()) { - if (fd->getName() == name) { - return fd; - } + NodeVector fds = getFieldDescriptors(); + ssize_t idx = ousia::getFieldDescriptorIndex(fds, name); + if (idx != -1) { + return fds[idx]; + } else { + return nullptr; } - return nullptr; } -void Descriptor::addFieldDescriptor(Handle fd) +void Descriptor::addAndSortFieldDescriptor(Handle fd, + Logger &logger) { // only add it if we need to. - if (fieldDescriptors.find(fd) == fieldDescriptors.end()) { + auto fds = getFieldDescriptors(); + if (fds.find(fd) == fds.end()) { invalidate(); - fieldDescriptors.push_back(fd); + // check if the previous field is a tree field already. + if (!fds.empty() && + fds.back()->getFieldType() == FieldDescriptor::FieldType::TREE && + fd->getFieldType() != FieldDescriptor::FieldType::TREE) { + // if so we add the new field before the TREE field and log a + // warning. + + logger.warning( + std::string("Field \"") + fd->getName() + + "\" was declared after main field \"" + + fds.back()->getName() + + "\". The order of fields was changed to make the " + "main field the last field.", + *fd); + fieldDescriptors.insert(fieldDescriptors.end() - 1, fd); + } else { + fieldDescriptors.push_back(fd); + } } +} + +void Descriptor::addFieldDescriptor(Handle fd, Logger &logger) +{ + addAndSortFieldDescriptor(fd, logger); if (fd->getParent() == nullptr) { fd->setParent(this); } } -void Descriptor::moveFieldDescriptor(Handle fd) +void Descriptor::moveFieldDescriptor(Handle fd, Logger &logger) { - // only add it if we need to. - if (fieldDescriptors.find(fd) == fieldDescriptors.end()) { - invalidate(); - fieldDescriptors.push_back(fd); - } + addAndSortFieldDescriptor(fd, logger); Handle par = fd->getParent(); if (par != this) { if (par != nullptr) { @@ -494,18 +554,35 @@ void StructuredClass::removeSubclass(Handle sc, Logger &logger) sc->setSuperclass(nullptr, logger); } -const void StructuredClass::gatherFieldDescriptors( +void StructuredClass::gatherFieldDescriptors( NodeVector ¤t, - std::set &overriddenFields) const + std::set &overriddenFields, bool hasTREE) const { // append all FieldDescriptors that are not overridden. for (auto &f : Descriptor::getFieldDescriptors()) { if (overriddenFields.insert(f->getName()).second) { - current.push_back(f); + bool isTREE = f->getFieldType() == FieldDescriptor::FieldType::TREE; + if (hasTREE) { + if (!isTREE) { + /* + * If we already have a tree field it has to be at the end + * of the current vector. So ensure that all new non-TREE + * fields are inserted before the TREE field such that after + * this method the TREE field is still at the end. + */ + current.insert(current.end() - 1, f); + } + } else { + if (isTREE) { + hasTREE = true; + } + current.push_back(f); + } } } + // if we have a superclass, go there. if (superclass != nullptr) { - superclass->gatherFieldDescriptors(current, overriddenFields); + superclass->gatherFieldDescriptors(current, overriddenFields, hasTREE); } } @@ -514,7 +591,7 @@ NodeVector StructuredClass::getFieldDescriptors() const // in this case we return a NodeVector of Rooted entries without owner. NodeVector vec; std::set overriddenFields; - gatherFieldDescriptors(vec, overriddenFields); + gatherFieldDescriptors(vec, overriddenFields, false); return vec; } diff --git a/src/core/model/Domain.hpp b/src/core/model/Domain.hpp index 241c25d..43661c2 100644 --- a/src/core/model/Domain.hpp +++ b/src/core/model/Domain.hpp @@ -34,74 +34,46 @@ * * \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. + * "TREE". * - * The translation to context free grammars is as follows: + * The translation to a context free grammar is as follows: * * \code{.txt} * BOOK := BOOK_TREE @@ -128,21 +100,14 @@ * * \code{.xml} * - * - * - * - * - * - * - * - * - * - * ... - * - * - * - * - * + * + * + * + * + * + * ... + * + * * * \endcode * @@ -161,36 +126,36 @@ * * \code{.xml} * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * * * \endcode * @@ -227,25 +192,15 @@ static const std::string DEFAULT_FIELD_NAME = "$default"; * accordingly typed content without further descending in the Structure * Hierarchy. * - * As an example consider the "paragraph" StructuredClass, which might allow + * As an example consider the "text" 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; @@ -370,11 +325,11 @@ public: } /** - * Returns true if and only if the type of this field is PRIMITIVE. + * Returns if this field is primitive. * - * @return true if and only if the type of this field is PRIMITIVE. + * @return true if and only if this field is primitive. */ - bool isPrimitive() const { return fieldType == FieldType::PRIMITIVE; } + bool isPrimitive() const { return primitive; } /** * Returns the primitive type of this field, which is only allowed to be @@ -449,8 +404,10 @@ private: Owned attributesDescriptor; NodeVector fieldDescriptors; - bool continuePath(Handle target, - std::vector> &path) const; + bool continuePath(Handle target, NodeVector &path, + bool start) const; + + void addAndSortFieldDescriptor(Handle fd, Logger &logger); protected: void doResolve(ResolutionState &state) override; @@ -539,20 +496,7 @@ public: * * @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 yet. - * - * @param fds are FieldDescriptors. - */ - void addFieldDescriptors(const std::vector> &fds) - { - for (Handle fd : fds) { - addFieldDescriptor(fd); - } - } + void addFieldDescriptor(Handle fd, Logger &logger); /** * Adds the given FieldDescriptor to this Descriptor. This also sets the @@ -561,21 +505,7 @@ public: * * @param fd is a FieldDescriptor. */ - void moveFieldDescriptor(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 moveFieldDescriptors(const std::vector> &fds) - { - for (Handle fd : fds) { - moveFieldDescriptor(fd); - } - } + void moveFieldDescriptor(Handle fd, Logger &logger); /** * Copies a FieldDescriptor that belongs to another Descriptor to this @@ -583,7 +513,7 @@ public: * * @param fd some FieldDescriptor belonging to another Descriptor. */ - void copyFieldDescriptor(Handle fd); + void copyFieldDescriptor(Handle fd, Logger &logger); /** * Removes the given FieldDescriptor from this Descriptor. This also sets @@ -751,9 +681,9 @@ private: /** * Helper method for getFieldDescriptors. */ - const void gatherFieldDescriptors( - NodeVector ¤t, - std::set &overriddenFields) const; + void gatherFieldDescriptors(NodeVector ¤t, + std::set &overriddenFields, + bool hasTREE) const; protected: bool doValidate(Logger &logger) const override; diff --git a/src/plugins/html/DemoOutput.cpp b/src/plugins/html/DemoOutput.cpp index d041c1d..cb34cbe 100644 --- a/src/plugins/html/DemoOutput.cpp +++ b/src/plugins/html/DemoOutput.cpp @@ -324,7 +324,7 @@ Rooted DemoHTMLTransformer::transformParagraph( if (childDescriptorName == "text") { Handle primitive = t->getField()[0].cast(); - if (primitive.isNull()) { + if (primitive == nullptr) { throw OusiaException("Text field is not primitive!"); } current->addChild(new xml::Text( diff --git a/src/plugins/xml/XmlParser.cpp b/src/plugins/xml/XmlParser.cpp index 22498f4..d7efa4d 100644 --- a/src/plugins/xml/XmlParser.cpp +++ b/src/plugins/xml/XmlParser.cpp @@ -603,7 +603,7 @@ public: [](Handle field, Handle parent, Logger &logger) { if (field != nullptr) { parent.cast()->addFieldDescriptor( - field.cast()); + field.cast(), logger); } }); } @@ -969,7 +969,7 @@ static const ParserState DomainField = .parents({&DomainStruct, &DomainAnnotation}) .createdNodeType(&RttiTypes::FieldDescriptor) .elementHandler(DomainFieldHandler::create) - .arguments({Argument::String("name", DEFAULT_FIELD_NAME), + .arguments({Argument::String("name", ""), Argument::Bool("isSubtree", false), Argument::Bool("optional", false)}); @@ -985,7 +985,7 @@ static const ParserState DomainStructPrimitive = .parents({&DomainStruct, &DomainAnnotation}) .createdNodeType(&RttiTypes::FieldDescriptor) .elementHandler(DomainPrimitiveHandler::create) - .arguments({Argument::String("name", DEFAULT_FIELD_NAME), + .arguments({Argument::String("name", ""), Argument::Bool("isSubtree", false), Argument::Bool("optional", false), Argument::String("type")}); @@ -1008,7 +1008,7 @@ static const ParserState DomainStructParentField = .parent(&DomainStructParent) .createdNodeType(&RttiTypes::FieldDescriptor) .elementHandler(DomainParentFieldHandler::create) - .arguments({Argument::String("name", DEFAULT_FIELD_NAME), + .arguments({Argument::String("name", ""), Argument::Bool("isSubtree", false), Argument::Bool("optional", false)}); -- cgit v1.2.3