text: /*********************************************************************************
   *
   * Inviwo - Interactive Visualization Workshop
   *
   * Copyright (c) 2015-2019 Inviwo Foundation
   * All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions are met:
   *
   * 1. Redistributions of source code must retain the above copyright notice, this
   * list of conditions and the following disclaimer.
   * 2. Redistributions in binary form must reproduce the above copyright notice,
   * this list of conditions and the following disclaimer in the documentation
   * and/or other materials provided with the distribution.
   *
   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
   * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   *
   *********************************************************************************/
  
  #ifndef IVW_INVIWOMODULEFACTORYOBJECT_H
  #define IVW_INVIWOMODULEFACTORYOBJECT_H
  
  #include <inviwo/core/common/inviwocoredefine.h>
  #include <inviwo/core/common/inviwo.h>
  #include <inviwo/core/common/version.h>
  #include <inviwo/core/util/licenseinfo.h>
  #include <inviwo/core/util/stdextensions.h>
  
  namespace inviwo {
  
  class InviwoModule;
  class InviwoApplication;
  
  // A protected module does not participate in runtime reloading
  enum class ProtectedModule : bool { on, off };
  
  class IVW_CORE_API InviwoModuleFactoryObject {
  public:
      InviwoModuleFactoryObject(const std::string& name, Version version,
                                const std::string& description, Version inviwoCoreVersion,
                                std::vector<std::string> dependencies,
                                std::vector<Version> dependenciesVersion,
                                std::vector<std::string> aliases, std::vector<LicenseInfo> licenses,
                                ProtectedModule protectedModule);
      virtual ~InviwoModuleFactoryObject() = default;
  
      virtual std::unique_ptr<InviwoModule> create(InviwoApplication* app) = 0;
  
      const std::string name;           // Module name
      const Version version;            // Module version (Major.Minor.Patch)
      const std::string description;    // Module description
      const Version inviwoCoreVersion;  // Supported inviwo core version (Major.Minor.Patch)
      // Module dependencies Major.Minor.Patch version of each dependency
      const std::vector<std::pair<std::string, Version>> dependencies;
      // A module can have one or more aliases. Several modules can have the same alias. Useful when
      // several modules implement the same functionality
      const std::vector<std::string> aliases;
      // License information related to the module
      const std::vector<LicenseInfo> licenses;
      // A protected module does not participate in runtime reloading
      const ProtectedModule protectedModule;
  };
  
  template <typename T>
  class InviwoModuleFactoryObjectTemplate : public InviwoModuleFactoryObject {
  public:
      InviwoModuleFactoryObjectTemplate(const std::string& name, Version version,
                                        const std::string& description, Version inviwoCoreVersion,
                                        std::vector<std::string> dependencies,
                                        std::vector<Version> dependenciesVersion,
                                        std::vector<std::string> aliases,
                                        std::vector<LicenseInfo> licenses,
                                        ProtectedModule protectedModule);
  
      virtual std::unique_ptr<InviwoModule> create(InviwoApplication* app) override {
          return std::make_unique<T>(app);
      }
  };
  
  // Function pointer for exported module factory creation function in dynamic library.
  // Will be generated by globalmacros.cmake in function ivw_private_generate_module_registration_file
  // Returns a pointer to a InviwoModuleFactoryObject without any input arguments
  #ifdef WIN32
  // __stdcall is the convention used by the WinAPI
  using f_getModule = InviwoModuleFactoryObject*(__stdcall*)();
  #else
  using f_getModule = InviwoModuleFactoryObject* (*)();
  #endif
  
  template <typename T>
  InviwoModuleFactoryObjectTemplate<T>::InviwoModuleFactoryObjectTemplate(
      const std::string& name, Version version, const std::string& description,
      Version inviwoCoreVersion, std::vector<std::string> dependencies,
      std::vector<Version> dependenciesVersion, std::vector<std::string> aliases,
      std::vector<LicenseInfo> licenses, ProtectedModule protectedModule)
      : InviwoModuleFactoryObject(name, version, description, inviwoCoreVersion, dependencies,
                                  dependenciesVersion, aliases, licenses, protectedModule) {}
  
  /**
   * \brief Topological sort to make sure that we load modules in correct order
   *
   * https://en.wikipedia.org/wiki/Topological_sorting#Depth-first_search
   *
   * @param start Start of range to sort
   * @param end End of range to sort
   */
  IVW_CORE_API void topologicalModuleFactoryObjectSort(
      std::vector<std::unique_ptr<InviwoModuleFactoryObject>>::iterator start,
      std::vector<std::unique_ptr<InviwoModuleFactoryObject>>::iterator end);
  
  }  // namespace inviwo
  
  #endif  // IVW_INVIWOMODULEFACTORYOBJECT_H
  