diff --git a/.gitignore b/.gitignore
index a5940e9..333de67 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,4 +7,5 @@ rulette-core/lib/datasource.properties
/rulette-core copy/target/
/rulette-engine/target/
/rulette-engine copy/target/
-/rulette-examples/target/
\ No newline at end of file
+/rulette-examples/target/
+/rulette-postgres-provider/target/
diff --git a/pom.xml b/pom.xml
index d3ead7c..125f25f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -31,6 +31,7 @@
HEAD
+ 1.2.8-SNAPSHOT
1.6.2
@@ -38,6 +39,7 @@
rulette-core
rulette-engine
rulette-mysql-provider
+ rulette-postgres-provider
rulette-examples
diff --git a/rulette-engine/pom.xml b/rulette-engine/pom.xml
index d79c341..9117e49 100644
--- a/rulette-engine/pom.xml
+++ b/rulette-engine/pom.xml
@@ -15,7 +15,7 @@
com.github.kislayverma.rulette
rulette-core
- 1.2.8-SNAPSHOT
+ ${rulette.version}
compile
diff --git a/rulette-examples/pom.xml b/rulette-examples/pom.xml
index d0ec983..a3c2059 100644
--- a/rulette-examples/pom.xml
+++ b/rulette-examples/pom.xml
@@ -15,13 +15,19 @@
com.github.kislayverma.rulette
rulette-engine
- 1.2.8-SNAPSHOT
+ ${rulette.version}
compile
com.github.kislayverma.rulette
rulette-mysql-provider
- 1.2.8-SNAPSHOT
+ ${rulette.version}
+ compile
+
+
+ com.github.kislayverma.rulette
+ rulette-postgres-provider
+ ${rulette.version}
compile
diff --git a/rulette-examples/src/main/java/com/github/kislayverma/rulette/example/postgres/SimplePostgresUse.java b/rulette-examples/src/main/java/com/github/kislayverma/rulette/example/postgres/SimplePostgresUse.java
new file mode 100644
index 0000000..f3643a2
--- /dev/null
+++ b/rulette-examples/src/main/java/com/github/kislayverma/rulette/example/postgres/SimplePostgresUse.java
@@ -0,0 +1,51 @@
+package com.github.kislayverma.rulette.example.postgres;
+
+import com.github.kislayverma.rulette.RuleSystem;
+import com.github.kislayverma.rulette.core.data.IDataProvider;
+import com.github.kislayverma.rulette.core.rule.Rule;
+import java.io.File;
+import java.io.Serializable;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.github.kislayverma.rulette.mysql.MysqlDataProvider;
+
+/**
+ * NOT FOR ACTUAL USE!!!
+ * This class shows how to initialize a Rulette engine from PostgreSQL store and its use.
+ *
+ * @author Kislay Verma
+ *
+ */
+public class SimplePostgresUse implements Serializable {
+
+ public static void main(String[] args) throws Exception {
+ File f = new File("/Users/kislay.verma/Applications/apache-tomcat-7.0.53/conf/rulette-datasource.properties");
+ IDataProvider dataProvider = new MysqlDataProvider(f.getPath());
+ RuleSystem rs = new RuleSystem("govt_vat_rule_system", dataProvider);
+
+ Map inputMap = new HashMap<>();
+ inputMap.put("article_id", "7");
+ inputMap.put("source_state_code", "HAR");
+ inputMap.put("destination_state_code", "GUJ");
+ inputMap.put("courier_code", "IP");
+ inputMap.put("mrp_threshold", "5");
+ inputMap.put("gender", "Women");
+ inputMap.put("is_active", "1");
+ inputMap.put("valid_date_range", "20130820");
+
+ // Rule rule = null;
+ long stime = new Date().getTime();
+ for (int i = 0; i < 1; i++) {
+ Rule rule = rs.getRule(inputMap);
+// System.out.println((rule == null) ? "none" : rule.toString());
+// System.out.println("\n---------------------------\n");
+// List rules = rs.getAllApplicableRules(inputMap);
+// System.out.println((rules == null) ? "none" : rules.toString());
+ }
+
+ long etime = new Date().getTime();
+ System.out.println("Time taken to get rule : " + (etime - stime) + " ms.");
+ }
+}
diff --git a/rulette-mysql-provider/pom.xml b/rulette-mysql-provider/pom.xml
index 84e17a6..185ee2f 100644
--- a/rulette-mysql-provider/pom.xml
+++ b/rulette-mysql-provider/pom.xml
@@ -15,7 +15,7 @@
com.github.kislayverma.rulette
rulette-core
- 1.2.8-SNAPSHOT
+ ${rulette.version}
compile
diff --git a/rulette-postgres-provider/pom.xml b/rulette-postgres-provider/pom.xml
new file mode 100644
index 0000000..56fe0fc
--- /dev/null
+++ b/rulette-postgres-provider/pom.xml
@@ -0,0 +1,223 @@
+
+ 4.0.0
+
+ com.github.kislayverma
+ rulette
+ 1.2.8-SNAPSHOT
+
+
+ com.github.kislayverma.rulette
+ rulette-postgres-provider
+ rulette-postgres-provider
+ PostgreSQL integration for Rulette
+
+
+
+ com.github.kislayverma.rulette
+ rulette-core
+ ${rulette.version}
+ compile
+
+
+ org.postgresql
+ postgresql
+ 9.4.1209
+
+
+ c3p0
+ c3p0
+ 0.9.1.2
+
+
+ org.slf4j
+ slf4j-api
+ 1.7.21
+
+
+ junit
+ junit
+ 4.10
+
+
+ org.mockito
+ mockito-all
+ 1.10.19
+
+
+ org.easymock
+ easymock
+ 3.3.1
+
+
+ org.powermock
+ powermock-api-easymock
+ ${powermock.version}
+
+
+ org.powermock
+ powermock-module-junit4
+ ${powermock.version}
+
+
+ org.powermock
+ powermock-api-mockito
+ ${powermock.version}
+
+
+
+
+ src/main/java/
+
+
+ lib
+
+ **/*.java
+
+
+
+
+
+ maven-compiler-plugin
+ 3.1
+
+
+ 1.7
+
+
+
+ org.codehaus.mojo
+ cobertura-maven-plugin
+ 2.7
+
+
+ 0
+
+
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ 2.18.1
+ true
+
+
+ org.apache.maven.plugins
+ maven-pmd-plugin
+ 3.5
+
+
+
+ pmd
+
+
+
+
+ true
+ utf-8
+ 100
+ 1.7
+
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+ 2.4
+
+
+ attach-sources
+
+ jar
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 2.10.3
+
+
+ attach-javadocs
+
+ jar
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-gpg-plugin
+ 1.6
+
+
+ sign-artifacts
+ verify
+
+ sign
+
+
+
+
+
+ org.sonatype.plugins
+ nexus-staging-maven-plugin
+ 1.6.7
+ true
+
+ ossrh
+ https://oss.sonatype.org/
+ true
+
+
+
+ org.apache.maven.plugins
+ maven-release-plugin
+ 2.5.3
+
+ true
+ false
+ release
+ deploy
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jxr-plugin
+ 2.5
+
+
+ org.apache.maven.plugins
+ maven-project-info-reports-plugin
+ 2.9
+
+ false
+
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 2.10.3
+
+
+ org.codehaus.mojo
+ cobertura-maven-plugin
+ 2.7
+
+
+ org.apache.maven.plugins
+ maven-pmd-plugin
+ 3.6
+
+ true
+ utf-8
+ 100
+ 1.7
+
+
+
+
+
diff --git a/rulette-postgres-provider/src/main/.DS_Store b/rulette-postgres-provider/src/main/.DS_Store
new file mode 100644
index 0000000..508c44c
Binary files /dev/null and b/rulette-postgres-provider/src/main/.DS_Store differ
diff --git a/rulette-postgres-provider/src/main/java/.DS_Store b/rulette-postgres-provider/src/main/java/.DS_Store
new file mode 100644
index 0000000..cd11fc1
Binary files /dev/null and b/rulette-postgres-provider/src/main/java/.DS_Store differ
diff --git a/rulette-postgres-provider/src/main/java/com/.DS_Store b/rulette-postgres-provider/src/main/java/com/.DS_Store
new file mode 100644
index 0000000..eefea06
Binary files /dev/null and b/rulette-postgres-provider/src/main/java/com/.DS_Store differ
diff --git a/rulette-postgres-provider/src/main/java/com/github/.DS_Store b/rulette-postgres-provider/src/main/java/com/github/.DS_Store
new file mode 100644
index 0000000..9c88d1f
Binary files /dev/null and b/rulette-postgres-provider/src/main/java/com/github/.DS_Store differ
diff --git a/rulette-postgres-provider/src/main/java/com/github/kislayverma/.DS_Store b/rulette-postgres-provider/src/main/java/com/github/kislayverma/.DS_Store
new file mode 100644
index 0000000..a5f00f7
Binary files /dev/null and b/rulette-postgres-provider/src/main/java/com/github/kislayverma/.DS_Store differ
diff --git a/rulette-postgres-provider/src/main/java/com/github/kislayverma/rulette/postgres/PostgresDataProvider.java b/rulette-postgres-provider/src/main/java/com/github/kislayverma/rulette/postgres/PostgresDataProvider.java
new file mode 100644
index 0000000..1ebcf96
--- /dev/null
+++ b/rulette-postgres-provider/src/main/java/com/github/kislayverma/rulette/postgres/PostgresDataProvider.java
@@ -0,0 +1,268 @@
+/*
+ * Copyright 2016 kislay.verma.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.github.kislayverma.rulette.postgres;
+
+import com.github.kislayverma.rulette.core.data.IDataProvider;
+import com.github.kislayverma.rulette.core.metadata.RuleInputMetaData;
+import com.github.kislayverma.rulette.core.metadata.RuleSystemMetaData;
+import com.github.kislayverma.rulette.core.rule.Rule;
+import com.github.kislayverma.rulette.core.ruleinput.type.RuleInputType;
+import com.github.kislayverma.rulette.postgres.dao.DataSource;
+
+import java.io.IOException;
+import java.sql.*;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ *
+ * @author kislay.verma
+ */
+public class PostgresDataProvider implements IDataProvider {
+ private final Map metaDataMap;
+
+ public PostgresDataProvider(String datasourceUrl) throws IOException, SQLException {
+ metaDataMap = new ConcurrentHashMap<>();
+ DataSource.init(datasourceUrl);
+ }
+
+ private Connection getConnection() throws SQLException, IOException {
+ return DataSource.getInstance(null).getConnection();
+ }
+
+ @Override
+ public List getAllRules(String ruleSystemName) throws SQLException, Exception {
+ List rules = new ArrayList<>();
+
+ Statement statement = getConnection().createStatement();
+ ResultSet resultSet =
+ statement.executeQuery("SELECT * " + " FROM " + getRuleSystemMetaData(ruleSystemName).getTableName());
+
+ if (resultSet != null) {
+ rules = convertToRules(resultSet, getRuleSystemMetaData(ruleSystemName));
+ }
+
+ return rules;
+ }
+
+ @Override
+ public Rule saveRule(String ruleSystemName, Rule rule) throws SQLException, Exception {
+ RuleSystemMetaData metaData = getRuleSystemMetaData(ruleSystemName);
+
+ StringBuilder sqlBuilder = new StringBuilder();
+ StringBuilder nameListBuilder = new StringBuilder();
+ StringBuilder valueListBuilder = new StringBuilder();
+
+ for (RuleInputMetaData col : metaData.getInputColumnList()) {
+ nameListBuilder.append(col.getName()).append(",");
+ String val = rule.getColumnData(col.getName()).getRawValue();
+ valueListBuilder.append(val.isEmpty() ? null : "'" + val + "'").append(",");
+ }
+ nameListBuilder.append(metaData.getUniqueOutputColumnName()).append(",");
+ valueListBuilder.append(rule.getColumnData(metaData.getUniqueOutputColumnName()).getRawValue()).append(",");
+
+ sqlBuilder.append("INSERT INTO ")
+ .append(metaData.getTableName())
+ .append(" (").append(nameListBuilder.toString().substring(0, nameListBuilder.length() - 1)).append(") ")
+ .append(" VALUES (").append(valueListBuilder.toString().substring(0, valueListBuilder.length() - 1)).append(") ");
+
+ Connection connection = getConnection();
+ PreparedStatement preparedStatement =
+ connection.prepareStatement("SELECT * " + " FROM " + metaData.getTableName());
+
+ if (preparedStatement.executeUpdate(
+ sqlBuilder.toString(), Statement.RETURN_GENERATED_KEYS) > 0) {
+ // Get the rule object for returning using LAST_INSERT_ID() MySql function.
+ // This id is maintained per connection so multiple instances inserting rows
+ // isn't a problem.
+ preparedStatement =
+ connection.prepareStatement("SELECT * FROM " + metaData.getTableName()
+ + " WHERE " + metaData.getUniqueIdColumnName()
+ + " = LAST_INSERT_ID()");
+ ResultSet resultSet = preparedStatement.executeQuery();
+
+ List ruleList = convertToRules(resultSet, metaData);
+ if (ruleList != null && !ruleList.isEmpty()) {
+ return ruleList.get(0);
+ }
+ }
+
+ return null;
+ }
+
+ @Override
+ public boolean deleteRule(String ruleSystemName, Rule rule) throws SQLException, Exception {
+ RuleSystemMetaData metaData = getRuleSystemMetaData(ruleSystemName);
+
+ String sql = "DELETE FROM " + metaData.getTableName()
+ + " WHERE " + metaData.getUniqueIdColumnName() + "= ?";
+ PreparedStatement preparedStatement = getConnection().prepareStatement(sql);
+ preparedStatement.setString(1, rule.getColumnData(metaData.getUniqueIdColumnName()).getRawValue());
+
+ return preparedStatement.executeUpdate() > 0;
+ }
+
+ @Override
+ public Rule updateRule(String ruleSystemName, Rule rule) throws SQLException, Exception {
+ RuleSystemMetaData metaData = getRuleSystemMetaData(ruleSystemName);
+
+ StringBuilder sqlBuilder = new StringBuilder();
+ StringBuilder updateListBuilder = new StringBuilder();
+
+ for (RuleInputMetaData col : metaData.getInputColumnList()) {
+ String val = rule.getColumnData(col.getName()).getRawValue();
+
+ updateListBuilder.append(col.getName())
+ .append("=")
+ .append("".equals(val) ? null : "'" + val + "'")
+ .append(",");
+ }
+ updateListBuilder.append(metaData.getUniqueOutputColumnName())
+ .append("=")
+ .append(rule.getColumnData(metaData.getUniqueOutputColumnName()).getRawValue())
+ .append(",");
+
+ String oldRuleId = rule.getColumnData(metaData.getUniqueIdColumnName()).getRawValue();
+ sqlBuilder.append("UPDATE ")
+ .append(metaData.getTableName())
+ .append(" SET ")
+ .append(updateListBuilder.toString().substring(0, updateListBuilder.length() - 1))
+ .append(" WHERE ")
+ .append(metaData.getUniqueIdColumnName())
+ .append("=")
+ .append(oldRuleId);
+
+ Connection connection = getConnection();
+ PreparedStatement preparedStatement =
+ connection.prepareStatement(sqlBuilder.toString());
+ if (preparedStatement.executeUpdate() > 0) {
+ preparedStatement =
+ connection.prepareStatement("SELECT * FROM " + metaData.getTableName()
+ + " WHERE " + metaData.getUniqueIdColumnName()
+ + "=" + oldRuleId);
+ ResultSet resultSet = preparedStatement.executeQuery();
+
+ List ruleList = convertToRules(resultSet, metaData);
+ if (ruleList != null && !ruleList.isEmpty()) {
+ return ruleList.get(0);
+ }
+ }
+
+ return null;
+ }
+
+ private List convertToRules(ResultSet resultSet, RuleSystemMetaData metadata) throws Exception {
+ List rules = new ArrayList<>();
+
+ if (resultSet != null) {
+ while (resultSet.next()) {
+ Map inputMap = new HashMap<>();
+
+ for (RuleInputMetaData col : metadata.getInputColumnList()) {
+ inputMap.put(col.getName(), resultSet.getString(col.getName()));
+ }
+ inputMap.put(metadata.getUniqueIdColumnName(),
+ resultSet.getString(metadata.getUniqueIdColumnName()));
+ inputMap.put(metadata.getUniqueOutputColumnName(),
+ resultSet.getString(metadata.getUniqueOutputColumnName()));
+
+ rules.add(new Rule(metadata, inputMap));
+ }
+ }
+
+ return rules;
+ }
+
+ @Override
+ public RuleSystemMetaData getRuleSystemMetaData(String ruleSystemName) throws Exception {
+ RuleSystemMetaData rsMetaData = metaDataMap.get(ruleSystemName);
+ if (rsMetaData == null) {
+ rsMetaData = loadRuleSystemMetaData(ruleSystemName);
+ metaDataMap.put(ruleSystemName, rsMetaData);
+ }
+
+ return rsMetaData;
+ }
+
+ public RuleSystemMetaData loadRuleSystemMetaData(String ruleSystemName) throws Exception {
+ Statement statement = getConnection().createStatement();
+ ResultSet resultSet =
+ statement.executeQuery("SELECT * FROM rule_system WHERE name LIKE '" + ruleSystemName + "'");
+
+ if (!resultSet.next()) {
+ throw new Exception("No meta data found for rule system name : " + ruleSystemName);
+ }
+
+ // HACK . doesn't work in postgres
+ // the default database is specified in the connection
+ // better use schema
+ String tableName = removeSchemaName(resultSet.getString("table_name"));
+ if(tableName == null){
+ throw new Exception("rule system table cannot be null");
+ }
+
+ RuleSystemMetaData metaData = new RuleSystemMetaData(
+ resultSet.getString("name"),
+ tableName,
+ resultSet.getString("unique_id_column_name"),
+ resultSet.getString("output_column_name"),
+ getInputs(ruleSystemName));
+
+ return metaData;
+ }
+
+ private static String removeSchemaName(String tableName){
+ if (tableName!=null && !tableName.trim().equals("")) {
+ String[] splits = tableName.split("\\.");
+ if (splits.length==1) {
+ return tableName;
+ } else {
+ return splits[splits.length - 1];
+ }
+ }
+
+ return null;
+ }
+
+ private List getInputs(String ruleSystemName) throws SQLException, Exception {
+ List inputs = new ArrayList<>();
+
+ Statement statement = getConnection().createStatement();
+ ResultSet resultSet =
+ statement.executeQuery("SELECT b.* "
+ + "FROM rule_system AS a "
+ + "JOIN rule_input AS b "
+ + " ON b.rule_system_id = a.id "
+ + "WHERE a.name LIKE '" + ruleSystemName + "' "
+ + "ORDER BY b.priority ASC ");
+
+ while (resultSet.next()) {
+ RuleInputType ruleType =
+ "Value".equalsIgnoreCase(resultSet.getString("rule_type"))
+ ? RuleInputType.VALUE : RuleInputType.RANGE;
+ String dataType = resultSet.getString("data_type").toUpperCase();
+
+ inputs.add(new RuleInputMetaData(
+ resultSet.getString("name"), resultSet.getInt("priority"), ruleType, dataType));
+ }
+
+ return inputs;
+ }
+}
diff --git a/rulette-postgres-provider/src/main/java/com/github/kislayverma/rulette/postgres/dao/.DS_Store b/rulette-postgres-provider/src/main/java/com/github/kislayverma/rulette/postgres/dao/.DS_Store
new file mode 100644
index 0000000..040d803
Binary files /dev/null and b/rulette-postgres-provider/src/main/java/com/github/kislayverma/rulette/postgres/dao/.DS_Store differ
diff --git a/rulette-postgres-provider/src/main/java/com/github/kislayverma/rulette/postgres/dao/DataSource.java b/rulette-postgres-provider/src/main/java/com/github/kislayverma/rulette/postgres/dao/DataSource.java
new file mode 100644
index 0000000..e18f8ff
--- /dev/null
+++ b/rulette-postgres-provider/src/main/java/com/github/kislayverma/rulette/postgres/dao/DataSource.java
@@ -0,0 +1,93 @@
+package com.github.kislayverma.rulette.postgres.dao;
+
+import com.mchange.v2.c3p0.ComboPooledDataSource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.beans.PropertyVetoException;
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Properties;
+
+/**
+ *
+ * @author kislay
+ */
+public class DataSource {
+
+ private Properties props;
+ private ComboPooledDataSource cpds;
+ private static DataSource datasource;
+ private static final Logger LOGGER = LoggerFactory.getLogger(DataSource.class);
+
+ private DataSource(String fileName) throws IOException, SQLException {
+ // load datasource properties
+ props = Utils.readProperties(fileName);
+ cpds = new ComboPooledDataSource();
+ try {
+ cpds.setDriverClass(props.getProperty("driverClass"));
+ } catch (PropertyVetoException ex) {
+ throw new RuntimeException(ex);
+ }
+ cpds.setJdbcUrl(props.getProperty("jdbcUrl"));
+ cpds.setUser(props.getProperty("username"));
+ cpds.setPassword(props.getProperty("password"));
+ cpds.setInitialPoolSize(new Integer((String) props.getProperty("initialPoolSize")));
+ cpds.setAcquireIncrement(new Integer((String) props.getProperty("acquireIncrement")));
+ cpds.setMaxPoolSize(new Integer((String) props.getProperty("maxPoolSize")));
+ cpds.setMinPoolSize(new Integer((String) props.getProperty("minPoolSize")));
+ cpds.setMaxStatements(new Integer((String) props.getProperty("maxStatements")));
+
+ Connection testConnection = null;
+ Statement testStatement = null;
+
+ // test connectivity and initialize pool
+ try {
+ LOGGER.info("Testing DB connection...");
+ testConnection = cpds.getConnection();
+ testStatement = testConnection.createStatement();
+ testStatement.executeQuery("select 1");
+
+ LOGGER.info("DB connection tested successfully.");
+ } catch (SQLException e) {
+ throw e;
+ } finally {
+ if (testStatement != null)
+ testStatement.close();
+ if (testConnection != null)
+ testConnection.close();
+ }
+ }
+
+ public static void init(String fileName) throws IOException, SQLException {
+ if (datasource == null) {
+ loadDriverClass();
+ LOGGER.debug("File name is " + fileName);
+ datasource = new DataSource(fileName);
+ }
+ }
+
+ // This will load the PostgreSQL driver
+ // Source of the copy-paste : http://www.vogella.com/articles/MySQLJava/article.html
+ private static void loadDriverClass() {
+ try {
+ Class.forName("org.postgresql.Driver").newInstance();
+ } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static DataSource getInstance(String fileName) throws IOException, SQLException {
+ if (datasource == null) {
+ init(fileName);
+ }
+
+ return datasource;
+ }
+
+ public Connection getConnection() throws SQLException {
+ return this.cpds.getConnection();
+ }
+}
diff --git a/rulette-postgres-provider/src/main/java/com/github/kislayverma/rulette/postgres/dao/Utils.java b/rulette-postgres-provider/src/main/java/com/github/kislayverma/rulette/postgres/dao/Utils.java
new file mode 100644
index 0000000..c4d021d
--- /dev/null
+++ b/rulette-postgres-provider/src/main/java/com/github/kislayverma/rulette/postgres/dao/Utils.java
@@ -0,0 +1,35 @@
+package com.github.kislayverma.rulette.postgres.dao;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Properties;
+
+/**
+ *
+ * @author kislay
+ */
+public class Utils {
+
+ /**
+ * Read a properties file from the class path and return a Properties object
+ *
+ * @param fileName file to read
+ * @return Properties object loaded with properties from the given file
+ * @throws IOException on file reading error
+ */
+ public static Properties readProperties(String fileName) throws IOException {
+ File f = new File(fileName);
+ if (!f.canRead()) {
+ throw new IOException("Could not read the datasource file");
+ }
+
+ URL url = f.toURI().toURL();
+ InputStream in = url.openStream();
+ Properties props = new Properties();
+ props.load(in);
+
+ return props;
+ }
+}
diff --git a/rulette-postgres-provider/src/main/resources/.DS_Store b/rulette-postgres-provider/src/main/resources/.DS_Store
new file mode 100644
index 0000000..1f18b8c
Binary files /dev/null and b/rulette-postgres-provider/src/main/resources/.DS_Store differ
diff --git a/rulette-postgres-provider/src/main/resources/sql/.DS_Store b/rulette-postgres-provider/src/main/resources/sql/.DS_Store
new file mode 100644
index 0000000..a5d16b4
Binary files /dev/null and b/rulette-postgres-provider/src/main/resources/sql/.DS_Store differ
diff --git a/rulette-postgres-provider/src/main/resources/sql/sample-rulesystem-setup.sql b/rulette-postgres-provider/src/main/resources/sql/sample-rulesystem-setup.sql
new file mode 100644
index 0000000..375354a
--- /dev/null
+++ b/rulette-postgres-provider/src/main/resources/sql/sample-rulesystem-setup.sql
@@ -0,0 +1,77 @@
+CREATE DATABASE tax;
+
+USE tax;
+
+CREATE TABLE rule_system (
+ `id` bigint(11) NOT NULL AUTO_INCREMENT,
+ `name` varchar(100) NOT NULL,
+ `table_name` varchar(100) NOT NULL,
+ `output_column_name` varchar(256) DEFAULT NULL,
+ `unique_id_column_name` varchar(256) DEFAULT NULL,
+ PRIMARY KEY (`id`)
+);
+
+CREATE TABLE `rule_input` (
+ `id` BIGINT(20) NOT NULL AUTO_INCREMENT,
+ `name` varchar(100) NOT NULL,
+ `rule_system_id` int(11) NOT NULL,
+ `priority` int(11) NOT NULL,
+ `rule_type` varchar(45) NOT NULL,
+ `data_type` varchar(45) NOT NULL,
+ PRIMARY KEY (`id`)
+);
+
+CREATE TABLE `vat_rule_system` (
+ `id` BIGINT(20) NOT NULL AUTO_INCREMENT,
+ `source_state` varchar(100) NULL,
+ `item_type` int NULL,
+ `material` varchar(100) NULL,
+ `mrp_threshold` varchar(100) NULL,
+ `rule_output_id` VARCHAR(256) NOT NULL,
+ PRIMARY KEY (`id`)
+);
+
+CREATE TABLE govt_vat_value (
+ `id` bigint(20) NOT NULL AUTO_INCREMENT,
+ `tax_type` VARCHAR(20) NOT NULL,
+ `tax_rate` DECIMAL(12,3) NOT NULL,
+ PRIMARY KEY (`id`)
+);
+
+GRANT ALL PRIVILEGES ON tax.* TO 'taxUser'@'%';
+
+FLUSH PRIVILEGES;
+
+INSERT INTO rule_system
+ (`name`, `table_name`, `output_column_name`, `unique_id_column_name`)
+VALUES
+ ('vat_rule_system', 'tax.vat_rule_system', 'rule_output_id', 'id');
+
+INSERT INTO rule_input
+ (`name`, `rule_system_id`, `priority`, `rule_type`, `data_type`)
+VALUES
+ ('source_state', 1, 1, 'VALUE', 'STRING');
+INSERT INTO rule_input
+ (`name`, `rule_system_id`, `priority`, `rule_type`, `data_type`)
+VALUES
+ ('item_type', 1, 2, 'VALUE', 'NUMBER');
+INSERT INTO rule_input
+ (`name`, `rule_system_id`, `priority`, `rule_type`, `data_type`)
+VALUES
+ ('material', 1, 3, 'VALUE', 'STRING');
+INSERT INTO rule_input
+ (`name`, `rule_system_id`, `priority`, `rule_type`, `data_type`)
+VALUES
+ ('mrp_threshold', 1, 4, 'RANGE', 'NUMBER');
+
+INSERT INTO govt_vat_value (`tax_type`, `tax_rate`) VALUES ('VAT', 0.0);
+INSERT INTO govt_vat_value (`tax_type`, `tax_rate`) VALUES ('VAT', 1.0);
+INSERT INTO govt_vat_value (`tax_type`, `tax_rate`) VALUES ('VAT', 1.2);
+INSERT INTO govt_vat_value (`tax_type`, `tax_rate`) VALUES ('VAT', 5.0);
+INSERT INTO govt_vat_value (`tax_type`, `tax_rate`) VALUES ('VAT', 5.25);
+INSERT INTO govt_vat_value (`tax_type`, `tax_rate`) VALUES ('VAT', 5.5);
+INSERT INTO govt_vat_value (`tax_type`, `tax_rate`) VALUES ('VAT', 12.5);
+INSERT INTO govt_vat_value (`tax_type`, `tax_rate`) VALUES ('VAT', 13.125);
+INSERT INTO govt_vat_value (`tax_type`, `tax_rate`) VALUES ('VAT', 14.5);
+
+INSERT INTO `vat_rule_system` VALUES (1,NULL,1,NULL,NULL,'1'),(5,'DEL',1,NULL,NULL,'1'),(9,'HAR',1,NULL,NULL,'9'),(13,'KAR',1,NULL,NULL,'3'),(17,'MAH',1,NULL,NULL,'1'),(21,'TEL',1,NULL,NULL,'3'),(25,'WES',1,NULL,NULL,'3'),(29,NULL,10,NULL,NULL,'7'),(41,'DEL',10,NULL,NULL,'7'),(42,'DEL',10,'gold',NULL,'5'),(43,'DEL',10,'platinum',NULL,'5'),(44,'DEL',10,'silver',NULL,'5'),(54,'HAR',10,NULL,NULL,'2'),(55,'HAR',10,'gold',NULL,'5'),(56,'HAR',10,'platinum',NULL,'5'),(57,'HAR',10,'silver',NULL,'5'),(67,'KAR',10,NULL,NULL,'8'),(68,'KAR',10,'gold',NULL,'5'),(69,'KAR',10,'platinum',NULL,'5'),(70,'KAR',10,'silver',NULL,'5'),(80,'MAH',10,NULL,NULL,'8'),(81,'MAH',10,'gold',NULL,'6'),(82,'MAH',10,'platinum',NULL,'6'),(83,'MAH',10,'silver',NULL,'6'),(93,'TEL',10,NULL,NULL,'7'),(94,'TEL',10,'gold',NULL,'5'),(95,'TEL',10,'platinum',NULL,'5'),(96,'TEL',10,'silver',NULL,'5'),(106,'WES',10,NULL,NULL,'7'),(107,'WES',10,'gold',NULL,'5'),(108,'WES',10,'platinum',NULL,'5'),(109,'WES',10,'silver',NULL,'5'),(118,NULL,11,NULL,NULL,'4'),(122,'DEL',11,NULL,NULL,'7'),(126,'HAR',11,NULL,NULL,'4'),(130,'KAR',11,NULL,NULL,'4'),(134,'MAH',11,NULL,NULL,'4'),(138,'TEL',11,NULL,NULL,'4'),(142,'WES',11,NULL,NULL,'4'),(145,NULL,2,NULL,NULL,'7'),(149,'DEL',2,NULL,NULL,'7'),(153,'HAR',2,NULL,NULL,'2'),(157,'KAR',2,NULL,NULL,'8'),(161,'MAH',2,NULL,NULL,'8'),(165,'TEL',2,NULL,NULL,'7'),(169,'WES',2,NULL,NULL,'7'),(172,NULL,3,NULL,NULL,'4'),(176,'DEL',3,NULL,NULL,'4'),(180,'HAR',3,NULL,NULL,'4'),(184,'KAR',3,NULL,NULL,'4'),(188,'MAH',3,NULL,NULL,'4'),(192,'WES',3,NULL,NULL,'4'),(196,'WES',3,NULL,NULL,'4'),(199,NULL,4,NULL,NULL,'7'),(203,'DEL',4,NULL,NULL,'5'),(207,'HAR',4,NULL,NULL,'5'),(211,'KAR',4,NULL,NULL,'5'),(215,'MAH',4,NULL,NULL,'5'),(219,'TEL',4,NULL,NULL,'5'),(223,'WES',4,NULL,NULL,'5'),(226,NULL,5,NULL,NULL,'1'),(230,'DEL',5,NULL,NULL,'1'),(231,'DEL',5,'herbal',NULL,'7'),(238,'HAR',5,NULL,NULL,'9'),(239,'HAR',5,'herbal',NULL,'2'),(246,'KAR',5,NULL,NULL,'3'),(247,'KAR',5,'herbal',NULL,'8'),(254,'MAH',5,NULL,NULL,'1'),(255,'MAH',5,'herbal',NULL,'8'),(262,'TEL',5,NULL,NULL,'3'),(263,'TEL',5,'herbal',NULL,'7'),(270,'WES',5,NULL,NULL,'3'),(271,'WES',5,'herbal',NULL,'7'),(277,NULL,6,NULL,NULL,'1'),(281,'DEL',6,NULL,NULL,'1'),(282,'DEL',6,'fabric',NULL,'7'),(289,'HAR',6,NULL,NULL,'9'),(290,'HAR',6,'fabric',NULL,'2'),(297,'KAR',6,NULL,NULL,'3'),(298,'KAR',6,'fabric',NULL,'8'),(305,'MAH',6,NULL,NULL,'1'),(306,'MAH',6,'fabric',NULL,'8'),(313,'TEL',6,NULL,NULL,'3'),(314,'TEL',6,'fabric',NULL,'7'),(321,'WES',6,NULL,NULL,'3'),(322,'WES',6,'fabric',NULL,'7'),(327,NULL,7,NULL,NULL,'1'),(331,'DEL',7,NULL,'500.01-999999999','7'),(335,'HAR',7,NULL,'500.01-999999999','2'),(339,'KAR',7,NULL,'500.01-999999999','3'),(343,'MAH',7,NULL,NULL,'1'),(347,'TEL',7,NULL,NULL,'3'),(351,'WES',7,NULL,NULL,'3'),(354,NULL,8,NULL,NULL,'1'),(358,'DEL',8,NULL,NULL,'1'),(362,'HAR',8,NULL,NULL,'9'),(366,'KAR',8,NULL,NULL,'3'),(370,'MAH',8,NULL,NULL,'8'),(380,NULL,9,NULL,NULL,'5'),(383,'DEL',9,NULL,NULL,'5'),(387,'HAR',9,NULL,NULL,'5'),(391,'KAR',9,NULL,NULL,'5'),(395,'MAH',9,NULL,NULL,'6'),(399,'TEL',9,NULL,NULL,'5'),(403,'WES',9,NULL,NULL,'5'),(406,NULL,NULL,NULL,NULL,'7'),(409,'DEL',NULL,NULL,NULL,'7'),(410,'HAR',NULL,NULL,NULL,'2'),(411,'KAR',NULL,NULL,NULL,'8'),(412,'MAH',NULL,NULL,NULL,'8'),(413,'TEL',NULL,NULL,NULL,'7'),(414,'WES',NULL,NULL,NULL,'7');
diff --git a/rulette-postgres-provider/src/main/resources/sql/setup.sql b/rulette-postgres-provider/src/main/resources/sql/setup.sql
new file mode 100644
index 0000000..824121c
--- /dev/null
+++ b/rulette-postgres-provider/src/main/resources/sql/setup.sql
@@ -0,0 +1,19 @@
+
+CREATE TABLE rule_system (
+ `id` bigint(11) NOT NULL AUTO_INCREMENT,
+ `name` varchar(100) NOT NULL,
+ `table_name` varchar(100) NOT NULL,
+ `output_column_name` varchar(256) DEFAULT NULL,
+ `unique_id_column_name` varchar(256) DEFAULT NULL,
+ PRIMARY KEY (`id`)
+);
+
+CREATE TABLE `rule_input` (
+ `id` BIGINT(20) NOT NULL AUTO_INCREMENT,
+ `name` varchar(100) NOT NULL,
+ `rule_system_id` int(11) NOT NULL,
+ `priority` int(11) NOT NULL,
+ `rule_type` varchar(45) NOT NULL,
+ `data_type` varchar(45) NOT NULL,
+ PRIMARY KEY (`id`)
+);