diff options
-rw-r--r-- | src/core/model/Document.cpp | 43 | ||||
-rw-r--r-- | test/core/model/DocumentTest.cpp | 82 |
2 files changed, 119 insertions, 6 deletions
diff --git a/src/core/model/Document.cpp b/src/core/model/Document.cpp index e9b6136..a6bcb15 100644 --- a/src/core/model/Document.cpp +++ b/src/core/model/Document.cpp @@ -157,6 +157,32 @@ bool DocumentEntity::doValidate(Logger &logger) const } // iterate over every field for (unsigned int f = 0; f < fields.size(); f++) { + // we have a special check for primitive fields. + if (fieldDescs[f]->getFieldType() == + FieldDescriptor::FieldType::PRIMITIVE) { + switch (fields[f].size()) { + case 0: + if (!fieldDescs[f]->optional) { + logger.error(std::string("Primitive Field \"") + + fieldDescs[f]->getName() + + "\" had no content!"); + valid = false; + } + continue; + case 1: + break; + default: + logger.error(std::string("Primitive Field \"") + + fieldDescs[f]->getName() + + "\" had more than one child!"); + valid = false; + continue; + } + // if we are here we know that exactly one child exists. + // TODO: Check the primitive type of the child. + continue; + } + // we can do a faster check if this field is empty. if (fields[f].size() == 0) { // if this field is optional, an empty field is valid anyways. @@ -197,8 +223,10 @@ bool DocumentEntity::doValidate(Logger &logger) const continue; } if (rc->isa(RttiTypes::DocumentPrimitive)) { - // For DocumentPrimitives we have to check the content type. - // TODO: Do that! + logger.error(std::string("Non-primitive Field \"") + + fieldDescs[f]->getName() + + "\" had primitive content!"); + valid = false; continue; } // otherwise this is a StructuredEntity @@ -322,6 +350,7 @@ AnnotationEntity::AnnotationEntity(Manager &mgr, Handle<Document> parent, end(acquire(end)) { parent->annotations.push_back(this); + parent->invalidate(); } bool AnnotationEntity::doValidate(Logger &logger) const @@ -352,12 +381,18 @@ bool AnnotationEntity::doValidate(Logger &logger) const valid = valid & validateName(logger); } // check if the Anchors are part of the right document. - if (!doc->hasChild(start)) { + if (start == nullptr) { + logger.error("This annotation has no start Anchor!"); + valid = false; + } else if (!doc->hasChild(start)) { logger.error( "This annotations start anchor was not part of the same document!"); valid = false; } - if (!doc->hasChild(end)) { + if (end == nullptr) { + logger.error("This annotation has no end Anchor!"); + valid = false; + } else if (!doc->hasChild(end)) { logger.error( "This annotations end anchor was not part of the same document!"); valid = false; diff --git a/test/core/model/DocumentTest.cpp b/test/core/model/DocumentTest.cpp index d8ccef1..fea5296 100644 --- a/test/core/model/DocumentTest.cpp +++ b/test/core/model/DocumentTest.cpp @@ -134,6 +134,14 @@ TEST(Document, validate) buildRootStructuredEntity(doc, logger, {"root"}); ASSERT_TRUE(doc->validate(logger)); } + { + // A root with an invalid name, however, should make it invalid + Rooted<Document> doc{new Document(mgr, "myDoc.oxd")}; + doc->addDomain(domain); + Rooted<StructuredEntity> root = buildRootStructuredEntity( + doc, logger, {"root"}, {}, "my invalid root"); + ASSERT_FALSE(doc->validate(logger)); + } // now let's extend the rootClass with a default field. Rooted<FieldDescriptor> rootField{new FieldDescriptor(mgr, rootClass)}; @@ -192,8 +200,78 @@ TEST(Document, validate) buildStructuredEntity(doc, logger, root, {"childSub"}); ASSERT_FALSE(doc->validate(logger)); } - // TODO: Override child field in childSub such that an empty childSub is - // valid. + /* + * Override the default field in childSubClass. + */ + Rooted<FieldDescriptor> childSubField{ + new FieldDescriptor(mgr, childSubClass)}; + { + /* + * Now a document with one instance of the Child subclass should be + * valid, because of the override. + */ + Rooted<Document> doc{new Document(mgr, "myDoc.oxd")}; + doc->addDomain(domain); + Rooted<StructuredEntity> root = + buildRootStructuredEntity(doc, logger, {"root"}); + buildStructuredEntity(doc, logger, root, {"childSub"}); + ASSERT_TRUE(doc->validate(logger)); + } + // add a primitive field to the subclass with integer content. + Rooted<FieldDescriptor> primitive_field{new FieldDescriptor( + mgr, childSubClass, sys->getIntType(), "int", false)}; + { + /* + * Now a document with one instance of the Child subclass should be + * invalid again, because we are missing the primitive content. + */ + Rooted<Document> doc{new Document(mgr, "myDoc.oxd")}; + doc->addDomain(domain); + Rooted<StructuredEntity> root = + buildRootStructuredEntity(doc, logger, {"root"}); + buildStructuredEntity(doc, logger, root, {"childSub"}); + ASSERT_FALSE(doc->validate(logger)); + } + // TODO: Check wrongly typed primitive content. + + // Now add an Annotation class to the domain. + Rooted<AnnotationClass> annoClass{new AnnotationClass(mgr, "anno", domain)}; + { + /* + * Create a valid document in itself. + */ + Rooted<Document> doc{new Document(mgr, "myDoc.oxd")}; + doc->addDomain(domain); + Rooted<StructuredEntity> root = + buildRootStructuredEntity(doc, logger, {"root"}); + Rooted<StructuredEntity> child = + buildStructuredEntity(doc, logger, root, {"childSub"}); + Rooted<DocumentPrimitive> primitive{ + new DocumentPrimitive(mgr, child, {2}, "int")}; + ASSERT_TRUE(doc->validate(logger)); + // then add an AnnotationEntity without Anchors. + buildAnnotationEntity(doc, logger, {"anno"}, nullptr, nullptr); + ASSERT_FALSE(doc->validate(logger)); + } + { + /* + * Do the same again, but with a valid AnnotationEntity now. + */ + Rooted<Document> doc{new Document(mgr, "myDoc.oxd")}; + doc->addDomain(domain); + Rooted<StructuredEntity> root = + buildRootStructuredEntity(doc, logger, {"root"}); + Rooted<Anchor> start{new Anchor(mgr, "start", root)}; + Rooted<StructuredEntity> child = + buildStructuredEntity(doc, logger, root, {"childSub"}); + Rooted<DocumentPrimitive> primitive{ + new DocumentPrimitive(mgr, child, {2}, "int")}; + Rooted<Anchor> end{new Anchor(mgr, "end", root)}; + ASSERT_TRUE(doc->validate(logger)); + // then add an AnnotationEntity without Anchors. + buildAnnotationEntity(doc, logger, {"anno"}, start, end); + ASSERT_TRUE(doc->validate(logger)); + } } } } |