diff options
| author | Benjamin Paassen <bpaassen@techfak.uni-bielefeld.de> | 2015-01-15 12:13:18 +0100 | 
|---|---|---|
| committer | Benjamin Paassen <bpaassen@techfak.uni-bielefeld.de> | 2015-01-15 12:13:18 +0100 | 
| commit | 496c4e527852d0fd64a24bd5ac2506e50ba0afc7 (patch) | |
| tree | dfcd496dd09e203849d0c4a557f48f355fbfc9c4 | |
| parent | 86885e5a63c10d264bac822cb054607c27c0f734 (diff) | |
supported more automatic registration behaviour, checked for internal name consistency regarding FieldDescriptors, AnnotationClasses and StructuredClasses and made adding methods for automatically registered references protected.
| -rw-r--r-- | src/core/model/Document.cpp | 26 | ||||
| -rw-r--r-- | src/core/model/Document.hpp | 30 | ||||
| -rw-r--r-- | src/core/model/Domain.cpp | 117 | ||||
| -rw-r--r-- | src/core/model/Domain.hpp | 99 | ||||
| -rw-r--r-- | test/core/model/DomainTest.cpp | 36 | ||||
| -rw-r--r-- | test/core/model/TestAdvanced.hpp | 24 | ||||
| -rw-r--r-- | test/core/model/TestDocumentBuilder.hpp | 2 | ||||
| -rw-r--r-- | test/core/model/TestDomain.hpp | 17 | 
8 files changed, 197 insertions, 154 deletions
| diff --git a/src/core/model/Document.cpp b/src/core/model/Document.cpp index 022b91c..eca24e7 100644 --- a/src/core/model/Document.cpp +++ b/src/core/model/Document.cpp @@ -58,7 +58,8 @@ int DocumentEntity::getFieldDescriptorIndex(const std::string &fieldName,  		}  	}  	if (enforce) { -		throw OusiaException("No field for the given name exists!"); +		throw OusiaException(descriptor->getName() + +		                     " has no field with name " + fieldName);  	} else {  		return -1;  	} @@ -80,15 +81,27 @@ int DocumentEntity::getFieldDescriptorIndex(  		f++;  	}  	if (enforce) { -		throw OusiaException( -		    "The given FieldDescriptor is not specified in the Descriptor of " -		    "this " -		    "node."); +		throw OusiaException(descriptor->getName() + +		                     " has no field with name " + +		                     fieldDescriptor->getName());  	} else {  		return -1;  	}  } +/* Class AnnotationEntity */ + +AnnotationEntity::AnnotationEntity(Manager &mgr, Handle<Document> parent, +                 Handle<AnnotationClass> descriptor, Handle<Anchor> start, +                 Handle<Anchor> end, Variant attributes, std::string name) +    : Node(mgr, std::move(name), parent), +      DocumentEntity(this, descriptor, attributes), +      start(acquire(start)), +      end(acquire(end)) +{ +	parent->annotations.push_back(this); +} +  /* Class Document */  void Document::continueResolve(ResolutionState &state) @@ -109,8 +122,7 @@ const Rtti<model::Document> Document =  const Rtti<model::StructureNode> StructureNode =      RttiBuilder("StructureNode").parent(&Node);  const Rtti<model::AnnotationEntity> AnnotationEntity = -    RttiBuilder("AnnotationEntity").parent(&Node).composedOf( -        &StructureNode); +    RttiBuilder("AnnotationEntity").parent(&Node).composedOf(&StructureNode);  const Rtti<model::StructuredEntity> StructuredEntity =      RttiBuilder("StructuredEntity").parent(&StructureNode).composedOf(          {&StructureNode}); diff --git a/src/core/model/Document.hpp b/src/core/model/Document.hpp index 357b752..15a5ec8 100644 --- a/src/core/model/Document.hpp +++ b/src/core/model/Document.hpp @@ -427,7 +427,9 @@ public:  	 * The constructor for an AnnotationEntity.  	 *  	 * @param mgr        is the Manager instance. -	 * @param parent     is the Document this AnnotationEntity is part of. +	 * @param parent     is the Document this AnnotationEntity is part of. The +	 *                   constructor will automatically register this +	 *                   AnnotationEntity at that document.  	 * @param descriptor is the AnnotationClass of this AnnotationEntity.  	 * @param start      is the start Anchor of this AnnotationEntity. It has to  	 *                   be part of the Document given as parent. @@ -441,13 +443,7 @@ public:  	AnnotationEntity(Manager &mgr, Handle<Document> parent,  	                 Handle<AnnotationClass> descriptor, Handle<Anchor> start,  	                 Handle<Anchor> end, Variant attributes = {}, -	                 std::string name = "") -	    : Node(mgr, std::move(name), parent), -	      DocumentEntity(this, descriptor, attributes), -	      start(acquire(start)), -	      end(acquire(end)) -	{ -	} +	                 std::string name = "");  	/**  	 * Returns the start Anchor of this AnnotationEntity. @@ -470,6 +466,9 @@ public:   * document and the AnnotationEntities that span over Anchors in this Document.   */  class Document : public Node { + +friend AnnotationEntity; +  private:  	// TODO: Might there be several roots? E.g. metadata?  	Owned<StructuredEntity> root; @@ -511,21 +510,6 @@ public:  	}  	/** -	 * Adds an AnnotationEntity to this document. The Anchors used as start and -	 * end of this AnnotationEntity have to be part of this document. -	 */ -	void addAnnotation(Handle<AnnotationEntity> a) { annotations.push_back(a); } -	/** -	 * Adds multiple AnnotationEntities to this document. The Anchors used as -	 * start and end of these AnnotationEntities have to be part of this -	 * document. -	 */ -	void addAnnotations(const std::vector<Handle<AnnotationEntity>> &as) -	{ -		annotations.insert(annotations.end(), as.begin(), as.end()); -	} - -	/**  	 * Returns a const reference to the NodeVector of Domains that are used  	 * within this Document.  	 * diff --git a/src/core/model/Domain.cpp b/src/core/model/Domain.cpp index be9aa05..f1b91cc 100644 --- a/src/core/model/Domain.cpp +++ b/src/core/model/Domain.cpp @@ -26,8 +26,48 @@  namespace ousia {  namespace model { +template <class T> +static void checkUniqueName(Handle<Node> parent, NodeVector<T> vec, +                            Handle<T> child, +                            const std::string &parentClassName, +                            const std::string &childClassName) +{ +	std::set<std::string> childNames; +	for (auto &c : vec) { +		childNames.insert(c->getName()); +	} +	if (childNames.find(child->getName()) != childNames.end()) { +		throw OusiaException(std::string("The ") + parentClassName + " " + +		                     parent->getName() + " already has a " + +		                     childClassName + " with name " + child->getName()); +	} +} +  /* Class FieldDescriptor */ +FieldDescriptor::FieldDescriptor(Manager &mgr, Handle<Descriptor> parent, +                                 Handle<Type> primitiveType, std::string name, +                                 bool optional) +    : Node(mgr, std::move(name), parent), +      children(this), +      fieldType(FieldType::PRIMITIVE), +      primitiveType(acquire(primitiveType)), +      optional(optional) +{ +	parent->addFieldDescriptor(this); +} + +FieldDescriptor::FieldDescriptor(Manager &mgr, Handle<Descriptor> parent, +                                 FieldType fieldType, std::string name, +                                 bool optional) +    : Node(mgr, std::move(name), parent), +      children(this), +      fieldType(fieldType), +      optional(optional) +{ +	parent->addFieldDescriptor(this); +} +  /* Class Descriptor */  void Descriptor::continueResolve(ResolutionState &state) @@ -41,6 +81,13 @@ void Descriptor::continueResolve(ResolutionState &state)  	                         state);  } +void Descriptor::addFieldDescriptor(Handle<FieldDescriptor> fd) +{ +	checkUniqueName(this, fieldDescriptors, fd, "Descriptor", +	                "FieldDescriptor"); +	fieldDescriptors.push_back(fd); +} +  std::vector<Rooted<Node>> Descriptor::pathTo(      Handle<StructuredClass> target) const  { @@ -111,8 +158,8 @@ bool Descriptor::continuePath(Handle<StructuredClass> target,  	if (isa(RttiTypes::StructuredClass)) {  		const StructuredClass *tis = static_cast<const StructuredClass *>(this);  		/* -		 * if this is a StructuredClass, we can also use the super class (at -		 * least for fields that are not overridden) +		 * if this is a StructuredClass, we can also use the super class +		 * (at least for fields that are not overridden)  		 */  		if (exploreSuperclass && !tis->getIsA().isNull()) {  			// copy the path. @@ -148,6 +195,60 @@ bool Descriptor::continuePath(Handle<StructuredClass> target,  	return found;  } +void Descriptor::copyFieldDescriptor(Handle<FieldDescriptor> fd) +{ +	if (fd->getFieldType() == FieldDescriptor::FieldType::PRIMITIVE) { +		/* +		 *To call the "new" operation is enough here, because the +		 * constructor will add the newly constructed FieldDescriptor to this +		 * Descriptor automatically. +		 */ +		new FieldDescriptor(getManager(), this, +		                                       fd->getPrimitiveType(), +		                                       fd->getName(), fd->optional); +	} else { +		new FieldDescriptor(getManager(), this, +		                                       fd->getFieldType(), +		                                       fd->getName(), fd->optional); +	} +} + +/* Class StructuredClass */ + +StructuredClass::StructuredClass(Manager &mgr, std::string name, +                                 Handle<Domain> domain, +                                 const Cardinality &cardinality, +                                 Handle<StructType> attributesDescriptor, +                                 Handle<StructuredClass> isa, bool transparent, +                                 bool root) +    : Descriptor(mgr, std::move(name), domain, attributesDescriptor), +      cardinality(cardinality), +      isa(acquire(isa)), +      subclasses(this), +      transparent(transparent), +      root(root) +{ +	if (!isa.isNull()) { +		isa->subclasses.push_back(this); +	} +	if (!domain.isNull()) { +		domain->addStructuredClass(this); +	} +} + +/* 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) +{ +	if (!domain.isNull()) { +		domain->addAnnotationClass(this); +	} +} +  /* Class Domain */  void Domain::continueResolve(ResolutionState &state) @@ -159,6 +260,18 @@ void Domain::continueResolve(ResolutionState &state)  		continueResolveReferences(typesystems, state);  	}  } + +void Domain::addStructuredClass(Handle<StructuredClass> s) +{ +	checkUniqueName(this, structuredClasses, s, "Domain", "StructuredClass"); +	structuredClasses.push_back(s); +} + +void Domain::addAnnotationClass(Handle<AnnotationClass> a) +{ +	checkUniqueName(this, annotationClasses, a, "Domain", "AnnotationClass"); +	annotationClasses.push_back(a); +}  }  /* Type registrations */ diff --git a/src/core/model/Domain.hpp b/src/core/model/Domain.hpp index 4b26917..791d563 100644 --- a/src/core/model/Domain.hpp +++ b/src/core/model/Domain.hpp @@ -292,14 +292,7 @@ public:  	 */  	FieldDescriptor(Manager &mgr, Handle<Descriptor> parent,  	                Handle<Type> primitiveType, std::string name = "", -	                bool optional = false) -	    : Node(mgr, std::move(name), parent), -	      children(this), -	      fieldType(FieldType::PRIMITIVE), -	      primitiveType(acquire(primitiveType)), -	      optional(optional) -	{ -	} +	                bool optional = false);  	/**  	 * This is the constructor for non-primitive fields. You have to provide @@ -318,13 +311,7 @@ public:  	 */  	FieldDescriptor(Manager &mgr, Handle<Descriptor> parent,  	                FieldType fieldType = FieldType::TREE, -	                std::string name = "", bool optional = false) -	    : Node(mgr, std::move(name), parent), -	      children(this), -	      fieldType(fieldType), -	      optional(optional) -	{ -	} +	                std::string name = "", bool optional = false);  	/**  	 * Returns a const reference to the NodeVector of StructuredClasses whose @@ -389,6 +376,9 @@ public:   *   */  class Descriptor : public Node { + +friend FieldDescriptor; +  private:  	Owned<StructType> attributesDescriptor;  	NodeVector<FieldDescriptor> fieldDescriptors; @@ -401,6 +391,11 @@ private:  protected:  	void continueResolve(ResolutionState &state) override; +	 +	/** +	 * Adds a FieldDescriptor and checks for name uniqueness. +	 */ +	void addFieldDescriptor(Handle<FieldDescriptor> fd);  public:  	Descriptor(Manager &mgr, std::string name, Handle<Domain> domain, @@ -436,20 +431,11 @@ public:  	}  	/** -	 * Adds a FieldDescriptor to this Descriptor. +	 * Copies a FieldDescriptor that belongs to another Descriptor to this +	 * Descriptor. This will throw an exception if a FieldDescriptor with the +	 * given name already exists.  	 */ -	void addFieldDescriptor(Handle<FieldDescriptor> fd) -	{ -		fieldDescriptors.push_back(fd); -	} - -	/** -	 * Adds multiple FieldDescriptors to this Descriptor. -	 */ -	void addFieldDescriptors(const std::vector<Handle<FieldDescriptor>> &fds) -	{ -		fieldDescriptors.insert(fieldDescriptors.end(), fds.begin(), fds.end()); -	} +	void copyFieldDescriptor(Handle<FieldDescriptor> fd);  	/**  	 * This tries to construct the shortest possible path of this Descriptor @@ -600,18 +586,7 @@ public:  	                Handle<StructType> attributesDescriptor = nullptr,  	                // TODO: What would be a wise default value for isa?  	                Handle<StructuredClass> isa = nullptr, -	                bool transparent = false, bool root = false) -	    : Descriptor(mgr, std::move(name), domain, attributesDescriptor), -	      cardinality(cardinality), -	      isa(acquire(isa)), -	      subclasses(this), -	      transparent(transparent), -	      root(root) -	{ -		if (!isa.isNull()) { -			isa->subclasses.push_back(this); -		} -	} +	                bool transparent = false, bool root = false);  	/**  	 * Returns the Cardinality of this StructuredClass (as a RangeSet). @@ -672,10 +647,7 @@ public:  	 */  	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) -	{ -	} +	                Handle<StructType> attributesDescriptor = nullptr);  };  /** @@ -684,6 +656,10 @@ public:   * to certain Structures?   */  class Domain : public Node { + +friend StructuredClass; +friend AnnotationClass; +  private:  	NodeVector<StructuredClass> structuredClasses;  	NodeVector<AnnotationClass> annotationClasses; @@ -694,6 +670,9 @@ private:  protected:  	void continueResolve(ResolutionState &state) override; +	void addStructuredClass(Handle<StructuredClass> s); +	void addAnnotationClass(Handle<AnnotationClass> a); +  public:  	/**  	 * The constructor for a new domain. Note that this is an empty Domain and @@ -726,22 +705,6 @@ public:  	}  	/** -	 * Adds a StructuredClass to this Domain. -	 */ -	void addStructuredClass(Handle<StructuredClass> s) -	{ -		structuredClasses.push_back(s); -	} - -	/** -	 * Adds multiple StructuredClasses to this Domain. -	 */ -	void addStructuredClasses(const std::vector<Handle<StructuredClass>> &ss) -	{ -		structuredClasses.insert(structuredClasses.end(), ss.begin(), ss.end()); -	} - -	/**  	 * Returns a const reference to the NodeVector of AnnotationClasses that are  	 * part of this Domain.  	 * @@ -754,22 +717,6 @@ public:  	}  	/** -	 * Adds an AnnotationClass to this Domain. -	 */ -	void addAnnotationClass(Handle<AnnotationClass> a) -	{ -		annotationClasses.push_back(a); -	} - -	/** -	 * Adds multiple AnnotationClasses to this Domain. -	 */ -	void addAnnotationClasses(const std::vector<Handle<AnnotationClass>> &as) -	{ -		annotationClasses.insert(annotationClasses.end(), as.begin(), as.end()); -	} - -	/**  	 * 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 af00151..772130c 100644 --- a/test/core/model/DomainTest.cpp +++ b/test/core/model/DomainTest.cpp @@ -158,55 +158,55 @@ TEST(Descriptor, pathToAdvanced)  	// Let's create the classes that we need first  	Rooted<StructuredClass> A{new StructuredClass(  	    mgr, "A", domain, any, {nullptr}, {nullptr}, false, true)}; -	domain->addStructuredClass(A); +  	Rooted<StructuredClass> start{new StructuredClass(  	    mgr, "start", domain, any, {nullptr}, A, false, false)}; -	domain->addStructuredClass(start); +  	Rooted<StructuredClass> B{new StructuredClass(  	    mgr, "B", domain, any, {nullptr}, {nullptr}, true, false)}; -	domain->addStructuredClass(B); +  	Rooted<StructuredClass> C{  	    new StructuredClass(mgr, "C", domain, any, {nullptr}, B, true, false)}; -	domain->addStructuredClass(C); +  	Rooted<StructuredClass> D{new StructuredClass(  	    mgr, "D", domain, any, {nullptr}, {nullptr}, true, false)}; -	domain->addStructuredClass(D); +  	Rooted<StructuredClass> E{new StructuredClass(  	    mgr, "E", domain, any, {nullptr}, {nullptr}, true, false)}; -	domain->addStructuredClass(E); +  	Rooted<StructuredClass> target{  	    new StructuredClass(mgr, "target", domain, any)}; -	domain->addStructuredClass(target); +  	// We create two fields for A  	Rooted<FieldDescriptor> A_field{new FieldDescriptor(mgr, A)}; -	A->addFieldDescriptor(A_field); +  	A_field->addChild(target);  	Rooted<FieldDescriptor> A_field2{new FieldDescriptor(  	    mgr, A, FieldDescriptor::FieldType::SUBTREE, "second")}; -	A->addFieldDescriptor(A_field2); +  	A_field2->addChild(B);  	// We create no field for B  	// One for C  	Rooted<FieldDescriptor> C_field{new FieldDescriptor(mgr, C)}; -	C->addFieldDescriptor(C_field); +  	C_field->addChild(target);  	// one for start  	Rooted<FieldDescriptor> start_field{new FieldDescriptor(mgr, start)}; -	start->addFieldDescriptor(start_field); +  	start_field->addChild(D);  	// One for D  	Rooted<FieldDescriptor> D_field{new FieldDescriptor(mgr, D)}; -	D->addFieldDescriptor(D_field); +  	D_field->addChild(E);  	// One for E  	Rooted<FieldDescriptor> E_field{new FieldDescriptor(mgr, E)}; -	E->addFieldDescriptor(E_field); +  	E_field->addChild(target); -	 -	#ifdef MANAGER_GRAPHVIZ_EXPORT -		// dump the manager state -		mgr.exportGraphviz("nastyDomain.dot"); -	#endif + +#ifdef MANAGER_GRAPHVIZ_EXPORT +	// dump the manager state +	mgr.exportGraphviz("nastyDomain.dot"); +#endif  	// and now we should be able to find the shortest path as suggested  	std::vector<Rooted<Node>> path = start->pathTo(target); diff --git a/test/core/model/TestAdvanced.hpp b/test/core/model/TestAdvanced.hpp index 696fbed..15a4042 100644 --- a/test/core/model/TestAdvanced.hpp +++ b/test/core/model/TestAdvanced.hpp @@ -58,11 +58,9 @@ static Rooted<Domain> constructHeadingDomain(Manager &mgr,  	// set up heading StructuredClass.  	Rooted<StructuredClass> heading{new StructuredClass(  	    mgr, "heading", domain, card, {nullptr}, {nullptr}, true)}; -	// as field we actually want to refer to the field of paragraph. +	// as field want to copy the field of paragraph.  	Rooted<StructuredClass> p = resolveDescriptor(bookDomain, "paragraph"); -	heading->addFieldDescriptor(p->getFieldDescriptors()[0]); -	// add the class to the domain. -	domain->addStructuredClass(heading); +	heading->copyFieldDescriptor(p->getFieldDescriptors()[0]);  	// create a new field for headings in each section type.  	std::vector<std::string> secclasses{"book", "section", "subsection",  	                                    "paragraph"}; @@ -71,7 +69,6 @@ static Rooted<Domain> constructHeadingDomain(Manager &mgr,  		Rooted<FieldDescriptor> heading_field{new FieldDescriptor(  		    mgr, desc, FieldDescriptor::FieldType::SUBTREE, "heading")};  		heading_field->addChild(heading); -		desc->addFieldDescriptor(heading_field);  	}  	return domain;  } @@ -94,9 +91,9 @@ static Rooted<Domain> constructListDomain(Manager &mgr,  	// set up item StructuredClass;  	Rooted<StructuredClass> item{new StructuredClass(  	    mgr, "item", domain, any, {nullptr}, {nullptr}, false)}; -	domain->addStructuredClass(item); -	// as field we actually want to refer to the field of paragraph. -	item->addFieldDescriptor(p->getFieldDescriptors()[0]); + +	// as field we want to copy the field of paragraph. +	item->copyFieldDescriptor(p->getFieldDescriptors()[0]);  	// set up list StructuredClasses.  	std::vector<std::string> listTypes{"ol", "ul"};  	for (auto &listType : listTypes) { @@ -104,8 +101,6 @@ static Rooted<Domain> constructListDomain(Manager &mgr,  		    mgr, listType, domain, any, {nullptr}, p, false)};  		Rooted<FieldDescriptor> list_field{new FieldDescriptor(mgr, list)};  		list_field->addChild(item); -		list->addFieldDescriptor(list_field); -		domain->addStructuredClass(list);  	}  	return domain;  } @@ -121,11 +116,11 @@ static Rooted<Domain> constructEmphasisDomain(Manager &mgr,  	Rooted<Domain> domain{new Domain(mgr, sys, "emphasis")};  	// create AnnotationClasses  	Rooted<AnnotationClass> em{ -	    new AnnotationClass(mgr, "emphasized", domain, {nullptr})}; -	domain->addAnnotationClass(em); +	    new AnnotationClass(mgr, "emphasized", domain)}; +  	Rooted<AnnotationClass> strong{ -	    new AnnotationClass(mgr, "strong", domain, {nullptr})}; -	domain->addAnnotationClass(strong); +	    new AnnotationClass(mgr, "strong", domain)}; +  	return domain;  } @@ -338,4 +333,3 @@ static Rooted<Document> constructAdvancedDocument(Manager &mgr, Logger &logger,  }  #endif /* _TEST_DOCUMENT_HPP_ */ - diff --git a/test/core/model/TestDocumentBuilder.hpp b/test/core/model/TestDocumentBuilder.hpp index 081e934..5896802 100644 --- a/test/core/model/TestDocumentBuilder.hpp +++ b/test/core/model/TestDocumentBuilder.hpp @@ -295,8 +295,6 @@ Rooted<AnnotationEntity> buildAnnotationEntity(  	Rooted<AnnotationEntity> anno{new AnnotationEntity(  	    document->getManager(), document, descriptor.cast<AnnotationClass>(),  	    start, end, attributes, name)}; -	// append the new entity to the document -	document->addAnnotation(anno);  	// and return it.  	return anno;  } diff --git a/test/core/model/TestDomain.hpp b/test/core/model/TestDomain.hpp index 48db57a..f6b8805 100644 --- a/test/core/model/TestDomain.hpp +++ b/test/core/model/TestDomain.hpp @@ -44,40 +44,37 @@ static Rooted<Domain> constructBookDomain(Manager &mgr,  	// Set up the "book" node.  	Rooted<StructuredClass> book{new StructuredClass(  	    mgr, "book", domain, single, {nullptr}, {nullptr}, false, true)}; -	domain->addStructuredClass(book); +  	// The structure field of it.  	Rooted<FieldDescriptor> book_field{new FieldDescriptor(mgr, book)}; -	book->addFieldDescriptor(book_field);  	// From there on the "section".  	Rooted<StructuredClass> section{  	    new StructuredClass(mgr, "section", domain, any)};  	book_field->addChild(section); -	domain->addStructuredClass(section); +  	// And the field of it.  	Rooted<FieldDescriptor> section_field{new FieldDescriptor(mgr, section)}; -	section->addFieldDescriptor(section_field);  	// We also add the "paragraph", which is transparent.  	Rooted<StructuredClass> paragraph{new StructuredClass(  	    mgr, "paragraph", domain, any, {nullptr}, {nullptr}, true)};  	section_field->addChild(paragraph);  	book_field->addChild(paragraph); -	domain->addStructuredClass(paragraph); +  	// And the field of it.  	Rooted<FieldDescriptor> paragraph_field{  	    new FieldDescriptor(mgr, paragraph)}; -	paragraph->addFieldDescriptor(paragraph_field);  	// We append "subsection" to section.  	Rooted<StructuredClass> subsection{  	    new StructuredClass(mgr, "subsection", domain, any)};  	section_field->addChild(subsection); -	domain->addStructuredClass(subsection); +  	// And the field of it.  	Rooted<FieldDescriptor> subsection_field{  	    new FieldDescriptor(mgr, subsection)}; -	subsection->addFieldDescriptor(subsection_field); +  	// and we add the paragraph to subsections fields  	subsection_field->addChild(paragraph); @@ -85,12 +82,11 @@ static Rooted<Domain> constructBookDomain(Manager &mgr,  	Rooted<StructuredClass> text{new StructuredClass(  	    mgr, "text", domain, any, {nullptr}, {nullptr}, true)};  	paragraph_field->addChild(text); -	domain->addStructuredClass(text); +  	// ... and has a primitive field.  	Rooted<FieldDescriptor> text_field{new FieldDescriptor(  	    mgr, text, domain->getTypesystems()[0]->getTypes()[0], "content",  	    false)}; -	text->addFieldDescriptor(text_field);  	return domain;  } @@ -98,4 +94,3 @@ static Rooted<Domain> constructBookDomain(Manager &mgr,  }  #endif /* _TEST_DOMAIN_HPP_ */ - | 
