From fe678b1ee8b6a27ad1dca06777a4ce06ff08781b Mon Sep 17 00:00:00 2001
From: Jan Travnicek <Jan.Travnicek@fit.cvut.cz>
Date: Wed, 12 Aug 2015 21:08:59 +0200
Subject: [PATCH] refactor cast capability to be fully dynamic

---
 acast2/src/CastVisitorBase.hpp                | 114 ------------------
 acast2/src/acast.cpp                          |  77 ++----------
 acast2/src/cast/AutomatonCastVisitor.cpp      |  19 ---
 acast2/src/cast/AutomatonCastVisitor.h        |  13 --
 acast2/src/cast/GrammarCastVisitor.cpp        |  18 ---
 acast2/src/cast/GrammarCastVisitor.h          |  13 --
 acast2/src/cast/RegExpCastVisitor.cpp         |  18 ---
 acast2/src/cast/RegExpCastVisitor.h           |  13 --
 acast2/src/cast/TreeCastVisitor.cpp           |  18 ---
 acast2/src/cast/TreeCastVisitor.h             |  13 --
 acast2/src/cast/TreeToStringCastVisitor.cpp   |  19 ---
 acast2/src/cast/TreeToStringCastVisitor.h     |  14 ---
 alib2data/src/CastApi.hpp                     | 101 ++++++++++++++++
 alib2data/src/automaton/FSM/CompactNFA.cpp    |   7 ++
 alib2data/src/automaton/FSM/EpsilonNFA.cpp    |   6 +
 alib2data/src/automaton/FSM/ExtendedNFA.cpp   |   8 ++
 .../automaton/FSM/MultiInitialStateNFA.cpp    |   5 +
 alib2data/src/automaton/FSM/NFA.cpp           |   4 +
 alib2data/src/regexp/formal/FormalRegExp.cpp  |   4 +
 .../src/regexp/unbounded/UnboundedRegExp.cpp  |   4 +
 alib2data/src/string/CyclicString.cpp         |   4 +
 alib2data/src/string/LinearString.cpp         |   5 +
 .../src/tree/ranked/PrefixRankedPattern.cpp   |   4 +
 .../src/tree/ranked/PrefixRankedTree.cpp      |   4 +
 24 files changed, 164 insertions(+), 341 deletions(-)
 delete mode 100644 acast2/src/CastVisitorBase.hpp
 delete mode 100644 acast2/src/cast/AutomatonCastVisitor.cpp
 delete mode 100644 acast2/src/cast/AutomatonCastVisitor.h
 delete mode 100644 acast2/src/cast/GrammarCastVisitor.cpp
 delete mode 100644 acast2/src/cast/GrammarCastVisitor.h
 delete mode 100644 acast2/src/cast/RegExpCastVisitor.cpp
 delete mode 100644 acast2/src/cast/RegExpCastVisitor.h
 delete mode 100644 acast2/src/cast/TreeCastVisitor.cpp
 delete mode 100644 acast2/src/cast/TreeCastVisitor.h
 delete mode 100644 acast2/src/cast/TreeToStringCastVisitor.cpp
 delete mode 100644 acast2/src/cast/TreeToStringCastVisitor.h
 create mode 100644 alib2data/src/CastApi.hpp

