diff options
author | Benjamin Paassen <bpaassen@techfak.uni-bielefeld.de> | 2015-01-21 00:30:28 +0100 |
---|---|---|
committer | Benjamin Paassen <bpaassen@techfak.uni-bielefeld.de> | 2015-01-21 00:30:28 +0100 |
commit | 6f1954eb9eed34aa1b5836bd1a2d153470cf3d59 (patch) | |
tree | c578e1b9de54fcd364165b5020bed771fcdef319 /src/core/model | |
parent | 497e39289191b7759f95605bc5f2c1eb5069666c (diff) |
introduced Domain validation functionality and a Unit test for it.
Diffstat (limited to 'src/core/model')
-rw-r--r-- | src/core/model/Domain.cpp | 147 | ||||
-rw-r--r-- | src/core/model/Domain.hpp | 47 |
2 files changed, 164 insertions, 30 deletions
diff --git a/src/core/model/Domain.cpp b/src/core/model/Domain.cpp index 0fc078f..50bde9c 100644 --- a/src/core/model/Domain.cpp +++ b/src/core/model/Domain.cpp @@ -55,6 +55,72 @@ FieldDescriptor::FieldDescriptor(Manager &mgr, Handle<Descriptor> parent, } } +bool FieldDescriptor::doValidate(Logger &logger) const +{ + bool valid = true; + // check parent type + if(getParent() == nullptr){ + logger.error("This field has no parent!"); + valid = false; + } else if (!getParent()->isa(RttiTypes::Descriptor)) { + logger.error("The parent of this field is not a descriptor!"); + valid = false; + } + // check name + if (!getName().empty()) { + valid = valid & validateName(logger); + } + // check consistency of FieldType with the rest of the FieldDescriptor. + if (fieldType == FieldType::PRIMITIVE) { + if (children.size() > 0) { + logger.error( + "This field is supposed to be primitive but has " + "registered child classes!"); + valid = false; + } + if (primitiveType == nullptr) { + logger.error( + "This field is supposed to be primitive but has " + "no primitive type!"); + valid = false; + } + } else { + if (primitiveType != nullptr) { + logger.error( + "This field is supposed to be non-primitive but has " + "a primitive type!"); + valid = false; + } + } + /* + * we are not allowed to call the validation functions of each child because + * this might lead to cycles. What we should do, however, is to check if + * there are no duplicates. + */ + std::set<std::string> names; + for (Handle<StructuredClass> c : children) { + if (!names.insert(c->getName()).second) { + logger.error(std::string("Field \"") + getName() + + "\" had multiple children with the name \"" + + c->getName() + "\""); + valid = false; + } + } + + return valid; +} + + +bool FieldDescriptor::removeChild(Handle<StructuredClass> c){ + auto it = children.find(c); + if(it != children.end()){ + invalidate(); + children.erase(it); + return true; + } + return false; +} + /* Class Descriptor */ void Descriptor::doResolve(ResolutionState &state) @@ -68,6 +134,40 @@ void Descriptor::doResolve(ResolutionState &state) state); } +bool Descriptor::doValidate(Logger &logger) const +{ + bool valid = true; + // check parent type + if(getParent() == nullptr){ + logger.error("This Descriptor has no parent!"); + valid = false; + } else if (!getParent()->isa(RttiTypes::Domain)) { + logger.error("The parent of this Descriptor is not a Domain!"); + valid = false; + } + // check name + if (getName().empty()) { + logger.error("The name of this Descriptor is empty!"); + valid = false; + } else{ + valid = valid & validateName(logger); + } + // check if all FieldDescriptors have this Descriptor as parent. + for (Handle<FieldDescriptor> fd : fieldDescriptors) { + if (fd->getParent() != this) { + logger.error(std::string("Descriptor \"") + getName() + + "\" has " + "field \"" + + fd->getName() + + "\" as child but the field does not " + "have the Descriptor as parent."); + valid = false; + } + } + // check the FieldDescriptors themselves. + return valid & continueValidationCheckDuplicates(fieldDescriptors, logger); +} + std::vector<Rooted<Node>> Descriptor::pathTo( Handle<StructuredClass> target) const { @@ -184,19 +284,47 @@ StructuredClass::StructuredClass(Manager &mgr, std::string name, } } +bool StructuredClass::doValidate(Logger &logger) const +{ + bool valid = true; + // check if all registered subclasses have this StructuredClass as parent. + for (Handle<StructuredClass> sub : subclasses) { + if (sub->getSuperclass() != this) { + logger.error(std::string("Struct \"") + sub->getName() + + "\" is registered as subclass of \"" + getName() + + "\" but does not have it as superclass!"); + valid = false; + } + } + // check the validity of this superclass. + if (superclass != nullptr) { + valid = valid & superclass->validate(logger); + } + // check the validity as a Descriptor. + /* + * Note that we do not check the validity of all subclasses. This is because + * it will lead to cycles as the subclasses would call validate on their + * superclass, which is this one. + */ + return valid & Descriptor::doValidate(logger); +} + void StructuredClass::setSuperclass(Handle<StructuredClass> sup) { if (superclass == sup) { return; } - invalidate(); - if (sup != nullptr) { - sup->addSubclass(this); - } + // remove this subclass from the old superclass. if (superclass != nullptr) { superclass->removeSubclass(this); } + // set the new superclass superclass = acquire(sup); + invalidate(); + // add this class as new subclass of the new superclass. + if (sup != nullptr) { + sup->addSubclass(this); + } } bool StructuredClass::isSubclassOf(Handle<StructuredClass> c) const @@ -287,6 +415,16 @@ void Domain::doResolve(ResolutionState &state) } } +bool Domain::doValidate(Logger &logger) const +{ + // check validity of name, of StructuredClasses, of AnnotationClasses and + // TypeSystems. + return validateName(logger) & + continueValidationCheckDuplicates(structuredClasses, logger) & + continueValidationCheckDuplicates(annotationClasses, logger) & + continueValidationCheckDuplicates(typesystems, logger); +} + void Domain::addStructuredClass(Handle<StructuredClass> s) { invalidate(); @@ -323,4 +461,3 @@ const Rtti Domain = RttiBuilder<model::Domain>("Domain") .composedOf({&StructuredClass, &AnnotationClass}); } } - diff --git a/src/core/model/Domain.hpp b/src/core/model/Domain.hpp index e4a6967..e485171 100644 --- a/src/core/model/Domain.hpp +++ b/src/core/model/Domain.hpp @@ -271,13 +271,9 @@ private: Owned<Type> primitiveType; bool optional; - /* - * TODO: doValidate with: - * # primitive and primitiveType set and no children XOR other FieldType and - * no primitive type set - * # namecheck - * # parent typecheck - */ +protected: + bool doValidate(Logger &logger) const override; + public: /** * This is the constructor for primitive fields. The type is automatically @@ -348,6 +344,17 @@ public: } /** + * 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). * @@ -451,14 +458,8 @@ private: protected: void doResolve(ResolutionState &state) override; - /* - * TODO: doValidate with: - * # namecheck - * # FieldDescriptor name uniqueness - * # do all FieldDescriptors have this Descriptor as parent? - * # is the parent a domain? - * # is the attributes descriptor either not set or a StructType? - */ + + bool doValidate(Logger &logger) const override; public: Descriptor(Manager &mgr, std::string name, Handle<Domain> domain, @@ -584,12 +585,12 @@ public: */ typedef RangeSet<size_t> Cardinality; - /** * This is the default cardinality. */ -static Cardinality createAny(){ +static Cardinality createAny() +{ Cardinality any; any.merge(Range<size_t>::typeRangeFrom(0)); return std::move(any); @@ -685,14 +686,8 @@ private: NodeVector<FieldDescriptor> ¤t, std::set<std::string> &overriddenFields) const; - - - /* - * TODO: doValidate with - * # does the subclasses have this class as superclass? - * # are the subclasses and the superclass valid? - * # is this a valid descriptor? - */ +protected: + bool doValidate(Logger &logger) const override; public: /** @@ -883,6 +878,8 @@ protected: * # are all annotationclasses valid and have a unique name? * # are all typesystems valid? */ + bool doValidate(Logger &logger) const override; + public: /** * The constructor for a new domain. Note that this is an empty Domain and |