more configuration/options v_0
authorFrantišek Kučera <franta-hg@frantovo.cz>
Mon, 06 May 2019 16:00:20 +0200
branchv_0
changeset 8 513ea30d2fa3
parent 7 46db0e6e548b
child 9 b064f1b3676e
more configuration/options
src/CLIParser.h
src/Configuration.h
--- a/src/CLIParser.h	Sun May 05 23:09:20 2019 +0200
+++ b/src/CLIParser.h	Mon May 06 16:00:20 2019 +0200
@@ -29,6 +29,10 @@
 namespace tr {
 namespace awk {
 
+/**
+ * This tr-awk CLI options are inspired by tr-guile options.
+ * These configurations are independent and might diverge, but when possible, the should share same option names and same logic for common parts.
+ */
 class CLIParser {
 private:
 
@@ -39,17 +43,65 @@
 		else throw relpipe::cli::RelpipeCLIException(L"Missing CLI argument" + (i > 0 ? (L" after " + arguments[i - 1]) : L""), relpipe::cli::CLI::EXIT_CODE_BAD_CLI_ARGUMENTS);
 	}
 
+	void addRelation(Configuration& c, RelationConfiguration& currentRelation) {
+		if (currentRelation.relation.size()) {
+			c.relationConfigurations.push_back(currentRelation);
+			currentRelation = RelationConfiguration();
+		}
+	}
+
+	relpipe::writer::TypeId parseTypeId(const string_t& value) {
+		using t = relpipe::writer::TypeId;
+		if (value == L"string") return t::STRING;
+		else if (value == L"integer") return t::INTEGER;
+		else if (value == L"boolean") return t::BOOLEAN;
+		else throw relpipe::cli::RelpipeCLIException(L"Unable to parse TypeId: " + value, relpipe::cli::CLI::EXIT_CODE_BAD_CLI_ARGUMENTS);
+	}
+
 public:
 
-	static const string_t OPTION_EXPRESSION;
+	static const string_t OPTION_RELATION;
+	static const string_t OPTION_OUTPUT_ATTRIBUTE;
+	static const string_t OPTION_INPUT_ATTRIBUTES_APPEND;
+	static const string_t OPTION_INPUT_ATTRIBUTES_PREPEND;
+	static const string_t OPTION_BEFORE_RECORDS;
+	static const string_t OPTION_AFTER_RECORDS;
+	static const string_t OPTION_FOR_EACH;
+	static const string_t OPTION_DEFINE;
 
 	Configuration parse(const std::vector<string_t>& arguments) {
 		Configuration c;
+		RelationConfiguration currentRelation;
 
-		for (int i = 0; i < arguments.size();) {
-			string_t option = readNext(arguments, i);
-			if (option == OPTION_EXPRESSION) c.awkExpression = readNext(arguments, i);
-			else throw relpipe::cli::RelpipeCLIException(L"Unsupported CLI option: " + option, relpipe::cli::CLI::EXIT_CODE_BAD_CLI_ARGUMENTS);
+		{
+			for (int i = 0; i < arguments.size();) {
+				string_t option = readNext(arguments, i);
+
+				if (option == OPTION_BEFORE_RECORDS) currentRelation.awkBeforeRecords = readNext(arguments, i);
+				else if (option == OPTION_AFTER_RECORDS) currentRelation.awkAfterRecords = readNext(arguments, i);
+				else if (option == OPTION_FOR_EACH) currentRelation.awkForEach = readNext(arguments, i);
+				else if (option == OPTION_INPUT_ATTRIBUTES_APPEND) currentRelation.inputAttributesAppend = true;
+				else if (option == OPTION_INPUT_ATTRIBUTES_PREPEND) currentRelation.inputAttributesPrepend = true;
+				else if (option == OPTION_RELATION) {
+					addRelation(c, currentRelation); // previous relation
+					currentRelation.relation = readNext(arguments, i);
+				} else if (option == OPTION_OUTPUT_ATTRIBUTE) {
+					relpipe::writer::AttributeMetadata attribute;
+					attribute.attributeName = readNext(arguments, i);
+					attribute.typeId = parseTypeId(readNext(arguments, i));
+					currentRelation.writerMetadata.push_back(attribute);
+				} else if (option == OPTION_DEFINE) {
+					DefinitionRecipe definition;
+					definition.name = readNext(arguments, i);
+					definition.type = readNext(arguments, i);
+					definition.value = readNext(arguments, i);
+					if (currentRelation.relation.size()) currentRelation.definitions.push_back(definition);
+					else c.definitions.push_back(definition);
+				} else throw relpipe::cli::RelpipeCLIException(L"Unsupported CLI option: " + option, relpipe::cli::CLI::EXIT_CODE_BAD_CLI_ARGUMENTS);
+
+			}
+
+			addRelation(c, currentRelation); // last relation
 		}
 
 		return c;
@@ -59,7 +111,14 @@
 	}
 };
 
-const string_t CLIParser::OPTION_EXPRESSION = L"--expression";
+const string_t CLIParser::OPTION_RELATION = L"--relation";
+const string_t CLIParser::OPTION_OUTPUT_ATTRIBUTE = L"--output-attribute";
+const string_t CLIParser::OPTION_INPUT_ATTRIBUTES_APPEND = L"--input-attributes-append";
+const string_t CLIParser::OPTION_INPUT_ATTRIBUTES_PREPEND = L"--input-attributes-prepend";
+const string_t CLIParser::OPTION_BEFORE_RECORDS = L"--before-records";
+const string_t CLIParser::OPTION_AFTER_RECORDS = L"--after-records";
+const string_t CLIParser::OPTION_FOR_EACH = L"--for-each";
+const string_t CLIParser::OPTION_DEFINE = L"--define";
 
 }
 }