diff --git a/acast2/src/CastVisitorBase.hpp b/acast2/src/CastVisitorBase.hpp
deleted file mode 100644
index 38aa6ceb72..0000000000
--- a/acast2/src/CastVisitorBase.hpp
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * acast.cpp
- *
- *  Created on: 24. 2. 2014
- *      Author: Jan Travnicek
- */
-
-#include <exception/AlibException.h>
-#include <factory/XmlDataFactory.hpp>
-#include <type_traits>
-
-template<typename ToType, typename FromType, typename std::enable_if< std::is_constructible<ToType, FromType>::value >::type* = nullptr >
-ToType cast(const FromType& orig) {
-	return ToType(orig);
-}
-
-template<typename ToType, typename FromType, typename std::enable_if< ! std::is_constructible<ToType, FromType>::value >::type* = nullptr >
-ToType cast(const FromType& /* orig */) {
-	throw exception::AlibException(std::string("Invalid cast from ") + typeid(FromType).name() + " to " + typeid(ToType).name());
-}
-
-// --------------------------------------------------------------------------------------------------------------
-
-template<typename FromBaseVisitor, typename ToType, typename ToWrapper, typename ... FromTypes>
-class cast_implementer_helper;
-
-template<typename FromBaseVisitor, typename ToType, typename ToWrapper>
-class cast_implementer_helper< FromBaseVisitor, ToType, ToWrapper > : public FromBaseVisitor {
-
-};
-
-template<typename FromBaseVisitor, typename ToType, typename ToWrapper, typename FromType, typename ... FromTypes>
-class cast_implementer_helper<FromBaseVisitor, ToType, ToWrapper, FromType, FromTypes ...> : public cast_implementer_helper<FromBaseVisitor, ToType, ToWrapper, FromTypes ...> {
-public:
-#ifdef __llvm__
-	using cast_implementer_helper<FromBaseVisitor, ToType, ToWrapper, FromTypes ...>::Visit;
-#endif
-
-	void Visit(void*, const FromType& orig) const;
-};
-
-template<typename FromBaseVisitor, typename ToType, typename ToWrapper, typename FromType, typename ... FromTypes>
-void cast_implementer_helper<FromBaseVisitor, ToType, ToWrapper, FromType, FromTypes ...>::Visit(void* data, const FromType& orig) const {
-	ToWrapper* & out = *((ToWrapper**) data);
-	out = new ToWrapper(cast<ToType, FromType>(orig));
-}
-
-// --------------------------------------------------------------------------------------------------------------------
-
-template<typename FromBaseVisitor, typename FromBase, typename ToWrapper, typename ToType, typename FromTypes>
-class cast_implementer {
-};
-
-template<typename FromBaseVisitor, typename FromBase, typename ToWrapper, typename ToType, typename ... FromTypes>
-class cast_implementer< FromBaseVisitor, FromBase, ToWrapper, ToType, std::tuple< FromTypes ... > > : public cast_implementer_helper< FromBaseVisitor, ToType, ToWrapper, FromTypes ... > {
-public:
-	using cast_implementer_helper<FromBaseVisitor, ToType, ToWrapper, FromTypes ... >::Visit;
-
-	static ToWrapper cast(const FromBase& obj);
-};
-
-template<typename FromBaseVisitor, typename FromBase, typename ToWrapper, typename ToType, typename ... FromTypes>
-ToWrapper cast_implementer<FromBaseVisitor, FromBase, ToWrapper, ToType, std::tuple< FromTypes ... > >::cast(const FromBase& obj) {
-	cast_implementer<FromBaseVisitor, FromBase, ToWrapper, ToType, std::tuple< FromTypes ... > > tmp;
-	ToWrapper* out = NULL;
-	obj.Accept((void*) &out, tmp);
-	ToWrapper res = std::move(*out);
-	delete out;
-	return res;
-}
-
-// ----------------------------------------------------------------------------------------
-
-template<typename FromBaseVisitor, typename FromBase, typename FromTypes, typename ToWrapper, typename ... ToTypes >
-class cast_helper;
-
-template<typename FromBaseVisitor, typename FromBase, typename FromTypes, typename ToWrapper >
-class cast_helper<FromBaseVisitor, FromBase, FromTypes, ToWrapper> {
-public:
-	static ToWrapper do_cast(const std::string&, const FromBase&/* obj*/) {
-		throw exception::AlibException("invalid type specified");
-	}
-};
-
-template<typename FromBaseVisitor, typename FromBase, typename FromTypes, typename ToWrapper, typename ToType, typename ... ToTypes >
-class cast_helper< FromBaseVisitor, FromBase, FromTypes, ToWrapper, ToType, ToTypes ... > : public cast_helper< FromBaseVisitor, FromBase, FromTypes, ToWrapper, ToTypes ...> {
-public:
-	static ToWrapper do_cast(const std::string& name, const FromBase& obj);
-};
-
-template<typename FromBaseVisitor, typename FromBase, typename FromTypes, typename ToWrapper, typename ToType, typename ... ToTypes >
-ToWrapper cast_helper<FromBaseVisitor, FromBase, FromTypes, ToWrapper, ToType, ToTypes ...>::do_cast(const std::string& name, const FromBase& obj) {
-	if(std::is_same_type<ToType>(name.c_str())) {
-		return cast_implementer<FromBaseVisitor, FromBase, ToWrapper, ToType, FromTypes>::cast(obj);
-	} else {
-		return cast_helper<FromBaseVisitor, FromBase, FromTypes, ToWrapper, ToTypes ...>::do_cast(name, obj);
-	}
-}
-
-// -----------------------------------------------------------------------------------------
-
-// visitor, fromType (base), toType (wrapper), possible from types, possible to types
-
-template<typename FromBaseVisitor, typename FromBase, typename FromTypes, typename ToWrapper, typename ToTypes>
-class cast_base_helper {
-};
-
-template<typename FromBaseVisitor, typename FromBase, typename ... FromTypes, typename ToWrapper, typename ... ToTypes>
-class cast_base_helper< FromBaseVisitor, FromBase, std::tuple<FromTypes ...>, ToWrapper, std::tuple< ToTypes ... > > : public cast_helper< FromBaseVisitor, FromBase, std::tuple< FromTypes ...>, ToWrapper, ToTypes ... > {
-public:
-
-};
-
-//typedef cast_base_helper< alib::VisitableObjectBase::const_visitor_type, alib::ObjectBase, alib::Types > ObjectCastVisitor;
diff --git a/acast2/src/acast.cpp b/acast2/src/acast.cpp
index 0cd74c1ee1..407b93f4ec 100644
--- a/acast2/src/acast.cpp
+++ b/acast2/src/acast.cpp
@@ -12,13 +12,7 @@
 #include <sax/SaxParseInterface.h>
 #include <sax/ParserException.h>
 #include <object/Object.h>
-#include <string/LinearString.h>
-
-#include "cast/AutomatonCastVisitor.h"
-#include "cast/GrammarCastVisitor.h"
-#include "cast/RegExpCastVisitor.h"
-#include "cast/TreeCastVisitor.h"
-#include "cast/TreeToStringCastVisitor.h"
+#include "CastApi.hpp"
 
 // -----------------------------------------------------------------------------------------
 
@@ -53,72 +47,17 @@ int main(int argc, char** argv) {
 			sax::SaxParseInterface::parseStdin(tokens);
 		}
 
