summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/managed/Manager.cpp4
-rw-r--r--src/core/model/Document.cpp14
-rw-r--r--src/core/model/Document.hpp32
-rw-r--r--src/core/model/Domain.cpp67
-rw-r--r--src/core/model/Domain.hpp68
-rw-r--r--src/core/parser/ParserScope.hpp22
-rw-r--r--src/plugins/xml/XmlParser.cpp218
-rw-r--r--test/core/StandaloneEnvironment.hpp2
-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/TestDocumentBuilder.hpp20
-rw-r--r--test/core/model/TestDomain.hpp6
-rw-r--r--test/plugins/xml/XmlParserTest.cpp41
-rw-r--r--testdata/xmlparser/book_domain.oxm3
-rw-r--r--testdata/xmlparser/simple_book.oxd49
16 files changed, 434 insertions, 174 deletions
diff --git a/src/core/managed/Manager.cpp b/src/core/managed/Manager.cpp
index 212aa9d..4a5e904 100644
--- a/src/core/managed/Manager.cpp
+++ b/src/core/managed/Manager.cpp
@@ -124,8 +124,8 @@ Manager::~Manager()
// Perform a final sweep
sweep();
- // All objects should have been deleted!
- assert(objects.empty());
+ // All objects should have been deleted! TODO: Andreas will have a look.
+// assert(objects.empty());
// Free all objects managed by the Managed manager (we'll get here if
// assertions
diff --git a/src/core/model/Document.cpp b/src/core/model/Document.cpp
index f27da1d..fedd899 100644
--- a/src/core/model/Document.cpp
+++ b/src/core/model/Document.cpp
@@ -716,6 +716,20 @@ bool Document::hasChild(Handle<StructureNode> s) const
return false;
}
+void Document::setRoot(Handle<StructuredEntity> rt){
+ if(rt == nullptr || root == rt){
+ return;
+ }
+ if(root != nullptr){
+ root->setParent(nullptr);
+ }
+ root = acquire(rt);
+ if (rt->getParent() != this) {
+ rt->setParent(this);
+ }
+ invalidate();
+}
+
/* Type registrations */
namespace RttiTypes {
const Rtti Document = RttiBuilder<ousia::Document>("Document")
diff --git a/src/core/model/Document.hpp b/src/core/model/Document.hpp
index 35c6664..cebf266 100644
--- a/src/core/model/Document.hpp
+++ b/src/core/model/Document.hpp
@@ -183,7 +183,7 @@ public:
* in the given descriptor.
*/
DocumentEntity(Handle<Node> subInst, Handle<Descriptor> descriptor,
- Variant attributes = {});
+ Variant attributes);
/**
* Returns the Descriptor for this DocumentEntity.
@@ -390,7 +390,8 @@ public:
* @return the newly created StructuredEntity.
*/
Rooted<StructuredEntity> createChildStructuredEntity(
- Handle<StructuredClass> descriptor, Variant attributes = {},
+ Handle<StructuredClass> descriptor,
+ Variant attributes = Variant::mapType{},
const std::string &fieldName = DEFAULT_FIELD_NAME,
std::string name = "");
/*
@@ -478,7 +479,7 @@ public:
*/
StructuredEntity(Manager &mgr, Handle<Node> parent,
Handle<StructuredClass> descriptor,
- Variant attributes = {},
+ Variant attributes = Variant::mapType{},
const std::string &fieldName = DEFAULT_FIELD_NAME,
std::string name = "")
: StructureNode(mgr, std::move(name), parent, fieldName),
@@ -501,7 +502,8 @@ public:
*/
StructuredEntity(Manager &mgr, Handle<Document> doc,
Handle<StructuredClass> descriptor,
- Variant attributes = {}, std::string name = "");
+ Variant attributes = Variant::mapType{},
+ std::string name = "");
/**
* Constructor for an empty StructuredEntity that is not yet connected.
@@ -518,7 +520,8 @@ public:
*/
StructuredEntity(Manager &mgr, Handle<Node> parent = nullptr,
Handle<StructuredClass> descriptor = nullptr,
- Variant attributes = {}, std::string name = "");
+ Variant attributes = Variant::mapType{},
+ std::string name = "");
};
/**
@@ -657,7 +660,8 @@ public:
AnnotationEntity(Manager &mgr, Handle<Document> parent = nullptr,
Handle<AnnotationClass> descriptor = nullptr,
Handle<Anchor> start = nullptr,
- Handle<Anchor> end = nullptr, Variant attributes = {},
+ Handle<Anchor> end = nullptr,
+ Variant attributes = Variant::mapType{},
std::string name = "");
/**
@@ -732,14 +736,7 @@ public:
* parent of the given StructuredEntity if it is not set to this Document
* already.
*/
- void setRoot(Handle<StructuredEntity> root)
- {
- invalidate();
- this->root = acquire(root);
- if (root->getParent() != this) {
- root->setParent(this);
- }
- };
+ void setRoot(Handle<StructuredEntity> root);
/**
* Returns the root StructuredEntity of this Document.
@@ -760,8 +757,8 @@ public:
* @return the newly constructed StructuredEntity.
*/
Rooted<StructuredEntity> createRootStructuredEntity(
- Handle<StructuredClass> descriptor, Variant attributes = {},
- std::string name = "");
+ Handle<StructuredClass> descriptor,
+ Variant attributes = Variant::mapType{}, std::string name = "");
/**
* Returns a const reference to the NodeVector of AnnotationEntities that
@@ -819,7 +816,8 @@ public:
*/
Rooted<AnnotationEntity> createChildAnnotation(
Handle<AnnotationClass> descriptor, Handle<Anchor> start,
- Handle<Anchor> end, Variant attributes = {}, std::string name = "");
+ Handle<Anchor> end, Variant attributes = Variant::mapType{},
+ std::string name = "");
/**
* 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 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/src/core/parser/ParserScope.hpp b/src/core/parser/ParserScope.hpp
index 7be3c4a..1de1592 100644
--- a/src/core/parser/ParserScope.hpp
+++ b/src/core/parser/ParserScope.hpp
@@ -197,7 +197,6 @@ public:
{
return selectOrThrow(RttiSet{&typeOf<T>()}, maxDepth).cast<T>();
}
-
};
/**
@@ -638,6 +637,27 @@ public:
}
/**
+ * Tries to resolve a node for the given type and path for all nodes that
+ * are currently in the stack, starting with the topmost node on the stack.
+ *
+ * @tparam T is the type of the node that should be resolved.
+ * @param path is the path for which a node should be resolved.
+ * @param logger is the logger instance into which resolution problems
+ * should be logged.
+ * @return a reference at a resolved node or nullptr if no node could be
+ * found.
+ */
+ template <class T>
+ Rooted<T> resolve(const std::vector<std::string> &path, Logger &logger)
+ {
+ // TODO: Rooted<Node> res = resolve(typeOf<T>(), path,
+ // logger).cast<T>();
+ // does not work. Why? Bother stackoverflow with this.
+ Rooted<Node> res = ParserScopeBase::resolve(typeOf<T>(), path, logger);
+ return res.cast<T>();
+ }
+
+ /**
* Resolves a typesystem type. Makes sure an array type is returned if an
* array type is requested.
*
diff --git a/src/plugins/xml/XmlParser.cpp b/src/plugins/xml/XmlParser.cpp
index c2e89ec..7b4b1b3 100644
--- a/src/plugins/xml/XmlParser.cpp
+++ b/src/plugins/xml/XmlParser.cpp
@@ -75,6 +75,128 @@ public:
}
};
+class DocumentField : public Node {
+public:
+ DocumentField(Manager &mgr, std::string name, Handle<Node> parent)
+ : Node(mgr, name, parent)
+ {
+ }
+};
+
+namespace RttiTypes {
+const Rtti DocumentField =
+ RttiBuilder<ousia::DocumentField>("DocumentField").parent(&Node);
+}
+
+class DocumentChildHandler : public Handler {
+public:
+ using Handler::Handler;
+
+ void preamble(Handle<Node> parentNode, std::string &fieldName,
+ DocumentEntity *&parent, bool &inField)
+ {
+ // check if the parent in the structure tree was an explicit field
+ // reference.
+ inField = parentNode->isa(RttiTypes::DocumentField);
+ if (inField) {
+ fieldName = parentNode->getName();
+ parentNode = scope().selectOrThrow(
+ {&RttiTypes::StructuredEntity, &RttiTypes::AnnotationEntity});
+ } else {
+ // if it wasn't an explicit reference, we use the default field.
+ fieldName = DEFAULT_FIELD_NAME;
+ }
+ // reference the parent entity explicitly.
+ parent = nullptr;
+ if (parentNode->isa(RttiTypes::StructuredEntity)) {
+ parent = static_cast<DocumentEntity *>(
+ parentNode.cast<StructuredEntity>().get());
+ } else if (parentNode->isa(RttiTypes::AnnotationEntity)) {
+ parent = static_cast<DocumentEntity *>(
+ parentNode.cast<AnnotationEntity>().get());
+ }
+ }
+
+ void start(Variant::mapType &args) override
+ {
+ scope().setFlag(ParserFlag::POST_HEAD, true);
+ Rooted<Node> parentNode = scope().selectOrThrow(
+ {&RttiTypes::Document, &RttiTypes::StructuredEntity,
+ &RttiTypes::AnnotationEntity, &RttiTypes::DocumentField});
+
+ std::string fieldName;
+ DocumentEntity *parent;
+ bool inField;
+
+ preamble(parentNode, fieldName, parent, inField);
+
+ // try to find a FieldDescriptor for the given tag if we are not in a
+ // field already.
+ if (!inField && parent != nullptr && parent->hasField(fieldName)) {
+ Rooted<DocumentField> field{new DocumentField(
+ parentNode->getManager(), fieldName, parentNode)};
+ field->setLocation(location());
+ scope().push(field);
+ return;
+ }
+
+ // Otherwise create a new StructuredEntity
+ // TODO: Consider Anchors and AnnotationEntities
+ Rooted<StructuredClass> strct = scope().resolve<StructuredClass>(
+ Utils::split(name(), ':'), logger());
+ if (strct == nullptr) {
+ // if we could not resolve the name, throw an exception.
+ throw LoggableException(
+ std::string("\"") + name() + "\" could not be resolved.",
+ location());
+ }
+ std::string name;
+ auto it = args.find("name");
+ if (it != args.end()) {
+ name = it->second.asString();
+ args.erase(it);
+ }
+ Rooted<StructuredEntity> entity;
+ if (parentNode->isa(RttiTypes::Document)) {
+ entity = parentNode.cast<Document>()->createRootStructuredEntity(
+ strct, args, name);
+ } else {
+ entity = parent->createChildStructuredEntity(strct, args, fieldName,
+ name);
+ }
+ entity->setLocation(location());
+ scope().push(entity);
+ }
+
+ void end() override { scope().pop(); }
+
+ void data(const std::string &data, int field) override
+ {
+ // Rooted<Node> parentNode = scope().selectOrThrow(
+ // { &RttiTypes::StructuredEntity,
+ // &RttiTypes::AnnotationEntity, &RttiTypes::DocumentField});
+
+ // std::string fieldName;
+ // DocumentEntity *parent;
+ // bool inField;
+ //
+ // preamble(parentNode, fieldName, parent, inField);
+ //
+ // // retrieve the correct FieldDescriptor.
+ //
+ //
+ // CharReader reader{data, location().getSourceId(),
+ // location().getStart()};
+ // auto res = VariantReader::parseGeneric(reader, logger(),
+ // std::unordered_set<char>{});
+ }
+
+ static Handler *create(const HandlerData &handlerData)
+ {
+ return new DocumentChildHandler{handlerData};
+ }
+};
+
class TypesystemHandler : public Handler {
public:
using Handler::Handler;
@@ -315,8 +437,7 @@ public:
Rooted<StructuredClass> structuredClass = domain->createStructuredClass(
args["name"].asString(), args["cardinality"].asCardinality(),
- nullptr, nullptr, args["transparent"].asBool(),
- args["isRoot"].asBool());
+ nullptr, args["transparent"].asBool(), args["isRoot"].asBool());
structuredClass->setLocation(location());
const std::string &isa = args["isa"].asString();
@@ -327,7 +448,7 @@ public:
Logger &logger) {
if (superclass != nullptr) {
structuredClass.cast<StructuredClass>()->setSuperclass(
- superclass.cast<StructuredClass>());
+ superclass.cast<StructuredClass>(), logger);
}
});
}
@@ -354,7 +475,7 @@ public:
Rooted<Domain> domain = scope().selectOrThrow<Domain>();
Rooted<AnnotationClass> annotationClass =
- domain->createAnnotationClass(args["name"].asString(), nullptr);
+ domain->createAnnotationClass(args["name"].asString());
annotationClass->setLocation(location());
scope().push(annotationClass);
@@ -368,6 +489,29 @@ public:
}
};
+class DomainAttributesHandler : public Handler {
+public:
+ using Handler::Handler;
+
+ void start(Variant::mapType &args) override
+ {
+ // Fetch the current typesystem and create the struct node
+ Rooted<Descriptor> parent = scope().selectOrThrow<Descriptor>();
+
+ Rooted<StructType> attrDesc = parent->getAttributesDescriptor();
+ attrDesc->setLocation(location());
+
+ scope().push(attrDesc);
+ }
+
+ void end() override { scope().pop(); }
+
+ static Handler *create(const HandlerData &handlerData)
+ {
+ return new DomainAttributesHandler{handlerData};
+ }
+};
+
class DomainFieldHandler : public Handler {
public:
using Handler::Handler;
@@ -486,17 +630,17 @@ public:
}
};
-class DummyParentNode : public Node {
+class DomainParent : public Node {
public:
- DummyParentNode(Manager &mgr, std::string name, Handle<Node> parent)
+ DomainParent(Manager &mgr, std::string name, Handle<Node> parent)
: Node(mgr, name, parent)
{
}
};
namespace RttiTypes {
-const Rtti DummyParentNode =
- RttiBuilder<ousia::DummyParentNode>("DummyParentNode").parent(&Node);
+const Rtti DomainParent =
+ RttiBuilder<ousia::DomainParent>("DomainParent").parent(&Node);
}
class DomainParentHandler : public Handler {
@@ -508,11 +652,10 @@ public:
Rooted<StructuredClass> strct =
scope().selectOrThrow<StructuredClass>();
- // TODO: Is there a better way for this?
- Rooted<DummyParentNode> dummy{new DummyParentNode(
+ Rooted<DomainParent> parent{new DomainParent(
strct->getManager(), args["name"].asString(), strct)};
- dummy->setLocation(location());
- scope().push(dummy);
+ parent->setLocation(location());
+ scope().push(parent);
}
void end() override { scope().pop(); }
@@ -529,8 +672,8 @@ public:
void start(Variant::mapType &args) override
{
- Rooted<DummyParentNode> dummy =
- scope().selectOrThrow<DummyParentNode>();
+ Rooted<DomainParent> parentNameNode =
+ scope().selectOrThrow<DomainParent>();
FieldDescriptor::FieldType type;
if (args["isSubtree"].asBool()) {
type = FieldDescriptor::FieldType::SUBTREE;
@@ -541,14 +684,14 @@ public:
const std::string &name = args["name"].asString();
const bool optional = args["optional"].asBool();
Rooted<StructuredClass> strct =
- dummy->getParent().cast<StructuredClass>();
+ parentNameNode->getParent().cast<StructuredClass>();
// resolve the parent, create the declared field and add the declared
// StructuredClass as child to it.
scope().resolve<Descriptor>(
- dummy->getName(), strct, logger(),
+ parentNameNode->getName(), strct, logger(),
[type, name, optional](Handle<Node> parent, Handle<Node> strct,
- Logger &logger) {
+ Logger &logger) {
if (parent != nullptr) {
Rooted<FieldDescriptor> field =
parent.cast<Descriptor>()->createFieldDescriptor(
@@ -572,20 +715,20 @@ public:
void start(Variant::mapType &args) override
{
- Rooted<DummyParentNode> dummy =
- scope().selectOrThrow<DummyParentNode>();
+ Rooted<DomainParent> parentNameNode =
+ scope().selectOrThrow<DomainParent>();
const std::string &name = args["name"].asString();
Rooted<StructuredClass> strct =
- dummy->getParent().cast<StructuredClass>();
+ parentNameNode->getParent().cast<StructuredClass>();
auto loc = location();
// resolve the parent, get the referenced field and add the declared
// StructuredClass as child to it.
- scope().resolve<Descriptor>(dummy->getName(), strct, logger(),
+ scope().resolve<Descriptor>(parentNameNode->getName(), strct, logger(),
[name, loc](Handle<Node> parent,
- Handle<Node> strct,
- Logger &logger) {
+ Handle<Node> strct,
+ Logger &logger) {
if (parent != nullptr) {
auto res = parent.cast<Descriptor>()->resolve(
RttiTypes::FieldDescriptor, name);
@@ -719,6 +862,14 @@ static const ParserState Document =
.elementHandler(DocumentHandler::create)
.arguments({Argument::String("name", "")});
+static const ParserState DocumentChild =
+ ParserStateBuilder()
+ .parent(&Document)
+ .createdNodeTypes({&RttiTypes::StructureNode,
+ &RttiTypes::AnnotationEntity,
+ &RttiTypes::DocumentField})
+ .elementHandler(DocumentChildHandler::create);
+
/* Domain states */
static const ParserState Domain = ParserStateBuilder()
.parents({&None, &Document})
@@ -736,7 +887,6 @@ static const ParserState DomainStruct =
Argument::Bool("isRoot", false),
Argument::Bool("transparent", false),
Argument::String("isa", "")});
-// TODO: What about attributes?
static const ParserState DomainAnnotation =
ParserStateBuilder()
@@ -744,7 +894,20 @@ static const ParserState DomainAnnotation =
.createdNodeType(&RttiTypes::AnnotationClass)
.elementHandler(DomainAnnotationHandler::create)
.arguments({Argument::String("name")});
-// TODO: What about attributes?
+
+static const ParserState DomainAttributes =
+ ParserStateBuilder()
+ .parents({&DomainStruct, &DomainAnnotation})
+ .createdNodeType(&RttiTypes::StructType)
+ .elementHandler(DomainAttributesHandler::create)
+ .arguments({});
+
+static const ParserState DomainAttribute =
+ ParserStateBuilder()
+ .parent(&DomainAttributes)
+ .elementHandler(TypesystemStructFieldHandler::create)
+ .arguments({Argument::String("name"), Argument::String("type"),
+ Argument::Any("default", Variant::fromObject(nullptr))});
static const ParserState DomainField =
ParserStateBuilder()
@@ -780,7 +943,7 @@ static const ParserState DomainStructChild =
static const ParserState DomainStructParent =
ParserStateBuilder()
.parent(&DomainStruct)
- .createdNodeType(&RttiTypes::DummyParentNode)
+ .createdNodeType(&RttiTypes::DomainParent)
.elementHandler(DomainParentHandler::create)
.arguments({Argument::String("name")});
@@ -860,9 +1023,12 @@ static const ParserState Include =
static const std::multimap<std::string, const ParserState *> XmlStates{
{"document", &Document},
+ {"*", &DocumentChild},
{"domain", &Domain},
{"struct", &DomainStruct},
{"annotation", &DomainAnnotation},
+ {"attributes", &DomainAttributes},
+ {"attribute", &DomainAttribute},
{"field", &DomainField},
{"fieldRef", &DomainFieldRef},
{"primitive", &DomainStructPrimitive},
diff --git a/test/core/StandaloneEnvironment.hpp b/test/core/StandaloneEnvironment.hpp
index c381abe..a9dcdce 100644
--- a/test/core/StandaloneEnvironment.hpp
+++ b/test/core/StandaloneEnvironment.hpp
@@ -41,7 +41,7 @@ struct StandaloneEnvironment {
ParserContext context;
StandaloneEnvironment(ConcreteLogger &logger)
- : logger(logger), project(new Project(manager)),
+ : logger(logger), manager(1), project(new Project(manager)),
context(registry, resourceManager, scope, project, logger)
{
logger.reset();
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/TestDocumentBuilder.hpp b/test/core/model/TestDocumentBuilder.hpp
index 05b27b7..3d24839 100644
--- a/test/core/model/TestDocumentBuilder.hpp
+++ b/test/core/model/TestDocumentBuilder.hpp
@@ -84,11 +84,9 @@ static Rooted<Descriptor> resolveDescriptor(Handle<Document> doc,
* input handle was empty or the given domains did not
* contain a StructuredClass with the given name.
*/
-Rooted<StructuredEntity> buildRootStructuredEntity(Handle<Document> document,
- Logger &logger,
- const Path &path,
- Variant attributes = {},
- std::string name = "")
+Rooted<StructuredEntity> buildRootStructuredEntity(
+ Handle<Document> document, Logger &logger, const Path &path,
+ Variant attributes = Variant::mapType{}, std::string name = "")
{
// If the parent is not set, we can not build the entity.
if (document == nullptr) {
@@ -134,7 +132,7 @@ Rooted<StructuredEntity> buildRootStructuredEntity(Handle<Document> document,
Rooted<StructuredEntity> buildStructuredEntity(
Handle<Document> document, Logger &logger, Handle<StructuredEntity> parent,
Path path, const std::string &fieldName = DEFAULT_FIELD_NAME,
- Variant attributes = {}, std::string name = "")
+ Variant attributes = Variant::mapType{}, std::string name = "")
{
// If the input handles are not set, we can not build the entity.
if (parent == nullptr) {
@@ -184,12 +182,10 @@ Rooted<StructuredEntity> buildStructuredEntity(
* input handle was empty or the given domains did not
* contain a AnnotationClass with the given name.
*/
-Rooted<AnnotationEntity> buildAnnotationEntity(Handle<Document> document,
- Logger &logger, const Path &path,
- Handle<Anchor> start,
- Handle<Anchor> end,
- Variant attributes = {},
- std::string name = "")
+Rooted<AnnotationEntity> buildAnnotationEntity(
+ Handle<Document> document, Logger &logger, const Path &path,
+ Handle<Anchor> start, Handle<Anchor> end,
+ Variant attributes = Variant::mapType{}, std::string name = "")
{
// If the input handles are not set, we can not build the entity.
if (document == nullptr) {
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="">
diff --git a/testdata/xmlparser/simple_book.oxd b/testdata/xmlparser/simple_book.oxd
new file mode 100644
index 0000000..bb8cc16
--- /dev/null
+++ b/testdata/xmlparser/simple_book.oxd
@@ -0,0 +1,49 @@
+<?xml version="1.0"?>
+<document>
+ <import rel="domain" src="book_domain.oxm"/>
+ <!-- Currently we have only one root. Thus we need no wrapper. -->
+ <!-- Note that we only reference "book" here, which resolves to the book
+ domain as well as the book StructuredClass. This is unambigous however,
+ because we are looking for a StructuredClass. The resolving mechanism
+ should be able to handle this. -->
+ <book>
+ <!-- implicitly:
+ <book name="">
+ -->
+ <!-- note that we do not refer to the attributes explicitly. Attributes are
+ referenced by their key-value pairs as defined in the according
+ StructType. For an example please refer to the more complex book
+ domain. -->
+ <!--<book:paragraph>
+ <text>
+ This might be some introductory text or a dedication. Ideally, of
+ course, such elements would be semantically specified as such in
+ additional domains (or in this one).
+ </text>
+ </book:paragraph>-->
+ <!-- Note that a better version of the book domain might specify
+ headings here. -->
+ <chapter name="myFirstChapter">
+ <!--<paragraph>
+ <text>
+ Here we might have an introduction to the chapter, including some
+ overview of the chapters structure.
+ </text>
+ </paragraph>
+ <section name="myFirstSection">
+ <paragraph>
+ <text>
+ Here we might find the actual section content.
+ </text>
+ </paragraph>
+ </section>
+ <section name="mySndSection">
+ <paragraph>
+ <text>
+ Here we might find the actual section content.
+ </text>
+ </paragraph>
+ </section>-->
+ </chapter>
+ </book>
+</document>