Index: /library/bdm/base/user_info.h
===================================================================
--- /library/bdm/base/user_info.h (revision 535)
+++ /library/bdm/base/user_info.h (revision 540)
@@ -34,47 +34,71 @@
 namespace bdm {
 
-//! Exception prepared for reporting user-info errors which are always related to some concrete Setting path
+//! Generic exception for reporting configuration errors
 //!
 //!  \ref ui_page
 class UIException : public std::exception {
-
-public:
+private:
 	//! Error message
 	const string message;
 
-	//! Path to the problematic setting
-	const string path;
-
-private:
-	string what_message;
-
+public:
+	/*!
+	  \brief The constructor
+	  \param message the reason for throwing the exception. Should be a complete English sentence (or a couple sentences), starting with "UIException: ".
+	*/
+	UIException ( const string &message ) :
+		message ( message ) {
+	}
+
+	//! Overriden method for reporting the error message
+	virtual const char* what() const throw() {
+		return message.c_str();
+	}
+
+	~UIException() throw() {};
+
+protected:
+	/*!
+	  Formats error messages for derived classes, which use a
+	  Setting path in addition to the message.
+	*/
+	static string format_message( const string &reason, const string &path );
+};
+
+//! Exception for reporting configuration errors related to some concrete Setting path
+//!
+//!  \ref ui_page
+class UISettingException : public UIException {
 public:
 	//! Use this constructor when you can pass the problematical Setting as a parameter
-	UIException ( const string &message, const Setting &element )
-			: message ( "UI error: " + message + "." ), path ( "Check path \"" + string ( element.getPath() ) + "\"." ) {
-		init_what_message();
+	UISettingException ( const string &message, const Setting &element ):
+		UIException ( format_message ( message, string ( element.getPath() ) ) ) {
 	}
 
 	//! This constructor is for other occasions, when only path of problematical Setting is known
-	UIException ( const string &message, const string &path )
-			: message ( "UI error: " + message + "." ), path ( "Check path \"" + path + "\"." ) {
-		init_what_message();
-	}
-
-	//! Overriden method for reporting an error message
-	virtual const char* what() const throw() {
-		return what_message.c_str();
-	}
-
-	~UIException() throw() {};
-
-private:
-	void init_what_message() {
-		what_message = message;
-		what_message += ' ';
-		what_message += path;
-	}
+	UISettingException ( const string &message, const string &path ):
+		UIException ( format_message ( message, path ) ) {
+	}
+
+	~UISettingException() throw() {};
 };
 
+//! Exception for reporting configuration errors in the "class" attribute
+//!
+//!  \ref ui_page
+class UIClassException : public UIException {
+public:
+	//! Use this constructor when you can pass the problematical Setting as a parameter
+	UIClassException ( const string &message, const Setting &element ):
+		UIException ( format_message ( message, string ( element.getPath() ) ) ) {
+	}
+
+	//! This constructor is for other occasions, when only path of problematical Setting is known
+	UIClassException ( const string &message, const string &path ):
+		UIException ( format_message ( message, path ) ) {
+	}
+
+	~UIClassException() throw() {};
+};
 
 /*!
@@ -291,5 +315,5 @@
 		string class_name;
 		if ( !link.result.lookupValue ( "class", class_name ) )
-			throw UIException ( "the obligatory \"class\" identifier is missing", link.result );
+			throw UIClassException ( "UIException: the obligatory \"class\" identifier is missing.", link.result );
 
 		// then we find a user-info related to this type
@@ -302,5 +326,5 @@
 		if ( !instance ) {
 			delete typeless_instance;
-			throw UIException ( "class " + class_name + " is not a descendant of the desired output class. Try to call the UI::build<T> function with a different type parameter.", link.result );
+			throw UIClassException ( "UIException: class " + class_name + " is not a descendant of the desired output class. Try to call the UI::build<T> function with a different type parameter.", link.result );
 		}
 
@@ -308,6 +332,8 @@
 			instance->from_setting ( link.result );
 		} catch ( SettingException sttng_xcptn ) {
-			string msg = "the method " + class_name + ".from_setting(Setting&) has thrown a SettingException. Try to correct this method. Check path \"" + sttng_xcptn.getPath() + "\".";
-			throw UIException(msg, link.result);
+			string msg = "UIException: method ";
+			msg += class_name;
+			msg += ".from_setting(Setting&) has thrown a SettingException.";
+			throw UISettingException(msg, sttng_xcptn.getPath());
 		}
 	}
@@ -342,7 +368,8 @@
 	//! The exception can help to find the place where the template is misused and also to correct it.
 	template<class T> static void from_setting ( T &variable_to_load, const Setting &element ) {
-		std::string msg = "from_setting is not implemented for type ";
+		std::string msg = "UIException: from_setting is not implemented for type ";
 		msg += typeid(T).name();
-		throw UIException ( msg, element );
+		msg += '.';
+		throw UISettingException ( msg, element );
 	}
 
@@ -372,5 +399,5 @@
 				return shared_ptr<T>();
 			else
-				throw UIException ( "the compulsory Setting named \"" + name + "\" is missing", element );
+				throw UISettingException ( "UIException: the compulsory Setting named \"" + name + "\" is missing.", element );
 		}
 
@@ -391,5 +418,5 @@
 				stringstream stream;
 				stream << index;
-				throw UIException ( "the compulsory Setting with the index " + stream.str() + " is missing", element );
+				throw UISettingException ( "UIException: the compulsory Setting with the index " + stream.str() + " is missing.", element );
 			}
 		}
@@ -413,5 +440,5 @@
 				return false;
 			else
-				throw UIException ( "the compulsory Setting named \"" + name + "\" is missing", element );
+				throw UISettingException ( "UIException: the compulsory Setting named \"" + name + "\" is missing.", element );
 		}
 
@@ -428,6 +455,7 @@
 			else {
 				stringstream stream;
+				stream << "UIException: the compulsory Setting with the index " << index << " is missing.";
 				stream << index;
-				throw UIException ( "the compulsory Setting with the index " + stream.str() + " is missing", element );
+				throw UISettingException (stream.str(), element );
 			}
 		}
@@ -494,8 +522,8 @@
 			instance->to_setting ( set );
 		} catch ( SettingException sttng_xcptn ) {
-		    string msg = "the method ";
-		    msg += class_name;
-		    msg += ".to_setting(Setting&) has thrown a SettingException. Try to correct this method.";
-		    throw UIException(msg, sttng_xcptn.getPath());
+			string msg = "UIException: method ";
+			msg += class_name;
+			msg += ".to_setting(Setting&) has thrown a SettingException.";
+			throw UISettingException(msg, sttng_xcptn.getPath());
 		}
 	}
Index: /library/bdm/base/user_info.cpp
===================================================================
--- /library/bdm/base/user_info.cpp (revision 493)
+++ /library/bdm/base/user_info.cpp (revision 540)
@@ -14,4 +14,12 @@
 
 namespace bdm {
+
+string UIException::format_message( const string &reason, const string &path ) {
+	stringstream ss;
+	ss << reason;
+	ss << " Check path \"" << path << "\".";
+	return ss.str();
+}
+
 ///////////////////////////// Class UIFile /////////////////////////////////////////////
 
@@ -132,5 +140,5 @@
 
 	if ( !result->exists ( link ) )
-		throw UIException ( "linked setting was not found", potential_link );
+		throw UISettingException ( "UIException: linked setting was not found.", string ( ( const char* ) potential_link ) );
 
 	return ( *result ) [link];
@@ -145,10 +153,10 @@
 void UI::assert_type ( const Setting &element, Setting::Type type ) {
 	if ( element.getType() != type )
-		throw UIException ( "wrong setting type", element );
+		throw UISettingException ( "UIException: wrong setting type.", element );
 }
 
 const Setting& UI::to_child_setting ( const Setting &element, const int index ) {
 	if ( !element.isList() )
-		throw UIException ( "only TypeList elements could be indexed by integers", element );
+		throw UISettingException ( "UIException: only TypeList elements could be indexed by integers.", element );
 
 	return element[index];
@@ -157,5 +165,5 @@
 const Setting& UI::to_child_setting ( const Setting &element, const string &name ) {
 	if ( !element.isGroup() )
-		throw UIException ( "only TypeGroup elements could be indexed by strings", element );
+		throw UISettingException ( "UIException: only TypeGroup elements could be indexed by strings.", element );
 
 	return element[name];
@@ -236,9 +244,9 @@
 			const char* elem1 = ( const char* ) link.result[0];
 			if ( ( strcmp ( elem1, "matrix" ) ) )
-				throw UIException ( "the setting supposed to represent a matrix element has wrong syntax", link.result );
+				throw UISettingException ( "UIException: the setting supposed to represent a matrix element has wrong syntax.", link.result );
 
 			data_offset = 1;
 		} else
-			throw UIException ( "the setting supposed to represent a matrix element has wrong syntax", link.result );
+			throw UISettingException ( "UIException: the setting supposed to represent a matrix element has wrong syntax.", link.result );
 
 		Setting &rows_setting = link.result[0 + data_offset];
@@ -254,8 +262,8 @@
 
 		if ( cols < 0 || rows < 0 )
-			throw UIException ( "the dimensions of a matrix has to be non-negative", link.result );
+			throw UISettingException ( "UIException: the dimensions of a matrix has to be non-negative.", link.result );
 
 		if ( elements.getLength() != cols * rows )
-			throw UIException ( "the count of the matrix elements is incompatible with matrix dimension", elements );
+			throw UISettingException ( "UIException: the count of the matrix elements is incompatible with matrix dimension.", elements );
 
 		matrix.set_size ( rows, cols );
@@ -265,5 +273,5 @@
 
 		if ( !elements[0].isNumber() )
-			throw UIException ( "matrix elements have to be numbers", elements[0] );
+			throw UISettingException ( "UIException: matrix elements have to be numbers.", elements[0] );
 
 		// build matrix row-wise
@@ -275,5 +283,5 @@
 	}
 
-	throw UIException ( "only numeric types or TypeList are supported as matrix values", link.result );
+	throw UISettingException ( "UIException: only numeric types or TypeList are supported as matrix values.", link.result );
 }
 
@@ -292,5 +300,5 @@
 
 		if ( matrix.cols() != 1 && matrix.rows() != 1 )
-			throw UIException ( "the vector length is invalid, it seems to be rather a matrix", link.result );
+			throw UISettingException ( "UIException: the vector length is invalid, it seems to be rather a matrix.", link.result );
 
 		int len = matrix.rows() * matrix.cols();
@@ -313,5 +321,5 @@
 
 		if ( !link.result[0].isNumber() )
-			throw UIException ( "a vector element has to be a number", link.result[0] );
+			throw UISettingException ( "UIException: a vector element has to be a number.", link.result[0] );
 
 		for ( int i = 0; i < len; i++ )
@@ -321,5 +329,5 @@
 	}
 
-	throw UIException ( "only numeric types, TypeArray or TypeList are supported as vector values", link.result );
+	throw UISettingException ( "UIException: only numeric types, TypeArray or TypeList are supported as vector values.", link.result );
 }
 
