diff options
| author | Andreas Stöckel <astoecke@techfak.uni-bielefeld.de> | 2015-01-16 16:34:09 +0100 | 
|---|---|---|
| committer | Andreas Stöckel <andreas@somweyr.de> | 2015-01-16 16:34:09 +0100 | 
| commit | e3caf907184286b795fadc1991cf69348f97d192 (patch) | |
| tree | 1167037d70ab4dfa23676ca5c8a23682b16b23b8 /src | |
| parent | 9ea137094077eee7f7e80f25871cc91592982e4b (diff) | |
| parent | 9929838e62d9c17647d74be54af5853e8b613c4b (diff) | |
Merge branch 'master' of somweyr.de:ousia
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/RangeSet.hpp | 51 | ||||
| -rw-r--r-- | src/core/managed/Managed.hpp | 21 | ||||
| -rw-r--r-- | src/core/model/Document.cpp | 113 | ||||
| -rw-r--r-- | src/core/model/Document.hpp | 2 | ||||
| -rw-r--r-- | src/core/model/Domain.cpp | 65 | ||||
| -rw-r--r-- | src/core/model/Domain.hpp | 30 | 
6 files changed, 229 insertions, 53 deletions
| diff --git a/src/core/RangeSet.hpp b/src/core/RangeSet.hpp index 3b351c3..2c138dc 100644 --- a/src/core/RangeSet.hpp +++ b/src/core/RangeSet.hpp @@ -205,7 +205,7 @@ protected:  	 * end of the list if no such element was found.  	 */  	typename std::set<Range<T>, RangeComp<T>>::iterator firstOverlapping( -	    const Range<T> &r, const bool allowNeighbours) +	    const Range<T> &r, const bool allowNeighbours) const  	{  		// Find the element with the next larger start value compared to the  		// start value given in r. @@ -265,7 +265,7 @@ public:  	 * @param r is the range for which the containment should be checked.  	 * @return true if the above condition is met, false otherwise.  	 */ -	bool contains(const Range<T> &r) +	bool contains(const Range<T> &r) const  	{  		auto it = firstOverlapping(r, false);  		if (it != ranges.end()) { @@ -275,12 +275,29 @@ public:  	}  	/** +	 * Checks whether this range Set S contains a given value v, which is +	 * the case if at least one contained range R contains v. +	 * +	 * @param v is some value. +	 * @return  true if at least one Range r returns true for r.inRange(v) +	 */ +	bool contains(const T &v) const +	{ +		for (auto &r : ranges) { +			if (r.inRange(v)) { +				return true; +			} +		} +		return false; +	} + +	/**  	 * Checks whether this range set S1 contains the given range set S2:  	 *  	 * @param s is the range for which the containment should be checked.  	 * @return true if the above condition is met, false otherwise.  	 */ -	bool contains(const RangeSet<T> &s) +	bool contains(const RangeSet<T> &s) const  	{  		bool res = true;  		for (Range<T> &r : s.ranges) { @@ -290,6 +307,29 @@ public:  	}  	/** +	 * Returns the minimum value that is still covered by this RangeSet. +	 * +	 * @return the minimum value that is still covered by this RangeSet. +	 */ +	T min() const { return ranges.begin()->start; } + +	/** +	 * Returns the maximum value that is still covered by this RangeSet. +	 * +	 * @return the maximum value that is still covered by this RangeSet. +	 */ +	T max() const +	{ +		T max = ranges.begin()->end; +		for (Range<T> &r : ranges) { +			if (r.end > max) { +				max = r.end; +			} +		} +		return std::move(max); +	} + +	/**  	 * Empties the set.  	 */  	void clear() { ranges.clear(); } @@ -297,7 +337,10 @@ public:  	/**  	 * Returns the current list of ranges as a const reference.  	 */ -	const std::set<Range<T>, RangeComp<T>> &getRanges() { return this->ranges; } +	const std::set<Range<T>, RangeComp<T>> &getRanges() const +	{ +		return this->ranges; +	}  };  } diff --git a/src/core/managed/Managed.hpp b/src/core/managed/Managed.hpp index dd1a23a..e98e95e 100644 --- a/src/core/managed/Managed.hpp +++ b/src/core/managed/Managed.hpp @@ -94,6 +94,24 @@ public:  	Manager &getManager() { return mgr; }  	/** +	 * Returns the unique identifier (UID) of this object. Valid UIDs are +	 * positive non-zero values. +	 * +	 * @return the unique id of the object. +	 */ +	ManagedUid getUid() const +	{ +		/* +		 * Dear Bjarne Stroustroup, dear gods of C++, please excuse this +		 * const_cast, for I did try other means but was not able to apply them +		 * and in my despair turned to this folly, this ugliness, this heresy! +		 * I pledge my life to better programming and promise that this cast +		 * will do no harm to anyone. +		 */ +		return mgr.getUid(const_cast<Managed *>(this)); +	} + +	/**  	 * Acquires a reference to the object wraped in the given handle -- creates  	 * a new Owned handle instance with this Managed instance as owner and the  	 * given object handle as the referenced object. @@ -151,8 +169,7 @@ public:  	 * object. The event id must be used when unregistering event handlers.  	 */  	EventId registerEvent(EventType type, EventHandler handler, -	                      Handle<Managed> owner, -	                      void *data = nullptr); +	                      Handle<Managed> owner, void *data = nullptr);  	/**  	 * Unregisters the event handler with the given signature. diff --git a/src/core/model/Document.cpp b/src/core/model/Document.cpp index 299b427..2f12acb 100644 --- a/src/core/model/Document.cpp +++ b/src/core/model/Document.cpp @@ -18,6 +18,9 @@  #include "Document.hpp" +#include <map> +#include <set> +  #include <core/common/Exceptions.hpp>  #include <core/common/Rtti.hpp> @@ -89,17 +92,121 @@ int DocumentEntity::getFieldDescriptorIndex(  	}  } +bool DocumentEntity::validate(Logger &logger) const +{ +	// TODO: check the validated form of Attributes +	// iterate over every field +	for (unsigned int f = 0; f < fields.size(); f++) { +		// we can do a faster check if this field is empty. +		if (fields[f].size() == 0) { +			// if this field is optional, an empty field is valid anyways. +			if (descriptor->getFieldDescriptors()[f]->optional) { +				continue; +			} +			/* +			 * if it is not optional we have to chack if zero is a valid +			 * cardinality. +			 */ +			for (auto &ac : +			     descriptor->getFieldDescriptors()[f]->getChildren()) { +				const size_t min = ac->getCardinality().min(); +				if (min > 0) { +					logger.error( +					    std::string("Field ") + +					    descriptor->getFieldDescriptors()[f]->getName() + +					    " was empty but needs at least " + std::to_string(min) + +					    " elements of class " + ac->getName() + +					    " according to the definition of " + +					    descriptor->getName()); +					return false; +				} +			} +			continue; +		} + +		// create a set of allowed classes identified by their unique id. +		std::set<ManagedUid> accs; +		for (auto &ac : descriptor->getFieldDescriptors()[f]->getChildren()) { +			accs.insert(ac->getUid()); +		} +		// store the actual numbers of children for each child class in a map +		std::map<ManagedUid, unsigned int> nums; + +		// iterate over every actual child of this DocumentEntity +		for (auto &rc : fields[f]) { +			if (!rc->isa(RttiTypes::StructuredEntity)) { +				continue; +			} +			Handle<StructuredEntity> c = rc.cast<StructuredEntity>(); + +			ManagedUid id = c->getDescriptor()->getUid(); +			// check if its class is allowed. +			bool allowed = accs.find(id) != accs.end(); +			/* +			 * if it is not allowed directly, we have to check if the class is a +			 * child of a permitted class. +			 */ +			if (!allowed) { +				for (auto &ac : +				     descriptor->getFieldDescriptors()[f]->getChildren()) { +					if (c->getDescriptor() +					        .cast<StructuredClass>() +					        ->isSubclassOf(ac)) { +						allowed = true; +						id = ac->getUid(); +					} +				} +			} +			if (!allowed) { +				logger.error(std::string("An instance of ") + +				             c->getDescriptor()->getName() + +				             " is not allowed as child of an instance of " + +				             descriptor->getName() + " in field " + +				             descriptor->getFieldDescriptors()[f]->getName()); +				return false; +			} +			// note the number of occurences. +			const auto &n = nums.find(id); +			if (n != nums.end()) { +				n->second++; +			} else { +				nums.emplace(id, 1); +			} +		} + +		// now check if the cardinalities are right. +		for (auto &ac : descriptor->getFieldDescriptors()[f]->getChildren()) { +			const auto &n = nums.find(ac->getUid()); +			unsigned int num = 0; +			if (n != nums.end()) { +				num = n->second; +			} +			if (!ac->getCardinality().contains(num)) { +				logger.error( +				    std::string("Field ") + +				    descriptor->getFieldDescriptors()[f]->getName() + " had " + +				    std::to_string(num) + " elements of class " + +				    ac->getName() + +				    ", which is invalid according to the definition of " + +				    descriptor->getName()); +				return false; +			} +		} +	} +	return true; +} +  /* Class StructureNode */  StructureNode::StructureNode(Manager &mgr, std::string name,                               Handle<Node> parent, const std::string &fieldName)      : Node(mgr, std::move(name), parent)  { -	if(parent->isa(RttiTypes::StructuredEntity)){ +	if (parent->isa(RttiTypes::StructuredEntity)) {  		parent.cast<StructuredEntity>()->addStructureNode(this, fieldName); -	} else if(parent->isa(RttiTypes::AnnotationEntity)){ +	} else if (parent->isa(RttiTypes::AnnotationEntity)) {  		parent.cast<AnnotationEntity>()->addStructureNode(this, fieldName); -	} else{ +	} else {  		throw OusiaException("The proposed parent was no DocumentEntity!");  	}  } diff --git a/src/core/model/Document.hpp b/src/core/model/Document.hpp index be8b5c8..c70a6a3 100644 --- a/src/core/model/Document.hpp +++ b/src/core/model/Document.hpp @@ -256,6 +256,8 @@ public:  		return fields[getFieldDescriptorIndex(fieldDescriptor, true)];  	} +	bool validate(Logger& logger) const; +  	// TODO: Change this to move methods.  	//	/**  	//	 * This adds a StructureNode to the field with the given name. If an diff --git a/src/core/model/Domain.cpp b/src/core/model/Domain.cpp index f1b91cc..2ac2d8d 100644 --- a/src/core/model/Domain.cpp +++ b/src/core/model/Domain.cpp @@ -28,8 +28,7 @@ namespace model {  template <class T>  static void checkUniqueName(Handle<Node> parent, NodeVector<T> vec, -                            Handle<T> child, -                            const std::string &parentClassName, +                            Handle<T> child, const std::string &parentClassName,                              const std::string &childClassName)  {  	std::set<std::string> childNames; @@ -37,6 +36,7 @@ static void checkUniqueName(Handle<Node> parent, NodeVector<T> vec,  		childNames.insert(c->getName());  	}  	if (childNames.find(child->getName()) != childNames.end()) { +		//TODO: Do we really want to have an exception here?  		throw OusiaException(std::string("The ") + parentClassName + " " +  		                     parent->getName() + " already has a " +  		                     childClassName + " with name " + child->getName()); @@ -96,31 +96,15 @@ std::vector<Rooted<Node>> Descriptor::pathTo(  	return path;  } -static bool pathEquals(const Descriptor &a, const Descriptor &b) -{ -	// We assume that two Descriptors are equal if their names and domain names -	// are equal. -	if (a.getName() != b.getName()) { -		return false; -	} -	Handle<Domain> aDom = a.getParent().cast<Domain>(); -	Handle<Domain> bDom = b.getParent().cast<Domain>(); -	return aDom->getName() == bDom->getName(); -} -  bool Descriptor::continuePath(Handle<StructuredClass> target,                                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(); +	// check if we are at the target already +	if (this == target) { +		return true;  	}  	// a variable to determine if we already found a solution  	bool found = false; @@ -133,7 +117,8 @@ bool Descriptor::continuePath(Handle<StructuredClass> target,  			continue;  		}  		for (auto &c : fd->getChildren()) { -			if (pathEquals(*c, *target)) { +			// check if a child is the target node. +			if (c == target) {  				// if we have made the connection, stop the search.  				currentPath.push_back(fd);  				return true; @@ -161,11 +146,11 @@ bool Descriptor::continuePath(Handle<StructuredClass> target,  		 * 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()) { +		if (exploreSuperclass && tis->getSuperclass() != nullptr) {  			// copy the path.  			std::vector<Rooted<Node>> cPath = currentPath; -			if (tis->getIsA()->continuePath(target, cPath, ignoredFields, true, -			                                false) && +			if (tis->getSuperclass()->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); @@ -203,13 +188,11 @@ void Descriptor::copyFieldDescriptor(Handle<FieldDescriptor> fd)  		 * constructor will add the newly constructed FieldDescriptor to this  		 * Descriptor automatically.  		 */ -		new FieldDescriptor(getManager(), this, -		                                       fd->getPrimitiveType(), -		                                       fd->getName(), fd->optional); +		new FieldDescriptor(getManager(), this, fd->getPrimitiveType(), +		                    fd->getName(), fd->optional);  	} else { -		new FieldDescriptor(getManager(), this, -		                                       fd->getFieldType(), -		                                       fd->getName(), fd->optional); +		new FieldDescriptor(getManager(), this, fd->getFieldType(), +		                    fd->getName(), fd->optional);  	}  } @@ -219,23 +202,33 @@ StructuredClass::StructuredClass(Manager &mgr, std::string name,                                   Handle<Domain> domain,                                   const Cardinality &cardinality,                                   Handle<StructType> attributesDescriptor, -                                 Handle<StructuredClass> isa, bool transparent, -                                 bool root) +                                 Handle<StructuredClass> superclass, +                                 bool transparent, bool root)      : Descriptor(mgr, std::move(name), domain, attributesDescriptor),        cardinality(cardinality), -      isa(acquire(isa)), +      superclass(acquire(superclass)),        subclasses(this),        transparent(transparent),        root(root)  { -	if (!isa.isNull()) { -		isa->subclasses.push_back(this); +	if (superclass != nullptr) { +		superclass->subclasses.push_back(this);  	}  	if (!domain.isNull()) {  		domain->addStructuredClass(this);  	}  } +bool StructuredClass::isSubclassOf(Handle<StructuredClass> c) const{ +	if(c == nullptr || superclass == nullptr){ +		return false; +	} +	if(c == superclass){ +		return true; +	} +	return superclass->isSubclassOf(c); +} +  /* Class AnnotationClass */  AnnotationClass::AnnotationClass( diff --git a/src/core/model/Domain.hpp b/src/core/model/Domain.hpp index 791d563..ac02ec7 100644 --- a/src/core/model/Domain.hpp +++ b/src/core/model/Domain.hpp @@ -324,6 +324,10 @@ public:  	 */  	const NodeVector<StructuredClass> &getChildren() const { return children; } +	/* +	 *TODO: This should check whether another class is permitted that is a +	 * superclass of this one. +	 */  	/**  	 * Adds a StructuredClass whose instances shall be allowed as children in  	 * the StructureTree of instances of this field. @@ -546,7 +550,7 @@ typedef RangeSet<size_t> Cardinality;  class StructuredClass : public Descriptor {  private:  	const Cardinality cardinality; -	Owned<StructuredClass> isa; +	Owned<StructuredClass> superclass;  	NodeVector<StructuredClass> subclasses;  public: @@ -570,7 +574,7 @@ public:  	 * @param attributesDescriptor is a StructType that specifies the attribute  	 *                             keys as well as value domains for this  	 *                             Descriptor. -	 * @param isa                  references a parent StructuredClass. Please +	 * @param superclass           references a parent StructuredClass. Please  	 *                             look for more information on inheritance in  	 *                             the class documentation above. The default is  	 *                             a null reference, meaning no super class. @@ -585,7 +589,7 @@ public:  	                const Cardinality &cardinality,  	                Handle<StructType> attributesDescriptor = nullptr,  	                // TODO: What would be a wise default value for isa? -	                Handle<StructuredClass> isa = nullptr, +	                Handle<StructuredClass> superclass = nullptr,  	                bool transparent = false, bool root = false);  	/** @@ -596,13 +600,23 @@ public:  	const Cardinality &getCardinality() const { return cardinality; }  	/** -	 * Returns the parent of this StructuredClass in the class inheritance -	 * hierarchy (!). This is not the same as the parents in the Structure Tree! +	 * Returns the superclass of this StructuredClass. This is not the same as +	 * the parents in the Structure Tree! +	 * +	 * @return the superclass of this StructuredClass. +	 */ +	Rooted<StructuredClass> getSuperclass() const { return superclass; } +	 +	/** +	 * Returns true if this class is a subclass of the given class. It does not +	 * return true if the other class is equal to the given class. +	 * +	 * @param c is another class that might or might not be a superclass of this +	 *          one +	 * @return  true if this class is a subclass of the given class.  	 * -	 * @return the parent of this StructuredClass in the class inheritance -	 * hierarchy (!).  	 */ -	Rooted<StructuredClass> getIsA() const { return isa; } +	bool isSubclassOf(Handle<StructuredClass> c) const;  	/**  	 * Returns the StructuredClasses that are subclasses of this class. This | 
