Merge "Removes unused & untested methods"
diff --git a/tools/cpp-enum-generator/enums/AssetKind b/tools/cpp-enum-generator/enums/AssetKind
new file mode 100644
index 0000000..042f500
--- /dev/null
+++ b/tools/cpp-enum-generator/enums/AssetKind
@@ -0,0 +1,3 @@
+Type
+Instance
+Unknown
\ No newline at end of file
diff --git a/tools/cpp-enum-generator/enums/ModelTypes b/tools/cpp-enum-generator/enums/ModelTypes
new file mode 100644
index 0000000..55a310f
--- /dev/null
+++ b/tools/cpp-enum-generator/enums/ModelTypes
@@ -0,0 +1,28 @@
+Asset
+AssetAdministrationShell
+ConceptDescription
+Submodel
+AccessPermissionRule
+AnnotatedRelationshipElement
+BasicEvent
+Blob
+Capability
+ConceptDictionary
+DataElement
+File
+Entity
+Event
+MultiLanguageProperty
+Operation
+Property
+Range
+ReferenceElement
+RelationshipElement
+SubmodelElement
+SubmodelElementCollection
+View
+GlobalReference
+FragmentReference
+Constraint
+Formula
+Qualifier
diff --git a/tools/cpp-enum-generator/generate_enums.sh b/tools/cpp-enum-generator/generate_enums.sh
new file mode 100644
index 0000000..45690b2
--- /dev/null
+++ b/tools/cpp-enum-generator/generate_enums.sh
@@ -0,0 +1,22 @@
+#!/bin/sh
+
+CPP_SDK_DIR=../../sdks/c++/basys.sdk.cc
+TARGET_SRC_DIR=$CPP_SDK_DIR/src/submodel/submodel/enumerations
+TARGET_HEADER_DIR=$CPP_SDK_DIR/include/BaSyx/submodel/enumerations/
+
+ENUMS_DIR=enums
+OUT_DIR=generated
+
+TEMPLATE=template.txt
+
+mkdir -p $OUT_DIR
+mkdir -p $TARGET_SRC_DIR
+mkdir -p $TARGET_HEADER_DIR
+
+for f in $ENUMS_DIR/*; do
+    python3 generator.py -t $TEMPLATE -o $OUT_DIR $f
+done
+
+
+mv $OUT_DIR/*.cpp $TARGET_SRC_DIR
+mv $OUT_DIR/*.h $TARGET_HEADER_DIR
diff --git a/tools/cpp-enum-generator/generator.py b/tools/cpp-enum-generator/generator.py
new file mode 100755
index 0000000..a1025bd
--- /dev/null
+++ b/tools/cpp-enum-generator/generator.py
@@ -0,0 +1,113 @@
+#!/bin/python3
+
+import re
+import os
+import sys
+import argparse
+
+class Generator:
+    def __init__(self, filename):
+        self.regular_source_file_ending = "hpp"
+        self.enum_class = filename.split("/")[-1].replace(".txt", "")
+        self.first_element = ""
+        self.last_element = ""
+        self.size = 0
+        self.other_elements = list()
+        self.constants = dict()
+        self.__get_elements__(filename)
+        print("Enum class-name is:", self.enum_class)
+        print("Elements are:")
+        print(self.first_element)
+        for elem in self.other_elements:
+            print(elem)
+        print(self.last_element)
+        
+    def __get_elements__(self, filename):
+        elements = list()
+        with open(filename, "r") as f:
+            elements = f.read().splitlines()
+        self.size = len(elements)
+        self.first_element = elements[0]
+        elements = elements[1:]
+        self.last_element = elements.pop()
+        self.other_elements = elements
+    
+    def __set_constants__(self, line_templates):
+        for line in line_templates:
+            if re.match(r"\$CONSTANT\$", line):
+                match = re.split(r"\W+", line)
+                value_pos = -1
+                if match[-1] == "":
+                    value_pos = -2
+                value = match[value_pos]
+                constant = "$" + match[value_pos - 1] + "$"
+                self.constants[constant] = value
+        print(self.constants)
+                
+    
+    def __write_file__(self, line_templates, ending, output_path):
+        if not os.path.exists(output_path):
+            raise Exception("Output path does not exist")
+        with open(os.path.abspath(output_path) + "/" + self.enum_class + "." + ending, "w") as out_file:
+            for line_template in line_templates:
+                line = line_template + "\n"
+                line = line.replace("$ENUM_CLASS$", self.enum_class)
+                line = line.replace("$SIZE$", str(self.size))
+                for constant in self.constants.keys():
+                    line = line.replace(constant, self.constants[constant])
+                if "$FIRST_ENUM$" in line:
+                    out_file.write(line.replace("$FIRST_ENUM$", self.first_element))
+                elif "$LAST_ENUM$" in line:
+                    out_file.write(line.replace("$LAST_ENUM$", self.last_element))
+                elif "$MIDDLE_ENUM$" in line:
+                    for enum_elem in self.other_elements:
+                        out_file.write(line.replace("$MIDDLE_ENUM$", enum_elem))
+                else:
+                    out_file.write(line)
+    
+    def get_files(self, template_path, output_path):
+        line_templates = list()
+        with open(template_path, "r") as template:
+            line_templates = template.read().splitlines()
+        self.__set_constants__(line_templates)
+        file_template = list()
+        file_ending = ""
+        for line in line_templates:
+            # filter out comments and jump over lines with constant definitions
+            if re.match(r";", line):
+                continue
+            if re.match(r"\$CONSTANT\$", line):
+                continue
+            
+            # Find file endings
+            if "$FILE_ENDING$" in line:
+                match = re.split(r"\W+", line)
+                file_ending = match[-1]
+                if file_ending == "":
+                    file_ending = match[-2]
+                self.__write_file__(file_template, file_ending, output_path)
+                file_template = list()
+                continue
+            
+            file_template.append(line)
+        
+        # if no file ending is set, use the 
+        if file_ending == "":
+            self.__write_file__(file_template, self.regular_source_file_ending, output_path)
+
+
+if __name__ == "__main__":
+    parser = argparse.ArgumentParser()
+    parser.add_argument("enum_list_file", help="Path to a file containing a list of enums to be generated.")
+    parser.add_argument("-t", "--template_path", help="If template is not located in bin folder of script, please specify here.")
+    parser.add_argument("-o", "--output_path", help="Specify a path to a directory to place the generated file(s).")
+    
+    args = parser.parse_args()
+    generator = Generator(args.enum_list_file)
+    template_path = "template.txt"
+    if args.template_path:
+        template_path = args.template_path
+    output_path = ""
+    if args.output_path:
+        output_path = args.output_path    
+    generator.get_files(template_path, output_path)
diff --git a/tools/cpp-enum-generator/template.txt b/tools/cpp-enum-generator/template.txt
new file mode 100644
index 0000000..55c552b
--- /dev/null
+++ b/tools/cpp-enum-generator/template.txt
@@ -0,0 +1,79 @@
+; Comments must start with ; all other lines will be present in the corresponding file
+; Indicate a source-code file by $FILE_ENDING$-tag and the corresponding file ending
+; at the end of the file. i.e.: "$FILE_ENDING cpp". If $FILE_ENDING$ is not set, ".hpp" will be used.
+; Other tags that can be used are:
+; $ENUM_CLASS$  : Class name of enum, obtained from file name
+; $FIRST_ENUM$  : The first enum in the list of enums
+; $MIDDLE_ENUM$ : All enums that are in between first and last enum.
+; $LAST_ENUM$   : The last enum in the list of enums
+; $SIZE$        : The number of enums
+; $CONSTANT$    : Define a costant, i.e.: $CONSTSANT$ NAME value, usage in document with $NAME$
+;
+;
+$CONSTANT$ NAMESPACE submodel
+#ifndef BASYX_SUBMODEL_ENUM_$ENUM_CLASS$_H
+#define BASYX_SUBMODEL_ENUM_$ENUM_CLASS$_H
+
+#include <string>
+
+namespace basyx {
+namespace $NAMESPACE$ {
+
+enum class $ENUM_CLASS$ {
+    $FIRST_ENUM$,
+    $MIDDLE_ENUM$,
+    $LAST_ENUM$,
+};
+
+class $ENUM_CLASS$_
+{
+public:
+    static $ENUM_CLASS$ from_string(const std::string & name);
+    static const char * to_string($ENUM_CLASS$ value);
+};
+
+
+}
+}
+
+#endif
+$FILE_ENDING$ h
+#include <BaSyx/$NAMESPACE$/enumerations/$ENUM_CLASS$.h>
+
+#include <array>
+#include <algorithm>
+#include <memory>
+#include <string>
+
+using namespace basyx::submodel;
+
+using enum_pair_t = std::pair<const char*, $ENUM_CLASS$>;
+
+static const std::array<enum_pair_t, $SIZE$> string_to_enum = 
+{
+    std::make_pair("$FIRST_ENUM$",  $ENUM_CLASS$::$FIRST_ENUM$),
+    std::make_pair("$MIDDLE_ENUM$", $ENUM_CLASS$::$MIDDLE_ENUM$),
+    std::make_pair("$LAST_ENUM$", $ENUM_CLASS$::$LAST_ENUM$),
+};
+
+$ENUM_CLASS$ $ENUM_CLASS$_::from_string(const std::string & name)
+{
+    auto pair = std::find_if(string_to_enum.begin(), string_to_enum.end(), 
+		[&name](const auto & pair) {
+			return !name.compare(pair.first);
+	});
+
+    return pair->second;
+}
+
+const char * $ENUM_CLASS$_::to_string($ENUM_CLASS$ value)
+{
+    auto pair = std::find_if(string_to_enum.begin(), string_to_enum.end(), 
+		[value](const auto & pair) {
+			return value == pair.second;
+	});
+
+    return pair->first;
+}
+
+$FILE_ENDING$ cpp
diff --git a/tools/cpp-enum-generator/template.txt.example b/tools/cpp-enum-generator/template.txt.example
new file mode 100644
index 0000000..0100688
--- /dev/null
+++ b/tools/cpp-enum-generator/template.txt.example
@@ -0,0 +1,57 @@
+; Comments must start with ; all other lines will be present in the corresponding file
+; Indicate a source-code file by $FILE_ENDING$-tag and the corresponding file ending
+; at the end of the file. i.e.: "$FILE_ENDING cpp". If $FILE_ENDING$ is not set, ".hpp" will be used.
+; Other tags that can be used are:
+; $ENUM_CLASS$  : Class name of enum, obtained from file name
+; $FIRST_ENUM$  : The first enum in the list of enums
+; $MIDDLE_ENUM$ : All enums that are in between first and last enum.
+; $LAST_ENUM$   : The last enum in the list of enums
+; $SIZE$        : The number of enums
+; $CONSTANT$    : Define a costant, i.e.: $CONSTSANT$ NAME value, usage in document with $NAME$
+;
+;
+$CONSTANT$ NAMESPACE submodel
+#include <memory>
+
+namespace basyx {
+namespace $NAMESPACE$ {
+
+enum class $ENUM_CLASS${
+    $FIRST_ENUM$,
+    $MIDDLE_ENUM$,
+    $LAST_ENUM$
+};
+
+static const std::array<std::pair<const char*, $ENUM_CLASS$>, $SIZE$> string_to_$ENUM_CLASS$ = 
+{{
+    std::pair<const char*, $ENUM_CLASS$>("$FIRST_ENUM$", $ENUM_CLASS$::$FIRST_ENUM$),
+    std::pair<const char*, $ENUM_CLASS$>("$MIDDLE_ENUM$", $ENUM_CLASS$::$MIDDLE_ENUM$),
+    std::pair<const char*, $ENUM_CLASS$>("$LAST_ENUM$", $ENUM_CLASS$::$LAST_ENUM$)
+}};
+
+template<class $ENUM_CLASS$>
+$ENUM_CLASS$ from_string(const std::string name);
+std::string to_string($ENUM_CLASS$ enum_elem);
+
+}
+}
+
+$FILE_ENDING$ h
+#include <BaSyx/$NAMESPACE$/map/$ENUM_CLASS$.h>
+
+#include <string>
+#include <algorithm>
+
+template<>
+basyx::$NAMESPACE$::$ENUM_CLASS$ basyx::$NAMESPACE$::from_string<basyx::$NAMESPACE$::$ENUM_CLASS$>(const std::string name)
+{
+    auto pair = std::find_if(string_to_$ENUM_CLASS$.begin(), string_to_$ENUM_CLASS$.end(), [name](std::pair<const char*, $ENUM_CLASS$> pair) {return not name.compare(pair.first);});
+    return pair->second;
+}
+
+std::string basyx::$NAMESPACE$::to_string($ENUM_CLASS$ enum_elem)
+{
+    auto pair = std::find_if(string_to_$ENUM_CLASS$.begin(), string_to_$ENUM_CLASS$.end(), [enum_elem](std::pair<const char*, $ENUM_CLASS$> pair) {return enum_elem == pair.second;});
+    return pair->first;
+}
+$FILE_ENDING$ cpp