summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Paassen <bpaassen@techfak.uni-bielefeld.de>2015-02-06 16:47:49 +0100
committerBenjamin Paassen <bpaassen@techfak.uni-bielefeld.de>2015-02-06 16:47:49 +0100
commit3883e6df939ad1ecb9a788153e087fefd9f0e838 (patch)
tree7a775a29f7883d1e98849d2a4d016fe917558250
parent72848f6155c40e88572723a39852473a8be3b5bd (diff)
corrected attributes descriptor handling.
-rw-r--r--src/core/model/Domain.cpp67
-rw-r--r--src/core/model/Domain.hpp68
-rw-r--r--test/core/model/DocumentTest.cpp24
-rw-r--r--test/core/model/DomainTest.cpp32
-rw-r--r--test/core/model/TestAdvanced.hpp6
-rw-r--r--test/core/model/TestDomain.hpp6
-rw-r--r--test/plugins/xml/XmlParserTest.cpp41
-rw-r--r--testdata/xmlparser/book_domain.oxm3
8 files changed, 132 insertions, 115 deletions
diff --git a/src/core/model/Domain.cpp b/src/core/model/Domain.cpp
index f8c0779..3284759 100644
--- a/src/core/model/Domain.cpp
+++ b/src/core/model/Domain.cpp
@@ -128,11 +128,9 @@ bool FieldDescriptor::removeChild(Handle<StructuredClass> c)
void Descriptor::doResolve(ResolutionState &state)
{
- if (attributesDescriptor != nullptr) {
- const NodeVector<Attribute> &attributes =
- attributesDescriptor->getAttributes();
- continueResolveComposita(attributes, attributes.getIndex(), state);
- }
+ const NodeVector<Attribute> &attributes =
+ attributesDescriptor->getAttributes();
+ continueResolveComposita(attributes, attributes.getIndex(), state);
continueResolveComposita(fieldDescriptors, fieldDescriptors.getIndex(),
state);
}
@@ -155,8 +153,9 @@ bool Descriptor::doValidate(Logger &logger) const
} else {
valid = valid & validateName(logger);
}
- // check the FieldDescriptors themselves.
- return valid & continueValidationCheckDuplicates(fieldDescriptors, logger);
+ // check attributes and the FieldDescriptors
+ return valid & attributesDescriptor->validate(logger) &
+ continueValidationCheckDuplicates(fieldDescriptors, logger);
}
std::vector<Rooted<Node>> Descriptor::pathTo(
@@ -235,7 +234,6 @@ bool Descriptor::continuePath(Handle<StructuredClass> target,
return found;
}
-
void Descriptor::addFieldDescriptor(Handle<FieldDescriptor> fd)
{
// only add it if we need to.
@@ -319,18 +317,18 @@ Rooted<FieldDescriptor> Descriptor::createFieldDescriptor(
StructuredClass::StructuredClass(Manager &mgr, std::string name,
Handle<Domain> domain, Variant cardinality,
- Handle<StructType> attributesDescriptor,
Handle<StructuredClass> superclass,
bool transparent, bool root)
- : Descriptor(mgr, std::move(name), domain, attributesDescriptor),
+ : Descriptor(mgr, std::move(name), domain),
cardinality(std::move(cardinality)),
superclass(acquire(superclass)),
subclasses(this),
transparent(transparent),
root(root)
{
+ ExceptionLogger logger;
if (superclass != nullptr) {
- superclass->addSubclass(this);
+ superclass->addSubclass(this, logger);
}
if (domain != nullptr) {
domain->addStructuredClass(this);
@@ -368,21 +366,26 @@ bool StructuredClass::doValidate(Logger &logger) const
return valid & Descriptor::doValidate(logger);
}
-void StructuredClass::setSuperclass(Handle<StructuredClass> sup)
+void StructuredClass::setSuperclass(Handle<StructuredClass> sup, Logger &logger)
{
if (superclass == sup) {
return;
}
// remove this subclass from the old superclass.
if (superclass != nullptr) {
- superclass->removeSubclass(this);
+ superclass->removeSubclass(this, logger);
}
// set the new superclass
superclass = acquire(sup);
invalidate();
// add this class as new subclass of the new superclass.
if (sup != nullptr) {
- sup->addSubclass(this);
+ sup->addSubclass(this, logger);
+ // set the attribute descriptor supertype
+ getAttributesDescriptor()->setParentStructure(
+ sup->getAttributesDescriptor(), logger);
+ } else {
+ getAttributesDescriptor()->setParentStructure(nullptr, logger);
}
}
@@ -397,17 +400,20 @@ bool StructuredClass::isSubclassOf(Handle<StructuredClass> c) const
return superclass->isSubclassOf(c);
}
-void StructuredClass::addSubclass(Handle<StructuredClass> sc)
+void StructuredClass::addSubclass(Handle<StructuredClass> sc, Logger &logger)
{
+ if (sc == nullptr) {
+ return;
+ }
// check if we already have that class.
if (subclasses.find(sc) == subclasses.end()) {
invalidate();
subclasses.push_back(sc);
}
- sc->setSuperclass(this);
+ sc->setSuperclass(this, logger);
}
-void StructuredClass::removeSubclass(Handle<StructuredClass> sc)
+void StructuredClass::removeSubclass(Handle<StructuredClass> sc, Logger &logger)
{
// if we don't have this subclass we can return directly.
if (sc == nullptr) {
@@ -420,7 +426,7 @@ void StructuredClass::removeSubclass(Handle<StructuredClass> sc)
// otherwise we have to erase it.
invalidate();
subclasses.erase(it);
- sc->setSuperclass(nullptr);
+ sc->setSuperclass(nullptr, logger);
}
const void StructuredClass::gatherFieldDescriptors(
@@ -450,13 +456,11 @@ NodeVector<FieldDescriptor> StructuredClass::getEffectiveFieldDescriptors()
/* Class AnnotationClass */
-AnnotationClass::AnnotationClass(
- Manager &mgr, std::string name, Handle<Domain> domain,
- // TODO: What would be a wise default value for attributes?
- Handle<StructType> attributesDescriptor)
- : Descriptor(mgr, std::move(name), domain, attributesDescriptor)
+AnnotationClass::AnnotationClass(Manager &mgr, std::string name,
+ Handle<Domain> domain)
+ : Descriptor(mgr, std::move(name), domain)
{
- if (!domain.isNull()) {
+ if (domain != nullptr) {
domain->addAnnotationClass(this);
}
}
@@ -525,14 +529,12 @@ bool Domain::removeStructuredClass(Handle<StructuredClass> s)
}
Rooted<StructuredClass> Domain::createStructuredClass(
- std::string name, Variant cardinality,
- Handle<StructType> attributesDescriptor, Handle<StructuredClass> superclass,
+ std::string name, Variant cardinality, Handle<StructuredClass> superclass,
bool transparent, bool root)
{
return Rooted<StructuredClass>{new StructuredClass(
- getManager(), std::move(name), this, std::move(cardinality),
- attributesDescriptor, superclass, std::move(transparent),
- std::move(root))};
+ getManager(), std::move(name), this, std::move(cardinality), superclass,
+ std::move(transparent), std::move(root))};
}
void Domain::addAnnotationClass(Handle<AnnotationClass> a)
@@ -564,11 +566,10 @@ bool Domain::removeAnnotationClass(Handle<AnnotationClass> a)
return false;
}
-Rooted<AnnotationClass> Domain::createAnnotationClass(
- std::string name, Handle<StructType> attributesDescriptor)
+Rooted<AnnotationClass> Domain::createAnnotationClass(std::string name)
{
- return Rooted<AnnotationClass>{new AnnotationClass(
- getManager(), std::move(name), this, attributesDescriptor)};
+ return Rooted<AnnotationClass>{
+ new AnnotationClass(getManager(), std::move(name), this)};
}
/* Type registrations */
diff --git a/src/core/model/Domain.hpp b/src/core/model/Domain.hpp
index dd0af4c..cd05441 100644
--- a/src/core/model/Domain.hpp
+++ b/src/core/model/Domain.hpp
@@ -217,7 +217,6 @@ class Descriptor;
class StructuredClass;
class Domain;
-
static const std::string DEFAULT_FIELD_NAME = "$default";
/**
@@ -292,7 +291,8 @@ public:
* Descriptor to be valid.
*/
FieldDescriptor(Manager &mgr, Handle<Descriptor> parent,
- Handle<Type> primitiveType, std::string name = DEFAULT_FIELD_NAME,
+ Handle<Type> primitiveType,
+ std::string name = DEFAULT_FIELD_NAME,
bool optional = false);
/**
@@ -312,7 +312,8 @@ public:
*/
FieldDescriptor(Manager &mgr, Handle<Descriptor> parent = nullptr,
FieldType fieldType = FieldType::TREE,
- std::string name = DEFAULT_FIELD_NAME, bool optional = false);
+ std::string name = DEFAULT_FIELD_NAME,
+ bool optional = false);
/**
* Returns a const reference to the NodeVector of StructuredClasses whose
@@ -464,10 +465,9 @@ protected:
bool doValidate(Logger &logger) const override;
public:
- Descriptor(Manager &mgr, std::string name, Handle<Domain> domain,
- Handle<StructType> attributesDescriptor)
+ Descriptor(Manager &mgr, std::string name, Handle<Domain> domain)
: Node(mgr, std::move(name), domain),
- attributesDescriptor(acquire(attributesDescriptor)),
+ attributesDescriptor(acquire(new StructType(mgr, "", nullptr))),
fieldDescriptors(this)
{
}
@@ -485,17 +485,6 @@ public:
}
/**
- * Sets the StructType that specifies the attributes of this Descriptor.
- *
- * @param t some StructType.
- */
- void setAttributesDescriptor(Handle<StructType> t)
- {
- invalidate();
- attributesDescriptor = acquire(t);
- }
-
- /**
* Returns a const reference to the NodeVector of all FieldDescriptors of
* this Descriptor.
*
@@ -602,8 +591,7 @@ public:
*/
Rooted<FieldDescriptor> createFieldDescriptor(
FieldDescriptor::FieldType fieldType = FieldDescriptor::FieldType::TREE,
- std::string name = DEFAULT_FIELD_NAME,
- bool optional = false);
+ std::string name = DEFAULT_FIELD_NAME, bool optional = false);
/**
* This tries to construct the shortest possible path of this Descriptor
@@ -748,9 +736,6 @@ public:
* have at least one author. This is set to *
* per default, meaning that any number of
* of instances is valid, including zero.
- * @param attributesDescriptor is a StructType that specifies the attribute
- * keys as well as value domains for this
- * Descriptor.
* @param superclass references a parent StructuredClass. Please
* look for more information on inheritance in
* the class documentation above. The default is
@@ -767,7 +752,6 @@ public:
StructuredClass(Manager &mgr, std::string name,
Handle<Domain> domain = nullptr,
Variant cardinality = AnyCardinality,
- Handle<StructType> attributesDescriptor = nullptr,
Handle<StructuredClass> superclass = nullptr,
bool transparent = false, bool root = false);
@@ -793,10 +777,15 @@ public:
* This will also register this class as a subclass at the given superclass
* and unregister it at the previous superclass.
*
- * @parem sup some StructuredClass that shall be the new superclass of this
- * StructuredClass.
+ * It will also set the parent for this Descriptors AttributesDescriptor.
+ *
+ * @param sup some StructuredClass that shall be the new superclass of
+ * this StructuredClass.
+ * @param logger is some logger. Errors during setting the parent for this
+ * Descriptors AttributesDescriptor will be written into this
+ * logger.
*/
- void setSuperclass(Handle<StructuredClass> sup);
+ void setSuperclass(Handle<StructuredClass> sup, Logger &logger);
/**
* Returns true if this class is a subclass of the given class. It does not
@@ -832,16 +821,22 @@ public:
* on the given subclass.
*
* @param sc is some StructuredClass.
+ * @param logger is some logger. Errors during setting the parent for the
+ * new subclasses AttributesDescriptor will be written into
+ * this logger.
*/
- void addSubclass(Handle<StructuredClass> sc);
+ void addSubclass(Handle<StructuredClass> sc, Logger& logger);
/**
* Removes a subclass from this StructuredClass. This also calls
* setSuperclass(nullptr) on the given subclass.
*
* @param sc is some StructuredClass.
+ * @param logger is some logger. Errors during setting the parent for the
+ * removed subclasses AttributesDescriptor will be written
+ * into this logger.
*/
- void removeSubclass(Handle<StructuredClass> sc);
+ void removeSubclass(Handle<StructuredClass> sc, Logger& logger);
/**
* Returns a const reference to the NodeVector of all FieldDescriptors of
@@ -891,13 +886,8 @@ public:
* AnnotationClass.
* @param domain is the Domain this AnnotationClass belongs
* to.
- * @param attributesDescriptor is a StructType that specifies the attribute
- * keys as well as value domains for this
- * Descriptor.
*/
- AnnotationClass(Manager &mgr, std::string name, Handle<Domain> domain,
- // TODO: What would be a wise default value for attributes?
- Handle<StructType> attributesDescriptor = nullptr);
+ AnnotationClass(Manager &mgr, std::string name, Handle<Domain> domain);
};
/**
@@ -1004,9 +994,6 @@ public:
* have at least one author. This is set to *
* per default, meaning that any number of
* of instances is valid, including zero.
- * @param attributesDescriptor is a StructType that specifies the attribute
- * keys as well as value domains for this
- * Descriptor.
* @param superclass references a parent StructuredClass. Please
* look for more information on inheritance in
* the class documentation above. The default is
@@ -1024,7 +1011,6 @@ public:
*/
Rooted<StructuredClass> createStructuredClass(
std::string name, Variant cardinality = AnyCardinality,
- Handle<StructType> attributesDescriptor = nullptr,
Handle<StructuredClass> superclass = nullptr, bool transparent = false,
bool root = false);
@@ -1064,12 +1050,8 @@ public:
* @param name is a name for this AnnotationClass that will
* be used for later references to this
* AnnotationClass.
- * @param attributesDescriptor is a StructType that specifies the attribute
- * keys as well as value domains for this
- * Descriptor.
*/
- Rooted<AnnotationClass> createAnnotationClass(
- std::string name, Handle<StructType> attributesDescriptor = nullptr);
+ Rooted<AnnotationClass> createAnnotationClass(std::string name);
/**
* Returns a const reference to the NodeVector of TypeSystems that are
diff --git a/test/core/model/DocumentTest.cpp b/test/core/model/DocumentTest.cpp
index 5a2bcec..177f69b 100644
--- a/test/core/model/DocumentTest.cpp
+++ b/test/core/model/DocumentTest.cpp
@@ -123,7 +123,7 @@ TEST(Document, validate)
single.merge({1});
// Set up the "root" StructuredClass.
Rooted<StructuredClass> rootClass{new StructuredClass(
- mgr, "root", domain, single, {nullptr}, {nullptr}, false, true)};
+ mgr, "root", domain, single, {nullptr}, false, true)};
// set up a document for it.
{
@@ -177,8 +177,8 @@ TEST(Document, validate)
/*
* Add a further extension to the domain: We add a subclass to child.
*/
- Rooted<StructuredClass> childSubClass{new StructuredClass(
- mgr, "childSub", domain, single, {nullptr}, childClass)};
+ Rooted<StructuredClass> childSubClass{
+ new StructuredClass(mgr, "childSub", domain, single, childClass)};
{
/*
* A document with one instance of the Child subclass should be valid.
@@ -284,23 +284,19 @@ TEST(Document, validate)
ASSERT_EQ(ValidationState::UNKNOWN, doc->getValidationState());
ASSERT_TRUE(doc->validate(logger));
// add an attribute to the root, which should make it invalid.
- root->setAttributes({2});
+ root->setAttributes(Variant::mapType{{"bla", 2}});
ASSERT_EQ(ValidationState::UNKNOWN, doc->getValidationState());
ASSERT_FALSE(doc->validate(logger));
- // if we reset it to null it should be valid again
- root->setAttributes({});
+ // if we reset it to an empty map it should be valid again
+ root->setAttributes(Variant::mapType{});
ASSERT_EQ(ValidationState::UNKNOWN, doc->getValidationState());
ASSERT_TRUE(doc->validate(logger));
// let's set an attribute descriptor.
- Rooted<StructType> structType{StructType::createValidated(
- mgr, "attributes", nullptr, nullptr,
- NodeVector<Attribute>{
- new Attribute{mgr, "myAttr", sys->getStringType(), "default"}},
- logger)};
- childSubClass->setAttributesDescriptor(structType);
+ childSubClass->getAttributesDescriptor()->addAttribute(
+ new Attribute{mgr, "myAttr", sys->getStringType(), "default"},
+ logger);
// the right map content should be valid now.
- child->setAttributes(
- std::map<std::string, Variant>{{"myAttr", "content"}});
+ child->setAttributes(Variant::mapType{{"myAttr", "content"}});
ASSERT_EQ(ValidationState::UNKNOWN, doc->getValidationState());
ASSERT_TRUE(doc->validate(logger));
// but an empty map as well
diff --git a/test/core/model/DomainTest.cpp b/test/core/model/DomainTest.cpp
index 69c6694..8fcd21d 100644
--- a/test/core/model/DomainTest.cpp
+++ b/test/core/model/DomainTest.cpp
@@ -154,22 +154,22 @@ TEST(Descriptor, pathToAdvanced)
// Let's create the classes that we need first
Rooted<StructuredClass> A{new StructuredClass(
- mgr, "A", domain, AnyCardinality, {nullptr}, {nullptr}, false, true)};
+ mgr, "A", domain, AnyCardinality, {nullptr}, false, true)};
Rooted<StructuredClass> start{new StructuredClass(
- mgr, "start", domain, AnyCardinality, {nullptr}, A, false, false)};
+ mgr, "start", domain, AnyCardinality, A, false, false)};
Rooted<StructuredClass> B{new StructuredClass(
- mgr, "B", domain, AnyCardinality, {nullptr}, {nullptr}, true, false)};
+ mgr, "B", domain, AnyCardinality, {nullptr}, true, false)};
- Rooted<StructuredClass> C{new StructuredClass(
- mgr, "C", domain, AnyCardinality, {nullptr}, B, true, false)};
+ Rooted<StructuredClass> C{
+ new StructuredClass(mgr, "C", domain, AnyCardinality, B, true, false)};
Rooted<StructuredClass> D{new StructuredClass(
- mgr, "D", domain, AnyCardinality, {nullptr}, {nullptr}, true, false)};
+ mgr, "D", domain, AnyCardinality, {nullptr}, true, false)};
Rooted<StructuredClass> E{new StructuredClass(
- mgr, "E", domain, AnyCardinality, {nullptr}, {nullptr}, true, false)};
+ mgr, "E", domain, AnyCardinality, {nullptr}, true, false)};
Rooted<StructuredClass> target{
new StructuredClass(mgr, "target", domain, AnyCardinality)};
@@ -223,19 +223,19 @@ TEST(StructuredClass, isSubclassOf)
Rooted<SystemTypesystem> sys{new SystemTypesystem(mgr)};
Rooted<Domain> domain{new Domain(mgr, sys, "inheritance")};
Rooted<StructuredClass> A{new StructuredClass(
- mgr, "A", domain, AnyCardinality, {nullptr}, {nullptr}, false, true)};
+ mgr, "A", domain, AnyCardinality, {nullptr}, false, true)};
// first branch
Rooted<StructuredClass> B{
- new StructuredClass(mgr, "B", domain, AnyCardinality, {nullptr}, A)};
+ new StructuredClass(mgr, "B", domain, AnyCardinality, A)};
Rooted<StructuredClass> C{
- new StructuredClass(mgr, "C", domain, AnyCardinality, {nullptr}, B)};
+ new StructuredClass(mgr, "C", domain, AnyCardinality, B)};
// second branch
Rooted<StructuredClass> D{
- new StructuredClass(mgr, "D", domain, AnyCardinality, {nullptr}, A)};
+ new StructuredClass(mgr, "D", domain, AnyCardinality, A)};
Rooted<StructuredClass> E{
- new StructuredClass(mgr, "E", domain, AnyCardinality, {nullptr}, D)};
+ new StructuredClass(mgr, "E", domain, AnyCardinality, D)};
Rooted<StructuredClass> F{
- new StructuredClass(mgr, "F", domain, AnyCardinality, {nullptr}, D)};
+ new StructuredClass(mgr, "F", domain, AnyCardinality, D)};
// check function results
ASSERT_FALSE(A->isSubclassOf(A));
@@ -335,16 +335,16 @@ TEST(Domain, validate)
ASSERT_EQ(ValidationState::UNKNOWN, domain->getValidationState());
ASSERT_TRUE(domain->validate(logger));
// and still if we add a superclass.
- sub->setSuperclass(base);
+ sub->setSuperclass(base, logger);
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);
+ base->removeSubclass(sub, logger);
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);
+ base->addSubclass(sub, logger);
ASSERT_EQ(ValidationState::UNKNOWN, domain->getValidationState());
ASSERT_TRUE(domain->validate(logger));
ASSERT_EQ(base, sub->getSuperclass());
diff --git a/test/core/model/TestAdvanced.hpp b/test/core/model/TestAdvanced.hpp
index 3845676..2e4a541 100644
--- a/test/core/model/TestAdvanced.hpp
+++ b/test/core/model/TestAdvanced.hpp
@@ -56,7 +56,7 @@ static Rooted<Domain> constructHeadingDomain(Manager &mgr,
card.merge({0, 1});
// set up heading StructuredClass.
Rooted<StructuredClass> heading{new StructuredClass(
- mgr, "heading", domain, card, {nullptr}, {nullptr}, true)};
+ mgr, "heading", domain, card, {nullptr}, true)};
// as field want to copy the field of paragraph.
Rooted<StructuredClass> p = resolveDescriptor(bookDomain, "paragraph");
heading->copyFieldDescriptor(p->getFieldDescriptors()[0]);
@@ -86,7 +86,7 @@ static Rooted<Domain> constructListDomain(Manager &mgr,
Rooted<StructuredClass> p = resolveDescriptor(bookDomain, "paragraph");
// set up item StructuredClass;
Rooted<StructuredClass> item{new StructuredClass(
- mgr, "item", domain, AnyCardinality, {nullptr}, {nullptr}, false)};
+ mgr, "item", domain, AnyCardinality, {nullptr}, false)};
// as field we want to copy the field of paragraph.
item->copyFieldDescriptor(p->getFieldDescriptors()[0]);
@@ -94,7 +94,7 @@ static Rooted<Domain> constructListDomain(Manager &mgr,
std::vector<std::string> listTypes{"ol", "ul"};
for (auto &listType : listTypes) {
Rooted<StructuredClass> list{new StructuredClass(
- mgr, listType, domain, AnyCardinality, {nullptr}, p, false)};
+ mgr, listType, domain, AnyCardinality, p, false)};
Rooted<FieldDescriptor> list_field{new FieldDescriptor(mgr, list)};
list_field->addChild(item);
}
diff --git a/test/core/model/TestDomain.hpp b/test/core/model/TestDomain.hpp
index 88ab715..18c42bd 100644
--- a/test/core/model/TestDomain.hpp
+++ b/test/core/model/TestDomain.hpp
@@ -39,7 +39,7 @@ static Rooted<Domain> constructBookDomain(Manager &mgr,
// Set up the "book" node.
Rooted<StructuredClass> book{new StructuredClass(
- mgr, "book", domain, single, {nullptr}, {nullptr}, false, true)};
+ mgr, "book", domain, single, {nullptr}, false, true)};
// The structure field of it.
Rooted<FieldDescriptor> book_field{new FieldDescriptor(mgr, book)};
@@ -54,7 +54,7 @@ static Rooted<Domain> constructBookDomain(Manager &mgr,
// We also add the "paragraph", which is transparent.
Rooted<StructuredClass> paragraph{new StructuredClass(
- mgr, "paragraph", domain, AnyCardinality, {nullptr}, {nullptr}, true)};
+ mgr, "paragraph", domain, AnyCardinality, {nullptr}, true)};
section_field->addChild(paragraph);
book_field->addChild(paragraph);
@@ -76,7 +76,7 @@ static Rooted<Domain> constructBookDomain(Manager &mgr,
// Finally we add the "text" node, which is transparent as well.
Rooted<StructuredClass> text{new StructuredClass(
- mgr, "text", domain, AnyCardinality, {nullptr}, {nullptr}, true)};
+ mgr, "text", domain, AnyCardinality, {nullptr}, true)};
paragraph_field->addChild(text);
// ... and has a primitive field.
diff --git a/test/plugins/xml/XmlParserTest.cpp b/test/plugins/xml/XmlParserTest.cpp
index 0512fd0..647fc6d 100644
--- a/test/plugins/xml/XmlParserTest.cpp
+++ b/test/plugins/xml/XmlParserTest.cpp
@@ -74,6 +74,27 @@ TEST(XmlParser, generic)
#endif
}
+static void checkAttributes(Handle<StructType> expected,
+ Handle<Descriptor> desc)
+{
+ if (expected == nullptr) {
+ ASSERT_TRUE(desc->getAttributesDescriptor()->getAttributes().empty());
+ } else {
+ ASSERT_EQ(expected->getName(),
+ desc->getAttributesDescriptor()->getName());
+ auto &attrs_exp = expected->getAttributes();
+ auto &attrs = desc->getAttributesDescriptor()->getAttributes();
+ ASSERT_EQ(attrs_exp.size(), attrs.size());
+ for (size_t i = 0; i < attrs_exp.size(); i++) {
+ ASSERT_EQ(attrs_exp[i]->getName(), attrs[i]->getName());
+ ASSERT_EQ(attrs_exp[i]->getType(), attrs[i]->getType());
+ ASSERT_EQ(attrs_exp[i]->isOptional(), attrs[i]->isOptional());
+ ASSERT_EQ(attrs_exp[i]->getDefaultValue(),
+ attrs[i]->getDefaultValue());
+ }
+ }
+}
+
static void checkStructuredClass(
Handle<Node> n, const std::string &name, Handle<Domain> domain,
Variant cardinality = AnyCardinality,
@@ -89,7 +110,7 @@ static void checkStructuredClass(
ASSERT_EQ(cardinality, sc->getCardinality());
ASSERT_EQ(transparent, sc->isTransparent());
ASSERT_EQ(root, sc->hasRootPermission());
- ASSERT_EQ(attributesDescriptor, sc->getAttributesDescriptor());
+ checkAttributes(attributesDescriptor, sc);
}
static Rooted<StructuredClass> checkStructuredClass(
@@ -118,7 +139,7 @@ static void checkAnnotationClass(
ASSERT_FALSE(ac == nullptr);
ASSERT_EQ(name, ac->getName());
ASSERT_EQ(domain, ac->getParent());
- ASSERT_EQ(attributesDescriptor, ac->getAttributesDescriptor());
+ checkAttributes(attributesDescriptor, ac);
}
static Rooted<AnnotationClass> checkAnnotationClass(
@@ -191,8 +212,15 @@ TEST(XmlParser, domainParsing)
// get the book struct node.
Cardinality single;
single.merge({1});
+ Rooted<StructType> bookAuthor{
+ new StructType(book_domain->getManager(), "", nullptr)};
+ bookAuthor->addAttribute(
+ {new Attribute(book_domain->getManager(), "author",
+ env.project->getSystemTypesystem()->getStringType(),
+ "")},
+ logger);
Rooted<StructuredClass> book = checkStructuredClass(
- "book", "book", book_domain, single, nullptr, nullptr, false, true);
+ "book", "book", book_domain, single, bookAuthor, nullptr, false, true);
// get the chapter struct node.
Rooted<StructuredClass> chapter =
checkStructuredClass("chapter", "chapter", book_domain);
@@ -274,5 +302,12 @@ TEST(XmlParser, domainParsing)
// as should heading, because it references the paragraph default field.
checkFieldDescriptor(heading, paragraph, {text, comment});
}
+
+TEST(XmlParser, documentParsing)
+{
+ XmlStandaloneEnvironment env(logger);
+ Rooted<Node> book_domain_node =
+ env.parse("simple_book.oxd", "", "", RttiSet{&RttiTypes::Document});
+}
}
diff --git a/testdata/xmlparser/book_domain.oxm b/testdata/xmlparser/book_domain.oxm
index e02ec53..ed9309b 100644
--- a/testdata/xmlparser/book_domain.oxm
+++ b/testdata/xmlparser/book_domain.oxm
@@ -10,6 +10,9 @@
values. Also note that we need to specify explicitly, which classes
are allowed as root nodes. -->
<struct name="book" cardinality="{1}" isRoot="true">
+ <attributes>
+ <attribute name="author" type="string" default="''"/>
+ </attributes>
<!-- implicitly:
<struct name="book" cardinality="{1}" isRoot="true"
transparent="false" isa="" attributesDescriptor="">