diff options
author | Benjamin Paassen <bpaassen@techfak.uni-bielefeld.de> | 2015-01-22 00:43:40 +0100 |
---|---|---|
committer | Benjamin Paassen <bpaassen@techfak.uni-bielefeld.de> | 2015-01-22 00:43:40 +0100 |
commit | 33008f1110523ae9c9b9e1d2ca24ed642637c40d (patch) | |
tree | d058340aaab51df5a59dc89a8b08b829923074b3 | |
parent | 601d07df6339696bace0f303a69a0a02a39f9eea (diff) |
added move semantics do Domain and Document classes.
-rw-r--r-- | src/core/model/Document.cpp | 89 | ||||
-rw-r--r-- | src/core/model/Document.hpp | 88 | ||||
-rw-r--r-- | src/core/model/Domain.cpp | 101 | ||||
-rw-r--r-- | src/core/model/Domain.hpp | 64 | ||||
-rw-r--r-- | test/core/model/DomainTest.cpp | 28 |
5 files changed, 303 insertions, 67 deletions
diff --git a/src/core/model/Document.cpp b/src/core/model/Document.cpp index f29af1c..2ae9107 100644 --- a/src/core/model/Document.cpp +++ b/src/core/model/Document.cpp @@ -335,13 +335,39 @@ void DocumentEntity::setAttributes(const Variant &a) void DocumentEntity::addStructureNode(Handle<StructureNode> s, const int &i) { - invalidateSubInstance(); - fields[i].push_back(s); - if (s->getParent() != subInst) { + // only add the new node if we don't have it already. + auto it = fields[i].find(s); + if (it == fields[i].end()) { + invalidateSubInstance(); + fields[i].push_back(s); + } + Handle<Managed> par = s->getParent(); + if (par != subInst) { + // if a previous parent existed, remove the StructureNode from it + if (par != nullptr) { + if (par->isa(RttiTypes::StructuredEntity)) { + par.cast<StructuredEntity>()->removeStructureNode(s); + } else { + par.cast<AnnotationEntity>()->removeStructureNode(s); + } + } s->setParent(subInst); } } +bool DocumentEntity::removeStructureNodeFromField(Handle<StructureNode> s, + const int &i) +{ + 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::addStructureNode(Handle<StructureNode> s, const std::string &fieldName) { @@ -357,6 +383,13 @@ void DocumentEntity::addStructureNodes( } } +bool DocumentEntity::removeStructureNodeFromField( + Handle<StructureNode> s, const std::string &fieldName) +{ + return removeStructureNodeFromField( + s, getFieldDescriptorIndex(fieldName, true)); +} + void DocumentEntity::addStructureNode(Handle<StructureNode> s, Handle<FieldDescriptor> fieldDescriptor) { @@ -373,6 +406,28 @@ void DocumentEntity::addStructureNodes( } } +bool DocumentEntity::removeStructureNodeFromField( + Handle<StructureNode> s, Handle<FieldDescriptor> fieldDescriptor) +{ + return removeStructureNodeFromField( + s, getFieldDescriptorIndex(fieldDescriptor, true)); +} + +bool DocumentEntity::removeStructureNode(Handle<StructureNode> s) +{ + for (auto field : fields) { + auto it = field.find(s); + if (it != field.end()) { + invalidateSubInstance(); + field.erase(it); + s->setParent(nullptr); + return true; + } + } + + return false; +} + /* Class StructureNode */ bool StructureNode::doValidate(Logger &logger) const @@ -558,9 +613,17 @@ bool Document::doValidate(Logger &logger) const void Document::addAnnotation(Handle<AnnotationEntity> a) { - invalidate(); - annotations.push_back(a); - if (a->getParent() != this) { + // only add it if we need to. + if (annotations.find(a) == annotations.end()) { + invalidate(); + annotations.push_back(a); + } + Handle<Managed> par = a->getParent(); + if (par != this) { + if (par != nullptr) { + // remove the StructuredClass from the old parent. + par.cast<Document>()->removeAnnotation(a); + } a->setParent(this); } } @@ -572,6 +635,20 @@ void Document::addAnnotations(const std::vector<Handle<AnnotationEntity>> &as) } } + + +bool Document::removeAnnotation(Handle<AnnotationEntity> a) +{ + auto it = annotations.find(a); + if (it != annotations.end()) { + invalidate(); + annotations.erase(it); + a->setParent(nullptr); + return true; + } + return false; +} + bool Document::hasChild(Handle<StructureNode> s) const { Rooted<Managed> parent = s->getParent(); diff --git a/src/core/model/Document.hpp b/src/core/model/Document.hpp index f13faf2..7357dd2 100644 --- a/src/core/model/Document.hpp +++ b/src/core/model/Document.hpp @@ -162,6 +162,8 @@ private: void addStructureNode(Handle<StructureNode> s, const int &i); + bool removeStructureNodeFromField(Handle<StructureNode> s, const int &i); + protected: bool doValidate(Logger &logger) const; @@ -278,8 +280,8 @@ public: * If the name is unknown an exception is thrown. * * This method also changes the parent of the newly added StructureNode if - * it is not set to this DocumentEntity already. - * TODO: This could get move semantics. + * 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 fieldName is the name of a field as specified in the @@ -287,6 +289,7 @@ public: */ void addStructureNode(Handle<StructureNode> s, const std::string &fieldName = ""); + /** * This adds multiple StructureNodes to the field with the given name. * If an empty name is given it is assumed that the 'default' @@ -297,7 +300,8 @@ public: * If the name is unknown an exception is thrown. * * This method also changes the parent of each newly added StructureNode if - * it is not set to this DocumentEntity already. + * it is not set to this DocumentEntity already and removes it from the + * old parent. * * @param ss are the StructureNodes that shall be added. * @param fieldName is the name of a field as specified in the @@ -307,13 +311,34 @@ public: const std::string &fieldName = ""); /** + * This removes a StructureNode from the field with the given name. If an + * empty name is given it is assumed that the 'default' FieldDescriptor is + * referenced, where 'default' means either: + * 1.) The only TREE typed FieldDescriptor (if present) or + * 2.) the only FieldDescriptor (if only one is specified). + * + * If the name is unknown an exception is thrown. + * + * This method also changes the parent of the removed StructureNode to null. + * + * @param s is the StructureNode that shall be removed. + * @param fieldName is the name 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<StructureNode> s, + const std::string &fieldName = ""); + + /** * This adds a StructureNode to the field with the given FieldDescriptor. * * If the FieldDescriptor does not belong to the Descriptor of this node * an exception is thrown. * * This method also changes the parent of the newly added StructureNode if - * it is not set to this DocumentEntity already. + * 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 fieldDescriptor is a FieldDescriptor defined in the Descriptor for @@ -330,7 +355,8 @@ public: * an exception is thrown. * * This method also changes the parent of each newly added StructureNode if - * it is not set to this DocumentEntity already. + * it is not set to this DocumentEntity already and removes it from the + * old parent. * * @param ss are the StructureNodes that shall be added. * @param fieldDescriptor is a FieldDescriptor defined in the Descriptor for @@ -338,6 +364,35 @@ public: */ void addStructureNodes(const std::vector<Handle<StructureNode>> &ss, Handle<FieldDescriptor> fieldDescriptor); + + /** + * This removes a StructureNode from the field with the given + * FieldDescriptor. + * + * This method also changes the parent of the removed StructureNode to null. + * + * @param s is the StructureNode that shall be removed. + * @param fieldDescriptor is a FieldDescriptor defined in the Descriptor for + * this DocumentEntity. + + * @return true if this StructureNode was a child here and false if + * if was not found. + */ + bool removeStructureNodeFromField(Handle<StructureNode> s, + Handle<FieldDescriptor> fieldDescriptor); + + /** + * This removes a StructureNode from this DocumentEntity. It iterates + * through all fields to find it. + * + * This method also changes the parent of the removed StructureNode to null. + * + * @param s is the StructureNode that shall be removed. + + * @return true if this StructureNode was a child here and false if if was + * not found. + */ + bool removeStructureNode(Handle<StructureNode> s); }; /** @@ -680,21 +735,32 @@ public: } /** - * Adds an AnnotationEntity to this document. This also sets the parent - * of the given AnnotationEntity if it is not set to this document already. + * Adds an AnnotationEntity to this Document. This also sets the parent + * of the given AnnotationEntity if it is not set to this Document already + * and removes it from the old Document. * * @param a is some AnnotationEntity */ void addAnnotation(Handle<AnnotationEntity> a); /** - * Adds multiple AnnotationEntities to this document. This also sets the - * parent of each given AnnotationEntity if it is not set to this document - * already. + * Adds multiple AnnotationEntities to this Document. This also sets the + * parent of each given AnnotationEntity if it is not set to this Document + * already and removes it from the old Document. * * @param as is a vector of AnnotationEntities. */ - void addAnnotations(const std::vector<Handle<AnnotationEntity>>& as); + void addAnnotations(const std::vector<Handle<AnnotationEntity>> &as); + + /** + * Removes an AnnotationEntity from this Document. This also sets the parent + * of the given AnnotationEntity to null. + * + * @param a is some AnnotationEntity. + * @return true if the given AnnotationEntity was removed and false if this + * Document did not have the given AnnotationEntity as child. + */ + bool removeAnnotation(Handle<AnnotationEntity> a); /** * Returns a const reference to the NodeVector of Domains that are used diff --git a/src/core/model/Domain.cpp b/src/core/model/Domain.cpp index 50bde9c..b425174 100644 --- a/src/core/model/Domain.cpp +++ b/src/core/model/Domain.cpp @@ -59,7 +59,7 @@ bool FieldDescriptor::doValidate(Logger &logger) const { bool valid = true; // check parent type - if(getParent() == nullptr){ + if (getParent() == nullptr) { logger.error("This field has no parent!"); valid = false; } else if (!getParent()->isa(RttiTypes::Descriptor)) { @@ -110,10 +110,10 @@ bool FieldDescriptor::doValidate(Logger &logger) const return valid; } - -bool FieldDescriptor::removeChild(Handle<StructuredClass> c){ +bool FieldDescriptor::removeChild(Handle<StructuredClass> c) +{ auto it = children.find(c); - if(it != children.end()){ + if (it != children.end()) { invalidate(); children.erase(it); return true; @@ -138,7 +138,7 @@ bool Descriptor::doValidate(Logger &logger) const { bool valid = true; // check parent type - if(getParent() == nullptr){ + if (getParent() == nullptr) { logger.error("This Descriptor has no parent!"); valid = false; } else if (!getParent()->isa(RttiTypes::Domain)) { @@ -149,7 +149,7 @@ bool Descriptor::doValidate(Logger &logger) const if (getName().empty()) { logger.error("The name of this Descriptor is empty!"); valid = false; - } else{ + } else { valid = valid & validateName(logger); } // check if all FieldDescriptors have this Descriptor as parent. @@ -244,9 +244,25 @@ bool Descriptor::continuePath(Handle<StructuredClass> target, return found; } +void Descriptor::addFieldDescriptor(Handle<FieldDescriptor> fd) +{ + // only add it if we need to. + if (fieldDescriptors.find(fd) == fieldDescriptors.end()) { + invalidate(); + fieldDescriptors.push_back(fd); + } + Handle<Managed> par = fd->getParent(); + if (par != this) { + if (par != nullptr) { + // remove the FieldDescriptor from the old parent. + par.cast<Descriptor>()->removeFieldDescriptor(fd); + } + fd->setParent(this); + } +} + void Descriptor::copyFieldDescriptor(Handle<FieldDescriptor> fd) { - invalidate(); if (fd->getFieldType() == FieldDescriptor::FieldType::PRIMITIVE) { /* * To call the "new" operation is enough here, because the @@ -261,6 +277,18 @@ void Descriptor::copyFieldDescriptor(Handle<FieldDescriptor> fd) } } +bool Descriptor::removeFieldDescriptor(Handle<FieldDescriptor> fd) +{ + auto it = fieldDescriptors.find(fd); + if (it != fieldDescriptors.end()) { + invalidate(); + fieldDescriptors.erase(it); + fd->setParent(nullptr); + return true; + } + return false; +} + /* Class StructuredClass */ StructuredClass::StructuredClass(Manager &mgr, std::string name, @@ -341,11 +369,10 @@ bool StructuredClass::isSubclassOf(Handle<StructuredClass> c) const void StructuredClass::addSubclass(Handle<StructuredClass> sc) { // check if we already have that class. - if (subclasses.find(sc) != subclasses.end()) { - return; + if (subclasses.find(sc) == subclasses.end()) { + invalidate(); + subclasses.push_back(sc); } - invalidate(); - subclasses.push_back(sc); sc->setSuperclass(this); } @@ -427,21 +454,61 @@ bool Domain::doValidate(Logger &logger) const void Domain::addStructuredClass(Handle<StructuredClass> s) { - invalidate(); - structuredClasses.push_back(s); - if (s->getParent() != this) { + // only add it if we need to. + if (structuredClasses.find(s) == structuredClasses.end()) { + invalidate(); + structuredClasses.push_back(s); + } + Handle<Managed> par = s->getParent(); + if (par != this) { + if (par != nullptr) { + // remove the StructuredClass from the old parent. + par.cast<Domain>()->removeStructuredClass(s); + } s->setParent(this); } } +bool Domain::removeStructuredClass(Handle<StructuredClass> s) +{ + auto it = structuredClasses.find(s); + if (it != structuredClasses.end()) { + invalidate(); + structuredClasses.erase(it); + s->setParent(nullptr); + return true; + } + return false; +} + void Domain::addAnnotationClass(Handle<AnnotationClass> a) { - invalidate(); - annotationClasses.push_back(a); - if (a->getParent() != this) { + // only add it if we need to. + if (annotationClasses.find(a) == annotationClasses.end()) { + invalidate(); + annotationClasses.push_back(a); + } + Handle<Managed> par = a->getParent(); + if (par != this) { + if (par != nullptr) { + // remove the StructuredClass from the old parent. + par.cast<Domain>()->removeAnnotationClass(a); + } a->setParent(this); } } + +bool Domain::removeAnnotationClass(Handle<AnnotationClass> a) +{ + auto it = annotationClasses.find(a); + if (it != annotationClasses.end()) { + invalidate(); + annotationClasses.erase(it); + a->setParent(nullptr); + return true; + } + return false; +} } /* Type registrations */ diff --git a/src/core/model/Domain.hpp b/src/core/model/Domain.hpp index 85caa14..12cb9b3 100644 --- a/src/core/model/Domain.hpp +++ b/src/core/model/Domain.hpp @@ -510,33 +510,21 @@ public: /** * 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. - * - * This should not be used if the given FieldDescriptor is a field of - * another Descriptor already. Use copyFieldDescriptor in that case. - * TODO: But this could get move semantics. + * already and removes it from the old parent Descriptor. * * @param fd is a FieldDescriptor. */ - void addFieldDescriptor(Handle<FieldDescriptor> fd) - { - invalidate(); - fieldDescriptors.push_back(fd); - if (fd->getParent() != this) { - fd->setParent(this); - } - } + void addFieldDescriptor(Handle<FieldDescriptor> 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. + * already and removes it from the old parent Descriptor. * * @param fds are FieldDescriptors. */ void addFieldDescriptors(const std::vector<Handle<FieldDescriptor>> &fds) { - invalidate(); for (Handle<FieldDescriptor> fd : fds) { addFieldDescriptor(fd); } @@ -551,6 +539,16 @@ public: void copyFieldDescriptor(Handle<FieldDescriptor> 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<FieldDescriptor> fd); + + /** * 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. @@ -877,13 +875,7 @@ private: protected: void doResolve(ResolutionState &state) override; - /* - * TODO: doValidate with: - * # namecheck - * # are all structureclasses valid and have a unique name? - * # are all annotationclasses valid and have a unique name? - * # are all typesystems valid? - */ + bool doValidate(Logger &logger) const override; public: @@ -931,14 +923,24 @@ public: } /** * Adds a StructuredClass to this domain. This also sets the parent of the - * given StructuredClass if it is not set to this Domain already. - * TODO: This could have move semantics. + * 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); + + /** * Returns a const reference to the NodeVector of AnnotationClasses that are * part of this Domain. * @@ -951,14 +953,24 @@ public: } /** * Adds an AnnotationClass to this domain. This also sets the parent of the - * given AnnotationClass if it is not set to this Domain already. - * TODO: This could have move semantics. + * 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); + + /** * Returns a const reference to the NodeVector of TypeSystems that are * references in this Domain. * diff --git a/test/core/model/DomainTest.cpp b/test/core/model/DomainTest.cpp index 8ece2c9..2b63aeb 100644 --- a/test/core/model/DomainTest.cpp +++ b/test/core/model/DomainTest.cpp @@ -293,77 +293,91 @@ TEST(Domain, validate) // start with an easy example: Our book domain should be valid. { Rooted<Domain> domain = constructBookDomain(mgr, sys, logger); + ASSERT_EQ(ValidationState::UNKNOWN, domain->getValidationState()); ASSERT_TRUE(domain->validate(logger)); } { // Even easier: An empty domain should be valid. Rooted<Domain> domain{new Domain(mgr, sys, "domain")}; + ASSERT_EQ(ValidationState::UNKNOWN, domain->getValidationState()); ASSERT_TRUE(domain->validate(logger)); // if we add a StructureClass it should be valid still. Rooted<StructuredClass> base{ new StructuredClass(mgr, "myClass", domain)}; + ASSERT_EQ(ValidationState::UNKNOWN, domain->getValidationState()); ASSERT_TRUE(domain->validate(logger)); - // if we tamper with the parent reference, however, it shouldn't be - // valid anymore. - base->setParent(nullptr); - ASSERT_FALSE(base->validate(logger)); - base->setParent(domain); - ASSERT_TRUE(domain->validate(logger)); - // the same goes for the name. + // if we tamper with the name, however, it shouldn't be valid anymore. base->setName(""); + ASSERT_EQ(ValidationState::UNKNOWN, domain->getValidationState()); ASSERT_FALSE(domain->validate(logger)); base->setName("my class"); + ASSERT_EQ(ValidationState::UNKNOWN, domain->getValidationState()); ASSERT_FALSE(domain->validate(logger)); base->setName("myClass"); + ASSERT_EQ(ValidationState::UNKNOWN, domain->getValidationState()); ASSERT_TRUE(domain->validate(logger)); // Let's add a primitive field (without a primitive type at first) Rooted<FieldDescriptor> base_field{ new FieldDescriptor(mgr, base, nullptr)}; // this should not be valid. + ASSERT_EQ(ValidationState::UNKNOWN, domain->getValidationState()); ASSERT_FALSE(domain->validate(logger)); // but it should be if we set the type. base_field->setPrimitiveType(sys->getStringType()); + ASSERT_EQ(ValidationState::UNKNOWN, domain->getValidationState()); ASSERT_TRUE(domain->validate(logger)); // not anymore, however, if we tamper with the FieldType. base_field->setFieldType(FieldDescriptor::FieldType::TREE); + ASSERT_EQ(ValidationState::UNKNOWN, domain->getValidationState()); ASSERT_FALSE(domain->validate(logger)); base_field->setFieldType(FieldDescriptor::FieldType::PRIMITIVE); + ASSERT_EQ(ValidationState::UNKNOWN, domain->getValidationState()); ASSERT_TRUE(domain->validate(logger)); // add a subclass for our base class. Rooted<StructuredClass> sub{ new StructuredClass(mgr, "sub", domain)}; // this should be valid in itself. + ASSERT_EQ(ValidationState::UNKNOWN, domain->getValidationState()); ASSERT_TRUE(domain->validate(logger)); // and still if we add a superclass. sub->setSuperclass(base); + ASSERT_EQ(ValidationState::UNKNOWN, domain->getValidationState()); ASSERT_TRUE(domain->validate(logger)); // and still we we remove the subclass from the base class. base->removeSubclass(sub); + ASSERT_EQ(ValidationState::UNKNOWN, domain->getValidationState()); ASSERT_TRUE(domain->validate(logger)); ASSERT_EQ(nullptr, sub->getSuperclass()); // and still if we re-add it. base->addSubclass(sub); + ASSERT_EQ(ValidationState::UNKNOWN, domain->getValidationState()); ASSERT_TRUE(domain->validate(logger)); ASSERT_EQ(base, sub->getSuperclass()); // add a non-primitive field to the child class. Rooted<FieldDescriptor> sub_field{ new FieldDescriptor(mgr, sub)}; // this should be valid + ASSERT_EQ(ValidationState::UNKNOWN, domain->getValidationState()); ASSERT_TRUE(domain->validate(logger)); // .. until we set a primitive type. sub_field->setPrimitiveType(sys->getStringType()); + ASSERT_EQ(ValidationState::UNKNOWN, domain->getValidationState()); ASSERT_FALSE(domain->validate(logger)); // and valid again if we unset it. sub_field->setPrimitiveType(nullptr); + ASSERT_EQ(ValidationState::UNKNOWN, domain->getValidationState()); ASSERT_TRUE(domain->validate(logger)); // we should also be able to add a child and have it still be valid. sub_field->addChild(base); + ASSERT_EQ(ValidationState::UNKNOWN, domain->getValidationState()); ASSERT_TRUE(domain->validate(logger)); // it should be invalid if we add it twice. sub_field->addChild(base); + ASSERT_EQ(ValidationState::UNKNOWN, domain->getValidationState()); ASSERT_FALSE(domain->validate(logger)); // and valid again if we remove it once. sub_field->removeChild(base); + ASSERT_EQ(ValidationState::UNKNOWN, domain->getValidationState()); ASSERT_TRUE(domain->validate(logger)); } } |