diff options
| author | Andreas Stöckel <astoecke@techfak.uni-bielefeld.de> | 2015-01-17 15:27:32 +0100 | 
|---|---|---|
| committer | Andreas Stöckel <astoecke@techfak.uni-bielefeld.de> | 2015-01-17 15:27:32 +0100 | 
| commit | 9eb32731b024d792b0aa212cbcd6bf07b8d6ccca (patch) | |
| tree | b085d0b42cb7b22ca2816c7f549994e1140381d3 /src | |
| parent | 97b364112f0c9f3378011d6567433923f9fd8328 (diff) | |
Improved typesystem, allowing online creation of structs
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/model/Typesystem.cpp | 142 | ||||
| -rw-r--r-- | src/core/model/Typesystem.hpp | 79 | 
2 files changed, 170 insertions, 51 deletions
| diff --git a/src/core/model/Typesystem.cpp b/src/core/model/Typesystem.cpp index c2f8a9c..726de3e 100644 --- a/src/core/model/Typesystem.cpp +++ b/src/core/model/Typesystem.cpp @@ -147,6 +147,18 @@ EnumType::Ordinal EnumType::valueOf(const std::string &name) const  	throw LoggableException(std::string("Unknown enum constant: ") + name);  } +/* Class Attribute */ + +bool Attribute::doValidate(Logger &logger) const +{ +	if (!Utils::isIdentifier(getName())) { +		logger.error("Attribute name \"" + getName() + +		             "\" is not a valid identifier."); +		return false; +	} +	return true; +} +  /* Class StructType */  bool StructType::resolveIndexKey(const std::string &key, size_t &idx) const @@ -289,66 +301,115 @@ bool StructType::buildFromArrayOrMap(Variant &data, Logger &logger,  	    data.getTypeName());  } +void StructType::initialize(Logger &logger) +{ +	// Copy the location in the attributes list at which the attributes started +	size_t oldAttributeStart = attributeStart; +	NodeVector<Attribute> oldAttributes{std::move(attributes)}; + +	// Clear the attributes and attributeNames containers +	attributes.clear(); +	attributeNames.clear(); + +	// Assemble a new attributes list, add the attributes of the parent +	// structure first +	if (parentStructure != nullptr) { +		attributes.assign(parentStructure->attributes); +		attributeNames = parentStructure->attributeNames; +	} +	attributeStart = attributes.size(); + +	// Add the own attributes from the old attribute list +	for (size_t i = oldAttributeStart; i < oldAttributes.size(); i++) { +		addAttribute(oldAttributes[i], logger, true); +	} +} +  bool StructType::doBuild(Variant &data, Logger &logger) const  {  	return buildFromArrayOrMap(data, logger, false);  } +bool StructType::doValidate(Logger &logger) const +{ +	// Check whether all attributes are valid and unique +	std::unordered_set<std::string> names; +	bool res = true; +	for (Handle<Attribute> a : attributes) { +		res = a->validate(logger) && res; +		const std::string &name = a->getName(); +		if (!names.emplace(name).second) { +			logger.error( +			    std::string("Attribute with name \"") + name + +			    std::string("\" defined multiple times in structure \"") + +			    Utils::join(path(), ".") + std::string("\"")); +			res = false; +		} +	} + +	return res; +} +  Rooted<StructType> StructType::createValidated(      Manager &mgr, std::string name, Handle<Typesystem> system,      Handle<StructType> parentStructure, NodeVector<Attribute> attributes,      Logger &logger)  { -	// Check the attributes for validity and uniqueness -	std::map<std::string, size_t> attributeNames; -	NodeVector<Attribute> collectedAttributes; - -	// Copy the attributes from the parent structure -	if (parentStructure != nullptr) { -		attributeNames = parentStructure->attributeNames; -		collectedAttributes = parentStructure->attributes; -	} +	Rooted<StructType> structType{new StructType(mgr, name, system)}; +	structType->setParentStructure(parentStructure, logger); +	structType->addAttributes(attributes, logger); +	return structType; +} -	// Check the attributes for validity and uniqueness -	for (size_t idx = 0; idx < attributes.size(); idx++) { -		// Check for valid attribute names -		const std::string &attrName = attributes[idx]->getName(); -		if (!Utils::isIdentifier(attrName)) { -			logger.error(std::string("Invalid attribute name \"") + attrName + -			             std::string("\"")); -		} +Rooted<StructType> StructType::getParentStructure() const +{ +	return parentStructure; +} -		// Check for uniqueness -		auto res = attributeNames.emplace(attrName, idx); -		if (!res.second) { -			logger.error(std::string("Attribute with name \"") + attrName + -			             std::string("\" defined multiple times")); -			if (parentStructure != nullptr && -			    parentStructure->indexOf(attrName) >= 0) { -				logger.note(std::string("Attribute \"") + attrName + -				            std::string("\" was defined in parent class \"") + -				            parentStructure->getName() + std::string("\"")); -			} -		} +void StructType::setParentStructure(Handle<StructType> parentStructure, +                                    Logger &logger) +{ +	invalidate(); +	this->parentStructure = acquire(parentStructure); +	initialize(logger); +} -		// Store the attribute in the complete attribute list -		collectedAttributes.push_back(attributes[idx]); +void StructType::addAttribute(Handle<Attribute> attribute, Logger &logger, +                              bool fromInitialize) +{ +	// Make sure an attribute with the given name does not already exist +	const std::string &attrName = attribute->getName(); +	attributes.push_back(attribute); +	if (!hasAttribute(attrName)) { +		attributeNames[attrName] = attributes.size() - 1; +		return;  	} -	// Call the private constructor -	return new StructType(mgr, name, system, parentStructure, -	                      collectedAttributes, attributeNames); +	// Check whether the attribute was defined in the parent structure, adapt +	// error message accordingly +	if (parentStructure != nullptr && parentStructure->hasAttribute(attrName)) { +		logger.error("Field with name \"" + attrName + +		             "\" hides field defined by parent structure \"" + +		             parentStructure->getName() + "\"."); +	} else { +		logger.error("Field with name \"" + attrName + "\" already exists."); +	} +	markInvalid();  } -Rooted<StructType> StructType::getParentStructure() const +void StructType::addAttribute(Handle<Attribute> attribute, Logger &logger)  { -	return parentStructure; +	invalidate(); +	addAttribute(attribute, logger, false);  } -void StructType::setParentStructure(Handle<StructType> parentStructure) +void StructType::addAttributes(const NodeVector<Attribute> &attributes, +                               Logger &logger)  {  	invalidate(); -	this->parentStructure = acquire(parentStructure); +	for (Handle<Attribute> a : attributes) { +		addAttribute(a, logger, false); +	}  }  Variant StructType::create() const @@ -390,6 +451,11 @@ ssize_t StructType::indexOf(const std::string &name) const  	return -1;  } +bool StructType::hasAttribute(const std::string &name) const +{ +	return indexOf(name) >= 0; +} +  /* Class ArrayType */  bool ArrayType::doBuild(Variant &data, Logger &logger) const diff --git a/src/core/model/Typesystem.hpp b/src/core/model/Typesystem.hpp index 42c2591..7bc8950 100644 --- a/src/core/model/Typesystem.hpp +++ b/src/core/model/Typesystem.hpp @@ -373,6 +373,15 @@ private:  	 */  	const Owned<Type> type; +protected: +	/** +	 * Returns true if the name of the Attribute is a valid identifier. +	 * +	 * @param logger is the logger instance to which validation errors are +	 * logged. +	 */ +	bool doValidate(Logger &logger) const override; +  public:  	/**  	 * Default value of the attribute. @@ -441,7 +450,14 @@ private:  	Owned<StructType> parentStructure;  	/** -	 * Vector containing references to all attribute descriptors. +	 * Contains the index at which the attributes declared by this StructType +	 * start. +	 */ +	size_t attributeStart; + +	/** +	 * Vector containing references to all attribute descriptors, including the +	 * attributes of the parent structure.  	 */  	NodeVector<Attribute> attributes; @@ -528,6 +544,22 @@ private:  	 */  	bool buildFromArrayOrMap(Variant &data, Logger &logger, bool trim) const; +	/** +	 * Rebuilds the internal index and attribute list depending on the parent +	 * structure. +	 */ +	void initialize(Logger &logger); + +	/** +	 * Function used internally to add and index attributes while logging +	 * exceptions. +	 * +	 * @param attribute is the attribute that should be added. +	 * @param logger is the logger instance to which +	 */ +	void addAttribute(Handle<Attribute> attribute, Logger &logger, +	                  bool fromInitialize); +  protected:  	/**  	 * Converts the given variant to the representation of the structure type. @@ -549,9 +581,8 @@ protected:  	 *  	 * @param logger is a reference to the logger to which error messages should  	 * be logged. -	 * @param visited is used internally for recursion avoidance.  	 */ -	bool doValidate(Logger &logger, std::set<ManagedUid> &visited) const override; +	bool doValidate(Logger &logger) const override;  public:  	/** @@ -564,10 +595,17 @@ public:  	 * @param system is a reference to the parent Typesystem instance.  	 */  	StructType(Manager &mgr, std::string name, Handle<Typesystem> system) -	    : Type(mgr, std::move(name), system, false), attributes(this) +	    : Type(mgr, std::move(name), system, false), +	      attributeStart(0), +	      attributes(this)  	{  	} +	static Rooted<StructType> createValidated( +	    Manager &mgr, std::string name, Handle<Typesystem> system, +	    Handle<StructType> parentStructure, NodeVector<Attribute> attributes, +	    Logger &logger); +  	/**  	 * Returns a handle pointing at the parent type.  	 * @@ -581,7 +619,7 @@ public:  	 *  	 * @param parentStructure is the new parent structure.  	 */ -	void setParentStructure(Handle<StructType> parentStructure); +	void setParentStructure(Handle<StructType> parentStructure, Logger &logger);  	/**  	 * Adds an attribute. Throws an exception if the name of the attribute is @@ -590,14 +628,14 @@ public:  	 * @param attribute is the attribute descriptor that should be added to the  	 * internal attribute list.  	 */ -	void addAttribute(Handle<Attribute> attribute); +	void addAttribute(Handle<Attribute> attribute, Logger &logger);  	/**  	 * Adds a complete list of attributes to the typesystem.  	 *  	 * @param attributes is the list with typesystems that should be added.  	 */ -	void addAttributes(const NodeVector<Attribute> &attributes); +	void addAttributes(const NodeVector<Attribute> &attributes, Logger &logger);  	/**  	 * Creates a Variant containing a valid representation of a data instance of @@ -630,11 +668,12 @@ public:  	bool cast(Variant &data, Logger &logger) const;  	/** -	 * Returns a reference at the list containing all attributes. +	 * Returns a reference at the list containing all attributes, including the +	 * attributes of the parent structure.  	 *  	 * @return a const reference pointing at the attribute list.  	 */ -	const NodeVector<Attribute> &getAttributes() const { return attributes; } +	const NodeVector<Attribute> &getAttributes() const { return attributes; };  	/**  	 * Returns the index of the given attribute in a data array representing @@ -645,6 +684,15 @@ public:  	 * @return the index or -1 if the attribute does not exist.  	 */  	ssize_t indexOf(const std::string &name) const; + +	/** +	 * Returns true if an attribute with the given name exists. +	 * +	 * @param name is the name of the attribute for which the index is +	 * requested. +	 * @return true if the requested attribute name exists, false otherwise. +	 */ +	bool hasAttribute(const std::string &name) const;  };  /** @@ -833,14 +881,18 @@ public:  	/**  	 * Adds the given types to the type list. +	 * +	 * @param ts is the list of types that should be added to the typesystem.  	 */ -	void addTypes(const std::vector<Handle<Type>> &ts) +	void addTypes(const NodeVector<Type> &ts)  	{  		types.insert(types.end(), ts.begin(), ts.end());  	}  	/**  	 * Adds the given constant to the constant list. +	 * +	 * @param constant is the constant that should be added to the typesystem.  	 */  	void addConstant(Handle<Constant> constant)  	{ @@ -849,8 +901,11 @@ public:  	/**  	 * Adds the given constants to the constant list. +	 * +	 * @param cs is the list of constants that should be added to the +	 * typesystem.  	 */ -	void addConstants(const std::vector<Handle<Constant>> &cs) +	void addConstants(const NodeVector<Constant> &cs)  	{  		constants.insert(constants.end(), cs.begin(), cs.end());  	} @@ -868,8 +923,6 @@ public:  	 * @return NodeVector containing all registered constants.  	 */  	const NodeVector<Constant> &getConstants() const { return constants; } - -	static Rooted<Typesystem> createSystemTypesystem(Manager &mgr);  };  /** | 
