+/**
+ * @file Common/iregistry.h
+ * @brief Common registry for interfaces
+ * @author Enar Vaikene
+ *
+ * Copyright (c) 2011 Enar Vaikene
+ *
+ * This file is part of the eVaf C++ cross-platform application development framework.
+ *
+ * This file can be used under the terms of the GNU General Public License
+ * version 3.0 as published by the Free Software Foundation and appearing in
+ * the file LICENSE included in the packaging of this file. Please review the
+ * the following information to ensure the GNU General Public License version
+ * 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
+ *
+ * Alternatively, this file may be used in accordance with the Commercial License
+ * Agreement provided with the Software.
+ */
+
+#ifndef __COMMON_IREGISTRY_H
+#define __COMMON_IREGISTRY_H
+
+#include "libcommon.h"
+
+#include <QObject>
+#include <QString>
+
+namespace eVaf {
+namespace Common {
+
+/**
+ * Common registry for interfaces.
+ * @code#include <Common/iRegistry>@endcode
+ *
+ * Registry is a central collection of all the eVaf interfaces and iRegistry the interface for it.
+ * Modules use the iRegistry interface to register new interfaces and query existing ones.
+ *
+ * Existing interfaces are queried with the queryInterface() function. The returned pointer to QObject
+ * shall be type casted to the requested interface class using qobject_cast<>():
+ * @code
+ * iEnv * env = qobject_cast<iEnv *>(iRegistry::instance()->queryInterface("iEnv"));
+ * @endcode
+ *
+ * Or use the evafQueryInterface<>() function:
+ * @code
+ * iEnv * env = evafQueryInterface<iEnv>("iEnv");
+ * @endcode
+ *
+ * Registering new interfaces is done with the registerInterface() function as shown in the following example:
+ * @code
+ * iRegistry::instance()->registerInterface("iSample", this);
+ * @endcode
+ *
+ * In general, every interface should have a unique name. If an interface is registered with a name that already
+ * exists, then the new interface overwrites the old interface with the same name. To reimplement an interface,
+ * query for the old implementation, store it and then register a new interface with the same name.
+ *
+ * Any class implementing an interface shall have QObject as their top-most parent.
+ *
+ * <b>iRegistry and instance() functions</b>
+ *
+ * Most of the interfaces have the instance() function that returns the current instance of the interface.
+ * The main difference is that by using the instance() function, modules shall link against the module
+ * that implements the interface's instance() function. The iRegistry interface can be used to get the same
+ * interface without knowing the module that implements it.
+ */
+class COMMON_EXPORT iRegistry : public QObject
+{
+ Q_OBJECT
+
+public:
+
+ /// Interface constructor
+ iRegistry() : QObject() {}
+
+ /// Empty virtual destructor
+ virtual ~iRegistry() {}
+
+ /**
+ * Returns the iRegistry interface instance
+ * @return The iRegistry interface
+ *
+ * This function returns the global iRegistry interface instance. All eVaf modules and applications
+ * are expected to be linked against the common library and this is the only method of obtaining
+ * the iRegistry interface.
+ */
+ static iRegistry * instance();
+
+ /**
+ * Registers an interface
+ * @param name Name of the interface
+ * @param obj Object implementing the interface
+ * @return True if ok; false if registering failed
+ *
+ * This function registers a new interface in the global registry of interfaces.
+ *
+ * If an interface with this name already exists, then the new interface implementation overwrites the old
+ * implementation.
+ */
+ virtual bool registerInterface(QString const & name, QObject * obj) = 0;
+
+ /**
+ * Returns the interface by its name
+ * @param name Name of the interface
+ * @return Interface implementation or NULL if not found.
+ *
+ * This function queries the global registry for the interface by its name. It returns a pointer
+ * to the implementation of the interface or NULL if no such interface is found.
+ *
+ * Use the qobject_cast<>() function to type cast the returned pointer to the required interface class.
+ * Always check for NULL in case there is a mismatch in interface versions or no such interface is found.
+ */
+ virtual QObject * queryInterface(QString const & name) const = 0;
+
+};
+
+} // namespace eVaf::Common
+} // namespace eVaf
+
+/**
+ * Helper function for querying interfaces
+ * @param name Name of the requested interface
+ * @return The requested interface or NULL if not found
+ *
+ * This function can be used to query interfaces from the global registry. It returns a properly
+ * type-casted interface or NULL if the interface cannot be found or is of an invalid type.
+ *
+ * Example:
+ * @code
+ * iEnv * env = evafQueryInterface<iEnv>("iEnv");
+ * if (env) {
+ * // Use the interface
+ * }
+ * @endcode
+ */
+template<typename T>
+inline T * evafQueryInterface(QString const & name)
+{
+ return qobject_cast<T *>(eVaf::Common::iRegistry::instance()->queryInterface(name));
+}
+
+#endif // iregistry.h