--- a/src/Configuration.h	Sun May 05 23:09:20 2019 +0200
+++ b/src/Configuration.h	Mon May 06 16:00:20 2019 +0200
@@ -24,10 +24,62 @@
 namespace tr {
 namespace awk {
 
+class DefinitionRecipe {
+public:
+
+	virtual ~DefinitionRecipe() {
+	}
+
+	relpipe::writer::string_t name;
+	relpipe::writer::string_t type;
+	relpipe::writer::string_t value;
+};
+
+class RelationConfiguration {
+public:
+
+	virtual ~RelationConfiguration() {
+	}
+
+	relpipe::writer::string_t relation;
+	relpipe::writer::string_t awkBeforeRecords;
+	relpipe::writer::string_t awkAfterRecords;
+	relpipe::writer::string_t awkForEach;
+
+	/**
+	 * Variable definitions for this relation.
+	 * Can be used as a safe way for passing parameters from the outside environment.
+	 * See also Configuration::definitions (can be overridden by relation's definitions)
+	 */
+	std::vector<DefinitionRecipe> definitions;
+
+	/**
+	 * If empty, output relation will have same metadata as the input relation.
+	 */
+	std::vector<relpipe::writer::AttributeMetadata> writerMetadata;
+
+	/**
+	 * Whether original attributes should be appended to those specified using --output-attribute
+	 */
+	bool inputAttributesAppend = false;
+
+	/**
+	 * Whether original attributes should be prepended to those specified using --output-attribute
+	 */
+	bool inputAttributesPrepend = false;
+};
+
 class Configuration {
 public:
 
-	relpipe::writer::string_t awkExpression;
+	vector<RelationConfiguration> relationConfigurations;
+
+	/**
+	 * Global definitions for all relations.
+	 * Can be used as a safe way for passing parameters from the outside environment.
+	 * See also RelationConfiguration::definitions
+	 */
+	std::vector<DefinitionRecipe> definitions;
 
 	virtual ~Configuration() {
 	}