diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/model/Domain.cpp | 117 | ||||
| -rw-r--r-- | src/core/model/Domain.hpp | 34 | 
2 files changed, 102 insertions, 49 deletions
diff --git a/src/core/model/Domain.cpp b/src/core/model/Domain.cpp index d664809..be9aa05 100644 --- a/src/core/model/Domain.cpp +++ b/src/core/model/Domain.cpp @@ -16,6 +16,8 @@      along with this program.  If not, see <http://www.gnu.org/licenses/>.  */ +#include <set> +  #include <core/common/Rtti.hpp>  #include <core/common/Exceptions.hpp> @@ -60,65 +62,88 @@ static bool pathEquals(const Descriptor &a, const Descriptor &b)  }  bool Descriptor::continuePath(Handle<StructuredClass> target, -                              std::vector<Rooted<Node>> &path) const +                              std::vector<Rooted<Node>> ¤tPath, +                              std::set<std::string> ignoredFields, +                              bool exploreSuperclass, +                              bool exploreSubclasses) const  { +	// TODO: REMOVE +	std::string targetName = target->getName(); +	std::string thisName = getName(); +	std::string currentPathName; +	for (auto &n : currentPath) { +		currentPathName += "."; +		currentPathName += n->getName(); +	} +	// a variable to determine if we already found a solution  	bool found = false; +	// the currently optimal path. +	std::vector<Rooted<Node>> optimum;  	// use recursive depth-first search from the top to reach the given child -	if (fieldDescriptors.size() > 0) { -		for (auto &fd : fieldDescriptors) { -			for (auto &c : fd->getChildren()) { -				if (pathEquals(*c, *target)) { -					// if we have made the connection, stop the search. -					path.push_back(fd); -					return true; -				} -				// look for transparent intermediate nodes. -				if (c->transparent) { -					// copy the path. -					std::vector<Rooted<Node>> cPath = path; -					cPath.push_back(fd); -					cPath.push_back(c); -					// recursion. -					if (c->continuePath(target, cPath) && -					    (!found || path.size() > cPath.size())) { -						// look if this path is better than the current optimum. -						path = std::move(cPath); -						found = true; -					} -				} -			} +	for (auto &fd : fieldDescriptors) { +		if (!(ignoredFields.insert(fd->getName()).second)) { +			// if we want to ignore that field, we continue. +			continue;  		} -	} else { -		// if this is a StructuredClass and if it did not formulate own -		// fieldDescriptors (overriding the parent), we can also use the -		// (inheritance-wise) parent -		if (isa(RttiTypes::StructuredClass)) { -			const StructuredClass *tis = -			    static_cast<const StructuredClass *>(this); -			if (!tis->getIsA().isNull()) { +		for (auto &c : fd->getChildren()) { +			if (pathEquals(*c, *target)) { +				// if we have made the connection, stop the search. +				currentPath.push_back(fd); +				return true; +			} +			// look for transparent intermediate nodes. +			if (c->transparent) {  				// copy the path. -				std::vector<Rooted<Node>> cPath = path; -				if (tis->getIsA()->continuePath(target, cPath) && -				    (found || path.size() > cPath.size())) { +				std::vector<Rooted<Node>> cPath = currentPath; +				cPath.push_back(fd); +				cPath.push_back(c); +				// recursion. +				if (c->continuePath(target, cPath) && +				    (!found || optimum.size() > cPath.size())) {  					// look if this path is better than the current optimum. -					path = std::move(cPath); +					optimum = std::move(cPath);  					found = true;  				}  			}  		}  	} -	// either way we can try to find the targets parent (inheritance-wise) -	// instead of the target itself. -	if (!target->getIsA().isNull()) { -		// copy the path. -		std::vector<Rooted<Node>> cPath = path; -		if (continuePath(target->getIsA(), cPath) && -		    (!found || path.size() > cPath.size())) { -			// look if this path is better than the current optimum. -			path = std::move(cPath); -			found = true; + +	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 (exploreSuperclass && !tis->getIsA().isNull()) { +			// copy the path. +			std::vector<Rooted<Node>> cPath = currentPath; +			if (tis->getIsA()->continuePath(target, cPath, ignoredFields, true, +			                                false) && +			    (!found || optimum.size() > cPath.size())) { +				// look if this path is better than the current optimum. +				optimum = std::move(cPath); +				found = true; +			} +		} + +		// we also can call the subclasses. +		if (exploreSubclasses) { +			for (auto &c : tis->getSubclasses()) { +				// copy the path. +				std::vector<Rooted<Node>> cPath = currentPath; +				if (c->continuePath(target, cPath, {}, false) && +				    (!found || optimum.size() > cPath.size())) { +					// look if this path is better than the current optimum. +					optimum = std::move(cPath); +					found = true; +				} +			}  		}  	} + +	// put the optimum in the given path reference. +	currentPath = std::move(optimum); +  	// return if we found something.  	return found;  } diff --git a/src/core/model/Domain.hpp b/src/core/model/Domain.hpp index 1f65242..4b26917 100644 --- a/src/core/model/Domain.hpp +++ b/src/core/model/Domain.hpp @@ -394,7 +394,10 @@ private:  	NodeVector<FieldDescriptor> fieldDescriptors;  	bool continuePath(Handle<StructuredClass> target, -	                  std::vector<Rooted<Node>> &path) const; +	                  std::vector<Rooted<Node>> &path, +	                  std::set<std::string> ignoredFields = {}, +	                  bool exploreSuperclass = true, +	                  bool exploreSubclasses = true) const;  protected:  	void continueResolve(ResolutionState &state) override; @@ -558,6 +561,7 @@ class StructuredClass : public Descriptor {  private:  	const Cardinality cardinality;  	Owned<StructuredClass> isa; +	NodeVector<StructuredClass> subclasses;  public:  	const bool transparent; @@ -583,7 +587,9 @@ public:  	 * @param isa                  references a parent StructuredClass. Please  	 *                             look for more information on inheritance in  	 *                             the class documentation above. The default is -	 *                             a null reference, meaning no parent class. +	 *                             a null reference, meaning no super class. +	 *                             The constructor automatically registers this +	 *                             class as a subclass at the super class.  	 * @param transparent          specifies whether this StructuredClass is  	 *                             transparent. For more information on  	 *                             transparency please refer to the class @@ -598,9 +604,13 @@ public:  	    : 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); +		}  	}  	/** @@ -618,6 +628,24 @@ public:  	 * hierarchy (!).  	 */  	Rooted<StructuredClass> getIsA() const { return isa; } + +	/** +	 * Returns the StructuredClasses that are subclasses of this class. This +	 * is the inverted version of isa, meaning: each class c that has a isa +	 * relationship to this class is part of the returned vector. +	 * +	 * Note that the order of subclasses is not strictly defined. +	 * +	 * You are not allowed to add subclasses directly to the vector. When you +	 * construct a new StructuredClass with a non-empty isa-handle it will +	 * automatically register as subclass at the super class. +	 * +	 * @return the StructuredClasses that are subclasses of this class. +	 */ +	const NodeVector<StructuredClass> &getSubclasses() const +	{ +		return subclasses; +	}  };  /** @@ -637,7 +665,7 @@ public:  	 *                             be used for later references to this  	 *                             AnnotationClass.  	 * @param domain               is the Domain this AnnotationClass belongs -	 *to. +	 *                             to.  	 * @param attributesDescriptor is a StructType that specifies the attribute  	 *                             keys as well as value domains for this  	 *                             Descriptor.  | 
