From 65f33c0a63372815223b7286eaa026a13c24391a Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Wed, 16 Oct 2019 11:30:04 +0200
Subject: [PATCH] proper register unregister scheme in file type registraion

---
 .../registration/InputFileTypeRegistration.hpp   | 10 ++++++++--
 .../registration/OutputFileTypeRegistration.hpp  | 10 ++++++++--
 alib2cli/src/registry/InputFileRegistry.cpp      | 16 ++++++++++++++++
 alib2cli/src/registry/InputFileRegistry.hpp      | 11 ++++-------
 alib2cli/src/registry/OutputFileRegistry.cpp     | 16 ++++++++++++++++
 alib2cli/src/registry/OutputFileRegistry.hpp     | 11 ++++-------
 6 files changed, 56 insertions(+), 18 deletions(-)

diff --git a/alib2cli/src/registration/InputFileTypeRegistration.hpp b/alib2cli/src/registration/InputFileTypeRegistration.hpp
index 28cb35ef38..1fd84aa119 100644
--- a/alib2cli/src/registration/InputFileTypeRegistration.hpp
+++ b/alib2cli/src/registration/InputFileTypeRegistration.hpp
@@ -6,9 +6,15 @@
 namespace registration {
 
 class InputFileRegister {
+	std::string m_FileType;
+
 public:
-	InputFileRegister ( const std::string & fileType, std::shared_ptr < abstraction::OperationAbstraction > ( * callback ) ( const std::string & type, const ext::vector < std::string > & templateParams ) ) {
-		abstraction::InputFileRegistry::registerInputFileHandler ( fileType, callback );
+	InputFileRegister ( std::string fileType, std::shared_ptr < abstraction::OperationAbstraction > ( * callback ) ( const std::string & type, const ext::vector < std::string > & templateParams ) ) : m_FileType ( std::move ( fileType ) ) {
+		abstraction::InputFileRegistry::registerInputFileHandler ( m_FileType, callback );
+	}
+
+	~InputFileRegister ( ) {
+		abstraction::InputFileRegistry::unregisterInputFileHandler ( m_FileType );
 	}
 };
 
diff --git a/alib2cli/src/registration/OutputFileTypeRegistration.hpp b/alib2cli/src/registration/OutputFileTypeRegistration.hpp
index 9238b54221..8f81cfbe5c 100644
--- a/alib2cli/src/registration/OutputFileTypeRegistration.hpp
+++ b/alib2cli/src/registration/OutputFileTypeRegistration.hpp
@@ -6,9 +6,15 @@
 namespace registration {
 
 class OutputFileRegister {
+	std::string m_FileType;
+
 public:
-	OutputFileRegister ( const std::string & fileType, std::shared_ptr < abstraction::OperationAbstraction > ( * callback ) ( const std::string & typehint ) ) {
-		abstraction::OutputFileRegistry::registerOutputFileHandler ( fileType, callback );
+	OutputFileRegister ( std::string fileType, std::shared_ptr < abstraction::OperationAbstraction > ( * callback ) ( const std::string & typehint ) ) : m_FileType ( std::move ( fileType ) ) {
+		abstraction::OutputFileRegistry::registerOutputFileHandler ( m_FileType, callback );
+	}
+
+	~OutputFileRegister ( ) {
+		abstraction::OutputFileRegistry::unregisterOutputFileHandler ( m_FileType );
 	}
 };
 
diff --git a/alib2cli/src/registry/InputFileRegistry.cpp b/alib2cli/src/registry/InputFileRegistry.cpp
index e06f0be975..9260784782 100644
--- a/alib2cli/src/registry/InputFileRegistry.cpp
+++ b/alib2cli/src/registry/InputFileRegistry.cpp
@@ -10,6 +10,22 @@
 
 namespace abstraction {
 
+ext::map < std::string, std::unique_ptr < InputFileRegistry::Entry > > & InputFileRegistry::getEntries ( ) {
+	static ext::map < std::string, std::unique_ptr < Entry > > inputFileHandlers;
+	return inputFileHandlers;
+}
+
+void InputFileRegistry::registerInputFileHandler ( const std::string & fileType, std::shared_ptr < abstraction::OperationAbstraction > ( * callback ) ( const std::string & type, const ext::vector < std::string > & templateParams ) ) {
+	auto iter = getEntries ( ).insert ( std::make_pair ( fileType, std::unique_ptr < Entry > ( new EntryImpl ( callback ) ) ) );
+	if ( ! iter.second )
+		throw std::invalid_argument ( "Entry " + iter.first->first + " already registered." );
+}
+
+void InputFileRegistry::unregisterInputFileHandler ( const std::string & fileType ) {
+	if ( getEntries ( ).erase ( fileType ) == 0u )
+		throw std::invalid_argument ( "Entry " + fileType + " not registered." );
+}
+
 std::shared_ptr < abstraction::OperationAbstraction > InputFileRegistry::getAbstraction ( const std::string & fileType, const std::string & type, const ext::vector < std::string > & templateParams ) {
 	auto res = getEntries ( ).find ( fileType );
 	if ( res == getEntries ( ).end ( ) )
diff --git a/alib2cli/src/registry/InputFileRegistry.hpp b/alib2cli/src/registry/InputFileRegistry.hpp
index 796681df33..312ae510b6 100644
--- a/alib2cli/src/registry/InputFileRegistry.hpp
+++ b/alib2cli/src/registry/InputFileRegistry.hpp
@@ -35,15 +35,12 @@ class InputFileRegistry {
 		std::shared_ptr < abstraction::OperationAbstraction > getAbstraction ( const std::string & type, const ext::vector < std::string > & templateParams ) const override;
 	};
 
-	static ext::map < std::string, std::unique_ptr < Entry > > & getEntries ( ) {
-		static ext::map < std::string, std::unique_ptr < Entry > > inputFileHandlers;
-		return inputFileHandlers;
-	}
+	static ext::map < std::string, std::unique_ptr < Entry > > & getEntries ( );
 
 public:
-	static void registerInputFileHandler ( const std::string & fileType, std::shared_ptr < abstraction::OperationAbstraction > ( * callback ) ( const std::string & type, const ext::vector < std::string > & templateParams ) ) {
-		getEntries ( ).insert ( std::make_pair ( fileType, std::unique_ptr < Entry > ( new EntryImpl ( callback ) ) ) );
-	}
+	static void registerInputFileHandler ( const std::string & fileType, std::shared_ptr < abstraction::OperationAbstraction > ( * callback ) ( const std::string & type, const ext::vector < std::string > & templateParams ) );
+
+	static void unregisterInputFileHandler ( const std::string & fileType );
 
 	static std::shared_ptr < abstraction::OperationAbstraction > getAbstraction ( const std::string & fileType, const std::string & type, const ext::vector < std::string > & templateParams );
 };
diff --git a/alib2cli/src/registry/OutputFileRegistry.cpp b/alib2cli/src/registry/OutputFileRegistry.cpp
index 82cbb79331..3a2b2abf8c 100644
--- a/alib2cli/src/registry/OutputFileRegistry.cpp
+++ b/alib2cli/src/registry/OutputFileRegistry.cpp
@@ -10,6 +10,22 @@
 
 namespace abstraction {
 
+ext::map < std::string, std::unique_ptr < OutputFileRegistry::Entry > > & OutputFileRegistry::getEntries ( ) {
+	static ext::map < std::string, std::unique_ptr < Entry > > inputFileHandlers;
+	return inputFileHandlers;
+}
+
+void OutputFileRegistry::registerOutputFileHandler ( const std::string & fileType, std::shared_ptr < abstraction::OperationAbstraction > ( * callback ) ( const std::string & typehint ) ) {
+	auto iter = getEntries ( ).insert ( std::make_pair ( fileType, std::unique_ptr < Entry > ( new EntryImpl ( callback ) ) ) );
+	if ( ! iter.second )
+		throw std::invalid_argument ( "Entry " + iter.first->first + " already registered." );
+}
+
+void OutputFileRegistry::unregisterOutputFileHandler ( const std::string & fileType ) {
+	if ( getEntries ( ).erase ( fileType ) == 0u )
+		throw std::invalid_argument ( "Entry " + fileType + " not registered." );
+}
+
 std::shared_ptr < abstraction::OperationAbstraction > OutputFileRegistry::getAbstraction ( const std::string & fileType, const std::string & typehint ) {
 	auto res = getEntries ( ).find ( fileType );
 	if ( res == getEntries ( ).end ( ) )
diff --git a/alib2cli/src/registry/OutputFileRegistry.hpp b/alib2cli/src/registry/OutputFileRegistry.hpp
index c50d761532..4365f57f4c 100644
--- a/alib2cli/src/registry/OutputFileRegistry.hpp
+++ b/alib2cli/src/registry/OutputFileRegistry.hpp
@@ -35,15 +35,12 @@ class OutputFileRegistry {
 		std::shared_ptr < abstraction::OperationAbstraction > getAbstraction ( const std::string & typehint ) const override;
 	};
 
-	static ext::map < std::string, std::unique_ptr < Entry > > & getEntries ( ) {
-		static ext::map < std::string, std::unique_ptr < Entry > > inputFileHandlers;
-		return inputFileHandlers;
-	}
+	static ext::map < std::string, std::unique_ptr < Entry > > & getEntries ( );
 
 public:
-	static void registerOutputFileHandler ( const std::string & fileType, std::shared_ptr < abstraction::OperationAbstraction > ( * callback ) ( const std::string & typehint ) ) {
-		getEntries ( ).insert ( std::make_pair ( fileType, std::unique_ptr < Entry > ( new EntryImpl ( callback ) ) ) );
-	}
+	static void registerOutputFileHandler ( const std::string & fileType, std::shared_ptr < abstraction::OperationAbstraction > ( * callback ) ( const std::string & typehint ) );
+
+	static void unregisterOutputFileHandler ( const std::string & fileType );
 
 	static std::shared_ptr < abstraction::OperationAbstraction > getAbstraction ( const std::string & fileType, const std::string & typehint );
 };
-- 
GitLab