-		/*alib::Object object = alib::XmlDataFactory::fromTokens<alib::Object>(tokens);
-		CastBaseVisitor::do_cast(type.getValue(), object.getData());*/
-
-		if(alib::XmlDataFactory::first<tree::PrefixRankedTree>(tokens) && std::is_same_type<string::LinearString>(type.getValue().c_str())) {
-			tree::Tree tree = alib::XmlDataFactory::fromTokens<tree::Tree>(tokens);
-
-			std::chrono::measurements::end();
-			std::chrono::measurements::start("Cast", std::chrono::measurements::Type::MAIN);
-
-			string::String res = TreeToStringCastVisitor::doCast(type.getValue(), tree);
-
-			std::chrono::measurements::end();
-			std::chrono::measurements::start("Output write", std::chrono::measurements::Type::AUXILARY);
-
-			alib::XmlDataFactory::toStdout(res);
-		} else if(alib::XmlDataFactory::first<automaton::Automaton>(tokens)) {
-			automaton::Automaton automaton = alib::XmlDataFactory::fromTokens<automaton::Automaton>(tokens);
-
-			std::chrono::measurements::end();
-			std::chrono::measurements::start("Cast", std::chrono::measurements::Type::MAIN);
-
-			automaton::Automaton res = AutomatonCastVisitor::doCast(type.getValue(), automaton);
-
-			std::chrono::measurements::end();
-			std::chrono::measurements::start("Output write", std::chrono::measurements::Type::AUXILARY);
-
-			alib::XmlDataFactory::toStdout(res);
-		} else if(alib::XmlDataFactory::first<grammar::Grammar>(tokens)) {
-			grammar::Grammar grammar = alib::XmlDataFactory::fromTokens<grammar::Grammar>(tokens);
-
-			std::chrono::measurements::end();
-			std::chrono::measurements::start("Cast", std::chrono::measurements::Type::MAIN);
+		alib::Object in = alib::XmlDataFactory::fromTokens<alib::Object>(tokens);
 
-			grammar::Grammar res = GrammarCastVisitor::doCast(type.getValue(), grammar);
-
-			std::chrono::measurements::end();
-			std::chrono::measurements::start("Output write", std::chrono::measurements::Type::AUXILARY);
-
-			alib::XmlDataFactory::toStdout(res);
-		} else if(alib::XmlDataFactory::first<regexp::RegExp>(tokens)) {
-			regexp::RegExp regexp = alib::XmlDataFactory::fromTokens<regexp::RegExp>(tokens);
-
-			std::chrono::measurements::end();
-			std::chrono::measurements::start("Cast", std::chrono::measurements::Type::MAIN);
-
-			regexp::RegExp res = RegExpCastVisitor::doCast(type.getValue(), regexp);
-
-			std::chrono::measurements::end();
-			std::chrono::measurements::start("Output write", std::chrono::measurements::Type::AUXILARY);
-
-			alib::XmlDataFactory::toStdout(res);
-		} else if(alib::XmlDataFactory::first<tree::Tree>(tokens)) {
-			tree::Tree tree = alib::XmlDataFactory::fromTokens<tree::Tree>(tokens);
-
-			std::chrono::measurements::end();
-			std::chrono::measurements::start("Cast", std::chrono::measurements::Type::MAIN);
+		std::chrono::measurements::end();
+		std::chrono::measurements::start("Cast", std::chrono::measurements::Type::MAIN);
 
-			tree::Tree res = TreeCastVisitor::doCast(type.getValue(), tree);
+		alib::Object res = alib::castApi::getCastPool(type.getValue()).cast(in.getData());
 
-			std::chrono::measurements::end();
-			std::chrono::measurements::start("Output write", std::chrono::measurements::Type::AUXILARY);
+		std::chrono::measurements::end();
+		std::chrono::measurements::start("Output write", std::chrono::measurements::Type::AUXILARY);
 
-			alib::XmlDataFactory::toStdout(res);
-		} else {
-			throw exception::AlibException(std::string("Invalid cast from to ") + type.getValue());
-		}
+		alib::XmlDataFactory::toStdout(res);
 
 		std::chrono::measurements::end();
 		std::chrono::measurements::end();
