src/GuileHandler.h
branchv_0
changeset 8 1e6206284c6c
parent 7 61fc569b77e6
child 9 65f9d6b94f5c
equal deleted inserted replaced
7:61fc569b77e6 8:1e6206284c6c
    54 	std::wstring_convert<codecvt_utf8<wchar_t>> convertor; // TODO: support also other encodings or use always UTF-8 between C++ and Guile
    54 	std::wstring_convert<codecvt_utf8<wchar_t>> convertor; // TODO: support also other encodings or use always UTF-8 between C++ and Guile
    55 
    55 
    56 	Configuration configuration;
    56 	Configuration configuration;
    57 	writer::RelationalWriter* relationalWriter;
    57 	writer::RelationalWriter* relationalWriter;
    58 
    58 
    59 	wregex relationNameRegEx;
    59 	RelationConfiguration* currentRelationConfiguration = nullptr;
    60 
       
    61 	vector<AttributeMetadata> currentReaderMetadata;
    60 	vector<AttributeMetadata> currentReaderMetadata;
    62 	vector<writer::AttributeMetadata> currentWriterMetadata;
    61 	vector<writer::AttributeMetadata> currentWriterMetadata;
    63 	vector<string_t> currentRecord;
    62 	vector<string_t> currentRecord;
    64 	integer_t currentAttributeIndex = 0;
    63 	integer_t currentAttributeIndex = 0;
    65 	boolean_t includeCurrentRecord = false;
    64 	boolean_t includeCurrentRecord = false;
    66 	boolean_t filterCurrentRelation = false;
       
    67 	string_t guileCodeWhereCondition;
       
    68 
    65 
    69 	/**
    66 	/**
    70 	 * @param attributeName name from relational pipe
    67 	 * @param attributeName name from relational pipe
    71 	 * @return variable name in Guile
    68 	 * @return variable name in Guile
    72 	 */
    69 	 */
   145 	}
   142 	}
   146 
   143 
   147 public:
   144 public:
   148 
   145 
   149 	GuileHandler(writer::RelationalWriter* relationalWriter, Configuration& configuration, const vector<string_t>& arguments) : relationalWriter(relationalWriter), configuration(configuration) {
   146 	GuileHandler(writer::RelationalWriter* relationalWriter, Configuration& configuration, const vector<string_t>& arguments) : relationalWriter(relationalWriter), configuration(configuration) {
   150 
       
   151 		// FIXME: remove and work directly with configuration in startRelation() and attribute()
       
   152 		// i.e. support multiple relationConfigurations
       
   153 		if (configuration.relationConfigurations.size() == 1) {
       
   154 			relationNameRegEx = wregex(configuration.relationConfigurations[0].relation);
       
   155 			guileCodeWhereCondition = configuration.relationConfigurations[0].guileWhere;
       
   156 		} else {
       
   157 			throw cli::RelpipeCLIException(L"FIXME: only single relationConfiguration is currently supported", cli::CLI::EXIT_CODE_UNKNOWN_COMMAND);
       
   158 		}
       
   159 	}
   147 	}
   160 
   148 
   161 	void startRelation(string_t name, vector<AttributeMetadata> attributes) override {
   149 	void startRelation(string_t name, vector<AttributeMetadata> attributes) override {
   162 		for (auto attribute : currentReaderMetadata) undefineGuileVariable(attribute.getAttributeName());
   150 		for (auto attribute : currentReaderMetadata) undefineGuileVariable(attribute.getAttributeName());
   163 		currentReaderMetadata = attributes;
   151 		currentReaderMetadata = attributes;
   164 		// TODO: move to a reusable method (or use same metadata on both reader and writer side?)
   152 		// TODO: move to a reusable method (or use same metadata on both reader and writer side?)
   165 		// TODO: allow structural changes during transformation
   153 		// TODO: allow structural changes during transformation
   166 		// TODO: clear Guile variables for attributes from previous relation
       
   167 		currentWriterMetadata.clear();
   154 		currentWriterMetadata.clear();
   168 		for (AttributeMetadata readerMetadata : attributes) {
   155 		for (AttributeMetadata readerMetadata : attributes) {
   169 			currentWriterMetadata.push_back({readerMetadata.getAttributeName(), relationalWriter->toTypeId(readerMetadata.getTypeName())});
   156 			currentWriterMetadata.push_back({readerMetadata.getAttributeName(), relationalWriter->toTypeId(readerMetadata.getTypeName())});
   170 		}
   157 		}
   171 
   158 
   172 		currentRecord.resize(attributes.size());
   159 		currentRecord.resize(attributes.size());
   173 		filterCurrentRelation = regex_match(name, relationNameRegEx);
   160 
       
   161 		for (int i = 0; i < configuration.relationConfigurations.size(); i++) {
       
   162 			if (regex_match(name, wregex(configuration.relationConfigurations[i].relation))) {
       
   163 				currentRelationConfiguration = &configuration.relationConfigurations[i];
       
   164 				break; // it there are multiple matches, only the first configuration is used
       
   165 			}
       
   166 		}
   174 
   167 
   175 		relationalWriter->startRelation(name, currentWriterMetadata, true);
   168 		relationalWriter->startRelation(name, currentWriterMetadata, true);
   176 	}
   169 	}
   177 
   170 
   178 	void attribute(const void* value, const std::type_info& type) override {
   171 	void attribute(const void* value, const std::type_info& type) override {
   179 		if (filterCurrentRelation) {
   172 		if (currentRelationConfiguration) {
   180 			defineGuileVariable(a2v(currentReaderMetadata[currentAttributeIndex].getAttributeName()), value, type, currentReaderMetadata[currentAttributeIndex].getTypeId());
   173 			defineGuileVariable(a2v(currentReaderMetadata[currentAttributeIndex].getAttributeName()), value, type, currentReaderMetadata[currentAttributeIndex].getTypeId());
   181 
   174 
   182 			currentAttributeIndex++;
   175 			currentAttributeIndex++;
   183 
   176 
   184 			// TODO: > 0 ?:
   177 			// TODO: > 0 ?:
   185 			if (currentAttributeIndex > 0 && currentAttributeIndex % currentReaderMetadata.size() == 0) {
   178 			if (currentAttributeIndex > 0 && currentAttributeIndex % currentReaderMetadata.size() == 0) {
   186 				includeCurrentRecord = scm_to_bool(evalGuileCode(guileCodeWhereCondition));
   179 				includeCurrentRecord = scm_to_bool(evalGuileCode(currentRelationConfiguration->guileWhere));
   187 				if (includeCurrentRecord) for (auto attribute : currentWriterMetadata) writeGuileValueToAttribute(attribute);
   180 				if (includeCurrentRecord) for (auto attribute : currentWriterMetadata) writeGuileValueToAttribute(attribute);
   188 				includeCurrentRecord = false;
   181 				includeCurrentRecord = false;
   189 			}
   182 			}
   190 
   183 
   191 			currentAttributeIndex = currentAttributeIndex % currentReaderMetadata.size();
   184 			currentAttributeIndex = currentAttributeIndex % currentReaderMetadata.size();