src/GuileHandler.h
branchv_0
changeset 23 6ee7a9e311e9
parent 20 dccbfd273a5a
child 26 421608ecc12a
equal deleted inserted replaced
22:d5e80f15d1f7 23:6ee7a9e311e9
    18 #pragma once
    18 #pragma once
    19 
    19 
    20 #include <memory>
    20 #include <memory>
    21 #include <string>
    21 #include <string>
    22 #include <vector>
    22 #include <vector>
       
    23 #include <map>
    23 #include <iostream>
    24 #include <iostream>
    24 #include <sstream>
    25 #include <sstream>
    25 #include <locale>
    26 #include <locale>
    26 #include <codecvt>
    27 #include <codecvt>
    27 #include <regex>
    28 #include <regex>
    37 #include <relpipe/writer/Factory.h>
    38 #include <relpipe/writer/Factory.h>
    38 
    39 
    39 #include <relpipe/cli/RelpipeCLIException.h>
    40 #include <relpipe/cli/RelpipeCLIException.h>
    40 
    41 
    41 #include "Configuration.h"
    42 #include "Configuration.h"
       
    43 #include "GuileException.h"
    42 
    44 
    43 namespace relpipe {
    45 namespace relpipe {
    44 namespace tr {
    46 namespace tr {
    45 namespace guile {
    47 namespace guile {
    46 
    48 
    57 	writer::RelationalWriter* relationalWriter;
    59 	writer::RelationalWriter* relationalWriter;
    58 
    60 
    59 	RelationConfiguration* currentRelationConfiguration = nullptr;
    61 	RelationConfiguration* currentRelationConfiguration = nullptr;
    60 	vector<AttributeMetadata> currentReaderMetadata;
    62 	vector<AttributeMetadata> currentReaderMetadata;
    61 	vector<writer::AttributeMetadata> currentWriterMetadata;
    63 	vector<writer::AttributeMetadata> currentWriterMetadata;
       
    64 	std::map<string_t, string_t> currenVariablesMapping;
    62 	integer_t currentAttributeIndex = 0;
    65 	integer_t currentAttributeIndex = 0;
    63 	boolean_t includeCurrentRecord = false;
    66 	boolean_t includeCurrentRecord = false;
    64 
    67 
    65 	void add(vector<AttributeMetadata>& readerAttributes, vector<writer::AttributeMetadata>& writerAttributes) {
    68 	void add(vector<AttributeMetadata>& readerAttributes, vector<writer::AttributeMetadata>& writerAttributes) {
    66 		for (AttributeMetadata readerAttributes : readerAttributes)
    69 		for (AttributeMetadata readerAttributes : readerAttributes)
    68 				readerAttributes.getAttributeName(),
    71 				readerAttributes.getAttributeName(),
    69 				relationalWriter->toTypeId(readerAttributes.getTypeName())
    72 				relationalWriter->toTypeId(readerAttributes.getTypeName())
    70 			});
    73 			});
    71 	}
    74 	}
    72 
    75 
       
    76 	void generateVariableMappings() {
       
    77 		currenVariablesMapping.clear();
       
    78 		for (AttributeMetadata m : currentReaderMetadata) currenVariablesMapping[m.getAttributeName()] = L"";
       
    79 		for (writer::AttributeMetadata m : currentWriterMetadata) currenVariablesMapping[m.attributeName] = L"";
       
    80 
       
    81 		for (std::pair<string_t, string_t> m : currenVariablesMapping) {
       
    82 			currenVariablesMapping[m.first] = escapeAwkVariableName(m.first);
       
    83 		}
       
    84 	}
       
    85 
    73 	/**
    86 	/**
    74 	 * @param attributeName name from relational pipe
    87 	 * @param attributeName name from relational pipe
    75 	 * @return variable name in Guile
    88 	 * @return variable name in Guile
    76 	 */
    89 	 */
    77 	string_t a2v(const string_t& attributeName) {
    90 	string_t a2v(const string_t& attributeName) {
    78 		// TODO: escape spaces and special characters
    91 		if (currenVariablesMapping.find(attributeName) != currenVariablesMapping.end()) return currenVariablesMapping[attributeName];
    79 		return L"$" + attributeName;
    92 		else throw GuileException(L"Unable to find value in currenVariablesMapping");
       
    93 	}
       
    94 
       
    95 	template <typename K, typename V> bool containsValue(std::map<K, V> map, V value) { // TODO: common function (Guile, AWK)
       
    96 		for (std::pair<K, V> p : map) if (p.second == value) return true;
       
    97 		return false;
       
    98 	}
       
    99 
       
   100 	string_t escapeAwkVariableName(const string_t& attributeName, bool addPrefix = true) {
       
   101 		std::wregex badCharacters(L"\\s");
       
   102 		string_t name = std::regex_replace(attributeName, badCharacters, L"-");
       
   103 
       
   104 		if (addPrefix) name = L"$" + name; // $ = standard attribute-variable prefix
       
   105 
       
   106 		if (containsValue(currenVariablesMapping, name)) return escapeAwkVariableName(L"$" + name, false); // $ = different prefix added to distinguish two attributes with ambiguous names
       
   107 		else return name;
       
   108 
       
   109 	}
       
   110 
       
   111 	void debugVariableMapping(const string_t& relationName) {
       
   112 		relationalWriter->startRelation(relationName + L".variableMapping",{
       
   113 			{L"attribute", writer::TypeId::STRING},
       
   114 			{L"variable", writer::TypeId::STRING},
       
   115 		}, true);
       
   116 
       
   117 		for (std::pair<string_t, string_t> m : currenVariablesMapping) {
       
   118 			relationalWriter->writeAttribute(m.first);
       
   119 			relationalWriter->writeAttribute(m.second);
       
   120 		}
    80 	}
   121 	}
    81 
   122 
    82 	SCM toGuileSymbol(const string_t& name) {
   123 	SCM toGuileSymbol(const string_t& name) {
    83 		return scm_string_to_symbol(scm_from_locale_string(convertor.to_bytes(name).c_str()));
   124 		return scm_string_to_symbol(scm_from_locale_string(convertor.to_bytes(name).c_str()));
    84 	}
   125 	}
   231 			if (currentRelationConfiguration->inputAttributesAppend) add(currentReaderMetadata, currentWriterMetadata);
   272 			if (currentRelationConfiguration->inputAttributesAppend) add(currentReaderMetadata, currentWriterMetadata);
   232 		} else {
   273 		} else {
   233 			add(currentReaderMetadata, currentWriterMetadata);
   274 			add(currentReaderMetadata, currentWriterMetadata);
   234 		}
   275 		}
   235 
   276 
       
   277 		generateVariableMappings();
       
   278 
       
   279 		if (currentRelationConfiguration->debugVariableMapping) debugVariableMapping(name);
       
   280 
   236 		if (!currentRelationConfiguration || !currentRelationConfiguration->drop) relationalWriter->startRelation(name, currentWriterMetadata, true);
   281 		if (!currentRelationConfiguration || !currentRelationConfiguration->drop) relationalWriter->startRelation(name, currentWriterMetadata, true);
   237 
   282 
   238 		if (currentRelationConfiguration) {
   283 		if (currentRelationConfiguration) {
   239 			// TODO: better variable name, object, function?
   284 			// TODO: better variable name, object, function?
   240 			defineGuileVariable(L"relpipe-relation-name", &name, typeid (name), TypeId::STRING);
   285 			defineGuileVariable(L"relpipe-relation-name", &name, typeid (name), TypeId::STRING);