diff --git a/acast2/src/cast/AutomatonCastVisitor.cpp b/acast2/src/cast/AutomatonCastVisitor.cpp
deleted file mode 100644
index 37b3bdc700..0000000000
--- a/acast2/src/cast/AutomatonCastVisitor.cpp
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * AutomatonCastVisitor.cpp
- *
- *  Created on: 24. 2. 2014
- *      Author: Jan Travnicek
- */
-
-#include "AutomatonCastVisitor.h"
-#include "automaton/AutomatonClasses.h"
-
-#include "../CastVisitorBase.hpp"
-
-// fromVisitor, fromType (base), possible from types, toType (wrapper), possible to types
-typedef cast_base_helper< automaton::VisitableAutomatonBase::const_visitor_type, automaton::AutomatonBase, alib::AutomatonTypes, automaton::Automaton, alib::AutomatonTypes > AutomatonCastVisitorType;
-
-automaton::Automaton AutomatonCastVisitor::doCast(const std::string& name, const automaton::Automaton& orig) {
-	return AutomatonCastVisitorType::do_cast(name, orig.getData());
-}
-
diff --git a/acast2/src/cast/AutomatonCastVisitor.h b/acast2/src/cast/AutomatonCastVisitor.h
deleted file mode 100644
index 7168ca422a..0000000000
--- a/acast2/src/cast/AutomatonCastVisitor.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * AutomatonCastVisitor.h
- *
- *  Created on: 24. 2. 2014
- *      Author: Jan Travnicek
- */
-#include <string>
-#include <automaton/Automaton.h>
-
-class AutomatonCastVisitor {
-public:
-	static automaton::Automaton doCast(const std::string& name, const automaton::Automaton& automaton);
-};
diff --git a/acast2/src/cast/GrammarCastVisitor.cpp b/acast2/src/cast/GrammarCastVisitor.cpp
deleted file mode 100644
index 3b03a0d720..0000000000
--- a/acast2/src/cast/GrammarCastVisitor.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * GrammarCastVisitor.cpp
- *
- *  Created on: 24. 2. 2014
- *      Author: Jan Travnicek
- */
-
-#include "GrammarCastVisitor.h"
-#include "grammar/GrammarClasses.h"
-
-#include "../CastVisitorBase.hpp"
-
-typedef cast_base_helper< grammar::VisitableGrammarBase::const_visitor_type, grammar::GrammarBase, alib::GrammarTypes, grammar::Grammar, alib::GrammarTypes > GrammarCastVisitorType;
-
-grammar::Grammar GrammarCastVisitor::doCast(const std::string& name, const grammar::Grammar& orig) {
-	return GrammarCastVisitorType::do_cast(name, orig.getData());
-}
-
diff --git a/acast2/src/cast/GrammarCastVisitor.h b/acast2/src/cast/GrammarCastVisitor.h
deleted file mode 100644
index 72d043ed2f..0000000000
--- a/acast2/src/cast/GrammarCastVisitor.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * GrammarCastVisitor.h
- *
- *  Created on: 24. 2. 2014
- *      Author: Jan Travnicek
- */
-#include <string>
-#include <grammar/Grammar.h>
-
-class GrammarCastVisitor {
-public:
-	static grammar::Grammar doCast(const std::string& name, const grammar::Grammar& grammar);
-};
diff --git a/acast2/src/cast/RegExpCastVisitor.cpp b/acast2/src/cast/RegExpCastVisitor.cpp
deleted file mode 100644
index f09cc12843..0000000000
--- a/acast2/src/cast/RegExpCastVisitor.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * RegExpCastVisitor.cpp
- *
- *  Created on: 24. 2. 2014
- *      Author: Jan Travnicek
- */
-
-#include "RegExpCastVisitor.h"
-#include "regexp/RegExpClasses.h"
-
-#include "../CastVisitorBase.hpp"
-
-typedef cast_base_helper< regexp::VisitableRegExpBase::const_visitor_type, regexp::RegExpBase, alib::RegExpTypes, regexp::RegExp, alib::RegExpTypes > RegExpCastVisitorType;
-
-regexp::RegExp RegExpCastVisitor::doCast(const std::string& name, const regexp::RegExp& orig) {
-	return RegExpCastVisitorType::do_cast(name, orig.getData());
-}
-
diff --git a/acast2/src/cast/RegExpCastVisitor.h b/acast2/src/cast/RegExpCastVisitor.h
deleted file mode 100644
index f815f9a64a..0000000000
--- a/acast2/src/cast/RegExpCastVisitor.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * RegExpCastVisitor.h
- *
- *  Created on: 24. 2. 2014
- *      Author: Jan Travnicek
- */
-#include <string>
-#include <regexp/RegExp.h>
-
-class RegExpCastVisitor {
-public:
-	static regexp::RegExp doCast(const std::string& name, const regexp::RegExp& regexp);
-};
diff --git a/acast2/src/cast/TreeCastVisitor.cpp b/acast2/src/cast/TreeCastVisitor.cpp
deleted file mode 100644
index df1aa8c0ae..0000000000
--- a/acast2/src/cast/TreeCastVisitor.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-/*
- * TreeCastVisitor.cpp
- *
- *  Created on: 24. 2. 2014
- *      Author: Jan Travnicek
- */
-
-#include "TreeCastVisitor.h"
-#include "tree/TreeClasses.h"
-
-#include "../CastVisitorBase.hpp"
-
-typedef cast_base_helper< tree::VisitableTreeBase::const_visitor_type, tree::TreeBase, alib::TreeTypes, tree::Tree, alib::TreeTypes > TreeCastVisitorType;
-
-tree::Tree TreeCastVisitor::doCast(const std::string& name, const tree::Tree& orig) {
-	return TreeCastVisitorType::do_cast(name, orig.getData());
-}
-
diff --git a/acast2/src/cast/TreeCastVisitor.h b/acast2/src/cast/TreeCastVisitor.h
deleted file mode 100644
index 0266f313e9..0000000000
--- a/acast2/src/cast/TreeCastVisitor.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * TreeCastVisitor.h
- *
- *  Created on: 24. 2. 2014
- *      Author: Jan Travnicek
- */
-#include <string>
-#include <tree/Tree.h>
-
-class TreeCastVisitor {
-public:
-	static tree::Tree doCast(const std::string& name, const tree::Tree& tree);
-};
diff --git a/acast2/src/cast/TreeToStringCastVisitor.cpp b/acast2/src/cast/TreeToStringCastVisitor.cpp
deleted file mode 100644
index 90b45d1f34..0000000000
--- a/acast2/src/cast/TreeToStringCastVisitor.cpp
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * TreeCastVisitor.cpp
- *
- *  Created on: 24. 2. 2014
- *      Author: Jan Travnicek
- */
-
-#include "TreeToStringCastVisitor.h"
-#include "string/StringClasses.h"
-#include "tree/TreeClasses.h"
-
-#include "../CastVisitorBase.hpp"
-
-typedef cast_base_helper< tree::VisitableTreeBase::const_visitor_type, tree::TreeBase, alib::TreeTypes, string::String, alib::StringTypes > TreeToStringCastVisitorType;
-
-string::String TreeToStringCastVisitor::doCast(const std::string& name, const tree::Tree& orig) {
-	return TreeToStringCastVisitorType::do_cast(name, orig.getData());
-}
-
diff --git a/acast2/src/cast/TreeToStringCastVisitor.h b/acast2/src/cast/TreeToStringCastVisitor.h
deleted file mode 100644
index 1e87230f06..0000000000
--- a/acast2/src/cast/TreeToStringCastVisitor.h
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * TreeCastVisitor.h
- *
- *  Created on: 24. 2. 2014
- *      Author: Jan Travnicek
- */
-#include <string>
-#include <tree/Tree.h>
-#include <string/String.h>
-
-class TreeToStringCastVisitor {
-public:
-	static string::String doCast(const std::string& name, const tree::Tree& tree);
-};
diff --git a/alib2data/src/CastApi.hpp b/alib2data/src/CastApi.hpp
new file mode 100644
index 0000000000..93fa69286f
--- /dev/null
+++ b/alib2data/src/CastApi.hpp
@@ -0,0 +1,101 @@
+/*
+ * CastApi.hpp
+ *
+ * Created on: Apr 1, 2013
+ * Author: Jan Travnicek
+ */
+
+#ifndef CAST_API_HPP_
+#define CAST_API_HPP_
+
+#include <functional>
+#include <map>
+#include <string>
+
+#include "object/ObjectBase.h"
+#include "object/Object.h"
+
+namespace alib {
+
+struct castApi {
+	class CastPoolBase {
+	protected:
+		std::map<long long, std::function<alib::Object(const alib::ObjectBase&)>> castFunctions;
+
+	public:
+		alib::Object cast(const alib::ObjectBase& from) {
+			std::map<long long, std::function<alib::Object(const alib::ObjectBase&)>>::iterator res = castFunctions.find(from.selfTypeId());
+			if(res == castFunctions.end())
+				throw std::bad_cast();
+			return res->second(from);
+		}
+	};
+
+	template<class To>
+	class CastPool : public CastPoolBase {
+	public:
+		template<class From>
+		void add() {
+			int a = 0;
+			castFunctions.insert(std::make_pair(From::typeId((const From&) a), [](const alib::ObjectBase& from) { return alib::Object(To((const From&) from)); } ));
+		}
+
+	};
+
+private:
+	// INFO: Function exist to handle static order of initialisation
+	static std::map<long long, CastPoolBase*>& castFunctionsById() {
+		static std::map<long long, CastPoolBase*> res;
+		return res;
+	}
+
+	// INFO: Function exist to handle static order of initialisation
+	static std::map<std::string, CastPoolBase*>& castFunctionsByString() {
+		static std::map<std::string, CastPoolBase*> res;
+		return res;
+	}
+
+public:
+	template<class To>
+	static CastPool<To>& getCastPool() {
+		int a = 0;
+		std::map<long long, CastPoolBase*>::iterator res = castFunctionsById().find(To::typeId((const To&) a));
+		if(res == castFunctionsById().end()) {
+			CastPool<To>* castPool = new CastPool<To>();
+			castPool->template add<To>();
+			return * (CastPool<To>*) ( castFunctionsById().insert(std::make_pair(To::typeId((const To&) a), castPool)).first->second );
+		} else {
+			return * (CastPool<To>*) res->second;
+		}
+	}
+
+	static CastPoolBase& getCastPool(const std::string& tagName) {
+		std::map<std::string, CastPoolBase*>::iterator res = castFunctionsByString().find(tagName);
+		if(res == castFunctionsByString().end()) {
+			throw std::invalid_argument("Casting to type " + tagName + " not available.");
+		} else {
+			return * res->second;
+		}
+	}
+
+	template<class To>
+	class CastPoolStringBinder {
+	public:
+		CastPoolStringBinder(std::string tagName) {
+			castFunctionsByString().insert(std::make_pair(tagName, & getCastPool<To>()));
+		}
+
+	};
+
+	template<class To, class From>
+	class CastRegister {
+	public:
+		CastRegister() {
+			getCastPool<To>().template add<From>();
+		}
+	};
+};
+
+} /* namespace alib */
+
+#endif /* CAST_API_HPP_ */
diff --git a/alib2data/src/automaton/FSM/CompactNFA.cpp b/alib2data/src/automaton/FSM/CompactNFA.cpp
index 78834a9fcd..16f06b909b 100644
--- a/alib2data/src/automaton/FSM/CompactNFA.cpp
+++ b/alib2data/src/automaton/FSM/CompactNFA.cpp
@@ -21,6 +21,7 @@
 #include "../Automaton.h"
 #include "../../object/Object.h"
 #include "../../XmlApi.hpp"
