diff --git a/TBF/Rig/Output/DataStorage/UniDataStorageWriter/Diagnostic/WriterDiagnosticResult.cs b/TBF/Rig/Output/DataStorage/UniDataStorageWriter/Diagnostic/WriterDiagnosticResult.cs
new file mode 100644
index 000000000..88be87585
--- /dev/null
+++ b/TBF/Rig/Output/DataStorage/UniDataStorageWriter/Diagnostic/WriterDiagnosticResult.cs
@@ -0,0 +1,53 @@
+using System.Text;
+
+namespace TBF.Rig.Output.DataStorage.UniDataStorageWriter
+{
+ ///
+ /// Diagnostic result for writer source testing and write execution.
+ ///
+ public class WriterDiagnosticResult
+ {
+ public bool Success { get; set; }
+
+ public string Message { get; set; }
+
+ ///
+ /// Final resolved template/query/body actually executed by writer.
+ ///
+ public string ExecutedTemplate { get; set; }
+
+ public static WriterDiagnosticResult Ok(string message = null)
+ {
+ return new WriterDiagnosticResult
+ {
+ Success = true,
+ Message = message
+ };
+ }
+
+ public static WriterDiagnosticResult Fail(string message)
+ {
+ return new WriterDiagnosticResult
+ {
+ Success = false,
+ Message = message
+ };
+ }
+
+ public string ToDisplayDiag()
+ {
+ StringBuilder sb = new StringBuilder();
+
+ sb.AppendLine("Success: " + Success);
+ sb.AppendLine("Message: " + (string.IsNullOrWhiteSpace(Message) ? "" : Message));
+
+ if (!string.IsNullOrWhiteSpace(ExecutedTemplate))
+ {
+ sb.AppendLine("Executed template:");
+ sb.AppendLine(ExecutedTemplate);
+ }
+
+ return sb.ToString();
+ }
+ }
+}
\ No newline at end of file
diff --git a/TBF/Rig/Output/DataStorage/UniDataStorageWriter/Enums.cs b/TBF/Rig/Output/DataStorage/UniDataStorageWriter/Enums.cs
new file mode 100644
index 000000000..d06ca28d9
--- /dev/null
+++ b/TBF/Rig/Output/DataStorage/UniDataStorageWriter/Enums.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace TBF.Rig.Output.DataStorage.UniDataStorageWriter
+{
+ ///
+ /// Helper class to assign descriptions to enum values
+ ///
+ public class Description : Attribute
+ {
+ public string Text;
+ public Description(string t)
+ {
+ Text = t;
+ }
+ }
+
+ public static class GetDescription
+ {
+ /// Extension method for enum-s
+ public static string ToDescription(this Enum en)
+ {
+ Type type = en.GetType();
+ MemberInfo[] memInfo = type.GetMember(en.ToString());
+
+ if (memInfo != null && memInfo.Length > 0)
+ {
+ object[] attrs = memInfo[0].GetCustomAttributes(typeof(Description), false);
+ if (attrs != null && attrs.Length > 0)
+ return ((Description)attrs[0]).Text;
+ }
+
+ return en.ToString(); /// Return ToString() value in case there is no description
+ }
+ }
+
+ ///
+ /// Identifies the type of data storage
+ ///
+ public enum DataStorageType
+ {
+ RestApi,
+ Database,
+ Json,
+ Csv
+ }
+}
diff --git a/TBF/Rig/Output/DataStorage/UniDataStorageWriter/Factory.cs b/TBF/Rig/Output/DataStorage/UniDataStorageWriter/Factory.cs
new file mode 100644
index 000000000..271dfdf59
--- /dev/null
+++ b/TBF/Rig/Output/DataStorage/UniDataStorageWriter/Factory.cs
@@ -0,0 +1,38 @@
+///
+/// Copyright (c) 2018 Sensus Slovensko a.s.
+///
+
+using System;
+using System.Collections.Generic;
+using TBF.Rig.Generic;
+
+namespace TBF.Rig.Output.DataStorage.UniDataStorageWriter
+{
+ ///
+ /// Factory component 'UniDataStorageWriter' implements more storing modules
+ /// Modules:
+ ///
+ public class Factory : IComponentFactory
+ {
+ public string ClassName { get { return GetType().Namespace.Substring(8); } } /// For backward compatibility
+ public override string ToString() { return ClassName; }
+
+ public IComponent DummyComponent() { return new Writer(new WriterCfg("UniDataStorageWriter", this)); }
+
+ public IComponent GetComponent(IComponentCfg cfg, IList components)
+ {
+ WriterCfg WriterCfg = cfg as WriterCfg;
+ if (WriterCfg == null)
+ throw new ArgumentException("Invalid config for UniDataStorageWriter");
+
+ return new Writer(WriterCfg);
+ }
+
+ public IComponentCfg DefaultConfig() { return new WriterCfg("UniDataStorageWriter", this); }
+
+ public IComponentCfg CmpntCfgFromCmpntEntity(Config.Entities.Component component)
+ {
+ return ComponentCfgBase.CreateFromDbEntity(WriterCfg.Serializer, component, this);
+ }
+ }
+}
diff --git a/TBF/Rig/Output/DataStorage/UniDataStorageWriter/Interfaces/DataWriteRequest.cs b/TBF/Rig/Output/DataStorage/UniDataStorageWriter/Interfaces/DataWriteRequest.cs
new file mode 100644
index 000000000..86ab4ca98
--- /dev/null
+++ b/TBF/Rig/Output/DataStorage/UniDataStorageWriter/Interfaces/DataWriteRequest.cs
@@ -0,0 +1,59 @@
+using System.Collections.Generic;
+
+namespace TBF.Rig.Output.DataStorage.UniDataStorageWriter.Interfaces
+{
+ ///
+ /// Request for write operation.
+ /// Contains batch of write items.
+ ///
+ public class DataWriteRequest
+ {
+ public DataWriteRequest()
+ {
+ InsertItems = new List();
+ UpdateItems = new List();
+ Mode = WriteMode.Insert;
+ }
+
+ public string TargetName { get; set; }
+
+ public WriteMode Mode { get; set; }
+
+ public List InsertItems { get; private set; }
+
+ public List UpdateItems { get; private set; }
+ }
+
+ public enum WriteMode
+ {
+ Insert,
+ Update,
+ Upsert,
+ Append
+ }
+
+ public class InsertWriteItem
+ {
+ public string ColumnName { get; set; }
+ public string Value { get; set; }
+
+ public override string ToString()
+ {
+ return $"{ColumnName} = {Value}";
+ }
+ }
+
+ public class UpdateWriteItem
+ {
+ public string WhereParameterName { get; set; }
+ public string WhereValue { get; set; }
+
+ public string SetParameterName { get; set; }
+ public string SetValue { get; set; }
+
+ public override string ToString()
+ {
+ return $"WHERE {WhereParameterName} = {WhereValue} -> SET {SetParameterName} = {SetValue}";
+ }
+ }
+}
\ No newline at end of file
diff --git a/TBF/Rig/Output/DataStorage/UniDataStorageWriter/Interfaces/IDataStorageWriter.cs b/TBF/Rig/Output/DataStorage/UniDataStorageWriter/Interfaces/IDataStorageWriter.cs
new file mode 100644
index 000000000..94cb41759
--- /dev/null
+++ b/TBF/Rig/Output/DataStorage/UniDataStorageWriter/Interfaces/IDataStorageWriter.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using TBF.Rig.Output.DataStorage.UniDataStorageWriter.Interfaces;
+
+namespace TBF.Rig.Output.DataStorage.UniDataStorageWriter
+{
+ public interface IDataStorageWriter
+ {
+ WriterDiagnosticResult TestSource(bool validateOnly);
+ WriterDiagnosticResult WriteData(DataWriteRequest request);
+ }
+}
diff --git a/TBF/Rig/Output/DataStorage/UniDataStorageWriter/Searching/SearchOrderDefinition.cs b/TBF/Rig/Output/DataStorage/UniDataStorageWriter/Searching/SearchOrderDefinition.cs
new file mode 100644
index 000000000..e25ba9491
--- /dev/null
+++ b/TBF/Rig/Output/DataStorage/UniDataStorageWriter/Searching/SearchOrderDefinition.cs
@@ -0,0 +1,65 @@
+using System;
+
+namespace TBF.Rig.Input.DataStorage.UniDataStorageWriter.Searching
+{
+ ///
+ /// Parsed representation of QueryTemplate expression.
+ /// Example:
+ /// SELECT [Password] WHERE [PcbId] = QUERYPARAM
+ ///
+ public class SearchOrderDefinition
+ {
+ ///
+ /// Column to be returned.
+ ///
+ public ColumnReference SelectColumn { get; set; }
+
+ ///
+ /// Column used for lookup.
+ ///
+ public ColumnReference WhereColumn { get; set; }
+ }
+
+ ///
+ /// Represents a column reference either by name or by zero-based index.
+ ///
+ public class ColumnReference
+ {
+ ///
+ /// Column name if referenced by [ColumnName].
+ ///
+ public string Name { get; set; }
+
+ ///
+ /// Zero-based column index if referenced by COLUMN(n).
+ ///
+ public int? Index { get; set; }
+
+ ///
+ /// Returns true if reference is by column name.
+ ///
+ public bool HasName
+ {
+ get { return !string.IsNullOrWhiteSpace(Name); }
+ }
+
+ ///
+ /// Returns true if reference is by column index.
+ ///
+ public bool HasIndex
+ {
+ get { return Index.HasValue; }
+ }
+
+ public override string ToString()
+ {
+ if (HasName)
+ return "[" + Name + "]";
+
+ if (HasIndex)
+ return "COLUMN(" + Index.Value + ")";
+
+ return "";
+ }
+ }
+}
\ No newline at end of file
diff --git a/TBF/Rig/Output/DataStorage/UniDataStorageWriter/Searching/SearchOrderParser.cs b/TBF/Rig/Output/DataStorage/UniDataStorageWriter/Searching/SearchOrderParser.cs
new file mode 100644
index 000000000..8ba62f7d0
--- /dev/null
+++ b/TBF/Rig/Output/DataStorage/UniDataStorageWriter/Searching/SearchOrderParser.cs
@@ -0,0 +1,87 @@
+using System;
+using System.Text.RegularExpressions;
+using TBF.Rig.Input.DataStorage.UniDataStorageWriter.Searching;
+
+namespace TBF.Rig.Input.DataStorage.UniDataStorageWriter
+{
+ ///
+ /// Parses SQL-like QueryTemplate expressions.
+ /// Supported syntax:
+ /// SELECT [ReturnColumn] WHERE [MatchColumn] = QUERYPARAM
+ /// SELECT COLUMN(1) WHERE COLUMN(0) = QUERYPARAM
+ /// Mixed forms are also supported.
+ ///
+ public static class SearchOrderParser
+ {
+ private static readonly Regex FullPattern = new Regex(
+ @"^\s*SELECT\s+(?