+#include "../../CastApi.hpp"
 
 namespace automaton {
 
@@ -256,4 +257,10 @@ namespace alib {
 xmlApi<automaton::Automaton>::ParserRegister<automaton::CompactNFA> compactNFAParserRegister = xmlApi<automaton::Automaton>::ParserRegister<automaton::CompactNFA>(automaton::CompactNFA::XML_TAG_NAME, automaton::CompactNFA::parse);
 xmlApi<alib::Object>::ParserRegister<automaton::CompactNFA> compactNFAParserRegister2 = xmlApi<alib::Object>::ParserRegister<automaton::CompactNFA>(automaton::CompactNFA::XML_TAG_NAME, automaton::CompactNFA::parse);
 
+auto CompactNFAFromDFA = castApi::CastRegister<automaton::CompactNFA, automaton::DFA>();
+auto CompactNFAFromNFA = castApi::CastRegister<automaton::CompactNFA, automaton::NFA>();
+auto CompactNFAFromMultiInitialStateNFA = castApi::CastRegister<automaton::CompactNFA, automaton::MultiInitialStateNFA>();
+auto CompactNFAEpsilonNFA = castApi::CastRegister<automaton::CompactNFA, automaton::EpsilonNFA>();
+auto CompactNFACastBinder = castApi::CastPoolStringBinder<automaton::CompactNFA>(automaton::CompactNFA::XML_TAG_NAME);
+
 } /* namespace alib */
diff --git a/alib2data/src/automaton/FSM/EpsilonNFA.cpp b/alib2data/src/automaton/FSM/EpsilonNFA.cpp
index ec2845b216..0233e29ccb 100644
--- a/alib2data/src/automaton/FSM/EpsilonNFA.cpp
+++ b/alib2data/src/automaton/FSM/EpsilonNFA.cpp
@@ -20,6 +20,7 @@
 #include "../Automaton.h"
 #include "../../object/Object.h"
 #include "../../XmlApi.hpp"
+#include "../../CastApi.hpp"
 
 namespace automaton {
 
@@ -345,4 +346,9 @@ namespace alib {
 xmlApi<automaton::Automaton>::ParserRegister<automaton::EpsilonNFA> epsilonNFAParserRegister = xmlApi<automaton::Automaton>::ParserRegister<automaton::EpsilonNFA>(automaton::EpsilonNFA::XML_TAG_NAME, automaton::EpsilonNFA::parse);
 xmlApi<alib::Object>::ParserRegister<automaton::EpsilonNFA> epsilonNFAParserRegister2 = xmlApi<alib::Object>::ParserRegister<automaton::EpsilonNFA>(automaton::EpsilonNFA::XML_TAG_NAME, automaton::EpsilonNFA::parse);
 
+auto EpsilonNFAFromDFA = castApi::CastRegister<automaton::EpsilonNFA, automaton::DFA>();
+auto EpsilonNFAFromNFA = castApi::CastRegister<automaton::EpsilonNFA, automaton::NFA>();
+auto EpsilonNFAFromMultiInitialStateNFA = castApi::CastRegister<automaton::EpsilonNFA, automaton::MultiInitialStateNFA>();
+auto EpsilonNFACastBinder = castApi::CastPoolStringBinder<automaton::EpsilonNFA>(automaton::EpsilonNFA::XML_TAG_NAME);
+
 } /* namespace alib */
diff --git a/alib2data/src/automaton/FSM/ExtendedNFA.cpp b/alib2data/src/automaton/FSM/ExtendedNFA.cpp
index e37ca4e82d..00de1706cb 100644
--- a/alib2data/src/automaton/FSM/ExtendedNFA.cpp
+++ b/alib2data/src/automaton/FSM/ExtendedNFA.cpp
@@ -24,6 +24,7 @@
 #include "../Automaton.h"
 #include "../../object/Object.h"
 #include "../../XmlApi.hpp"
+#include "../../CastApi.hpp"
 
 namespace automaton {
 
@@ -267,4 +268,11 @@ namespace alib {
 xmlApi<automaton::Automaton>::ParserRegister<automaton::ExtendedNFA> extendedNFAParserRegister = xmlApi<automaton::Automaton>::ParserRegister<automaton::ExtendedNFA>(automaton::ExtendedNFA::XML_TAG_NAME, automaton::ExtendedNFA::parse);
 xmlApi<alib::Object>::ParserRegister<automaton::ExtendedNFA> extendedNFAParserRegister2 = xmlApi<alib::Object>::ParserRegister<automaton::ExtendedNFA>(automaton::ExtendedNFA::XML_TAG_NAME, automaton::ExtendedNFA::parse);
 
+auto ExtendedNFAFromDFA = castApi::CastRegister<automaton::ExtendedNFA, automaton::DFA>();
+auto ExtendedNFAFromNFA = castApi::CastRegister<automaton::ExtendedNFA, automaton::NFA>();
+auto ExtendedNFAFromMultiInitialStateNFA = castApi::CastRegister<automaton::ExtendedNFA, automaton::MultiInitialStateNFA>();
+auto ExtendedNFAEpsilonNFA = castApi::CastRegister<automaton::ExtendedNFA, automaton::EpsilonNFA>();
+auto ExtendedNFACompactNFA = castApi::CastRegister<automaton::ExtendedNFA, automaton::CompactNFA>();
+auto ExtendedNFACastBinder = castApi::CastPoolStringBinder<automaton::ExtendedNFA>(automaton::ExtendedNFA::XML_TAG_NAME);
+
 } /* namespace alib */
diff --git a/alib2data/src/automaton/FSM/MultiInitialStateNFA.cpp b/alib2data/src/automaton/FSM/MultiInitialStateNFA.cpp
index 2fceef193c..dafe752d8d 100644
--- a/alib2data/src/automaton/FSM/MultiInitialStateNFA.cpp
+++ b/alib2data/src/automaton/FSM/MultiInitialStateNFA.cpp
@@ -18,6 +18,7 @@
 #include "../Automaton.h"
 #include "../../object/Object.h"
 #include "../../XmlApi.hpp"
+#include "../../CastApi.hpp"
 
 namespace automaton {
 
@@ -247,4 +248,8 @@ namespace alib {
 xmlApi<automaton::Automaton>::ParserRegister<automaton::MultiInitialStateNFA> multiInitialStateNFAParserRegister = xmlApi<automaton::Automaton>::ParserRegister<automaton::MultiInitialStateNFA>(automaton::MultiInitialStateNFA::XML_TAG_NAME, automaton::MultiInitialStateNFA::parse);
 xmlApi<alib::Object>::ParserRegister<automaton::MultiInitialStateNFA> multiInitialStateNFAParserRegister2 = xmlApi<alib::Object>::ParserRegister<automaton::MultiInitialStateNFA>(automaton::MultiInitialStateNFA::XML_TAG_NAME, automaton::MultiInitialStateNFA::parse);
 
+auto MultiInitialStateNFAFromDFA = castApi::CastRegister<automaton::MultiInitialStateNFA, automaton::DFA>();
+auto MultiInitialStateNFAFromNFA = castApi::CastRegister<automaton::MultiInitialStateNFA, automaton::NFA>();
+auto MultiInitialStateNFACastBinder = castApi::CastPoolStringBinder<automaton::MultiInitialStateNFA>(automaton::MultiInitialStateNFA::XML_TAG_NAME);
+
 } /* namespace alib */
diff --git a/alib2data/src/automaton/FSM/NFA.cpp b/alib2data/src/automaton/FSM/NFA.cpp
index d06ae07f36..28eacec4eb 100644
--- a/alib2data/src/automaton/FSM/NFA.cpp
+++ b/alib2data/src/automaton/FSM/NFA.cpp
@@ -16,6 +16,7 @@
 #include "../Automaton.h"
 #include "../../object/Object.h"
 #include "../../XmlApi.hpp"
+#include "../../CastApi.hpp"
 
 namespace automaton {
 
@@ -229,4 +230,7 @@ namespace alib {
 xmlApi<automaton::Automaton>::ParserRegister<automaton::NFA> NFAParserRegister = xmlApi<automaton::Automaton>::ParserRegister<automaton::NFA>(automaton::NFA::XML_TAG_NAME, automaton::NFA::parse);
 xmlApi<alib::Object>::ParserRegister<automaton::NFA> NFAParserRegister2 = xmlApi<alib::Object>::ParserRegister<automaton::NFA>(automaton::NFA::XML_TAG_NAME, automaton::NFA::parse);
 
+auto NFAFromDFA = castApi::CastRegister<automaton::NFA, automaton::DFA>();
+auto NFACastBinder = castApi::CastPoolStringBinder<automaton::NFA>(automaton::NFA::XML_TAG_NAME);
+
 } /* namespace alib */
diff --git a/alib2data/src/regexp/formal/FormalRegExp.cpp b/alib2data/src/regexp/formal/FormalRegExp.cpp
index 7174184068..5f432f19d2 100644
--- a/alib2data/src/regexp/formal/FormalRegExp.cpp
+++ b/alib2data/src/regexp/formal/FormalRegExp.cpp
@@ -22,6 +22,7 @@
 #include "../RegExp.h"
 #include "../../object/Object.h"
 #include "../../XmlApi.hpp"
+#include "../../CastApi.hpp"
 
 namespace regexp {
 
@@ -178,4 +179,7 @@ namespace alib {
 xmlApi<regexp::RegExp>::ParserRegister<regexp::FormalRegExp> formalRegExpParserRegister = xmlApi<regexp::RegExp>::ParserRegister<regexp::FormalRegExp>(regexp::FormalRegExp::XML_TAG_NAME, regexp::FormalRegExp::parse);
 xmlApi<alib::Object>::ParserRegister<regexp::FormalRegExp> formalRegExpParserRegister2 = xmlApi<alib::Object>::ParserRegister<regexp::FormalRegExp>(regexp::FormalRegExp::XML_TAG_NAME, regexp::FormalRegExp::parse);
 
+auto FormalRegExpFromUnboundedRegExp = castApi::CastRegister<regexp::FormalRegExp, regexp::UnboundedRegExp>();
+auto FormalRegExpCastBinder = castApi::CastPoolStringBinder<regexp::FormalRegExp>(regexp::FormalRegExp::XML_TAG_NAME);
+
 } /* namespace alib */
diff --git a/alib2data/src/regexp/unbounded/UnboundedRegExp.cpp b/alib2data/src/regexp/unbounded/UnboundedRegExp.cpp
index 155f477524..734e922845 100644
--- a/alib2data/src/regexp/unbounded/UnboundedRegExp.cpp
+++ b/alib2data/src/regexp/unbounded/UnboundedRegExp.cpp
@@ -22,6 +22,7 @@
 #include "../RegExp.h"
 #include "../../object/Object.h"
 #include "../../XmlApi.hpp"
+#include "../../CastApi.hpp"
 
 namespace regexp {
 
@@ -179,4 +180,7 @@ namespace alib {
 xmlApi<regexp::RegExp>::ParserRegister<regexp::UnboundedRegExp> unboundedRegExpParserRegister = xmlApi<regexp::RegExp>::ParserRegister<regexp::UnboundedRegExp>(regexp::UnboundedRegExp::XML_TAG_NAME, regexp::UnboundedRegExp::parse);
 xmlApi<alib::Object>::ParserRegister<regexp::UnboundedRegExp> unboundedRegExpParserRegister2 = xmlApi<alib::Object>::ParserRegister<regexp::UnboundedRegExp>(regexp::UnboundedRegExp::XML_TAG_NAME, regexp::UnboundedRegExp::parse);
 
+auto UnboundedRegExpFromFormalRegExp = castApi::CastRegister<regexp::UnboundedRegExp, regexp::FormalRegExp>();
+auto UnboundedRegExpCastBinder = castApi::CastPoolStringBinder<regexp::UnboundedRegExp>(regexp::UnboundedRegExp::XML_TAG_NAME);
+
 } /* namespace alib */
diff --git a/alib2data/src/string/CyclicString.cpp b/alib2data/src/string/CyclicString.cpp
index d20d73af76..6808021235 100644
--- a/alib2data/src/string/CyclicString.cpp
+++ b/alib2data/src/string/CyclicString.cpp
@@ -18,6 +18,7 @@
 #include "String.h"
 #include "../object/Object.h"
 #include "../XmlApi.hpp"
+#include "../CastApi.hpp"
 
 namespace string {
 
@@ -132,4 +133,7 @@ namespace alib {
 xmlApi<string::String>::ParserRegister<string::CyclicString> cyclicStringParserRegister = xmlApi<string::String>::ParserRegister<string::CyclicString>(string::CyclicString::XML_TAG_NAME, string::CyclicString::parse);
 xmlApi<alib::Object>::ParserRegister<string::CyclicString> cyclicStringParserRegister2 = xmlApi<alib::Object>::ParserRegister<string::CyclicString>(string::CyclicString::XML_TAG_NAME, string::CyclicString::parse);
 
+auto CyclicStringFromEpsilon = castApi::CastRegister<string::CyclicString, string::Epsilon>();
+auto CyclicStringCastBinder = castApi::CastPoolStringBinder<string::CyclicString>(string::CyclicString::XML_TAG_NAME);
+
 } /* namespace alib */
diff --git a/alib2data/src/string/LinearString.cpp b/alib2data/src/string/LinearString.cpp
index 351dbbb8d2..237ac193a6 100644
--- a/alib2data/src/string/LinearString.cpp
+++ b/alib2data/src/string/LinearString.cpp
@@ -18,6 +18,7 @@
 #include "String.h"
 #include "../object/Object.h"
 #include "../XmlApi.hpp"
+#include "../CastApi.hpp"
 
 namespace string {
 
@@ -146,4 +147,8 @@ namespace alib {
 xmlApi<string::String>::ParserRegister<string::LinearString> linearStringParserRegister = xmlApi<string::String>::ParserRegister<string::LinearString>(string::LinearString::XML_TAG_NAME, string::LinearString::parse);
 xmlApi<alib::Object>::ParserRegister<string::LinearString> linearStringParserRegister2 = xmlApi<alib::Object>::ParserRegister<string::LinearString>(string::LinearString::XML_TAG_NAME, string::LinearString::parse);
 
+auto LinearStringFromEpsilon = castApi::CastRegister<string::LinearString, string::Epsilon>();
+auto LinearStringFromPrefixRankedTree = castApi::CastRegister<string::LinearString, tree::PrefixRankedTree>();
+auto LinearStringCastBinder = castApi::CastPoolStringBinder<string::LinearString>(string::LinearString::XML_TAG_NAME);
+
 } /* namespace alib */
diff --git a/alib2data/src/tree/ranked/PrefixRankedPattern.cpp b/alib2data/src/tree/ranked/PrefixRankedPattern.cpp
index f16508dfa6..7234234895 100644
--- a/alib2data/src/tree/ranked/PrefixRankedPattern.cpp
+++ b/alib2data/src/tree/ranked/PrefixRankedPattern.cpp
@@ -20,6 +20,7 @@
 #include "../Tree.h"
 #include "../../object/Object.h"
 #include "../../XmlApi.hpp"
+#include "../../CastApi.hpp"
 
 namespace tree {
 
@@ -156,4 +157,7 @@ namespace alib {
 xmlApi<tree::Tree>::ParserRegister<tree::PrefixRankedPattern> prefixRankedPatternParserRegister = xmlApi<tree::Tree>::ParserRegister<tree::PrefixRankedPattern>(tree::PrefixRankedPattern::XML_TAG_NAME, tree::PrefixRankedPattern::parse);
 xmlApi<alib::Object>::ParserRegister<tree::PrefixRankedPattern> prefixRankedPatternParserRegister2 = xmlApi<alib::Object>::ParserRegister<tree::PrefixRankedPattern>(tree::PrefixRankedPattern::XML_TAG_NAME, tree::PrefixRankedPattern::parse);
 
+auto PrefixRankedPatternFromRankedPattern = castApi::CastRegister<tree::PrefixRankedPattern, tree::RankedPattern>();
+auto PrefixRankedPatternCastBinder = castApi::CastPoolStringBinder<tree::PrefixRankedPattern>(tree::PrefixRankedPattern::XML_TAG_NAME);
+
 } /* namespace alib */
diff --git a/alib2data/src/tree/ranked/PrefixRankedTree.cpp b/alib2data/src/tree/ranked/PrefixRankedTree.cpp
index fcc2554163..eb98239f6c 100644
--- a/alib2data/src/tree/ranked/PrefixRankedTree.cpp
+++ b/alib2data/src/tree/ranked/PrefixRankedTree.cpp
@@ -20,6 +20,7 @@
 #include "../Tree.h"
 #include "../../object/Object.h"
 #include "../../XmlApi.hpp"
+#include "../../CastApi.hpp"
 
 namespace tree {
 
@@ -151,4 +152,7 @@ namespace alib {
 xmlApi<tree::Tree>::ParserRegister<tree::PrefixRankedTree> prefixRankedTreeParserRegister = xmlApi<tree::Tree>::ParserRegister<tree::PrefixRankedTree>(tree::PrefixRankedTree::XML_TAG_NAME, tree::PrefixRankedTree::parse);
 xmlApi<alib::Object>::ParserRegister<tree::PrefixRankedTree> prefixRankedTreeParserRegister2 = xmlApi<alib::Object>::ParserRegister<tree::PrefixRankedTree>(tree::PrefixRankedTree::XML_TAG_NAME, tree::PrefixRankedTree::parse);
 
+auto PrefixRankedTreeFromRankedTree = castApi::CastRegister<tree::PrefixRankedTree, tree::RankedTree>();
+auto PrefixRankedTreeCastBinder = castApi::CastPoolStringBinder<tree::PrefixRankedTree>(tree::PrefixRankedTree::XML_TAG_NAME);
+
 } /* namespace alib */
-- 
GitLab